From 386f2ca03bdbcf5d08e5ec417bdad6c3de01acb6 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Mon, 12 May 2025 08:55:38 -0600 Subject: Allow multi-member variants in DWARF (#139300) Currently, each variant in the variant part of a structure type can only contain a single member. This was sufficient for Rust, where each variant is represented as its own type. However, this isn't really enough for Ada, where a variant can have multiple members. This patch adds support for this scenario. This is done by allowing the use of DW_TAG_variant by DICompositeType, and then changing the DWARF generator to recognize when a DIDerivedType representing a variant holds one of these. In this case, the fields from the DW_TAG_variant are inlined into the variant, like so: ``` <4><7d>: Abbrev Number: 9 (DW_TAG_variant) <7e> DW_AT_discr_value : 74 <5><7f>: Abbrev Number: 7 (DW_TAG_member) <80> DW_AT_name : (indirect string, offset: 0x43): field0 <84> DW_AT_type : <0xa7> <88> DW_AT_alignment : 8 <89> DW_AT_data_member_location: 0 <5><8a>: Abbrev Number: 7 (DW_TAG_member) <8b> DW_AT_name : (indirect string, offset: 0x4a): field1 <8f> DW_AT_type : <0xa7> <93> DW_AT_alignment : 8 <94> DW_AT_data_member_location: 8 ``` Note that the intermediate DIDerivedType is still needed in this situation, because that is where the discriminants are stored. --- llvm/lib/IR/DIBuilder.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'llvm/lib/IR/DIBuilder.cpp') diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index d9cc49f..90da9f3 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -444,6 +444,19 @@ DIDerivedType *DIBuilder::createVariantMemberType( std::nullopt, std::nullopt, Flags, getConstantOrNull(Discriminant)); } +DIDerivedType *DIBuilder::createVariantMemberType(DIScope *Scope, + DINodeArray Elements, + Constant *Discriminant, + DIType *Ty) { + auto *V = DICompositeType::get(VMContext, dwarf::DW_TAG_variant, {}, nullptr, + 0, getNonCompileUnitScope(Scope), {}, 0, 0, 0, + DINode::FlagZero, Elements, 0, {}, nullptr); + + trackIfUnresolved(V); + return createVariantMemberType(Scope, {}, nullptr, 0, 0, 0, 0, Discriminant, + DINode::FlagZero, V); +} + DIDerivedType *DIBuilder::createBitFieldMemberType( DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, uint64_t SizeInBits, uint64_t OffsetInBits, uint64_t StorageOffsetInBits, -- cgit v1.1