[llvm] 4042ada - [DebugInfo] support for DW_AT_data_location in llvm

Sourabh Singh Tomar via llvm-commits llvm-commits at lists.llvm.org
Thu May 14 23:05:12 PDT 2020


Author: Alok Kumar Sharma
Date: 2020-05-15T11:33:17+05:30
New Revision: 4042ada1c1fe4a9cd546600602281686bb2270cd

URL: https://github.com/llvm/llvm-project/commit/4042ada1c1fe4a9cd546600602281686bb2270cd
DIFF: https://github.com/llvm/llvm-project/commit/4042ada1c1fe4a9cd546600602281686bb2270cd.diff

LOG: [DebugInfo] support for DW_AT_data_location in llvm

This patch adds support for DWARF attribute DW_AT_data_location.

Summary:
Dynamic arrays in fortran are described by array descriptor and
data allocation address. Former is mapped to DW_AT_location and
later is mapped to DW_AT_data_location.

Testing:
unit test cases added (hand-written)
check llvm
check debug-info

Reviewed By: aprantl

Differential Revision: https://reviews.llvm.org/D79592

Added: 
    llvm/test/Bitcode/dataLocation.ll
    llvm/test/DebugInfo/dwarfdump-dataLocationExp.ll
    llvm/test/DebugInfo/dwarfdump-dataLocationVar.ll
    llvm/test/Verifier/array_dataLocation.ll

Modified: 
    llvm/docs/LangRef.rst
    llvm/include/llvm/IR/DebugInfoMetadata.h
    llvm/lib/AsmParser/LLParser.cpp
    llvm/lib/Bitcode/Reader/MetadataLoader.cpp
    llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
    llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
    llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
    llvm/lib/IR/AsmWriter.cpp
    llvm/lib/IR/DebugInfoMetadata.cpp
    llvm/lib/IR/LLVMContextImpl.h
    llvm/lib/IR/Verifier.cpp
    llvm/unittests/IR/DebugTypeODRUniquingTest.cpp
    llvm/unittests/IR/MetadataTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 8b5bc8f3a95f..240dbd68e9e0 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -4810,7 +4810,12 @@ The following ``tag:`` values are valid:
 For ``DW_TAG_array_type``, the ``elements:`` should be :ref:`subrange
 descriptors <DISubrange>`, each representing the range of subscripts at that
 level of indexing. The ``DIFlagVector`` flag to ``flags:`` indicates that an
-array type is a native packed vector.
+array type is a native packed vector. The optional ``dataLocation`` is a
+DIExpression that describes how to get from an object's address to the actual
+raw data, if they aren't equivalent. This is only supported for array types,
+particularly to describe Fortran arrays, which have an array descriptor in
+addition to the array data. Alternatively it can also be DIVariable which
+has the address of the actual raw data.
 
 For ``DW_TAG_enumeration_type``, the ``elements:`` should be :ref:`enumerator
 descriptors <DIEnumerator>`, each representing the definition of an enumeration

diff  --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 26d6e12f0eb4..7dca44247c04 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -931,13 +931,14 @@ class DICompositeType : public DIType {
           uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags,
           DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder,
           DITemplateParameterArray TemplateParams, 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), Discriminator, Storage, ShouldCreate);
+          DIDerivedType *Discriminator, Metadata *DataLocation,
+          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), Discriminator,
+                   DataLocation, Storage, ShouldCreate);
   }
   static DICompositeType *
   getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,
@@ -945,7 +946,7 @@ 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, Metadata *Discriminator,
+          MDString *Identifier, Metadata *Discriminator, Metadata *DataLocation,
           StorageType Storage, bool ShouldCreate = true);
 
   TempDICompositeType cloneImpl() const {
@@ -953,34 +954,34 @@ class DICompositeType : public DIType {
                         getScope(), getBaseType(), getSizeInBits(),
                         getAlignInBits(), getOffsetInBits(), getFlags(),
                         getElements(), getRuntimeLang(), getVTableHolder(),
-                        getTemplateParams(), getIdentifier(), getDiscriminator());
+                        getTemplateParams(), getIdentifier(),
+                        getDiscriminator(), getRawDataLocation());
   }
 
 public:
