Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit 9a09a46

Browse files
adrian-prantlTom Tromey
authored and
Tom Tromey
committed
Add DWARF for discriminated unions
n Rust, an enum that carries data in the variants is, essentially, a discriminated union. Furthermore, the Rust compiler will perform space optimizations on such enums in some situations. Previously, DWARF for these constructs was emitted using a hack (a magic field name); but this approach stopped working when more space optimizations were added in rust-lang/rust#45225. This patch changes LLVM to allow discriminated unions to be represented in DWARF. It adds createDiscriminatedUnionType and createDiscriminatedMemberType to DIBuilder and then arranges for this to be emitted using DWARF's DW_TAG_variant_part and DW_TAG_variant. Note that DWARF requires that a discriminated union be represented as a structure with a variant part. However, as Rust only needs to emit pure discriminated unions, this is what I chose to expose on DIBuilder. Patch by Tom Tromey! Differential Revision: https://reviews.llvm.org/D42082 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@324426 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 9ad4b7e commit 9a09a46

19 files changed

+380
-56
lines changed

include/llvm/IR/DIBuilder.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,27 @@ namespace llvm {
255255
uint64_t OffsetInBits,
256256
DINode::DIFlags Flags, DIType *Ty);
257257

258+
/// Create debugging information entry for a variant. A variant
259+
/// normally should be a member of a variant part.
260+
/// \param Scope Member scope.
261+
/// \param Name Member name.
262+
/// \param File File where this member is defined.
263+
/// \param LineNo Line number.
264+
/// \param SizeInBits Member size.
265+
/// \param AlignInBits Member alignment.
266+
/// \param OffsetInBits Member offset.
267+
/// \param Flags Flags to encode member attribute, e.g. private
268+
/// \param Discriminant The discriminant for this branch; null for
269+
/// the default branch
270+
/// \param Ty Parent type.
271+
DIDerivedType *createVariantMemberType(DIScope *Scope, StringRef Name,
272+
DIFile *File, unsigned LineNo,
273+
uint64_t SizeInBits,
274+
uint32_t AlignInBits,
275+
uint64_t OffsetInBits,
276+
Constant *Discriminant,
277+
DINode::DIFlags Flags, DIType *Ty);
278+
258279
/// Create debugging information entry for a bit field member.
259280
/// \param Scope Member scope.
260281
/// \param Name Member name.
@@ -376,6 +397,27 @@ namespace llvm {
376397
unsigned RunTimeLang = 0,
377398
StringRef UniqueIdentifier = "");
378399

400+
/// Create debugging information entry for a variant part. A
401+
/// variant part normally has a discriminator (though this is not
402+
/// required) and a number of variant children.
403+
/// \param Scope Scope in which this union is defined.
404+
/// \param Name Union name.
405+
/// \param File File where this member is defined.
406+
/// \param LineNumber Line number.
407+
/// \param SizeInBits Member size.
408+
/// \param AlignInBits Member alignment.
409+
/// \param Flags Flags to encode member attribute, e.g. private
410+
/// \param Discriminator Discriminant member
411+
/// \param Elements Variant elements.
412+
/// \param UniqueIdentifier A unique identifier for the union.
413+
DICompositeType *createVariantPart(DIScope *Scope, StringRef Name,
414+
DIFile *File, unsigned LineNumber,
415+
uint64_t SizeInBits, uint32_t AlignInBits,
416+
DINode::DIFlags Flags,
417+
DIDerivedType *Discriminator,
418+
DINodeArray Elements,
419+
StringRef UniqueIdentifier = "");
420+
379421
/// Create debugging information for template
380422
/// type parameter.
381423
/// \param Scope Scope in which this type is defined.

include/llvm/IR/DebugInfoMetadata.h

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,12 @@ class DIDerivedType : public DIType {
819819
return C->getValue();
820820
return nullptr;
821821
}
822+
Constant *getDiscriminantValue() const {
823+
assert(getTag() == dwarf::DW_TAG_member && !isStaticMember());
824+
if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData()))
825+
return C->getValue();
826+
return nullptr;
827+
}
822828
/// @}
823829

