Index: clang/lib/CodeGen/CGDebugInfo.cpp =================================================================== --- clang/lib/CodeGen/CGDebugInfo.cpp +++ clang/lib/CodeGen/CGDebugInfo.cpp @@ -930,14 +930,19 @@ } llvm::DIType *CGDebugInfo::CreateType(const BitIntType *Ty) { - - StringRef Name = Ty->isUnsigned() ? "unsigned _BitInt" : "_BitInt"; + SmallString<32> Name; + if (Ty->isUnsigned()) + Name += "unsigned "; + Name += "_BitInt("; + Name += std::to_string(Ty->getNumBits()); + Name += ")"; llvm::dwarf::TypeKind Encoding = Ty->isUnsigned() ? llvm::dwarf::DW_ATE_unsigned : llvm::dwarf::DW_ATE_signed; return DBuilder.createBasicType(Name, CGM.getContext().getTypeSize(Ty), - Encoding); + Encoding, llvm::DINode::FlagZero, + Ty->getNumBits()); } llvm::DIType *CGDebugInfo::CreateType(const ComplexType *Ty) { Index: llvm/include/llvm/IR/DIBuilder.h =================================================================== --- llvm/include/llvm/IR/DIBuilder.h +++ llvm/include/llvm/IR/DIBuilder.h @@ -206,9 +206,14 @@ /// \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. + /// \param NumDataBits Optional for cases where the value of an object + /// does not fully occupy the storage size specified + /// by SizeInBits. NumDataBits=0 implies that all bits + /// specified by SizeInBits are used. DIBasicType *createBasicType(StringRef Name, uint64_t SizeInBits, unsigned Encoding, - DINode::DIFlags Flags = DINode::FlagZero); + DINode::DIFlags Flags = DINode::FlagZero, + unsigned NumDataBits = 0); /// Create debugging information entry for a string /// type. Index: llvm/include/llvm/IR/DebugInfoMetadata.h =================================================================== --- llvm/include/llvm/IR/DebugInfoMetadata.h +++ llvm/include/llvm/IR/DebugInfoMetadata.h @@ -805,57 +805,65 @@ friend class MDNode; unsigned Encoding; + uint64_t NumDataBits; DIBasicType(LLVMContext &C, StorageType Storage, unsigned Tag, uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, - DIFlags Flags, ArrayRef Ops) + DIFlags Flags, uint64_t NumDataBits, ArrayRef Ops) : DIType(C, DIBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, Flags, Ops), - Encoding(Encoding) {} + Encoding(Encoding), NumDataBits(NumDataBits) {} ~DIBasicType() = default; static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, - DIFlags Flags, StorageType Storage, - bool ShouldCreate = true) { + DIFlags Flags, uint64_t NumDataBits, + StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Tag, getCanonicalMDString(Context, Name), - SizeInBits, AlignInBits, Encoding, Flags, Storage, - ShouldCreate); + SizeInBits, AlignInBits, Encoding, Flags, NumDataBits, + 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, uint64_t NumDataBits, + StorageType Storage, bool ShouldCreate = true); TempDIBasicType cloneImpl() const { return getTemporary(getContext(), getTag(), getName(), getSizeInBits(), - getAlignInBits(), getEncoding(), getFlags()); + getAlignInBits(), getEncoding(), getFlags(), + getNumDataBits()); } public: DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name), - (Tag, Name, 0, 0, 0, FlagZero)) + (Tag, Name, 0, 0, 0, FlagZero, 0)) DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name, uint64_t SizeInBits), - (Tag, Name, SizeInBits, 0, 0, FlagZero)) + (Tag, Name, SizeInBits, 0, 0, FlagZero, 0)) DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, MDString *Name, uint64_t SizeInBits), - (Tag, Name, SizeInBits, 0, 0, FlagZero)) + (Tag, Name, SizeInBits, 0, 0, FlagZero, 0)) 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, DIFlags Flags, + unsigned NumDataBits), + (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags, + NumDataBits)) 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, DIFlags Flags, + unsigned NumDataBits), + (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags, + NumDataBits)) TempDIBasicType clone() const { return cloneImpl(); } unsigned getEncoding() const { return Encoding; } + uint64_t getNumDataBits() const { return NumDataBits; } + enum class Signedness { Signed, Unsigned }; /// Return the signedness of this type, or std::nullopt if this type is Index: llvm/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/lib/AsmParser/LLParser.cpp +++ llvm/lib/AsmParser/LLParser.cpp @@ -5007,12 +5007,14 @@ OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX)); \ OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \ OPTIONAL(encoding, DwarfAttEncodingField, ); \ - OPTIONAL(flags, DIFlagField, ); + OPTIONAL(flags, DIFlagField, ); \ + OPTIONAL(data_bits, MDUnsignedField, (0, UINT64_MAX)); 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)); + align.Val, encoding.Val, flags.Val, + data_bits.Val)); return false; } Index: llvm/lib/Bitcode/Reader/MetadataLoader.cpp =================================================================== --- llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -1417,7 +1417,7 @@ break; } case bitc::METADATA_BASIC_TYPE: { - if (Record.size() < 6 || Record.size() > 7) + if (Record.size() < 6 || Record.size() > 8) return error("Invalid record"); IsDistinct = Record[0]; @@ -1425,10 +1425,12 @@ ? static_cast(Record[6]) : DINode::FlagZero; + uint64_t NumDataBits = (Record.size() > 7) ? Record[7] : 0; + MetadataList.assignValue( GET_OR_DISTINCT(DIBasicType, (Context, Record[1], getMDString(Record[2]), Record[3], - Record[4], Record[5], Flags)), + Record[4], Record[5], Flags, NumDataBits)), NextMetadataNo); NextMetadataNo++; break; Index: llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -706,6 +706,14 @@ uint64_t Size = BTy->getSizeInBits() >> 3; addUInt(Buffer, dwarf::DW_AT_byte_size, std::nullopt, Size); + uint64_t NumDataBits = BTy->getNumDataBits(); + + assert(NumDataBits <= BTy->getNumDataBits()); + if (NumDataBits > 0 && NumDataBits != BTy->getSizeInBits()) { + addUInt(Buffer, dwarf::DW_AT_bit_size, std::nullopt, NumDataBits); + // addUInt(Buffer, dwarf::DW_AT_data_bit_offset, std::nullopt, BTy->getSizeInBits() - NumDataBits); + } + if (BTy->isBigEndian()) addUInt(Buffer, dwarf::DW_AT_endianity, std::nullopt, dwarf::DW_END_big); else if (BTy->isLittleEndian()) Index: llvm/lib/IR/AsmWriter.cpp =================================================================== --- llvm/lib/IR/AsmWriter.cpp +++ llvm/lib/IR/AsmWriter.cpp @@ -2001,6 +2001,7 @@ Printer.printDwarfEnum("encoding", N->getEncoding(), dwarf::AttributeEncodingString); Printer.printDIFlags("flags", N->getFlags()); + Printer.printInt("data_bits", N->getNumDataBits()); Out << ")"; } Index: llvm/lib/IR/DIBuilder.cpp =================================================================== --- llvm/lib/IR/DIBuilder.cpp +++ llvm/lib/IR/DIBuilder.cpp @@ -276,10 +276,12 @@ DIBasicType *DIBuilder::createBasicType(StringRef Name, uint64_t SizeInBits, unsigned Encoding, - DINode::DIFlags Flags) { + DINode::DIFlags Flags, + unsigned NumDataBits) { assert(!Name.empty() && "Unable to create type without name"); + assert(NumDataBits <= SizeInBits && "More data bits than storage size"); return DIBasicType::get(VMContext, dwarf::DW_TAG_base_type, Name, SizeInBits, - 0, Encoding, Flags); + 0, Encoding, Flags, NumDataBits); } DIStringType *DIBuilder::createStringType(StringRef Name, uint64_t SizeInBits) { Index: llvm/lib/IR/DebugInfoMetadata.cpp =================================================================== --- llvm/lib/IR/DebugInfoMetadata.cpp +++ llvm/lib/IR/DebugInfoMetadata.cpp @@ -656,14 +656,16 @@ 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, uint64_t NumDataBits, + StorageType Storage, bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); DEFINE_GETIMPL_LOOKUP(DIBasicType, - (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags)); + (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags, + NumDataBits)); Metadata *Ops[] = {nullptr, nullptr, Name}; DEFINE_GETIMPL_STORE(DIBasicType, - (Tag, SizeInBits, AlignInBits, Encoding, Flags), Ops); + (Tag, SizeInBits, AlignInBits, Encoding, Flags, + NumDataBits), Ops); } std::optional DIBasicType::getSignedness() const { Index: llvm/lib/IR/LLVMContextImpl.h =================================================================== --- llvm/lib/IR/LLVMContextImpl.h +++ llvm/lib/IR/LLVMContextImpl.h @@ -465,25 +465,28 @@ uint32_t AlignInBits; unsigned Encoding; unsigned Flags; + uint64_t NumDataBits; MDNodeKeyImpl(unsigned Tag, MDString *Name, uint64_t SizeInBits, - uint32_t AlignInBits, unsigned Encoding, unsigned Flags) + uint32_t AlignInBits, unsigned Encoding, unsigned Flags, + uint64_t NumDataBits) : Tag(Tag), Name(Name), SizeInBits(SizeInBits), AlignInBits(AlignInBits), - Encoding(Encoding), Flags(Flags) {} + Encoding(Encoding), Flags(Flags), NumDataBits(NumDataBits) {} MDNodeKeyImpl(const DIBasicType *N) : Tag(N->getTag()), Name(N->getRawName()), SizeInBits(N->getSizeInBits()), AlignInBits(N->getAlignInBits()), Encoding(N->getEncoding()), - Flags(N->getFlags()) {} + Flags(N->getFlags()), NumDataBits(N->getNumDataBits()) {} 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(); + Encoding == RHS->getEncoding() && Flags == RHS->getFlags() && + NumDataBits == RHS->getNumDataBits(); } unsigned getHashValue() const { - return hash_combine(Tag, Name, SizeInBits, AlignInBits, Encoding); + return hash_combine(Tag, Name, SizeInBits, AlignInBits, Encoding, NumDataBits); } };