-  DEFINE_MDNODE_GET(DICompositeType,
-                    (unsigned Tag, StringRef Name, DIFile *File, unsigned Line,
-                     DIScope *Scope, DIType *BaseType, uint64_t SizeInBits,
-                     uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags,
-                     DINodeArray Elements, unsigned RuntimeLang,
-                     DIType *VTableHolder,
-                     DITemplateParameterArray TemplateParams = nullptr,
-                     StringRef Identifier = "",
-                     DIDerivedType *Discriminator = nullptr),
-                    (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
-                     AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
-                     VTableHolder, TemplateParams, Identifier, Discriminator))
-  DEFINE_MDNODE_GET(DICompositeType,
-                    (unsigned Tag, MDString *Name, 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 = nullptr,
-                     MDString *Identifier = nullptr,
-                     Metadata *Discriminator = nullptr),
-                    (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
-                     AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
-                     VTableHolder, TemplateParams, Identifier, Discriminator))
+  DEFINE_MDNODE_GET(
+      DICompositeType,
+      (unsigned Tag, StringRef Name, DIFile *File, unsigned Line,
+       DIScope *Scope, DIType *BaseType, uint64_t SizeInBits,
+       uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags,
+       DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder,
+       DITemplateParameterArray TemplateParams = nullptr,
+       StringRef Identifier = "", DIDerivedType *Discriminator = nullptr,
+       Metadata *DataLocation = nullptr),
+      (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
+       OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams,
+       Identifier, Discriminator, DataLocation))
+  DEFINE_MDNODE_GET(
+      DICompositeType,
+      (unsigned Tag, MDString *Name, 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 = nullptr, MDString *Identifier = nullptr,
+       Metadata *Discriminator = nullptr, Metadata *DataLocation = nullptr),
+      (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
+       OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams,
+       Identifier, Discriminator, DataLocation))
 
   TempDICompositeType clone() const { return cloneImpl(); }
 
@@ -997,7 +998,8 @@ class DICompositeType : public DIType {
              Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits,
              uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements,
              unsigned RuntimeLang, Metadata *VTableHolder,
-             Metadata *TemplateParams, Metadata *Discriminator);
+             Metadata *TemplateParams, Metadata *Discriminator,
+             Metadata *DataLocation);
   static DICompositeType *getODRTypeIfExists(LLVMContext &Context,
                                              MDString &Identifier);
 
@@ -1016,7 +1018,8 @@ class DICompositeType : public DIType {
                Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits,
                uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements,
                unsigned RuntimeLang, Metadata *VTableHolder,
-               Metadata *TemplateParams, Metadata *Discriminator);
+               Metadata *TemplateParams, Metadata *Discriminator,
+               Metadata *DataLocation);
 
   DIType *getBaseType() const { return cast_or_null<DIType>(getRawBaseType()); }
   DINodeArray getElements() const {
@@ -1038,6 +1041,13 @@ class DICompositeType : public DIType {
   MDString *getRawIdentifier() const { return getOperandAs<MDString>(7); }
   Metadata *getRawDiscriminator() const { return getOperand(8); }
   DIDerivedType *getDiscriminator() const { return getOperandAs<DIDerivedType>(8); }
+  Metadata *getRawDataLocation() const { return getOperand(9); }
+  DIVariable *getDataLocation() const {
+    return dyn_cast_or_null<DIVariable>(getRawDataLocation());
+  }
+  DIExpression *getDataLocationExp() const {
+    return dyn_cast_or_null<DIExpression>(getRawDataLocation());
+  }
 
   /// Replace operands.
   ///

diff  --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 0cfaae0c0b67..ce1e9d23210e 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -4617,7 +4617,8 @@ bool LLParser::ParseDICompositeType(MDNode *&Result, bool IsDistinct) {
   OPTIONAL(vtableHolder, MDField, );                                           \
   OPTIONAL(templateParams, MDField, );                                         \
   OPTIONAL(identifier, MDStringField, );                                       \
-  OPTIONAL(discriminator, MDField, );
+  OPTIONAL(discriminator, MDField, );                                          \
+  OPTIONAL(dataLocation, MDField, );
   PARSE_MD_FIELDS();
 #undef VISIT_MD_FIELDS
 
@@ -4626,8 +4627,8 @@ bool LLParser::ParseDICompositeType(MDNode *&Result, bool IsDistinct) {
     if (auto *CT = DICompositeType::buildODRType(
             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, discriminator.Val)) {
+            elements.Val, runtimeLang.Val, vtableHolder.Val, templateParams.Val,
+            discriminator.Val, dataLocation.Val)) {
       Result = CT;
       return false;
     }
@@ -4639,7 +4640,7 @@ bool LLParser::ParseDICompositeType(MDNode *&Result, bool IsDistinct) {
       (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,
-       discriminator.Val));
+       discriminator.Val, dataLocation.Val));
   return false;
 }
 