824830
static bool classof(const Metadata *MD) {
@@ -861,27 +867,29 @@ class DICompositeType : public DIType {
861867
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
862868
DIFlags Flags, DINodeArray Elements, unsigned RuntimeLang,
863869
DITypeRef VTableHolder, DITemplateParameterArray TemplateParams,
864-
StringRef Identifier, StorageType Storage, bool ShouldCreate = true) {
870+
StringRef Identifier, DIDerivedType *Discriminator,
871+
StorageType Storage, bool ShouldCreate = true) {
865872
return getImpl(
866873
Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope,
867874
BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(),
868875
RuntimeLang, VTableHolder, TemplateParams.get(),
869-
getCanonicalMDString(Context, Identifier), Storage, ShouldCreate);
876+
getCanonicalMDString(Context, Identifier), Discriminator, Storage, ShouldCreate);
870877
}
871878
static DICompositeType *
872879
getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,
873880
unsigned Line, Metadata *Scope, Metadata *BaseType,
874881
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
875882
DIFlags Flags, Metadata *Elements, unsigned RuntimeLang,
876883
Metadata *VTableHolder, Metadata *TemplateParams,
877-
MDString *Identifier, StorageType Storage, bool ShouldCreate = true);
884+
MDString *Identifier, Metadata *Discriminator,
885+
StorageType Storage, bool ShouldCreate = true);
878886

879887
TempDICompositeType cloneImpl() const {
880888
return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(),
881889
getScope(), getBaseType(), getSizeInBits(),
882890
getAlignInBits(), getOffsetInBits(), getFlags(),
883891
getElements(), getRuntimeLang(), getVTableHolder(),
884-
getTemplateParams(), getIdentifier());
892+
getTemplateParams(), getIdentifier(), getDiscriminator());
885893
}
886894

887895
public:
@@ -892,21 +900,22 @@ class DICompositeType : public DIType {
892900
DIFlags Flags, DINodeArray Elements, unsigned RuntimeLang,
893901
DITypeRef VTableHolder,
894902
DITemplateParameterArray TemplateParams = nullptr,
895-
StringRef Identifier = ""),
903+
StringRef Identifier = "", DIDerivedType *Discriminator = nullptr),
896904
(Tag, Name, File, Line, Scope, BaseType, SizeInBits,
897905
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
898-
VTableHolder, TemplateParams, Identifier))
906+
VTableHolder, TemplateParams, Identifier, Discriminator))
899907
DEFINE_MDNODE_GET(DICompositeType,
900908
(unsigned Tag, MDString *Name, Metadata *File,
901909
unsigned Line, Metadata *Scope, Metadata *BaseType,
902910
uint64_t SizeInBits, uint32_t AlignInBits,
903911
uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements,
904912
unsigned RuntimeLang, Metadata *VTableHolder,
905913
Metadata *TemplateParams = nullptr,
906-
MDString *Identifier = nullptr),
914+
MDString *Identifier = nullptr,
915+
Metadata *Discriminator = nullptr),
907916
(Tag, Name, File, Line, Scope, BaseType, SizeInBits,
908917
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
909-
VTableHolder, TemplateParams, Identifier))
918+
VTableHolder, TemplateParams, Identifier, Discriminator))
910919

911920
TempDICompositeType clone() const { return cloneImpl(); }
912921

@@ -923,7 +932,7 @@ class DICompositeType : public DIType {
923932
Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits,
924933
uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements,
925934
unsigned RuntimeLang, Metadata *VTableHolder,
926-
Metadata *TemplateParams);
935+
Metadata *TemplateParams, Metadata *Discriminator);
927936
static DICompositeType *getODRTypeIfExists(LLVMContext &Context,
928937
MDString &Identifier);
929938

@@ -942,7 +951,7 @@ class DICompositeType : public DIType {
942951
Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits,
943952
uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements,
944953
unsigned RuntimeLang, Metadata *VTableHolder,
945-
Metadata *TemplateParams);
954+
Metadata *TemplateParams, Metadata *Discriminator);
946955

