Skip to content

Commit 79daafc

Browse files
committed
Reland: [DWARF] Allow cross-CU references of subprogram definitions
This allows a call site tag in CU A to reference a callee DIE in CU B without resorting to creating an incomplete duplicate DIE for the callee inside of CU A. We already allow cross-CU references of subprogram declarations, so it doesn't seem like definitions ought to be special. This improves entry value evaluation and tail call frame synthesis in the LTO setting. During LTO, it's common for cross-module inlining to produce a call in some CU A where the callee resides in a different CU, and there is no declaration subprogram for the callee anywhere. In this case llvm would (unnecessarily, I think) emit an empty DW_TAG_subprogram in order to fill in the call site tag. That empty 'definition' defeats entry value evaluation etc., because the debugger can't figure out what it means. As a follow-up, maybe we could add a DWARF verifier check that a DW_TAG_subprogram at least has a DW_AT_name attribute. Update: Reland with a fix to create a declaration DIE when the declaration is missing from the CU's retainedTypes list. The declaration is left out of the retainedTypes list in two cases: 1) Re-compiling pre-r266445 bitcode (in which declarations weren't added to the retainedTypes list), and 2) Doing LTO function importing (which doesn't update the retainedTypes list). It's possible to handle (1) and (2) by modifying the retainedTypes list (in AutoUpgrade, or in the LTO importing logic resp.), but I don't see an advantage to doing it this way, as it would cause more DWARF to be emitted compared to creating the declaration DIEs lazily. Tested with a stage2 ThinLTO+RelWithDebInfo build of clang, and with a ReleaseLTO-g build of the test suite. rdar://46577651, rdar://57855316, rdar://57840415 Differential Revision: https://reviews.llvm.org/D70350
1 parent f72d001 commit 79daafc

File tree

6 files changed

+297
-7
lines changed

6 files changed

+297
-7
lines changed

llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -972,8 +972,8 @@ DIE &DwarfCompileUnit::constructCallSiteEntryDIE(
972972
addAddress(CallSiteDIE, getDwarf5OrGNUAttr(dwarf::DW_AT_call_target),
973973
MachineLocation(CallReg));
974974
} else {
975-
DIE *CalleeDIE = getOrCreateSubprogramDIE(CalleeSP);
976-
assert(CalleeDIE && "Could not create DIE for call site entry origin");
975+
DIE *CalleeDIE = getDIE(CalleeSP);
976+
assert(CalleeDIE && "Could not find DIE for call site entry origin");
977977
addDIEEntry(CallSiteDIE, getDwarf5OrGNUAttr(dwarf::DW_AT_call_origin),
978978
*CalleeDIE);
979979
}

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,14 @@ void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &SrcCU,
540540
}
541541
}
542542

543+
DIE &DwarfDebug::constructSubprogramDefinitionDIE(const DISubprogram *SP) {
544+
DICompileUnit *Unit = SP->getUnit();
545+
assert(SP->isDefinition() && "Subprogram not a definition");
546+
assert(Unit && "Subprogram definition without parent unit");
547+
auto &CU = getOrCreateDwarfCompileUnit(Unit);
548+
return *CU.getOrCreateSubprogramDIE(SP);
549+
}
550+
543551
/// Try to interpret values loaded into registers that forward parameters
544552
/// for \p CallMI. Store parameters with interpreted value into \p Params.
545553
static void collectCallSiteParameters(const MachineInstr *CallMI,
@@ -750,6 +758,17 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP,
750758
if (!CalleeDecl || !CalleeDecl->getSubprogram())
751759
continue;
752760
CalleeSP = CalleeDecl->getSubprogram();
761+
762+
if (CalleeSP->isDefinition()) {
763+
// Ensure that a subprogram DIE for the callee is available in the
764+
// appropriate CU.
765+
constructSubprogramDefinitionDIE(CalleeSP);
766+
} else {
767+
// Create the declaration DIE if it is missing. This is required to
768+
// support compilation of old bitcode with an incomplete list of
769+
// retained metadata.
770+
CU.getOrCreateSubprogramDIE(CalleeSP);
771+
}
753772
}
754773

755774
// TODO: Omit call site entries for runtime calls (objc_msgSend, etc).
@@ -906,6 +925,8 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) {
906925
}
907926

908927
// Create DIEs for function declarations used for call site debug info.
928+
// Note: Declaration subprograms imported by LTO are not added to the unit's
929+
// list of retained types, so their DIEs are not constructed here.
909930
for (auto Scope : DIUnit->getRetainedTypes())
910931
if (auto *SP = dyn_cast_or_null<DISubprogram>(Scope))
911932
NewCU.getOrCreateSubprogramDIE(SP);

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h

