Skip to content

Add support for fixed-point types #129596

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

Merged
merged 1 commit into from
Mar 31, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6210,6 +6210,35 @@ following:
DW_ATE_unsigned = 7
DW_ATE_unsigned_char = 8

.. _DIFixedPointType:

DIFixedPointType
""""""""""""""""

``DIFixedPointType`` nodes represent fixed-point types. A fixed-point
type is conceptually an integer with a scale factor.
``DIFixedPointType`` is derived from ``DIBasicType`` and inherits its
attributes. However, only certain encodings are accepted:

.. code-block:: text

DW_ATE_signed_fixed = 13
DW_ATE_unsigned_fixed = 14

There are three kinds of fixed-point type: binary, where the scale
factor is a power of 2; decimal, where the scale factor is a power of
10; and rational, where the scale factor is an arbitrary rational
number.

.. code-block:: text

!0 = !DIFixedPointType(name: "decimal", size: 8, encoding: DW_ATE_signed_fixed,
kind: Decimal, factor: -4)
!1 = !DIFixedPointType(name: "binary", size: 8, encoding: DW_ATE_unsigned_fixed,
kind: Binary, factor: -16)
!2 = !DIFixedPointType(name: "rational", size: 8, encoding: DW_ATE_signed_fixed,
kind: Rational, numerator: 1234, denominator: 5678)

.. _DISubroutineType:

DISubroutineType
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm-c/DebugInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ enum {
LLVMDISubrangeMetadataKind,
LLVMDIEnumeratorMetadataKind,
LLVMDIBasicTypeMetadataKind,
LLVMDIFixedPointTypeMetadataKind,
LLVMDIDerivedTypeMetadataKind,
LLVMDISubrangeTypeMetadataKind,
LLVMDICompositeTypeMetadataKind,
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/AsmParser/LLToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,7 @@ enum Kind {
DwarfCC, // DW_CC_foo
EmissionKind, // lineTablesOnly
NameTableKind, // GNU
FixedPointKind, // Fixed point
DwarfOp, // DW_OP_foo
DIFlag, // DIFlagFoo
DISPFlag, // DISPFlagFoo
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 @@ -386,6 +386,7 @@ enum MetadataCodes {
METADATA_ARG_LIST = 46, // [n x [type num, value num]]
METADATA_ASSIGN_ID = 47, // [distinct, ...]
METADATA_SUBRANGE_TYPE = 48, // [distinct, ...]
METADATA_FIXED_POINT_TYPE = 49, // [distinct, ...]
};

// The constants block (CONSTANTS_BLOCK_ID) describes emission for each
Expand Down
36 changes: 36 additions & 0 deletions llvm/include/llvm/IR/DIBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,42 @@ namespace llvm {
DINode::DIFlags Flags = DINode::FlagZero,
uint32_t NumExtraInhabitants = 0);

/// Create debugging information entry for a binary fixed-point type.
/// \param Name Type name.
/// \param Encoding DWARF encoding code, either
/// dwarf::DW_ATE_signed_fixed or DW_ATE_unsigned_fixed.
/// \param Flags Optional DWARF attributes, e.g., DW_AT_endianity.
/// \param Factor Binary scale factor.
DIFixedPointType *
createBinaryFixedPointType(StringRef Name, uint64_t SizeInBits,
uint32_t AlignInBits, unsigned Encoding,
DINode::DIFlags Flags, int Factor);

/// Create debugging information entry for a decimal fixed-point type.
/// \param Name Type name.
/// \param Encoding DWARF encoding code, either
/// dwarf::DW_ATE_signed_fixed or DW_ATE_unsigned_fixed.
/// \param Flags Optional DWARF attributes, e.g., DW_AT_endianity.
/// \param Factor Decimal scale factor.
DIFixedPointType *
createDecimalFixedPointType(StringRef Name, uint64_t SizeInBits,
uint32_t AlignInBits, unsigned Encoding,
DINode::DIFlags Flags, int Factor);

/// Create debugging information entry for an arbitrary rational
/// fixed-point type.
/// \param Name Type name.
/// \param Encoding DWARF encoding code, either
/// dwarf::DW_ATE_signed_fixed or DW_ATE_unsigned_fixed.
/// \param Flags Optional DWARF attributes, e.g., DW_AT_endianity.
/// \param Numerator Numerator of scale factor.
/// \param Denominator Denominator of scale factor.
DIFixedPointType *
createRationalFixedPointType(StringRef Name, uint64_t SizeInBits,
uint32_t AlignInBits, unsigned Encoding,
DINode::DIFlags Flags, APInt Numerator,
APInt Denominator);

/// Create debugging information entry for a string
/// type.
/// \param Name Type name.
Expand Down
138 changes: 137 additions & 1 deletion llvm/include/llvm/IR/DebugInfoMetadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ class DINode : public MDNode {
case DISubrangeKind:
case DIEnumeratorKind:
case DIBasicTypeKind:
case DIFixedPointTypeKind:
case DIStringTypeKind:
case DISubrangeTypeKind:
case DIDerivedTypeKind:
Expand Down Expand Up @@ -547,6 +548,7 @@ class DIScope : public DINode {
default:
return false;
case DIBasicTypeKind:
case DIFixedPointTypeKind:
case DIStringTypeKind:
case DISubrangeTypeKind:
case DIDerivedTypeKind:
Expand Down Expand Up @@ -806,6 +808,7 @@ class DIType : public DIScope {
default:
return false;
case DIBasicTypeKind:
case DIFixedPointTypeKind:
case DIStringTypeKind:
case DISubrangeTypeKind:
case DIDerivedTypeKind:
Expand All @@ -826,13 +829,21 @@ class DIBasicType : public DIType {

unsigned Encoding;

protected:
DIBasicType(LLVMContext &C, StorageType Storage, unsigned Tag,
uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding,
uint32_t NumExtraInhabitants, DIFlags Flags,
ArrayRef<Metadata *> Ops)
: DIType(C, DIBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0,
NumExtraInhabitants, Flags, Ops),
Encoding(Encoding) {}
DIBasicType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding,
uint32_t NumExtraInhabitants, DIFlags Flags,
ArrayRef<Metadata *> Ops)
: DIType(C, ID, Storage, Tag, 0, SizeInBits, AlignInBits, 0,
NumExtraInhabitants, Flags, Ops),
Encoding(Encoding) {}
~DIBasicType() = default;

static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag,
Expand Down Expand Up @@ -897,7 +908,132 @@ class DIBasicType : public DIType {
std::optional<Signedness> getSignedness() const;

static bool classof(const Metadata *MD) {
return MD->getMetadataID() == DIBasicTypeKind;
return MD->getMetadataID() == DIBasicTypeKind ||
MD->getMetadataID() == DIFixedPointTypeKind;
}
};

/// Fixed-point type.
class DIFixedPointType : public DIBasicType {
friend class LLVMContextImpl;
friend class MDNode;

// Actually FixedPointKind.
unsigned Kind;
// Used for binary and decimal.
int Factor;
// Used for rational.
APInt Numerator;
APInt Denominator;

DIFixedPointType(LLVMContext &C, StorageType Storage, unsigned Tag,
uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding,
DIFlags Flags, unsigned Kind, int Factor,
ArrayRef<Metadata *> Ops)
: DIBasicType(C, DIFixedPointTypeKind, Storage, Tag, SizeInBits,
AlignInBits, Encoding, 0, Flags, Ops),
Kind(Kind), Factor(Factor) {
assert(Kind == FixedPointBinary || Kind == FixedPointDecimal);
}
DIFixedPointType(LLVMContext &C, StorageType Storage, unsigned Tag,
uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding,
DIFlags Flags, unsigned Kind, APInt Numerator,
APInt Denominator, ArrayRef<Metadata *> Ops)
: DIBasicType(C, DIFixedPointTypeKind, Storage, Tag, SizeInBits,
AlignInBits, Encoding, 0, Flags, Ops),
Kind(Kind), Factor(0), Numerator(Numerator), Denominator(Denominator) {
assert(Kind == FixedPointRational);
}
DIFixedPointType(LLVMContext &C, StorageType Storage, unsigned Tag,
uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding,
DIFlags Flags, unsigned Kind, int Factor, APInt Numerator,
APInt Denominator, ArrayRef<Metadata *> Ops)
: DIBasicType(C, DIFixedPointTypeKind, Storage, Tag, SizeInBits,
AlignInBits, Encoding, 0, Flags, Ops),
Kind(Kind), Factor(Factor), Numerator(Numerator),
Denominator(Denominator) {}
~DIFixedPointType() = default;

static DIFixedPointType *
getImpl(LLVMContext &Context, unsigned Tag, StringRef Name,
uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding,
DIFlags Flags, unsigned Kind, int Factor, APInt Numerator,
APInt Denominator, StorageType Storage, bool ShouldCreate = true) {
return getImpl(Context, Tag, getCanonicalMDString(Context, Name),
SizeInBits, AlignInBits, Encoding, Flags, Kind, Factor,
Numerator, Denominator, Storage, ShouldCreate);
}
static DIFixedPointType *
getImpl(LLVMContext &Context, unsigned Tag, MDString *Name,
uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding,
DIFlags Flags, unsigned Kind, int Factor, APInt Numerator,
APInt Denominator, StorageType Storage, bool ShouldCreate = true);

TempDIFixedPointType cloneImpl() const {
return getTemporary(getContext(), getTag(), getName(), getSizeInBits(),
getAlignInBits(), getEncoding(), getFlags(), Kind,
Factor, Numerator, Denominator);
}

public:
enum FixedPointKind : unsigned {
/// Scale factor 2^Factor.
FixedPointBinary,
/// Scale factor 10^Factor.
FixedPointDecimal,
/// Arbitrary rational scale factor.
FixedPointRational,
LastFixedPointKind = FixedPointRational,
};

static std::optional<FixedPointKind> getFixedPointKind(StringRef Str);
static const char *fixedPointKindString(FixedPointKind);

DEFINE_MDNODE_GET(DIFixedPointType,
(unsigned Tag, MDString *Name, uint64_t SizeInBits,
uint32_t AlignInBits, unsigned Encoding, DIFlags Flags,
unsigned Kind, int Factor, APInt Numerator,
APInt Denominator),
(Tag, Name, SizeInBits, AlignInBits, Encoding, Flags, Kind,
Factor, Numerator, Denominator))
DEFINE_MDNODE_GET(DIFixedPointType,
(unsigned Tag, StringRef Name, uint64_t SizeInBits,
uint32_t AlignInBits, unsigned Encoding, DIFlags Flags,
unsigned Kind, int Factor, APInt Numerator,
APInt Denominator),
(Tag, Name, SizeInBits, AlignInBits, Encoding, Flags, Kind,
Factor, Numerator, Denominator))

TempDIFixedPointType clone() const { return cloneImpl(); }

bool isBinary() const { return Kind == FixedPointBinary; }
bool isDecimal() const { return Kind == FixedPointDecimal; }
bool isRational() const { return Kind == FixedPointRational; }

bool isSigned() const;

FixedPointKind getKind() const { return static_cast<FixedPointKind>(Kind); }

int getFactorRaw() const { return Factor; }
int getFactor() const {
assert(Kind == FixedPointBinary || Kind == FixedPointDecimal);
return Factor;
}

const APInt &getNumeratorRaw() const { return Numerator; }
const APInt &getNumerator() const {
assert(Kind == FixedPointRational);
return Numerator;
}

const APInt &getDenominatorRaw() const { return Denominator; }
const APInt &getDenominator() const {
assert(Kind == FixedPointRational);
return Denominator;
}

static bool classof(const Metadata *MD) {
return MD->getMetadataID() == DIFixedPointTypeKind;
}
};

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 @@ -119,6 +119,7 @@ HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DICommonBlock)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIStringType)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGenericSubrange)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DISubrangeType)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIFixedPointType)

#undef HANDLE_METADATA
#undef HANDLE_METADATA_LEAF
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/AsmParser/LLLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1024,6 +1024,11 @@ lltok::Kind LLLexer::LexIdentifier() {
return lltok::NameTableKind;
}

if (Keyword == "Binary" || Keyword == "Decimal" || Keyword == "Rational") {
StrVal.assign(Keyword.begin(), Keyword.end());
return lltok::FixedPointKind;
}

// Check for [us]0x[0-9A-Fa-f]+ which are Hexadecimal constant generated by
// the CFE to avoid forcing it to deal with 64-bit numbers.
if ((TokStart[0] == 'u' || TokStart[0] == 's') &&
Expand Down
51 changes: 51 additions & 0 deletions llvm/lib/AsmParser/LLParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4750,6 +4750,11 @@ struct EmissionKindField : public MDUnsignedField {
EmissionKindField() : MDUnsignedField(0, DICompileUnit::LastEmissionKind) {}
};

struct FixedPointKindField : public MDUnsignedField {
FixedPointKindField()
: MDUnsignedField(0, DIFixedPointType::LastFixedPointKind) {}
};

struct NameTableKindField : public MDUnsignedField {
NameTableKindField()
: MDUnsignedField(
Expand Down Expand Up @@ -4993,6 +4998,25 @@ bool LLParser::parseMDField(LocTy Loc, StringRef Name,
return false;
}

template <>
bool LLParser::parseMDField(LocTy Loc, StringRef Name,
FixedPointKindField &Result) {
if (Lex.getKind() == lltok::APSInt)
return parseMDField(Loc, Name, static_cast<MDUnsignedField &>(Result));

if (Lex.getKind() != lltok::FixedPointKind)
return tokError("expected fixed-point kind");

auto Kind = DIFixedPointType::getFixedPointKind(Lex.getStrVal());
if (!Kind)
return tokError("invalid fixed-point kind" + Twine(" '") + Lex.getStrVal() +
"'");
assert(*Kind <= Result.Max && "Expected valid fixed-point kind");
Result.assign(*Kind);
Lex.Lex();
return false;
}

template <>
bool LLParser::parseMDField(LocTy Loc, StringRef Name,
NameTableKindField &Result) {
Expand Down Expand Up @@ -5515,6 +5539,33 @@ bool LLParser::parseDIBasicType(MDNode *&Result, bool IsDistinct) {
return false;
}

/// parseDIFixedPointType:
/// ::= !DIFixedPointType(tag: DW_TAG_base_type, name: "xyz", size: 32,
/// align: 32, encoding: DW_ATE_signed_fixed,
/// flags: 0, kind: Rational, factor: 3, numerator: 1,
/// denominator: 8)
bool LLParser::parseDIFixedPointType(MDNode *&Result, bool IsDistinct) {
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
OPTIONAL(tag, DwarfTagField, (dwarf::DW_TAG_base_type)); \
OPTIONAL(name, MDStringField, ); \
OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX)); \
OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \
OPTIONAL(encoding, DwarfAttEncodingField, ); \
OPTIONAL(flags, DIFlagField, ); \
OPTIONAL(kind, FixedPointKindField, ); \
OPTIONAL(factor, MDSignedField, ); \
OPTIONAL(numerator, MDAPSIntField, ); \
OPTIONAL(denominator, MDAPSIntField, );
PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS

Result = GET_OR_DISTINCT(DIFixedPointType,
(Context, tag.Val, name.Val, size.Val, align.Val,
encoding.Val, flags.Val, kind.Val, factor.Val,
numerator.Val, denominator.Val));
return false;
}

/// parseDIStringType:
/// ::= !DIStringType(name: "character(4)", size: 32, align: 32)
bool LLParser::parseDIStringType(MDNode *&Result, bool IsDistinct) {
Expand Down
Loading