[llvm] Add bit stride to DICompositeType (PR #131680)
Tom Tromey via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 24 10:46:01 PDT 2025
https://github.com/tromey updated https://github.com/llvm/llvm-project/pull/131680
>From 90e9554fe468e7d3e9f44b97f83c15bd7b0f96fb Mon Sep 17 00:00:00 2001
From: Tom Tromey <tromey at adacore.com>
Date: Thu, 13 Mar 2025 08:34:14 -0600
Subject: [PATCH] Add bit stride to DICompositeType
In Ada, an array can be packed and the elements can take less space
than their natural object size. For example, for this type:
type Packed_Array is array (4 .. 8) of Boolean;
pragma pack (Packed_Array);
... each element of the array occupies a single bit, even though the
"natural" size for a Boolean in memory is a byte.
In DWARF, this is represented by putting a DW_AT_bit_stride onto the
array type itself.
This patch adds a bit stride to DICompositeType so that gnat-llvm can
emit DWARF for these sorts of arrays.
---
llvm/docs/LangRef.rst | 5 ++-
llvm/include/llvm/IR/DIBuilder.h | 4 +-
llvm/include/llvm/IR/DebugInfoMetadata.h | 45 ++++++++++++-------
llvm/lib/AsmParser/LLParser.cpp | 8 ++--
llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 21 +++++----
llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 1 +
llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 4 ++
llvm/lib/IR/AsmWriter.cpp | 1 +
llvm/lib/IR/DIBuilder.cpp | 5 ++-
llvm/lib/IR/DebugInfoMetadata.cpp | 18 ++++----
llvm/lib/IR/LLVMContextImpl.h | 12 +++--
llvm/test/Bitcode/array-bitstride.ll | 30 +++++++++++++
llvm/unittests/IR/DebugInfoTest.cpp | 18 ++++++++
.../unittests/IR/DebugTypeODRUniquingTest.cpp | 37 ++++++++-------
14 files changed, 146 insertions(+), 63 deletions(-)
create mode 100644 llvm/test/Bitcode/array-bitstride.ll
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 <DIEnumerator>`, 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<DIExpression *, DIVariable *> DataLocation = nullptr,
PointerUnion<DIExpression *, DIVariable *> Associated = nullptr,
PointerUnion<DIExpression *, DIVariable *> Allocated = nullptr,
- PointerUnion<DIExpression *, DIVariable *> Rank = nullptr);
+ PointerUnion<DIExpression *, DIVariable *> 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<DIType>(getRawBaseType()); }
DINodeArray getElements() const {
@@ -1477,6 +1480,14 @@ class DICompositeType : public DIType {
DIType *getSpecification() const {
return cast_or_null<DIType>(getRawSpecification());
}
+
+ Metadata *getRawBitStride() const { return getOperand(15); }
+ ConstantInt *getBitStrideConst() const {
+ if (auto *MD = dyn_cast_or_null<ConstantAsMetadata>(getRawBitStride()))
+ return dyn_cast_or_null<ConstantInt>(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<DICompositeType>(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<DIExpression *, DIVariable *> DL,
PointerUnion<DIExpression *, DIVariable *> AS,
PointerUnion<DIExpression *, DIVariable *> AL,
- PointerUnion<DIExpression *, DIVariable *> RK) {
+ PointerUnion<DIExpression *, DIVariable *> 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<DIExpression *>(AL) ? (Metadata *)cast<DIExpression *>(AL)
: (Metadata *)cast<DIVariable *>(AL),
isa<DIExpression *>(RK) ? (Metadata *)cast<DIExpression *>(RK)
- : (Metadata *)cast<DIVariable *>(RK));
+ : (Metadata *)cast<DIVariable *>(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<uint32_t> 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<uint32_t> 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<DICompositeType> {
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<DICompositeType> {
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<DICompositeType> {
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<DICompositeType> {
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<DICompositeType> {
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<Module> 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<Module> 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());
More information about the llvm-commits
mailing list