-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add DISubrangeType #126772
Add DISubrangeType #126772
Conversation
@llvm/pr-subscribers-debuginfo @llvm/pr-subscribers-llvm-ir Author: Tom Tromey (tromey) ChangesAn Ada program can have types that are subranges of other types. This patch adds a new DIType node, DISubrangeType, to represent this concept. I considered extending the existing DISubrange to do this, but as DISubrange does not derive from DIType, that approach seemed more disruptive. A DISubrangeType can be used both as an ordinary type, but also as the type of an array index. This is also important for Ada. Ada subrange types can also be stored using a bias. Representing this in the DWARF required the use of an extension. GCC has been emitting this extension for years, so I've reused it here. Patch is 35.00 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/126772.diff 18 Files Affected:
diff --git a/llvm/include/llvm-c/DebugInfo.h b/llvm/include/llvm-c/DebugInfo.h
index ac7ee5a7cc9a19d..9d0875a4ed8d8fa 100644
--- a/llvm/include/llvm-c/DebugInfo.h
+++ b/llvm/include/llvm-c/DebugInfo.h
@@ -172,6 +172,7 @@ enum {
LLVMDIEnumeratorMetadataKind,
LLVMDIBasicTypeMetadataKind,
LLVMDIDerivedTypeMetadataKind,
+ LLVMDISubrangeTypeMetadataKind,
LLVMDICompositeTypeMetadataKind,
LLVMDISubroutineTypeMetadataKind,
LLVMDIFileMetadataKind,
diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
index 9eb38c3e4482910..ec2535ac85966ac 100644
--- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -385,6 +385,7 @@ enum MetadataCodes {
METADATA_GENERIC_SUBRANGE = 45, // [distinct, count, lo, up, stride]
METADATA_ARG_LIST = 46, // [n x [type num, value num]]
METADATA_ASSIGN_ID = 47, // [distinct, ...]
+ METADATA_SUBRANGE_TYPE = 48, // [distinct, ...]
};
// The constants block (CONSTANTS_BLOCK_ID) describes emission for each
diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h
index 8bee9f4703dd9c7..fc6b88821b09897 100644
--- a/llvm/include/llvm/IR/DIBuilder.h
+++ b/llvm/include/llvm/IR/DIBuilder.h
@@ -667,6 +667,26 @@ namespace llvm {
/// If \p Implicit is true, also set FlagArtificial.
static DIType *createObjectPointerType(DIType *Ty, bool Implicit);
+ /// Create a type describing a subrange of another type.
+ /// \param Scope Scope in which this set is defined.
+ /// \param Name Set name.
+ /// \param File File where this set is defined.
+ /// \param LineNo Line number.
+ /// \param SizeInBits Size.
+ /// \param AlignInBits Alignment.
+ /// \param Flags Flags to encode attributes.
+ /// \param Ty Base type.
+ /// \param LowerBound Lower bound.
+ /// \param UpperBound Upper bound.
+ /// \param Stride Stride, if any.
+ /// \param Bias Bias, if any.
+ DISubrangeType *
+ createSubrangeType(StringRef Name, DIFile *File, unsigned LineNo,
+ DIScope *Scope, uint64_t SizeInBits,
+ uint32_t AlignInBits, DINode::DIFlags Flags, DIType *Ty,
+ Metadata *LowerBound, Metadata *UpperBound,
+ Metadata *Stride, Metadata *Bias);
+
/// Create a permanent forward-declared type.
DICompositeType *
createForwardDecl(unsigned Tag, StringRef Name, DIScope *Scope, DIFile *F,
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 8515d8eda85686b..7826514cd3e44aa 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -200,6 +200,7 @@ class DINode : public MDNode {
case DIEnumeratorKind:
case DIBasicTypeKind:
case DIStringTypeKind:
+ case DISubrangeTypeKind:
case DIDerivedTypeKind:
case DICompositeTypeKind:
case DISubroutineTypeKind:
@@ -342,9 +343,6 @@ class DIAssignID : public MDNode {
};
/// Array subrange.
-///
-/// TODO: Merge into node for DW_TAG_array_type, which should have a custom
-/// type.
class DISubrange : public DINode {
friend class LLVMContextImpl;
friend class MDNode;
@@ -550,6 +548,7 @@ class DIScope : public DINode {
return false;
case DIBasicTypeKind:
case DIStringTypeKind:
+ case DISubrangeTypeKind:
case DIDerivedTypeKind:
case DICompositeTypeKind:
case DISubroutineTypeKind:
@@ -808,6 +807,7 @@ class DIType : public DIScope {
return false;
case DIBasicTypeKind:
case DIStringTypeKind:
+ case DISubrangeTypeKind:
case DIDerivedTypeKind:
case DICompositeTypeKind:
case DISubroutineTypeKind:
@@ -1167,6 +1167,97 @@ inline bool operator!=(DIDerivedType::PtrAuthData Lhs,
return !(Lhs == Rhs);
}
+/// Subrange type. This is somewhat similar to DISubrange, but it
+/// is also a DIType.
+class DISubrangeType : public DIType {
+public:
+ typedef PointerUnion<ConstantInt *, DIVariable *, DIExpression *> BoundType;
+
+private:
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ DISubrangeType(LLVMContext &C, StorageType Storage, unsigned Line,
+ uint64_t SizeInBits, uint32_t AlignInBits, DIFlags Flags,
+ ArrayRef<Metadata *> Ops);
+
+ ~DISubrangeType() = default;
+
+ static DISubrangeType *
+ getImpl(LLVMContext &Context, StringRef Name, DIFile *File, unsigned Line,
+ DIScope *Scope, uint64_t SizeInBits, uint32_t AlignInBits,
+ DIFlags Flags, DIType *BaseType, Metadata *LowerBound,
+ Metadata *UpperBound, Metadata *Stride, Metadata *Bias,
+ StorageType Storage, bool ShouldCreate = true) {
+ return getImpl(Context, getCanonicalMDString(Context, Name), File, Line,
+ Scope, SizeInBits, AlignInBits, Flags, BaseType, LowerBound,
+ UpperBound, Stride, Bias, Storage, ShouldCreate);
+ }
+
+ static DISubrangeType *getImpl(LLVMContext &Context, MDString *Name,
+ Metadata *File, unsigned Line, Metadata *Scope,
+ uint64_t SizeInBits, uint32_t AlignInBits,
+ DIFlags Flags, Metadata *BaseType,
+ Metadata *LowerBound, Metadata *UpperBound,
+ Metadata *Stride, Metadata *Bias,
+ StorageType Storage, bool ShouldCreate = true);
+
+ TempDISubrangeType cloneImpl() const {
+ return getTemporary(getContext(), getName(), getFile(), getLine(),
+ getScope(), getSizeInBits(), getAlignInBits(),
+ getFlags(), getBaseType(), getRawLowerBound(),
+ getRawUpperBound(), getRawStride(), getRawBias());
+ }
+
+ BoundType convertRawToBound(Metadata *IN) const;
+
+public:
+ DEFINE_MDNODE_GET(DISubrangeType,
+ (MDString * Name, Metadata *File, unsigned Line,
+ Metadata *Scope, uint64_t SizeInBits, uint32_t AlignInBits,
+ DIFlags Flags, Metadata *BaseType, Metadata *LowerBound,
+ Metadata *UpperBound, Metadata *Stride, Metadata *Bias),
+ (Name, File, Line, Scope, SizeInBits, AlignInBits, Flags,
+ BaseType, LowerBound, UpperBound, Stride, Bias))
+ DEFINE_MDNODE_GET(DISubrangeType,
+ (StringRef Name, DIFile *File, unsigned Line,
+ DIScope *Scope, uint64_t SizeInBits, uint32_t AlignInBits,
+ DIFlags Flags, DIType *BaseType, Metadata *LowerBound,
+ Metadata *UpperBound, Metadata *Stride, Metadata *Bias),
+ (Name, File, Line, Scope, SizeInBits, AlignInBits, Flags,
+ BaseType, LowerBound, UpperBound, Stride, Bias))
+
+ TempDISubrangeType clone() const { return cloneImpl(); }
+
+ /// Get the base type this is derived from.
+ DIType *getBaseType() const { return cast_or_null<DIType>(getRawBaseType()); }
+ Metadata *getRawBaseType() const { return getOperand(3); }
+
+ Metadata *getRawLowerBound() const { return getOperand(4).get(); }
+
+ Metadata *getRawUpperBound() const { return getOperand(5).get(); }
+
+ Metadata *getRawStride() const { return getOperand(6).get(); }
+
+ Metadata *getRawBias() const { return getOperand(7).get(); }
+
+ BoundType getLowerBound() const {
+ return convertRawToBound(getRawLowerBound());
+ }
+
+ BoundType getUpperBound() const {
+ return convertRawToBound(getRawUpperBound());
+ }
+
+ BoundType getStride() const { return convertRawToBound(getRawStride()); }
+
+ BoundType getBias() const { return convertRawToBound(getRawBias()); }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DISubrangeTypeKind;
+ }
+};
+
/// Composite types.
///
/// TODO: Detach from DerivedTypeBase (split out MDEnumType?).
diff --git a/llvm/include/llvm/IR/Metadata.def b/llvm/include/llvm/IR/Metadata.def
index a3cfb9ad6e3e785..7cb257fefbc3838 100644
--- a/llvm/include/llvm/IR/Metadata.def
+++ b/llvm/include/llvm/IR/Metadata.def
@@ -118,6 +118,7 @@ HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacroFile)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DICommonBlock)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIStringType)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGenericSubrange)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DISubrangeType)
#undef HANDLE_METADATA
#undef HANDLE_METADATA_LEAF
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index ad52a9f493eae0e..71cb9cb75ab6e5b 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -5318,6 +5318,50 @@ bool LLParser::parseGenericDINode(MDNode *&Result, bool IsDistinct) {
return false;
}
+/// parseDISubrangeType:
+/// ::= !DISubrangeType(name: "whatever", file: !0,
+/// line: 7, scope: !1, baseType: !2, size: 32,
+/// align: 32, flags: 0, lowerBound: !3
+/// upperBound: !4, stride: !5, bias: !6)
+bool LLParser::parseDISubrangeType(MDNode *&Result, bool IsDistinct) {
+#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
+ OPTIONAL(name, MDStringField, ); \
+ OPTIONAL(file, MDField, ); \
+ OPTIONAL(line, LineField, ); \
+ OPTIONAL(scope, MDField, ); \
+ OPTIONAL(baseType, MDField, ); \
+ OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX)); \
+ OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \
+ OPTIONAL(flags, DIFlagField, ); \
+ OPTIONAL(lowerBound, MDSignedOrMDField, ); \
+ OPTIONAL(upperBound, MDSignedOrMDField, ); \
+ OPTIONAL(stride, MDSignedOrMDField, ); \
+ OPTIONAL(bias, MDSignedOrMDField, );
+ PARSE_MD_FIELDS();
+#undef VISIT_MD_FIELDS
+
+ auto convToMetadata = [&](MDSignedOrMDField Bound) -> Metadata * {
+ if (Bound.isMDSignedField())
+ return ConstantAsMetadata::get(ConstantInt::getSigned(
+ Type::getInt64Ty(Context), Bound.getMDSignedValue()));
+ if (Bound.isMDField())
+ return Bound.getMDFieldValue();
+ return nullptr;
+ };
+
+ Metadata *LowerBound = convToMetadata(lowerBound);
+ Metadata *UpperBound = convToMetadata(upperBound);
+ Metadata *Stride = convToMetadata(stride);
+ Metadata *Bias = convToMetadata(bias);
+
+ Result = GET_OR_DISTINCT(DISubrangeType,
+ (Context, name.Val, file.Val, line.Val, scope.Val,
+ size.Val, align.Val, flags.Val, baseType.Val,
+ LowerBound, UpperBound, Stride, Bias));
+
+ return false;
+}
+
/// parseDISubrange:
/// ::= !DISubrange(count: 30, lowerBound: 2)
/// ::= !DISubrange(count: !node, lowerBound: 2)
diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
index 413d9f68e6cc3b7..0fbab3200fcf1fc 100644
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -1599,6 +1599,24 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
NextMetadataNo++;
break;
}
+ case bitc::METADATA_SUBRANGE_TYPE: {
+ if (Record.size() != 13)
+ return error("Invalid record");
+
+ IsDistinct = Record[0];
+ DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[7]);
+ MetadataList.assignValue(
+ GET_OR_DISTINCT(DISubrangeType,
+ (Context, getMDString(Record[1]),
+ getMDOrNull(Record[2]), Record[3],
+ getMDOrNull(Record[4]), Record[5], Record[6], Flags,
+ getDITypeRefOrNull(Record[8]), getMDOrNull(Record[9]),
+ getMDOrNull(Record[10]), getMDOrNull(Record[11]),
+ getMDOrNull(Record[12]))),
+ NextMetadataNo);
+ NextMetadataNo++;
+ break;
+ }
case bitc::METADATA_COMPOSITE_TYPE: {
if (Record.size() < 16 || Record.size() > 25)
return error("Invalid record");
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 7ca63c2c7251ded..244bf8eeb9b1893 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -327,6 +327,8 @@ class ModuleBitcodeWriter : public ModuleBitcodeWriterBase {
SmallVectorImpl<uint64_t> &Record, unsigned Abbrev);
void writeDIDerivedType(const DIDerivedType *N,
SmallVectorImpl<uint64_t> &Record, unsigned Abbrev);
+ void writeDISubrangeType(const DISubrangeType *N,
+ SmallVectorImpl<uint64_t> &Record, unsigned Abbrev);
void writeDICompositeType(const DICompositeType *N,
SmallVectorImpl<uint64_t> &Record, unsigned Abbrev);
void writeDISubroutineType(const DISubroutineType *N,
@@ -1930,6 +1932,27 @@ void ModuleBitcodeWriter::writeDIDerivedType(const DIDerivedType *N,
Record.clear();
}
+void ModuleBitcodeWriter::writeDISubrangeType(const DISubrangeType *N,
+ SmallVectorImpl<uint64_t> &Record,
+ unsigned Abbrev) {
+ Record.push_back(N->isDistinct());
+ Record.push_back(VE.getMetadataOrNullID(N->getRawName()));
+ Record.push_back(VE.getMetadataOrNullID(N->getFile()));
+ Record.push_back(N->getLine());
+ Record.push_back(VE.getMetadataOrNullID(N->getScope()));
+ Record.push_back(N->getSizeInBits());
+ Record.push_back(N->getAlignInBits());
+ Record.push_back(N->getFlags());
+ Record.push_back(VE.getMetadataOrNullID(N->getBaseType()));
+ Record.push_back(VE.getMetadataOrNullID(N->getRawLowerBound()));
+ Record.push_back(VE.getMetadataOrNullID(N->getRawUpperBound()));
+ Record.push_back(VE.getMetadataOrNullID(N->getRawStride()));
+ Record.push_back(VE.getMetadataOrNullID(N->getRawBias()));
+
+ Stream.EmitRecord(bitc::METADATA_SUBRANGE_TYPE, Record, Abbrev);
+ Record.clear();
+}
+
void ModuleBitcodeWriter::writeDICompositeType(
const DICompositeType *N, SmallVectorImpl<uint64_t> &Record,
unsigned Abbrev) {
diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
index de2263c57493bb2..533c554faceddec 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
@@ -148,20 +148,21 @@ MCSymbol *DebugHandlerBase::getLabelAfterInsn(const MachineInstr *MI) {
/// If this type is derived from a base type then return base type size.
uint64_t DebugHandlerBase::getBaseTypeSize(const DIType *Ty) {
assert(Ty);
- const DIDerivedType *DDTy = dyn_cast<DIDerivedType>(Ty);
- if (!DDTy)
- return Ty->getSizeInBits();
- unsigned Tag = DDTy->getTag();
+ unsigned Tag = Ty->getTag();
if (Tag != dwarf::DW_TAG_member && Tag != dwarf::DW_TAG_typedef &&
Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type &&
Tag != dwarf::DW_TAG_restrict_type && Tag != dwarf::DW_TAG_atomic_type &&
Tag != dwarf::DW_TAG_immutable_type &&
Tag != dwarf::DW_TAG_template_alias)
- return DDTy->getSizeInBits();
+ return Ty->getSizeInBits();
- DIType *BaseType = DDTy->getBaseType();
+ DIType *BaseType = nullptr;
+ if (const DIDerivedType *DDTy = dyn_cast<DIDerivedType>(Ty))
+ BaseType = DDTy->getBaseType();
+ else if (const DISubrangeType *SRTy = dyn_cast<DISubrangeType>(Ty))
+ BaseType = SRTy->getBaseType();
if (!BaseType)
return 0;
@@ -187,6 +188,12 @@ bool DebugHandlerBase::isUnsignedDIType(const DIType *Ty) {
return true;
}
+ if (auto *SRTy = dyn_cast<DISubrangeType>(Ty)) {
+ Ty = SRTy->getBaseType();
+ if (!Ty)
+ return false;
+ }
+
if (auto *CTy = dyn_cast<DICompositeType>(Ty)) {
if (CTy->getTag() == dwarf::DW_TAG_enumeration_type) {
if (!(Ty = CTy->getBaseType()))
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index c0f2878c84bc84c..700a9831f261788 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -621,6 +621,8 @@ DIE *DwarfUnit::createTypeDIE(const DIScope *Context, DIE &ContextDIE,
construct(ST);
else if (auto *STy = dyn_cast<DISubroutineType>(Ty))
construct(STy);
+ else if (auto *SRTy = dyn_cast<DISubrangeType>(Ty))
+ constructSubrangeDIE(TyDIE, SRTy);
else
construct(cast<DIDerivedType>(Ty));
@@ -1421,10 +1423,69 @@ void DwarfUnit::applySubprogramAttributes(const DISubprogram *SP, DIE &SPDie,
addFlag(SPDie, dwarf::DW_AT_deleted);
}
-void DwarfUnit::constructSubrangeDIE(DIE &Buffer, const DISubrange *SR,
- DIE *IndexTy) {
+void DwarfUnit::constructSubrangeDIE(DIE &DW_Subrange, const DISubrangeType *SR,
+ bool ForArray) {
+ StringRef Name = SR->getName();
+ if (!Name.empty())
+ addString(DW_Subrange, dwarf::DW_AT_name, Name);
+
+ if (SR->getBaseType())
+ addType(DW_Subrange, SR->getBaseType());
+
+ addSourceLine(DW_Subrange, SR);
+
+ if (uint64_t Size = SR->getSizeInBits())
+ addUInt(DW_Subrange, dwarf::DW_AT_byte_size, std::nullopt, Size >> 3);
+ if (uint32_t AlignInBytes = SR->getAlignInBytes())
+ addUInt(DW_Subrange, dwarf::DW_AT_alignment, dwarf::DW_FORM_udata,
+ AlignInBytes);
+
+ if (SR->isBigEndian())
+ addUInt(DW_Subrange, dwarf::DW_AT_endianity, std::nullopt,
+ dwarf::DW_END_big);
+ else if (SR->isLittleEndian())
+ addUInt(DW_Subrange, dwarf::DW_AT_endianity, std::nullopt,
+ dwarf::DW_END_little);
+
+ // The LowerBound value defines the lower bounds which is typically
+ // zero for C/C++. Values are 64 bit.
+ int64_t DefaultLowerBound = getDefaultLowerBound();
+
+ auto AddBoundTypeEntry = [&](dwarf::Attribute Attr,
+ DISubrangeType::BoundType Bound) -> void {
+ if (auto *BV = Bound.dyn_cast<DIVariable *>()) {
+ if (auto *VarDIE = getDIE(BV))
+ addDIEEntry(DW_Subrange, Attr, *VarDIE);
+ } else if (auto *BE = Bound.dyn_cast<DIExpression *>()) {
+ DIELoc *Loc = new (DIEValueAllocator) DIELoc;
+ DIEDwarfExpression DwarfExpr(*Asm, getCU(), *Loc);
+ DwarfExpr.setMemoryLocationKind();
+ DwarfExpr.addExpression(BE);
+ addBlock(DW_Subrange, Attr, DwarfExpr.finalize());
+ } else if (auto *BI = Bound.dyn_cast<ConstantInt *>()) {
+ if (Attr == dwarf::DW_AT_GNU_bias) {
+ if (BI->getSExtValue() != 0)
+ addUInt(DW_Subrange, Attr, dwarf::DW_FORM_sdata, BI->getSExtValue());
+ } else if (Attr != dwarf::DW_AT_lower_bound || DefaultLowerBound == -1 ||
+ BI->getSExtValue() != DefaultLowerBound || !ForArray)
+ addSInt(DW_Subrange, Attr, dwarf::DW_FORM_sdata, BI->getSExtValue());
+ }
+ };
+
+ AddBoundTypeEntry(dwarf::DW_AT_lower_bound, SR->getLowerBound());
+
+ AddBoundTypeEntry(dwarf::DW_AT_upper_bound, SR->getUpperBound());
+
+ AddBoundTypeEntry(dwarf::DW_AT_byte_stride, SR->getStride());
+
+ AddBoundTypeEntry(dwarf::DW_AT_GNU_bias, SR->getBias());
+}
+
+void DwarfUnit::constructSubrangeDIE(DIE &Buffer, const DISubrange *SR) {
DIE &DW_Subrange = createAndAddDIE(dwarf::DW_TAG_subrange_type, Buffer);
- addDIEEntry(DW_Subrange, dwarf::DW_AT_type, *IndexTy);
+
+ DIE *IdxTy = getIndexTyDie();
+ addDIEEntry(DW_Subrange, dwarf::DW_AT_type, *IdxTy);
// The LowerBound value defines the lower bounds which is typically zero for
// C/C++. The Count value is the number of elements. Values are 64 bit. If
@@ -1463,11 +1524,14 @@ void DwarfUnit::constructSubrangeDIE(DIE &Buffer, const DISubrange *SR,
}
void DwarfUnit::constructGenericSubrangeDIE(DIE &Buffer,
- const DIGenericSubrange *GSR,
- ...
[truncated]
|
Definitely a failure in this patch, but I don't really understand it. Will try to find out. |
Could you share some examples of what these Ada types look like, how they're used and what the expected DWARF would look like? |
Here's an example of a range type that shows some of the features:
This is an integer range. Objects of this type take 2 bits, so the type is stored with a bias -- that is, the value -7 is represented as 0 in memory. It looks like this in the DWARF (this is the GCC output but the LLVM output is similar):
|
FTR, Pascal also has subrange types, so this can be useful beyond Ada. I suspect Pascal compilers would also use a bias if the type is used as an array index, and maybe if it was a packed type, although I haven't worked on any Pascal compilers for decades. |
Oops, I forgot the "how they're used" part. They are just integers:
Also worth pointing out that in Ada you can have a subrange of an enumeration type (and I think fixed point types -- but I haven't submitted the fixed point work yet). Also, the bounds can be dynamic. |
Haven't looked into the semantics of the new node kind, but the mechanical part of the implementation and test coverage LGTM. |
06f4f46
to
bf4cb17
Compare
I made some changes to try to fix the failure pointed out by the bot. I am not sure if |
✅ With the latest revision this PR passed the C/C++ code formatter. |
Maybe worth pointing out that the bias extension is being standardized: https://dwarfstd.org/issues/190809.1.html When DWARF 6 is released this will be an easy fix. Pierre-Marie documented the extension when it was added to GCC: https://gcc.gnu.org/wiki/DW_AT_GNU_bias |
This patch refactors DebugHandlerBase::getBaseTypeSize a little, making it less dependent on DIDerivedType. This is preparation for a subsequent patch that adds a new case here.
DwarfUnit::constructArrayTypeDIE has a FIXME comment related to an over-broad cast. As I am planning to add a new case in this spot, this patch first refactors it to be more precise.
A future patch will add the ability to specify the index type of an array. To facilitate this, this patch moves the creation of the current index type out of DwarfUnit::constructArrayTypeDIE and into the methods where it is needed.
Valgrind helped track it down. I was missing an initializer in |
An Ada program can have types that are subranges of other types. This patch adds a new DIType node, DISubrangeType, to represent this concept. I considered extending the existing DISubrange to do this, but as DISubrange does not derive from DIType, that approach seemed more disruptive. A DISubrangeType can be used both as an ordinary type, but also as the type of an array index. This is also important for Ada.
bf4cb17
to
5944333
Compare
Ping. |
1. Fix build break caused by llvm#126772 by adding `writeDISubrangeType` stub to `DXILBitcodeWriter.cpp` 2. Fix build break caused by llvm#128480 by adding implementation of pure virtual method `TargetSubtargetInfo::getRegisterInfo`
1. Fix build break caused by llvm#126772 by adding `writeDISubrangeType` stub to `DXILBitcodeWriter.cpp` 2. Fix build break caused by llvm#128480 by adding implementation of pure virtual method `TargetSubtargetInfo::getRegisterInfo`
An Ada program can have types that are subranges of other types. This patch adds a new DIType node, DISubrangeType, to represent this concept.
I considered extending the existing DISubrange to do this, but as DISubrange does not derive from DIType, that approach seemed more disruptive.
A DISubrangeType can be used both as an ordinary type, but also as the type of an array index. This is also important for Ada.
Ada subrange types can also be stored using a bias. Representing this in the DWARF required the use of an extension. GCC has been emitting this extension for years, so I've reused it here.