[llvm] r324426 - Add DWARF for discriminated unions

Adrian Prantl via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 6 15:46:00 PST 2018


Author: adrian
Date: Tue Feb  6 15:45:59 2018
New Revision: 324426

URL: http://llvm.org/viewvc/llvm-project?rev=324426&view=rev
Log:
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 https://github.com/rust-lang/rust/pull/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

Added:
    llvm/trunk/test/DebugInfo/Generic/discriminated-union.ll
    llvm/trunk/test/DebugInfo/Generic/univariant-discriminated-union.ll
    llvm/trunk/test/Verifier/variant-part.ll
Modified:
    llvm/trunk/include/llvm/IR/DIBuilder.h
    llvm/trunk/include/llvm/IR/DebugInfoMetadata.h
    llvm/trunk/lib/AsmParser/LLParser.cpp
    llvm/trunk/lib/BinaryFormat/Dwarf.cpp
    llvm/trunk/lib/Bitcode/Reader/MetadataLoader.cpp
    llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h
    llvm/trunk/lib/IR/AsmWriter.cpp
    llvm/trunk/lib/IR/DIBuilder.cpp
    llvm/trunk/lib/IR/DebugInfoMetadata.cpp
    llvm/trunk/lib/IR/LLVMContextImpl.h
    llvm/trunk/lib/IR/Verifier.cpp
    llvm/trunk/test/Assembler/debug-info.ll
    llvm/trunk/unittests/IR/DebugTypeODRUniquingTest.cpp
    llvm/trunk/unittests/IR/MetadataTest.cpp

Modified: llvm/trunk/include/llvm/IR/DIBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/DIBuilder.h?rev=324426&r1=324425&r2=324426&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/DIBuilder.h (original)
+++ llvm/trunk/include/llvm/IR/DIBuilder.h Tue Feb  6 15:45:59 2018
@@ -258,6 +258,27 @@ namespace llvm {
                                     uint64_t OffsetInBits,
                                     DINode::DIFlags Flags, DIType *Ty);
 
+    /// Create debugging information entry for a variant.  A variant
+    /// normally should be a member of a variant part.
+    /// \param Scope        Member scope.
+    /// \param Name         Member name.
+    /// \param File         File where this member is defined.
+    /// \param LineNo       Line number.
+    /// \param SizeInBits   Member size.
+    /// \param AlignInBits  Member alignment.
+    /// \param OffsetInBits Member offset.
+    /// \param Flags        Flags to encode member attribute, e.g. private
+    /// \param Discriminant The discriminant for this branch; null for
+    ///                     the default branch
+    /// \param Ty           Parent type.
+    DIDerivedType *createVariantMemberType(DIScope *Scope, StringRef Name,
+					   DIFile *File, unsigned LineNo,
+					   uint64_t SizeInBits,
+					   uint32_t AlignInBits,
+					   uint64_t OffsetInBits,
+					   Constant *Discriminant,
+					   DINode::DIFlags Flags, DIType *Ty);
+
     /// Create debugging information entry for a bit field member.
     /// \param Scope               Member scope.
     /// \param Name                Member name.
@@ -379,6 +400,27 @@ namespace llvm {
                                      unsigned RunTimeLang = 0,
                                      StringRef UniqueIdentifier = "");
 
+    /// Create debugging information entry for a variant part.  A
+    /// variant part normally has a discriminator (though this is not
+    /// required) and a number of variant children.
+    /// \param Scope        Scope in which this union is defined.
+    /// \param Name         Union name.
+    /// \param File         File where this member is defined.
+    /// \param LineNumber   Line number.
+    /// \param SizeInBits   Member size.
+    /// \param AlignInBits  Member alignment.
+    /// \param Flags        Flags to encode member attribute, e.g. private
+    /// \param Discriminator Discriminant member
+    /// \param Elements     Variant elements.
+    /// \param UniqueIdentifier A unique identifier for the union.
+    DICompositeType *createVariantPart(DIScope *Scope, StringRef Name,
+				       DIFile *File, unsigned LineNumber,
+				       uint64_t SizeInBits, uint32_t AlignInBits,
+				       DINode::DIFlags Flags,
+				       DIDerivedType *Discriminator,
+				       DINodeArray Elements,
+				       StringRef UniqueIdentifier = "");
+
     /// Create debugging information for template
     /// type parameter.
     /// \param Scope        Scope in which this type is defined.

Modified: llvm/trunk/include/llvm/IR/DebugInfoMetadata.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/DebugInfoMetadata.h?rev=324426&r1=324425&r2=324426&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/DebugInfoMetadata.h (original)
+++ llvm/trunk/include/llvm/IR/DebugInfoMetadata.h Tue Feb  6 15:45:59 2018
@@ -847,6 +847,12 @@ public:
       return C->getValue();
     return nullptr;
   }
+  Constant *getDiscriminantValue() const {
+    assert(getTag() == dwarf::DW_TAG_member && !isStaticMember());
+    if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData()))
+      return C->getValue();
+    return nullptr;
+  }
   /// @}
 
   static bool classof(const Metadata *MD) {
@@ -889,12 +895,13 @@ class DICompositeType : public DIType {
           uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
           DIFlags Flags, DINodeArray Elements, unsigned RuntimeLang,
           DITypeRef VTableHolder, DITemplateParameterArray TemplateParams,
-          StringRef Identifier, StorageType Storage, bool ShouldCreate = true) {
+          StringRef Identifier, DIDerivedType *Discriminator,
+          StorageType Storage, bool ShouldCreate = true) {
     return getImpl(
         Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope,
         BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(),
         RuntimeLang, VTableHolder, TemplateParams.get(),
-        getCanonicalMDString(Context, Identifier), Storage, ShouldCreate);
+        getCanonicalMDString(Context, Identifier), Discriminator, Storage, ShouldCreate);
   }
   static DICompositeType *
   getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,