diff  --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
index 33776bd1be6b..7338d170cb48 100644
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -1340,7 +1340,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
     break;
   }
   case bitc::METADATA_COMPOSITE_TYPE: {
-    if (Record.size() < 16 || Record.size() > 17)
+    if (Record.size() < 16 || Record.size() > 18)
       return error("Invalid record");
 
     // If we have a UUID and this is not a forward declaration, lookup the
@@ -1364,6 +1364,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
     Metadata *VTableHolder = nullptr;
     Metadata *TemplateParams = nullptr;
     Metadata *Discriminator = nullptr;
+    Metadata *DataLocation = 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
@@ -1386,13 +1387,15 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
       TemplateParams = getMDOrNull(Record[14]);
       if (Record.size() > 16)
         Discriminator = getMDOrNull(Record[16]);
+      if (Record.size() > 17)
+        DataLocation = getMDOrNull(Record[17]);
     }
     DICompositeType *CT = nullptr;
     if (Identifier)
       CT = DICompositeType::buildODRType(
           Context, *Identifier, Tag, Name, File, Line, Scope, BaseType,
           SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
-          VTableHolder, TemplateParams, Discriminator);
+          VTableHolder, TemplateParams, Discriminator, DataLocation);
 
     // Create a node if we didn't get a lazy ODR type.
     if (!CT)
@@ -1400,7 +1403,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
                            (Context, Tag, Name, File, Line, Scope, BaseType,
                             SizeInBits, AlignInBits, OffsetInBits, Flags,
                             Elements, RuntimeLang, VTableHolder, TemplateParams,
-                            Identifier, Discriminator));
+                            Identifier, Discriminator, DataLocation));
     if (!IsNotUsedInTypeRef && Identifier)
       MetadataList.addTypeRef(*Identifier, *cast<DICompositeType>(CT));
 

