-
Notifications
You must be signed in to change notification settings - Fork 15.3k
Allow multi-member variants in DWARF #139300
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
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/pr-subscribers-llvm-ir Author: Tom Tromey (tromey) ChangesCurrently, 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) Note that the intermediate DIDerivedType is still needed in this situation, because that is where the discriminants are stored. Full diff: https://github.com/llvm/llvm-project/pull/139300.diff 6 Files Affected:
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 7296bb84b7d95..5f14726c36672 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -6363,6 +6363,8 @@ The following ``tag:`` values are valid:
DW_TAG_enumeration_type = 4
DW_TAG_structure_type = 19
DW_TAG_union_type = 23
+ DW_TAG_variant = 25
+ DW_TAG_variant_part = 51
For ``DW_TAG_array_type``, the ``elements:`` should be :ref:`subrange
descriptors <DISubrange>` or :ref:`subrange descriptors
@@ -6398,6 +6400,16 @@ For ``DW_TAG_structure_type``, ``DW_TAG_class_type``, and
``tag: DW_TAG_friend``; or :ref:`subprograms <DISubprogram>` with
``isDefinition: false``.
+``DW_TAG_variant_part`` introduces a variant part of a structure type.
+This should have a discriminant, a member that is used to decide which
+elements are active. The elements of the variant part should each be
+a ``DW_TAG_member``; if a member has a non-null ``ExtraData``, then it
+is a ``ConstantInt`` or ``ConstantDataArray`` indicating the values of
+the discriminant member that cause the activation of this branch. A
+member itself may be of composite type with tag ``DW_TAG_variant``; in
+this case the members of that composite type are inlined into the
+current one.
+
.. _DISubrange:
DISubrange
diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h
index d293c28f5b450..4ce71bd3dad58 100644
--- a/llvm/include/llvm/IR/DIBuilder.h
+++ b/llvm/include/llvm/IR/DIBuilder.h
@@ -406,6 +406,19 @@ namespace llvm {
Constant *Discriminant,
DINode::DIFlags Flags, DIType *Ty);
+ /// Create debugging information entry for a variant. A variant
+ /// created this way "inlines" multiple members into the enclosing
+ /// variant part.
+ /// \param Scope Scope in which this variant is defined.
+ /// \param Elements Variant elements.
+ /// \param Discriminant The discriminant for this branch; null for
+ /// the default branch. This may be a
+ /// ConstantDataArray if the variant applies
+ /// for multiple discriminants.
+ /// \param Ty Parent type.
+ DIDerivedType *createVariantMemberType(DIScope *Scope, DINodeArray Elements,
+ Constant *Discriminant, DIType *Ty);
+
/// Create debugging information entry for a bit field member.
/// \param Scope Member scope.
/// \param Name Member name.
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 5f04e8b0d18ba..5a1ac5d662704 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -1013,6 +1013,7 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
constructEnumTypeDIE(Buffer, CTy);
break;
case dwarf::DW_TAG_variant_part:
+ case dwarf::DW_TAG_variant:
case dwarf::DW_TAG_structure_type:
case dwarf::DW_TAG_union_type:
case dwarf::DW_TAG_class_type:
@@ -1066,7 +1067,17 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
addDiscriminant(Variant, CI,
DD->isUnsignedDIType(Discriminator->getBaseType()));
}
- constructMemberDIE(Variant, DDTy);
+ // If the variant holds a composite type with tag
+ // DW_TAG_variant, inline those members into the variant
+ // DIE.
+ if (auto *Composite =
+ dyn_cast_or_null<DICompositeType>(DDTy->getBaseType());
+ Composite != nullptr &&
+ Composite->getTag() == dwarf::DW_TAG_variant) {
+ constructTypeDIE(Variant, Composite);
+ } else {
+ constructMemberDIE(Variant, DDTy);
+ }
} else {
constructMemberDIE(Buffer, DDTy);
}
diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index d9cc49fdad89c..90da9f3acfe57 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,
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 83c1264aef12b..2cfd3822ea05d 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -1343,6 +1343,7 @@ void Verifier::visitDICompositeType(const DICompositeType &N) {
N.getTag() == dwarf::DW_TAG_enumeration_type ||
N.getTag() == dwarf::DW_TAG_class_type ||
N.getTag() == dwarf::DW_TAG_variant_part ||
+ N.getTag() == dwarf::DW_TAG_variant ||
N.getTag() == dwarf::DW_TAG_namelist,
"invalid tag", &N);
diff --git a/llvm/test/DebugInfo/Generic/multi-variant.ll b/llvm/test/DebugInfo/Generic/multi-variant.ll
new file mode 100644
index 0000000000000..1c680b371bb8f
--- /dev/null
+++ b/llvm/test/DebugInfo/Generic/multi-variant.ll
@@ -0,0 +1,74 @@
+; RUN: %llc_dwarf -O0 -filetype=obj < %s > %t
+; RUN: llvm-dwarfdump -v -debug-info %t | FileCheck %s
+
+; Check for a variant part where a variant has multiple members.
+
+; CHECK: DW_AT_name [DW_FORM_str{{[a-z]+}}] ({{.*}} = "Discr")
+; CHECK: DW_TAG_variant_part
+; CHECK-NOT: TAG
+; CHECK: DW_AT_discr [DW_FORM_ref4] (cu + {{0x[0-9a-fA-F]+}} => {[[OFFSET:0x[0-9a-fA-F]+]]})
+; CHECK: DW_TAG_variant
+; CHECK: DW_AT_discr_value [DW_FORM_data1] (0x4a)
+; CHECK: DW_TAG_member
+; CHECK: DW_AT_name [DW_FORM_str{{[a-z]+}}] ({{.*}} = "field0")
+; CHECK: DW_AT_type
+; CHECK: DW_AT_alignment
+; CHECK: DW_AT_data_member_location [DW_FORM_data1] (0x00)
+; CHECK: DW_TAG_member
+; CHECK: DW_AT_name [DW_FORM_str{{[a-z]+}}] ({{.*}} = "field1")
+; CHECK: DW_AT_type
+; CHECK: DW_AT_alignment
+; CHECK: DW_AT_data_member_location [DW_FORM_data1] (0x08)
+; CHECK: DW_TAG_variant
+; CHECK: DW_AT_discr_value [DW_FORM_data1] (0x4b)
+; CHECK: DW_TAG_member
+; CHECK: DW_AT_name [DW_FORM_str{{[a-z]+}}] ({{.*}} = "field2")
+; CHECK: DW_AT_type
+; CHECK: DW_AT_alignment
+; CHECK: DW_AT_data_member_location [DW_FORM_data1] (0x00)
+
+%F = type { [0 x i8], ptr, [8 x i8] }
+
+define internal void @_ZN2e34main17h934ff72f9a38d4bbE() unnamed_addr #0 !dbg !5 {
+start:
+ %qq = alloca %F, align 8
+ call void @llvm.dbg.declare(metadata ptr %qq, metadata !10, metadata !24), !dbg !25
+ store ptr null, ptr %qq, !dbg !25
+ ret void, !dbg !26
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #0
+
+attributes #0 = { nounwind uwtable }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.dbg.cu = !{!2}
+
+!0 = !{i32 1, !"PIE Level", i32 2}
+!1 = !{i32 2, !"Debug Info Version", i32 3}
+!2 = distinct !DICompileUnit(language: DW_LANG_Ada95, file: !3, producer: "gnat-llvm", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4)
+!3 = !DIFile(filename: "e3.rs", directory: "/home/tromey/Ada")
+!4 = !{}
+!5 = distinct !DISubprogram(name: "main", linkageName: "_ZN2e34mainE", scope: !6, file: !3, line: 2, type: !8, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagMainSubprogram, isOptimized: false, unit: !2, templateParams: !4, retainedNodes: !4)
+!6 = !DINamespace(name: "e3", scope: null)
+!7 = !DIFile(filename: "<unknown>", directory: "")
+!8 = !DISubroutineType(types: !9)
+!9 = !{null}
+!10 = !DILocalVariable(name: "qq", scope: !11, file: !3, line: 3, type: !12, align: 64)
+!11 = distinct !DILexicalBlock(scope: !5, file: !3, line: 3, column: 4)
+!12 = !DICompositeType(tag: DW_TAG_structure_type, name: "F", scope: !6, file: !7, size: 128, align: 64, elements: !13, identifier: "7ce1efff6b82281ab9ceb730566e7e20")
+!13 = !{!14, !15}
+!14 = !DIDerivedType(tag: DW_TAG_member, name: "Discr", scope: !12, file: !7, baseType: !23, size: 64, align: 64)
+!15 = !DICompositeType(tag: DW_TAG_variant_part, scope: !12, file: !7, size: 128, align: 64, elements: !16, identifier: "7ce1efff6b82281ab9ceb730566e7e20", discriminator: !14)
+!16 = !{!17, !22}
+!17 = !DIDerivedType(tag: DW_TAG_member, scope: !15, file: !7, baseType: !18, size: 128, align: 64, extraData: i32 74)
+!18 = !DICompositeType(tag: DW_TAG_variant, scope: !15, file: !7, size: 128, align: 64, elements: !19)
+!19 = !{!20, !21}
+!20 = !DIDerivedType(tag: DW_TAG_member, name: "field0", scope: !18, file: !7, baseType: !23, size: 64, align: 64, offset: 0)
+!21 = !DIDerivedType(tag: DW_TAG_member, name: "field1", scope: !18, file: !7, baseType: !23, size: 64, align: 64, offset: 64)
+!22 = !DIDerivedType(tag: DW_TAG_member, name: "field2", scope: !15, file: !7, baseType: !23, size: 64, align: 64, offset: 0, extraData: i32 75)
+!23 = !DIBasicType(name: "u64", size: 64, encoding: DW_ATE_unsigned)
+!24 = !DIExpression()
+!25 = !DILocation(line: 3, scope: !11)
+!26 = !DILocation(line: 4, scope: !5)
|
|
@llvm/pr-subscribers-debuginfo Author: Tom Tromey (tromey) ChangesCurrently, 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) Note that the intermediate DIDerivedType is still needed in this situation, because that is where the discriminants are stored. Full diff: https://github.com/llvm/llvm-project/pull/139300.diff 6 Files Affected:
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 7296bb84b7d95..5f14726c36672 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -6363,6 +6363,8 @@ The following ``tag:`` values are valid:
DW_TAG_enumeration_type = 4
DW_TAG_structure_type = 19
DW_TAG_union_type = 23
+ DW_TAG_variant = 25
+ DW_TAG_variant_part = 51
For ``DW_TAG_array_type``, the ``elements:`` should be :ref:`subrange
descriptors <DISubrange>` or :ref:`subrange descriptors
@@ -6398,6 +6400,16 @@ For ``DW_TAG_structure_type``, ``DW_TAG_class_type``, and
``tag: DW_TAG_friend``; or :ref:`subprograms <DISubprogram>` with
``isDefinition: false``.
+``DW_TAG_variant_part`` introduces a variant part of a structure type.
+This should have a discriminant, a member that is used to decide which
+elements are active. The elements of the variant part should each be
+a ``DW_TAG_member``; if a member has a non-null ``ExtraData``, then it
+is a ``ConstantInt`` or ``ConstantDataArray`` indicating the values of
+the discriminant member that cause the activation of this branch. A
+member itself may be of composite type with tag ``DW_TAG_variant``; in
+this case the members of that composite type are inlined into the
+current one.
+
.. _DISubrange:
DISubrange
diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h
index d293c28f5b450..4ce71bd3dad58 100644
--- a/llvm/include/llvm/IR/DIBuilder.h
+++ b/llvm/include/llvm/IR/DIBuilder.h
@@ -406,6 +406,19 @@ namespace llvm {
Constant *Discriminant,
DINode::DIFlags Flags, DIType *Ty);
+ /// Create debugging information entry for a variant. A variant
+ /// created this way "inlines" multiple members into the enclosing
+ /// variant part.
+ /// \param Scope Scope in which this variant is defined.
+ /// \param Elements Variant elements.
+ /// \param Discriminant The discriminant for this branch; null for
+ /// the default branch. This may be a
+ /// ConstantDataArray if the variant applies
+ /// for multiple discriminants.
+ /// \param Ty Parent type.
+ DIDerivedType *createVariantMemberType(DIScope *Scope, DINodeArray Elements,
+ Constant *Discriminant, DIType *Ty);
+
/// Create debugging information entry for a bit field member.
/// \param Scope Member scope.
/// \param Name Member name.
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 5f04e8b0d18ba..5a1ac5d662704 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -1013,6 +1013,7 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
constructEnumTypeDIE(Buffer, CTy);
break;
case dwarf::DW_TAG_variant_part:
+ case dwarf::DW_TAG_variant:
case dwarf::DW_TAG_structure_type:
case dwarf::DW_TAG_union_type:
case dwarf::DW_TAG_class_type:
@@ -1066,7 +1067,17 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
addDiscriminant(Variant, CI,
DD->isUnsignedDIType(Discriminator->getBaseType()));
}
- constructMemberDIE(Variant, DDTy);
+ // If the variant holds a composite type with tag
+ // DW_TAG_variant, inline those members into the variant
+ // DIE.
+ if (auto *Composite =
+ dyn_cast_or_null<DICompositeType>(DDTy->getBaseType());
+ Composite != nullptr &&
+ Composite->getTag() == dwarf::DW_TAG_variant) {
+ constructTypeDIE(Variant, Composite);
+ } else {
+ constructMemberDIE(Variant, DDTy);
+ }
} else {
constructMemberDIE(Buffer, DDTy);
}
diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index d9cc49fdad89c..90da9f3acfe57 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,
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 83c1264aef12b..2cfd3822ea05d 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -1343,6 +1343,7 @@ void Verifier::visitDICompositeType(const DICompositeType &N) {
N.getTag() == dwarf::DW_TAG_enumeration_type ||
N.getTag() == dwarf::DW_TAG_class_type ||
N.getTag() == dwarf::DW_TAG_variant_part ||
+ N.getTag() == dwarf::DW_TAG_variant ||
N.getTag() == dwarf::DW_TAG_namelist,
"invalid tag", &N);
diff --git a/llvm/test/DebugInfo/Generic/multi-variant.ll b/llvm/test/DebugInfo/Generic/multi-variant.ll
new file mode 100644
index 0000000000000..1c680b371bb8f
--- /dev/null
+++ b/llvm/test/DebugInfo/Generic/multi-variant.ll
@@ -0,0 +1,74 @@
+; RUN: %llc_dwarf -O0 -filetype=obj < %s > %t
+; RUN: llvm-dwarfdump -v -debug-info %t | FileCheck %s
+
+; Check for a variant part where a variant has multiple members.
+
+; CHECK: DW_AT_name [DW_FORM_str{{[a-z]+}}] ({{.*}} = "Discr")
+; CHECK: DW_TAG_variant_part
+; CHECK-NOT: TAG
+; CHECK: DW_AT_discr [DW_FORM_ref4] (cu + {{0x[0-9a-fA-F]+}} => {[[OFFSET:0x[0-9a-fA-F]+]]})
+; CHECK: DW_TAG_variant
+; CHECK: DW_AT_discr_value [DW_FORM_data1] (0x4a)
+; CHECK: DW_TAG_member
+; CHECK: DW_AT_name [DW_FORM_str{{[a-z]+}}] ({{.*}} = "field0")
+; CHECK: DW_AT_type
+; CHECK: DW_AT_alignment
+; CHECK: DW_AT_data_member_location [DW_FORM_data1] (0x00)
+; CHECK: DW_TAG_member
+; CHECK: DW_AT_name [DW_FORM_str{{[a-z]+}}] ({{.*}} = "field1")
+; CHECK: DW_AT_type
+; CHECK: DW_AT_alignment
+; CHECK: DW_AT_data_member_location [DW_FORM_data1] (0x08)
+; CHECK: DW_TAG_variant
+; CHECK: DW_AT_discr_value [DW_FORM_data1] (0x4b)
+; CHECK: DW_TAG_member
+; CHECK: DW_AT_name [DW_FORM_str{{[a-z]+}}] ({{.*}} = "field2")
+; CHECK: DW_AT_type
+; CHECK: DW_AT_alignment
+; CHECK: DW_AT_data_member_location [DW_FORM_data1] (0x00)
+
+%F = type { [0 x i8], ptr, [8 x i8] }
+
+define internal void @_ZN2e34main17h934ff72f9a38d4bbE() unnamed_addr #0 !dbg !5 {
+start:
+ %qq = alloca %F, align 8
+ call void @llvm.dbg.declare(metadata ptr %qq, metadata !10, metadata !24), !dbg !25
+ store ptr null, ptr %qq, !dbg !25
+ ret void, !dbg !26
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #0
+
+attributes #0 = { nounwind uwtable }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.dbg.cu = !{!2}
+
+!0 = !{i32 1, !"PIE Level", i32 2}
+!1 = !{i32 2, !"Debug Info Version", i32 3}
+!2 = distinct !DICompileUnit(language: DW_LANG_Ada95, file: !3, producer: "gnat-llvm", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4)
+!3 = !DIFile(filename: "e3.rs", directory: "/home/tromey/Ada")
+!4 = !{}
+!5 = distinct !DISubprogram(name: "main", linkageName: "_ZN2e34mainE", scope: !6, file: !3, line: 2, type: !8, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagMainSubprogram, isOptimized: false, unit: !2, templateParams: !4, retainedNodes: !4)
+!6 = !DINamespace(name: "e3", scope: null)
+!7 = !DIFile(filename: "<unknown>", directory: "")
+!8 = !DISubroutineType(types: !9)
+!9 = !{null}
+!10 = !DILocalVariable(name: "qq", scope: !11, file: !3, line: 3, type: !12, align: 64)
+!11 = distinct !DILexicalBlock(scope: !5, file: !3, line: 3, column: 4)
+!12 = !DICompositeType(tag: DW_TAG_structure_type, name: "F", scope: !6, file: !7, size: 128, align: 64, elements: !13, identifier: "7ce1efff6b82281ab9ceb730566e7e20")
+!13 = !{!14, !15}
+!14 = !DIDerivedType(tag: DW_TAG_member, name: "Discr", scope: !12, file: !7, baseType: !23, size: 64, align: 64)
+!15 = !DICompositeType(tag: DW_TAG_variant_part, scope: !12, file: !7, size: 128, align: 64, elements: !16, identifier: "7ce1efff6b82281ab9ceb730566e7e20", discriminator: !14)
+!16 = !{!17, !22}
+!17 = !DIDerivedType(tag: DW_TAG_member, scope: !15, file: !7, baseType: !18, size: 128, align: 64, extraData: i32 74)
+!18 = !DICompositeType(tag: DW_TAG_variant, scope: !15, file: !7, size: 128, align: 64, elements: !19)
+!19 = !{!20, !21}
+!20 = !DIDerivedType(tag: DW_TAG_member, name: "field0", scope: !18, file: !7, baseType: !23, size: 64, align: 64, offset: 0)
+!21 = !DIDerivedType(tag: DW_TAG_member, name: "field1", scope: !18, file: !7, baseType: !23, size: 64, align: 64, offset: 64)
+!22 = !DIDerivedType(tag: DW_TAG_member, name: "field2", scope: !15, file: !7, baseType: !23, size: 64, align: 64, offset: 0, extraData: i32 75)
+!23 = !DIBasicType(name: "u64", size: 64, encoding: DW_ATE_unsigned)
+!24 = !DIExpression()
+!25 = !DILocation(line: 3, scope: !11)
+!26 = !DILocation(line: 4, scope: !5)
|
|
Worth noting that Pascal also can have an arbitrary number of members per variant, which OpenVMS will surely care about @JohnReagan |
|
Thank you for the review. Can you land this for me? I do not have access. |
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/66/builds/13831 Here is the relevant piece of the build log for the reference |
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/85/builds/8683 Here is the relevant piece of the build log for the reference |
|
I do not understand how this patch could relate to that failure. |
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.