947956
DITypeRef getBaseType() const { return DITypeRef(getRawBaseType()); }
948957
DINodeArray getElements() const {
@@ -960,6 +969,8 @@ class DICompositeType : public DIType {
960969
Metadata *getRawVTableHolder() const { return getOperand(5); }
961970
Metadata *getRawTemplateParams() const { return getOperand(6); }
962971
MDString *getRawIdentifier() const { return getOperandAs<MDString>(7); }
972+
Metadata *getRawDiscriminator() const { return getOperand(8); }
973+
DIDerivedType *getDiscriminator() const { return getOperandAs<DIDerivedType>(8); }
963974

964975
/// Replace operands.
965976
///

lib/AsmParser/LLParser.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4068,7 +4068,8 @@ bool LLParser::ParseDICompositeType(MDNode *&Result, bool IsDistinct) {
40684068
OPTIONAL(runtimeLang, DwarfLangField, ); \
40694069
OPTIONAL(vtableHolder, MDField, ); \
40704070
OPTIONAL(templateParams, MDField, ); \
4071-
OPTIONAL(identifier, MDStringField, );
4071+
OPTIONAL(identifier, MDStringField, ); \
4072+
OPTIONAL(discriminator, MDField, );
40724073
PARSE_MD_FIELDS();
40734074
#undef VISIT_MD_FIELDS
40744075

@@ -4078,7 +4079,7 @@ bool LLParser::ParseDICompositeType(MDNode *&Result, bool IsDistinct) {
40784079
Context, *identifier.Val, tag.Val, name.Val, file.Val, line.Val,
40794080
scope.Val, baseType.Val, size.Val, align.Val, offset.Val, flags.Val,
40804081
elements.Val, runtimeLang.Val, vtableHolder.Val,
4081-
templateParams.Val)) {
4082+
templateParams.Val, discriminator.Val)) {
40824083
Result = CT;
40834084
return false;
40844085
}
@@ -4089,7 +4090,8 @@ bool LLParser::ParseDICompositeType(MDNode *&Result, bool IsDistinct) {
40894090
DICompositeType,
40904091
(Context, tag.Val, name.Val, file.Val, line.Val, scope.Val, baseType.Val,
40914092
size.Val, align.Val, offset.Val, flags.Val, elements.Val,
4092-
runtimeLang.Val, vtableHolder.Val, templateParams.Val, identifier.Val));
4093+
runtimeLang.Val, vtableHolder.Val, templateParams.Val, identifier.Val,
4094+
discriminator.Val));
40934095
return false;
40944096
}
40954097

lib/BinaryFormat/Dwarf.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -393,16 +393,6 @@ StringRef llvm::dwarf::ArrayOrderString(unsigned Order) {
393393
return StringRef();
394394
}
395395

396-
StringRef llvm::dwarf::DiscriminantString(unsigned Discriminant) {
397-
switch (Discriminant) {
398-
case DW_DSC_label:
399-
return "DW_DSC_label";
400-
case DW_DSC_range:
401-
return "DW_DSC_range";
402-
}
403-
return StringRef();
404-
}
405-
406396
StringRef llvm::dwarf::LNStandardString(unsigned Standard) {
407397
switch (Standard) {
408398
default:
@@ -560,8 +550,6 @@ StringRef llvm::dwarf::AttributeValueString(uint16_t Attr, unsigned Val) {
560550
return InlineCodeString(Val);
561551
case DW_AT_ordering:
562552
return ArrayOrderString(Val);
563-
case DW_AT_discr_value:
564-
return DiscriminantString(Val);
565553
}
566554

567555
return StringRef();

lib/Bitcode/Reader/MetadataLoader.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,7 +1235,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
12351235
break;
12361236
}
12371237
case bitc::METADATA_COMPOSITE_TYPE: {
1238-
if (Record.size() != 16)
1238+
if (Record.size() < 16 || Record.size() > 17)
12391239
return error("Invalid record");
12401240

12411241
// If we have a UUID and this is not a forward declaration, lookup the
@@ -1258,6 +1258,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
12581258
unsigned RuntimeLang = Record[12];
12591259
Metadata *VTableHolder = nullptr;
12601260
Metadata *TemplateParams = nullptr;
1261+
Metadata *Discriminator = nullptr;
12611262
auto *Identifier = getMDString(Record[15]);
12621263
// If this module is being parsed so that it can be ThinLTO imported
12631264
// into another module, composite types only need to be imported
@@ -1278,13 +1279,15 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
12781279
Elements = getMDOrNull(Record[11]);
12791280
VTableHolder = getDITypeRefOrNull(Record[13]);
12801281
TemplateParams = getMDOrNull(Record[14]);
1282+
if (Record.size() > 16)
1283+
Discriminator = getMDOrNull(Record[16]);
12811284
}
12821285
DICompositeType *CT = nullptr;
12831286
if (Identifier)
12841287
CT = DICompositeType::buildODRType(
12851288
Context, *Identifier, Tag, Name, File, Line, Scope, BaseType,
12861289
SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
1287-
VTableHolder, TemplateParams);
1290+
VTableHolder, TemplateParams, Discriminator);
12881291