diff  --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index c70c5ac543b2..9e389fc64a64 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -1627,6 +1627,7 @@ void ModuleBitcodeWriter::writeDICompositeType(
   Record.push_back(VE.getMetadataOrNullID(N->getTemplateParams().get()));
   Record.push_back(VE.getMetadataOrNullID(N->getRawIdentifier()));
   Record.push_back(VE.getMetadataOrNullID(N->getDiscriminator()));
+  Record.push_back(VE.getMetadataOrNullID(N->getRawDataLocation()));
 
   Stream.EmitRecord(bitc::METADATA_COMPOSITE_TYPE, Record, Abbrev);
   Record.clear();

diff  --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index dbe782980f36..93bf9d6c2f71 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -764,6 +764,8 @@ static SmallVector<const DIVariable *, 2> dependencies(DbgVariable *Var) {
   auto *Array = dyn_cast<DICompositeType>(Var->getType());
   if (!Array || Array->getTag() != dwarf::DW_TAG_array_type)
     return Result;
+  if (auto *DLVar = Array->getDataLocation())
+    Result.push_back(DLVar);
   for (auto *El : Array->getElements()) {
     if (auto *Subrange = dyn_cast<DISubrange>(El)) {
       auto Count = Subrange->getCount();

diff  --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index ba20e08aae2e..62bf51d42206 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -1414,6 +1414,17 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
               CTy->getSizeInBits() / CHAR_BIT);
   }
 
+  if (DIVariable *Var = CTy->getDataLocation()) {
+    if (auto *VarDIE = getDIE(Var))
+      addDIEEntry(Buffer, dwarf::DW_AT_data_location, *VarDIE);
+  } else if (DIExpression *Expr = CTy->getDataLocationExp()) {
+    DIELoc *Loc = new (DIEValueAllocator) DIELoc;
+    DIEDwarfExpression DwarfExpr(*Asm, getCU(), *Loc);
+    DwarfExpr.setMemoryLocationKind();
+    DwarfExpr.addExpression(Expr);
+    addBlock(Buffer, dwarf::DW_AT_data_location, DwarfExpr.finalize());
+  }
+
   // Emit the element type.
   addType(Buffer, CTy->getBaseType());
 

diff  --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 83874e47a015..6f451a12c4c0 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -1931,6 +1931,7 @@ static void writeDICompositeType(raw_ostream &Out, const DICompositeType *N,
   Printer.printMetadata("templateParams", N->getRawTemplateParams());
   Printer.printString("identifier", N->getIdentifier());
   Printer.printMetadata("discriminator", N->getRawDiscriminator());
+  Printer.printMetadata("dataLocation", N->getRawDataLocation());
   Out << ")";
 }
 

diff  --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index 83e0958e21f2..f1e946c1902e 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -405,17 +405,18 @@ DICompositeType *DICompositeType::getImpl(
     uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags,
     Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder,
     Metadata *TemplateParams, MDString *Identifier, Metadata *Discriminator,
-    StorageType Storage, bool ShouldCreate) {
+    Metadata *DataLocation, 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, Discriminator));
-  Metadata *Ops[] = {File,     Scope,        Name,           BaseType,
-                     Elements, VTableHolder, TemplateParams, Identifier,
-                     Discriminator};
+  DEFINE_GETIMPL_LOOKUP(DICompositeType,
+                        (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+                         AlignInBits, OffsetInBits, Flags, Elements,
+                         RuntimeLang, VTableHolder, TemplateParams, Identifier,
+                         Discriminator, DataLocation));
+  Metadata *Ops[] = {File,          Scope,        Name,           BaseType,
+                     Elements,      VTableHolder, TemplateParams, Identifier,
+                     Discriminator, DataLocation};
   DEFINE_GETIMPL_STORE(DICompositeType, (Tag, Line, RuntimeLang, SizeInBits,
                                          AlignInBits, OffsetInBits, Flags),
                        Ops);
@@ -426,7 +427,8 @@ DICompositeType *DICompositeType::buildODRType(
     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 *Discriminator) {
+    Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator,
+    Metadata *DataLocation) {
   assert(!Identifier.getString().empty() && "Expected valid identifier");
   if (!Context.isODRUniquingDebugTypes())
     return nullptr;
@@ -435,7 +437,8 @@ DICompositeType *DICompositeType::buildODRType(
     return CT = DICompositeType::getDistinct(
                Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
                AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
-               VTableHolder, TemplateParams, &Identifier, Discriminator);
+               VTableHolder, TemplateParams, &Identifier, Discriminator,
+               DataLocation);
 
   // Only mutate CT if it's a forward declaration and the new operands aren't.
   assert(CT->getRawIdentifier() == &Identifier && "Wrong ODR identifier?");
@@ -445,9 +448,9 @@ DICompositeType *DICompositeType::buildODRType(
   // Mutate CT in place.  Keep this in sync with getImpl.
   CT->mutate(Tag, Line, RuntimeLang, SizeInBits, AlignInBits, OffsetInBits,
              Flags);
-  Metadata *Ops[] = {File,     Scope,        Name,           BaseType,
-                     Elements, VTableHolder, TemplateParams, &Identifier,
-                     Discriminator};
+  Metadata *Ops[] = {File,          Scope,        Name,           BaseType,
+                     Elements,      VTableHolder, TemplateParams, &Identifier,
+                     Discriminator, DataLocation};
   assert((std::end(Ops) - std::begin(Ops)) == (int)CT->getNumOperands() &&
          "Mismatched number of operands");
   for (unsigned I = 0, E = CT->getNumOperands(); I != E; ++I)
@@ -461,7 +464,8 @@ DICompositeType *DICompositeType::getODRType(
     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 *Discriminator) {
+    Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator,
+    Metadata *DataLocation) {
   assert(!Identifier.getString().empty() && "Expected valid identifier");
   if (!Context.isODRUniquingDebugTypes())
     return nullptr;
@@ -470,7 +474,7 @@ DICompositeType *DICompositeType::getODRType(
     CT = DICompositeType::getDistinct(
         Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
         AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder,
-        TemplateParams, &Identifier, Discriminator);
+        TemplateParams, &Identifier, Discriminator, DataLocation);
   return CT;
 }
 

diff  --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index 543f2e964e73..a019f1ee07b9 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -510,19 +510,21 @@ template <> struct MDNodeKeyImpl<DICompositeType> {
   Metadata *TemplateParams;
   MDString *Identifier;
   Metadata *Discriminator;
+  Metadata *DataLocation;
 
   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, Metadata *Discriminator)
+                MDString *Identifier, Metadata *Discriminator,
+                Metadata *DataLocation)
       : 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),
-        Discriminator(Discriminator) {}
+        Discriminator(Discriminator), DataLocation(DataLocation) {}
   MDNodeKeyImpl(const DICompositeType *N)
       : Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()),
         Line(N->getLine()), Scope(N->getRawScope()),
