Skip to content

Commit

Permalink
Add DISubrangeType
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
tromey committed Feb 12, 2025
1 parent 36fba1c commit bf4cb17
Show file tree
Hide file tree
Showing 18 changed files with 511 additions and 7 deletions.
1 change: 1 addition & 0 deletions llvm/include/llvm-c/DebugInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ enum {
LLVMDIEnumeratorMetadataKind,
LLVMDIBasicTypeMetadataKind,
LLVMDIDerivedTypeMetadataKind,
LLVMDISubrangeTypeMetadataKind,
LLVMDICompositeTypeMetadataKind,
LLVMDISubroutineTypeMetadataKind,
LLVMDIFileMetadataKind,
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/Bitcode/LLVMBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
20 changes: 20 additions & 0 deletions llvm/include/llvm/IR/DIBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
97 changes: 94 additions & 3 deletions llvm/include/llvm/IR/DebugInfoMetadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ class DINode : public MDNode {
case DIEnumeratorKind:
case DIBasicTypeKind:
case DIStringTypeKind:
case DISubrangeTypeKind:
case DIDerivedTypeKind:
case DICompositeTypeKind:
case DISubroutineTypeKind:
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -550,6 +548,7 @@ class DIScope : public DINode {
return false;
case DIBasicTypeKind:
case DIStringTypeKind:
case DISubrangeTypeKind:
case DIDerivedTypeKind:
case DICompositeTypeKind:
case DISubroutineTypeKind:
Expand Down Expand Up @@ -808,6 +807,7 @@ class DIType : public DIScope {
return false;
case DIBasicTypeKind:
case DIStringTypeKind:
case DISubrangeTypeKind:
case DIDerivedTypeKind:
case DICompositeTypeKind:
case DISubroutineTypeKind:
Expand Down Expand Up @@ -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?).
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/IR/Metadata.def
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
44 changes: 44 additions & 0 deletions llvm/lib/AsmParser/LLParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
18 changes: 18 additions & 0 deletions llvm/lib/Bitcode/Reader/MetadataLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
23 changes: 23 additions & 0 deletions llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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) {
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ uint64_t DebugHandlerBase::getBaseTypeSize(const DIType *Ty) {
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;
Expand All @@ -186,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()))
Expand Down
Loading

0 comments on commit bf4cb17

Please sign in to comment.