12891292
// Create a node if we didn't get a lazy ODR type.
12901293
if (!CT)

lib/Bitcode/Writer/BitcodeWriter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1521,6 +1521,7 @@ void ModuleBitcodeWriter::writeDICompositeType(
15211521
Record.push_back(VE.getMetadataOrNullID(N->getVTableHolder()));
15221522
Record.push_back(VE.getMetadataOrNullID(N->getTemplateParams().get()));
15231523
Record.push_back(VE.getMetadataOrNullID(N->getRawIdentifier()));
1524+
Record.push_back(VE.getMetadataOrNullID(N->getDiscriminator()));
15241525

15251526
Stream.EmitRecord(bitc::METADATA_COMPOSITE_TYPE, Record, Abbrev);
15261527
Record.clear();

lib/CodeGen/AsmPrinter/DwarfUnit.cpp

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -917,9 +917,24 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
917917
case dwarf::DW_TAG_enumeration_type:
918918
constructEnumTypeDIE(Buffer, CTy);
919919
break;
920+
case dwarf::DW_TAG_variant_part:
920921
case dwarf::DW_TAG_structure_type:
921922
case dwarf::DW_TAG_union_type:
922923
case dwarf::DW_TAG_class_type: {
924+
// Emit the discriminator for a variant part.
925+
DIDerivedType *Discriminator = nullptr;
926+
if (Tag == dwarf::DW_TAG_variant_part) {
927+
Discriminator = CTy->getDiscriminator();
928+
if (Discriminator) {
929+
// DWARF says:
930+
// If the variant part has a discriminant, the discriminant is
931+
// represented by a separate debugging information entry which is
932+
// a child of the variant part entry.
933+
DIE &DiscMember = constructMemberDIE(Buffer, Discriminator);
934+
addDIEEntry(Buffer, dwarf::DW_AT_discr, DiscMember);
935+
}
936+
}
937+
923938
// Add elements to structure type.
924939
DINodeArray Elements = CTy->getElements();
925940
for (const auto *Element : Elements) {
@@ -933,6 +948,18 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
933948
addType(ElemDie, resolve(DDTy->getBaseType()), dwarf::DW_AT_friend);
934949
} else if (DDTy->isStaticMember()) {
935950
getOrCreateStaticMemberDIE(DDTy);
951+
} else if (Tag == dwarf::DW_TAG_variant_part) {
952+
// When emitting a variant part, wrap each member in
953+
// DW_TAG_variant.
954+
DIE &Variant = createAndAddDIE(dwarf::DW_TAG_variant, Buffer);
955+
if (const ConstantInt *CI =
956+
dyn_cast_or_null<ConstantInt>(DDTy->getDiscriminantValue())) {
957+
if (isUnsignedDIType(DD, resolve(Discriminator->getBaseType())))
958+
addUInt(Variant, dwarf::DW_AT_discr_value, None, CI->getZExtValue());
959+
else
960+
addSInt(Variant, dwarf::DW_AT_discr_value, None, CI->getSExtValue());
961+
}
962+
constructMemberDIE(Variant, DDTy);
936963
} else {
937964
constructMemberDIE(Buffer, DDTy);
938965
}
@@ -952,6 +979,11 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
952979
if (unsigned PropertyAttributes = Property->getAttributes())
953980
addUInt(ElemDie, dwarf::DW_AT_APPLE_property_attribute, None,
954981
PropertyAttributes);
982+
} else if (auto *Composite = dyn_cast<DICompositeType>(Element)) {
983+
if (Composite->getTag() == dwarf::DW_TAG_variant_part) {
984+
DIE &VariantPart = createAndAddDIE(Composite->getTag(), Buffer);
985+
constructTypeDIE(VariantPart, Composite);
986+
}
955987
}
956988
}
957989