@@ -532,7 +534,8 @@ template <> struct MDNodeKeyImpl<DICompositeType> {
         RuntimeLang(N->getRuntimeLang()), VTableHolder(N->getRawVTableHolder()),
         TemplateParams(N->getRawTemplateParams()),
         Identifier(N->getRawIdentifier()),
-        Discriminator(N->getRawDiscriminator()) {}
+        Discriminator(N->getRawDiscriminator()),
+        DataLocation(N->getRawDataLocation()) {}
 
   bool isKeyOf(const DICompositeType *RHS) const {
     return Tag == RHS->getTag() && Name == RHS->getRawName() &&
@@ -546,7 +549,8 @@ template <> struct MDNodeKeyImpl<DICompositeType> {
            VTableHolder == RHS->getRawVTableHolder() &&
            TemplateParams == RHS->getRawTemplateParams() &&
            Identifier == RHS->getRawIdentifier() &&
-           Discriminator == RHS->getRawDiscriminator();
+           Discriminator == RHS->getRawDiscriminator() &&
+           DataLocation == RHS->getRawDataLocation();
   }
 
   unsigned getHashValue() const {

diff  --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 464a052b783d..8fbc9e743990 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -1011,6 +1011,11 @@ void Verifier::visitDICompositeType(const DICompositeType &N) {
     AssertDI(isa<DIDerivedType>(D) && N.getTag() == dwarf::DW_TAG_variant_part,
              "discriminator can only appear on variant part");
   }
+
+  if (N.getRawDataLocation()) {
+    AssertDI(N.getTag() == dwarf::DW_TAG_array_type,
+             "dataLocation can only appear in array type");
+  }
 }
 
 void Verifier::visitDISubroutineType(const DISubroutineType &N) {

diff  --git a/llvm/test/Bitcode/dataLocation.ll b/llvm/test/Bitcode/dataLocation.ll
new file mode 100644
index 000000000000..4b491d0f961a
--- /dev/null
+++ b/llvm/test/Bitcode/dataLocation.ll
@@ -0,0 +1,31 @@
+;; This test checks dataLocation field of DICompositeType
+
+; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
+
+;; Test whether DW_AT_data_location is generated.
+; CHECK:  !DICompositeType(tag: DW_TAG_array_type, baseType: !{{[0-9]+}}, size: 32, align: 32, elements: !{{[0-9]+}}, dataLocation: !{{[0-9]+}})
+; CHECK:  !DICompositeType(tag: DW_TAG_array_type, baseType: !{{[0-9]+}}, size: 32, align: 32, elements: !{{[0-9]+}}, dataLocation: !DIExpression(DW_OP_constu, 3412))
+
+; ModuleID = 'dataLocation.f90'
+source_filename = "/dir/dataLocation.ll"
+
+!llvm.module.flags = !{!0, !1}
+!llvm.dbg.cu = !{!2}
+
+!0 = !{i32 2, !"Dwarf Version", i32 4}
+!1 = !{i32 2, !"Debug Info Version", i32 3}
+!2 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !5, globals: !4, imports: !4)
+!3 = !DIFile(filename: "fortsubrange.f90", directory: "/dir")
+!4 = !{}
+!5 = !{!6, !16}
+!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 32, align: 32, elements: !8, dataLocation: !10)
+!7 = !DIBasicType(name: "integer", size: 32, align: 32, encoding: DW_ATE_signed)
+!8 = !{!9}
+!9 = !DISubrange(count: 19, lowerBound: 2)
+!10 = distinct !DILocalVariable(scope: !11, file: !3, type: !15, flags: DIFlagArtificial)
+!11 = !DILexicalBlock(scope: !12, file: !3, line: 1, column: 1)
+!12 = distinct !DISubprogram(name: "main", scope: !2, file: !3, line: 1, type: !13, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !2)
+!13 = !DISubroutineType(cc: DW_CC_program, types: !14)
+!14 = !{null}
+!15 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 32, align: 32)
+!16 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 32, align: 32, elements: !8, dataLocation: !DIExpression(DW_OP_constu, 3412))

