diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -4906,7 +4906,9 @@ and pointee is called association. The optional ``associated`` is a DIExpression that describes whether the pointer array is currently associated. The optional ``allocated`` is a DIExpression that describes whether the -allocatable array is currently allocated. +allocatable array is currently allocated. The optional ``rank`` is a +DIExpression that describes the rank (number of dimensions) of fortran assumed +rank array (rank is known at runtime). For ``DW_TAG_enumeration_type``, the ``elements:`` should be :ref:`enumerator descriptors `, each representing the definition of an enumeration diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -1026,14 +1026,14 @@ DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder, DITemplateParameterArray TemplateParams, StringRef Identifier, DIDerivedType *Discriminator, Metadata *DataLocation, - Metadata *Associated, Metadata *Allocated, 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, Associated, Allocated, Storage, ShouldCreate); + Metadata *Associated, Metadata *Allocated, Metadata *Rank, + 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, + Associated, Allocated, Rank, Storage, ShouldCreate); } static DICompositeType * getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, @@ -1042,16 +1042,17 @@ DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams, MDString *Identifier, Metadata *Discriminator, Metadata *DataLocation, - Metadata *Associated, Metadata *Allocated, StorageType Storage, - bool ShouldCreate = true); + Metadata *Associated, Metadata *Allocated, Metadata *Rank, + 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(), getDiscriminator(), - getRawDataLocation(), getRawAssociated(), getRawAllocated()); + return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), + getScope(), getBaseType(), getSizeInBits(), + getAlignInBits(), getOffsetInBits(), getFlags(), + getElements(), getRuntimeLang(), getVTableHolder(), + getTemplateParams(), getIdentifier(), + getDiscriminator(), getRawDataLocation(), + getRawAssociated(), getRawAllocated(), getRawRank()); } public: @@ -1064,10 +1065,10 @@ DITemplateParameterArray TemplateParams = nullptr, StringRef Identifier = "", DIDerivedType *Discriminator = nullptr, Metadata *DataLocation = nullptr, Metadata *Associated = nullptr, - Metadata *Allocated = nullptr), + Metadata *Allocated = nullptr, Metadata *Rank = nullptr), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, - Identifier, Discriminator, DataLocation, Associated, Allocated)) + Identifier, Discriminator, DataLocation, Associated, Allocated, Rank)) DEFINE_MDNODE_GET( DICompositeType, (unsigned Tag, MDString *Name, Metadata *File, unsigned Line, @@ -1076,10 +1077,11 @@ Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams = nullptr, MDString *Identifier = nullptr, Metadata *Discriminator = nullptr, Metadata *DataLocation = nullptr, - Metadata *Associated = nullptr, Metadata *Allocated = nullptr), + Metadata *Associated = nullptr, Metadata *Allocated = nullptr, + Metadata *Rank = nullptr), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, - Identifier, Discriminator, DataLocation, Associated, Allocated)) + Identifier, Discriminator, DataLocation, Associated, Allocated, Rank)) TempDICompositeType clone() const { return cloneImpl(); } @@ -1097,7 +1099,8 @@ uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator, - Metadata *DataLocation, Metadata *Associated, Metadata *Allocated); + Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, + Metadata *Rank); static DICompositeType *getODRTypeIfExists(LLVMContext &Context, MDString &Identifier); @@ -1110,13 +1113,15 @@ /// /// If not \a LLVMContext::isODRUniquingDebugTypes(), this function returns /// nullptr. - static DICompositeType *buildODRType( - LLVMContext &Context, MDString &Identifier, 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, Metadata *Discriminator, - Metadata *DataLocation, Metadata *Associated, Metadata *Allocated); + static DICompositeType * + buildODRType(LLVMContext &Context, MDString &Identifier, 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, Metadata *Discriminator, + Metadata *DataLocation, Metadata *Associated, + Metadata *Allocated, Metadata *Rank); DIType *getBaseType() const { return cast_or_null(getRawBaseType()); } DINodeArray getElements() const { @@ -1159,6 +1164,15 @@ DIExpression *getAllocatedExp() const { return dyn_cast_or_null(getRawAllocated()); } + Metadata *getRawRank() const { return getOperand(12); } + ConstantInt *getRankConst() const { + if (auto *MD = dyn_cast_or_null(getRawRank())) + return dyn_cast_or_null(MD->getValue()); + return nullptr; + } + DIExpression *getRankExp() const { + return dyn_cast_or_null(getRawRank()); + } /// Replace operands. /// diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -4712,18 +4712,26 @@ OPTIONAL(discriminator, MDField, ); \ OPTIONAL(dataLocation, MDField, ); \ OPTIONAL(associated, MDField, ); \ - OPTIONAL(allocated, MDField, ); + OPTIONAL(allocated, MDField, ); \ + OPTIONAL(rank, MDSignedOrMDField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS + Metadata *Rank = nullptr; + if (rank.isMDSignedField()) + Rank = ConstantAsMetadata::get(ConstantInt::getSigned( + Type::getInt64Ty(Context), rank.getMDSignedValue())); + else if (rank.isMDField()) + Rank = rank.getMDFieldValue(); + // If this has an identifier try to build an ODR type. if (identifier.Val) 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, dataLocation.Val, associated.Val, - allocated.Val)) { + discriminator.Val, dataLocation.Val, associated.Val, allocated.Val, + Rank)) { Result = CT; return false; } @@ -4735,7 +4743,8 @@ (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, dataLocation.Val, associated.Val, allocated.Val)); + discriminator.Val, dataLocation.Val, associated.Val, allocated.Val, + Rank)); return false; } diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -1362,7 +1362,7 @@ break; } case bitc::METADATA_COMPOSITE_TYPE: { - if (Record.size() < 16 || Record.size() > 20) + if (Record.size() < 16 || Record.size() > 21) return error("Invalid record"); // If we have a UUID and this is not a forward declaration, lookup the @@ -1389,6 +1389,7 @@ Metadata *DataLocation = nullptr; Metadata *Associated = nullptr; Metadata *Allocated = nullptr; + Metadata *Rank = 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 @@ -1417,6 +1418,9 @@ Associated = getMDOrNull(Record[18]); Allocated = getMDOrNull(Record[19]); } + if (Record.size() > 20) { + Rank = getMDOrNull(Record[20]); + } } DICompositeType *CT = nullptr; if (Identifier) @@ -1424,7 +1428,7 @@ Context, *Identifier, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, Discriminator, DataLocation, Associated, - Allocated); + Allocated, Rank); // Create a node if we didn't get a lazy ODR type. if (!CT) @@ -1433,7 +1437,7 @@ SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier, Discriminator, DataLocation, Associated, - Allocated)); + Allocated, Rank)); if (!IsNotUsedInTypeRef && Identifier) MetadataList.addTypeRef(*Identifier, *cast(CT)); diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1662,6 +1662,7 @@ Record.push_back(VE.getMetadataOrNullID(N->getRawDataLocation())); Record.push_back(VE.getMetadataOrNullID(N->getRawAssociated())); Record.push_back(VE.getMetadataOrNullID(N->getRawAllocated())); + Record.push_back(VE.getMetadataOrNullID(N->getRawRank())); Stream.EmitRecord(bitc::METADATA_COMPOSITE_TYPE, Record, Abbrev); Record.clear(); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1472,6 +1472,17 @@ addBlock(Buffer, dwarf::DW_AT_allocated, DwarfExpr.finalize()); } + if (auto *RankConst = CTy->getRankConst()) { + addSInt(Buffer, dwarf::DW_AT_rank, dwarf::DW_FORM_sdata, + RankConst->getSExtValue()); + } else if (auto *RankExpr = CTy->getRankExp()) { + DIELoc *Loc = new (DIEValueAllocator) DIELoc; + DIEDwarfExpression DwarfExpr(*Asm, getCU(), *Loc); + DwarfExpr.setMemoryLocationKind(); + DwarfExpr.addExpression(RankExpr); + addBlock(Buffer, dwarf::DW_AT_rank, DwarfExpr.finalize()); + } + // Emit the element type. addType(Buffer, CTy->getBaseType()); diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -1991,6 +1991,11 @@ Printer.printMetadata("dataLocation", N->getRawDataLocation()); Printer.printMetadata("associated", N->getRawAssociated()); Printer.printMetadata("allocated", N->getRawAllocated()); + if (auto *RankConst = N->getRankConst()) + Printer.printInt("rank", RankConst->getSExtValue(), + /* ShouldSkipZero */ false); + else + Printer.printMetadata("rank", N->getRawRank(), /*ShouldSkipNull */ true); Out << ")"; } diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -508,18 +508,19 @@ Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams, MDString *Identifier, Metadata *Discriminator, Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, - StorageType Storage, bool ShouldCreate) { + Metadata *Rank, 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, DataLocation, Associated, Allocated)); + DEFINE_GETIMPL_LOOKUP( + DICompositeType, + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, + OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, + Identifier, Discriminator, DataLocation, Associated, Allocated, Rank)); Metadata *Ops[] = {File, Scope, Name, BaseType, Elements, VTableHolder, TemplateParams, Identifier, - Discriminator, DataLocation, Associated, Allocated}; + Discriminator, DataLocation, Associated, Allocated, + Rank}; DEFINE_GETIMPL_STORE(DICompositeType, (Tag, Line, RuntimeLang, SizeInBits, AlignInBits, OffsetInBits, Flags), Ops); @@ -531,7 +532,8 @@ uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator, - Metadata *DataLocation, Metadata *Associated, Metadata *Allocated) { + Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, + Metadata *Rank) { assert(!Identifier.getString().empty() && "Expected valid identifier"); if (!Context.isODRUniquingDebugTypes()) return nullptr; @@ -541,7 +543,7 @@ Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, &Identifier, Discriminator, - DataLocation, Associated, Allocated); + DataLocation, Associated, Allocated, Rank); // Only mutate CT if it's a forward declaration and the new operands aren't. assert(CT->getRawIdentifier() == &Identifier && "Wrong ODR identifier?"); @@ -553,7 +555,8 @@ Flags); Metadata *Ops[] = {File, Scope, Name, BaseType, Elements, VTableHolder, TemplateParams, &Identifier, - Discriminator, DataLocation, Associated, Allocated}; + Discriminator, DataLocation, Associated, Allocated, + Rank}; assert((std::end(Ops) - std::begin(Ops)) == (int)CT->getNumOperands() && "Mismatched number of operands"); for (unsigned I = 0, E = CT->getNumOperands(); I != E; ++I) @@ -568,7 +571,8 @@ uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator, - Metadata *DataLocation, Metadata *Associated, Metadata *Allocated) { + Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, + Metadata *Rank) { assert(!Identifier.getString().empty() && "Expected valid identifier"); if (!Context.isODRUniquingDebugTypes()) return nullptr; @@ -578,7 +582,7 @@ Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, &Identifier, Discriminator, DataLocation, Associated, - Allocated); + Allocated, Rank); return CT; } diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -538,6 +538,7 @@ Metadata *DataLocation; Metadata *Associated; Metadata *Allocated; + Metadata *Rank; MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, @@ -546,14 +547,14 @@ Metadata *VTableHolder, Metadata *TemplateParams, MDString *Identifier, Metadata *Discriminator, Metadata *DataLocation, Metadata *Associated, - Metadata *Allocated) + Metadata *Allocated, Metadata *Rank) : 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), DataLocation(DataLocation), - Associated(Associated), Allocated(Allocated) {} + Associated(Associated), Allocated(Allocated), Rank(Rank) {} MDNodeKeyImpl(const DICompositeType *N) : Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()), Line(N->getLine()), Scope(N->getRawScope()), @@ -565,7 +566,8 @@ Identifier(N->getRawIdentifier()), Discriminator(N->getRawDiscriminator()), DataLocation(N->getRawDataLocation()), - Associated(N->getRawAssociated()), Allocated(N->getRawAllocated()) {} + Associated(N->getRawAssociated()), Allocated(N->getRawAllocated()), + Rank(N->getRawRank()) {} bool isKeyOf(const DICompositeType *RHS) const { return Tag == RHS->getTag() && Name == RHS->getRawName() && @@ -582,7 +584,7 @@ Discriminator == RHS->getRawDiscriminator() && DataLocation == RHS->getRawDataLocation() && Associated == RHS->getRawAssociated() && - Allocated == RHS->getRawAllocated(); + Allocated == RHS->getRawAllocated() && Rank == RHS->getRawRank(); } unsigned getHashValue() const { diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -1056,6 +1056,11 @@ AssertDI(N.getTag() == dwarf::DW_TAG_array_type, "allocated can only appear in array type"); } + + if (N.getRawRank()) { + AssertDI(N.getTag() == dwarf::DW_TAG_array_type, + "rank can only appear in array type"); + } } void Verifier::visitDISubroutineType(const DISubroutineType &N) { diff --git a/llvm/test/Bitcode/rankConst.ll b/llvm/test/Bitcode/rankConst.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Bitcode/rankConst.ll @@ -0,0 +1,41 @@ +;; This test checks rank field of DICompositeType + +; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s + +;; Test whether rank is generated. +; CHECK: !DICompositeType(tag: DW_TAG_array_type, baseType: !{{[0-9]+}}, size: 32, align: 32, elements: !{{[0-9]+}}, dataLocation: !{{[0-9]+}}, rank: 7) + +; ModuleID = 'rank.f90' +source_filename = "/dir/rank.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: "arank.f90", directory: "/dir") +!4 = !{} +!5 = !{!6} +!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 32, align: 32, elements: !8, dataLocation: !16, rank: 7) +!7 = !DIBasicType(name: "real", size: 32, align: 32, encoding: DW_ATE_float) +!8 = !{!9, !10, !11, !12, !13, !14, !15} +!9 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 80, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 120, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 112, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!10 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 128, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 168, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 160, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!11 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 176, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 216, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 208, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!12 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 224, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 264, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 256, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!13 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 272, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 312, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 304, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!14 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 320, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 360, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 352, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!15 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 368, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 408, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 400, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!16 = distinct !DILocalVariable(scope: !17, file: !3, type: !24, flags: DIFlagArtificial) +!17 = distinct !DISubprogram(name: "sub1", scope: !2, file: !3, line: 1, type: !18, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2) +!18 = !DISubroutineType(types: !19) +!19 = !{null, !20, !25} +!20 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 32, align: 32, elements: !21) +!21 = !{!22} +!22 = !DISubrange(lowerBound: 1, upperBound: !23) +!23 = distinct !DILocalVariable(scope: !17, file: !3, type: !24, flags: DIFlagArtificial) +!24 = !DIBasicType(name: "integer*8", size: 64, align: 64, encoding: DW_ATE_signed) +!25 = !DICompositeType(tag: DW_TAG_array_type, baseType: !24, size: 1024, align: 64, elements: !26) +!26 = !{!27} +!27 = !DISubrange(lowerBound: 1, upperBound: 16) diff --git a/llvm/test/Bitcode/rankExp.ll b/llvm/test/Bitcode/rankExp.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Bitcode/rankExp.ll @@ -0,0 +1,41 @@ +;; This test checks rank field of DICompositeType + +; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s + +;; Test whether rank is generated. +; CHECK: !DICompositeType(tag: DW_TAG_array_type, baseType: !{{[0-9]+}}, size: 32, align: 32, elements: !{{[0-9]+}}, dataLocation: !{{[0-9]+}}, rank: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 8, DW_OP_deref)) + +; ModuleID = 'rank.f90' +source_filename = "/dir/rank.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: "arank.f90", directory: "/dir") +!4 = !{} +!5 = !{!6} +!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 32, align: 32, elements: !8, dataLocation: !16, rank: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 8, DW_OP_deref)) +!7 = !DIBasicType(name: "real", size: 32, align: 32, encoding: DW_ATE_float) +!8 = !{!9, !10, !11, !12, !13, !14, !15} +!9 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 80, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 120, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 112, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!10 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 128, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 168, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 160, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!11 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 176, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 216, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 208, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!12 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 224, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 264, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 256, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!13 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 272, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 312, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 304, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!14 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 320, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 360, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 352, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!15 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 368, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 408, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 400, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!16 = distinct !DILocalVariable(scope: !17, file: !3, type: !24, flags: DIFlagArtificial) +!17 = distinct !DISubprogram(name: "sub1", scope: !2, file: !3, line: 1, type: !18, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2) +!18 = !DISubroutineType(types: !19) +!19 = !{null, !20, !25} +!20 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 32, align: 32, elements: !21) +!21 = !{!22} +!22 = !DISubrange(lowerBound: 1, upperBound: !23) +!23 = distinct !DILocalVariable(scope: !17, file: !3, type: !24, flags: DIFlagArtificial) +!24 = !DIBasicType(name: "integer*8", size: 64, align: 64, encoding: DW_ATE_signed) +!25 = !DICompositeType(tag: DW_TAG_array_type, baseType: !24, size: 1024, align: 64, elements: !26) +!26 = !{!27} +!27 = !DISubrange(lowerBound: 1, upperBound: 16) diff --git a/llvm/test/DebugInfo/X86/dwarfdump-rankConst.ll b/llvm/test/DebugInfo/X86/dwarfdump-rankConst.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/X86/dwarfdump-rankConst.ll @@ -0,0 +1,68 @@ +;; This test checks whether DW_AT_rank attribute accepts DIExpression. + +; RUN: llc %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_rank (7) + +;; Test case is hand written with the help of below testcase +;;------------------------------ +;;subroutine sub(arank) +;; real :: arank(..) +;; print *, RANK(arank) +;;end +;;------------------------------ + +; ModuleID = 'dwarfdump-rank.ll' +source_filename = "dwarfdump-rank.ll" + +define void @sub_(i64* noalias %arank, i64* noalias %"arank$sd") !dbg !5 { +L.entry: + call void @llvm.dbg.value(metadata i64* %arank, metadata !17, metadata !DIExpression()), !dbg !18 + call void @llvm.dbg.declare(metadata i64* %"arank$sd", metadata !19, metadata !DIExpression()), !dbg !18 + call void @llvm.dbg.declare(metadata i64* %"arank$sd", metadata !29, metadata !DIExpression()), !dbg !18 + ret void, !dbg !18 +} + +; 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: "rank.f90", directory: "/dir") +!4 = !{} +!5 = distinct !DISubprogram(name: "sub", scope: !2, file: !3, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2) +!6 = !DISubroutineType(types: !7) +!7 = !{null, !8, !14} +!8 = !DICompositeType(tag: DW_TAG_array_type, baseType: !9, size: 32, align: 32, elements: !10) +!9 = !DIBasicType(name: "real", size: 32, align: 32, encoding: DW_ATE_float) +!10 = !{!11} +!11 = !DISubrange(lowerBound: 1, upperBound: !12) +!12 = distinct !DILocalVariable(scope: !5, file: !3, type: !13, flags: DIFlagArtificial) +!13 = !DIBasicType(name: "integer*8", size: 64, align: 64, encoding: DW_ATE_signed) +!14 = !DICompositeType(tag: DW_TAG_array_type, baseType: !13, size: 1024, align: 64, elements: !15) +!15 = !{!16} +!16 = !DISubrange(lowerBound: 1, upperBound: 16) +!17 = distinct !DILocalVariable(scope: !5, file: !3, type: !13, flags: DIFlagArtificial) +!18 = !DILocation(line: 0, scope: !5) +!19 = !DILocalVariable(name: "arank", arg: 1, scope: !5, file: !3, line: 1, type: !20) +!20 = !DICompositeType(tag: DW_TAG_array_type, baseType: !9, size: 32, align: 32, elements: !21, dataLocation: !17, rank: 7) +!21 = !{!22, !23, !24, !25, !26, !27, !28} +!22 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 80, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 120, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 112, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!23 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 128, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 168, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 160, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!24 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 176, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 216, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 208, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!25 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 224, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 264, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 256, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!26 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 272, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 312, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 304, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!27 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 320, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 360, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 352, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!28 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 368, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 408, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 400, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!29 = !DILocalVariable(arg: 2, scope: !5, file: !3, line: 1, type: !14, flags: DIFlagArtificial) diff --git a/llvm/test/DebugInfo/X86/dwarfdump-rankExp.ll b/llvm/test/DebugInfo/X86/dwarfdump-rankExp.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/X86/dwarfdump-rankExp.ll @@ -0,0 +1,68 @@ +;; This test checks whether DW_AT_rank attribute accepts DIExpression. + +; RUN: llc %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_rank (DW_OP_push_object_address, DW_OP_plus_uconst 0x8, DW_OP_deref) + +;; Test case is hand written with the help of below testcase +;;------------------------------ +;;subroutine sub(arank) +;; real :: arank(..) +;; print *, RANK(arank) +;;end +;;------------------------------ + +; ModuleID = 'dwarfdump-rank.ll' +source_filename = "dwarfdump-rank.ll" + +define void @sub_(i64* noalias %arank, i64* noalias %"arank$sd") !dbg !5 { +L.entry: + call void @llvm.dbg.value(metadata i64* %arank, metadata !17, metadata !DIExpression()), !dbg !18 + call void @llvm.dbg.declare(metadata i64* %"arank$sd", metadata !19, metadata !DIExpression()), !dbg !18 + call void @llvm.dbg.declare(metadata i64* %"arank$sd", metadata !29, metadata !DIExpression()), !dbg !18 + ret void, !dbg !18 +} + +; 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: "rank.f90", directory: "/dir") +!4 = !{} +!5 = distinct !DISubprogram(name: "sub", scope: !2, file: !3, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2) +!6 = !DISubroutineType(types: !7) +!7 = !{null, !8, !14} +!8 = !DICompositeType(tag: DW_TAG_array_type, baseType: !9, size: 32, align: 32, elements: !10) +!9 = !DIBasicType(name: "real", size: 32, align: 32, encoding: DW_ATE_float) +!10 = !{!11} +!11 = !DISubrange(lowerBound: 1, upperBound: !12) +!12 = distinct !DILocalVariable(scope: !5, file: !3, type: !13, flags: DIFlagArtificial) +!13 = !DIBasicType(name: "integer*8", size: 64, align: 64, encoding: DW_ATE_signed) +!14 = !DICompositeType(tag: DW_TAG_array_type, baseType: !13, size: 1024, align: 64, elements: !15) +!15 = !{!16} +!16 = !DISubrange(lowerBound: 1, upperBound: 16) +!17 = distinct !DILocalVariable(scope: !5, file: !3, type: !13, flags: DIFlagArtificial) +!18 = !DILocation(line: 0, scope: !5) +!19 = !DILocalVariable(name: "arank", arg: 1, scope: !5, file: !3, line: 1, type: !20) +!20 = !DICompositeType(tag: DW_TAG_array_type, baseType: !9, size: 32, align: 32, elements: !21, dataLocation: !17, rank: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 8, DW_OP_deref)) +!21 = !{!22, !23, !24, !25, !26, !27, !28} +!22 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 80, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 120, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 112, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!23 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 128, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 168, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 160, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!24 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 176, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 216, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 208, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!25 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 224, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 264, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 256, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!26 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 272, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 312, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 304, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!27 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 320, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 360, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 352, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!28 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 368, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 408, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 400, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul)) +!29 = !DILocalVariable(arg: 2, scope: !5, file: !3, line: 1, type: !14, flags: DIFlagArtificial) diff --git a/llvm/test/Verifier/array_rank.ll b/llvm/test/Verifier/array_rank.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Verifier/array_rank.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, rank: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 8, DW_OP_deref)) + +; CHECK: rank can only appear in array type diff --git a/llvm/unittests/IR/DebugTypeODRUniquingTest.cpp b/llvm/unittests/IR/DebugTypeODRUniquingTest.cpp --- a/llvm/unittests/IR/DebugTypeODRUniquingTest.cpp +++ b/llvm/unittests/IR/DebugTypeODRUniquingTest.cpp @@ -30,7 +30,7 @@ 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, nullptr, nullptr)); + nullptr, nullptr, nullptr, nullptr)); // Enable the mapping. There still shouldn't be a type. Context.enableDebugTypeODRUniquing(); @@ -40,20 +40,21 @@ 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, nullptr, nullptr); + nullptr, nullptr, nullptr, nullptr); EXPECT_EQ(UUID.getString(), CT.getIdentifier()); // Check that we get it back, even if we change a field. EXPECT_EQ(&CT, DICompositeType::getODRTypeIfExists(Context, UUID)); - 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, nullptr)); + 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, 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, nullptr, nullptr)); + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr)); // Check that it's discarded with the type map. Context.disableDebugTypeODRUniquing(); @@ -73,7 +74,7 @@ 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, nullptr, nullptr); + nullptr, nullptr, nullptr, nullptr, nullptr); EXPECT_EQ(&CT, DICompositeType::getODRTypeIfExists(Context, UUID)); EXPECT_EQ(dwarf::DW_TAG_class_type, CT.getTag()); @@ -82,7 +83,7 @@ DICompositeType::buildODRType( Context, UUID, dwarf::DW_TAG_structure_type, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr)); + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr)); EXPECT_EQ(dwarf::DW_TAG_class_type, CT.getTag()); // Update with a definition. This time we should see a change. @@ -90,19 +91,21 @@ 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, nullptr, nullptr)); + nullptr, nullptr, nullptr, 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, nullptr, nullptr, nullptr)); + 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, 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)); + 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()); } @@ -115,7 +118,7 @@ auto &CT = *DICompositeType::buildODRType( Context, UUID, 0, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr); + nullptr, nullptr, nullptr); // Create macros for running through all the fields except Identifier and Flags. #define FOR_EACH_MDFIELD() \ @@ -149,7 +152,7 @@ Context, UUID, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, DINode::FlagArtificial, Elements, RuntimeLang, VTableHolder, TemplateParams, nullptr, - nullptr, nullptr, nullptr)); + nullptr, nullptr, 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 --- a/llvm/unittests/IR/MetadataTest.cpp +++ b/llvm/unittests/IR/MetadataTest.cpp @@ -1780,6 +1780,16 @@ uint64_t Elements2[] = {dwarf::DW_OP_constu, 0}; Metadata *DataLocation2 = DIExpression::get(Context, Elements2); + uint64_t Elements3[] = {dwarf::DW_OP_constu, 3}; + Metadata *Rank1 = DIExpression::get(Context, Elements3); + + uint64_t Elements4[] = {dwarf::DW_OP_constu, 4}; + Metadata *Rank2 = DIExpression::get(Context, Elements4); + + ConstantInt *RankInt1 = ConstantInt::get(Context, APInt(7, 0)); + ConstantAsMetadata *RankConst1 = ConstantAsMetadata::get(RankInt1); + ConstantInt *RankInt2 = ConstantInt::get(Context, APInt(6, 0)); + ConstantAsMetadata *RankConst2 = ConstantAsMetadata::get(RankInt2); auto *N1 = DICompositeType::get( Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier, @@ -1817,6 +1827,44 @@ EXPECT_EQ(N2, Same2); EXPECT_NE(Same2, Other2); EXPECT_EQ(N2->getDataLocationExp(), DataLocation1); + + auto *N3 = DICompositeType::get( + Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, + OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier, + nullptr, DataLocation1, nullptr, nullptr, Rank1); + + auto *Same3 = DICompositeType::get( + Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, + OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier, + nullptr, DataLocation1, nullptr, nullptr, Rank1); + + auto *Other3 = DICompositeType::get( + Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, + OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier, + nullptr, DataLocation1, nullptr, nullptr, Rank2); + + EXPECT_EQ(N3, Same3); + EXPECT_NE(Same3, Other3); + EXPECT_EQ(N3->getRankExp(), Rank1); + + auto *N4 = DICompositeType::get( + Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, + OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier, + nullptr, DataLocation1, nullptr, nullptr, RankConst1); + + auto *Same4 = DICompositeType::get( + Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, + OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier, + nullptr, DataLocation1, nullptr, nullptr, RankConst1); + + auto *Other4 = DICompositeType::get( + Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, + OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier, + nullptr, DataLocation1, nullptr, nullptr, RankConst2); + + EXPECT_EQ(N4, Same4); + EXPECT_NE(Same4, Other4); + EXPECT_EQ(N4->getRankConst(), RankInt1); } typedef MetadataTest DISubroutineTypeTest;