+3
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,9 @@ class DwarfDebug : public DebugHandlerBase {
442442
/// Construct a DIE for this abstract scope.
443443
void constructAbstractSubprogramScopeDIE(DwarfCompileUnit &SrcCU, LexicalScope *Scope);
444444

445+
/// Construct a DIE for the subprogram definition \p SP and return it.
446+
DIE &constructSubprogramDefinitionDIE(const DISubprogram *SP);
447+
445448
/// Construct DIEs for call site entries describing the calls in \p MF.
446449
void constructCallSiteEntryDIEs(const DISubprogram &SP, DwarfCompileUnit &CU,
447450
DIE &ScopeDIE, const MachineFunction &MF);

llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp

+4-5
Original file line numberDiff line numberDiff line change
@@ -188,18 +188,17 @@ int64_t DwarfUnit::getDefaultLowerBound() const {
188188

189189
/// Check whether the DIE for this MDNode can be shared across CUs.
190190
bool DwarfUnit::isShareableAcrossCUs(const DINode *D) const {
191-
// When the MDNode can be part of the type system, the DIE can be shared
192-
// across CUs.
191+
// When the MDNode can be part of the type system (this includes subprogram
192+
// declarations *and* subprogram definitions, even local definitions), the
193+
// DIE must be shared across CUs.
193194
// Combining type units and cross-CU DIE sharing is lower value (since
194195
// cross-CU DIE sharing is used in LTO and removes type redundancy at that
195196
// level already) but may be implementable for some value in projects
196197
// building multiple independent libraries with LTO and then linking those
197198
// together.
198199
if (isDwoUnit() && !DD->shareAcrossDWOCUs())
199200
return false;
200-
return (isa<DIType>(D) ||
201-
(isa<DISubprogram>(D) && !cast<DISubprogram>(D)->isDefinition())) &&
202-
!DD->generateTypeUnits();
201+
return (isa<DIType>(D) || isa<DISubprogram>(D)) && !DD->generateTypeUnits();
203202
}
204203

205204
DIE *DwarfUnit::getDIE(const DINode *D) const {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
; RUN: llc -mtriple=arm64-apple-ios -filetype=obj < %s -o %t.o
2+
; RUN: llvm-dwarfdump %t.o | FileCheck %s -implicit-check-not=DW_TAG_subprogram
3+
4+
; The declaration subprogram for "function" is not in the CU's list of
5+
; retained types. Test that a DWARF call site entry can still be constructed.
6+
7+
; CHECK: DW_TAG_subprogram
8+
; CHECK: DW_AT_name {{.*}}__hidden#3_
9+
; CHECK: DW_TAG_call_site
10+
; CHECK: DW_AT_call_origin (0x{{0+}}[[FUNCTION_DIE:.*]])
11+
12+
; CHECK: 0x{{0+}}[[FUNCTION_DIE]]: DW_TAG_subprogram
13+
; CHECK: DW_AT_name {{.*}}function
14+
15+
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
16+
target triple = "arm64-apple-ios9.0.0"
17+
18+
define i32 @main() local_unnamed_addr !dbg !8 {
19+
%1 = tail call [2 x i64] @function([2 x i64] zeroinitializer), !dbg !11
20+
%2 = extractvalue [2 x i64] %1, 0, !dbg !11
21+
%3 = trunc i64 %2 to i32, !dbg !11
22+
ret i32 %3, !dbg !12
23+
}
24+
25+
declare !dbg !13 [2 x i64] @function([2 x i64]) local_unnamed_addr
26+
27+
!llvm.module.flags = !{!0, !1, !2, !3, !4}
28+
!llvm.dbg.cu = !{!5}
29+
!llvm.ident = !{!7}
30+
31+
!0 = !{i32 2, !"SDK Version", [2 x i32] [i32 13, i32 4]}
32+
!1 = !{i32 7, !"Dwarf Version", i32 4}
33+
!2 = !{i32 2, !"Debug Info Version", i32 3}
34+
!3 = !{i32 1, !"wchar_size", i32 4}
35+
!4 = !{i32 7, !"PIC Level", i32 2}
36+
!5 = distinct !DICompileUnit(language: DW_LANG_C99, file: !6, producer: "__hidden#0_", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, nameTableKind: None)
37+
!6 = !DIFile(filename: "__hidden#1_", directory: "__hidden#2_")
38+
!7 = !{!"Apple clang version 11.0.0 (llvm-project fa407d93fd5e618d76378c1ce4e4f517e0563278) (+internal-os)"}
39+
!8 = distinct !DISubprogram(name: "__hidden#3_", scope: !6, file: !6, line: 9, type: !9, scopeLine: 9, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !5)
40+
!9 = !DISubroutineType(types: !10)
41+
!10 = !{}
42+
!11 = !DILocation(line: 12, column: 10, scope: !8)
43+
!12 = !DILocation(line: 13, column: 3, scope: !8)
44+
!13 = !DISubprogram(name: "function", scope: !6, file: !6, line: 7, type: !9, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
; RUN: llc -mtriple=x86_64-apple-darwin -filetype=obj < %s -o %t.o
2+
; RUN: llvm-dwarfdump %t.o | FileCheck %s -implicit-check-not=DW_TAG_subprogram
3+
; RUN: llvm-dwarfdump --verify %t.o
4+
5+
; This test checks that cross-CU references within call site tags to subprogram
6+
; definitions are well-formed. There are 5 cases checked in this test. Each set
7+
; of checks is numbered and has a brief summary.
8+
9+
; Instructions to regenerate the IR:
10+
; clang -O1 -g -emit-llvm -o a.bc -c a.c
11+
; clang -O1 -g -emit-llvm -o b.bc -c b.c
12+
; llvm-link -o linked.bc a.bc b.bc
13+
; opt -O1 linked.bc -o merged.bc
14+
15+
; Source:
16+
; // a.c
17+
; __attribute__((optnone)) void noinline_func_in_a() {}
18+
;
19+
; __attribute__((optnone)) static void foo() {}
20+
; __attribute__((always_inline)) void always_inline_helper_in_a_that_calls_foo() {
21+
; foo();
22+
; }
23+
;
24+
; extern void func_from_b();
25+
; void call_func_in_b_from_a() {
26+
; func_from_b();
27+
; }
28+
;
29+
; // b.c
30+
; extern void noinline_func_in_a();
31+
; void call_noinline_func_in_a_from_b() {
32+
; noinline_func_in_a();
33+
; }
34+
;
35+
; __attribute__((optnone)) void foo() {}
36+
; extern void always_inline_helper_in_a_that_calls_foo();
37+
; void call_both_foos_from_b() {
38+
; foo();
39+
; always_inline_helper_in_a_that_calls_foo();
40+
; }
41+
;
42+
; __attribute__((optnone)) void func_from_b() {}
43+
; void call_func_in_b_from_b() {
44+
; func_from_b();
45+
; }
46+
47+
; === CU for a.c ===
48+
49+
; CHECK: DW_TAG_compile_unit
50+
; CHECK: DW_AT_name ("a.c")
51+
52+
; CHECK: DW_TAG_subprogram
53+
; CHECK: DW_AT_name ("func_from_b")
54+
; CHECK: DW_AT_declaration (true)
55+
56+
; CHECK: 0x{{0+}}[[NOINLINE_FUNC_IN_A:.*]]: DW_TAG_subprogram
57+
; CHECK: DW_AT_name ("noinline_func_in_a")
58+
59+
; 1) Check that "always_inline_helper_in_a_that_calls_foo" calls the "foo" in
60+
; a.c, and *not* the "foo" in b.c.
61+
; CHECK: 0x{{0+}}[[ALWAYS_INLINE_HELPER_IN_A:.*]]: DW_TAG_subprogram
62+
; CHECK: DW_AT_abstract_origin ({{.*}} "always_inline_helper_in_a_that_calls_foo")
63+
; CHECK: DW_TAG_call_site
64+
; CHECK-NEXT: DW_AT_call_origin (0x{{0+}}[[FOO_IN_A:.*]])
65+
66+
; CHECK: 0x{{0+}}[[FOO_IN_A]]: DW_TAG_subprogram
67+
; CHECK: DW_AT_name ("foo")
68+
69+
; 2) Check that "call_func_in_b_from_a" has a cross-CU ref into b.c.
70+
; CHECK: DW_TAG_subprogram
71+
; CHECK: DW_AT_name ("call_func_in_b_from_a")
72+
; CHECK: DW_TAG_call_site
73+
; CHECK-NEXT: DW_AT_call_origin (0x{{0+}}[[FUNC_FROM_B:.*]])
74+
75+
; CHECK: DW_TAG_subprogram
76+
; CHECK: DW_AT_name ("always_inline_helper_in_a_that_calls_foo")
77+
; CHECK: DW_AT_inline (DW_INL_inlined)
78+
79+
; === CU for b.c ===
80+
81+
; CHECK: DW_TAG_compile_unit
82+
; CHECK: DW_AT_name ("b.c")
83+
84+
; CHECK: DW_TAG_subprogram
85+
; CHECK: DW_AT_name ("noinline_func_in_a")
86+
; CHECK: DW_AT_declaration (true)
87+
88+
; CHECK: DW_TAG_subprogram
89+
; CHECK: DW_AT_name ("always_inline_helper_in_a_that_calls_foo")
90+
; CHECK: DW_AT_declaration (true)
91+
92+
; 3) Validate the cross-CU ref from "call_func_in_b_from_a" in a.c.
93+
; CHECK: 0x{{0+}}[[FUNC_FROM_B]]: DW_TAG_subprogram
94+
; CHECK: DW_AT_name ("func_from_b")
95+
96+
; 4) Validate the cross-CU ref from "call_noinline_func_in_a_from_b" in b.c.
97+
; CHECK: DW_TAG_subprogram
98+
; CHECK: DW_AT_name ("call_noinline_func_in_a_from_b")
99+
; CHECK: DW_TAG_call_site
100+
; CHECK-NEXT: DW_AT_call_origin (0x{{0+}}[[NOINLINE_FUNC_IN_A]])
101+
102+
; CHECK: 0x{{0+}}[[FOO_IN_B:.*]]: DW_TAG_subprogram
103+
; CHECK: DW_AT_name ("foo")
104+
105+
; 5) Validate that we correctly emit a cross-CU ref when the call is inlined
106+
; from another CU.
107+
; CHECK: DW_TAG_subprogram
108+
; CHECK: DW_AT_name ("call_both_foos_from_b")
109+
; CHECK: DW_TAG_call_site
110+
; CHECK-NEXT: DW_AT_call_origin (0x{{0+}}[[FOO_IN_B]])
111+
; CHECK: DW_TAG_call_site
112+
; CHECK-NEXT: DW_AT_call_origin (0x{{0+}}[[FOO_IN_A]])
113+
114+
; CHECK: DW_TAG_subprogram
115+
; CHECK: DW_AT_name ("call_func_in_b_from_b")
116+
; CHECK: DW_TAG_call_site
117+
; CHECK-NEXT: DW_AT_call_origin (0x{{0+}}[[FUNC_FROM_B]])
118+
119+
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
120+
target triple = "x86_64-apple-macosx10.14.0"
121+
122+
define void @noinline_func_in_a() local_unnamed_addr #0 !dbg !17 {
123+
entry:
124+
ret void, !dbg !20
125+
}
126+
127+
define void @always_inline_helper_in_a_that_calls_foo() local_unnamed_addr #1 !dbg !21 {
128+
entry:
129+
tail call fastcc void @foo.2(), !dbg !22
130+
ret void, !dbg !23
131+
}
132+
133+
define internal fastcc void @foo.2() unnamed_addr #0 !dbg !24 {
134+
entry:
135+
ret void, !dbg !25
136+
}
137+
138+
define void @call_func_in_b_from_a() local_unnamed_addr !dbg !26 {
139+
entry:
140+
tail call void @func_from_b() #3, !dbg !27
141+
ret void, !dbg !28
142+
}
143+
144+
define void @call_noinline_func_in_a_from_b() local_unnamed_addr !dbg !29 {
145+
entry:
146+
tail call void @noinline_func_in_a() #3, !dbg !30
147+
ret void, !dbg !31
148+
}
149+
150+
define void @foo() local_unnamed_addr #0 !dbg !32 {
151+
entry:
152+
ret void, !dbg !33
153+
}
154+
155+
define void @call_both_foos_from_b() local_unnamed_addr !dbg !34 {
156+
entry:
157+
tail call void @foo(), !dbg !35
158+
tail call fastcc void @foo.2() #3, !dbg !36
159+
ret void, !dbg !38
160+
}
161+
162+
define void @func_from_b() local_unnamed_addr #0 !dbg !39 {
163+
entry:
164+
ret void, !dbg !40
165+
}
166+
167+
define void @call_func_in_b_from_b() local_unnamed_addr !dbg !41 {
168+
entry:
169+
tail call void @func_from_b(), !dbg !42
170+
ret void, !dbg !43
171+
}
172+
173+
attributes #0 = { noinline }
174+
attributes #1 = { alwaysinline }
175+
176+
!llvm.dbg.cu = !{!0, !7}
177+
!llvm.ident = !{!12, !12}
178+
!llvm.module.flags = !{!13, !14, !15, !16}
179+
180+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 ([email protected]:llvm/llvm-project.git 310e85309f870ee7347ef979d7d8da9bf28e92ea)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
181+
!1 = !DIFile(filename: "a.c", directory: "/Users/vsk/tmp/lto-entry-vals")
182+
!2 = !{}
183+
!3 = !{!4}
184+
!4 = !DISubprogram(name: "func_from_b", scope: !1, file: !1, line: 8, type: !5, spFlags: DISPFlagOptimized, retainedNodes: !2)
185+
!5 = !DISubroutineType(types: !6)
186+
!6 = !{null, null}
187+
!7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !8, producer: "clang version 10.0.0 ([email protected]:llvm/llvm-project.git 310e85309f870ee7347ef979d7d8da9bf28e92ea)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !9, nameTableKind: None)
188+
!8 = !DIFile(filename: "b.c", directory: "/Users/vsk/tmp/lto-entry-vals")
189+
!9 = !{!10, !11}
190+
!10 = !DISubprogram(name: "noinline_func_in_a", scope: !8, file: !8, line: 1, type: !5, spFlags: DISPFlagOptimized, retainedNodes: !2)
191+
!11 = !DISubprogram(name: "always_inline_helper_in_a_that_calls_foo", scope: !8, file: !8, line: 7, type: !5, spFlags: DISPFlagOptimized, retainedNodes: !2)
192+
!12 = !{!"clang version 10.0.0 ([email protected]:llvm/llvm-project.git 310e85309f870ee7347ef979d7d8da9bf28e92ea)"}
193+
!13 = !{i32 7, !"Dwarf Version", i32 4}
194+
!14 = !{i32 2, !"Debug Info Version", i32 3}
195+
!15 = !{i32 1, !"wchar_size", i32 4}
196+
!16 = !{i32 7, !"PIC Level", i32 2}
197+
!17 = distinct !DISubprogram(name: "noinline_func_in_a", scope: !1, file: !1, line: 1, type: !18, scopeLine: 1, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
198+
!18 = !DISubroutineType(types: !19)
199+
!19 = !{null}
200+
!20 = !DILocation(line: 1, column: 53, scope: !17)
201+
!21 = distinct !DISubprogram(name: "always_inline_helper_in_a_that_calls_foo", scope: !1, file: !1, line: 4, type: !18, scopeLine: 4, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
202+
!22 = !DILocation(line: 5, column: 3, scope: !21)
203+
!23 = !DILocation(line: 6, column: 1, scope: !21)
204+
!24 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 3, type: !18, scopeLine: 3, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
205+
!25 = !DILocation(line: 3, column: 45, scope: !24)
206+
!26 = distinct !DISubprogram(name: "call_func_in_b_from_a", scope: !1, file: !1, line: 9, type: !18, scopeLine: 9, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
207+
!27 = !DILocation(line: 10, column: 3, scope: !26)
208+
!28 = !DILocation(line: 11, column: 1, scope: !26)
209+
!29 = distinct !DISubprogram(name: "call_noinline_func_in_a_from_b", scope: !8, file: !8, line: 2, type: !18, scopeLine: 2, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !7, retainedNodes: !2)
210+
!30 = !DILocation(line: 3, column: 3, scope: !29)
211+
!31 = !DILocation(line: 4, column: 1, scope: !29)
212+
!32 = distinct !DISubprogram(name: "foo", scope: !8, file: !8, line: 6, type: !18, scopeLine: 6, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !7, retainedNodes: !2)
213+
!33 = !DILocation(line: 6, column: 38, scope: !32)
214+
!34 = distinct !DISubprogram(name: "call_both_foos_from_b", scope: !8, file: !8, line: 8, type: !18, scopeLine: 8, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !7, retainedNodes: !2)
215+
!35 = !DILocation(line: 9, column: 3, scope: !34)
216+
!36 = !DILocation(line: 5, column: 3, scope: !21, inlinedAt: !37)
217+
!37 = distinct !DILocation(line: 10, column: 3, scope: !34)
218+
!38 = !DILocation(line: 11, column: 1, scope: !34)
219+
!39 = distinct !DISubprogram(name: "func_from_b", scope: !8, file: !8, line: 13, type: !18, scopeLine: 13, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !7, retainedNodes: !2)
220+
!40 = !DILocation(line: 13, column: 46, scope: !39)
221+
!41 = distinct !DISubprogram(name: "call_func_in_b_from_b", scope: !8, file: !8, line: 14, type: !18, scopeLine: 14, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !7, retainedNodes: !2)
222+
!42 = !DILocation(line: 15, column: 3, scope: !41)
223+
!43 = !DILocation(line: 16, column: 1, scope: !41)

0 commit comments

Comments
 (0)