diff  --git a/llvm/test/DebugInfo/dwarfdump-dataLocationExp.ll b/llvm/test/DebugInfo/dwarfdump-dataLocationExp.ll
new file mode 100644
index 000000000000..adb7816b1b04
--- /dev/null
+++ b/llvm/test/DebugInfo/dwarfdump-dataLocationExp.ll
@@ -0,0 +1,66 @@
+;; This test checks whether DW_AT_data_location attribute
+;; accepts DIExpression.
+
+; RUN: llc mtriple=x86_64-unknown-linux-gnu %s -filetype=obj -o %t.o
+; RUN: llvm-dwarfdump  %t.o | FileCheck %s
+
+;; Test whether DW_AT_data_location is generated.
+; CHECK-LABEL:  DW_TAG_array_type
+
+; CHECK:        DW_AT_data_location (DW_OP_constu 0x1a85)
+; CHECK:        DW_TAG_subrange_type
+
+;; Test case is hand written with the help of below testcase
+;;------------------------------
+;;program main
+;;integer, allocatable :: arr(:)
+;;allocate(arr(2:20))
+;;arr(2)=99
+;;print *, arr
+;;end program main
+;;------------------------------
+
+; ModuleID = 'fortsubrange.ll'
+source_filename = "fortsubrange.ll"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @MAIN_() !dbg !5 {
+L.entry:
+  %.Z0640_333 = alloca i32*, align 8
+  %"arr$sd1_349" = alloca [16 x i64], align 8
+  call void @llvm.dbg.declare(metadata [16 x i64]* %"arr$sd1_349", metadata !8, metadata !DIExpression()), !dbg !14
+  call void @llvm.dbg.declare(metadata i32** %.Z0640_333, metadata !15, metadata !DIExpression()), !dbg !14
+  ret void, !dbg !17
+}
+
+; Function Attrs: nounwind readnone speculatable willreturn
+declare void @llvm.dbg.declare(metadata, metadata, metadata)
+
+; Function Attrs: nounwind readnone speculatable willreturn
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+!llvm.module.flags = !{!0, !1}
+!llvm.dbg.cu = !{!2}
+
+!0 = !{i32 2, !"Dwarf Version", i32 4}
+!1 = !{i32 2, !"Debug Info Version", i32 3}
+!2 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !4, globals: !4, imports: !4)
+!3 = !DIFile(filename: "fortsubrange.f90", directory: "/dir")
+!4 = !{}
+!5 = distinct !DISubprogram(name: "main", scope: !2, file: !3, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !2)
+!6 = !DISubroutineType(cc: DW_CC_program, types: !7)
+!7 = !{null}
+!8 = !DILocalVariable(name: "arr", scope: !9, file: !3, type: !10)
+!9 = !DILexicalBlock(scope: !5, file: !3, line: 1, column: 1)
+;; We intend to use DW_OP_push_object_address, since that is not available yet,
+;; we are using meaning less expression
+;;!10 = !DICompositeType(tag: DW_TAG_array_type, baseType: !11, size: 32, align: 32, elements: !12, dataLocation: !DIExpression(DW_OP_push_object_address, DW_OP_deref))
+!10 = !DICompositeType(tag: DW_TAG_array_type, baseType: !11, size: 32, align: 32, elements: !12, dataLocation: !DIExpression(DW_OP_constu, 6789))
+!11 = !DIBasicType(name: "integer", size: 32, align: 32, encoding: DW_ATE_signed)
+!12 = !{!13}
+!13 = !DISubrange(count: 19, lowerBound: 2)
+!14 = !DILocation(line: 0, scope: !9)
+!15 = distinct !DILocalVariable(scope: !9, file: !3, type: !16, flags: DIFlagArtificial)
+!16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 32, align: 32)
+!17 = !DILocation(line: 6, column: 1, scope: !9)

