Skip to content

Commit 6894734

Browse files
authored
Add support for fixed-point types (#129596)
This adds DWARF generation for fixed-point types. This feature is needed by Ada. Note that a pre-existing GNU extension is used in one case. This has been emitted by GCC for years, and is needed because standard DWARF is otherwise incapable of representing these types.
1 parent 4007de0 commit 6894734

File tree

20 files changed

+577
-2
lines changed

20 files changed

+577
-2
lines changed

llvm/docs/LangRef.rst

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6212,6 +6212,35 @@ following:
62126212
DW_ATE_unsigned = 7
62136213
DW_ATE_unsigned_char = 8
62146214

6215+
.. _DIFixedPointType:
6216+
6217+
DIFixedPointType
6218+
""""""""""""""""
6219+
6220+
``DIFixedPointType`` nodes represent fixed-point types. A fixed-point
6221+
type is conceptually an integer with a scale factor.
6222+
``DIFixedPointType`` is derived from ``DIBasicType`` and inherits its
6223+
attributes. However, only certain encodings are accepted:
6224+
6225+
.. code-block:: text
6226+
6227+
DW_ATE_signed_fixed = 13
6228+
DW_ATE_unsigned_fixed = 14
6229+
6230+
There are three kinds of fixed-point type: binary, where the scale
6231+
factor is a power of 2; decimal, where the scale factor is a power of
6232+
10; and rational, where the scale factor is an arbitrary rational
6233+
number.
6234+
6235+
.. code-block:: text
6236+
6237+
!0 = !DIFixedPointType(name: "decimal", size: 8, encoding: DW_ATE_signed_fixed,
6238+
kind: Decimal, factor: -4)
6239+
!1 = !DIFixedPointType(name: "binary", size: 8, encoding: DW_ATE_unsigned_fixed,
6240+
kind: Binary, factor: -16)
6241+
!2 = !DIFixedPointType(name: "rational", size: 8, encoding: DW_ATE_signed_fixed,
6242+
kind: Rational, numerator: 1234, denominator: 5678)
6243+
62156244
.. _DISubroutineType:
62166245

62176246
DISubroutineType

llvm/include/llvm-c/DebugInfo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ enum {
173173
LLVMDISubrangeMetadataKind,
174174
LLVMDIEnumeratorMetadataKind,
175175
LLVMDIBasicTypeMetadataKind,
176+
LLVMDIFixedPointTypeMetadataKind,
176177
LLVMDIDerivedTypeMetadataKind,
177178
LLVMDICompositeTypeMetadataKind,
178179
LLVMDISubroutineTypeMetadataKind,

llvm/include/llvm/AsmParser/LLToken.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,7 @@ enum Kind {
494494
DwarfCC, // DW_CC_foo
495495
EmissionKind, // lineTablesOnly
496496
NameTableKind, // GNU
497+
FixedPointKind, // Fixed point
497498
DwarfOp, // DW_OP_foo
498499
DIFlag, // DIFlagFoo
499500
DISPFlag, // DISPFlagFoo

llvm/include/llvm/Bitcode/LLVMBitCodes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ enum MetadataCodes {
386386
METADATA_ARG_LIST = 46, // [n x [type num, value num]]
387387
METADATA_ASSIGN_ID = 47, // [distinct, ...]
388388
METADATA_SUBRANGE_TYPE = 48, // [distinct, ...]
389+
METADATA_FIXED_POINT_TYPE = 49, // [distinct, ...]
389390
};
390391

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

llvm/include/llvm/IR/DIBuilder.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,42 @@ namespace llvm {
215215
DINode::DIFlags Flags = DINode::FlagZero,
216216
uint32_t NumExtraInhabitants = 0);
217217

218+
/// Create debugging information entry for a binary fixed-point type.
219+
/// \param Name Type name.
220+
/// \param Encoding DWARF encoding code, either
221+
/// dwarf::DW_ATE_signed_fixed or DW_ATE_unsigned_fixed.
222+
/// \param Flags Optional DWARF attributes, e.g., DW_AT_endianity.
223+
/// \param Factor Binary scale factor.
224+
DIFixedPointType *
225+
createBinaryFixedPointType(StringRef Name, uint64_t SizeInBits,
226+
uint32_t AlignInBits, unsigned Encoding,
227+
DINode::DIFlags Flags, int Factor);
228+
229+
/// Create debugging information entry for a decimal fixed-point type.
230+
/// \param Name Type name.
231+
/// \param Encoding DWARF encoding code, either
232+
/// dwarf::DW_ATE_signed_fixed or DW_ATE_unsigned_fixed.
233+
/// \param Flags Optional DWARF attributes, e.g., DW_AT_endianity.
234+
/// \param Factor Decimal scale factor.
235+
DIFixedPointType *
236+
createDecimalFixedPointType(StringRef Name, uint64_t SizeInBits,
237+
uint32_t AlignInBits, unsigned Encoding,
238+
DINode::DIFlags Flags, int Factor);
239+
240+
/// Create debugging information entry for an arbitrary rational
241+
/// fixed-point type.
242+
/// \param Name Type name.
243+
/// \param Encoding DWARF encoding code, either
244+
/// dwarf::DW_ATE_signed_fixed or DW_ATE_unsigned_fixed.
245+
/// \param Flags Optional DWARF attributes, e.g., DW_AT_endianity.
246+
/// \param Numerator Numerator of scale factor.
247+
/// \param Denominator Denominator of scale factor.
248+
DIFixedPointType *
249+
createRationalFixedPointType(StringRef Name, uint64_t SizeInBits,
250+
uint32_t AlignInBits, unsigned Encoding,
251+
DINode::DIFlags Flags, APInt Numerator,
252+
APInt Denominator);
253+
218254
/// Create debugging information entry for a string
219255
/// type.
220256
/// \param Name Type name.

llvm/include/llvm/IR/DebugInfoMetadata.h

Lines changed: 137 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ class DINode : public MDNode {
199199
case DISubrangeKind:
200200
case DIEnumeratorKind:
201201
case DIBasicTypeKind:
202+
case DIFixedPointTypeKind:
202203
case DIStringTypeKind:
203204
case DISubrangeTypeKind:
204205
case DIDerivedTypeKind:
@@ -547,6 +548,7 @@ class DIScope : public DINode {
547548
default:
548549
return false;
549550
case DIBasicTypeKind:
551+
case DIFixedPointTypeKind:
550552
case DIStringTypeKind:
551553
case DISubrangeTypeKind:
552554
case DIDerivedTypeKind:
@@ -806,6 +808,7 @@ class DIType : public DIScope {
806808
default:
807809
return false;
808810
case DIBasicTypeKind:
811+
case DIFixedPointTypeKind:
809812
case DIStringTypeKind:
810813
case DISubrangeTypeKind:
811814
case DIDerivedTypeKind:
@@ -826,13 +829,21 @@ class DIBasicType : public DIType {
826829

827830
unsigned Encoding;
828831

832+
protected:
829833
DIBasicType(LLVMContext &C, StorageType Storage, unsigned Tag,
830834
uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding,
831835
uint32_t NumExtraInhabitants, DIFlags Flags,
832836
ArrayRef<Metadata *> Ops)
833837
: DIType(C, DIBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0,
834838
NumExtraInhabitants, Flags, Ops),
835839
Encoding(Encoding) {}
840+
DIBasicType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
841+
uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding,
842+
uint32_t NumExtraInhabitants, DIFlags Flags,
843+
ArrayRef<Metadata *> Ops)
844+
: DIType(C, ID, Storage, Tag, 0, SizeInBits, AlignInBits, 0,
845+
NumExtraInhabitants, Flags, Ops),
846+
Encoding(Encoding) {}
836847
~DIBasicType() = default;
837848

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

899910
static bool classof(const Metadata *MD) {
900-
return MD->getMetadataID() == DIBasicTypeKind;
911+
return MD->getMetadataID() == DIBasicTypeKind ||
912+
MD->getMetadataID() == DIFixedPointTypeKind;
913+
}
914+
};
915+
916+
/// Fixed-point type.
917+
class DIFixedPointType : public DIBasicType {
918+
friend class LLVMContextImpl;
919+
friend class MDNode;
920+
921+
// Actually FixedPointKind.
922+
unsigned Kind;
923+
// Used for binary and decimal.
924+
int Factor;
925+
// Used for rational.
926+
APInt Numerator;
927+
APInt Denominator;
928+
929+
DIFixedPointType(LLVMContext &C, StorageType Storage, unsigned Tag,
930+
uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding,
931+
DIFlags Flags, unsigned Kind, int Factor,
932+
ArrayRef<Metadata *> Ops)
933+
: DIBasicType(C, DIFixedPointTypeKind, Storage, Tag, SizeInBits,
934+
AlignInBits, Encoding, 0, Flags, Ops),
935+
Kind(Kind), Factor(Factor) {
936+
assert(Kind == FixedPointBinary || Kind == FixedPointDecimal);
937+
}
938+
DIFixedPointType(LLVMContext &C, StorageType Storage, unsigned Tag,
939+
uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding,
940+
DIFlags Flags, unsigned Kind, APInt Numerator,
941+
APInt Denominator, ArrayRef<Metadata *> Ops)
942+
: DIBasicType(C, DIFixedPointTypeKind, Storage, Tag, SizeInBits,
943+
AlignInBits, Encoding, 0, Flags, Ops),
944+
Kind(Kind), Factor(0), Numerator(Numerator), Denominator(Denominator) {
945+
assert(Kind == FixedPointRational);
946+
}
947+
DIFixedPointType(LLVMContext &C, StorageType Storage, unsigned Tag,
948+
uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding,
949+
DIFlags Flags, unsigned Kind, int Factor, APInt Numerator,
950+
APInt Denominator, ArrayRef<Metadata *> Ops)
951+
: DIBasicType(C, DIFixedPointTypeKind, Storage, Tag, SizeInBits,
952+
AlignInBits, Encoding, 0, Flags, Ops),
953+
Kind(Kind), Factor(Factor), Numerator(Numerator),
954+
Denominator(Denominator) {}
955+
~DIFixedPointType() = default;
956+
957+
static DIFixedPointType *
958+
getImpl(LLVMContext &Context, unsigned Tag, StringRef Name,
959+
uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding,
960+
DIFlags Flags, unsigned Kind, int Factor, APInt Numerator,
961+
APInt Denominator, StorageType Storage, bool ShouldCreate = true) {
962+
return getImpl(Context, Tag, getCanonicalMDString(Context, Name),
963+
SizeInBits, AlignInBits, Encoding, Flags, Kind, Factor,
964+
Numerator, Denominator, Storage, ShouldCreate);
965+
}
966+
static DIFixedPointType *
967+
getImpl(LLVMContext &Context, unsigned Tag, MDString *Name,
968+
uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding,
969+
DIFlags Flags, unsigned Kind, int Factor, APInt Numerator,
970+
APInt Denominator, StorageType Storage, bool ShouldCreate = true);
971+
972+
TempDIFixedPointType cloneImpl() const {
973+
return getTemporary(getContext(), getTag(), getName(), getSizeInBits(),
974+
getAlignInBits(), getEncoding(), getFlags(), Kind,
975+
Factor, Numerator, Denominator);
976+
}
977+
978+
public:
979+
enum FixedPointKind : unsigned {
980+
/// Scale factor 2^Factor.
981+
FixedPointBinary,
982+
/// Scale factor 10^Factor.
983+
FixedPointDecimal,
984+
/// Arbitrary rational scale factor.
985+
FixedPointRational,
986+
LastFixedPointKind = FixedPointRational,
987+
};
988+
989+
static std::optional<FixedPointKind> getFixedPointKind(StringRef Str);
990+
static const char *fixedPointKindString(FixedPointKind);
991+
992+
DEFINE_MDNODE_GET(DIFixedPointType,
993+
(unsigned Tag, MDString *Name, uint64_t SizeInBits,
994+
uint32_t AlignInBits, unsigned Encoding, DIFlags Flags,
995+
unsigned Kind, int Factor, APInt Numerator,
996+
APInt Denominator),
997+
(Tag, Name, SizeInBits, AlignInBits, Encoding, Flags, Kind,
998+
Factor, Numerator, Denominator))
999+
DEFINE_MDNODE_GET(DIFixedPointType,
1000+
(unsigned Tag, StringRef Name, uint64_t SizeInBits,
1001+
uint32_t AlignInBits, unsigned Encoding, DIFlags Flags,
1002+
unsigned Kind, int Factor, APInt Numerator,
1003+
APInt Denominator),
1004+
(Tag, Name, SizeInBits, AlignInBits, Encoding, Flags, Kind,
1005+
Factor, Numerator, Denominator))
1006+
1007+
TempDIFixedPointType clone() const { return cloneImpl(); }
1008+
1009+
bool isBinary() const { return Kind == FixedPointBinary; }
1010+
bool isDecimal() const { return Kind == FixedPointDecimal; }
1011+
bool isRational() const { return Kind == FixedPointRational; }
1012+
1013+
bool isSigned() const;
1014+
1015+
FixedPointKind getKind() const { return static_cast<FixedPointKind>(Kind); }
1016+
1017+
int getFactorRaw() const { return Factor; }
1018+
int getFactor() const {
1019+
assert(Kind == FixedPointBinary || Kind == FixedPointDecimal);
1020+
return Factor;
1021+
}
1022+
1023+
const APInt &getNumeratorRaw() const { return Numerator; }
1024+
const APInt &getNumerator() const {
1025+
assert(Kind == FixedPointRational);
1026+
return Numerator;
1027+
}
1028+
1029+
const APInt &getDenominatorRaw() const { return Denominator; }
1030+
const APInt &getDenominator() const {
1031+
assert(Kind == FixedPointRational);
1032+
return Denominator;
1033+
}
1034+
1035+
static bool classof(const Metadata *MD) {
1036+
return MD->getMetadataID() == DIFixedPointTypeKind;
9011037
}
9021038
};
9031039

llvm/include/llvm/IR/Metadata.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DICommonBlock)
119119
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIStringType)
120120
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGenericSubrange)
121121
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DISubrangeType)
122+
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIFixedPointType)
122123

123124
#undef HANDLE_METADATA
124125
#undef HANDLE_METADATA_LEAF

llvm/lib/AsmParser/LLLexer.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,6 +1024,11 @@ lltok::Kind LLLexer::LexIdentifier() {
10241024
return lltok::NameTableKind;
10251025
}
10261026

1027+
if (Keyword == "Binary" || Keyword == "Decimal" || Keyword == "Rational") {
1028+
StrVal.assign(Keyword.begin(), Keyword.end());
1029+
return lltok::FixedPointKind;
1030+
}
1031+
10271032
// Check for [us]0x[0-9A-Fa-f]+ which are Hexadecimal constant generated by
10281033
// the CFE to avoid forcing it to deal with 64-bit numbers.
10291034
if ((TokStart[0] == 'u' || TokStart[0] == 's') &&

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4751,6 +4751,11 @@ struct EmissionKindField : public MDUnsignedField {
47514751
EmissionKindField() : MDUnsignedField(0, DICompileUnit::LastEmissionKind) {}
47524752
};
47534753

4754+
struct FixedPointKindField : public MDUnsignedField {
4755+
FixedPointKindField()
4756+
: MDUnsignedField(0, DIFixedPointType::LastFixedPointKind) {}
4757+
};
4758+
47544759
struct NameTableKindField : public MDUnsignedField {
47554760
NameTableKindField()
47564761
: MDUnsignedField(
@@ -4994,6 +4999,25 @@ bool LLParser::parseMDField(LocTy Loc, StringRef Name,
49944999
return false;
49955000
}
49965001

5002+
template <>
5003+
bool LLParser::parseMDField(LocTy Loc, StringRef Name,
5004+
FixedPointKindField &Result) {
5005+
if (Lex.getKind() == lltok::APSInt)
5006+
return parseMDField(Loc, Name, static_cast<MDUnsignedField &>(Result));
5007+
5008+
if (Lex.getKind() != lltok::FixedPointKind)
5009+
return tokError("expected fixed-point kind");
5010+
5011+
auto Kind = DIFixedPointType::getFixedPointKind(Lex.getStrVal());
5012+
if (!Kind)
5013+
return tokError("invalid fixed-point kind" + Twine(" '") + Lex.getStrVal() +
5014+
"'");
5015+
assert(*Kind <= Result.Max && "Expected valid fixed-point kind");
5016+
Result.assign(*Kind);
5017+
Lex.Lex();
5018+
return false;
5019+
}
5020+
49975021
template <>
49985022
bool LLParser::parseMDField(LocTy Loc, StringRef Name,
49995023
NameTableKindField &Result) {
@@ -5516,6 +5540,33 @@ bool LLParser::parseDIBasicType(MDNode *&Result, bool IsDistinct) {
55165540
return false;
55175541
}
55185542

5543+
/// parseDIFixedPointType:
5544+
/// ::= !DIFixedPointType(tag: DW_TAG_base_type, name: "xyz", size: 32,
5545+
/// align: 32, encoding: DW_ATE_signed_fixed,
5546+
/// flags: 0, kind: Rational, factor: 3, numerator: 1,
5547+
/// denominator: 8)
5548+
bool LLParser::parseDIFixedPointType(MDNode *&Result, bool IsDistinct) {
5549+
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
5550+
OPTIONAL(tag, DwarfTagField, (dwarf::DW_TAG_base_type)); \
5551+
OPTIONAL(name, MDStringField, ); \
5552+
OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX)); \
5553+
OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \
5554+
OPTIONAL(encoding, DwarfAttEncodingField, ); \
5555+
OPTIONAL(flags, DIFlagField, ); \
5556+
OPTIONAL(kind, FixedPointKindField, ); \
5557+
OPTIONAL(factor, MDSignedField, ); \
5558+
OPTIONAL(numerator, MDAPSIntField, ); \
5559+
OPTIONAL(denominator, MDAPSIntField, );
5560+
PARSE_MD_FIELDS();
5561+
#undef VISIT_MD_FIELDS
5562+
5563+
Result = GET_OR_DISTINCT(DIFixedPointType,
5564+
(Context, tag.Val, name.Val, size.Val, align.Val,
5565+
encoding.Val, flags.Val, kind.Val, factor.Val,
5566+
numerator.Val, denominator.Val));
5567+
return false;
5568+
}
5569+
55195570
/// parseDIStringType:
55205571
/// ::= !DIStringType(name: "character(4)", size: 32, align: 32)
55215572
bool LLParser::parseDIStringType(MDNode *&Result, bool IsDistinct) {

0 commit comments

Comments
 (0)