Skip to content

Commit 1bbf89a

Browse files
committed
Add support for fixed-point types
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 da6d5fa commit 1bbf89a

File tree

19 files changed

+547
-2
lines changed

19 files changed

+547
-2
lines changed

llvm/include/llvm-c/DebugInfo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ enum {
171171
LLVMDISubrangeMetadataKind,
172172
LLVMDIEnumeratorMetadataKind,
173173
LLVMDIBasicTypeMetadataKind,
174+
LLVMDIFixedPointTypeMetadataKind,
174175
LLVMDIDerivedTypeMetadataKind,
175176
LLVMDISubrangeTypeMetadataKind,
176177
LLVMDICompositeTypeMetadataKind,

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
@@ -4750,6 +4750,11 @@ struct EmissionKindField : public MDUnsignedField {
47504750
EmissionKindField() : MDUnsignedField(0, DICompileUnit::LastEmissionKind) {}
47514751
};
47524752

4753+
struct FixedPointKindField : public MDUnsignedField {
4754+
FixedPointKindField()
4755+
: MDUnsignedField(0, DIFixedPointType::LastFixedPointKind) {}
4756+
};
4757+
47534758
struct NameTableKindField : public MDUnsignedField {
47544759
NameTableKindField()
47554760
: MDUnsignedField(
@@ -4993,6 +4998,25 @@ bool LLParser::parseMDField(LocTy Loc, StringRef Name,
49934998
return false;
49944999
}
49955000

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

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

llvm/lib/Bitcode/Reader/MetadataLoader.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1542,6 +1542,39 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
15421542
NextMetadataNo++;
15431543
break;
15441544
}
1545+
case bitc::METADATA_FIXED_POINT_TYPE: {
1546+
if (Record.size() < 11)
1547+
return error("Invalid record");
1548+
1549+
IsDistinct = Record[0];
1550+
DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[6]);
1551+
1552+
size_t Offset = 9;
1553+
1554+
auto ReadWideInt = [&]() {
1555+
uint64_t Encoded = Record[Offset++];
1556+
unsigned NumWords = Encoded >> 32;
1557+
unsigned BitWidth = Encoded & 0xffffffff;
1558+
auto Value = readWideAPInt(ArrayRef(&Record[Offset], NumWords), BitWidth);
1559+
Offset += NumWords;
1560+
return Value;
1561+
};
1562+
1563+
APInt Numerator = ReadWideInt();
1564+
APInt Denominator = ReadWideInt();
1565+
1566+
if (Offset != Record.size())
1567+
return error("Invalid record");
1568+
1569+
MetadataList.assignValue(
1570+
GET_OR_DISTINCT(DIFixedPointType,
1571+
(Context, Record[1], getMDString(Record[2]), Record[3],
1572+
Record[4], Record[5], Flags, Record[7], Record[8],
1573+
Numerator, Denominator)),
1574+
NextMetadataNo);
1575+
NextMetadataNo++;
1576+
break;
1577+
}
15451578
case bitc::METADATA_STRING_TYPE: {
15461579
if (Record.size() > 9 || Record.size() < 8)
15471580
return error("Invalid record");

0 commit comments

Comments
 (0)