@@ -902,14 +909,15 @@ class DICompositeType : public DIType {
           uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
           DIFlags Flags, Metadata *Elements, unsigned RuntimeLang,
           Metadata *VTableHolder, Metadata *TemplateParams,
-          MDString *Identifier, StorageType Storage, bool ShouldCreate = true);
+          MDString *Identifier, Metadata *Discriminator,
+          StorageType Storage, bool ShouldCreate = true);
 
   TempDICompositeType cloneImpl() const {
     return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(),
                         getScope(), getBaseType(), getSizeInBits(),
                         getAlignInBits(), getOffsetInBits(), getFlags(),
                         getElements(), getRuntimeLang(), getVTableHolder(),
-                        getTemplateParams(), getIdentifier());
+                        getTemplateParams(), getIdentifier(), getDiscriminator());
   }
 
 public:
@@ -920,10 +928,10 @@ public:
                      DIFlags Flags, DINodeArray Elements, unsigned RuntimeLang,
                      DITypeRef VTableHolder,
                      DITemplateParameterArray TemplateParams = nullptr,
-                     StringRef Identifier = ""),
+                     StringRef Identifier = "", DIDerivedType *Discriminator = nullptr),
                     (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
                      AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
-                     VTableHolder, TemplateParams, Identifier))
+                     VTableHolder, TemplateParams, Identifier, Discriminator))
   DEFINE_MDNODE_GET(DICompositeType,
                     (unsigned Tag, MDString *Name, Metadata *File,
                      unsigned Line, Metadata *Scope, Metadata *BaseType,
@@ -931,10 +939,11 @@ public:
                      uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements,
                      unsigned RuntimeLang, Metadata *VTableHolder,
                      Metadata *TemplateParams = nullptr,
-                     MDString *Identifier = nullptr),
+                     MDString *Identifier = nullptr,
+                     Metadata *Discriminator = nullptr),
                     (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
                      AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
-                     VTableHolder, TemplateParams, Identifier))
+                     VTableHolder, TemplateParams, Identifier, Discriminator))
 
   TempDICompositeType clone() const { return cloneImpl(); }
 
@@ -951,7 +960,7 @@ public:
              Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits,
              uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements,
              unsigned RuntimeLang, Metadata *VTableHolder,
-             Metadata *TemplateParams);
+             Metadata *TemplateParams, Metadata *Discriminator);
   static DICompositeType *getODRTypeIfExists(LLVMContext &Context,
                                              MDString &Identifier);
 
@@ -970,7 +979,7 @@ public:
                Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits,
                uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements,
                unsigned RuntimeLang, Metadata *VTableHolder,
-               Metadata *TemplateParams);
+               Metadata *TemplateParams, Metadata *Discriminator);
 
   DITypeRef getBaseType() const { return DITypeRef(getRawBaseType()); }
   DINodeArray getElements() const {
@@ -988,6 +997,8 @@ public:
   Metadata *getRawVTableHolder() const { return getOperand(5); }
   Metadata *getRawTemplateParams() const { return getOperand(6); }
   MDString *getRawIdentifier() const { return getOperandAs<MDString>(7); }
+  Metadata *getRawDiscriminator() const { return getOperand(8); }
+  DIDerivedType *getDiscriminator() const { return getOperandAs<DIDerivedType>(8); }
 
   /// Replace operands.
   ///

Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=324426&r1=324425&r2=324426&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLParser.cpp Tue Feb  6 15:45:59 2018
@@ -4156,7 +4156,8 @@ bool LLParser::ParseDICompositeType(MDNo
   OPTIONAL(runtimeLang, DwarfLangField, );                                     \
   OPTIONAL(vtableHolder, MDField, );                                           \
   OPTIONAL(templateParams, MDField, );                                         \
-  OPTIONAL(identifier, MDStringField, );
+  OPTIONAL(identifier, MDStringField, );                                       \
+  OPTIONAL(discriminator, MDField, );
   PARSE_MD_FIELDS();
 #undef VISIT_MD_FIELDS
 
@@ -4166,7 +4167,7 @@ bool LLParser::ParseDICompositeType(MDNo
             Context, *identifier.Val, tag.Val, name.Val, file.Val, line.Val,
             scope.Val, baseType.Val, size.Val, align.Val, offset.Val, flags.Val,
             elements.Val, runtimeLang.Val, vtableHolder.Val,
-            templateParams.Val)) {
+            templateParams.Val, discriminator.Val)) {
       Result = CT;
       return false;
     }
@@ -4177,7 +4178,8 @@ bool LLParser::ParseDICompositeType(MDNo
       DICompositeType,
       (Context, tag.Val, name.Val, file.Val, line.Val, scope.Val, baseType.Val,
        size.Val, align.Val, offset.Val, flags.Val, elements.Val,
-       runtimeLang.Val, vtableHolder.Val, templateParams.Val, identifier.Val));
+       runtimeLang.Val, vtableHolder.Val, templateParams.Val, identifier.Val,
+       discriminator.Val));
   return false;
 }
 

Modified: llvm/trunk/lib/BinaryFormat/Dwarf.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/BinaryFormat/Dwarf.cpp?rev=324426&r1=324425&r2=324426&view=diff
==============================================================================
--- llvm/trunk/lib/BinaryFormat/Dwarf.cpp (original)
+++ llvm/trunk/lib/BinaryFormat/Dwarf.cpp Tue Feb  6 15:45:59 2018
@@ -393,16 +393,6 @@ StringRef llvm::dwarf::ArrayOrderString(
   return StringRef();
 }
 
