diff options
author | Tom Tromey <tromey@adacore.com> | 2025-06-25 12:20:35 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-06-25 11:20:35 -0700 |
commit | 3b90597c2ceaae86608214f6b62b43e55823102b (patch) | |
tree | 3c8c3d739d99734bee8bc6bd5ed9d82d5b2d65bc /llvm/lib/Bitcode/Reader/MetadataLoader.cpp | |
parent | 487581b826a5339410aaf306eafedc7b806b25e3 (diff) | |
download | llvm-3b90597c2ceaae86608214f6b62b43e55823102b.zip llvm-3b90597c2ceaae86608214f6b62b43e55823102b.tar.gz llvm-3b90597c2ceaae86608214f6b62b43e55823102b.tar.bz2 |
Non constant size and offset in DWARF (#141106)
In Ada, a record type can have a non-constant size, and a field can
appear at a non-constant bit offset in a record.
To support this, this patch changes DIType to record the size and offset
using metadata, rather than plain integers. In addition to a constant
offset, both DIVariable and DIExpression are now supported here.
One thing of note in this patch is the choice of how exactly to
represent a non-constant bit offset, with the difficulty being that
DWARF 5 does not support this. DWARF 3 did have a way to support a
non-constant byte offset, combined with a constant bit offset within the
byte, but this was deprecated in DWARF 4 and removed from DWARF 5.
This patch takes a simple approach: a DWARF extension allowing the use
of an expression with DW_AT_data_bit_offset. There is a corresponding
DWARF issue, see https://dwarfstd.org/issues/250501.1.html. The main
reason for this approach is that it keeps API simplicity: just a single
value is needed, rather than having separate data describing the byte
offset and the bit within the byte.
Diffstat (limited to 'llvm/lib/Bitcode/Reader/MetadataLoader.cpp')
-rw-r--r-- | llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 61 |
1 files changed, 46 insertions, 15 deletions
diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp index 1cd1797..a9467d1 100644 --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -1287,6 +1287,14 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( return MetadataList.upgradeTypeRef(getMDOrNull(ID)); }; + auto getMetadataOrConstant = [&](bool IsMetadata, + uint64_t Entry) -> Metadata * { + if (IsMetadata) + return getMDOrNull(Entry); + return ConstantAsMetadata::get( + ConstantInt::get(Type::getInt64Ty(Context), Entry)); + }; + #define GET_OR_DISTINCT(CLASS, ARGS) \ (IsDistinct ? CLASS::getDistinct ARGS : CLASS::get ARGS) @@ -1525,15 +1533,18 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( if (Record.size() < 6 || Record.size() > 8) return error("Invalid record"); - IsDistinct = Record[0]; + IsDistinct = Record[0] & 1; + bool SizeIsMetadata = Record[0] & 2; DINode::DIFlags Flags = (Record.size() > 6) ? static_cast<DINode::DIFlags>(Record[6]) : DINode::FlagZero; uint32_t NumExtraInhabitants = (Record.size() > 7) ? Record[7] : 0; + Metadata *SizeInBits = getMetadataOrConstant(SizeIsMetadata, Record[3]); + MetadataList.assignValue( GET_OR_DISTINCT(DIBasicType, - (Context, Record[1], getMDString(Record[2]), Record[3], + (Context, Record[1], getMDString(Record[2]), SizeInBits, Record[4], Record[5], NumExtraInhabitants, Flags)), NextMetadataNo); NextMetadataNo++; @@ -1543,9 +1554,12 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( if (Record.size() < 11) return error("Invalid record"); - IsDistinct = Record[0]; + IsDistinct = Record[0] & 1; + bool SizeIsMetadata = Record[0] & 2; DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[6]); + Metadata *SizeInBits = getMetadataOrConstant(SizeIsMetadata, Record[3]); + size_t Offset = 9; auto ReadWideInt = [&]() { @@ -1565,7 +1579,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( MetadataList.assignValue( GET_OR_DISTINCT(DIFixedPointType, - (Context, Record[1], getMDString(Record[2]), Record[3], + (Context, Record[1], getMDString(Record[2]), SizeInBits, Record[4], Record[5], Flags, Record[7], Record[8], Numerator, Denominator)), NextMetadataNo); @@ -1576,17 +1590,21 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( if (Record.size() > 9 || Record.size() < 8) return error("Invalid record"); - IsDistinct = Record[0]; + IsDistinct = Record[0] & 1; + bool SizeIsMetadata = Record[0] & 2; bool SizeIs8 = Record.size() == 8; // StringLocationExp (i.e. Record[5]) is added at a later time // than the other fields. The code here enables backward compatibility. Metadata *StringLocationExp = SizeIs8 ? nullptr : getMDOrNull(Record[5]); unsigned Offset = SizeIs8 ? 5 : 6; + Metadata *SizeInBits = + getMetadataOrConstant(SizeIsMetadata, Record[Offset]); + MetadataList.assignValue( GET_OR_DISTINCT(DIStringType, (Context, Record[1], getMDString(Record[2]), getMDOrNull(Record[3]), getMDOrNull(Record[4]), - StringLocationExp, Record[Offset], Record[Offset + 1], + StringLocationExp, SizeInBits, Record[Offset + 1], Record[Offset + 2])), NextMetadataNo); NextMetadataNo++; @@ -1615,15 +1633,20 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( PtrAuthData.emplace(Record[14]); } - IsDistinct = Record[0]; + IsDistinct = Record[0] & 1; + bool SizeIsMetadata = Record[0] & 2; DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[10]); + + Metadata *SizeInBits = getMetadataOrConstant(SizeIsMetadata, Record[7]); + Metadata *OffsetInBits = getMetadataOrConstant(SizeIsMetadata, Record[9]); + MetadataList.assignValue( GET_OR_DISTINCT(DIDerivedType, (Context, Record[1], getMDString(Record[2]), getMDOrNull(Record[3]), Record[4], getDITypeRefOrNull(Record[5]), - getDITypeRefOrNull(Record[6]), Record[7], Record[8], - Record[9], DWARFAddressSpace, PtrAuthData, Flags, + getDITypeRefOrNull(Record[6]), SizeInBits, Record[8], + OffsetInBits, DWARFAddressSpace, PtrAuthData, Flags, getDITypeRefOrNull(Record[11]), Annotations)), NextMetadataNo); NextMetadataNo++; @@ -1633,13 +1656,17 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( if (Record.size() != 13) return error("Invalid record"); - IsDistinct = Record[0]; + IsDistinct = Record[0] & 1; + bool SizeIsMetadata = Record[0] & 2; DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[7]); + + Metadata *SizeInBits = getMetadataOrConstant(SizeIsMetadata, Record[5]); + MetadataList.assignValue( GET_OR_DISTINCT(DISubrangeType, (Context, getMDString(Record[1]), getMDOrNull(Record[2]), Record[3], - getMDOrNull(Record[4]), Record[5], Record[6], Flags, + getMDOrNull(Record[4]), SizeInBits, Record[6], Flags, getDITypeRefOrNull(Record[8]), getMDOrNull(Record[9]), getMDOrNull(Record[10]), getMDOrNull(Record[11]), getMDOrNull(Record[12]))), @@ -1654,18 +1681,18 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( // If we have a UUID and this is not a forward declaration, lookup the // mapping. IsDistinct = Record[0] & 0x1; - bool IsNotUsedInTypeRef = Record[0] >= 2; + bool IsNotUsedInTypeRef = Record[0] & 2; + bool SizeIsMetadata = Record[0] & 4; unsigned Tag = Record[1]; MDString *Name = getMDString(Record[2]); Metadata *File = getMDOrNull(Record[3]); unsigned Line = Record[4]; Metadata *Scope = getDITypeRefOrNull(Record[5]); Metadata *BaseType = nullptr; - uint64_t SizeInBits = Record[7]; if (Record[8] > (uint64_t)std::numeric_limits<uint32_t>::max()) return error("Alignment value is too large"); uint32_t AlignInBits = Record[8]; - uint64_t OffsetInBits = 0; + Metadata *OffsetInBits = nullptr; uint32_t NumExtraInhabitants = (Record.size() > 22) ? Record[22] : 0; DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[10]); Metadata *Elements = nullptr; @@ -1712,7 +1739,9 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( TemplateParams = getMDOrNull(Record[14]); } else { BaseType = getDITypeRefOrNull(Record[6]); - OffsetInBits = Record[9]; + + OffsetInBits = getMetadataOrConstant(SizeIsMetadata, Record[9]); + Elements = getMDOrNull(Record[11]); VTableHolder = getDITypeRefOrNull(Record[13]); TemplateParams = getMDOrNull(Record[14]); @@ -1740,6 +1769,8 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( if (Record.size() > 24 && Record[24] != dwarf::DW_APPLE_ENUM_KIND_invalid) EnumKind = Record[24]; + Metadata *SizeInBits = getMetadataOrConstant(SizeIsMetadata, Record[7]); + DICompositeType *CT = nullptr; if (Identifier) CT = DICompositeType::buildODRType( |