Index: include/llvm/BinaryFormat/Dwarf.h =================================================================== --- include/llvm/BinaryFormat/Dwarf.h +++ include/llvm/BinaryFormat/Dwarf.h @@ -141,11 +141,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 + DW_DS_Invalid = 0, +#define HANDLE_DW_DS(ID, NAME) DW_DS_##NAME = ID, +#include "llvm/BinaryFormat/Dwarf.def" }; enum EndianityEncoding { @@ -450,6 +448,7 @@ /// /// @{ unsigned getTag(StringRef TagString); +unsigned getDecimalSign(StringRef DSString); unsigned getOperationEncoding(StringRef OperationEncodingString); unsigned getVirtuality(StringRef VirtualityString); unsigned getLanguage(StringRef LanguageString); Index: include/llvm/BinaryFormat/Dwarf.def =================================================================== --- include/llvm/BinaryFormat/Dwarf.def +++ include/llvm/BinaryFormat/Dwarf.def @@ -21,7 +21,7 @@ defined HANDLE_DW_RLE || defined HANDLE_DW_CFA || \ 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 @@ -105,6 +105,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) HANDLE_DW_TAG(0x0001, array_type, 2, DWARF) HANDLE_DW_TAG(0x0002, class_type, 2, DWARF) @@ -695,6 +699,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) @@ -920,3 +931,4 @@ #undef HANDLE_DWARF_SECTION #undef HANDLE_DW_IDX #undef HANDLE_DW_END +#undef HANDLE_DW_DS Index: include/llvm/IR/DIBuilder.h =================================================================== --- include/llvm/IR/DIBuilder.h +++ include/llvm/IR/DIBuilder.h @@ -195,6 +195,23 @@ unsigned Encoding, DINode::DIFlags Flags = DINode::FlagZero); + /// 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, + Optional DigitCount = None, + Optional DecimalSign = None, + Optional Scale = None, + DINode::DIFlags Flags = DINode::FlagZero); + /// Create debugging information entry for a qualified /// type, e.g. 'const int'. /// \param Tag Tag identifing type, e.g. dwarf::TAG_volatile_type Index: include/llvm/IR/DebugInfoFlags.def =================================================================== --- include/llvm/IR/DebugInfoFlags.def +++ include/llvm/IR/DebugInfoFlags.def @@ -51,6 +51,7 @@ HANDLE_DI_FLAG((1 << 27), BigEndian) HANDLE_DI_FLAG((1 << 28), LittleEndian) HANDLE_DI_FLAG((1 << 29), AllCallsDescribed) +HANDLE_DI_FLAG((1 << 30), BinaryScale) // To avoid needing a dedicated value for IndirectVirtualBase, we use // the bitwise or of Virtual and FwdDecl, which does not otherwise @@ -60,7 +61,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 << 30), Largest) #undef DI_FLAG_LARGEST_NEEDED #endif Index: include/llvm/IR/DebugInfoMetadata.h =================================================================== --- include/llvm/IR/DebugInfoMetadata.h +++ include/llvm/IR/DebugInfoMetadata.h @@ -715,6 +715,7 @@ } bool isBigEndian() const { return getFlags() & FlagBigEndian; } bool isLittleEndian() const { return getFlags() & FlagLittleEndian; } + bool isBinaryScale() const { return getFlags() & FlagBinaryScale; } static bool classof(const Metadata *MD) { switch (MD->getMetadataID()) { @@ -737,14 +738,32 @@ friend class LLVMContextImpl; friend class MDNode; +public: + /// 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 { + Optional DigitCount; + Optional DecimalSign; + Optional Scale; + + bool operator==(const DecimalInfo &RHS) const { + return DigitCount == RHS.DigitCount && DecimalSign == RHS.DecimalSign && + Scale == RHS.Scale; + } + }; + +private: unsigned Encoding; + Optional DecimalAttrInfo; DIBasicType(LLVMContext &C, StorageType Storage, unsigned Tag, uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, - DIFlags Flags, ArrayRef Ops) + DIFlags Flags, Optional DecimalAttrInfo, + ArrayRef Ops) : DIType(C, DIBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, Flags, Ops), - Encoding(Encoding) {} + Encoding(Encoding), DecimalAttrInfo(DecimalAttrInfo) {} ~DIBasicType() = default; static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, @@ -752,19 +771,43 @@ uint32_t AlignInBits, unsigned Encoding, DIFlags Flags, 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, Flags, 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); + DIFlags Flags, + Optional DecimalAttrInfo, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Tag, Name, nullptr, SizeInBits, AlignInBits, + Encoding, Flags, DecimalAttrInfo, Storage, ShouldCreate); + } + + static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Name, MDString *PictureString, + uint64_t SizeInBits, uint32_t AlignInBits, + unsigned Encoding, DIFlags Flags, + Optional DecimalAttrInfo, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), + PictureString, SizeInBits, AlignInBits, Encoding, Flags, + DecimalAttrInfo, Storage, ShouldCreate); + } + + static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Name, MDString *PictureString, + uint64_t SizeInBits, uint32_t AlignInBits, + unsigned Encoding, DIFlags Flags, + 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(), getFlags(), + getDecimalInfo()); } public: @@ -777,7 +820,21 @@ DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, MDString *Name, uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, DIFlags Flags), - (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags)) + (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags, None)) + DEFINE_MDNODE_GET(DIBasicType, + (unsigned Tag, StringRef Name, MDString *PictureString, + uint64_t SizeInBits, uint32_t AlignInBits, + unsigned Encoding, DIFlags Flags, + Optional ExtInfo), + (Tag, Name, PictureString, SizeInBits, AlignInBits, + Encoding, Flags, ExtInfo)) + DEFINE_MDNODE_GET(DIBasicType, + (unsigned Tag, MDString *Name, MDString *PictureString, + uint64_t SizeInBits, uint32_t AlignInBits, + unsigned Encoding, DIFlags Flags, + Optional ExtInfo), + (Tag, Name, PictureString, SizeInBits, AlignInBits, + Encoding, Flags, ExtInfo)) TempDIBasicType clone() const { return cloneImpl(); } @@ -789,6 +846,23 @@ /// signed nor unsigned. Optional getSignedness() const; + bool hasDecimalInfo() const { return DecimalAttrInfo.hasValue(); } + Optional getDecimalInfo() const { return DecimalAttrInfo; } + StringRef getPictureString() const { return getStringOperand(3); } + MDString *getRawPictureString() const { return getOperandAs(3); } + + Optional getDigitCount() const { + return DecimalAttrInfo.getValue().DigitCount; + } + + Optional getDecimalSign() const { + return DecimalAttrInfo.getValue().DecimalSign; + } + + Optional getScale() const { + return DecimalAttrInfo.getValue().Scale; + } + static bool classof(const Metadata *MD) { return MD->getMetadataID() == DIBasicTypeKind; } Index: lib/AsmParser/LLLexer.cpp =================================================================== --- lib/AsmParser/LLLexer.cpp +++ lib/AsmParser/LLLexer.cpp @@ -787,6 +787,10 @@ KEYWORD(info); KEYWORD(byte); KEYWORD(bit); + KEYWORD(pic); + KEYWORD(digits); + KEYWORD(scale); + KEYWORD(sign); #undef KEYWORD @@ -893,6 +897,7 @@ DWKEYWORD(CC, DwarfCC); DWKEYWORD(OP, DwarfOp); DWKEYWORD(MACINFO, DwarfMacinfo); + DWKEYWORD(DS, DwarfDecimalSign); #undef DWKEYWORD Index: lib/AsmParser/LLParser.cpp =================================================================== --- lib/AsmParser/LLParser.cpp +++ lib/AsmParser/LLParser.cpp @@ -3688,6 +3688,11 @@ : MDUnsignedField(DefaultTag, dwarf::DW_TAG_hi_user) {} }; +struct DwarfDecimalSignField : public MDUnsignedField { + DwarfDecimalSignField() : MDUnsignedField(dwarf::DW_DS_Invalid) {} + DwarfDecimalSignField(dwarf::DecimalSignEncoding DS) : MDUnsignedField(DS) {} +}; + struct DwarfMacinfoTypeField : public MDUnsignedField { DwarfMacinfoTypeField() : MDUnsignedField(0, dwarf::DW_MACINFO_vendor_ext) {} DwarfMacinfoTypeField(dwarf::MacinfoRecordType DefaultType) @@ -3846,6 +3851,26 @@ 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"); + + unsigned DS = dwarf::getDecimalSign(Lex.getStrVal()); + if (DS == dwarf::DW_DS_Invalid) + 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) { @@ -4306,8 +4331,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)); \ @@ -4315,12 +4342,30 @@ OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX)); \ OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \ OPTIONAL(encoding, DwarfAttEncodingField, ); \ + OPTIONAL(pic, MDStringField, ); \ + OPTIONAL(digits, MDUnsignedField, ); \ + OPTIONAL(sign, DwarfDecimalSignField, (dwarf::DW_DS_Invalid)); \ + OPTIONAL(scale, MDSignedField, ); \ OPTIONAL(flags, DIFlagField, ); 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) { + DIBasicType::DecimalInfo DAInfo; + if (digits.Seen) + DAInfo.DigitCount = digits.Val; + if (sign.Seen) + DAInfo.DecimalSign = sign.Val; + if (scale.Seen) + DAInfo.Scale = scale.Val; + + Result = GET_OR_DISTINCT(DIBasicType, + (Context, tag.Val, name.Val, pic.Val, size.Val, + align.Val, encoding.Val, flags.Val, DAInfo)); + } else { + Result = GET_OR_DISTINCT(DIBasicType, (Context, tag.Val, name.Val, size.Val, + align.Val, encoding.Val, flags.Val)); + } return false; } Index: lib/AsmParser/LLToken.h =================================================================== --- lib/AsmParser/LLToken.h +++ lib/AsmParser/LLToken.h @@ -416,6 +416,10 @@ kw_info, kw_byte, kw_bit, + kw_pic, + kw_digits, + kw_scale, + kw_sign, // Unsigned Valued tokens (UIntVal). GlobalID, // @42 @@ -441,6 +445,7 @@ DIFlag, // DIFlagFoo DwarfMacinfo, // DW_MACINFO_foo ChecksumKind, // CSK_foo + DwarfDecimalSign, // DW_DS_foo // Type valued tokens (TyVal). Type, Index: lib/BinaryFormat/Dwarf.cpp =================================================================== --- lib/BinaryFormat/Dwarf.cpp +++ 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(DW_DS_Invalid); +} + unsigned llvm::dwarf::TagVersion(dwarf::Tag Tag) { switch (Tag) { default: Index: lib/Bitcode/Reader/MetadataLoader.cpp =================================================================== --- lib/Bitcode/Reader/MetadataLoader.cpp +++ lib/Bitcode/Reader/MetadataLoader.cpp @@ -1213,18 +1213,38 @@ break; } case bitc::METADATA_BASIC_TYPE: { - if (Record.size() < 6 || Record.size() > 7) - return error("Invalid record"); + if (Record.size() < 6 || Record.size() > 12) + 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); + DINode::DIFlags Flags = (Record.size() > 6) + ? static_cast(Record[6]) + : DINode::FlagZero; + + if (Record.size() > 7) { + DIBasicType::DecimalInfo DAInfo; + if (Record[8]) + DAInfo.DigitCount = Record[8]; + if (Record[9]) + DAInfo.DecimalSign = Record[9]; + if (Record[10]) + DAInfo.Scale = Record[11]; + + 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; } Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1494,6 +1494,32 @@ Record.push_back(N->getEncoding()); Record.push_back(N->getFlags()); + // Below are the optional decimal attributes in case base type is decimal type + // and one or more attributes are not needed, we encode 0 to mark the missing + // place except the `scale` attribute which is integer and may have valid zero + // value, to mark its validity we add one more non-zero record before it. + if (N->hasDecimalInfo()) { + Record.push_back(VE.getMetadataOrNullID(N->getRawPictureString())); + + if (const auto &digits = N->getDigitCount()) + Record.push_back(*digits); + else + Record.push_back(0); + + if (const auto &sign = N->getDecimalSign()) + Record.push_back(*sign); + else + Record.push_back(0); + + if (const auto &scale = N->getScale()) { + Record.push_back(1); + Record.push_back(*scale); + } else { + Record.push_back(0); + Record.push_back(0); + } + } + Stream.EmitRecord(bitc::METADATA_BASIC_TYPE, Record, Abbrev); Record.clear(); } Index: lib/CodeGen/AsmPrinter/DwarfUnit.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -738,6 +738,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 auto &digits = BTy->getDigitCount()) + addUInt(Buffer, dwarf::DW_AT_digit_count, None, *digits); + + if (const auto &sign = BTy->getDecimalSign()) + addUInt(Buffer, dwarf::DW_AT_decimal_sign, None, *sign); + + if (const auto &scale = BTy->getScale()) + if (BTy->isBinaryScale()) + addSInt(Buffer, dwarf::DW_AT_binary_scale, None, *scale); + else + addSInt(Buffer, dwarf::DW_AT_decimal_scale, None, *scale); + } } void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIDerivedType *DTy) { Index: lib/IR/AsmWriter.cpp =================================================================== --- lib/IR/AsmWriter.cpp +++ lib/IR/AsmWriter.cpp @@ -1805,6 +1805,19 @@ Printer.printInt("align", N->getAlignInBits()); Printer.printDwarfEnum("encoding", N->getEncoding(), dwarf::AttributeEncodingString); + + if (N->hasDecimalInfo()) { + Printer.printString("pic", N->getPictureString()); + if (const auto &digits = N->getDigitCount()) + Printer.printInt("digits", *digits); + + if (const auto &sign = N->getDecimalSign()) + Printer.printDwarfEnum("sign", *sign, dwarf::DecimalSignString); + + if (const auto &scale = N->getScale()) + Printer.printInt("scale", *scale, /*ShouldSkipZero*/ false); + } + Printer.printDIFlags("flags", N->getFlags()); Out << ")"; } Index: lib/IR/DIBuilder.cpp =================================================================== --- lib/IR/DIBuilder.cpp +++ lib/IR/DIBuilder.cpp @@ -264,6 +264,27 @@ 0, Encoding, Flags); } +DIBasicType *DIBuilder::createBasicType(StringRef Name, StringRef Pic, + uint64_t SizeInBits, unsigned Encoding, + Optional DigitCount, + Optional DecimalSign, + Optional Scale, + DINode::DIFlags Flags) { + assert(!Name.empty() && "Unable to create type without name"); + assert((!Pic.empty() || DigitCount != None || DecimalSign != None || + Scale != None) && + "Unable to create decimal info with empty attributes"); + + MDString *PicString = nullptr; + if (!Pic.empty()) + PicString = MDString::get(VMContext, Pic); + + return DIBasicType::get( + VMContext, dwarf::DW_TAG_base_type, Name, PicString, SizeInBits, 0, + Encoding, Flags, + DIBasicType::DecimalInfo{ DigitCount, DecimalSign, Scale }); +} + DIDerivedType *DIBuilder::createQualifiedType(unsigned Tag, DIType *FromTy) { return DIDerivedType::get(VMContext, Tag, "", nullptr, 0, nullptr, FromTy, 0, 0, 0, None, DINode::FlagZero); Index: lib/IR/DebugInfoMetadata.cpp =================================================================== --- lib/IR/DebugInfoMetadata.cpp +++ lib/IR/DebugInfoMetadata.cpp @@ -292,16 +292,18 @@ } 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, DIFlags Flags, + 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, Flags, DAInfo)); + Metadata *Ops[] = { nullptr, nullptr, Name, PictureString }; + DEFINE_GETIMPL_STORE(DIBasicType, + (Tag, SizeInBits, AlignInBits, Encoding, Flags, DAInfo), + Ops); } Optional DIBasicType::getSignedness() const { Index: lib/IR/LLVMContextImpl.h =================================================================== --- lib/IR/LLVMContextImpl.h +++ 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) {} + Optional DecimalAttrInfo; + + MDNodeKeyImpl(unsigned Tag, MDString *Name, MDString *PictureString, + uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, + unsigned Flags, + Optional DecimalAttrInfo) + : Tag(Tag), Name(Name), PictureString(PictureString), + SizeInBits(SizeInBits), AlignInBits(AlignInBits), Encoding(Encoding), + Flags(Flags), 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()), + Flags(N->getFlags()), 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() && Flags == RHS->getFlags() && + DecimalAttrInfo == RHS->getDecimalInfo(); } unsigned getHashValue() const { Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -888,6 +888,13 @@ "invalid tag", &N); AssertDI(!(N.isBigEndian() && N.isLittleEndian()) , "has conflicting 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) { Index: test/Assembler/debug-info.ll =================================================================== --- test/Assembler/debug-info.ll +++ 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) @@ -99,3 +99,18 @@ ; 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 !40 = !DIBasicType(name: "ext1", size: 48, align: 1, encoding: DW_ATE_numeric_string, pic: "S999V999", digits: 6, sign: DW_DS_trailing_overpunch, scale: -3) +; 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) +; CHECK-NEXT !42 = !DIBasicType(name: "ext3", size: 72, align: 1, encoding: DW_ATE_edited, pic: "+z,zz9.99", digits: 6, scale: -2) +; 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) +; CHECK-NEXT !45 = !DIBasicType(name: "ext6", size: 40, align: 1, encoding: DW_ATE_packed_decimal, pic: "S9(3)V99", digits: 5, scale: -2) +; CHECK-NEXT !46 = !DIBasicType(name: "ext7", size: 40, align: 1, encoding: DW_ATE_packed_decimal, pic: "S9(3)V99", digits: 5, scale: -2, flags: DIFlagBinaryScale) +!43 = !DIBasicType(name: "ext1", size: 48, align: 1, encoding: DW_ATE_numeric_string, pic: "S999V999", digits: 6, sign: DW_DS_trailing_overpunch, scale: -3) +!44 = !DIBasicType(name: "ext2", size: 16, align: 1, encoding: DW_ATE_packed_decimal, pic: "999PP", digits: 3, sign: DW_DS_unsigned, scale: 2) +!45 = !DIBasicType(name: "ext3", size: 72, align: 1, encoding: DW_ATE_edited, pic: "+z,zz9.99", digits: 6, scale: -2) +!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) +!48 = !DIBasicType(name: "ext6", size: 40, align: 1, encoding: DW_ATE_packed_decimal, pic: "S9(3)V99", digits: 5, scale: -2) +!49 = !DIBasicType(name: "ext7", size: 40, align: 1, encoding: DW_ATE_packed_decimal, pic: "S9(3)V99", digits: 5, scale: -2, flags: DIFlagBinaryScale) Index: unittests/IR/MetadataTest.cpp =================================================================== --- unittests/IR/MetadataTest.cpp +++ unittests/IR/MetadataTest.cpp @@ -1127,6 +1127,62 @@ 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, + DINode::FlagZero, + 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(DINode::FlagZero, N->getFlags()); + EXPECT_EQ("S999V99", N->getPictureString()); + EXPECT_EQ(dwarf::DW_DS_trailing_overpunch, N->getDecimalSign().getValue()); + EXPECT_EQ(-2, N->getScale().getValue()); + EXPECT_EQ(5, N->getDigitCount().getValue()); + + EXPECT_EQ(N, DIBasicType::get( + Context, dwarf::DW_TAG_base_type, "ext1", + MDString::get(Context, "S999V99"), 40, 1, + dwarf::DW_ATE_numeric_string, DINode::FlagZero, + 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, DINode::FlagZero, + 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, DINode::FlagZero, + 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, DINode::FlagZero, + 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, DINode::FlagZero, + 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) {