llvm.org GIT mirror llvm / 387a89b
Reapply "Linker: Drop function pointers for overridden subprograms" This reverts commit r233254, effectively reapplying r233164 (and its successors), with an additional testcase for when subprograms match exactly. This fixes PR22792 (again). I'm using the same approach, but I've moved up the call to `stripReplacedSubprograms()`. The function pointers need to be dropped before mapping any metadata from the source module, or else this can drop the function from new subprograms that have merged (via Metadata uniquing) with the old ones. Dropping the pointers first prevents them from merging. **** The original commit message follows. **** Linker: Drop function pointers for overridden subprograms Instead of dropping subprograms that have been overridden, just set their function pointers to `nullptr`. This is a minor adjustment to the stop-gap fix for PR21910 committed in r224487, and fixes the crasher from PR22792. The problem that r224487 put a band-aid on: how do we find the canonical subprogram for a `Function`? Since the backend currently relies on `DebugInfoFinder` (which does a naive in-order traversal of compile units and picks the first subprogram) for this, r224487 tried dropping non-canonical subprograms. Dropping subprograms fails because the backend *also* builds up a map from subprogram to compile unit (`DwarfDebug::SPMap`) based on the subprogram lists. A missing subprogram causes segfaults later when an inlined reference (such as in this testcase) is created. Instead, just drop the `Function` pointer to `nullptr`, which nicely mirrors what happens when an already-inlined `Function` is optimized out. We can't really be sure that it's the same definition anyway, as the testcase demonstrates. This still isn't completely satisfactory. Two flaws at least that I can think of: - I still haven't found a straightforward way to make this symmetric in the IR. (Interestingly, the DWARF output is already symmetric, and I've tested for that to be sure we don't regress.) - Using `DebugInfoFinder` to find the canonical subprogram for a function is kind of crazy. We should just attach metadata to the function, like this: define weak i32 @foo(i32, i32) !dbg !MDSubprogram(...) { git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@233302 91177308-0d34-0410-b5e6-96231b3b80d8 Duncan P. N. Exon Smith 5 years ago
6 changed file(s) with 404 addition(s) and 20 deletion(s). Raw diff Collapse all Expand all
12491249
12501250 /// Drop DISubprograms that have been superseded.
12511251 ///
1252 /// FIXME: this creates an asymmetric result: we strip losing subprograms from
1253 /// DstM, but leave losing subprograms in SrcM. Instead we should also strip
1254 /// losers from SrcM, but this requires extra plumbing in MapMetadata.
1252 /// FIXME: this creates an asymmetric result: we strip functions from losing
1253 /// subprograms in DstM, but leave losing subprograms in SrcM.
1254 /// TODO: Remove this logic once the backend can correctly determine canonical
1255 /// subprograms.
12551256 void ModuleLinker::stripReplacedSubprograms() {
12561257 // Avoid quadratic runtime by returning early when there's nothing to do.
12571258 if (OverridingFunctions.empty())
12611262 auto Functions = std::move(OverridingFunctions);
12621263 OverridingFunctions.clear();
12631264
1264 // Drop subprograms whose functions have been overridden by the new compile
1265 // unit.
1265 // Drop functions from subprograms if they've been overridden by the new
1266 // compile unit.
12661267 NamedMDNode *CompileUnits = DstM->getNamedMetadata("llvm.dbg.cu");
12671268 if (!CompileUnits)
12681269 return;
12731274 DITypedArray SPs(CU.getSubprograms());
12741275 assert(SPs && "Expected valid subprogram array");
12751276
1276 SmallVector NewSPs;
1277 NewSPs.reserve(SPs.getNumElements());
12781277 for (unsigned S = 0, SE = SPs.getNumElements(); S != SE; ++S) {
12791278 DISubprogram SP = SPs.getElement(S);
1280 if (SP && SP.getFunction() && Functions.count(SP.getFunction()))
1279 if (!SP || !SP.getFunction() || !Functions.count(SP.getFunction()))
12811280 continue;
12821281
1283 NewSPs.push_back(SP);
1284 }
1285
1286 // Redirect operand to the overriding subprogram.
1287 if (NewSPs.size() != SPs.getNumElements())
1288 CU.replaceSubprograms(DIArray(MDNode::get(DstM->getContext(), NewSPs)));
1282 // Prevent DebugInfoFinder from tagging this as the canonical subprogram,
1283 // since the canonical one is in the incoming module.
1284 SP->replaceFunction(nullptr);
1285 }
12891286 }
12901287 }
12911288
15621559 MapValue(GV, ValueMap, RF_None, &TypeMap, &ValMaterializer);
15631560 }
15641561
1562 // Strip replaced subprograms before mapping any metadata -- so that we're
1563 // not changing metadata from the source module (note that
1564 // linkGlobalValueBody() eventually calls RemapInstruction() and therefore
1565 // MapMetadata()) -- but after linking global value protocols -- so that
1566 // OverridingFunctions has been built.
1567 stripReplacedSubprograms();
1568
15651569 // Link in the function bodies that are defined in the source module into
15661570 // DstM.
15671571 for (Function &SF : *SrcM) {
15831587 continue;
15841588 linkGlobalValueBody(Src);
15851589 }
1586
1587 // Strip replaced subprograms before linking together compile units.
1588 stripReplacedSubprograms();
15891590
15901591 // Remap all of the named MDNodes in Src into the DstM module. We do this
15911592 // after linking GlobalValues so that MDNodes that reference GlobalValues
0 define weak_odr i32 @foo(i32 %a, i32 %b) {
1 entry:
2 %sum = add i32 %a, %b, !dbg !MDLocation(line: 2, scope: !3)
3 ret i32 %sum, !dbg !MDLocation(line: 3, scope: !3)
4 }
5
6 !llvm.module.flags = !{!0}
7 !0 = !{i32 2, !"Debug Info Version", i32 3}
8
9 !llvm.dbg.cu = !{!1}
10 !1 = !MDCompileUnit(language: DW_LANG_C99, file: !2, subprograms: !{!3}, emissionKind: 1)
11 !2 = !MDFile(filename: "foo.c", directory: "/path/to/dir")
12 !3 = !MDSubprogram(file: !4, scope: !4, line: 1, name: "foo", function: i32 (i32, i32)* @foo, type: !5)
13 !4 = !MDFile(filename: "foo.h", directory: "/path/to/dir")
14 !5 = !MDSubroutineType(types: !{})
0 define weak i32 @foo(i32 %a, i32 %b) {
1 entry:
2 %sum = call i32 @fastadd(i32 %a, i32 %b), !dbg !MDLocation(line: 52, scope: !3)
3 ret i32 %sum, !dbg !MDLocation(line: 53, scope: !3)
4 }
5
6 declare i32 @fastadd(i32, i32)
7
8 !llvm.module.flags = !{!0}
9 !0 = !{i32 2, !"Debug Info Version", i32 3}
10
11 !llvm.dbg.cu = !{!1}
12 !1 = !MDCompileUnit(language: DW_LANG_C99, file: !2, subprograms: !{!3}, emissionKind: 1)
13 !2 = !MDFile(filename: "foo.c", directory: "/path/to/dir")
14 !3 = !MDSubprogram(file: !2, scope: !2, line: 51, name: "foo", function: i32 (i32, i32)* @foo, type: !4)
15 !4 = !MDSubroutineType(types: !{})
4444 !1 = !MDFile(filename: "t1.cpp", directory: "/Users/dexonsmith/data/llvm/staging/test/Linker/repro/d1")
4545 !2 = !{}
4646
47 ; Extract out each compile unit's single subprogram. The replaced subprogram
48 ; should be dropped by the first compile unit.
49 ; CHECK-DAG: ![[SPs1]] = !{![[SP1:[0-9]+]]}
47 ; Extract out each compile unit's single subprogram. The replaced subprogram's
48 ; function should drop to null in the first compile unit.
49 ; CHECK-DAG: ![[SPs1]] = !{![[SP1:[0-9]+]], ![[SP2r:[0-9]+]]}
5050 ; CHECK-DAG: ![[SPs2]] = !{![[SP2:[0-9]+]]}
5151 !3 = !{!4, !7}
5252 !4 = !MDSubprogram(name: "foo", line: 2, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, scopeLine: 2, file: !1, scope: !5, type: !6, function: i32 ()* @_Z3foov, variables: !2)
5757 ; subprogram is pointing at the correct function.
5858 ; CHECK-DAG: ![[SP1]] = !MDSubprogram({{.*}} function: i32 ()* @_Z3foov
5959 ; CHECK-DAG: ![[SP2]] = !MDSubprogram({{.*}} file: ![[FILE:[0-9]+]],{{.*}} function: i32 (%struct.Class*)* @_ZN5ClassIiE3fooEv
60
61 ; We can't use CHECK-NOT/CHECK-SAME with a CHECK-DAG, so rely on field order to
62 ; prove that there's no function: here.
63 ; CHECK-DAG: ![[SP2r]] = {{.*}}!MDSubprogram({{.*}} isOptimized: false, variables:
6064 !7 = !MDSubprogram(name: "foo", line: 2, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, scopeLine: 2, file: !8, scope: !9, type: !6, function: i32 (%struct.Class*)* @_ZN5ClassIiE3fooEv, variables: !2)
6165
6266 ; The new subprogram should be pointing at the new directory.
0 ; RUN: llvm-link %s %S/Inputs/subprogram-linkonce-weak-odr.ll -S -o %t1
1 ; RUN: FileCheck %s -check-prefix=LW -check-prefix=CHECK <%t1
2 ; RUN: llvm-link %S/Inputs/subprogram-linkonce-weak-odr.ll %s -S -o %t2
3 ; RUN: FileCheck %s -check-prefix=WL -check-prefix=CHECK <%t2
4
5 ; This testcase tests the following flow:
6 ; - File A defines a linkonce_odr version of @foo which has inlined into @bar.
7 ; - File B defines a weak_odr version of @foo (identical definition).
8 ; - Linkage rules state File B version of @foo wins.
9 ; - Debug info for the subprograms of @foo match exactly. Without
10 ; intervention, the same subprogram would show up in both compile units, and
11 ; it would get associated with the compile unit where it was linkonce.
12 ; - @bar has inlined debug info related to the linkonce_odr @foo.
13 ;
14 ; This checks a corner case for the fix for PR22792, where subprograms match
15 ; exactly. It's a companion for subprogram-linkonce-weak.ll.
16
17 ; The LW prefix means linkonce (this file) first, then weak (the other file).
18 ; The WL prefix means weak (the other file) first, then linkonce (this file).
19
20 ; We'll see @bar before @foo if this file is first.
21 ; LW-LABEL: define i32 @bar(
22 ; LW: %sum = add i32 %a, %b, !dbg ![[FOOINBAR:[0-9]+]]
23 ; LW: ret i32 %sum, !dbg ![[BARRET:[0-9]+]]
24 ; LW-LABEL: define weak_odr i32 @foo(
25 ; LW: %sum = add i32 %a, %b, !dbg ![[FOOADD:[0-9]+]]
26 ; LW: ret i32 %sum, !dbg ![[FOORET:[0-9]+]]
27
28 ; We'll see @foo before @bar if this file is second.
29 ; WL-LABEL: define weak_odr i32 @foo(
30 ; WL: %sum = add i32 %a, %b, !dbg ![[FOOADD:[0-9]+]]
31 ; WL: ret i32 %sum, !dbg ![[FOORET:[0-9]+]]
32 ; WL-LABEL: define i32 @bar(
33 ; WL: %sum = add i32 %a, %b, !dbg ![[FOOINBAR:[0-9]+]]
34 ; WL: ret i32 %sum, !dbg ![[BARRET:[0-9]+]]
35
36 define i32 @bar(i32 %a, i32 %b) {
37 entry:
38 %sum = add i32 %a, %b, !dbg !MDLocation(line: 2, scope: !4,
39 inlinedAt: !MDLocation(line: 12, scope: !3))
40 ret i32 %sum, !dbg !MDLocation(line: 13, scope: !3)
41 }
42
43 define linkonce_odr i32 @foo(i32 %a, i32 %b) {
44 entry:
45 %sum = add i32 %a, %b, !dbg !MDLocation(line: 2, scope: !4)
46 ret i32 %sum, !dbg !MDLocation(line: 3, scope: !4)
47 }
48
49 !llvm.module.flags = !{!0}
50 !0 = !{i32 2, !"Debug Info Version", i32 3}
51
52 ; CHECK-LABEL: !llvm.dbg.cu =
53 ; LW-SAME: !{![[LCU:[0-9]+]], ![[WCU:[0-9]+]]}
54 ; WL-SAME: !{![[WCU:[0-9]+]], ![[LCU:[0-9]+]]}
55 !llvm.dbg.cu = !{!1}
56
57 ; LW: ![[LCU]] = !MDCompileUnit({{.*}} subprograms: ![[LSPs:[0-9]+]]
58 ; LW: ![[LSPs]] = !{![[BARSP:[0-9]+]], ![[FOOSP:[0-9]+]]}
59 ; LW: ![[BARSP]] = !MDSubprogram(name: "bar",
60 ; LW-SAME: function: i32 (i32, i32)* @bar
61 ; LW: ![[FOOSP]] = {{.*}}!MDSubprogram(name: "foo",
62 ; LW-NOT: function:
63 ; LW-SAME: ){{$}}
64 ; LW: ![[WCU]] = !MDCompileUnit({{.*}} subprograms: ![[WSPs:[0-9]+]]
65 ; LW: ![[WSPs]] = !{![[WEAKFOOSP:[0-9]+]]}
66 ; LW: ![[WEAKFOOSP]] = !MDSubprogram(name: "foo",
67 ; LW-SAME: function: i32 (i32, i32)* @foo
68 ; LW: ![[FOOINBAR]] = !MDLocation(line: 2, scope: ![[FOOSP]], inlinedAt: ![[BARIA:[0-9]+]])
69 ; LW: ![[BARIA]] = !MDLocation(line: 12, scope: ![[BARSP]])
70 ; LW: ![[BARRET]] = !MDLocation(line: 13, scope: ![[BARSP]])
71 ; LW: ![[FOOADD]] = !MDLocation(line: 2, scope: ![[WEAKFOOSP]])
72 ; LW: ![[FOORET]] = !MDLocation(line: 3, scope: ![[WEAKFOOSP]])
73
74 ; Same as above, but reordered.
75 ; WL: ![[WCU]] = !MDCompileUnit({{.*}} subprograms: ![[WSPs:[0-9]+]]
76 ; WL: ![[WSPs]] = !{![[WEAKFOOSP:[0-9]+]]}
77 ; WL: ![[WEAKFOOSP]] = !MDSubprogram(name: "foo",
78 ; WL-SAME: function: i32 (i32, i32)* @foo
79 ; WL: ![[LCU]] = !MDCompileUnit({{.*}} subprograms: ![[LSPs:[0-9]+]]
80 ; Note: for symmetry, LSPs would have a different copy of the subprogram.
81 ; WL: ![[LSPs]] = !{![[BARSP:[0-9]+]], ![[WEAKFOOSP:[0-9]+]]}
82 ; WL: ![[BARSP]] = !MDSubprogram(name: "bar",
83 ; WL-SAME: function: i32 (i32, i32)* @bar
84 ; WL: ![[FOOADD]] = !MDLocation(line: 2, scope: ![[WEAKFOOSP]])
85 ; WL: ![[FOORET]] = !MDLocation(line: 3, scope: ![[WEAKFOOSP]])
86 ; WL: ![[FOOINBAR]] = !MDLocation(line: 2, scope: ![[WEAKFOOSP]], inlinedAt: ![[BARIA:[0-9]+]])
87 ; WL: ![[BARIA]] = !MDLocation(line: 12, scope: ![[BARSP]])
88 ; WL: ![[BARRET]] = !MDLocation(line: 13, scope: ![[BARSP]])
89
90 !1 = !MDCompileUnit(language: DW_LANG_C99, file: !2, subprograms: !{!3, !4}, emissionKind: 1)
91 !2 = !MDFile(filename: "bar.c", directory: "/path/to/dir")
92 !3 = !MDSubprogram(file: !2, scope: !2, line: 11, name: "bar", function: i32 (i32, i32)* @bar, type: !6)
93 !4 = !MDSubprogram(file: !5, scope: !5, line: 1, name: "foo", function: i32 (i32, i32)* @foo, type: !6)
94 !5 = !MDFile(filename: "foo.h", directory: "/path/to/dir")
95 !6 = !MDSubroutineType(types: !{})
96
97 ; Crasher for llc.
98 ; REQUIRES: object-emission
99 ; RUN: %llc_dwarf -filetype=obj -O0 %t1 -o %t1.o
100 ; RUN: llvm-dwarfdump %t1.o -debug-dump=all | FileCheck %s -check-prefix=DWLW -check-prefix=DW
101 ; RUN: %llc_dwarf -filetype=obj -O0 %t2 -o %t2.o
102 ; RUN: llvm-dwarfdump %t2.o -debug-dump=all | FileCheck %s -check-prefix=DWWL -check-prefix=DW
103 ; Check that the debug info puts the subprogram (with PCs) in the correct
104 ; compile unit.
105
106 ; DW-LABEL: .debug_info contents:
107 ; DWLW: DW_TAG_compile_unit
108 ; DWLW: DW_AT_name {{.*}}"bar.c"
109 ; Note: If we stop emitting foo here, the comment below for DWWL (and the
110 ; check) should be copied up here.
111 ; DWLW: DW_TAG_subprogram
112 ; DWLW-NOT: DW_AT_low_pc
113 ; DWLW-NOT: DW_AT_high_pc
114 ; DWLW: DW_AT_name {{.*}}foo
115 ; DWLW: DW_AT_decl_file {{.*}}"/path/to/dir/foo.h"
116 ; DWLW: DW_AT_decl_line {{.*}}(1)
117 ; DWLW: DW_TAG_subprogram
118 ; DWLW: DW_AT_low_pc
119 ; DWLW: DW_AT_high_pc
120 ; DWLW: DW_AT_name {{.*}}bar
121 ; DWLW: DW_AT_decl_file {{.*}}"/path/to/dir/bar.c"
122 ; DWLW: DW_AT_decl_line {{.*}}(11)
123 ; DWLW: DW_TAG_inlined_subroutine
124 ; DWLW: DW_AT_abstract_origin
125 ; DWLW: DW_TAG_compile_unit
126 ; DWLW: DW_AT_name {{.*}}"foo.c"
127 ; DWLW: DW_TAG_subprogram
128 ; DWLW: DW_AT_low_pc
129 ; DWLW: DW_AT_high_pc
130 ; DWLW: DW_AT_name {{.*}}foo
131 ; DWLW: DW_AT_decl_file {{.*}}"/path/to/dir/foo.h"
132 ; DWLW: DW_AT_decl_line {{.*}}(1)
133
134 ; The DWARF output is already symmetric (just reordered).
135 ; DWWL: DW_TAG_compile_unit
136 ; DWWL: DW_AT_name {{.*}}"foo.c"
137 ; DWWL: DW_TAG_subprogram
138 ; DWWL: DW_AT_low_pc
139 ; DWWL: DW_AT_high_pc
140 ; DWWL: DW_AT_name {{.*}}foo
141 ; DWWL: DW_AT_decl_file {{.*}}"/path/to/dir/foo.h"
142 ; DWWL: DW_AT_decl_line {{.*}}(1)
143 ; DWWL: DW_TAG_compile_unit
144 ; DWWL: DW_AT_name {{.*}}"bar.c"
145 ; Note: for symmetry, foo would also show up in this compile unit
146 ; (alternatively, it wouldn't show up in the DWLW case). If we start emitting
147 ; foo here, this should be updated by checking that we don't emit low_pc and
148 ; high_pc for it.
149 ; DWWL-NOT: DW_AT_name {{.*}}foo
150 ; DWWL: DW_TAG_subprogram
151 ; DWWL-NOT: DW_AT_name {{.*}}foo
152 ; DWWL: DW_AT_low_pc
153 ; DWWL: DW_AT_high_pc
154 ; DWWL-NOT: DW_AT_name {{.*}}foo
155 ; DWWL: DW_AT_name {{.*}}bar
156 ; DWWL: DW_AT_decl_file {{.*}}"/path/to/dir/bar.c"
157 ; DWWL: DW_AT_decl_line {{.*}}(11)
158 ; DWWL: DW_TAG_inlined_subroutine
159 ; DWWL: DW_AT_abstract_origin
160
161 ; DW-LABEL: .debug_line contents:
162 ; Check that we have the right things in the line table as well.
163
164 ; DWLW-LABEL: file_names[{{ *}}1]{{.*}} bar.c
165 ; DWLW-LABEL: file_names[{{ *}}2]{{.*}} foo.h
166 ; DWLW: 2 0 2 0 0 is_stmt prologue_end
167 ; DWLW-LABEL: file_names[{{ *}}1]{{.*}} foo.h
168 ; DWLW: 2 0 1 0 0 is_stmt prologue_end
169 ; DWLW-NOT: prologue_end
170
171 ; DWWL-LABEL: file_names[{{ *}}1]{{.*}} foo.h
172 ; DWWL: 2 0 1 0 0 is_stmt prologue_end
173 ; DWWL-LABEL: file_names[{{ *}}1]{{.*}} bar.c
174 ; DWWL-LABEL: file_names[{{ *}}2]{{.*}} foo.h
175 ; DWWL: 2 0 2 0 0 is_stmt prologue_end
176 ; DWWL-NOT: prologue_end
0 ; RUN: llvm-link %s %S/Inputs/subprogram-linkonce-weak.ll -S -o %t1
1 ; RUN: FileCheck %s -check-prefix=LW -check-prefix=CHECK <%t1
2 ; RUN: llvm-link %S/Inputs/subprogram-linkonce-weak.ll %s -S -o %t2
3 ; RUN: FileCheck %s -check-prefix=WL -check-prefix=CHECK <%t2
4
5 ; This testcase tests the following flow:
6 ; - File A defines a linkonce version of @foo which has inlined into @bar.
7 ; - File B defines a weak version of @foo (different definition).
8 ; - Linkage rules state File B version of @foo wins.
9 ; - @bar still has inlined debug info related to the linkonce @foo.
10 ;
11 ; This should fix PR22792, although the testcase was hand-written. There's a
12 ; RUN line with a crasher for llc at the end with checks for the DWARF output.
13
14 ; The LW prefix means linkonce (this file) first, then weak (the other file).
15 ; The WL prefix means weak (the other file) first, then linkonce (this file).
16
17 ; We'll see @bar before @foo if this file is first.
18 ; LW-LABEL: define i32 @bar(
19 ; LW: %sum = add i32 %a, %b, !dbg ![[FOOINBAR:[0-9]+]]
20 ; LW: ret i32 %sum, !dbg ![[BARRET:[0-9]+]]
21 ; LW-LABEL: define weak i32 @foo(
22 ; LW: %sum = call i32 @fastadd(i32 %a, i32 %b), !dbg ![[FOOCALL:[0-9]+]]
23 ; LW: ret i32 %sum, !dbg ![[FOORET:[0-9]+]]
24
25 ; We'll see @foo before @bar if this file is second.
26 ; WL-LABEL: define weak i32 @foo(
27 ; WL: %sum = call i32 @fastadd(i32 %a, i32 %b), !dbg ![[FOOCALL:[0-9]+]]
28 ; WL: ret i32 %sum, !dbg ![[FOORET:[0-9]+]]
29 ; WL-LABEL: define i32 @bar(
30 ; WL: %sum = add i32 %a, %b, !dbg ![[FOOINBAR:[0-9]+]]
31 ; WL: ret i32 %sum, !dbg ![[BARRET:[0-9]+]]
32
33 define i32 @bar(i32 %a, i32 %b) {
34 entry:
35 %sum = add i32 %a, %b, !dbg !MDLocation(line: 2, scope: !4,
36 inlinedAt: !MDLocation(line: 12, scope: !3))
37 ret i32 %sum, !dbg !MDLocation(line: 13, scope: !3)
38 }
39
40 define linkonce i32 @foo(i32 %a, i32 %b) {
41 entry:
42 %sum = add i32 %a, %b, !dbg !MDLocation(line: 2, scope: !4)
43 ret i32 %sum, !dbg !MDLocation(line: 3, scope: !4)
44 }
45
46 !llvm.module.flags = !{!0}
47 !0 = !{i32 2, !"Debug Info Version", i32 3}
48
49 ; CHECK-LABEL: !llvm.dbg.cu =
50 ; LW-SAME: !{![[LCU:[0-9]+]], ![[WCU:[0-9]+]]}
51 ; WL-SAME: !{![[WCU:[0-9]+]], ![[LCU:[0-9]+]]}
52 !llvm.dbg.cu = !{!1}
53
54 ; LW: ![[LCU]] = !MDCompileUnit({{.*}} subprograms: ![[LSPs:[0-9]+]]
55 ; LW: ![[LSPs]] = !{![[BARSP:[0-9]+]], ![[FOOSP:[0-9]+]]}
56 ; LW: ![[BARSP]] = !MDSubprogram(name: "bar",
57 ; LW-SAME: function: i32 (i32, i32)* @bar
58 ; LW: ![[FOOSP]] = {{.*}}!MDSubprogram(name: "foo",
59 ; LW-NOT: function:
60 ; LW-SAME: ){{$}}
61 ; LW: ![[WCU]] = !MDCompileUnit({{.*}} subprograms: ![[WSPs:[0-9]+]]
62 ; LW: ![[WSPs]] = !{![[WEAKFOOSP:[0-9]+]]}
63 ; LW: ![[WEAKFOOSP]] = !MDSubprogram(name: "foo",
64 ; LW-SAME: function: i32 (i32, i32)* @foo
65 ; LW: ![[FOOINBAR]] = !MDLocation(line: 2, scope: ![[FOOSP]], inlinedAt: ![[BARIA:[0-9]+]])
66 ; LW: ![[BARIA]] = !MDLocation(line: 12, scope: ![[BARSP]])
67 ; LW: ![[BARRET]] = !MDLocation(line: 13, scope: ![[BARSP]])
68 ; LW: ![[FOOCALL]] = !MDLocation(line: 52, scope: ![[WEAKFOOSP]])
69 ; LW: ![[FOORET]] = !MDLocation(line: 53, scope: ![[WEAKFOOSP]])
70
71 ; Same as above, but reordered.
72 ; WL: ![[WCU]] = !MDCompileUnit({{.*}} subprograms: ![[WSPs:[0-9]+]]
73 ; WL: ![[WSPs]] = !{![[WEAKFOOSP:[0-9]+]]}
74 ; WL: ![[WEAKFOOSP]] = !MDSubprogram(name: "foo",
75 ; WL-SAME: function: i32 (i32, i32)* @foo
76 ; WL: ![[LCU]] = !MDCompileUnit({{.*}} subprograms: ![[LSPs:[0-9]+]]
77 ; WL: ![[LSPs]] = !{![[BARSP:[0-9]+]], ![[FOOSP:[0-9]+]]}
78 ; WL: ![[BARSP]] = !MDSubprogram(name: "bar",
79 ; WL-SAME: function: i32 (i32, i32)* @bar
80 ; WL: ![[FOOSP]] = {{.*}}!MDSubprogram(name: "foo",
81 ; Note, for symmetry, this should be "NOT: function:" and "SAME: ){{$}}".
82 ; WL-SAME: function: i32 (i32, i32)* @foo
83 ; WL: ![[FOOCALL]] = !MDLocation(line: 52, scope: ![[WEAKFOOSP]])
84 ; WL: ![[FOORET]] = !MDLocation(line: 53, scope: ![[WEAKFOOSP]])
85 ; WL: ![[FOOINBAR]] = !MDLocation(line: 2, scope: ![[FOOSP]], inlinedAt: ![[BARIA:[0-9]+]])
86 ; WL: ![[BARIA]] = !MDLocation(line: 12, scope: ![[BARSP]])
87 ; WL: ![[BARRET]] = !MDLocation(line: 13, scope: ![[BARSP]])
88
89 !1 = !MDCompileUnit(language: DW_LANG_C99, file: !2, subprograms: !{!3, !4}, emissionKind: 1)
90 !2 = !MDFile(filename: "bar.c", directory: "/path/to/dir")
91 !3 = !MDSubprogram(file: !2, scope: !2, line: 11, name: "bar", function: i32 (i32, i32)* @bar, type: !5)
92 !4 = !MDSubprogram(file: !2, scope: !2, line: 1, name: "foo", function: i32 (i32, i32)* @foo, type: !5)
93 !5 = !MDSubroutineType(types: !{})
94
95 ; Crasher for llc.
96 ; REQUIRES: object-emission
97 ; RUN: %llc_dwarf -filetype=obj -O0 %t1 -o %t1.o
98 ; RUN: llvm-dwarfdump %t1.o -debug-dump=all | FileCheck %s -check-prefix=DWLW -check-prefix=DW
99 ; RUN: %llc_dwarf -filetype=obj -O0 %t2 -o %t2.o
100 ; RUN: llvm-dwarfdump %t2.o -debug-dump=all | FileCheck %s -check-prefix=DWWL -check-prefix=DW
101 ; Check that the debug info for the discarded linkonce version of @foo doesn't
102 ; reference any code, and that the other subprograms look correct.
103
104 ; DW-LABEL: .debug_info contents:
105 ; DWLW: DW_TAG_compile_unit
106 ; DWLW: DW_AT_name {{.*}}"bar.c"
107 ; DWLW: DW_TAG_subprogram
108 ; DWLW-NOT: DW_AT_low_pc
109 ; DWLW-NOT: DW_AT_high_pc
110 ; DWLW: DW_AT_name {{.*}}foo
111 ; DWLW: DW_AT_decl_file {{.*}}"/path/to/dir/bar.c"
112 ; DWLW: DW_AT_decl_line {{.*}}(1)
113 ; DWLW: DW_TAG_subprogram
114 ; DWLW: DW_AT_low_pc
115 ; DWLW: DW_AT_high_pc
116 ; DWLW: DW_AT_name {{.*}}bar
117 ; DWLW: DW_AT_decl_file {{.*}}"/path/to/dir/bar.c"
118 ; DWLW: DW_AT_decl_line {{.*}}(11)
119
120 ; DWLW: DW_TAG_inlined_subroutine
121 ; DWLW: DW_AT_abstract_origin
122 ; DWLW: DW_TAG_compile_unit
123 ; DWLW: DW_AT_name {{.*}}"foo.c"
124 ; DWLW: DW_TAG_subprogram
125 ; DWLW: DW_AT_low_pc
126 ; DWLW: DW_AT_high_pc
127 ; DWLW: DW_AT_name {{.*}}foo
128 ; DWLW: DW_AT_decl_file {{.*}}"/path/to/dir/foo.c"
129 ; DWLW: DW_AT_decl_line {{.*}}(51)
130
131 ; The DWARF output is already symmetric (just reordered).
132 ; DWWL: DW_TAG_compile_unit
133 ; DWWL: DW_AT_name {{.*}}"foo.c"
134 ; DWWL: DW_TAG_subprogram
135 ; DWWL: DW_AT_low_pc
136 ; DWWL: DW_AT_high_pc
137 ; DWWL: DW_AT_name {{.*}}foo
138 ; DWWL: DW_AT_decl_file {{.*}}"/path/to/dir/foo.c"
139 ; DWWL: DW_AT_decl_line {{.*}}(51)
140 ; DWWL: DW_TAG_compile_unit
141 ; DWWL: DW_AT_name {{.*}}"bar.c"
142 ; DWWL: DW_TAG_subprogram
143 ; DWWL-NOT: DW_AT_low_pc
144 ; DWWL-NOT: DW_AT_high_pc
145 ; DWWL: DW_AT_name {{.*}}foo
146 ; DWWL: DW_AT_decl_file {{.*}}"/path/to/dir/bar.c"
147 ; DWWL: DW_AT_decl_line {{.*}}(1)
148 ; DWWL: DW_TAG_subprogram
149 ; DWWL: DW_AT_low_pc
150 ; DWWL: DW_AT_high_pc
151 ; DWWL: DW_AT_name {{.*}}bar
152 ; DWWL: DW_AT_decl_file {{.*}}"/path/to/dir/bar.c"
153 ; DWWL: DW_AT_decl_line {{.*}}(11)
154 ; DWWL: DW_TAG_inlined_subroutine
155 ; DWWL: DW_AT_abstract_origin
156
157 ; DW-LABEL: .debug_line contents:
158 ; Check that we have the right things in the line table as well.
159
160 ; DWLW-LABEL: file_names[{{ *}}1]{{.*}} bar.c
161 ; DWLW: 2 0 1 0 0 is_stmt prologue_end
162 ; DWLW-LABEL: file_names[{{ *}}1]{{.*}} foo.c
163 ; DWLW: 52 0 1 0 0 is_stmt prologue_end
164 ; DWLW-NOT: prologue_end
165
166 ; DWWL-LABEL: file_names[{{ *}}1]{{.*}} foo.c
167 ; DWWL: 52 0 1 0 0 is_stmt prologue_end
168 ; DWWL-LABEL: file_names[{{ *}}1]{{.*}} bar.c
169 ; DWWL: 2 0 1 0 0 is_stmt prologue_end
170 ; DWWL-NOT: prologue_end