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.
This commit is contained in:
@@ -6212,6 +6212,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
|
||||
|
||||
@@ -173,6 +173,7 @@ enum {
|
||||
LLVMDISubrangeMetadataKind,
|
||||
LLVMDIEnumeratorMetadataKind,
|
||||
LLVMDIBasicTypeMetadataKind,
|
||||
LLVMDIFixedPointTypeMetadataKind,
|
||||
LLVMDIDerivedTypeMetadataKind,
|
||||
LLVMDICompositeTypeMetadataKind,
|
||||
LLVMDISubroutineTypeMetadataKind,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -199,6 +199,7 @@ public:
|
||||
case DISubrangeKind:
|
||||
case DIEnumeratorKind:
|
||||
case DIBasicTypeKind:
|
||||
case DIFixedPointTypeKind:
|
||||
case DIStringTypeKind:
|
||||
case DISubrangeTypeKind:
|
||||
case DIDerivedTypeKind:
|
||||
@@ -547,6 +548,7 @@ public:
|
||||
default:
|
||||
return false;
|
||||
case DIBasicTypeKind:
|
||||
case DIFixedPointTypeKind:
|
||||
case DIStringTypeKind:
|
||||
case DISubrangeTypeKind:
|
||||
case DIDerivedTypeKind:
|
||||
@@ -806,6 +808,7 @@ public:
|
||||
default:
|
||||
return false;
|
||||
case DIBasicTypeKind:
|
||||
case DIFixedPointTypeKind:
|
||||
case DIStringTypeKind:
|
||||
case DISubrangeTypeKind:
|
||||
case DIDerivedTypeKind:
|
||||
@@ -826,6 +829,7 @@ 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,
|
||||
@@ -833,6 +837,13 @@ class DIBasicType : public DIType {
|
||||
: 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,
|
||||
@@ -897,7 +908,132 @@ public:
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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') &&
|
||||
|
||||
@@ -4751,6 +4751,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(
|
||||
@@ -4994,6 +4999,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) {
|
||||
@@ -5516,6 +5540,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) {
|
||||
|
||||
@@ -1542,6 +1542,39 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
|
||||
NextMetadataNo++;
|
||||
break;
|
||||
}
|
||||
case bitc::METADATA_FIXED_POINT_TYPE: {
|
||||
if (Record.size() < 11)
|
||||
return error("Invalid record");
|
||||
|
||||
IsDistinct = Record[0];
|
||||
DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[6]);
|
||||
|
||||
size_t Offset = 9;
|
||||
|
||||
auto ReadWideInt = [&]() {
|
||||
uint64_t Encoded = Record[Offset++];
|
||||
unsigned NumWords = Encoded >> 32;
|
||||
unsigned BitWidth = Encoded & 0xffffffff;
|
||||
auto Value = readWideAPInt(ArrayRef(&Record[Offset], NumWords), BitWidth);
|
||||
Offset += NumWords;
|
||||
return Value;
|
||||
};
|
||||
|
||||
APInt Numerator = ReadWideInt();
|
||||
APInt Denominator = ReadWideInt();
|
||||
|
||||
if (Offset != Record.size())
|
||||
return error("Invalid record");
|
||||
|
||||
MetadataList.assignValue(
|
||||
GET_OR_DISTINCT(DIFixedPointType,
|
||||
(Context, Record[1], getMDString(Record[2]), Record[3],
|
||||
Record[4], Record[5], Flags, Record[7], Record[8],
|
||||
Numerator, Denominator)),
|
||||
NextMetadataNo);
|
||||
NextMetadataNo++;
|
||||
break;
|
||||
}
|
||||
case bitc::METADATA_STRING_TYPE: {
|
||||
if (Record.size() > 9 || Record.size() < 8)
|
||||
return error("Invalid record");
|
||||
|
||||
@@ -323,6 +323,9 @@ private:
|
||||
SmallVectorImpl<uint64_t> &Record, unsigned Abbrev);
|
||||
void writeDIBasicType(const DIBasicType *N, SmallVectorImpl<uint64_t> &Record,
|
||||
unsigned Abbrev);
|
||||
void writeDIFixedPointType(const DIFixedPointType *N,
|
||||
SmallVectorImpl<uint64_t> &Record,
|
||||
unsigned Abbrev);
|
||||
void writeDIStringType(const DIStringType *N,
|
||||
SmallVectorImpl<uint64_t> &Record, unsigned Abbrev);
|
||||
void writeDIDerivedType(const DIDerivedType *N,
|
||||
@@ -1887,6 +1890,35 @@ void ModuleBitcodeWriter::writeDIBasicType(const DIBasicType *N,
|
||||
Record.clear();
|
||||
}
|
||||
|
||||
void ModuleBitcodeWriter::writeDIFixedPointType(
|
||||
const DIFixedPointType *N, SmallVectorImpl<uint64_t> &Record,
|
||||
unsigned Abbrev) {
|
||||
Record.push_back(N->isDistinct());
|
||||
Record.push_back(N->getTag());
|
||||
Record.push_back(VE.getMetadataOrNullID(N->getRawName()));
|
||||
Record.push_back(N->getSizeInBits());
|
||||
Record.push_back(N->getAlignInBits());
|
||||
Record.push_back(N->getEncoding());
|
||||
Record.push_back(N->getFlags());
|
||||
Record.push_back(N->getKind());
|
||||
Record.push_back(N->getFactorRaw());
|
||||
|
||||
auto WriteWideInt = [&](const APInt &Value) {
|
||||
// Write an encoded word that holds the number of active words and
|
||||
// the number of bits.
|
||||
uint64_t NumWords = Value.getActiveWords();
|
||||
uint64_t Encoded = (NumWords << 32) | Value.getBitWidth();
|
||||
Record.push_back(Encoded);
|
||||
emitWideAPInt(Record, Value);
|
||||
};
|
||||
|
||||
WriteWideInt(N->getNumeratorRaw());
|
||||
WriteWideInt(N->getDenominatorRaw());
|
||||
|
||||
Stream.EmitRecord(bitc::METADATA_FIXED_POINT_TYPE, Record, Abbrev);
|
||||
Record.clear();
|
||||
}
|
||||
|
||||
void ModuleBitcodeWriter::writeDIStringType(const DIStringType *N,
|
||||
SmallVectorImpl<uint64_t> &Record,
|
||||
unsigned Abbrev) {
|
||||
|
||||
@@ -615,7 +615,9 @@ DIE *DwarfUnit::createTypeDIE(const DIScope *Context, DIE &ContextDIE,
|
||||
return &TyDIE;
|
||||
}
|
||||
construct(CTy);
|
||||
} else if (auto *BT = dyn_cast<DIBasicType>(Ty))
|
||||
} else if (auto *FPT = dyn_cast<DIFixedPointType>(Ty))
|
||||
construct(FPT);
|
||||
else if (auto *BT = dyn_cast<DIBasicType>(Ty))
|
||||
construct(BT);
|
||||
else if (auto *ST = dyn_cast<DIStringType>(Ty))
|
||||
construct(ST);
|
||||
@@ -760,6 +762,30 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIBasicType *BTy) {
|
||||
NumExtraInhabitants);
|
||||
}
|
||||
|
||||
void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIFixedPointType *BTy) {
|
||||
// Base type handling.
|
||||
constructTypeDIE(Buffer, static_cast<const DIBasicType *>(BTy));
|
||||
|
||||
if (BTy->isBinary())
|
||||
addSInt(Buffer, dwarf::DW_AT_binary_scale, dwarf::DW_FORM_sdata,
|
||||
BTy->getFactor());
|
||||
else if (BTy->isDecimal())
|
||||
addSInt(Buffer, dwarf::DW_AT_decimal_scale, dwarf::DW_FORM_sdata,
|
||||
BTy->getFactor());
|
||||
else {
|
||||
assert(BTy->isRational());
|
||||
DIE *ContextDIE = getOrCreateContextDIE(BTy->getScope());
|
||||
DIE &Constant = createAndAddDIE(dwarf::DW_TAG_constant, *ContextDIE);
|
||||
|
||||
addInt(Constant, dwarf::DW_AT_GNU_numerator, BTy->getNumerator(),
|
||||
!BTy->isSigned());
|
||||
addInt(Constant, dwarf::DW_AT_GNU_denominator, BTy->getDenominator(),
|
||||
!BTy->isSigned());
|
||||
|
||||
addDIEEntry(Buffer, dwarf::DW_AT_small, Constant);
|
||||
}
|
||||
}
|
||||
|
||||
void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIStringType *STy) {
|
||||
// Get core information.
|
||||
StringRef Name = STy->getName();
|
||||
|
||||
@@ -343,6 +343,7 @@ private:
|
||||
void addIntAsBlock(DIE &Die, dwarf::Attribute Attribute, const APInt &Val);
|
||||
|
||||
void constructTypeDIE(DIE &Buffer, const DIBasicType *BTy);
|
||||
void constructTypeDIE(DIE &Buffer, const DIFixedPointType *BTy);
|
||||
void constructTypeDIE(DIE &Buffer, const DIStringType *BTy);
|
||||
void constructTypeDIE(DIE &Buffer, const DIDerivedType *DTy);
|
||||
void constructTypeDIE(DIE &Buffer, const DISubroutineType *CTy);
|
||||
|
||||
@@ -1894,6 +1894,7 @@ struct MDFieldPrinter {
|
||||
void printEmissionKind(StringRef Name, DICompileUnit::DebugEmissionKind EK);
|
||||
void printNameTableKind(StringRef Name,
|
||||
DICompileUnit::DebugNameTableKind NTK);
|
||||
void printFixedPointKind(StringRef Name, DIFixedPointType::FixedPointKind V);
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
@@ -2030,6 +2031,11 @@ void MDFieldPrinter::printNameTableKind(StringRef Name,
|
||||
Out << FS << Name << ": " << DICompileUnit::nameTableKindString(NTK);
|
||||
}
|
||||
|
||||
void MDFieldPrinter::printFixedPointKind(StringRef Name,
|
||||
DIFixedPointType::FixedPointKind V) {
|
||||
Out << FS << Name << ": " << DIFixedPointType::fixedPointKindString(V);
|
||||
}
|
||||
|
||||
template <class IntTy, class Stringifier>
|
||||
void MDFieldPrinter::printDwarfEnum(StringRef Name, IntTy Value,
|
||||
Stringifier toString, bool ShouldSkipZero) {
|
||||
@@ -2199,6 +2205,29 @@ static void writeDIBasicType(raw_ostream &Out, const DIBasicType *N,
|
||||
Out << ")";
|
||||
}
|
||||
|
||||
static void writeDIFixedPointType(raw_ostream &Out, const DIFixedPointType *N,
|
||||
AsmWriterContext &) {
|
||||
Out << "!DIFixedPointType(";
|
||||
MDFieldPrinter Printer(Out);
|
||||
if (N->getTag() != dwarf::DW_TAG_base_type)
|
||||
Printer.printTag(N);
|
||||
Printer.printString("name", N->getName());
|
||||
Printer.printInt("size", N->getSizeInBits());
|
||||
Printer.printInt("align", N->getAlignInBits());
|
||||
Printer.printDwarfEnum("encoding", N->getEncoding(),
|
||||
dwarf::AttributeEncodingString);
|
||||
Printer.printDIFlags("flags", N->getFlags());
|
||||
Printer.printFixedPointKind("kind", N->getKind());
|
||||
if (N->isRational()) {
|
||||
bool IsUnsigned = !N->isSigned();
|
||||
Printer.printAPInt("numerator", N->getNumerator(), IsUnsigned, false);
|
||||
Printer.printAPInt("denominator", N->getDenominator(), IsUnsigned, false);
|
||||
} else {
|
||||
Printer.printInt("factor", N->getFactor());
|
||||
}
|
||||
Out << ")";
|
||||
}
|
||||
|
||||
static void writeDIStringType(raw_ostream &Out, const DIStringType *N,
|
||||
AsmWriterContext &WriterCtx) {
|
||||
Out << "!DIStringType(";
|
||||
|
||||
@@ -272,6 +272,37 @@ DIBasicType *DIBuilder::createBasicType(StringRef Name, uint64_t SizeInBits,
|
||||
0, Encoding, NumExtraInhabitants, Flags);
|
||||
}
|
||||
|
||||
DIFixedPointType *
|
||||
DIBuilder::createBinaryFixedPointType(StringRef Name, uint64_t SizeInBits,
|
||||
uint32_t AlignInBits, unsigned Encoding,
|
||||
DINode::DIFlags Flags, int Factor) {
|
||||
return DIFixedPointType::get(VMContext, dwarf::DW_TAG_base_type, Name,
|
||||
SizeInBits, AlignInBits, Encoding, Flags,
|
||||
DIFixedPointType::FixedPointBinary, Factor,
|
||||
APInt(), APInt());
|
||||
}
|
||||
|
||||
DIFixedPointType *
|
||||
DIBuilder::createDecimalFixedPointType(StringRef Name, uint64_t SizeInBits,
|
||||
uint32_t AlignInBits, unsigned Encoding,
|
||||
DINode::DIFlags Flags, int Factor) {
|
||||
return DIFixedPointType::get(VMContext, dwarf::DW_TAG_base_type, Name,
|
||||
SizeInBits, AlignInBits, Encoding, Flags,
|
||||
DIFixedPointType::FixedPointDecimal, Factor,
|
||||
APInt(), APInt());
|
||||
}
|
||||
|
||||
DIFixedPointType *
|
||||
DIBuilder::createRationalFixedPointType(StringRef Name, uint64_t SizeInBits,
|
||||
uint32_t AlignInBits, unsigned Encoding,
|
||||
DINode::DIFlags Flags, APInt Numerator,
|
||||
APInt Denominator) {
|
||||
return DIFixedPointType::get(VMContext, dwarf::DW_TAG_base_type, Name,
|
||||
SizeInBits, AlignInBits, Encoding, Flags,
|
||||
DIFixedPointType::FixedPointRational, 0,
|
||||
Numerator, Denominator);
|
||||
}
|
||||
|
||||
DIStringType *DIBuilder::createStringType(StringRef Name, uint64_t SizeInBits) {
|
||||
assert(!Name.empty() && "Unable to create type without name");
|
||||
return DIStringType::get(VMContext, dwarf::DW_TAG_string_type, Name,
|
||||
|
||||
@@ -721,15 +721,58 @@ std::optional<DIBasicType::Signedness> DIBasicType::getSignedness() const {
|
||||
switch (getEncoding()) {
|
||||
case dwarf::DW_ATE_signed:
|
||||
case dwarf::DW_ATE_signed_char:
|
||||
case dwarf::DW_ATE_signed_fixed:
|
||||
return Signedness::Signed;
|
||||
case dwarf::DW_ATE_unsigned:
|
||||
case dwarf::DW_ATE_unsigned_char:
|
||||
case dwarf::DW_ATE_unsigned_fixed:
|
||||
return Signedness::Unsigned;
|
||||
default:
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
DIFixedPointType *
|
||||
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) {
|
||||
DEFINE_GETIMPL_LOOKUP(DIFixedPointType,
|
||||
(Tag, Name, SizeInBits, AlignInBits, Encoding, Flags,
|
||||
Kind, Factor, Numerator, Denominator));
|
||||
Metadata *Ops[] = {nullptr, nullptr, Name};
|
||||
DEFINE_GETIMPL_STORE(DIFixedPointType,
|
||||
(Tag, SizeInBits, AlignInBits, Encoding, Flags, Kind,
|
||||
Factor, Numerator, Denominator),
|
||||
Ops);
|
||||
}
|
||||
|
||||
bool DIFixedPointType::isSigned() const {
|
||||
return getEncoding() == dwarf::DW_ATE_signed_fixed;
|
||||
}
|
||||
|
||||
std::optional<DIFixedPointType::FixedPointKind>
|
||||
DIFixedPointType::getFixedPointKind(StringRef Str) {
|
||||
return StringSwitch<std::optional<FixedPointKind>>(Str)
|
||||
.Case("Binary", FixedPointBinary)
|
||||
.Case("Decimal", FixedPointDecimal)
|
||||
.Case("Rational", FixedPointRational)
|
||||
.Default(std::nullopt);
|
||||
}
|
||||
|
||||
const char *DIFixedPointType::fixedPointKindString(FixedPointKind V) {
|
||||
switch (V) {
|
||||
case FixedPointBinary:
|
||||
return "Binary";
|
||||
case FixedPointDecimal:
|
||||
return "Decimal";
|
||||
case FixedPointRational:
|
||||
return "Rational";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DIStringType *DIStringType::getImpl(LLVMContext &Context, unsigned Tag,
|
||||
MDString *Name, Metadata *StringLength,
|
||||
Metadata *StringLengthExp,
|
||||
|
||||
@@ -494,6 +494,43 @@ template <> struct MDNodeKeyImpl<DIBasicType> {
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct MDNodeKeyImpl<DIFixedPointType> {
|
||||
unsigned Tag;
|
||||
MDString *Name;
|
||||
uint64_t SizeInBits;
|
||||
uint32_t AlignInBits;
|
||||
unsigned Encoding;
|
||||
unsigned Flags;
|
||||
unsigned Kind;
|
||||
int Factor;
|
||||
APInt Numerator;
|
||||
APInt Denominator;
|
||||
|
||||
MDNodeKeyImpl(unsigned Tag, MDString *Name, uint64_t SizeInBits,
|
||||
uint32_t AlignInBits, unsigned Encoding, unsigned Flags,
|
||||
unsigned Kind, int Factor, APInt Numerator, APInt Denominator)
|
||||
: Tag(Tag), Name(Name), SizeInBits(SizeInBits), AlignInBits(AlignInBits),
|
||||
Encoding(Encoding), Flags(Flags), Kind(Kind), Factor(Factor),
|
||||
Numerator(Numerator), Denominator(Denominator) {}
|
||||
MDNodeKeyImpl(const DIFixedPointType *N)
|
||||
: Tag(N->getTag()), Name(N->getRawName()), SizeInBits(N->getSizeInBits()),
|
||||
AlignInBits(N->getAlignInBits()), Encoding(N->getEncoding()),
|
||||
Flags(N->getFlags()), Kind(N->getKind()), Factor(N->getFactorRaw()),
|
||||
Numerator(N->getNumeratorRaw()), Denominator(N->getDenominatorRaw()) {}
|
||||
|
||||
bool isKeyOf(const DIFixedPointType *RHS) const {
|
||||
return Name == RHS->getRawName() && SizeInBits == RHS->getSizeInBits() &&
|
||||
AlignInBits == RHS->getAlignInBits() && Kind == RHS->getKind() &&
|
||||
(RHS->isRational() ? (Numerator == RHS->getNumerator() &&
|
||||
Denominator == RHS->getDenominator())
|
||||
: Factor == RHS->getFactor());
|
||||
}
|
||||
|
||||
unsigned getHashValue() const {
|
||||
return hash_combine(Name, Flags, Kind, Factor, Numerator, Denominator);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct MDNodeKeyImpl<DIStringType> {
|
||||
unsigned Tag;
|
||||
MDString *Name;
|
||||
|
||||
@@ -1239,6 +1239,25 @@ void Verifier::visitDIBasicType(const DIBasicType &N) {
|
||||
"invalid tag", &N);
|
||||
}
|
||||
|
||||
void Verifier::visitDIFixedPointType(const DIFixedPointType &N) {
|
||||
visitDIBasicType(N);
|
||||
|
||||
CheckDI(N.getTag() == dwarf::DW_TAG_base_type, "invalid tag", &N);
|
||||
CheckDI(N.getEncoding() == dwarf::DW_ATE_signed_fixed ||
|
||||
N.getEncoding() == dwarf::DW_ATE_unsigned_fixed,
|
||||
"invalid encoding", &N);
|
||||
CheckDI(N.getKind() == DIFixedPointType::FixedPointBinary ||
|
||||
N.getKind() == DIFixedPointType::FixedPointDecimal ||
|
||||
N.getKind() == DIFixedPointType::FixedPointRational,
|
||||
"invalid kind", &N);
|
||||
CheckDI(N.getKind() != DIFixedPointType::FixedPointRational ||
|
||||
N.getFactorRaw() == 0,
|
||||
"factor should be 0 for rationals", &N);
|
||||
CheckDI(N.getKind() == DIFixedPointType::FixedPointRational ||
|
||||
(N.getNumeratorRaw() == 0 && N.getDenominatorRaw() == 0),
|
||||
"numerator and denominator should be 0 for non-rationals", &N);
|
||||
}
|
||||
|
||||
void Verifier::visitDIStringType(const DIStringType &N) {
|
||||
CheckDI(N.getTag() == dwarf::DW_TAG_string_type, "invalid tag", &N);
|
||||
CheckDI(!(N.isBigEndian() && N.isLittleEndian()), "has conflicting flags",
|
||||
|
||||
29
llvm/test/Bitcode/fixedpoint_type.ll
Normal file
29
llvm/test/Bitcode/fixedpoint_type.ll
Normal file
@@ -0,0 +1,29 @@
|
||||
;; This test checks generation of DIFixedPointType.
|
||||
|
||||
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
|
||||
|
||||
;; Test whether DIFixedPointType is generated.
|
||||
; CHECK: !DIFixedPointType(name: "fp__decimal", size: 32, align: 32, encoding: DW_ATE_signed_fixed, kind: Decimal, factor: -4)
|
||||
; CHECK: !DIFixedPointType(name: "fp__rational", size: 32, align: 32, encoding: DW_ATE_unsigned_fixed, kind: Rational, numerator: 1234, denominator: 5678)
|
||||
; CHECK: !DIFixedPointType(name: "fp__binary", size: 64, encoding: DW_ATE_unsigned_fixed, kind: Binary, factor: -16)
|
||||
|
||||
; ModuleID = 'fixedpoint_type.ll'
|
||||
source_filename = "/dir/fixedpoint_type.adb"
|
||||
|
||||
!llvm.module.flags = !{!0, !1}
|
||||
!llvm.dbg.cu = !{!2}
|
||||
|
||||
!0 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!1 = !{i32 2, !"Dwarf Version", i32 4}
|
||||
!2 = distinct !DICompileUnit(language: DW_LANG_Ada95, file: !3, producer: "GNAT/LLVM", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !5, globals: !4, imports: !4)
|
||||
!3 = !DIFile(filename: "fixedpoint_type.adb", directory: "/dir")
|
||||
!4 = !{}
|
||||
!5 = !{!11, !12, !13}
|
||||
!6 = distinct !DISubprogram(name: "fp", scope: !3, file: !3, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !4, retainedNodes: !9)
|
||||
!7 = !DISubroutineType(types: !8)
|
||||
!8 = !{null}
|
||||
!9 = !{!10}
|
||||
!10 = !DILocalVariable(name: "x", scope: !6, file: !3, line: 3, type: !11, align: 32)
|
||||
!11 = !DIFixedPointType(name: "fp__decimal", size: 32, align: 32, encoding: DW_ATE_signed_fixed, kind: Decimal, factor: -4)
|
||||
!12 = !DIFixedPointType(name: "fp__rational", size: 32, align: 32, encoding: DW_ATE_unsigned_fixed, kind: Rational, numerator: 1234, denominator: 5678)
|
||||
!13 = !DIFixedPointType(name: "fp__binary", size: 64, align: 0, encoding: DW_ATE_unsigned_fixed, kind: Binary, factor: -16)
|
||||
@@ -501,6 +501,40 @@ TEST(DIBuilder, DIEnumerator) {
|
||||
EXPECT_FALSE(E2);
|
||||
}
|
||||
|
||||
TEST(DIBuilder, FixedPointType) {
|
||||
LLVMContext Ctx;
|
||||
std::unique_ptr<Module> M(new Module("MyModule", Ctx));
|
||||
DIBuilder DIB(*M);
|
||||
|
||||
DIFixedPointType *Ty = DIB.createBinaryFixedPointType(
|
||||
{}, 32, 0, dwarf::DW_ATE_signed_fixed, DINode::FlagZero, -4);
|
||||
EXPECT_TRUE(Ty);
|
||||
EXPECT_TRUE(Ty->getKind() == DIFixedPointType::FixedPointBinary);
|
||||
EXPECT_TRUE(Ty->getFactor() == -4);
|
||||
EXPECT_TRUE(Ty->getEncoding() == dwarf::DW_ATE_signed_fixed);
|
||||
EXPECT_TRUE(Ty->getTag() == dwarf::DW_TAG_base_type);
|
||||
|
||||
Ty = DIB.createDecimalFixedPointType({}, 32, 0, dwarf::DW_ATE_unsigned_fixed,
|
||||
DINode::FlagZero, -7);
|
||||
EXPECT_TRUE(Ty);
|
||||
EXPECT_TRUE(Ty->getKind() == DIFixedPointType::FixedPointDecimal);
|
||||
EXPECT_TRUE(Ty->getFactor() == -7);
|
||||
EXPECT_TRUE(Ty->getEncoding() == dwarf::DW_ATE_unsigned_fixed);
|
||||
EXPECT_TRUE(Ty->getTag() == dwarf::DW_TAG_base_type);
|
||||
|
||||
APSInt Num(APInt(32, 1));
|
||||
APSInt Denom(APInt(33, 72));
|
||||
Ty = DIB.createRationalFixedPointType({}, 32, 0, dwarf::DW_ATE_unsigned_fixed,
|
||||
DINode::FlagZero, Num, Denom);
|
||||
EXPECT_TRUE(Ty);
|
||||
EXPECT_TRUE(Ty->getKind() == DIFixedPointType::FixedPointRational);
|
||||
EXPECT_TRUE(Ty->getFactorRaw() == 0);
|
||||
EXPECT_TRUE(Ty->getNumerator() == Num);
|
||||
EXPECT_TRUE(Ty->getDenominator() == Denom);
|
||||
EXPECT_TRUE(Ty->getEncoding() == dwarf::DW_ATE_unsigned_fixed);
|
||||
EXPECT_TRUE(Ty->getTag() == dwarf::DW_TAG_base_type);
|
||||
}
|
||||
|
||||
TEST(DbgAssignIntrinsicTest, replaceVariableLocationOp) {
|
||||
LLVMContext C;
|
||||
std::unique_ptr<Module> M = parseIR(C, R"(
|
||||
|
||||
Reference in New Issue
Block a user