-StringRef llvm::dwarf::DiscriminantString(unsigned Discriminant) {
-  switch (Discriminant) {
-  case DW_DSC_label:
-    return "DW_DSC_label";
-  case DW_DSC_range:
-    return "DW_DSC_range";
-  }
-  return StringRef();
-}
-
 StringRef llvm::dwarf::LNStandardString(unsigned Standard) {
   switch (Standard) {
   default:
@@ -563,8 +553,6 @@ StringRef llvm::dwarf::AttributeValueStr
     return InlineCodeString(Val);
   case DW_AT_ordering:
     return ArrayOrderString(Val);
-  case DW_AT_discr_value:
-    return DiscriminantString(Val);
   }
 
   return StringRef();

Modified: llvm/trunk/lib/Bitcode/Reader/MetadataLoader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/MetadataLoader.cpp?rev=324426&r1=324425&r2=324426&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/MetadataLoader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/MetadataLoader.cpp Tue Feb  6 15:45:59 2018
@@ -1246,7 +1246,7 @@ Error MetadataLoader::MetadataLoaderImpl
     break;
   }
   case bitc::METADATA_COMPOSITE_TYPE: {
-    if (Record.size() != 16)
+    if (Record.size() < 16 || Record.size() > 17)
       return error("Invalid record");
 
     // If we have a UUID and this is not a forward declaration, lookup the
@@ -1269,6 +1269,7 @@ Error MetadataLoader::MetadataLoaderImpl
     unsigned RuntimeLang = Record[12];
     Metadata *VTableHolder = nullptr;
     Metadata *TemplateParams = nullptr;
+    Metadata *Discriminator = nullptr;
     auto *Identifier = getMDString(Record[15]);
     // If this module is being parsed so that it can be ThinLTO imported
     // into another module, composite types only need to be imported
@@ -1289,13 +1290,15 @@ Error MetadataLoader::MetadataLoaderImpl
       Elements = getMDOrNull(Record[11]);
       VTableHolder = getDITypeRefOrNull(Record[13]);
       TemplateParams = getMDOrNull(Record[14]);
+      if (Record.size() > 16)
+        Discriminator = getMDOrNull(Record[16]);
     }
     DICompositeType *CT = nullptr;
     if (Identifier)
       CT = DICompositeType::buildODRType(
           Context, *Identifier, Tag, Name, File, Line, Scope, BaseType,
           SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
-          VTableHolder, TemplateParams);
+          VTableHolder, TemplateParams, Discriminator);
 
     // Create a node if we didn't get a lazy ODR type.
     if (!CT)

Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=324426&r1=324425&r2=324426&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
+++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Tue Feb  6 15:45:59 2018
@@ -1526,6 +1526,7 @@ void ModuleBitcodeWriter::writeDIComposi
   Record.push_back(VE.getMetadataOrNullID(N->getVTableHolder()));
   Record.push_back(VE.getMetadataOrNullID(N->getTemplateParams().get()));
   Record.push_back(VE.getMetadataOrNullID(N->getRawIdentifier()));
+  Record.push_back(VE.getMetadataOrNullID(N->getDiscriminator()));
 
   Stream.EmitRecord(bitc::METADATA_COMPOSITE_TYPE, Record, Abbrev);
   Record.clear();

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp?rev=324426&r1=324425&r2=324426&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp Tue Feb  6 15:45:59 2018
@@ -946,9 +946,24 @@ void DwarfUnit::constructTypeDIE(DIE &Bu
   case dwarf::DW_TAG_enumeration_type:
     constructEnumTypeDIE(Buffer, CTy);
     break;
+  case dwarf::DW_TAG_variant_part:
   case dwarf::DW_TAG_structure_type:
   case dwarf::DW_TAG_union_type:
   case dwarf::DW_TAG_class_type: {
+    // Emit the discriminator for a variant part.
+    DIDerivedType *Discriminator = nullptr;
+    if (Tag == dwarf::DW_TAG_variant_part) {
+      Discriminator = CTy->getDiscriminator();
+      if (Discriminator) {
+        // DWARF says:
+        //    If the variant part has a discriminant, the discriminant is
+        //    represented by a separate debugging information entry which is
+        //    a child of the variant part entry.
+        DIE &DiscMember = constructMemberDIE(Buffer, Discriminator);
+        addDIEEntry(Buffer, dwarf::DW_AT_discr, DiscMember);
+      }
+    }
+
     // Add elements to structure type.
     DINodeArray Elements = CTy->getElements();
     for (const auto *Element : Elements) {
@@ -962,6 +977,18 @@ void DwarfUnit::constructTypeDIE(DIE &Bu
           addType(ElemDie, resolve(DDTy->getBaseType()), dwarf::DW_AT_friend);
         } else if (DDTy->isStaticMember()) {
           getOrCreateStaticMemberDIE(DDTy);
+        } else if (Tag == dwarf::DW_TAG_variant_part) {
+          // When emitting a variant part, wrap each member in
+          // DW_TAG_variant.
+          DIE &Variant = createAndAddDIE(dwarf::DW_TAG_variant, Buffer);
+          if (const ConstantInt *CI =
+              dyn_cast_or_null<ConstantInt>(DDTy->getDiscriminantValue())) {
+            if (isUnsignedDIType(DD, resolve(Discriminator->getBaseType())))
+              addUInt(Variant, dwarf::DW_AT_discr_value, None, CI->getZExtValue());
+            else
+              addSInt(Variant, dwarf::DW_AT_discr_value, None, CI->getSExtValue());
+          }
+          constructMemberDIE(Variant, DDTy);
         } else {
           constructMemberDIE(Buffer, DDTy);
         }
@@ -981,6 +1008,11 @@ void DwarfUnit::constructTypeDIE(DIE &Bu
         if (unsigned PropertyAttributes = Property->getAttributes())
           addUInt(ElemDie, dwarf::DW_AT_APPLE_property_attribute, None,
                   PropertyAttributes);
+      } else if (auto *Composite = dyn_cast<DICompositeType>(Element)) {
+        if (Composite->getTag() == dwarf::DW_TAG_variant_part) {
+          DIE &VariantPart = createAndAddDIE(Composite->getTag(), Buffer);
+          constructTypeDIE(VariantPart, Composite);
+        }
       }
     }
 
@@ -1430,7 +1462,7 @@ void DwarfUnit::constructContainingTypeD
   }
 }
 
-void DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
+DIE &DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
   DIE &MemberDie = createAndAddDIE(DT->getTag(), Buffer);
   StringRef Name = DT->getName();
   if (!Name.empty())
@@ -1535,6 +1567,8 @@ void DwarfUnit::constructMemberDIE(DIE &
 
   if (DT->isArtificial())
     addFlag(MemberDie, dwarf::DW_AT_artificial);
+
+  return MemberDie;
 }
 
 DIE *DwarfUnit::getOrCreateStaticMemberDIE(const DIDerivedType *DT) {

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h?rev=324426&r1=324425&r2=324426&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h Tue Feb  6 15:45:59 2018
@@ -341,7 +341,7 @@ private:
   void constructSubrangeDIE(DIE &Buffer, const DISubrange *SR, DIE *IndexTy);
   void constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy);
   void constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy);
