diff options
| author | Orlando Cazalet-Hyams <orlando.hyams@sony.com> | 2025-10-29 15:23:46 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-10-29 15:23:46 +0000 |
| commit | aa5fe56db4777dc1dbd8e114090711068e76c770 (patch) | |
| tree | d603e0645fe182c2ba17e817c917e44cd4f55c3d /llvm/lib | |
| parent | 9b513ad505ff606f66efe8ece35351eeabc4133a (diff) | |
| download | llvm-aa5fe56db4777dc1dbd8e114090711068e76c770.zip llvm-aa5fe56db4777dc1dbd8e114090711068e76c770.tar.gz llvm-aa5fe56db4777dc1dbd8e114090711068e76c770.tar.bz2 | |
[DebugInfo] Add dataSize to DIBasicType to add DW_AT_bit_size to _BitInt types (#164372)
DW_TAG_base_type DIEs are permitted to have both byte_size and bit_size
attributes "If the value of an object of the given type does not fully
occupy the storage described by a byte size attribute"
* Add DataSizeInBits to DIBasicType (`DIBasicType(... dataSize: n ...)` in IR).
* Change Clang to add DataSizeInBits to _BitInt type metadata.
* Change LLVM to add DW_AT_bit_size to base_type DIEs that have non-zero
DataSizeInBits.
TODO: Do we need to emit DW_AT_data_bit_offset for big endian targets?
See discussion on the PR.
Fixes [#61952](https://github.com/llvm/llvm-project/issues/61952)
---------
Co-authored-by: David Stenberg <david.stenberg@ericsson.com>
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/AsmParser/LLParser.cpp | 9 | ||||
| -rw-r--r-- | llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 8 | ||||
| -rw-r--r-- | llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 1 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 6 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 15 | ||||
| -rw-r--r-- | llvm/lib/IR/AsmWriter.cpp | 1 | ||||
| -rw-r--r-- | llvm/lib/IR/DIBuilder.cpp | 6 | ||||
| -rw-r--r-- | llvm/lib/IR/DebugInfoMetadata.cpp | 15 | ||||
| -rw-r--r-- | llvm/lib/IR/LLVMContextImpl.h | 11 |
9 files changed, 49 insertions, 23 deletions
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 4cc47c0..8e3ce49 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -5642,16 +5642,17 @@ bool LLParser::parseDIBasicType(MDNode *&Result, bool IsDistinct) { OPTIONAL(name, MDStringField, ); \ OPTIONAL(size, MDUnsignedOrMDField, (0, UINT64_MAX)); \ OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(dataSize, MDUnsignedField, (0, UINT32_MAX)); \ OPTIONAL(encoding, DwarfAttEncodingField, ); \ OPTIONAL(num_extra_inhabitants, MDUnsignedField, (0, UINT32_MAX)); \ OPTIONAL(flags, DIFlagField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS - Result = GET_OR_DISTINCT(DIBasicType, (Context, tag.Val, name.Val, - size.getValueAsMetadata(Context), - align.Val, encoding.Val, - num_extra_inhabitants.Val, flags.Val)); + Result = GET_OR_DISTINCT( + DIBasicType, + (Context, tag.Val, name.Val, size.getValueAsMetadata(Context), align.Val, + encoding.Val, num_extra_inhabitants.Val, dataSize.Val, flags.Val)); return false; } diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp index 4df500b..c63dc8f 100644 --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -1531,7 +1531,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( break; } case bitc::METADATA_BASIC_TYPE: { - if (Record.size() < 6 || Record.size() > 8) + if (Record.size() < 6 || Record.size() > 9) return error("Invalid record"); IsDistinct = Record[0] & 1; @@ -1540,13 +1540,13 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( ? static_cast<DINode::DIFlags>(Record[6]) : DINode::FlagZero; uint32_t NumExtraInhabitants = (Record.size() > 7) ? Record[7] : 0; - + uint32_t DataSizeInBits = (Record.size() > 8) ? Record[8] : 0; Metadata *SizeInBits = getMetadataOrConstant(SizeIsMetadata, Record[3]); - MetadataList.assignValue( GET_OR_DISTINCT(DIBasicType, (Context, Record[1], getMDString(Record[2]), SizeInBits, - Record[4], Record[5], NumExtraInhabitants, Flags)), + Record[4], Record[5], NumExtraInhabitants, + DataSizeInBits, Flags)), NextMetadataNo); NextMetadataNo++; break; diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 61aa7c2f5..f17656c 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1925,6 +1925,7 @@ void ModuleBitcodeWriter::writeDIBasicType(const DIBasicType *N, Record.push_back(N->getEncoding()); Record.push_back(N->getFlags()); Record.push_back(N->getNumExtraInhabitants()); + Record.push_back(N->getDataSizeInBits()); Stream.EmitRecord(bitc::METADATA_BASIC_TYPE, Record, Abbrev); Record.clear(); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index 518121e..751d373 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -1793,9 +1793,13 @@ void DwarfCompileUnit::createBaseTypeDIEs() { "_" + Twine(Btr.BitSize)).toStringRef(Str)); addUInt(Die, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, Btr.Encoding); // Round up to smallest number of bytes that contains this number of bits. + // ExprRefedBaseTypes is populated with types referenced by + // DW_OP_LLVM_convert operations in location expressions. These are often + // byte-sized, but one common counter-example is 1-bit sized conversions + // from `i1` types. TODO: Should these use DW_AT_bit_size? See + // DwarfUnit::constructTypeDIE. addUInt(Die, dwarf::DW_AT_byte_size, std::nullopt, divideCeil(Btr.BitSize, 8)); - Btr.Die = &Die; } } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index e40fb76..555c56f 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -766,8 +766,19 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIBasicType *BTy) { addUInt(Buffer, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, BTy->getEncoding()); - uint64_t Size = BTy->getSizeInBits() >> 3; - addUInt(Buffer, dwarf::DW_AT_byte_size, std::nullopt, Size); + uint64_t SizeInBytes = divideCeil(BTy->getSizeInBits(), 8); + addUInt(Buffer, dwarf::DW_AT_byte_size, std::nullopt, SizeInBytes); + if (BTy->getTag() == dwarf::Tag::DW_TAG_base_type) { + // DW_TAG_base_type: + // If the value of an object of the given type does not fully occupy the + // storage described by a byte size attribute, the base type entry may also + // have a DW_AT_bit_size [...] attribute. + // TODO: Do big endian targets need DW_AT_data_bit_offset? See discussion in + // pull request #164372. + if (uint64_t DataSizeInBits = BTy->getDataSizeInBits(); + DataSizeInBits && DataSizeInBits != SizeInBytes * 8) + addUInt(Buffer, dwarf::DW_AT_bit_size, std::nullopt, DataSizeInBits); + } if (BTy->isBigEndian()) addUInt(Buffer, dwarf::DW_AT_endianity, std::nullopt, dwarf::DW_END_big); diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index 3c222f5..95d954f 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -2199,6 +2199,7 @@ static void writeDIBasicType(raw_ostream &Out, const DIBasicType *N, Printer.printString("name", N->getName()); Printer.printMetadataOrInt("size", N->getRawSizeInBits(), true); Printer.printInt("align", N->getAlignInBits()); + Printer.printInt("dataSize", N->getDataSizeInBits()); Printer.printDwarfEnum("encoding", N->getEncoding(), dwarf::AttributeEncodingString); Printer.printInt("num_extra_inhabitants", N->getNumExtraInhabitants()); diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index 07a870f..ca11ecf 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -261,10 +261,12 @@ DIBasicType *DIBuilder::createNullPtrType() { DIBasicType *DIBuilder::createBasicType(StringRef Name, uint64_t SizeInBits, unsigned Encoding, DINode::DIFlags Flags, - uint32_t NumExtraInhabitants) { + uint32_t NumExtraInhabitants, + uint32_t DataSizeInBits) { assert(!Name.empty() && "Unable to create type without name"); return DIBasicType::get(VMContext, dwarf::DW_TAG_base_type, Name, SizeInBits, - 0, Encoding, NumExtraInhabitants, Flags); + 0, Encoding, NumExtraInhabitants, DataSizeInBits, + Flags); } DIFixedPointType * diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index e30df88..fafc325 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -872,15 +872,18 @@ DIEnumerator *DIEnumerator::getImpl(LLVMContext &Context, const APInt &Value, DIBasicType *DIBasicType::getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *SizeInBits, uint32_t AlignInBits, unsigned Encoding, - uint32_t NumExtraInhabitants, DIFlags Flags, + uint32_t NumExtraInhabitants, + uint32_t DataSizeInBits, DIFlags Flags, StorageType Storage, bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); - DEFINE_GETIMPL_LOOKUP(DIBasicType, (Tag, Name, SizeInBits, AlignInBits, - Encoding, NumExtraInhabitants, Flags)); + DEFINE_GETIMPL_LOOKUP(DIBasicType, + (Tag, Name, SizeInBits, AlignInBits, Encoding, + NumExtraInhabitants, DataSizeInBits, Flags)); Metadata *Ops[] = {nullptr, nullptr, Name, SizeInBits, nullptr}; - DEFINE_GETIMPL_STORE(DIBasicType, - (Tag, AlignInBits, Encoding, NumExtraInhabitants, Flags), - Ops); + DEFINE_GETIMPL_STORE( + DIBasicType, + (Tag, AlignInBits, Encoding, NumExtraInhabitants, DataSizeInBits, Flags), + Ops); } std::optional<DIBasicType::Signedness> DIBasicType::getSignedness() const { diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index e03f993..2c9921d 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -480,20 +480,22 @@ template <> struct MDNodeKeyImpl<DIBasicType> { uint32_t AlignInBits; unsigned Encoding; uint32_t NumExtraInhabitants; + uint32_t DataSizeInBits; unsigned Flags; MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *SizeInBits, uint32_t AlignInBits, unsigned Encoding, - uint32_t NumExtraInhabitants, unsigned Flags) + uint32_t NumExtraInhabitants, uint32_t DataSizeInBits, + unsigned Flags) : Tag(Tag), Name(Name), SizeInBits(SizeInBits), AlignInBits(AlignInBits), Encoding(Encoding), NumExtraInhabitants(NumExtraInhabitants), - Flags(Flags) {} + DataSizeInBits(DataSizeInBits), Flags(Flags) {} MDNodeKeyImpl(const DIBasicType *N) : Tag(N->getTag()), Name(N->getRawName()), SizeInBits(N->getRawSizeInBits()), AlignInBits(N->getAlignInBits()), Encoding(N->getEncoding()), - NumExtraInhabitants(N->getNumExtraInhabitants()), Flags(N->getFlags()) { - } + NumExtraInhabitants(N->getNumExtraInhabitants()), + DataSizeInBits(N->getDataSizeInBits()), Flags(N->getFlags()) {} bool isKeyOf(const DIBasicType *RHS) const { return Tag == RHS->getTag() && Name == RHS->getRawName() && @@ -501,6 +503,7 @@ template <> struct MDNodeKeyImpl<DIBasicType> { AlignInBits == RHS->getAlignInBits() && Encoding == RHS->getEncoding() && NumExtraInhabitants == RHS->getNumExtraInhabitants() && + DataSizeInBits == RHS->getDataSizeInBits() && Flags == RHS->getFlags(); } |
