aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
diff options
context:
space:
mode:
authorTom Tromey <tromey@adacore.com>2025-06-25 12:20:35 -0600
committerGitHub <noreply@github.com>2025-06-25 11:20:35 -0700
commit3b90597c2ceaae86608214f6b62b43e55823102b (patch)
tree3c8c3d739d99734bee8bc6bd5ed9d82d5b2d65bc /llvm/lib/Bitcode/Reader/MetadataLoader.cpp
parent487581b826a5339410aaf306eafedc7b806b25e3 (diff)
downloadllvm-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.cpp61
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(