-  void constructMemberDIE(DIE &Buffer, const DIDerivedType *DT);
+  DIE &constructMemberDIE(DIE &Buffer, const DIDerivedType *DT);
   void constructTemplateTypeParameterDIE(DIE &Buffer,
                                          const DITemplateTypeParameter *TP);
   void constructTemplateValueParameterDIE(DIE &Buffer,

Modified: llvm/trunk/lib/IR/AsmWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AsmWriter.cpp?rev=324426&r1=324425&r2=324426&view=diff
==============================================================================
--- llvm/trunk/lib/IR/AsmWriter.cpp (original)
+++ llvm/trunk/lib/IR/AsmWriter.cpp Tue Feb  6 15:45:59 2018
@@ -1691,6 +1691,7 @@ static void writeDICompositeType(raw_ost
   Printer.printMetadata("vtableHolder", N->getRawVTableHolder());
   Printer.printMetadata("templateParams", N->getRawTemplateParams());
   Printer.printString("identifier", N->getIdentifier());
+  Printer.printMetadata("discriminator", N->getRawDiscriminator());
   Out << ")";
 }
 

Modified: llvm/trunk/lib/IR/DIBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/DIBuilder.cpp?rev=324426&r1=324425&r2=324426&view=diff
==============================================================================
--- llvm/trunk/lib/IR/DIBuilder.cpp (original)
+++ llvm/trunk/lib/IR/DIBuilder.cpp Tue Feb  6 15:45:59 2018
@@ -333,6 +333,19 @@ static ConstantAsMetadata *getConstantOr
   return nullptr;
 }
 
+DIDerivedType *DIBuilder::createVariantMemberType(DIScope *Scope, StringRef Name,
+						  DIFile *File, unsigned LineNumber,
+						  uint64_t SizeInBits,
+						  uint32_t AlignInBits,
+						  uint64_t OffsetInBits,
+						  Constant *Discriminant,
+						  DINode::DIFlags Flags, DIType *Ty) {
+  return DIDerivedType::get(VMContext, dwarf::DW_TAG_member, Name, File,
+                            LineNumber, getNonCompileUnitScope(Scope), Ty,
+                            SizeInBits, AlignInBits, OffsetInBits, None, Flags,
+                            getConstantOrNull(Discriminant));
+}
+
 DIDerivedType *DIBuilder::createBitFieldMemberType(
     DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber,
     uint64_t SizeInBits, uint64_t OffsetInBits, uint64_t StorageOffsetInBits,
@@ -457,6 +470,18 @@ DICompositeType *DIBuilder::createUnionT
   trackIfUnresolved(R);
   return R;
 }
+
+DICompositeType *DIBuilder::createVariantPart(
+    DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber,
+    uint64_t SizeInBits, uint32_t AlignInBits, DINode::DIFlags Flags,
+    DIDerivedType *Discriminator, DINodeArray Elements, StringRef UniqueIdentifier) {
+  auto *R = DICompositeType::get(
+      VMContext, dwarf::DW_TAG_variant_part, Name, File, LineNumber,
+      getNonCompileUnitScope(Scope), nullptr, SizeInBits, AlignInBits, 0, Flags,
+      Elements, 0, nullptr, nullptr, UniqueIdentifier, Discriminator);
+  trackIfUnresolved(R);
+  return R;
+}
 
 DISubroutineType *DIBuilder::createSubroutineType(DITypeRefArray ParameterTypes,
                                                   DINode::DIFlags Flags,

Modified: llvm/trunk/lib/IR/DebugInfoMetadata.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/DebugInfoMetadata.cpp?rev=324426&r1=324425&r2=324426&view=diff
==============================================================================
--- llvm/trunk/lib/IR/DebugInfoMetadata.cpp (original)
+++ llvm/trunk/lib/IR/DebugInfoMetadata.cpp Tue Feb  6 15:45:59 2018
@@ -305,17 +305,18 @@ DICompositeType *DICompositeType::getImp
     unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits,
     uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags,
     Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder,
-    Metadata *TemplateParams, MDString *Identifier, StorageType Storage,
-    bool ShouldCreate) {
+    Metadata *TemplateParams, MDString *Identifier, Metadata *Discriminator,
+    StorageType Storage, bool ShouldCreate) {
   assert(isCanonical(Name) && "Expected canonical MDString");
 
   // Keep this in sync with buildODRType.
   DEFINE_GETIMPL_LOOKUP(
       DICompositeType, (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
                         AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
-                        VTableHolder, TemplateParams, Identifier));
+                        VTableHolder, TemplateParams, Identifier, Discriminator));
   Metadata *Ops[] = {File,     Scope,        Name,           BaseType,
-                     Elements, VTableHolder, TemplateParams, Identifier};
+                     Elements, VTableHolder, TemplateParams, Identifier,
+                     Discriminator};
   DEFINE_GETIMPL_STORE(DICompositeType, (Tag, Line, RuntimeLang, SizeInBits,
                                          AlignInBits, OffsetInBits, Flags),
                        Ops);
@@ -326,7 +327,7 @@ DICompositeType *DICompositeType::buildO
     Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType,
     uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
     DIFlags Flags, Metadata *Elements, unsigned RuntimeLang,
-    Metadata *VTableHolder, Metadata *TemplateParams) {
+    Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator) {
   assert(!Identifier.getString().empty() && "Expected valid identifier");
   if (!Context.isODRUniquingDebugTypes())
     return nullptr;
@@ -335,7 +336,7 @@ DICompositeType *DICompositeType::buildO
     return CT = DICompositeType::getDistinct(
                Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
                AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
-               VTableHolder, TemplateParams, &Identifier);
+               VTableHolder, TemplateParams, &Identifier, Discriminator);
 
   // Only mutate CT if it's a forward declaration and the new operands aren't.
   assert(CT->getRawIdentifier() == &Identifier && "Wrong ODR identifier?");
@@ -346,7 +347,8 @@ DICompositeType *DICompositeType::buildO
   CT->mutate(Tag, Line, RuntimeLang, SizeInBits, AlignInBits, OffsetInBits,
              Flags);
   Metadata *Ops[] = {File,     Scope,        Name,           BaseType,
-                     Elements, VTableHolder, TemplateParams, &Identifier};
+                     Elements, VTableHolder, TemplateParams, &Identifier,
+                     Discriminator};
   assert((std::end(Ops) - std::begin(Ops)) == (int)CT->getNumOperands() &&
          "Mismatched number of operands");
   for (unsigned I = 0, E = CT->getNumOperands(); I != E; ++I)
