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_float. + /// \param DigitCount Digits count in packed decimal type + /// \param DecimalSign decimal sign + /// \param DeimalScale decimal scale + /// \param Flags Optional DWARF attributes, e.g., DW_AT_endianity. + DIBasicType *createBasicType(StringRef Name, StringRef Pic, + uint64_t SizeInBits, unsigned Encoding, + Optional DigitCount = None, + Optional DecimalSign = None, + Optional DecimalScale = 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/DebugInfoMetadata.h =================================================================== --- include/llvm/IR/DebugInfoMetadata.h +++ include/llvm/IR/DebugInfoMetadata.h @@ -737,14 +737,35 @@ 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 PictureString; + Optional DigitCount; + Optional DecimalSign; + Optional DecimalScale; + + bool operator==(const DecimalInfo& RHS) const { + return PictureString == RHS.PictureString && + DigitCount == RHS.DigitCount && + DecimalSign == RHS.DecimalSign && + DecimalScale == RHS.DecimalScale; + } + }; + +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, @@ -753,18 +774,31 @@ DIFlags Flags, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Tag, getCanonicalMDString(Context, Name), - SizeInBits, AlignInBits, Encoding, Flags, Storage, + SizeInBits, AlignInBits, Encoding, Flags, None, Storage, ShouldCreate); } + static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Name, uint64_t SizeInBits, + uint32_t AlignInBits, unsigned Encoding, + DIFlags Flags, + Optional DecimalAttrInfo, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), + SizeInBits, AlignInBits, Encoding, Flags, DecimalAttrInfo, + 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); TempDIBasicType cloneImpl() const { return getTemporary(getContext(), getTag(), getName(), getSizeInBits(), - getAlignInBits(), getEncoding(), getFlags()); + getAlignInBits(), getEncoding(), getFlags(), + getDecimalInfo()); } public: @@ -777,7 +811,19 @@ 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, uint64_t SizeInBits, + uint32_t AlignInBits, unsigned Encoding, DIFlags Flags, + Optional ExtInfo), + (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags, + ExtInfo)) + DEFINE_MDNODE_GET(DIBasicType, + (unsigned Tag, MDString *Name, uint64_t SizeInBits, + uint32_t AlignInBits, unsigned Encoding, DIFlags Flags, + Optional ExtInfo), + (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags, + ExtInfo)) TempDIBasicType clone() const { return cloneImpl(); } @@ -789,6 +835,25 @@ /// 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 getDecimalScale() const { + return DecimalAttrInfo.getValue().DecimalScale; + } + 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,12 @@ : 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 +3852,24 @@ 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) { @@ -4307,7 +4331,8 @@ /// ParseDIBasicType: /// ::= !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, -/// encoding: DW_ATE_encoding, flags: 0) +/// encoding: DW_ATE_encoding, flags: 0, pic: "S999V999", +/// digits: 4, sign: DW_DS_leading_overpunch, scale: -2, ) bool LLParser::ParseDIBasicType(MDNode *&Result, bool IsDistinct) { #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ OPTIONAL(tag, DwarfTagField, (dwarf::DW_TAG_base_type)); \ @@ -4315,12 +4340,27 @@ OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX)); \ OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \ OPTIONAL(encoding, DwarfAttEncodingField, ); \ + OPTIONAL(pic, MDStringField, ); \ + OPTIONAL(digits, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(sign, DwarfDecimalSignField, (dwarf::DW_DS_Invalid)); \ + OPTIONAL(scale, MDSignedField, (0, INT32_MIN, INT32_MAX)); \ OPTIONAL(flags, DIFlagField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS + Optional DecimalAttrInfo; + if(pic.Seen || digits.Seen || sign.Seen || scale.Seen) { + DIBasicType::DecimalInfo DAInfo; + if (pic.Seen) DAInfo.PictureString = pic.Val; + if (digits.Seen) DAInfo.DigitCount = digits.Val; + if (sign.Seen) DAInfo.DecimalSign = sign.Val; + if (scale.Seen) DAInfo.DecimalScale = scale.Val; + DecimalAttrInfo = DAInfo; + } + Result = GET_OR_DISTINCT(DIBasicType, (Context, tag.Val, name.Val, size.Val, - align.Val, encoding.Val, flags.Val)); + align.Val, encoding.Val, flags.Val, + DecimalAttrInfo)); 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,14 @@ .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,17 +1213,34 @@ 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) ? + + DINode::DIFlags Flags; + Optional DecimalAttrInfo; + + if (Record.size() > 7) { + DIBasicType::DecimalInfo DAInfo; + + if(Record[6]) DAInfo.PictureString = getMDString(Record[6]); + if(Record[7]) DAInfo.DigitCount = Record[7]; + if(Record[8]) DAInfo.DecimalSign = Record[8]; + if(Record[9]) DAInfo.DecimalScale = Record[10]; + DecimalAttrInfo = DAInfo; + Flags = (Record.size() > 11) ? + static_cast(Record[11]) : DINode::FlagZero; + } + else { + 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)), + Record[4], Record[5], Flags, DecimalAttrInfo)), NextMetadataNo); NextMetadataNo++; break; Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1492,6 +1492,35 @@ Record.push_back(N->getSizeInBits()); Record.push_back(N->getAlignInBits()); Record.push_back(N->getEncoding()); + + // 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->getDecimalScale()) { + Record.push_back(1); + Record.push_back(*scale); + } + else { + Record.push_back(0); + Record.push_back(0); + } + } + Record.push_back(N->getFlags()); Stream.EmitRecord(bitc::METADATA_BASIC_TYPE, Record, Abbrev); Index: lib/CodeGen/AsmPrinter/DwarfUnit.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -738,6 +738,21 @@ 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->getDecimalScale()) + 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 @@ -1799,6 +1799,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->getDigitCount()) + Printer.printDwarfEnum("sign", *sign, dwarf::DecimalSignString); + + if (const auto &scale = N->getDecimalScale()) + 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,25 @@ 0, Encoding, Flags); } +DIBasicType *DIBuilder::createBasicType(StringRef Name, StringRef Pic, + uint64_t SizeInBits, unsigned Encoding, + Optional DigitCount, + Optional DecimalSign, + Optional DecimalScale, + DINode::DIFlags Flags) { + assert(!Name.empty() && "Unable to create type without name"); + assert((!Pic.empty() || DigitCount != None || DecimalSign != None || + DecimalScale != None) && "Unable to create decimal info"); + + Optional PicString; + if (!Pic.empty()) PicString = MDString::get(VMContext, Pic); + + return DIBasicType::get(VMContext, dwarf::DW_TAG_base_type, Name, SizeInBits, + 0, Encoding, Flags, + DIBasicType::DecimalInfo{ PicString, DigitCount, + DecimalSign, DecimalScale }); +} + 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 @@ -294,14 +294,17 @@ DIBasicType *DIBasicType::getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, - DIFlags Flags, StorageType Storage, - bool ShouldCreate) { + 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}; + (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags, + DAInfo)); + auto PicString = DAInfo ? DAInfo->PictureString.getValueOr(nullptr) : nullptr; + Metadata *Ops[] = {nullptr, nullptr, Name, PicString}; DEFINE_GETIMPL_STORE(DIBasicType, (Tag, SizeInBits, AlignInBits, Encoding, - Flags), Ops); + Flags, DAInfo), Ops); } Optional DIBasicType::getSignedness() const { Index: lib/IR/LLVMContextImpl.h =================================================================== --- lib/IR/LLVMContextImpl.h +++ lib/IR/LLVMContextImpl.h @@ -380,21 +380,25 @@ uint32_t AlignInBits; unsigned Encoding; unsigned Flags; + Optional DecimalAttrInfo; MDNodeKeyImpl(unsigned Tag, MDString *Name, uint64_t SizeInBits, - uint32_t AlignInBits, unsigned Encoding, unsigned Flags) + uint32_t AlignInBits, unsigned Encoding, unsigned Flags, + Optional DecimalAttrInfo) : Tag(Tag), Name(Name), SizeInBits(SizeInBits), AlignInBits(AlignInBits), - Encoding(Encoding), Flags(Flags) {} + 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()) {} + 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() && SizeInBits == RHS->getSizeInBits() && AlignInBits == RHS->getAlignInBits() && Encoding == RHS->getEncoding() && - Flags == RHS->getFlags(); + 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} +!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} ; CHECK: !0 = !DISubrange(count: 3) ; CHECK-NEXT: !1 = !DISubrange(count: 3, lowerBound: 4) @@ -99,3 +99,16 @@ ; 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) +!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) Index: unittests/IR/MetadataTest.cpp =================================================================== --- unittests/IR/MetadataTest.cpp +++ unittests/IR/MetadataTest.cpp @@ -1127,6 +1127,48 @@ EXPECT_EQ(DINode::FlagZero, N->getFlags()); } +TEST_F(DIBasicTypeTest, getOptionalDecimalInfo) { + DIBasicType::DecimalInfo DAInfo; + DAInfo.PictureString = MDString::get(Context, "ABBA(5)"); + + auto *N = + DIBasicType::get(Context, dwarf::DW_TAG_base_type, "ext1", 64, 1, + dwarf::DW_ATE_edited, DINode::FlagZero, DAInfo); + + EXPECT_EQ(dwarf::DW_TAG_base_type, N->getTag()); + EXPECT_EQ("ext1", N->getName()); + EXPECT_EQ(64u, N->getSizeInBits()); + EXPECT_EQ(1u, N->getAlignInBits()); + EXPECT_EQ(dwarf::DW_ATE_edited, N->getEncoding()); + EXPECT_EQ(DINode::FlagZero, N->getFlags()); + EXPECT_EQ("ABBA(5)", N->getPictureString()); + + EXPECT_EQ(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "ext1", 64, 1, + dwarf::DW_ATE_edited, DINode::FlagZero, + DIBasicType::DecimalInfo{MDString::get(Context, "ABBA(5)"), + None, None, None})); + /// 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", 64, 1, + dwarf::DW_ATE_edited, DINode::FlagZero, None)); + EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "ext1", 64, 1, + dwarf::DW_ATE_edited, DINode::FlagZero, + DIBasicType::DecimalInfo{MDString::get(Context, "S999V99"), + None, None, None})); + EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "ext1", 64, 1, + dwarf::DW_ATE_edited, DINode::FlagZero, + DIBasicType::DecimalInfo{None, 1, None, None})); + EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "ext1", 64, 1, + dwarf::DW_ATE_edited, DINode::FlagZero, + DIBasicType::DecimalInfo{None, None, 1, None})); + EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "ext1", 64, 1, + dwarf::DW_ATE_edited, DINode::FlagZero, + DIBasicType::DecimalInfo{None, None, None, 0})); + + TempDIBasicType Temp = N->clone(); + EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); +} + typedef MetadataTest DITypeTest; TEST_F(DITypeTest, clone) {