diff  --git a/llvm/test/DebugInfo/dwarfdump-dataLocationVar.ll b/llvm/test/DebugInfo/dwarfdump-dataLocationVar.ll
new file mode 100644
index 000000000000..2602e7a7a1c0
--- /dev/null
+++ b/llvm/test/DebugInfo/dwarfdump-dataLocationVar.ll
@@ -0,0 +1,65 @@
+;; This test checks whether DW_AT_data_location attribute
+;; accepts DIVariable
+
+; RUN: llc -mtriple=x86_64-unknown-linux-gnu %s -filetype=obj -o %t.o
+; RUN: llvm-dwarfdump  %t.o | FileCheck %s
+
+;; Test whether DW_AT_data_location is generated.
+; CHECK: [[LOCDIE:0x.+]]:       DW_TAG_variable
+; CHECK:                          DW_AT_artificial    (true)
+; CHECK:  DW_TAG_variable
+; CHECK:    DW_AT_name  ("arr")
+; CHECK:  DW_TAG_array_type
+; CHECK-NEXT:    DW_AT_data_location     ([[LOCDIE]])
+
+;; Test case is hand written with the help of below testcase
+;;------------------------------
+;;program main
+;;integer, allocatable :: arr(:)
+;;allocate(arr(2:20))
+;;arr(2)=99
+;;print *, arr
+;;end program main
+;;------------------------------
+
+; ModuleID = 'fortsubrange.ll'
+source_filename = "fortsubrange.ll"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @MAIN_() !dbg !5 {
+L.entry:
+  %.Z0640_333 = alloca i32*, align 8
+  %"arr$sd1_349" = alloca [16 x i64], align 8
+  call void @llvm.dbg.declare(metadata [16 x i64]* %"arr$sd1_349", metadata !8, metadata !DIExpression()), !dbg !16
+  call void @llvm.dbg.declare(metadata i32** %.Z0640_333, metadata !14, metadata !DIExpression()), !dbg !16
+  ret void, !dbg !17
+}
+
+; Function Attrs: nounwind readnone speculatable willreturn
+declare void @llvm.dbg.declare(metadata, metadata, metadata)
+
+; Function Attrs: nounwind readnone speculatable willreturn
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+!llvm.module.flags = !{!0, !1}
+!llvm.dbg.cu = !{!2}
+
+!0 = !{i32 2, !"Dwarf Version", i32 4}
+!1 = !{i32 2, !"Debug Info Version", i32 3}
+!2 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !4, globals: !4, imports: !4)
+!3 = !DIFile(filename: "fortsubrange.f90", directory: "/dir")
+!4 = !{}
+!5 = distinct !DISubprogram(name: "main", scope: !2, file: !3, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !2)
+!6 = !DISubroutineType(cc: DW_CC_program, types: !7)
+!7 = !{null}
+!8 = !DILocalVariable(name: "arr", scope: !9, file: !3, type: !10)
+!9 = !DILexicalBlock(scope: !5, file: !3, line: 1, column: 1)
+!10 = !DICompositeType(tag: DW_TAG_array_type, baseType: !11, size: 32, align: 32, elements: !12, dataLocation: !14)
+!11 = !DIBasicType(name: "integer", size: 32, align: 32, encoding: DW_ATE_signed)
+!12 = !{!13}
+!13 = !DISubrange(count: 19, lowerBound: 2)
+!14 = distinct !DILocalVariable(scope: !9, file: !3, type: !15, flags: DIFlagArtificial)
+!15 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 32, align: 32)
+!16 = !DILocation(line: 0, scope: !9)
+!17 = !DILocation(line: 6, column: 1, scope: !9)

diff  --git a/llvm/test/Verifier/array_dataLocation.ll b/llvm/test/Verifier/array_dataLocation.ll
new file mode 100644
index 000000000000..953dd0f611a0
--- /dev/null
+++ b/llvm/test/Verifier/array_dataLocation.ll
@@ -0,0 +1,6 @@
+; RUN: not llvm-as -disable-output <%s 2>&1 | FileCheck %s
+
+!named = !{!0}
+!0 = !DICompositeType(tag: DW_TAG_structure_type, name: "A", size: 64, dataLocation: !DIExpression(DW_OP_constu, 6789))
+
+; CHECK:  dataLocation can only appear in array type

diff  --git a/llvm/unittests/IR/DebugTypeODRUniquingTest.cpp b/llvm/unittests/IR/DebugTypeODRUniquingTest.cpp
index 8031bf756aef..a809b52f2723 100644
--- a/llvm/unittests/IR/DebugTypeODRUniquingTest.cpp
+++ b/llvm/unittests/IR/DebugTypeODRUniquingTest.cpp
@@ -29,7 +29,8 @@ TEST(DebugTypeODRUniquingTest, getODRType) {
   // 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));
+      nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr, nullptr,
+      nullptr));
 
   // Enable the mapping.  There still shouldn't be a type.
   Context.enableDebugTypeODRUniquing();
@@ -38,7 +39,8 @@ TEST(DebugTypeODRUniquingTest, getODRType) {
   // 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);
+      nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr, nullptr,
+      nullptr);
   EXPECT_EQ(UUID.getString(), CT.getIdentifier());
 
   // Check that we get it back, even if we change a field.
@@ -46,12 +48,12 @@ TEST(DebugTypeODRUniquingTest, getODRType) {
   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));
+  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, 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, nullptr));
 
   // Check that it's discarded with the type map.
   Context.disableDebugTypeODRUniquing();
@@ -70,32 +72,35 @@ TEST(DebugTypeODRUniquingTest, buildODRType) {
   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);