@@ -360,7 +362,7 @@ DICompositeType *DICompositeType::getODR
     Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType,
     uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
     DIFlags Flags, Metadata *Elements, unsigned RuntimeLang,
-    Metadata *VTableHolder, Metadata *TemplateParams) {
+    Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator) {
   assert(!Identifier.getString().empty() && "Expected valid identifier");
   if (!Context.isODRUniquingDebugTypes())
     return nullptr;
@@ -369,7 +371,7 @@ DICompositeType *DICompositeType::getODR
     CT = DICompositeType::getDistinct(
         Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
         AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder,
-        TemplateParams, &Identifier);
+        TemplateParams, &Identifier, Discriminator);
   return CT;
 }
 

Modified: llvm/trunk/lib/IR/LLVMContextImpl.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContextImpl.h?rev=324426&r1=324425&r2=324426&view=diff
==============================================================================
--- llvm/trunk/lib/IR/LLVMContextImpl.h (original)
+++ llvm/trunk/lib/IR/LLVMContextImpl.h Tue Feb  6 15:45:59 2018
@@ -499,18 +499,20 @@ template <> struct MDNodeKeyImpl<DICompo
   Metadata *VTableHolder;
   Metadata *TemplateParams;
   MDString *Identifier;
+  Metadata *Discriminator;
 
   MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line,
                 Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits,
                 uint32_t AlignInBits, uint64_t OffsetInBits, unsigned Flags,
                 Metadata *Elements, unsigned RuntimeLang,
                 Metadata *VTableHolder, Metadata *TemplateParams,
-                MDString *Identifier)
+                MDString *Identifier, Metadata *Discriminator)
       : Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope),
         BaseType(BaseType), SizeInBits(SizeInBits), OffsetInBits(OffsetInBits),
         AlignInBits(AlignInBits), Flags(Flags), Elements(Elements),
         RuntimeLang(RuntimeLang), VTableHolder(VTableHolder),
-        TemplateParams(TemplateParams), Identifier(Identifier) {}
+        TemplateParams(TemplateParams), Identifier(Identifier),
+        Discriminator(Discriminator) {}
   MDNodeKeyImpl(const DICompositeType *N)
       : Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()),
         Line(N->getLine()), Scope(N->getRawScope()),
@@ -519,7 +521,8 @@ template <> struct MDNodeKeyImpl<DICompo
         Flags(N->getFlags()), Elements(N->getRawElements()),
         RuntimeLang(N->getRuntimeLang()), VTableHolder(N->getRawVTableHolder()),
         TemplateParams(N->getRawTemplateParams()),
-        Identifier(N->getRawIdentifier()) {}
+        Identifier(N->getRawIdentifier()),
+        Discriminator(N->getRawDiscriminator()) {}
 
   bool isKeyOf(const DICompositeType *RHS) const {
     return Tag == RHS->getTag() && Name == RHS->getRawName() &&
@@ -532,7 +535,8 @@ template <> struct MDNodeKeyImpl<DICompo
            RuntimeLang == RHS->getRuntimeLang() &&
            VTableHolder == RHS->getRawVTableHolder() &&
            TemplateParams == RHS->getRawTemplateParams() &&
-           Identifier == RHS->getRawIdentifier();
+           Identifier == RHS->getRawIdentifier() &&
+           Discriminator == RHS->getRawDiscriminator();
   }
 
   unsigned getHashValue() const {

Modified: llvm/trunk/lib/IR/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=324426&r1=324425&r2=324426&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Verifier.cpp (original)
+++ llvm/trunk/lib/IR/Verifier.cpp Tue Feb  6 15:45:59 2018
@@ -945,7 +945,8 @@ void Verifier::visitDICompositeType(cons
                N.getTag() == dwarf::DW_TAG_structure_type ||
                N.getTag() == dwarf::DW_TAG_union_type ||
                N.getTag() == dwarf::DW_TAG_enumeration_type ||
-               N.getTag() == dwarf::DW_TAG_class_type,
+               N.getTag() == dwarf::DW_TAG_class_type ||
+               N.getTag() == dwarf::DW_TAG_variant_part,
            "invalid tag", &N);
 
   AssertDI(isScope(N.getRawScope()), "invalid scope", &N, N.getRawScope());
@@ -966,6 +967,11 @@ void Verifier::visitDICompositeType(cons
     AssertDI(N.getFile() && !N.getFile()->getFilename().empty(),
              "class/union requires a filename", &N, N.getFile());
   }
+
+  if (auto *D = N.getRawDiscriminator()) {
+    AssertDI(isa<DIDerivedType>(D) && N.getTag() == dwarf::DW_TAG_variant_part,
+             "discriminator can only appear on variant part");
+  }
 }
 
 void Verifier::visitDISubroutineType(const DISubroutineType &N) {

Modified: llvm/trunk/test/Assembler/debug-info.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/debug-info.ll?rev=324426&r1=324425&r2=324426&view=diff
==============================================================================
--- llvm/trunk/test/Assembler/debug-info.ll (original)
+++ llvm/trunk/test/Assembler/debug-info.ll Tue Feb  6 15:45:59 2018
@@ -1,8 +1,8 @@
 ; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
 ; RUN: verify-uselistorder %s
 
-; CHECK: !named = !{!0, !0, !1, !2, !3, !4, !5, !6, !7, !8, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !27, !28, !29, !30, !31, !32, !33, !33}
-!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, !37}
+; CHECK: !named = !{!0, !0, !1, !2, !3, !4, !5, !6, !7, !8, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36}
+!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, !38, !39, !40}
 
 ; CHECK:      !0 = !DISubrange(count: 3)
 ; CHECK-NEXT: !1 = !DISubrange(count: 3, lowerBound: 4)
@@ -85,3 +85,10 @@
 !35 = !DIFile(filename: "file", directory: "dir", checksumkind: CSK_MD5, checksum: "000102030405060708090a0b0c0d0e0f")
 !36 = !DIFile(filename: "file", directory: "dir", checksumkind: CSK_None)
 !37 = !DIFile(filename: "file", directory: "dir", checksumkind: CSK_None, checksum: "")
