Skip to content

Commit 1c2088c

Browse files
committed
Allow ExtraData field to be a node reference when used with DW_TAG_member/variable/inheritance
1 parent ab1765d commit 1c2088c

File tree

2 files changed

+108
-4
lines changed

2 files changed

+108
-4
lines changed

llvm/lib/IR/DebugInfoMetadata.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -959,16 +959,29 @@ DIType *DIDerivedType::getClassType() const {
959959
assert(getTag() == dwarf::DW_TAG_ptr_to_member_type);
960960
return cast_or_null<DIType>(getExtraData());
961961
}
962+
963+
// Helper function to extract ConstantAsMetadata from ExtraData,
964+
// handling extra data MDTuple unwrapping if needed.
965+
static ConstantAsMetadata *extractConstantMetadata(Metadata *ExtraData) {
966+
Metadata *ED = ExtraData;
967+
while (auto *Tuple = dyn_cast_or_null<MDTuple>(ED)) {
968+
if (Tuple->getNumOperands() != 1)
969+
return nullptr;
970+
ED = Tuple->getOperand(0);
971+
}
972+
return cast_or_null<ConstantAsMetadata>(ED);
973+
}
974+
962975
uint32_t DIDerivedType::getVBPtrOffset() const {
963976
assert(getTag() == dwarf::DW_TAG_inheritance);
964-
if (auto *CM = cast_or_null<ConstantAsMetadata>(getExtraData()))
977+
if (auto *CM = extractConstantMetadata(getExtraData()))
965978
if (auto *CI = dyn_cast_or_null<ConstantInt>(CM->getValue()))
966979
return static_cast<uint32_t>(CI->getZExtValue());
967980
return 0;
968981
}
969982
Constant *DIDerivedType::getStorageOffsetInBits() const {
970983
assert(getTag() == dwarf::DW_TAG_member && isBitField());
971-
if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData()))
984+
if (auto *C = extractConstantMetadata(getExtraData()))
972985
return C->getValue();
973986
return nullptr;
974987
}
@@ -977,13 +990,13 @@ Constant *DIDerivedType::getConstant() const {
977990
assert((getTag() == dwarf::DW_TAG_member ||
978991
getTag() == dwarf::DW_TAG_variable) &&
979992
isStaticMember());
980-
if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData()))
993+
if (auto *C = extractConstantMetadata(getExtraData()))
981994
return C->getValue();
982995
return nullptr;
983996
}
984997
Constant *DIDerivedType::getDiscriminantValue() const {
985998
assert(getTag() == dwarf::DW_TAG_member && !isStaticMember());
986-
if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData()))
999+
if (auto *C = extractConstantMetadata(getExtraData()))
9871000
return C->getValue();
9881001
return nullptr;
9891002
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
;; Test verifies that node reference in the extraData field are handled correctly
2+
;; when used with tags like DW_TAG_member, DW_TAG_inheritance etc.
3+
4+
; REQUIRES: object-emission
5+
; RUN: %llc_dwarf %s -filetype=obj -o - | llvm-dwarfdump - | FileCheck %s
6+
7+
; Example 1: BitField with storage offset (extraData: i64 0)
8+
%struct.BitField = type { i8 }
9+
@bf = global %struct.BitField zeroinitializer, !dbg !9
10+
11+
; Example 2: Static member with constant value (extraData: i32 42)
12+
%struct.Static = type { i32 }
13+
@st = global %struct.Static zeroinitializer, !dbg !16
14+
15+
; Example 3: Discriminant value for variant (extraData: i32 100)
16+
%union.Variant = type { [8 x i8] }
17+
@var = global %union.Variant zeroinitializer, !dbg !24
18+
19+
; Example 4: Inheritance VBPtr offset (extraData: i32 0)
20+
%class.Derived = type { i32 }
21+
@der = global %class.Derived zeroinitializer, !dbg !35
22+
23+
!llvm.dbg.cu = !{!0}
24+
!llvm.module.flags = !{!2, !3, !4}
25+
26+
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 11.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !8)
27+
!1 = !DIFile(filename: "test.cpp", directory: ".")
28+
!2 = !{i32 2, !"Debug Info Version", i32 3}
29+
!3 = !{i32 1, !"wchar_size", i32 4}
30+
!4 = !{i32 2, !"Dwarf Version", i32 5}
31+
!8 = !{!9, !16, !24, !35}
32+
33+
; extraData node definitions
34+
!15 = !{i64 0} ; BitField storage offset
35+
!22 = !{i32 42} ; Static member constant value
36+
!33 = !{!42}
37+
!41 = !{i32 0} ; VBPtr offset
38+
!42 = !{i32 100} ; Discriminant value
39+
40+
; CHECK: {{.*}} DW_TAG_variable
41+
; CHECK: {{.*}} DW_AT_name ("bf")
42+
; CHECK: {{.*}} DW_TAG_member
43+
; CHECK: {{.*}} DW_AT_name ("field")
44+
; === BitField: extraData holds storage offset ===
45+
!9 = !DIGlobalVariableExpression(var: !10, expr: !DIExpression())
46+
!10 = distinct !DIGlobalVariable(name: "bf", scope: !0, file: !1, line: 5, type: !11, isLocal: false, isDefinition: true)
47+
!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "BitField", file: !1, line: 5, size: 8, elements: !12)
48+
!12 = !{!13}
49+
!13 = !DIDerivedType(tag: DW_TAG_member, name: "field", scope: !11, file: !1, line: 6, baseType: !14, size: 3, flags: DIFlagBitField, extraData: !15)
50+
!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
51+
52+
; CHECK: {{.*}} DW_TAG_variable
53+
; CHECK: {{.*}} DW_AT_name ("st")
54+
; CHECK: {{.*}} DW_TAG_member
55+
; CHECK: {{.*}} DW_AT_name ("const_val")
56+
; CHECK: {{.*}} DW_AT_const_value (42)
57+
; === Static Member: extraData holds constant value ===
58+
!16 = !DIGlobalVariableExpression(var: !17, expr: !DIExpression())
59+
!17 = distinct !DIGlobalVariable(name: "st", scope: !0, file: !1, line: 10, type: !18, isLocal: false, isDefinition: true)
60+
!18 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Static", file: !1, line: 10, size: 32, elements: !19)
61+
!19 = !{!20}
62+
!20 = !DIDerivedType(tag: DW_TAG_member, name: "const_val", scope: !18, file: !1, line: 11, baseType: !21, flags: DIFlagStaticMember, extraData: !22)
63+
!21 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !14)
64+
65+
; CHECK: {{.*}} DW_TAG_variable
66+
; CHECK: {{.*}} DW_AT_name ("var")
67+
; CHECK: {{.*}} DW_TAG_member
68+
; CHECK: {{.*}} DW_AT_name ("variant_none")
69+
; CHECK: {{.*}} DW_AT_discr_value (0x64)
70+
; === Discriminant: extraData holds discriminant value ===
71+
!24 = !DIGlobalVariableExpression(var: !25, expr: !DIExpression())
72+
!25 = distinct !DIGlobalVariable(name: "var", scope: !0, file: !1, line: 15, type: !26, isLocal: false, isDefinition: true)
73+
!26 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Variant", file: !1, line: 15, size: 128, elements: !27)
74+
!27 = !{!28}
75+
!28 = !DICompositeType(tag: DW_TAG_variant_part, scope: !26, file: !1, size: 128, elements: !29, discriminator: !30)
76+
!29 = !{!31, !32}
77+
!30 = !DIDerivedType(tag: DW_TAG_member, scope: !28, file: !1, baseType: !14, size: 32, align: 32, flags: DIFlagArtificial)
78+
!31 = !DIDerivedType(tag: DW_TAG_member, name: "variant_none", scope: !28, file: !1, baseType: !14, size: 32)
79+
!32 = !DIDerivedType(tag: DW_TAG_member, name: "variant_some", scope: !28, file: !1, baseType: !14, size: 32, extraData: !33)
80+
81+
; CHECK: {{.*}} DW_TAG_variable
82+
; CHECK: {{.*}} DW_AT_name ("der")
83+
; CHECK: {{.*}} DW_TAG_inheritance
84+
; CHECK: {{.*}} DW_AT_type ({{.*}} "Base")
85+
; === Inheritance: extraData holds VBPtr offset ===
86+
!35 = !DIGlobalVariableExpression(var: !36, expr: !DIExpression())
87+
!36 = distinct !DIGlobalVariable(name: "der", scope: !0, file: !1, line: 20, type: !37, isLocal: false, isDefinition: true)
88+
!37 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Derived", file: !1, line: 20, size: 32, elements: !38)
89+
!38 = !{!39}
90+
!39 = !DIDerivedType(tag: DW_TAG_inheritance, scope: !37, baseType: !40, extraData: !41)
91+
!40 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Base", file: !1, line: 19, size: 32)

0 commit comments

Comments
 (0)