@@ -1385,7 +1417,7 @@ void DwarfUnit::constructContainingTypeDIEs() {
13851417
}
13861418
}
13871419

1388-
void DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
1420+
DIE &DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
13891421
DIE &MemberDie = createAndAddDIE(DT->getTag(), Buffer);
13901422
StringRef Name = DT->getName();
13911423
if (!Name.empty())
@@ -1490,6 +1522,8 @@ void DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
14901522

14911523
if (DT->isArtificial())
14921524
addFlag(MemberDie, dwarf::DW_AT_artificial);
1525+
1526+
return MemberDie;
14931527
}
14941528

14951529
DIE *DwarfUnit::getOrCreateStaticMemberDIE(const DIDerivedType *DT) {

lib/CodeGen/AsmPrinter/DwarfUnit.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ class DwarfUnit : public DIEUnit {
331331
void constructSubrangeDIE(DIE &Buffer, const DISubrange *SR, DIE *IndexTy);
332332
void constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy);
333333
void constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy);
334-
void constructMemberDIE(DIE &Buffer, const DIDerivedType *DT);
334+
DIE &constructMemberDIE(DIE &Buffer, const DIDerivedType *DT);
335335
void constructTemplateTypeParameterDIE(DIE &Buffer,
336336
const DITemplateTypeParameter *TP);
337337
void constructTemplateValueParameterDIE(DIE &Buffer,

lib/IR/AsmWriter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1696,6 +1696,7 @@ static void writeDICompositeType(raw_ostream &Out, const DICompositeType *N,
16961696
Printer.printMetadata("vtableHolder", N->getRawVTableHolder());
16971697
Printer.printMetadata("templateParams", N->getRawTemplateParams());
16981698
Printer.printString("identifier", N->getIdentifier());
1699+
Printer.printMetadata("discriminator", N->getRawDiscriminator());
16991700
Out << ")";
17001701
}
17011702

lib/IR/DIBuilder.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,19 @@ static ConstantAsMetadata *getConstantOrNull(Constant *C) {
333333
return nullptr;
334334
}
335335

336+
DIDerivedType *DIBuilder::createVariantMemberType(DIScope *Scope, StringRef Name,
337+
DIFile *File, unsigned LineNumber,
338+
uint64_t SizeInBits,
339+
uint32_t AlignInBits,
340+
uint64_t OffsetInBits,
341+
Constant *Discriminant,
342+
DINode::DIFlags Flags, DIType *Ty) {
343+
return DIDerivedType::get(VMContext, dwarf::DW_TAG_member, Name, File,
344+
LineNumber, getNonCompileUnitScope(Scope), Ty,
345+
SizeInBits, AlignInBits, OffsetInBits, None, Flags,
346+
getConstantOrNull(Discriminant));
347+
}
348+
336349
DIDerivedType *DIBuilder::createBitFieldMemberType(
337350
DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber,
338351
uint64_t SizeInBits, uint64_t OffsetInBits, uint64_t StorageOffsetInBits,
@@ -458,6 +471,18 @@ DICompositeType *DIBuilder::createUnionType(
458471
return R;
459472
}
460473

474+
DICompositeType *DIBuilder::createVariantPart(
475+
DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber,
476+
uint64_t SizeInBits, uint32_t AlignInBits, DINode::DIFlags Flags,
477+
DIDerivedType *Discriminator, DINodeArray Elements, StringRef UniqueIdentifier) {
478+
auto *R = DICompositeType::get(
479+
VMContext, dwarf::DW_TAG_variant_part, Name, File, LineNumber,
480+
getNonCompileUnitScope(Scope), nullptr, SizeInBits, AlignInBits, 0, Flags,
481+
Elements, 0, nullptr, nullptr, UniqueIdentifier, Discriminator);
482+
trackIfUnresolved(R);
483+
return R;
484+
}
485+
461486
DISubroutineType *DIBuilder::createSubroutineType(DITypeRefArray ParameterTypes,
462487
DINode::DIFlags Flags,
463488
unsigned CC) {

0 commit comments

Comments
 (0)