+
+; CHECK-NEXT: !34 = !DICompositeType(tag: DW_TAG_variant_part, name: "A", scope: !14, size: 64)
+; CHECK-NEXT: !35 = !DIDerivedType(tag: DW_TAG_member, scope: !34, baseType: !36, size: 64, align: 64, flags: DIFlagArtificial)
+; CHECK-NEXT: !36 = !DIBasicType(name: "u64", size: 64, encoding: DW_ATE_unsigned)
+!38 = !DICompositeType(tag: DW_TAG_variant_part, name: "A", scope: !16, size: 64, discriminator: !39)
+!39 = !DIDerivedType(tag: DW_TAG_member, scope: !38, baseType: !40, size: 64, align: 64, flags: DIFlagArtificial)
+!40 = !DIBasicType(name: "u64", size: 64, encoding: DW_ATE_unsigned)

Added: llvm/trunk/test/DebugInfo/Generic/discriminated-union.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/Generic/discriminated-union.ll?rev=324426&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/Generic/discriminated-union.ll (added)
+++ llvm/trunk/test/DebugInfo/Generic/discriminated-union.ll Tue Feb  6 15:45:59 2018
@@ -0,0 +1,80 @@
+; REQUIRES: object-emission
+
+; RUN: %llc_dwarf -O0 -filetype=obj < %s > %t
+; RUN: llvm-dwarfdump -v -debug-info %t | FileCheck %s
+
+; Check for a variant part that has two members, one of which has a
+; discriminant value.
+
+; CHECK: DW_TAG_variant_part
+;   CHECK-NOT: TAG
+;     CHECK: DW_AT_discr [DW_FORM_ref4] (cu + {{0x[0-9a-fA-F]+}} => {[[OFFSET:0x[0-9a-fA-F]+]]})
+;     CHECK-NOT: TAG
+;     CHECK: [[OFFSET]]: DW_TAG_member
+;       CHECK: DW_AT_type
+;       CHECK: DW_AT_alignment
+;       CHECK: DW_AT_data_member_location [DW_FORM_data1]	(0x00)
+;       CHECK: DW_AT_artificial [DW_FORM_flag_present]	(true)
+;     CHECK: DW_TAG_variant
+;       CHECK: DW_TAG_member
+;         CHECK: DW_AT_type
+;         CHECK: DW_AT_alignment
+;         CHECK: DW_AT_data_member_location [DW_FORM_data1]	(0x00)
+;     CHECK: DW_TAG_variant
+;       CHECK: DW_AT_discr_value [DW_FORM_data1]	(0x00)
+;       CHECK: DW_TAG_member
+;         CHECK: DW_AT_type
+;         CHECK: DW_AT_alignment
+;         CHECK: DW_AT_data_member_location [DW_FORM_data1]	(0x00)
+
+%F = type { [0 x i8], {}*, [8 x i8] }
+%"F::Nope" = type {}
+
+define internal void @_ZN2e34main17h934ff72f9a38d4bbE() unnamed_addr #0 !dbg !5 {
+start:
+  %qq = alloca %F, align 8
+  call void @llvm.dbg.declare(metadata %F* %qq, metadata !10, metadata !28), !dbg !29
+  %0 = bitcast %F* %qq to {}**, !dbg !29
+  store {}* null, {}** %0, !dbg !29
+  %1 = bitcast %F* %qq to %"F::Nope"*, !dbg !29
+  ret void, !dbg !30
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #0
+
+attributes #0 = { nounwind uwtable }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.dbg.cu = !{!2}
+
+!0 = !{i32 1, !"PIE Level", i32 2}
+!1 = !{i32 2, !"Debug Info Version", i32 3}
+!2 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !3, producer: "clang LLVM (rustc version 1.24.0-dev)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4)
+!3 = !DIFile(filename: "e3.rs", directory: "/home/tromey/Rust")
+!4 = !{}
+!5 = distinct !DISubprogram(name: "main", linkageName: "_ZN2e34mainE", scope: !6, file: !3, line: 2, type: !8, isLocal: true, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped | DIFlagMainSubprogram, isOptimized: false, unit: !2, templateParams: !4, variables: !4)
+!6 = !DINamespace(name: "e3", scope: null)
+!7 = !DIFile(filename: "<unknown>", directory: "")
+!8 = !DISubroutineType(types: !9)
+!9 = !{null}
+!10 = !DILocalVariable(name: "qq", scope: !11, file: !3, line: 3, type: !12, align: 8)
+!11 = distinct !DILexicalBlock(scope: !5, file: !3, line: 3, column: 4)
+!12 = !DICompositeType(tag: DW_TAG_structure_type, name: "F", scope: !6, file: !7, size: 128, align: 64, elements: !13, identifier: "7ce1efff6b82281ab9ceb730566e7e20")
+!13 = !{!14}
+!14 = !DICompositeType(tag: DW_TAG_variant_part, name: "", scope: !12, file: !7, size: 128, align: 64, elements: !16, identifier: "7ce1efff6b82281ab9ceb730566e7e20", discriminator: !15)
+!15 = !DIDerivedType(tag: DW_TAG_member, scope: !14, file: !7, baseType: !27, size: 64, align: 64, flags: DIFlagArtificial)
+!16 = !{!17, !24}
+!17 = !DIDerivedType(tag: DW_TAG_member, scope: !14, file: !7, baseType: !18, size: 128, align: 64)
+!18 = !DICompositeType(tag: DW_TAG_structure_type, name: "Yep", scope: !12, file: !7, size: 128, align: 64, elements: !19, identifier: "7ce1efff6b82281ab9ceb730566e7e20::Yep")
+!19 = !{!20, !22}
+!20 = !DIDerivedType(tag: DW_TAG_member, name: "__0", scope: !18, file: !7, baseType: !21, size: 8, align: 8, offset: 64)
+!21 = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned)
+!22 = !DIDerivedType(tag: DW_TAG_member, name: "__1", scope: !18, file: !7, baseType: !23, size: 64, align: 64)
+!23 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&u8", baseType: !21, size: 64, align: 64)
+!24 = !DIDerivedType(tag: DW_TAG_member, scope: !14, file: !7, baseType: !25, size: 128, align: 64, extraData: i64 0)
+!25 = !DICompositeType(tag: DW_TAG_structure_type, name: "Nope", scope: !12, file: !7, size: 128, align: 64, elements: !4, identifier: "7ce1efff6b82281ab9ceb730566e7e20::Nope")
+!27 = !DIBasicType(name: "u64", size: 64, encoding: DW_ATE_unsigned)
+!28 = !DIExpression()
+!29 = !DILocation(line: 3, scope: !11)
+!30 = !DILocation(line: 4, scope: !5)

