diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index f93435981c3e8..655ec4389456c 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -6336,7 +6336,10 @@ array is currently associated. The optional ``allocated`` is a DIExpression that describes whether the 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). +known at runtime). The optional ``bitStride`` is an unsigned constant +that describes the number of bits occupied by an element of the array; +this is only needed if it differs from the element type's natural +size, and is normally used for packed arrays. 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/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h index 92a0b7a16d039..b63e564dfd36b 100644 --- a/llvm/include/llvm/IR/DIBuilder.h +++ b/llvm/include/llvm/IR/DIBuilder.h @@ -609,13 +609,15 @@ namespace llvm { /// \param Rank The rank attribute of a descriptor-based /// Fortran array, either a DIExpression* or /// a DIVariable*. + /// \param BitStride The bit size of an element of the array. DICompositeType *createArrayType( DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, uint64_t Size, uint32_t AlignInBits, DIType *Ty, DINodeArray Subscripts, PointerUnion DataLocation = nullptr, PointerUnion Associated = nullptr, PointerUnion Allocated = nullptr, - PointerUnion Rank = nullptr); + PointerUnion Rank = nullptr, + Metadata *BitStride = nullptr); /// Create debugging information entry for a vector type. /// \param Size Array size. diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index 7826514cd3e44..62a59ddaee599 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -1302,15 +1302,15 @@ class DICompositeType : public DIType { DIType *VTableHolder, DITemplateParameterArray TemplateParams, StringRef Identifier, DIDerivedType *Discriminator, Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, - Metadata *Rank, DINodeArray Annotations, StorageType Storage, - bool ShouldCreate = true) { - return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, - Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, - Flags, Elements.get(), RuntimeLang, EnumKind, VTableHolder, - TemplateParams.get(), - getCanonicalMDString(Context, Identifier), Discriminator, - DataLocation, Associated, Allocated, Rank, Annotations.get(), - Specification, NumExtraInhabitants, Storage, ShouldCreate); + Metadata *Rank, DINodeArray Annotations, Metadata *BitStride, + StorageType Storage, bool ShouldCreate = true) { + return getImpl( + Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope, + BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(), + RuntimeLang, EnumKind, VTableHolder, TemplateParams.get(), + getCanonicalMDString(Context, Identifier), Discriminator, DataLocation, + Associated, Allocated, Rank, Annotations.get(), Specification, + NumExtraInhabitants, BitStride, Storage, ShouldCreate); } static DICompositeType * getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, @@ -1322,7 +1322,7 @@ class DICompositeType : public DIType { Metadata *Discriminator, Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, Metadata *Rank, Metadata *Annotations, Metadata *Specification, uint32_t NumExtraInhabitants, - StorageType Storage, bool ShouldCreate = true); + Metadata *BitStride, StorageType Storage, bool ShouldCreate = true); TempDICompositeType cloneImpl() const { return getTemporary( @@ -1332,7 +1332,7 @@ class DICompositeType : public DIType { getVTableHolder(), getTemplateParams(), getIdentifier(), getDiscriminator(), getRawDataLocation(), getRawAssociated(), getRawAllocated(), getRawRank(), getAnnotations(), getSpecification(), - getNumExtraInhabitants()); + getNumExtraInhabitants(), getRawBitStride()); } public: @@ -1348,11 +1348,12 @@ class DICompositeType : public DIType { Metadata *DataLocation = nullptr, Metadata *Associated = nullptr, Metadata *Allocated = nullptr, Metadata *Rank = nullptr, DINodeArray Annotations = nullptr, DIType *Specification = nullptr, - uint32_t NumExtraInhabitants = 0), + uint32_t NumExtraInhabitants = 0, Metadata *BitStride = nullptr), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Specification, NumExtraInhabitants, Flags, Elements, RuntimeLang, EnumKind, VTableHolder, TemplateParams, Identifier, - Discriminator, DataLocation, Associated, Allocated, Rank, Annotations)) + Discriminator, DataLocation, Associated, Allocated, Rank, Annotations, + BitStride)) DEFINE_MDNODE_GET( DICompositeType, (unsigned Tag, MDString *Name, Metadata *File, unsigned Line, @@ -1364,11 +1365,13 @@ class DICompositeType : public DIType { Metadata *Discriminator = nullptr, Metadata *DataLocation = nullptr, Metadata *Associated = nullptr, Metadata *Allocated = nullptr, Metadata *Rank = nullptr, Metadata *Annotations = nullptr, - Metadata *Specification = nullptr, uint32_t NumExtraInhabitants = 0), + Metadata *Specification = nullptr, uint32_t NumExtraInhabitants = 0, + Metadata *BitStride = nullptr), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, EnumKind, VTableHolder, TemplateParams, Identifier, Discriminator, DataLocation, Associated, - Allocated, Rank, Annotations, Specification, NumExtraInhabitants)) + Allocated, Rank, Annotations, Specification, NumExtraInhabitants, + BitStride)) TempDICompositeType clone() const { return cloneImpl(); } @@ -1389,7 +1392,7 @@ class DICompositeType : public DIType { Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator, Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, Metadata *Rank, - Metadata *Annotations); + Metadata *Annotations, Metadata *BitStride); static DICompositeType *getODRTypeIfExists(LLVMContext &Context, MDString &Identifier); @@ -1412,7 +1415,7 @@ class DICompositeType : public DIType { Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator, Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, Metadata *Rank, - Metadata *Annotations); + Metadata *Annotations, Metadata *BitStride); DIType *getBaseType() const { return cast_or_null(getRawBaseType()); } DINodeArray getElements() const { @@ -1477,6 +1480,14 @@ class DICompositeType : public DIType { DIType *getSpecification() const { return cast_or_null(getRawSpecification()); } + + Metadata *getRawBitStride() const { return getOperand(15); } + ConstantInt *getBitStrideConst() const { + if (auto *MD = dyn_cast_or_null(getRawBitStride())) + return dyn_cast_or_null(MD->getValue()); + return nullptr; + } + /// Replace operands. /// /// If this \a isUniqued() and not \a isResolved(), on a uniquing collision diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index d1ec575111d34..960119bab0933 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -5613,7 +5613,8 @@ bool LLParser::parseDICompositeType(MDNode *&Result, bool IsDistinct) { OPTIONAL(rank, MDSignedOrMDField, ); \ OPTIONAL(annotations, MDField, ); \ OPTIONAL(num_extra_inhabitants, MDUnsignedField, (0, UINT32_MAX)); \ - OPTIONAL(specification, MDField, ); + OPTIONAL(specification, MDField, ); \ + OPTIONAL(bitStride, MDField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS @@ -5636,7 +5637,8 @@ bool LLParser::parseDICompositeType(MDNode *&Result, bool IsDistinct) { specification.Val, num_extra_inhabitants.Val, flags.Val, elements.Val, runtimeLang.Val, EnumKind, vtableHolder.Val, templateParams.Val, discriminator.Val, dataLocation.Val, - associated.Val, allocated.Val, Rank, annotations.Val)) { + associated.Val, allocated.Val, Rank, annotations.Val, + bitStride.Val)) { Result = CT; return false; } @@ -5650,7 +5652,7 @@ bool LLParser::parseDICompositeType(MDNode *&Result, bool IsDistinct) { runtimeLang.Val, EnumKind, vtableHolder.Val, templateParams.Val, identifier.Val, discriminator.Val, dataLocation.Val, associated.Val, allocated.Val, Rank, annotations.Val, specification.Val, - num_extra_inhabitants.Val)); + num_extra_inhabitants.Val, bitStride.Val)); return false; } diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp index 12794d3346e3f..e87e5bde63d82 100644 --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -1618,7 +1618,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( break; } case bitc::METADATA_COMPOSITE_TYPE: { - if (Record.size() < 16 || Record.size() > 25) + if (Record.size() < 16 || Record.size() > 26) return error("Invalid record"); // If we have a UUID and this is not a forward declaration, lookup the @@ -1651,6 +1651,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( Metadata *Rank = nullptr; Metadata *Annotations = nullptr; Metadata *Specification = nullptr; + Metadata *BitStride = 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 as @@ -1702,6 +1703,8 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( if (Record.size() > 23) { Specification = getMDOrNull(Record[23]); } + if (Record.size() > 25) + BitStride = getMDOrNull(Record[25]); } if (Record.size() > 24 && Record[24] != dwarf::DW_APPLE_ENUM_KIND_invalid) @@ -1714,17 +1717,17 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( SizeInBits, AlignInBits, OffsetInBits, Specification, NumExtraInhabitants, Flags, Elements, RuntimeLang, EnumKind, VTableHolder, TemplateParams, Discriminator, DataLocation, Associated, - Allocated, Rank, Annotations); + Allocated, Rank, Annotations, BitStride); // Create a node if we didn't get a lazy ODR type. if (!CT) - CT = GET_OR_DISTINCT(DICompositeType, - (Context, Tag, Name, File, Line, Scope, BaseType, - SizeInBits, AlignInBits, OffsetInBits, Flags, - Elements, RuntimeLang, EnumKind, VTableHolder, - TemplateParams, Identifier, Discriminator, - DataLocation, Associated, Allocated, Rank, - Annotations, Specification, NumExtraInhabitants)); + CT = GET_OR_DISTINCT( + DICompositeType, + (Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, EnumKind, + VTableHolder, TemplateParams, Identifier, Discriminator, + DataLocation, Associated, Allocated, Rank, Annotations, + Specification, NumExtraInhabitants, BitStride)); if (!IsNotUsedInTypeRef && Identifier) MetadataList.addTypeRef(*Identifier, *cast(CT)); diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 8f7482d167977..34ba25dccc368 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1990,6 +1990,7 @@ void ModuleBitcodeWriter::writeDICompositeType( Record.push_back(VE.getMetadataOrNullID(N->getRawSpecification())); Record.push_back( N->getEnumKind().value_or(dwarf::DW_APPLE_ENUM_KIND_invalid)); + Record.push_back(VE.getMetadataOrNullID(N->getRawBitStride())); 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 index 383fbfb3fbd2b..081828ea358af 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1663,6 +1663,10 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) { addBlock(Buffer, dwarf::DW_AT_rank, DwarfExpr.finalize()); } + if (auto *BitStride = CTy->getBitStrideConst()) { + addUInt(Buffer, dwarf::DW_AT_bit_stride, {}, BitStride->getZExtValue()); + } + // Emit the element type. addType(Buffer, CTy->getBaseType()); diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index eb8bbd08fb762..79547b299a903 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -2308,6 +2308,7 @@ static void writeDICompositeType(raw_ostream &Out, const DICompositeType *N, Printer.printDwarfEnum("enumKind", *EnumKind, dwarf::EnumKindString, /*ShouldSkipZero=*/false); + Printer.printMetadata("bitStride", N->getRawBitStride()); Out << ")"; } diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index f127ca8d94295..9e7aea882c593 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -611,7 +611,7 @@ DICompositeType *DIBuilder::createArrayType( PointerUnion DL, PointerUnion AS, PointerUnion AL, - PointerUnion RK) { + PointerUnion RK, Metadata *BitStride) { auto *R = DICompositeType::get( VMContext, dwarf::DW_TAG_array_type, Name, File, LineNumber, getNonCompileUnitScope(Scope), Ty, Size, AlignInBits, 0, DINode::FlagZero, @@ -623,7 +623,8 @@ DICompositeType *DIBuilder::createArrayType( isa(AL) ? (Metadata *)cast(AL) : (Metadata *)cast(AL), isa(RK) ? (Metadata *)cast(RK) - : (Metadata *)cast(RK)); + : (Metadata *)cast(RK), + nullptr, nullptr, 0, BitStride); trackIfUnresolved(R); return R; } diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index f975d4ca33ad9..ae3d79fc17a59 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -813,8 +813,8 @@ DICompositeType *DICompositeType::getImpl( Metadata *VTableHolder, Metadata *TemplateParams, MDString *Identifier, Metadata *Discriminator, Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, Metadata *Rank, Metadata *Annotations, - Metadata *Specification, uint32_t NumExtraInhabitants, StorageType Storage, - bool ShouldCreate) { + Metadata *Specification, uint32_t NumExtraInhabitants, Metadata *BitStride, + StorageType Storage, bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); // Keep this in sync with buildODRType. @@ -823,11 +823,11 @@ DICompositeType *DICompositeType::getImpl( (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier, Discriminator, DataLocation, Associated, Allocated, Rank, - Annotations, Specification, NumExtraInhabitants)); + Annotations, Specification, NumExtraInhabitants, BitStride)); Metadata *Ops[] = {File, Scope, Name, BaseType, Elements, VTableHolder, TemplateParams, Identifier, Discriminator, DataLocation, Associated, Allocated, - Rank, Annotations, Specification}; + Rank, Annotations, Specification, BitStride}; DEFINE_GETIMPL_STORE(DICompositeType, (Tag, Line, RuntimeLang, SizeInBits, AlignInBits, OffsetInBits, NumExtraInhabitants, EnumKind, Flags), @@ -842,7 +842,7 @@ DICompositeType *DICompositeType::buildODRType( Metadata *Elements, unsigned RuntimeLang, std::optional EnumKind, Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator, Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, - Metadata *Rank, Metadata *Annotations) { + Metadata *Rank, Metadata *Annotations, Metadata *BitStride) { assert(!Identifier.getString().empty() && "Expected valid identifier"); if (!Context.isODRUniquingDebugTypes()) return nullptr; @@ -853,7 +853,7 @@ DICompositeType *DICompositeType::buildODRType( AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, EnumKind, VTableHolder, TemplateParams, &Identifier, Discriminator, DataLocation, Associated, Allocated, Rank, - Annotations, Specification, NumExtraInhabitants); + Annotations, Specification, NumExtraInhabitants, BitStride); if (CT->getTag() != Tag) return nullptr; @@ -868,7 +868,7 @@ DICompositeType *DICompositeType::buildODRType( Metadata *Ops[] = {File, Scope, Name, BaseType, Elements, VTableHolder, TemplateParams, &Identifier, Discriminator, DataLocation, Associated, Allocated, - Rank, Annotations, Specification}; + Rank, Annotations, Specification, BitStride}; assert((std::end(Ops) - std::begin(Ops)) == (int)CT->getNumOperands() && "Mismatched number of operands"); for (unsigned I = 0, E = CT->getNumOperands(); I != E; ++I) @@ -885,7 +885,7 @@ DICompositeType *DICompositeType::getODRType( Metadata *Elements, unsigned RuntimeLang, std::optional EnumKind, Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator, Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, - Metadata *Rank, Metadata *Annotations) { + Metadata *Rank, Metadata *Annotations, Metadata *BitStride) { assert(!Identifier.getString().empty() && "Expected valid identifier"); if (!Context.isODRUniquingDebugTypes()) return nullptr; @@ -896,7 +896,7 @@ DICompositeType *DICompositeType::getODRType( AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, EnumKind, VTableHolder, TemplateParams, &Identifier, Discriminator, DataLocation, Associated, Allocated, Rank, Annotations, Specification, - NumExtraInhabitants); + NumExtraInhabitants, BitStride); } else { if (CT->getTag() != Tag) return nullptr; diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index 72ea3104cc7d5..a18cf6f205623 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -735,6 +735,7 @@ template <> struct MDNodeKeyImpl { Metadata *Annotations; Metadata *Specification; uint32_t NumExtraInhabitants; + Metadata *BitStride; MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, @@ -744,7 +745,8 @@ template <> struct MDNodeKeyImpl { MDString *Identifier, Metadata *Discriminator, Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, Metadata *Rank, Metadata *Annotations, - Metadata *Specification, uint32_t NumExtraInhabitants) + Metadata *Specification, uint32_t NumExtraInhabitants, + Metadata *BitStride) : Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope), BaseType(BaseType), SizeInBits(SizeInBits), OffsetInBits(OffsetInBits), AlignInBits(AlignInBits), Flags(Flags), Elements(Elements), @@ -753,7 +755,7 @@ template <> struct MDNodeKeyImpl { Discriminator(Discriminator), DataLocation(DataLocation), Associated(Associated), Allocated(Allocated), Rank(Rank), Annotations(Annotations), Specification(Specification), - NumExtraInhabitants(NumExtraInhabitants) {} + NumExtraInhabitants(NumExtraInhabitants), BitStride(BitStride) {} MDNodeKeyImpl(const DICompositeType *N) : Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()), Line(N->getLine()), Scope(N->getRawScope()), @@ -768,7 +770,8 @@ template <> struct MDNodeKeyImpl { Associated(N->getRawAssociated()), Allocated(N->getRawAllocated()), Rank(N->getRawRank()), Annotations(N->getRawAnnotations()), Specification(N->getSpecification()), - NumExtraInhabitants(N->getNumExtraInhabitants()) {} + NumExtraInhabitants(N->getNumExtraInhabitants()), + BitStride(N->getRawBitStride()) {} bool isKeyOf(const DICompositeType *RHS) const { return Tag == RHS->getTag() && Name == RHS->getRawName() && @@ -788,7 +791,8 @@ template <> struct MDNodeKeyImpl { Allocated == RHS->getRawAllocated() && Rank == RHS->getRawRank() && Annotations == RHS->getRawAnnotations() && Specification == RHS->getSpecification() && - NumExtraInhabitants == RHS->getNumExtraInhabitants(); + NumExtraInhabitants == RHS->getNumExtraInhabitants() && + BitStride == RHS->getRawBitStride(); } unsigned getHashValue() const { diff --git a/llvm/test/Bitcode/array-bitstride.ll b/llvm/test/Bitcode/array-bitstride.ll new file mode 100644 index 0000000000000..5137e6fec9913 --- /dev/null +++ b/llvm/test/Bitcode/array-bitstride.ll @@ -0,0 +1,30 @@ +;; Test bit stride of arrays. + +; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s + +; CHECK: !DICompositeType(tag: DW_TAG_array_type, baseType: !{{[0-9]+}}, size: 32, align: 32, elements: !{{[0-9]+}}, bitStride: i32 7) + +; ModuleID = 'stride.adb' +source_filename = "/dir/stride.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_Ada95, file: !3, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !5, globals: !4, imports: !4) +!3 = !DIFile(filename: "stride.adb", directory: "/dir") +!4 = !{} +!5 = !{!6, !17} +!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 32, align: 32, elements: !8, dataLocation: !10, associated: !15) +!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: !14, flags: DIFlagArtificial) +!11 = distinct !DISubprogram(name: "main", scope: !2, file: !3, line: 1, type: !12, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !2) +!12 = !DISubroutineType(cc: DW_CC_program, types: !13) +!13 = !{null} +!14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 32, align: 32) +!15 = distinct !DILocalVariable(scope: !11, file: !3, type: !16, flags: DIFlagArtificial) +!16 = !DIBasicType(name: "integer", size: 32, align: 32, encoding: DW_ATE_signed) +!17 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 32, align: 32, elements: !8, bitStride: i32 7) diff --git a/llvm/unittests/IR/DebugInfoTest.cpp b/llvm/unittests/IR/DebugInfoTest.cpp index c632bd6d3cbb5..d019823a5548d 100644 --- a/llvm/unittests/IR/DebugInfoTest.cpp +++ b/llvm/unittests/IR/DebugInfoTest.cpp @@ -413,6 +413,24 @@ TEST(DIBuilder, CreateFortranArrayTypeWithAttributes) { DIVariable::deleteTemporary(DataLocation); } +TEST(DIBuilder, CreateArrayWithBitStride) { + LLVMContext Ctx; + std::unique_ptr M(new Module("MyModule", Ctx)); + DIBuilder DIB(*M); + + Type *Int32Ty = Type::getInt32Ty(Ctx); + Constant *Ci = ConstantInt::get(Int32Ty, 7); + Metadata *CM = ConstantAsMetadata::get(Ci); + + StringRef ArrayNameExp = "AnArray"; + DICompositeType *NamedArray = + DIB.createArrayType(nullptr, ArrayNameExp, nullptr, 0, 8, 8, nullptr, {}, + nullptr, nullptr, nullptr, nullptr, CM); + EXPECT_EQ(NamedArray->getTag(), dwarf::DW_TAG_array_type); + EXPECT_EQ(NamedArray->getRawBitStride(), CM); + EXPECT_EQ(NamedArray->getBitStrideConst(), Ci); +} + TEST(DIBuilder, CreateSetType) { LLVMContext Ctx; std::unique_ptr M(new Module("MyModule", Ctx)); diff --git a/llvm/unittests/IR/DebugTypeODRUniquingTest.cpp b/llvm/unittests/IR/DebugTypeODRUniquingTest.cpp index 7c673b0166188..e1ce671852c8b 100644 --- a/llvm/unittests/IR/DebugTypeODRUniquingTest.cpp +++ b/llvm/unittests/IR/DebugTypeODRUniquingTest.cpp @@ -31,7 +31,8 @@ TEST(DebugTypeODRUniquingTest, getODRType) { EXPECT_FALSE(DICompositeType::getODRType( Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0, nullptr, 0, DINode::FlagZero, nullptr, 0, std::nullopt, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr)); + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr)); // Enable the mapping. There still shouldn't be a type. Context.enableDebugTypeODRUniquing(); @@ -41,7 +42,8 @@ TEST(DebugTypeODRUniquingTest, getODRType) { auto &CT = *DICompositeType::getODRType( Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0, nullptr, 0, DINode::FlagZero, nullptr, 0, std::nullopt, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, 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. @@ -50,13 +52,13 @@ TEST(DebugTypeODRUniquingTest, getODRType) { Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0, nullptr, 0, DINode::FlagZero, nullptr, 0, std::nullopt, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr, 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, nullptr, 0, DINode::FlagZero, nullptr, 0, std::nullopt, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr)); + nullptr, nullptr, nullptr, nullptr)); // Check that it's discarded with the type map. Context.disableDebugTypeODRUniquing(); @@ -77,7 +79,7 @@ TEST(DebugTypeODRUniquingTest, buildODRType) { Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0, nullptr, 0, DINode::FlagFwdDecl, nullptr, 0, std::nullopt, 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()); @@ -87,20 +89,20 @@ TEST(DebugTypeODRUniquingTest, buildODRType) { Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0, nullptr, 0, DINode::FlagFwdDecl, nullptr, 0, std::nullopt, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr)); + nullptr, nullptr, nullptr, nullptr, nullptr)); EXPECT_FALSE(DICompositeType::buildODRType( Context, UUID, dwarf::DW_TAG_structure_type, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0, nullptr, 0, DINode::FlagFwdDecl, nullptr, 0, std::nullopt, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr)); + nullptr, nullptr, nullptr)); // Update with a definition. This time we should see a change. EXPECT_EQ(&CT, DICompositeType::buildODRType( Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0, nullptr, 0, DINode::FlagZero, nullptr, 0, std::nullopt, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr, nullptr)); + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr)); EXPECT_FALSE(CT.isForwardDecl()); // Further updates should be ignored. @@ -109,14 +111,14 @@ TEST(DebugTypeODRUniquingTest, buildODRType) { Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0, nullptr, 0, DINode::FlagFwdDecl, nullptr, 0, std::nullopt, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr)); + nullptr, nullptr, nullptr, nullptr, nullptr)); EXPECT_FALSE(CT.isForwardDecl()); EXPECT_EQ(&CT, DICompositeType::buildODRType( Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 111u, nullptr, nullptr, 0, 0, 0, nullptr, 0, DINode::FlagZero, nullptr, 0, std::nullopt, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr)); + nullptr, nullptr, nullptr, nullptr, nullptr)); EXPECT_NE(111u, CT.getLine()); } @@ -129,7 +131,7 @@ TEST(DebugTypeODRUniquingTest, buildODRTypeFields) { auto &CT = *DICompositeType::buildODRType( Context, UUID, 0, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0, nullptr, 0, DINode::FlagFwdDecl, nullptr, 0, std::nullopt, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr, 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() \ @@ -159,12 +161,13 @@ 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, 0, Name, File, Line, Scope, BaseType, - SizeInBits, AlignInBits, OffsetInBits, nullptr, - NumExtraInhabitants, DINode::FlagArtificial, Elements, - RuntimeLang, EnumKind, VTableHolder, TemplateParams, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr)); + EXPECT_EQ(&CT, + DICompositeType::buildODRType( + Context, UUID, 0, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, nullptr, NumExtraInhabitants, + DINode::FlagArtificial, Elements, RuntimeLang, EnumKind, + VTableHolder, TemplateParams, 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());