+      nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, 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));
+                     Context, UUID, dwarf::DW_TAG_structure_type, nullptr,
+                     nullptr, 0, nullptr, nullptr, 0, 0, 0, DINode::FlagFwdDecl,
+                     nullptr, 0, nullptr, 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));
+                     nullptr, 0, nullptr, 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));
+                     Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr,
+                     0, nullptr, nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr,
+                     0, nullptr, 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, nullptr, nullptr));
   EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
 }
 
@@ -107,7 +112,7 @@ TEST(DebugTypeODRUniquingTest, buildODRTypeFields) {
   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, nullptr);
+      DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, nullptr, nullptr);
 
 // Create macros for running through all the fields except Identifier and Flags.
 #define FOR_EACH_MDFIELD()                                                     \
@@ -136,11 +141,11 @@ TEST(DebugTypeODRUniquingTest, buildODRTypeFields) {
 #undef DO_FOR_FIELD
 
   // Replace all the fields with new values that are distinct from each other.
-  EXPECT_EQ(&CT,
-            DICompositeType::buildODRType(
-                Context, UUID, Tag, Name, File, Line, Scope, BaseType,
-                SizeInBits, AlignInBits, OffsetInBits, DINode::FlagArtificial,
-                Elements, RuntimeLang, VTableHolder, TemplateParams, nullptr));
+  EXPECT_EQ(&CT, DICompositeType::buildODRType(
+                     Context, UUID, Tag, Name, File, Line, Scope, BaseType,
+                     SizeInBits, AlignInBits, OffsetInBits,
+                     DINode::FlagArtificial, Elements, RuntimeLang,
+                     VTableHolder, TemplateParams, nullptr, nullptr));
 
   // Confirm that all the right fields got updated.
 #define DO_FOR_FIELD(X) EXPECT_EQ(X, CT.getRaw##X());

diff  --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index 39cd0edca6fc..d785e469e728 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -1623,6 +1623,69 @@ TEST_F(DICompositeTypeTest, variant_part) {
   EXPECT_EQ(N->getDiscriminator(), Discriminator);
 }
 
+TEST_F(DICompositeTypeTest, dynamicArray) {
+  unsigned Tag = dwarf::DW_TAG_array_type;
+  StringRef Name = "some name";
+  DIFile *File = getFile();
+  unsigned Line = 1;
+  DILocalScope *Scope = getSubprogram();
+  DIType *BaseType = getCompositeType();
+  uint64_t SizeInBits = 32;
+  uint32_t AlignInBits = 32;
+  uint64_t OffsetInBits = 4;
+  DINode::DIFlags Flags = static_cast<DINode::DIFlags>(3);
+  unsigned RuntimeLang = 6;
+  StringRef Identifier = "some id";
+  DIType *Type = getDerivedType();
+  Metadata *DlVar1 = DILocalVariable::get(Context, Scope, "dl_var1", File, 8,
+                                       Type, 2, Flags, 8);
+  Metadata *DlVar2 = DILocalVariable::get(Context, Scope, "dl_var2", File, 8,
+                                       Type, 2, Flags, 8);
+  uint64_t Elements1[] = {dwarf::DW_OP_push_object_address, dwarf::DW_OP_deref};
+  Metadata *DataLocation1 = DIExpression::get(Context, Elements1);
+
+  uint64_t Elements2[] = {dwarf::DW_OP_constu, 0};
+  Metadata *DataLocation2 = DIExpression::get(Context, Elements2);
+
+  auto *N1 = DICompositeType::get(
+      Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
+      OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
+      nullptr, DlVar1);
+
+  auto *Same1 = DICompositeType::get(
+      Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
+      OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
+      nullptr, DlVar1);
+
+  auto *Other1 = DICompositeType::get(
+      Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
+      OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
+      nullptr, DlVar2);
+
+  EXPECT_EQ(N1, Same1);
+  EXPECT_NE(Same1, Other1);
+  EXPECT_EQ(N1->getDataLocation(), DlVar1);
+
+  auto *N2 = DICompositeType::get(
+      Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
+      OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
+      nullptr, DataLocation1);
+
+  auto *Same2 = DICompositeType::get(
+      Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
+      OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
+      nullptr, DataLocation1);
+
+  auto *Other2 = DICompositeType::get(
+      Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
+      OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
+      nullptr, DataLocation2);
+
+  EXPECT_EQ(N2, Same2);
+  EXPECT_NE(Same2, Other2);
+  EXPECT_EQ(N2->getDataLocationExp(), DataLocation1);
+}
+
 typedef MetadataTest DISubroutineTypeTest;
 
 TEST_F(DISubroutineTypeTest, get) {


        


More information about the llvm-commits mailing list