Added: llvm/trunk/test/DebugInfo/Generic/univariant-discriminated-union.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/Generic/univariant-discriminated-union.ll?rev=324426&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/Generic/univariant-discriminated-union.ll (added)
+++ llvm/trunk/test/DebugInfo/Generic/univariant-discriminated-union.ll Tue Feb  6 15:45:59 2018
@@ -0,0 +1,65 @@
+; REQUIRES: object-emission
+
+; RUN: %llc_dwarf -O0 -filetype=obj < %s > %t
+; RUN: llvm-dwarfdump -v -debug-info %t | FileCheck %s
+
+; Check for a univariant discriminated union -- that is, a variant
+; part without a discriminant and with just a single variant.
+
+; CHECK: DW_TAG_variant_part
+;   CHECK-NOT: DW_AT_discr
+;   CHECK: DW_TAG_variant
+;     CHECK: DW_TAG_member
+;       CHECK: DW_AT_type
+;       CHECK: DW_AT_alignment
+;       CHECK: DW_AT_data_member_location [DW_FORM_data1]	(0x00)
+
+%F = type { [0 x i8], {}*, [8 x i8] }
+%"F::Nope" = type {}
+
+define internal void @_ZN2e34main17h934ff72f9a38d4bbE() unnamed_addr #0 !dbg !5 {
+start:
+  %qq = alloca %F, align 8
+  call void @llvm.dbg.declare(metadata %F* %qq, metadata !10, metadata !28), !dbg !29
+  %0 = bitcast %F* %qq to {}**, !dbg !29
+  store {}* null, {}** %0, !dbg !29
+  %1 = bitcast %F* %qq to %"F::Nope"*, !dbg !29
+  ret void, !dbg !30
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #0
+
+attributes #0 = { nounwind uwtable }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.dbg.cu = !{!2}
+
+!0 = !{i32 1, !"PIE Level", i32 2}
+!1 = !{i32 2, !"Debug Info Version", i32 3}
+!2 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !3, producer: "clang LLVM (rustc version 1.24.0-dev)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4)
+!3 = !DIFile(filename: "e3.rs", directory: "/home/tromey/Rust")
+!4 = !{}
+!5 = distinct !DISubprogram(name: "main", linkageName: "_ZN2e34mainE", scope: !6, file: !3, line: 2, type: !8, isLocal: true, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped | DIFlagMainSubprogram, isOptimized: false, unit: !2, templateParams: !4, variables: !4)
+!6 = !DINamespace(name: "e3", scope: null)
+!7 = !DIFile(filename: "<unknown>", directory: "")
+!8 = !DISubroutineType(types: !9)
+!9 = !{null}
+!10 = !DILocalVariable(name: "qq", scope: !11, file: !3, line: 3, type: !12, align: 8)
+!11 = distinct !DILexicalBlock(scope: !5, file: !3, line: 3, column: 4)
+!12 = !DICompositeType(tag: DW_TAG_structure_type, name: "F", scope: !6, file: !7, size: 128, align: 64, elements: !13, identifier: "7ce1efff6b82281ab9ceb730566e7e20")
+!13 = !{!14}
+!14 = !DICompositeType(tag: DW_TAG_variant_part, name: "", scope: !12, file: !7, size: 128, align: 64, elements: !16, identifier: "7ce1efff6b82281ab9ceb730566e7e20")
+
+!16 = !{!17}
+!17 = !DIDerivedType(tag: DW_TAG_member, scope: !14, file: !7, baseType: !18, size: 128, align: 64)
+!18 = !DICompositeType(tag: DW_TAG_structure_type, name: "Yep", scope: !12, file: !7, size: 128, align: 64, elements: !19, identifier: "7ce1efff6b82281ab9ceb730566e7e20::Yep")
+!19 = !{!20, !22}
+!20 = !DIDerivedType(tag: DW_TAG_member, name: "__0", scope: !18, file: !7, baseType: !21, size: 8, align: 8, offset: 64)
+!21 = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned)
+!22 = !DIDerivedType(tag: DW_TAG_member, name: "__1", scope: !18, file: !7, baseType: !23, size: 64, align: 64)
+!23 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&u8", baseType: !21, size: 64, align: 64)
+
+!28 = !DIExpression()
+!29 = !DILocation(line: 3, scope: !11)
+!30 = !DILocation(line: 4, scope: !5)

Added: llvm/trunk/test/Verifier/variant-part.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/variant-part.ll?rev=324426&view=auto
==============================================================================
--- llvm/trunk/test/Verifier/variant-part.ll (added)
+++ llvm/trunk/test/Verifier/variant-part.ll Tue Feb  6 15:45:59 2018
@@ -0,0 +1,8 @@
+; RUN: not llvm-as -disable-output <%s 2>&1 | FileCheck %s
+
+!named = !{!0}
+!0 = !DICompositeType(tag: DW_TAG_structure_type, name: "A", size: 64, discriminator: !1)
+!1 = !DIDerivedType(tag: DW_TAG_member, scope: !0, baseType: !3, size: 64, align: 64, flags: DIFlagArtificial)
+!3 = !DIBasicType(name: "u64", size: 64, encoding: DW_ATE_unsigned)
+
+; CHECK: discriminator can only appear on variant part

Modified: llvm/trunk/unittests/IR/DebugTypeODRUniquingTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/DebugTypeODRUniquingTest.cpp?rev=324426&r1=324425&r2=324426&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/DebugTypeODRUniquingTest.cpp (original)
+++ llvm/trunk/unittests/IR/DebugTypeODRUniquingTest.cpp Tue Feb  6 15:45:59 2018
@@ -30,7 +30,7 @@ TEST(DebugTypeODRUniquingTest, getODRTyp
   // Without a type map, this should return null.
   EXPECT_FALSE(DICompositeType::getODRType(
       Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
-      nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr));
+      nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr, nullptr));
 
   // Enable the mapping.  There still shouldn't be a type.
   Context.enableDebugTypeODRUniquing();
