diff --git a/llvm/include/llvm-c/DebugInfo.h b/llvm/include/llvm-c/DebugInfo.h --- a/llvm/include/llvm-c/DebugInfo.h +++ b/llvm/include/llvm-c/DebugInfo.h @@ -55,8 +55,6 @@ LLVMDIFlagFixedEnum = LLVMDIFlagEnumClass, // Deprecated. LLVMDIFlagThunk = 1 << 25, LLVMDIFlagNonTrivial = 1 << 26, - LLVMDIFlagBigEndian = 1 << 27, - LLVMDIFlagLittleEndian = 1 << 28, LLVMDIFlagIndirectVirtualBase = (1 << 2) | (1 << 5), LLVMDIFlagAccessibility = LLVMDIFlagPrivate | LLVMDIFlagProtected | LLVMDIFlagPublic, @@ -163,6 +161,14 @@ }; typedef unsigned LLVMMetadataKind; +typedef enum { + LLVMDIBTFlagZero = 0, + LLVMDIBTFlagLittleEndian = 1, + LLVMDIBTFlagBigEndian = 2, + LLVMDIBTFlagBinaryScale = (1u << 2), + LLVMDIBTFlagDecimalScale = (1u << 3), +} LLVMDIBTFlags; + /** * An LLVM DWARF type encoding. */ @@ -672,11 +678,11 @@ * \param Encoding DWARF encoding code, e.g. \c LLVMDWARFTypeEncoding_float. * \param Flags Flags to encode optional attribute like endianity */ -LLVMMetadataRef -LLVMDIBuilderCreateBasicType(LLVMDIBuilderRef Builder, const char *Name, - size_t NameLen, uint64_t SizeInBits, - LLVMDWARFTypeEncoding Encoding, - LLVMDIFlags Flags); +LLVMMetadataRef LLVMDIBuilderCreateBasicType(LLVMDIBuilderRef Builder, + const char *Name, size_t NameLen, + uint64_t SizeInBits, + LLVMDWARFTypeEncoding Encoding, + LLVMDIBTFlags Flags); /** * Create debugging information entry for a pointer. diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.h b/llvm/include/llvm/BinaryFormat/Dwarf.h --- a/llvm/include/llvm/BinaryFormat/Dwarf.h +++ b/llvm/include/llvm/BinaryFormat/Dwarf.h @@ -132,12 +132,9 @@ }; enum DecimalSignEncoding { - // Decimal sign attribute values - DW_DS_unsigned = 0x01, - DW_DS_leading_overpunch = 0x02, - DW_DS_trailing_overpunch = 0x03, - DW_DS_leading_separate = 0x04, - DW_DS_trailing_separate = 0x05 +// Decimal sign attribute values +#define HANDLE_DW_DS(ID, NAME) DW_DS_##NAME = ID, +#include "llvm/BinaryFormat/Dwarf.def" }; enum EndianityEncoding { @@ -492,6 +489,7 @@ /// /// @{ unsigned getTag(StringRef TagString); +unsigned getDecimalSign(StringRef DSString); unsigned getOperationEncoding(StringRef OperationEncodingString); unsigned getVirtuality(StringRef VirtualityString); unsigned getLanguage(StringRef LanguageString); diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def --- a/llvm/include/llvm/BinaryFormat/Dwarf.def +++ b/llvm/include/llvm/BinaryFormat/Dwarf.def @@ -21,7 +21,7 @@ (defined HANDLE_DW_CFA && defined HANDLE_DW_CFA_PRED) || \ defined HANDLE_DW_APPLE_PROPERTY || defined HANDLE_DW_UT || \ defined HANDLE_DWARF_SECTION || defined HANDLE_DW_IDX || \ - defined HANDLE_DW_END) + defined HANDLE_DW_END || defined HANDLE_DW_DS) #error "Missing macro definition of HANDLE_DW*" #endif @@ -123,6 +123,10 @@ #define HANDLE_DW_END(ID, NAME) #endif +#ifndef HANDLE_DW_DS +#define HANDLE_DW_DS(ID, NAME) +#endif + HANDLE_DW_TAG(0x0000, null, 2, DWARF, DW_KIND_NONE) HANDLE_DW_TAG(0x0001, array_type, 2, DWARF, DW_KIND_TYPE) HANDLE_DW_TAG(0x0002, class_type, 2, DWARF, DW_KIND_TYPE) @@ -725,6 +729,13 @@ HANDLE_DW_ATE(0x11, UCS, 5, DWARF) HANDLE_DW_ATE(0x12, ASCII, 5, DWARF) +// DWARF decimal sign +HANDLE_DW_DS(0x01, unsigned) +HANDLE_DW_DS(0x02, leading_overpunch) +HANDLE_DW_DS(0x03, trailing_overpunch) +HANDLE_DW_DS(0x04, leading_separate) +HANDLE_DW_DS(0x05, trailing_separate) + // DWARF attribute endianity HANDLE_DW_END(0x00, default) HANDLE_DW_END(0x01, big) @@ -965,3 +976,4 @@ #undef HANDLE_DWARF_SECTION #undef HANDLE_DW_IDX #undef HANDLE_DW_END +#undef HANDLE_DW_DS diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h --- a/llvm/include/llvm/IR/DIBuilder.h +++ b/llvm/include/llvm/IR/DIBuilder.h @@ -192,9 +192,25 @@ /// \param SizeInBits Size of the type. /// \param Encoding DWARF encoding code, e.g., dwarf::DW_ATE_float. /// \param Flags Optional DWARF attributes, e.g., DW_AT_endianity. - DIBasicType *createBasicType(StringRef Name, uint64_t SizeInBits, - unsigned Encoding, - DINode::DIFlags Flags = DINode::FlagZero); + DIBasicType * + createBasicType(StringRef Name, uint64_t SizeInBits, unsigned Encoding, + DIBasicType::DIBTFlags Flags = DIBasicType::BTFlagZero); + + /// Create debugging information entry for a basic type with packed decimal + /// type. + /// \param Name Type name. + /// \param Pic Picture String + /// \param SizeInBits Size of the type. + /// \param Encoding DWARF encoding code, e.g., dwarf::DW_ATE_edited_type. + /// \param DigitCount digit count + /// \param DecimalSign decimal sign + /// \param scale scale + /// \param Flags Optional DWARF attributes, e.g., DIFlagsBinaryScale + DIBasicType * + createBasicType(StringRef Name, StringRef Pic, uint64_t SizeInBits, + unsigned Encoding, uint8_t DigitCount = 0, + uint8_t DecimalSign = 0, int8_t Scale = 0, + DIBasicType::DIBTFlags Flags = DIBasicType::BTFlagZero); /// Create debugging information entry for a qualified /// type, e.g. 'const int'. diff --git a/llvm/include/llvm/IR/DebugInfoFlags.def b/llvm/include/llvm/IR/DebugInfoFlags.def --- a/llvm/include/llvm/IR/DebugInfoFlags.def +++ b/llvm/include/llvm/IR/DebugInfoFlags.def @@ -10,7 +10,8 @@ // //===----------------------------------------------------------------------===// -#if !(defined HANDLE_DI_FLAG || defined HANDLE_DISP_FLAG) +#if !(defined HANDLE_DI_FLAG || defined HANDLE_DISP_FLAG || \ + defined HANDLE_DIBT_FLAG) #error "Missing macro definition of HANDLE_DI*" #endif @@ -22,6 +23,10 @@ #define HANDLE_DISP_FLAG(ID, NAME) #endif +#ifndef HANDLE_DIBT_FLAG +#define HANDLE_DIBT_FLAG(ID, NAME) +#endif + // General flags kept in DINode. HANDLE_DI_FLAG(0, Zero) // Use it as zero value. @@ -55,9 +60,7 @@ HANDLE_DI_FLAG((1 << 24), EnumClass) HANDLE_DI_FLAG((1 << 25), Thunk) HANDLE_DI_FLAG((1 << 26), NonTrivial) -HANDLE_DI_FLAG((1 << 27), BigEndian) -HANDLE_DI_FLAG((1 << 28), LittleEndian) -HANDLE_DI_FLAG((1 << 29), AllCallsDescribed) +HANDLE_DI_FLAG((1 << 27), AllCallsDescribed) // To avoid needing a dedicated value for IndirectVirtualBase, we use // the bitwise or of Virtual and FwdDecl, which does not otherwise @@ -67,7 +70,7 @@ #ifdef DI_FLAG_LARGEST_NEEDED // intended to be used with ADT/BitmaskEnum.h // NOTE: always must be equal to largest flag, check this when adding new flag -HANDLE_DI_FLAG((1 << 29), Largest) +HANDLE_DI_FLAG((1 << 27), Largest) #undef DI_FLAG_LARGEST_NEEDED #endif @@ -99,5 +102,23 @@ #undef DISP_FLAG_LARGEST_NEEDED #endif +// BasicType flags kept in DIBasicType + +// Use this as a zero/initialization value. +// For example: void foo(DIBTFlags Flags = BTFlagZero). +HANDLE_DIBT_FLAG(0, Zero) +HANDLE_DIBT_FLAG(1u, LittleEndian) +HANDLE_DIBT_FLAG(2u, BigEndian) +HANDLE_DIBT_FLAG((1u << 2), BinaryScale) +HANDLE_DIBT_FLAG((1u << 3), DecimalScale) + +#ifdef DIBT_FLAG_LARGEST_NEEDED +// Intended to be used with ADT/BitmaskEnum.h. +// NOTE: Always must be equal to largest flag, check this when adding new flags. +HANDLE_DIBT_FLAG((1 << 3), Largest) +#undef DIBT_FLAG_LARGEST_NEEDED +#endif + #undef HANDLE_DI_FLAG #undef HANDLE_DISP_FLAG +#undef HANDLE_DIBT_FLAG diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -665,8 +665,6 @@ bool isTypePassByReference() const { return getFlags() & FlagTypePassByReference; } - bool isBigEndian() const { return getFlags() & FlagBigEndian; } - bool isLittleEndian() const { return getFlags() & FlagLittleEndian; } bool getExportSymbols() const { return getFlags() & FlagExportSymbols; } static bool classof(const Metadata *MD) { @@ -690,50 +688,132 @@ friend class LLVMContextImpl; friend class MDNode; +public: + /// Debug BasciType flags. + enum DIBTFlags : uint32_t { +#define HANDLE_DIBT_FLAG(ID, NAME) BTFlag##NAME = ID, +#define DIBT_FLAG_LARGEST_NEEDED +#include "llvm/IR/DebugInfoFlags.def" + LLVM_MARK_AS_BITMASK_ENUM(BTFlagLargest) + }; + + static DIBTFlags getFlag(StringRef Flag); + static StringRef getFlagString(DIBTFlags Flag); + + /// Split up a flags bitfield for easier printing. + /// + /// Split \c Flags into \c SplitFlags, a vector of its components. Returns + /// any remaining (unrecognized) bits. + static DIBTFlags splitFlags(DIBTFlags Flags, + SmallVectorImpl &SplitFlags); + + /// Basic Type decimal info, used to record optional dwarf decimal attributes + /// such as picture_string, digit_counts, decimal_sign, decimal_scale all or + /// some can be absent and optional depending on encoding type. + struct DecimalInfo { + uint8_t DigitCount; + uint8_t DecimalSign; + int8_t Scale; + + DecimalInfo(uint8_t DigitCount, uint8_t DecimalSign, int8_t Scale) + : DigitCount(DigitCount), DecimalSign(DecimalSign), Scale(Scale) {} + + bool operator==(const DecimalInfo &RHS) const { + return DigitCount == RHS.DigitCount && DecimalSign == RHS.DecimalSign && + Scale == RHS.Scale; + } + }; + +private: + DIBTFlags BTFlags; unsigned Encoding; + Optional DecimalAttrInfo; DIBasicType(LLVMContext &C, StorageType Storage, unsigned Tag, uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, - DIFlags Flags, ArrayRef Ops) + DIBTFlags BTFlags, Optional DecimalAttrInfo, + ArrayRef Ops) : DIType(C, DIBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, - Flags, Ops), - Encoding(Encoding) {} + FlagZero, Ops), + BTFlags(BTFlags), Encoding(Encoding), DecimalAttrInfo(DecimalAttrInfo) { + } ~DIBasicType() = default; static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, - DIFlags Flags, StorageType Storage, + DIBTFlags BTFlags, StorageType Storage, bool ShouldCreate = true) { - return getImpl(Context, Tag, getCanonicalMDString(Context, Name), - SizeInBits, AlignInBits, Encoding, Flags, Storage, + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), nullptr, + SizeInBits, AlignInBits, Encoding, BTFlags, None, Storage, ShouldCreate); } static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, - DIFlags Flags, StorageType Storage, - bool ShouldCreate = true); + DIBTFlags BTFlags, + Optional DecimalAttrInfo, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Tag, Name, nullptr, SizeInBits, AlignInBits, + Encoding, BTFlags, DecimalAttrInfo, Storage, ShouldCreate); + } + + static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Name, MDString *PictureString, + uint64_t SizeInBits, uint32_t AlignInBits, + unsigned Encoding, DIBTFlags BTFlags, + Optional DecimalAttrInfo, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), + PictureString, SizeInBits, AlignInBits, Encoding, BTFlags, + DecimalAttrInfo, Storage, ShouldCreate); + } + + static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Name, MDString *PictureString, + uint64_t SizeInBits, uint32_t AlignInBits, + unsigned Encoding, DIBTFlags BTFlags, + Optional DecimalAttrInfo, + StorageType Storage, bool ShouldCreate = true); TempDIBasicType cloneImpl() const { - return getTemporary(getContext(), getTag(), getName(), getSizeInBits(), - getAlignInBits(), getEncoding(), getFlags()); + return getTemporary(getContext(), getTag(), getName(), + getRawPictureString(), getSizeInBits(), + getAlignInBits(), getEncoding(), getBTFlags(), + getDecimalInfo()); } public: DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name), - (Tag, Name, 0, 0, 0, FlagZero)) + (Tag, Name, 0, 0, 0, BTFlagZero)) DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name, uint64_t SizeInBits, - uint32_t AlignInBits, unsigned Encoding, DIFlags Flags), - (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags)) + uint32_t AlignInBits, unsigned Encoding, + DIBTFlags BTFlags), + (Tag, Name, SizeInBits, AlignInBits, Encoding, BTFlags)) DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, MDString *Name, uint64_t SizeInBits, - uint32_t AlignInBits, unsigned Encoding, DIFlags Flags), - (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags)) + uint32_t AlignInBits, unsigned Encoding, + DIBTFlags BTFlags), + (Tag, Name, SizeInBits, AlignInBits, Encoding, BTFlags, + None)) + DEFINE_MDNODE_GET(DIBasicType, + (unsigned Tag, StringRef Name, MDString *PictureString, + uint64_t SizeInBits, uint32_t AlignInBits, + unsigned Encoding, DIBTFlags BTFlags, + Optional ExtInfo), + (Tag, Name, PictureString, SizeInBits, AlignInBits, + Encoding, BTFlags, ExtInfo)) + DEFINE_MDNODE_GET(DIBasicType, + (unsigned Tag, MDString *Name, MDString *PictureString, + uint64_t SizeInBits, uint32_t AlignInBits, + unsigned Encoding, DIBTFlags BTFlags, + Optional ExtInfo), + (Tag, Name, PictureString, SizeInBits, AlignInBits, + Encoding, BTFlags, ExtInfo)) TempDIBasicType clone() const { return cloneImpl(); } - + DIBTFlags getBTFlags() const { return BTFlags; } unsigned getEncoding() const { return Encoding; } enum class Signedness { Signed, Unsigned }; @@ -741,6 +821,21 @@ /// Return the signedness of this type, or None if this type is neither /// signed nor unsigned. Optional getSignedness() const; + bool isBigEndian() const { return getBTFlags() & BTFlagBigEndian; } + bool isLittleEndian() const { return getBTFlags() & BTFlagLittleEndian; } + bool isBinaryScale() const { return getBTFlags() & BTFlagBinaryScale; } + bool isDecimalScale() const { return getBTFlags() & BTFlagDecimalScale; } + bool hasDecimalInfo() const { return DecimalAttrInfo.hasValue(); } + Optional getDecimalInfo() const { return DecimalAttrInfo; } + StringRef getPictureString() const { return getStringOperand(3); } + MDString *getRawPictureString() const { return getOperandAs(3); } + uint8_t getDigitCount() const { + return DecimalAttrInfo.getValue().DigitCount; + } + uint8_t getDecimalSign() const { + return DecimalAttrInfo.getValue().DecimalSign; + } + int8_t getScale() const { return DecimalAttrInfo.getValue().Scale; } static bool classof(const Metadata *MD) { return MD->getMetadataID() == DIBasicTypeKind; diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -915,6 +915,7 @@ DWKEYWORD(CC, DwarfCC); DWKEYWORD(OP, DwarfOp); DWKEYWORD(MACINFO, DwarfMacinfo); + DWKEYWORD(DS, DwarfDecimalSign); #undef DWKEYWORD @@ -928,6 +929,11 @@ return lltok::DISPFlag; } + if (Keyword.startswith("DIBTFlag")) { + StrVal.assign(Keyword.begin(), Keyword.end()); + return lltok::DIBTFlag; + } + if (Keyword.startswith("CSK_")) { StrVal.assign(Keyword.begin(), Keyword.end()); return lltok::ChecksumKind; diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -3826,6 +3826,11 @@ : MDUnsignedField(DefaultTag, dwarf::DW_TAG_hi_user) {} }; +struct DwarfDecimalSignField : public MDUnsignedField { + DwarfDecimalSignField() : MDUnsignedField(0) {} + DwarfDecimalSignField(dwarf::DecimalSignEncoding DS) : MDUnsignedField(DS) {} +}; + struct DwarfMacinfoTypeField : public MDUnsignedField { DwarfMacinfoTypeField() : MDUnsignedField(0, dwarf::DW_MACINFO_vendor_ext) {} DwarfMacinfoTypeField(dwarf::MacinfoRecordType DefaultType) @@ -3867,6 +3872,10 @@ DISPFlagField() : MDFieldImpl(DISubprogram::SPFlagZero) {} }; +struct DIBTFlagField : public MDFieldImpl { + DIBTFlagField() : MDFieldImpl(DIBasicType::BTFlagZero) {} +}; + struct MDSignedField : public MDFieldImpl { int64_t Min; int64_t Max; @@ -3988,6 +3997,27 @@ return false; } +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, + DwarfDecimalSignField &Result) { + if (Lex.getKind() == lltok::APSInt) + return ParseMDField(Loc, Name, static_cast(Result)); + + if (Lex.getKind() != lltok::DwarfDecimalSign) + return TokError("expected DWARF Decimal sign"); + + // returns 0 for invalid values. + unsigned DS = dwarf::getDecimalSign(Lex.getStrVal()); + if (!DS) + return TokError("invalid DWARF decimal sign" + Twine(" '") + + Lex.getStrVal() + "'"); + assert(DS <= Result.Max && "Expected valid DWARF decimal sign"); + + Result.assign(DS); + Lex.Lex(); + return false; +} + template <> bool LLParser::ParseMDField(LocTy Loc, StringRef Name, DwarfMacinfoTypeField &Result) { @@ -4159,6 +4189,46 @@ return false; } +/// DIBTFlagField +/// ::= uint32 +/// ::= DIBTFlagBigEndian +/// ::= DIBTFlagBigEndian '|' DIBTFlag* '|' uint32 +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, DIBTFlagField &Result) { + + // Parser for a single flag. + auto parseFlag = [&](DIBasicType::DIBTFlags &Val) { + if (Lex.getKind() == lltok::APSInt && !Lex.getAPSIntVal().isSigned()) { + uint32_t TempVal = static_cast(Val); + bool Res = ParseUInt32(TempVal); + Val = static_cast(TempVal); + return Res; + } + + if (Lex.getKind() != lltok::DIBTFlag) + return TokError("expected debug info flag"); + + Val = DIBasicType::getFlag(Lex.getStrVal()); + if (!Val) + return TokError(Twine("invalid basicType debug info flag '") + + Lex.getStrVal() + "'"); + Lex.Lex(); + return false; + }; + + // Parse the flags and combine them together. + DIBasicType::DIBTFlags Combined = DIBasicType::BTFlagZero; + do { + DIBasicType::DIBTFlags Val; + if (parseFlag(Val)) + return true; + Combined |= Val; + } while (EatIfPresent(lltok::bar)); + + Result.assign(Combined); + return false; +} + /// DISPFlagField /// ::= uint32 /// ::= DISPFlagVector @@ -4488,8 +4558,10 @@ } /// ParseDIBasicType: -/// ::= !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, -/// encoding: DW_ATE_encoding, flags: 0) +/// ::= !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 1, +/// encoding: DW_ATE_encoding, pic: "picture_string", +/// digits: digit_count, sign: decimal_sign, +/// scale: decimal/binary scale, flags: 0) bool LLParser::ParseDIBasicType(MDNode *&Result, bool IsDistinct) { #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ OPTIONAL(tag, DwarfTagField, (dwarf::DW_TAG_base_type)); \ @@ -4497,12 +4569,26 @@ OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX)); \ OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \ OPTIONAL(encoding, DwarfAttEncodingField, ); \ - OPTIONAL(flags, DIFlagField, ); + OPTIONAL(pic, MDStringField, ); \ + OPTIONAL(digits, MDUnsignedField, ); \ + OPTIONAL(sign, DwarfDecimalSignField, ); \ + OPTIONAL(scale, MDSignedField, ); \ + OPTIONAL(btFlags, DIBTFlagField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS - Result = GET_OR_DISTINCT(DIBasicType, (Context, tag.Val, name.Val, size.Val, - align.Val, encoding.Val, flags.Val)); + if (pic.Seen || digits.Seen || sign.Seen || scale.Seen) { + Optional DAInfo; + DAInfo.emplace(digits.Val, sign.Val, scale.Val); + + Result = GET_OR_DISTINCT(DIBasicType, + (Context, tag.Val, name.Val, pic.Val, size.Val, + align.Val, encoding.Val, btFlags.Val, DAInfo)); + } else { + Result = + GET_OR_DISTINCT(DIBasicType, (Context, tag.Val, name.Val, size.Val, + align.Val, encoding.Val, btFlags.Val)); + } return false; } diff --git a/llvm/lib/AsmParser/LLToken.h b/llvm/lib/AsmParser/LLToken.h --- a/llvm/lib/AsmParser/LLToken.h +++ b/llvm/lib/AsmParser/LLToken.h @@ -462,8 +462,10 @@ DwarfOp, // DW_OP_foo DIFlag, // DIFlagFoo DISPFlag, // DISPFlagFoo + DIBTFlag, // DIBTFlagFoo DwarfMacinfo, // DW_MACINFO_foo ChecksumKind, // CSK_foo + DwarfDecimalSign, // DW_DS_foo // Type valued tokens (TyVal). Type, diff --git a/llvm/lib/BinaryFormat/Dwarf.cpp b/llvm/lib/BinaryFormat/Dwarf.cpp --- a/llvm/lib/BinaryFormat/Dwarf.cpp +++ b/llvm/lib/BinaryFormat/Dwarf.cpp @@ -37,6 +37,13 @@ .Default(DW_TAG_invalid); } +unsigned llvm::dwarf::getDecimalSign(StringRef DSString) { + return StringSwitch(DSString) +#define HANDLE_DW_DS(ID, NAME) .Case("DW_DS_" #NAME, DW_DS_##NAME) +#include "llvm/BinaryFormat/Dwarf.def" + .Default(0); +} + unsigned llvm::dwarf::TagVersion(dwarf::Tag Tag) { switch (Tag) { default: diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -1290,18 +1290,33 @@ break; } case bitc::METADATA_BASIC_TYPE: { - if (Record.size() < 6 || Record.size() > 7) - return error("Invalid record"); + if (Record.size() < 6 || Record.size() > 11) + return error("Invalid record"); IsDistinct = Record[0]; - DINode::DIFlags Flags = (Record.size() > 6) ? - static_cast(Record[6]) : DINode::FlagZero; - MetadataList.assignValue( - GET_OR_DISTINCT(DIBasicType, - (Context, Record[1], getMDString(Record[2]), Record[3], - Record[4], Record[5], Flags)), - NextMetadataNo); + DIBasicType::DIBTFlags Flags = + (Record.size() > 6) ? static_cast(Record[6]) + : DIBasicType::DIBTFlags::BTFlagZero; + + if (Record.size() > 7) { + Optional DAInfo; + DAInfo.emplace(Record[8], Record[9], Record[10]); + + MetadataList.assignValue( + GET_OR_DISTINCT(DIBasicType, + (Context, Record[1], getMDString(Record[2]), + Record[7] ? getMDString(Record[7]) : nullptr, + Record[3], Record[4], Record[5], Flags, DAInfo)), + NextMetadataNo); + } else { + MetadataList.assignValue( + GET_OR_DISTINCT(DIBasicType, + (Context, Record[1], getMDString(Record[2]), + Record[3], Record[4], Record[5], Flags)), + NextMetadataNo); + } + NextMetadataNo++; break; } diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1546,7 +1546,18 @@ Record.push_back(N->getSizeInBits()); Record.push_back(N->getAlignInBits()); Record.push_back(N->getEncoding()); - Record.push_back(N->getFlags()); + Record.push_back(N->getBTFlags()); + + // Below are the optional decimal attributes in case base type is decimal + // type, For digitcount and decimal sign zero is not-in-use value, for scale + // the value is in use or not is represented by BTFlags + // DIBTFlagDecimalScal or /DIBTFlagBinaryScale(but not both). + if (N->hasDecimalInfo()) { + Record.push_back(VE.getMetadataOrNullID(N->getRawPictureString())); + Record.push_back(N->getDigitCount()); + Record.push_back(N->getDecimalSign()); + Record.push_back(N->getScale()); + } Stream.EmitRecord(bitc::METADATA_BASIC_TYPE, Record, Abbrev); Record.clear(); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -782,6 +782,24 @@ addUInt(Buffer, dwarf::DW_AT_endianity, None, dwarf::DW_END_big); else if (BTy->isLittleEndian()) addUInt(Buffer, dwarf::DW_AT_endianity, None, dwarf::DW_END_little); + + if (BTy->hasDecimalInfo()) { + StringRef PictureString = BTy->getPictureString(); + if (!PictureString.empty()) + addString(Buffer, dwarf::DW_AT_picture_string, PictureString); + + if (const uint8_t digits = BTy->getDigitCount()) + addUInt(Buffer, dwarf::DW_AT_digit_count, None, digits); + + if (const uint8_t sign = BTy->getDecimalSign()) + addUInt(Buffer, dwarf::DW_AT_decimal_sign, None, sign); + + const uint8_t scale = BTy->getScale(); + if (BTy->isBinaryScale()) + addSInt(Buffer, dwarf::DW_AT_binary_scale, None, scale); + else if (BTy->isDecimalScale()) + addSInt(Buffer, dwarf::DW_AT_decimal_scale, None, scale); + } } void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIDerivedType *DTy) { diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -1617,6 +1617,7 @@ void printBool(StringRef Name, bool Value, Optional Default = None); void printDIFlags(StringRef Name, DINode::DIFlags Flags); void printDISPFlags(StringRef Name, DISubprogram::DISPFlags Flags); + void printDIBTFlags(StringRef Name, DIBasicType::DIBTFlags Flags); template void printDwarfEnum(StringRef Name, IntTy Value, Stringifier toString, bool ShouldSkipZero = true); @@ -1715,6 +1716,26 @@ Out << FlagsFS << Extra; } +void MDFieldPrinter::printDIBTFlags(StringRef Name, + DIBasicType::DIBTFlags Flags) { + if (!Flags) { + return; + } + + Out << FS << Name << ": "; + SmallVector SplitFlags; + auto Extra = DIBasicType::splitFlags(Flags, SplitFlags); + + FieldSeparator FlagsFS(" | "); + for (auto F : SplitFlags) { + auto StringF = DIBasicType::getFlagString(F); + assert(!StringF.empty() && "Expected valid flag"); + Out << FlagsFS << StringF; + } + if (Extra || SplitFlags.empty()) + Out << FlagsFS << Extra; +} + void MDFieldPrinter::printDISPFlags(StringRef Name, DISubprogram::DISPFlags Flags) { // Always print this field, because no flags in the IR at all will be @@ -1839,7 +1860,17 @@ Printer.printInt("align", N->getAlignInBits()); Printer.printDwarfEnum("encoding", N->getEncoding(), dwarf::AttributeEncodingString); - Printer.printDIFlags("flags", N->getFlags()); + if (N->hasDecimalInfo()) { + Printer.printString("pic", N->getPictureString()); + Printer.printInt("digits", N->getDigitCount()); + Printer.printDwarfEnum("sign", N->getDecimalSign(), + dwarf::DecimalSignString); + if (N->isDecimalScale() || N->isBinaryScale()) + Printer.printInt("scale", N->getScale(), + /*ShouldSkipZero*/ false); + } + + Printer.printDIBTFlags("btFlags", N->getBTFlags()); Out << ")"; } diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -260,12 +260,28 @@ DIBasicType *DIBuilder::createBasicType(StringRef Name, uint64_t SizeInBits, unsigned Encoding, - DINode::DIFlags Flags) { + DIBasicType::DIBTFlags Flags) { assert(!Name.empty() && "Unable to create type without name"); return DIBasicType::get(VMContext, dwarf::DW_TAG_base_type, Name, SizeInBits, 0, Encoding, Flags); } +DIBasicType *DIBuilder::createBasicType(StringRef Name, StringRef Pic, + uint64_t SizeInBits, unsigned Encoding, + uint8_t DigitCount, uint8_t DecimalSign, + int8_t Scale, + DIBasicType::DIBTFlags Flags) { + assert(!Name.empty() && "Unable to create type without name"); + MDString *PicString = nullptr; + if (!Pic.empty()) + PicString = MDString::get(VMContext, Pic); + + Optional DAInfo; + DAInfo.emplace(DigitCount, DecimalSign, Scale); + return DIBasicType::get(VMContext, dwarf::DW_TAG_base_type, Name, PicString, + SizeInBits, 0, Encoding, Flags, DAInfo); +} + DIDerivedType *DIBuilder::createQualifiedType(unsigned Tag, DIType *FromTy) { return DIDerivedType::get(VMContext, Tag, "", nullptr, 0, nullptr, FromTy, 0, 0, 0, None, DINode::FlagZero); diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -743,6 +743,10 @@ return static_cast(Flags); } +static DIBasicType::DIBTFlags map_from_llvmDIBTFlags(LLVMDIBTFlags Flags) { + return static_cast(Flags); +} + static DISubprogram::DISPFlags pack_into_DISPFlags(bool IsLocalToUnit, bool IsDefinition, bool IsOptimized) { return DISubprogram::toSPFlags(IsLocalToUnit, IsDefinition, IsOptimized); @@ -1030,14 +1034,13 @@ unwrapDI(Ty), Subs)); } -LLVMMetadataRef -LLVMDIBuilderCreateBasicType(LLVMDIBuilderRef Builder, const char *Name, - size_t NameLen, uint64_t SizeInBits, - LLVMDWARFTypeEncoding Encoding, - LLVMDIFlags Flags) { - return wrap(unwrap(Builder)->createBasicType({Name, NameLen}, - SizeInBits, Encoding, - map_from_llvmDIFlags(Flags))); +LLVMMetadataRef LLVMDIBuilderCreateBasicType(LLVMDIBuilderRef Builder, + const char *Name, size_t NameLen, + uint64_t SizeInBits, + LLVMDWARFTypeEncoding Encoding, + LLVMDIBTFlags Flags) { + return wrap(unwrap(Builder)->createBasicType( + {Name, NameLen}, SizeInBits, Encoding, map_from_llvmDIBTFlags(Flags))); } LLVMMetadataRef LLVMDIBuilderCreatePointerType( diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -342,16 +342,50 @@ } DIBasicType *DIBasicType::getImpl(LLVMContext &Context, unsigned Tag, - MDString *Name, uint64_t SizeInBits, - uint32_t AlignInBits, unsigned Encoding, - DIFlags Flags, StorageType Storage, - bool ShouldCreate) { + MDString *Name, MDString *PictureString, + uint64_t SizeInBits, uint32_t AlignInBits, + unsigned Encoding, DIBTFlags BTFlags, + Optional DAInfo, + StorageType Storage, bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); - DEFINE_GETIMPL_LOOKUP(DIBasicType, - (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags)); - Metadata *Ops[] = {nullptr, nullptr, Name}; - DEFINE_GETIMPL_STORE(DIBasicType, (Tag, SizeInBits, AlignInBits, Encoding, - Flags), Ops); + DEFINE_GETIMPL_LOOKUP(DIBasicType, (Tag, Name, PictureString, SizeInBits, + AlignInBits, Encoding, BTFlags, DAInfo)); + Metadata *Ops[] = {nullptr, nullptr, Name, PictureString}; + DEFINE_GETIMPL_STORE( + DIBasicType, (Tag, SizeInBits, AlignInBits, Encoding, BTFlags, DAInfo), + Ops); +} + +DIBasicType::DIBTFlags DIBasicType::getFlag(StringRef Flag) { + return StringSwitch(Flag) +#define HANDLE_DIBT_FLAG(ID, NAME) .Case("DIBTFlag" #NAME, BTFlag##NAME) +#include "llvm/IR/DebugInfoFlags.def" + .Default(BTFlagZero); +} + +StringRef DIBasicType::getFlagString(DIBTFlags Flag) { + switch (Flag) { + // Appease a warning. +#define HANDLE_DIBT_FLAG(ID, NAME) \ + case BTFlag##NAME: \ + return "DIBTFlag" #NAME; +#include "llvm/IR/DebugInfoFlags.def" + } + return ""; +} + +DIBasicType::DIBTFlags +DIBasicType::splitFlags(DIBTFlags Flags, + SmallVectorImpl &SplitFlags) { + // Multi-bit fields can require special handling. In our case all its values + // happen to be single-bit values. +#define HANDLE_DIBT_FLAG(ID, NAME) \ + if (DIBTFlags Bit = Flags & BTFlag##NAME) { \ + SplitFlags.push_back(Bit); \ + Flags &= ~Bit; \ + } +#include "llvm/IR/DebugInfoFlags.def" + return Flags; } Optional DIBasicType::getSignedness() const { diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -376,25 +376,33 @@ template <> struct MDNodeKeyImpl { unsigned Tag; MDString *Name; + MDString *PictureString; uint64_t SizeInBits; uint32_t AlignInBits; unsigned Encoding; - unsigned Flags; - - MDNodeKeyImpl(unsigned Tag, MDString *Name, uint64_t SizeInBits, - uint32_t AlignInBits, unsigned Encoding, unsigned Flags) - : Tag(Tag), Name(Name), SizeInBits(SizeInBits), AlignInBits(AlignInBits), - Encoding(Encoding), Flags(Flags) {} + unsigned BTFlags; + Optional DecimalAttrInfo; + + MDNodeKeyImpl(unsigned Tag, MDString *Name, MDString *PictureString, + uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, + unsigned BTFlags, + Optional DecimalAttrInfo) + : Tag(Tag), Name(Name), PictureString(PictureString), + SizeInBits(SizeInBits), AlignInBits(AlignInBits), Encoding(Encoding), + BTFlags(BTFlags), DecimalAttrInfo(DecimalAttrInfo) {} MDNodeKeyImpl(const DIBasicType *N) - : Tag(N->getTag()), Name(N->getRawName()), SizeInBits(N->getSizeInBits()), - AlignInBits(N->getAlignInBits()), Encoding(N->getEncoding()), Flags(N->getFlags()) {} + : Tag(N->getTag()), Name(N->getRawName()), + PictureString(N->getRawPictureString()), SizeInBits(N->getSizeInBits()), + AlignInBits(N->getAlignInBits()), Encoding(N->getEncoding()), + BTFlags(N->getBTFlags()), DecimalAttrInfo(N->getDecimalInfo()) {} bool isKeyOf(const DIBasicType *RHS) const { return Tag == RHS->getTag() && Name == RHS->getRawName() && + PictureString == RHS->getRawPictureString() && SizeInBits == RHS->getSizeInBits() && AlignInBits == RHS->getAlignInBits() && - Encoding == RHS->getEncoding() && - Flags == RHS->getFlags(); + Encoding == RHS->getEncoding() && BTFlags == RHS->getBTFlags() && + DecimalAttrInfo == RHS->getDecimalInfo(); } unsigned getHashValue() const { diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -907,8 +907,17 @@ AssertDI(N.getTag() == dwarf::DW_TAG_base_type || N.getTag() == dwarf::DW_TAG_unspecified_type, "invalid tag", &N); - AssertDI(!(N.isBigEndian() && N.isLittleEndian()) , - "has conflicting flags", &N); + AssertDI(!(N.isBigEndian() && N.isLittleEndian()), + "has conflicting endianess flags", &N); + AssertDI(!(N.isBinaryScale() && N.isDecimalScale()), + "has conflicting scale flags", &N); + if (N.hasDecimalInfo()) + AssertDI(N.getEncoding() == dwarf::DW_ATE_packed_decimal || + N.getEncoding() == dwarf::DW_ATE_numeric_string || + N.getEncoding() == dwarf::DW_ATE_edited || + N.getEncoding() == dwarf::DW_ATE_signed_fixed || + N.getEncoding() == dwarf::DW_ATE_unsigned_fixed, + "Invalid encoding for extended base type", &N); } void Verifier::visitDIDerivedType(const DIDerivedType &N) { diff --git a/llvm/test/Assembler/debug-info.ll b/llvm/test/Assembler/debug-info.ll --- a/llvm/test/Assembler/debug-info.ll +++ b/llvm/test/Assembler/debug-info.ll @@ -1,8 +1,8 @@ ; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s ; RUN: verify-uselistorder %s -; CHECK: !named = !{!0, !0, !1, !2, !3, !4, !5, !6, !7, !8, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, !37, !38, !39} -!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, !37, !38, !39, !40, !41, !42} +; CHECK: !named = !{!0, !0, !1, !2, !3, !4, !5, !6, !7, !8, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, !37, !38, !39, !40, !41, !42, !43, !44, !45, !46} +!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, !37, !38, !39, !40, !41, !42, !43, !44, !45, !46, !47, !48, !49} ; CHECK: !0 = !DISubrange(count: 3) ; CHECK-NEXT: !1 = !DISubrange(count: 3, lowerBound: 4) @@ -95,7 +95,22 @@ !39 = !DIFile(filename: "file", directory: "dir", source: "int source() { }\0A") !40 = !DIFile(filename: "file", directory: "dir", checksumkind: CSK_MD5, checksum: "3a420e2646916a475e68de8d48f779f5", source: "int source() { }\0A") -; CHECK-NEXT: !38 = !DIBasicType(name: "u64.be", size: 64, align: 1, encoding: DW_ATE_unsigned, flags: DIFlagBigEndian) -; CHECK-NEXT: !39 = !DIBasicType(name: "u64.le", size: 64, align: 1, encoding: DW_ATE_unsigned, flags: DIFlagLittleEndian) -!41 = !DIBasicType(name: "u64.be", size: 64, align: 1, encoding: DW_ATE_unsigned, flags: DIFlagBigEndian) -!42 = !DIBasicType(name: "u64.le", size: 64, align: 1, encoding: DW_ATE_unsigned, flags: DIFlagLittleEndian) +; CHECK-NEXT: !38 = !DIBasicType(name: "u64.be", size: 64, align: 1, encoding: DW_ATE_unsigned, btFlags: DIBTFlagBigEndian) +; CHECK-NEXT: !39 = !DIBasicType(name: "u64.le", size: 64, align: 1, encoding: DW_ATE_unsigned, btFlags: DIBTFlagLittleEndian) +!41 = !DIBasicType(name: "u64.be", size: 64, align: 1, encoding: DW_ATE_unsigned, btFlags: DIBTFlagBigEndian) +!42 = !DIBasicType(name: "u64.le", size: 64, align: 1, encoding: DW_ATE_unsigned, btFlags: DIBTFlagLittleEndian) + +; CHECK-NEXT !40 = !DIBasicType(name: "ext1", size: 48, align: 1, encoding: DW_ATE_numeric_string, pic: "S999V999", digits: 6, sign: DW_DS_trailing_overpunch, scale: -3, btFlags: DIBTFlagDecimalScale) +; CHECK-NEXT !41 = !DIBasicType(name: "ext2", size: 16, align: 1, encoding: DW_ATE_packed_decimal, pic: "999PP", digits: 3, sign: DW_DS_unsigned, scale: 2, btFlags: DIBTFlagDecimalScale) +; CHECK-NEXT !42 = !DIBasicType(name: "ext3", size: 72, align: 1, encoding: DW_ATE_edited, pic: "+z,zz9.99", digits: 6, scale: -2, btFlags: DIBTFlagDecimalScale) +; CHECK-NEXT !43 = !DIBasicType(name: "ext4", size: 64, align: 1, encoding: DW_ATE_edited, pic: "ABBA(5)") +; CHECK-NEXT !44 = !DIBasicType(name: "ext5", size: 32, align: 1, encoding: DW_ATE_signed_fixed, pic: "S999V999", digits: 5, scale: -2, btFlags: DIBTFlagDecimalScale) +; CHECK-NEXT !45 = !DIBasicType(name: "ext6", size: 40, align: 1, encoding: DW_ATE_packed_decimal, pic: "S9(3)V99", digits: 5, scale: -2, btFlags: DIBTFlagsDecimalScale) +; CHECK-NEXT !46 = !DIBasicType(name: "ext7", size: 40, align: 1, encoding: DW_ATE_packed_decimal, pic: "S9(3)V99", digits: 5, scale: -2, btFlags: DIBTFlagBinaryScale) +!43 = !DIBasicType(name: "ext1", size: 48, align: 1, encoding: DW_ATE_numeric_string, pic: "S999V999", digits: 6, sign: DW_DS_trailing_overpunch, scale: -3, btFlags: DIBTFlagDecimalScale) +!44 = !DIBasicType(name: "ext2", size: 16, align: 1, encoding: DW_ATE_packed_decimal, pic: "999PP", digits: 3, sign: DW_DS_unsigned, scale: 2, btFlags: DIBTFlagDecimalScale) +!45 = !DIBasicType(name: "ext3", size: 72, align: 1, encoding: DW_ATE_edited, pic: "+z,zz9.99", digits: 6, scale: -2, btFlags: DIBTFlagDecimalScale) +!46 = !DIBasicType(name: "ext4", size: 64, align: 1, encoding: DW_ATE_edited, pic: "ABBA(5)") +!47 = !DIBasicType(name: "ext5", size: 32, align: 1, encoding: DW_ATE_signed_fixed, pic: "S999V999", digits: 5, scale: -2, btFlags: DIBTFlagDecimalScale) +!48 = !DIBasicType(name: "ext6", size: 40, align: 1, encoding: DW_ATE_packed_decimal, pic: "S9(3)V99", digits: 5, scale: -2, btFlags: DIBTFlagDecimalScale) +!49 = !DIBasicType(name: "ext7", size: 40, align: 1, encoding: DW_ATE_packed_decimal, pic: "S9(3)V99", digits: 5, scale: -2, btFlags: DIBTFlagBinaryScale) diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp --- a/llvm/unittests/IR/MetadataTest.cpp +++ b/llvm/unittests/IR/MetadataTest.cpp @@ -1202,9 +1202,8 @@ typedef MetadataTest DIBasicTypeTest; TEST_F(DIBasicTypeTest, get) { - auto *N = - DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33, 26, 7, - DINode::FlagZero); + auto *N = DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33, + 26, 7, DIBasicType::BTFlagZero); EXPECT_EQ(dwarf::DW_TAG_base_type, N->getTag()); EXPECT_EQ("special", N->getName()); EXPECT_EQ(33u, N->getSizeInBits()); @@ -1213,31 +1212,31 @@ EXPECT_EQ(0u, N->getLine()); EXPECT_EQ(DINode::FlagZero, N->getFlags()); EXPECT_EQ(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33, - 26, 7, DINode::FlagZero)); + 26, 7, DIBasicType::BTFlagZero)); EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_unspecified_type, - "special", 33, 26, 7, DINode::FlagZero)); - EXPECT_NE(N, - DIBasicType::get(Context, dwarf::DW_TAG_base_type, "s", 33, 26, 7, - DINode::FlagZero)); + "special", 33, 26, 7, DIBasicType::BTFlagZero)); + EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "s", 33, 26, + 7, DIBasicType::BTFlagZero)); EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 32, - 26, 7, DINode::FlagZero)); + 26, 7, DIBasicType::BTFlagZero)); EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33, - 25, 7, DINode::FlagZero)); + 25, 7, DIBasicType::BTFlagZero)); EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33, - 26, 6, DINode::FlagZero)); + 26, 6, DIBasicType::BTFlagZero)); EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33, - 26, 7, DINode::FlagBigEndian)); + 26, 7, DIBasicType::BTFlagBigEndian)); EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33, - 26, 7, DINode::FlagLittleEndian)); + 26, 7, DIBasicType::BTFlagLittleEndian)); TempDIBasicType Temp = N->clone(); EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); } TEST_F(DIBasicTypeTest, getWithLargeValues) { - auto *N = DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", - UINT64_MAX, UINT32_MAX - 1, 7, DINode::FlagZero); + auto *N = + DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", UINT64_MAX, + UINT32_MAX - 1, 7, DIBasicType::BTFlagZero); EXPECT_EQ(UINT64_MAX, N->getSizeInBits()); EXPECT_EQ(UINT32_MAX - 1, N->getAlignInBits()); } @@ -1254,12 +1253,68 @@ EXPECT_EQ(DINode::FlagZero, N->getFlags()); } +TEST_F(DIBasicTypeTest, getOptionalDecimalInfo) { + auto *N = DIBasicType::get( + Context, dwarf::DW_TAG_base_type, "ext1", + MDString::get(Context, "S999V99"), 40, 1, dwarf::DW_ATE_numeric_string, + DIBasicType::BTFlagDecimalScale, + DIBasicType::DecimalInfo{5, dwarf::DW_DS_trailing_overpunch, -2}); + + EXPECT_EQ(dwarf::DW_TAG_base_type, N->getTag()); + EXPECT_EQ("ext1", N->getName()); + EXPECT_EQ(40u, N->getSizeInBits()); + EXPECT_EQ(1u, N->getAlignInBits()); + EXPECT_EQ(dwarf::DW_ATE_numeric_string, N->getEncoding()); + EXPECT_EQ(DIBasicType::BTFlagDecimalScale, N->getBTFlags()); + EXPECT_EQ("S999V99", N->getPictureString()); + EXPECT_EQ(dwarf::DW_DS_trailing_overpunch, N->getDecimalSign()); + EXPECT_EQ(-2, N->getScale()); + EXPECT_EQ(5, N->getDigitCount()); + + EXPECT_EQ( + N, DIBasicType::get( + Context, dwarf::DW_TAG_base_type, "ext1", + MDString::get(Context, "S999V99"), 40, 1, + dwarf::DW_ATE_numeric_string, DIBasicType::BTFlagDecimalScale, + DIBasicType::DecimalInfo{5, dwarf::DW_DS_trailing_overpunch, -2})); + + /// Generally this fails verifier as we are trying to create extended encoding + /// without any extended info. + EXPECT_NE( + N, DIBasicType::get( + Context, dwarf::DW_TAG_base_type, "ext1", + MDString::get(Context, "S999999"), 40, 1, + dwarf::DW_ATE_numeric_string, DIBasicType::BTFlagZero, + DIBasicType::DecimalInfo{5, dwarf::DW_DS_trailing_overpunch, -2})); + EXPECT_NE( + N, DIBasicType::get( + Context, dwarf::DW_TAG_base_type, "ext1", + MDString::get(Context, "S999V99"), 40, 1, + dwarf::DW_ATE_numeric_string, DIBasicType::BTFlagZero, + DIBasicType::DecimalInfo{4, dwarf::DW_DS_trailing_overpunch, -2})); + EXPECT_NE( + N, DIBasicType::get( + Context, dwarf::DW_TAG_base_type, "ext1", + MDString::get(Context, "S999V99"), 40, 1, + dwarf::DW_ATE_numeric_string, DIBasicType::BTFlagZero, + DIBasicType::DecimalInfo{5, dwarf::DW_DS_leading_overpunch, -2})); + EXPECT_NE( + N, DIBasicType::get( + Context, dwarf::DW_TAG_base_type, "ext1", + MDString::get(Context, "S999V99"), 40, 1, + dwarf::DW_ATE_numeric_string, DIBasicType::BTFlagZero, + DIBasicType::DecimalInfo{5, dwarf::DW_DS_trailing_overpunch, -1})); + + TempDIBasicType Temp = N->clone(); + EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); +} + typedef MetadataTest DITypeTest; TEST_F(DITypeTest, clone) { // Check that DIType has a specialized clone that returns TempDIType. DIType *N = DIBasicType::get(Context, dwarf::DW_TAG_base_type, "int", 32, 32, - dwarf::DW_ATE_signed, DINode::FlagZero); + dwarf::DW_ATE_signed, DIBasicType::BTFlagZero); TempDIType Temp = N->clone(); EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));