Skip to content

Commit e298fc2

Browse files
authored
Add DISubrangeType (#126772)
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.
1 parent 8dbc393 commit e298fc2

File tree

18 files changed

+531
-31
lines changed

18 files changed

+531
-31
lines changed

llvm/include/llvm-c/DebugInfo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ enum {
172172
LLVMDIEnumeratorMetadataKind,
173173
LLVMDIBasicTypeMetadataKind,
174174
LLVMDIDerivedTypeMetadataKind,
175+
LLVMDISubrangeTypeMetadataKind,
175176
LLVMDICompositeTypeMetadataKind,
176177
LLVMDISubroutineTypeMetadataKind,
177178
LLVMDIFileMetadataKind,

llvm/include/llvm/Bitcode/LLVMBitCodes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,7 @@ enum MetadataCodes {
385385
METADATA_GENERIC_SUBRANGE = 45, // [distinct, count, lo, up, stride]
386386
METADATA_ARG_LIST = 46, // [n x [type num, value num]]
387387
METADATA_ASSIGN_ID = 47, // [distinct, ...]
388+
METADATA_SUBRANGE_TYPE = 48, // [distinct, ...]
388389
};
389390

390391
// The constants block (CONSTANTS_BLOCK_ID) describes emission for each

llvm/include/llvm/IR/DIBuilder.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,26 @@ namespace llvm {
678678
/// If \p Implicit is true, also set FlagArtificial.
679679
static DIType *createObjectPointerType(DIType *Ty, bool Implicit);
680680

681+
/// Create a type describing a subrange of another type.
682+
/// \param Scope Scope in which this set is defined.
683+
/// \param Name Set name.
684+
/// \param File File where this set is defined.
685+
/// \param LineNo Line number.
686+
/// \param SizeInBits Size.
687+
/// \param AlignInBits Alignment.
688+
/// \param Flags Flags to encode attributes.
689+
/// \param Ty Base type.
690+
/// \param LowerBound Lower bound.
691+
/// \param UpperBound Upper bound.
692+
/// \param Stride Stride, if any.
693+
/// \param Bias Bias, if any.
694+
DISubrangeType *
695+
createSubrangeType(StringRef Name, DIFile *File, unsigned LineNo,
696+
DIScope *Scope, uint64_t SizeInBits,
697+
uint32_t AlignInBits, DINode::DIFlags Flags, DIType *Ty,
698+
Metadata *LowerBound, Metadata *UpperBound,
699+
Metadata *Stride, Metadata *Bias);
700+
681701
/// Create a permanent forward-declared type.
682702
DICompositeType *
683703
createForwardDecl(unsigned Tag, StringRef Name, DIScope *Scope, DIFile *F,

llvm/include/llvm/IR/DebugInfoMetadata.h

Lines changed: 94 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ class DINode : public MDNode {
200200
case DIEnumeratorKind:
201201
case DIBasicTypeKind:
202202
case DIStringTypeKind:
203+
case DISubrangeTypeKind:
203204
case DIDerivedTypeKind:
204205
case DICompositeTypeKind:
205206
case DISubroutineTypeKind:
@@ -342,9 +343,6 @@ class DIAssignID : public MDNode {
342343
};
343344

344345
/// Array subrange.
345-
///
346-
/// TODO: Merge into node for DW_TAG_array_type, which should have a custom
347-
/// type.
348346
class DISubrange : public DINode {
349347
friend class LLVMContextImpl;
350348
friend class MDNode;
@@ -550,6 +548,7 @@ class DIScope : public DINode {
550548
return false;
551549
case DIBasicTypeKind:
552550
case DIStringTypeKind:
551+
case DISubrangeTypeKind:
553552
case DIDerivedTypeKind:
554553
case DICompositeTypeKind:
555554
case DISubroutineTypeKind:
@@ -808,6 +807,7 @@ class DIType : public DIScope {
808807
return false;
809808
case DIBasicTypeKind:
810809
case DIStringTypeKind:
810+
case DISubrangeTypeKind:
811811
case DIDerivedTypeKind:
812812
case DICompositeTypeKind:
813813
case DISubroutineTypeKind:
@@ -1167,6 +1167,97 @@ inline bool operator!=(DIDerivedType::PtrAuthData Lhs,
11671167
return !(Lhs == Rhs);
11681168
}
11691169

1170+
/// Subrange type. This is somewhat similar to DISubrange, but it
1171+
/// is also a DIType.
1172+
class DISubrangeType : public DIType {
1173+
public:
1174+
typedef PointerUnion<ConstantInt *, DIVariable *, DIExpression *> BoundType;
1175+
1176+
private:
1177+
friend class LLVMContextImpl;
1178+
friend class MDNode;
1179+
1180+
DISubrangeType(LLVMContext &C, StorageType Storage, unsigned Line,
1181+
uint64_t SizeInBits, uint32_t AlignInBits, DIFlags Flags,
1182+
ArrayRef<Metadata *> Ops);
1183+
1184+
~DISubrangeType() = default;
1185+
1186+
static DISubrangeType *
1187+
getImpl(LLVMContext &Context, StringRef Name, DIFile *File, unsigned Line,
1188+
DIScope *Scope, uint64_t SizeInBits, uint32_t AlignInBits,
1189+
DIFlags Flags, DIType *BaseType, Metadata *LowerBound,
1190+
Metadata *UpperBound, Metadata *Stride, Metadata *Bias,
1191+
StorageType Storage, bool ShouldCreate = true) {
1192+
return getImpl(Context, getCanonicalMDString(Context, Name), File, Line,
1193+
Scope, SizeInBits, AlignInBits, Flags, BaseType, LowerBound,
1194+
UpperBound, Stride, Bias, Storage, ShouldCreate);
1195+
}
1196+
1197+
static DISubrangeType *getImpl(LLVMContext &Context, MDString *Name,
1198+
Metadata *File, unsigned Line, Metadata *Scope,
1199+
uint64_t SizeInBits, uint32_t AlignInBits,
1200+
DIFlags Flags, Metadata *BaseType,
1201+
Metadata *LowerBound, Metadata *UpperBound,
1202+
Metadata *Stride, Metadata *Bias,
1203+
StorageType Storage, bool ShouldCreate = true);
1204+
1205+
TempDISubrangeType cloneImpl() const {
1206+
return getTemporary(getContext(), getName(), getFile(), getLine(),
1207+
getScope(), getSizeInBits(), getAlignInBits(),
1208+
getFlags(), getBaseType(), getRawLowerBound(),
1209+
getRawUpperBound(), getRawStride(), getRawBias());
1210+
}
1211+
1212+
BoundType convertRawToBound(Metadata *IN) const;
1213+
1214+
public:
1215+
DEFINE_MDNODE_GET(DISubrangeType,
1216+
(MDString * Name, Metadata *File, unsigned Line,
1217+
Metadata *Scope, uint64_t SizeInBits, uint32_t AlignInBits,
1218+
DIFlags Flags, Metadata *BaseType, Metadata *LowerBound,
1219+
Metadata *UpperBound, Metadata *Stride, Metadata *Bias),
1220+
(Name, File, Line, Scope, SizeInBits, AlignInBits, Flags,
1221+
BaseType, LowerBound, UpperBound, Stride, Bias))
1222+
DEFINE_MDNODE_GET(DISubrangeType,
1223+
(StringRef Name, DIFile *File, unsigned Line,
1224+
DIScope *Scope, uint64_t SizeInBits, uint32_t AlignInBits,
1225+
DIFlags Flags, DIType *BaseType, Metadata *LowerBound,
1226+
Metadata *UpperBound, Metadata *Stride, Metadata *Bias),
1227+
(Name, File, Line, Scope, SizeInBits, AlignInBits, Flags,
1228+
BaseType, LowerBound, UpperBound, Stride, Bias))
1229+
1230+
TempDISubrangeType clone() const { return cloneImpl(); }
1231+
1232+
/// Get the base type this is derived from.
1233+
DIType *getBaseType() const { return cast_or_null<DIType>(getRawBaseType()); }
1234+
Metadata *getRawBaseType() const { return getOperand(3); }
1235+
1236+
Metadata *getRawLowerBound() const { return getOperand(4).get(); }
1237+
1238+
Metadata *getRawUpperBound() const { return getOperand(5).get(); }
1239+
1240+
Metadata *getRawStride() const { return getOperand(6).get(); }
1241+
1242+
Metadata *getRawBias() const { return getOperand(7).get(); }
1243+
1244+
BoundType getLowerBound() const {
1245+
return convertRawToBound(getRawLowerBound());
1246+
}
1247+
1248+
BoundType getUpperBound() const {
1249+
return convertRawToBound(getRawUpperBound());
1250+
}
1251+
1252+
BoundType getStride() const { return convertRawToBound(getRawStride()); }
1253+
1254+
BoundType getBias() const { return convertRawToBound(getRawBias()); }
1255+
1256+
static bool classof(const Metadata *MD) {
1257+
return MD->getMetadataID() == DISubrangeTypeKind;
1258+
}
1259+
};
1260+
11701261
/// Composite types.
11711262
///
11721263
/// TODO: Detach from DerivedTypeBase (split out MDEnumType?).

llvm/include/llvm/IR/Metadata.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacroFile)
118118
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DICommonBlock)
119119
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIStringType)
120120
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGenericSubrange)
121+
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DISubrangeType)
121122

122123
#undef HANDLE_METADATA
123124
#undef HANDLE_METADATA_LEAF

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5321,6 +5321,50 @@ bool LLParser::parseGenericDINode(MDNode *&Result, bool IsDistinct) {
53215321
return false;
53225322
}
53235323

5324+
/// parseDISubrangeType:
5325+
/// ::= !DISubrangeType(name: "whatever", file: !0,
5326+
/// line: 7, scope: !1, baseType: !2, size: 32,
5327+
/// align: 32, flags: 0, lowerBound: !3
5328+
/// upperBound: !4, stride: !5, bias: !6)
5329+
bool LLParser::parseDISubrangeType(MDNode *&Result, bool IsDistinct) {
5330+
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
5331+
OPTIONAL(name, MDStringField, ); \
5332+
OPTIONAL(file, MDField, ); \
5333+
OPTIONAL(line, LineField, ); \
5334+
OPTIONAL(scope, MDField, ); \
5335+
OPTIONAL(baseType, MDField, ); \
5336+
OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX)); \
5337+
OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \
5338+
OPTIONAL(flags, DIFlagField, ); \
5339+
OPTIONAL(lowerBound, MDSignedOrMDField, ); \
5340+
OPTIONAL(upperBound, MDSignedOrMDField, ); \
5341+
OPTIONAL(stride, MDSignedOrMDField, ); \
5342+
OPTIONAL(bias, MDSignedOrMDField, );
5343+
PARSE_MD_FIELDS();
5344+
#undef VISIT_MD_FIELDS
5345+
5346+
auto convToMetadata = [&](MDSignedOrMDField Bound) -> Metadata * {
5347+
if (Bound.isMDSignedField())
5348+
return ConstantAsMetadata::get(ConstantInt::getSigned(
5349+
Type::getInt64Ty(Context), Bound.getMDSignedValue()));
5350+
if (Bound.isMDField())
5351+
return Bound.getMDFieldValue();
5352+
return nullptr;
5353+
};
5354+
5355+
Metadata *LowerBound = convToMetadata(lowerBound);
5356+
Metadata *UpperBound = convToMetadata(upperBound);
5357+
Metadata *Stride = convToMetadata(stride);
5358+
Metadata *Bias = convToMetadata(bias);
5359+
5360+
Result = GET_OR_DISTINCT(DISubrangeType,
5361+
(Context, name.Val, file.Val, line.Val, scope.Val,
5362+
size.Val, align.Val, flags.Val, baseType.Val,
5363+
LowerBound, UpperBound, Stride, Bias));
5364+
5365+
return false;
5366+
}
5367+
53245368
/// parseDISubrange:
53255369
/// ::= !DISubrange(count: 30, lowerBound: 2)
53265370
/// ::= !DISubrange(count: !node, lowerBound: 2)

llvm/lib/Bitcode/Reader/MetadataLoader.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1599,6 +1599,24 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
15991599
NextMetadataNo++;
16001600
break;
16011601
}
1602+
case bitc::METADATA_SUBRANGE_TYPE: {
1603+
if (Record.size() != 13)
1604+
return error("Invalid record");
1605+
1606+
IsDistinct = Record[0];
1607+
DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[7]);
1608+
MetadataList.assignValue(
1609+
GET_OR_DISTINCT(DISubrangeType,
1610+
(Context, getMDString(Record[1]),
1611+
getMDOrNull(Record[2]), Record[3],
1612+
getMDOrNull(Record[4]), Record[5], Record[6], Flags,
1613+
getDITypeRefOrNull(Record[8]), getMDOrNull(Record[9]),
1614+
getMDOrNull(Record[10]), getMDOrNull(Record[11]),
1615+
getMDOrNull(Record[12]))),
1616+
NextMetadataNo);
1617+
NextMetadataNo++;
1618+
break;
1619+
}
16021620
case bitc::METADATA_COMPOSITE_TYPE: {
16031621
if (Record.size() < 16 || Record.size() > 25)
16041622
return error("Invalid record");

llvm/lib/Bitcode/Writer/BitcodeWriter.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,8 @@ class ModuleBitcodeWriter : public ModuleBitcodeWriterBase {
327327
SmallVectorImpl<uint64_t> &Record, unsigned Abbrev);
328328
void writeDIDerivedType(const DIDerivedType *N,
329329
SmallVectorImpl<uint64_t> &Record, unsigned Abbrev);
330+
void writeDISubrangeType(const DISubrangeType *N,
331+
SmallVectorImpl<uint64_t> &Record, unsigned Abbrev);
330332
void writeDICompositeType(const DICompositeType *N,
331333
SmallVectorImpl<uint64_t> &Record, unsigned Abbrev);
332334
void writeDISubroutineType(const DISubroutineType *N,
@@ -1937,6 +1939,27 @@ void ModuleBitcodeWriter::writeDIDerivedType(const DIDerivedType *N,
19371939
Record.clear();
19381940
}
19391941

1942+
void ModuleBitcodeWriter::writeDISubrangeType(const DISubrangeType *N,
1943+
SmallVectorImpl<uint64_t> &Record,
1944+
unsigned Abbrev) {
1945+
Record.push_back(N->isDistinct());
1946+
Record.push_back(VE.getMetadataOrNullID(N->getRawName()));
1947+
Record.push_back(VE.getMetadataOrNullID(N->getFile()));
1948+
Record.push_back(N->getLine());
1949+
Record.push_back(VE.getMetadataOrNullID(N->getScope()));
1950+
Record.push_back(N->getSizeInBits());
1951+
Record.push_back(N->getAlignInBits());
1952+
Record.push_back(N->getFlags());
1953+
Record.push_back(VE.getMetadataOrNullID(N->getBaseType()));
1954+
Record.push_back(VE.getMetadataOrNullID(N->getRawLowerBound()));
1955+
Record.push_back(VE.getMetadataOrNullID(N->getRawUpperBound()));
1956+
Record.push_back(VE.getMetadataOrNullID(N->getRawStride()));
1957+
Record.push_back(VE.getMetadataOrNullID(N->getRawBias()));
1958+
1959+
Stream.EmitRecord(bitc::METADATA_SUBRANGE_TYPE, Record, Abbrev);
1960+
Record.clear();
1961+
}
1962+
19401963
void ModuleBitcodeWriter::writeDICompositeType(
19411964
const DICompositeType *N, SmallVectorImpl<uint64_t> &Record,
19421965
unsigned Abbrev) {

llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -148,20 +148,21 @@ MCSymbol *DebugHandlerBase::getLabelAfterInsn(const MachineInstr *MI) {
148148
/// If this type is derived from a base type then return base type size.
149149
uint64_t DebugHandlerBase::getBaseTypeSize(const DIType *Ty) {
150150
assert(Ty);
151-
const DIDerivedType *DDTy = dyn_cast<DIDerivedType>(Ty);
152-
if (!DDTy)
153-
return Ty->getSizeInBits();
154151

155-
unsigned Tag = DDTy->getTag();
152+
unsigned Tag = Ty->getTag();
156153

157154
if (Tag != dwarf::DW_TAG_member && Tag != dwarf::DW_TAG_typedef &&
158155
Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type &&
159156
Tag != dwarf::DW_TAG_restrict_type && Tag != dwarf::DW_TAG_atomic_type &&
160157
Tag != dwarf::DW_TAG_immutable_type &&
161158
Tag != dwarf::DW_TAG_template_alias)
162-
return DDTy->getSizeInBits();
159+
return Ty->getSizeInBits();
163160

164-
DIType *BaseType = DDTy->getBaseType();
161+
DIType *BaseType = nullptr;
162+
if (const DIDerivedType *DDTy = dyn_cast<DIDerivedType>(Ty))
163+
BaseType = DDTy->getBaseType();
164+
else if (const DISubrangeType *SRTy = dyn_cast<DISubrangeType>(Ty))
165+
BaseType = SRTy->getBaseType();
165166

166167
if (!BaseType)
167168
return 0;
@@ -187,6 +188,12 @@ bool DebugHandlerBase::isUnsignedDIType(const DIType *Ty) {
187188
return true;
188189
}
189190

191+
if (auto *SRTy = dyn_cast<DISubrangeType>(Ty)) {
192+
Ty = SRTy->getBaseType();
193+
if (!Ty)
194+
return false;
195+
}
196+
190197
if (auto *CTy = dyn_cast<DICompositeType>(Ty)) {
191198
if (CTy->getTag() == dwarf::DW_TAG_enumeration_type) {
192199
if (!(Ty = CTy->getBaseType()))

0 commit comments

Comments
 (0)