@@ -39,7 +39,7 @@ TEST(DebugTypeODRUniquingTest, getODRTyp
   // Create some ODR-uniqued type.
   auto &CT = *DICompositeType::getODRType(
       Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
-      nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr);
+      nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr, nullptr);
   EXPECT_EQ(UUID.getString(), CT.getIdentifier());
 
   // Check that we get it back, even if we change a field.
@@ -47,12 +47,12 @@ TEST(DebugTypeODRUniquingTest, getODRTyp
   EXPECT_EQ(&CT, DICompositeType::getODRType(
                      Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr,
                      0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0,
-                     nullptr, nullptr));
+                     nullptr, nullptr, nullptr));
   EXPECT_EQ(&CT,
             DICompositeType::getODRType(
                 Context, UUID, dwarf::DW_TAG_class_type,
                 MDString::get(Context, "name"), nullptr, 0, nullptr, nullptr, 0,
-                0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr));
+                0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr, nullptr));
 
   // Check that it's discarded with the type map.
   Context.disableDebugTypeODRUniquing();
@@ -71,32 +71,32 @@ TEST(DebugTypeODRUniquingTest, buildODRT
   MDString &UUID = *MDString::get(Context, "Type");
   auto &CT = *DICompositeType::buildODRType(
       Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
-      nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr);
+      nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, nullptr);
   EXPECT_EQ(&CT, DICompositeType::getODRTypeIfExists(Context, UUID));
   EXPECT_EQ(dwarf::DW_TAG_class_type, CT.getTag());
 
   // Update with another forward decl.  This should be a no-op.
   EXPECT_EQ(&CT, DICompositeType::buildODRType(
       Context, UUID, dwarf::DW_TAG_structure_type, nullptr, nullptr, 0, nullptr,
-      nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr));
+      nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, nullptr));
   EXPECT_EQ(dwarf::DW_TAG_class_type, CT.getTag());
 
   // Update with a definition.  This time we should see a change.
   EXPECT_EQ(&CT, DICompositeType::buildODRType(
                      Context, UUID, dwarf::DW_TAG_structure_type, nullptr,
                      nullptr, 0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero,
-                     nullptr, 0, nullptr, nullptr));
+                     nullptr, 0, nullptr, nullptr, nullptr));
   EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
 
   // Further updates should be ignored.
   EXPECT_EQ(&CT, DICompositeType::buildODRType(
       Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
-      nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr));
+      nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, nullptr));
   EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
   EXPECT_EQ(&CT, DICompositeType::buildODRType(
                      Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr,
                      0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0,
-                     nullptr, nullptr));
+                     nullptr, nullptr, nullptr));
   EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
 }
 
@@ -108,7 +108,7 @@ TEST(DebugTypeODRUniquingTest, buildODRT
   MDString &UUID = *MDString::get(Context, "UUID");
   auto &CT = *DICompositeType::buildODRType(
       Context, UUID, 0, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0,
-      DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr);
+      DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, nullptr);
 
 // Create macros for running through all the fields except Identifier and Flags.
 #define FOR_EACH_MDFIELD()                                                     \
@@ -141,7 +141,7 @@ TEST(DebugTypeODRUniquingTest, buildODRT
             DICompositeType::buildODRType(
                 Context, UUID, Tag, Name, File, Line, Scope, BaseType,
                 SizeInBits, AlignInBits, OffsetInBits, DINode::FlagArtificial,
-                Elements, RuntimeLang, VTableHolder, TemplateParams));
+                Elements, RuntimeLang, VTableHolder, TemplateParams, nullptr));
 
   // Confirm that all the right fields got updated.
 #define DO_FOR_FIELD(X) EXPECT_EQ(X, CT.getRaw##X());

Modified: llvm/trunk/unittests/IR/MetadataTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/MetadataTest.cpp?rev=324426&r1=324425&r2=324426&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/MetadataTest.cpp (original)
+++ llvm/trunk/unittests/IR/MetadataTest.cpp Tue Feb  6 15:45:59 2018
@@ -1355,6 +1355,51 @@ TEST_F(DICompositeTypeTest, replaceOpera
   EXPECT_EQ(nullptr, N->getTemplateParams().get());
 }
 
+TEST_F(DICompositeTypeTest, variant_part) {
+  unsigned Tag = dwarf::DW_TAG_variant_part;
+  StringRef Name = "some name";
+  DIFile *File = getFile();
+  unsigned Line = 1;
+  DIScope *Scope = getSubprogram();
+  DIType *BaseType = getCompositeType();
+  uint64_t SizeInBits = 2;
+  uint32_t AlignInBits = 3;
+  uint64_t OffsetInBits = 4;
+  DINode::DIFlags Flags = static_cast<DINode::DIFlags>(5);
+  unsigned RuntimeLang = 6;
+  StringRef Identifier = "some id";
+  DIDerivedType *Discriminator = cast<DIDerivedType>(getDerivedType());
+  DIDerivedType *Discriminator2 = cast<DIDerivedType>(getDerivedType());
+
+  EXPECT_NE(Discriminator, Discriminator2);
+
+  auto *N = DICompositeType::get(
+      Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
+      OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
+      Discriminator);
+
+  // Test the hashing.
+  auto *Same = DICompositeType::get(
+      Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
+      OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
+      Discriminator);
+  auto *Other = DICompositeType::get(
+      Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
+      OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
+      Discriminator2);
+  auto *NoDisc = DICompositeType::get(
+      Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
+      OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
+      nullptr);
+
+  EXPECT_EQ(N, Same);
+  EXPECT_NE(Same, Other);
+  EXPECT_NE(Same, NoDisc);
+  EXPECT_NE(Other, NoDisc);
+
+  EXPECT_EQ(N->getDiscriminator(), Discriminator);
+}
+
 typedef MetadataTest DISubroutineTypeTest;
 
 TEST_F(DISubroutineTypeTest, get) {




More information about the llvm-commits mailing list