Skip to content

Commit cac94c5

Browse files
authored
Copy debug info when inlining (#2168)
1 parent 5f252c3 commit cac94c5

16 files changed

Lines changed: 269 additions & 13 deletions

src/ir/debug.h

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright 2019 WebAssembly Community Group participants
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef wasm_ir_debug_h
18+
#define wasm_ir_debug_h
19+
20+
#include <wasm-traversal.h>
21+
22+
namespace wasm {
23+
24+
namespace debug {
25+
26+
// Given an expression and a copy of it in another function, copy the debug
27+
// info into the second function.
28+
inline void copyDebugInfo(Expression* origin,
29+
Expression* copy,
30+
Function* originFunc,
31+
Function* copyFunc) {
32+
struct Lister : public PostWalker<Lister, UnifiedExpressionVisitor<Lister>> {
33+
std::vector<Expression*> list;
34+
void visitExpression(Expression* curr) { list.push_back(curr); }
35+
};
36+
37+
Lister originList;
38+
originList.walk(origin);
39+
Lister copyList;
40+
copyList.walk(copy);
41+
42+
auto& originDebug = originFunc->debugLocations;
43+
auto& copyDebug = copyFunc->debugLocations;
44+
45+
assert(originList.list.size() == copyList.list.size());
46+
for (Index i = 0; i < originList.list.size(); i++) {
47+
auto iter = originDebug.find(originList.list[i]);
48+
if (iter != originDebug.end()) {
49+
auto location = iter->second;
50+
copyDebug[copyList.list[i]] = location;
51+
}
52+
}
53+
};
54+
55+
} // namespace debug
56+
57+
} // namespace wasm
58+
59+
#endif // wasm_ir_debug_h

src/passes/Inlining.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
#include <atomic>
3434

35+
#include "ir/debug.h"
3536
#include "ir/literal-utils.h"
3637
#include "ir/module-utils.h"
3738
#include "ir/utils.h"
@@ -175,7 +176,7 @@ doInlining(Module* module, Function* into, InliningAction& action) {
175176
auto* block = Builder(*module).makeBlock();
176177
block->name = Name(std::string("__inlined_func$") + from->name.str);
177178
*action.callSite = block;
178-
// set up a locals mapping
179+
// Prepare to update the inlined code's locals and other things.
179180
struct Updater : public PostWalker<Updater> {
180181
std::map<Index, Index> localMapping;
181182
Name returnName;
@@ -193,33 +194,37 @@ doInlining(Module* module, Function* into, InliningAction& action) {
193194
} updater;
194195
updater.returnName = block->name;
195196
updater.builder = &builder;
197+
// Set up a locals mapping
196198
for (Index i = 0; i < from->getNumLocals(); i++) {
197199
updater.localMapping[i] = builder.addVar(into, from->getLocalType(i));
198200
}
199-
// assign the operands into the params
201+
// Assign the operands into the params
200202
for (Index i = 0; i < from->params.size(); i++) {
201203
block->list.push_back(
202204
builder.makeLocalSet(updater.localMapping[i], call->operands[i]));
203205
}
204-
// zero out the vars (as we may be in a loop, and may depend on their
206+
// Zero out the vars (as we may be in a loop, and may depend on their
205207
// zero-init value
206208
for (Index i = 0; i < from->vars.size(); i++) {
207209
block->list.push_back(
208210
builder.makeLocalSet(updater.localMapping[from->getVarIndexBase() + i],
209211
LiteralUtils::makeZero(from->vars[i], *module)));
210212
}
211-
// generate and update the inlined contents
213+
// Generate and update the inlined contents
212214
auto* contents = ExpressionManipulator::copy(from->body, *module);
215+
if (!from->debugLocations.empty()) {
216+
debug::copyDebugInfo(from->body, contents, from, into);
217+
}
213218
updater.walk(contents);
214219
block->list.push_back(contents);
215220
block->type = call->type;
216-
// if the function returned a value, we just set the block containing the
221+
// If the function returned a value, we just set the block containing the
217222
// inlined code to have that type. or, if the function was void and
218223
// contained void, that is fine too. a bad case is a void function in which
219224
// we have unreachable code, so we would be replacing a void call with an
220225
// unreachable; we need to handle
221226
if (contents->type == unreachable && block->type == none) {
222-
// make the block reachable by adding a break to it
227+
// Make the block reachable by adding a break to it
223228
block->list.push_back(builder.makeBreak(block->name));
224229
}
225230
return block;

test/debugInfo.asm.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,19 @@ function () {
8484
function nofile() {
8585
nofile(); //@line 1337
8686
}
87-
return { add: add, ret: ret, opts: opts, fib: fib, switch_reach: switch_reach, nofile: nofile };
87+
function inlineMe(x, y) {
88+
x = x | 0;
89+
y = y | 0;
90+
x = x + y | 0; //@line 120 "inline_me.c"
91+
y = x + y | 0; //@line 121 "inline_me.c"
92+
x = x + y | 0; //@line 122 "inline_me.c"
93+
return x | 0; //@line 123 "inline_me.c"
94+
}
95+
function inlineInto(x, y) {
96+
x = x | 0;
97+
y = y | 0;
98+
return inlineMe(x | 0, y | 0) | 0; //@line 125 "inline_me.c"
99+
}
100+
return { add: add, ret: ret, opts: opts, fib: fib, switch_reach: switch_reach, nofile: nofile, inlineInto: inlineInto };
88101
}
89102

test/debugInfo.fromasm

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
(export "fib" (func $fib))
99
(export "switch_reach" (func $switch_reach))
1010
(export "nofile" (func $nofile))
11+
(export "inlineInto" (func $inlineInto))
1112
(func $add (; 0 ;) (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32)
1213
;;@ tests/other_file.cpp:314159:0
1314
(i32.add
@@ -169,4 +170,20 @@
169170
;;@ (unknown):1337:0
170171
(call $nofile)
171172
)
173+
(func $inlineInto (; 6 ;) (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32)
174+
;;@ inline_me.c:125:0
175+
(i32.add
176+
;;@ inline_me.c:120:0
177+
(local.tee $0
178+
(i32.add
179+
(local.get $0)
180+
(local.get $1)
181+
)
182+
)
183+
(i32.add
184+
(local.get $0)
185+
(local.get $1)
186+
)
187+
)
188+
)
172189
)

test/debugInfo.fromasm.clamp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
(export "fib" (func $fib))
99
(export "switch_reach" (func $switch_reach))
1010
(export "nofile" (func $nofile))
11+
(export "inlineInto" (func $inlineInto))
1112
(func $add (; 0 ;) (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32)
1213
;;@ tests/other_file.cpp:314159:0
1314
(i32.add
@@ -169,4 +170,20 @@
169170
;;@ (unknown):1337:0
170171
(call $nofile)
171172
)
173+
(func $inlineInto (; 6 ;) (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32)
174+
;;@ inline_me.c:125:0
175+
(i32.add
176+
;;@ inline_me.c:120:0
177+
(local.tee $0
178+
(i32.add
179+
(local.get $0)
180+
(local.get $1)
181+
)
182+
)
183+
(i32.add
184+
(local.get $0)
185+
(local.get $1)
186+
)
187+
)
188+
)
172189
)

test/debugInfo.fromasm.clamp.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/debugInfo.fromasm.clamp.no-opts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
(export "fib" (func $fib))
1212
(export "switch_reach" (func $switch_reach))
1313
(export "nofile" (func $nofile))
14+
(export "inlineInto" (func $inlineInto))
1415
(func $add (; 0 ;) (param $x i32) (param $y i32) (result i32)
1516
;;@ tests/hello_world.c:5:0
1617
(local.set $x
@@ -287,4 +288,40 @@
287288
;;@ (unknown):1337:0
288289
(call $nofile)
289290
)
291+
(func $inlineMe (; 7 ;) (param $x i32) (param $y i32) (result i32)
292+
;;@ inline_me.c:120:0
293+
(local.set $x
294+
(i32.add
295+
(local.get $x)
296+
(local.get $y)
297+
)
298+
)
299+
;;@ inline_me.c:121:0
300+
(local.set $y
301+
(i32.add
302+
(local.get $x)
303+
(local.get $y)
304+
)
305+
)
306+
;;@ inline_me.c:122:0
307+
(local.set $x
308+
(i32.add
309+
(local.get $x)
310+
(local.get $y)
311+
)
312+
)
313+
;;@ inline_me.c:123:0
314+
(return
315+
(local.get $x)
316+
)
317+
)
318+
(func $inlineInto (; 8 ;) (param $x i32) (param $y i32) (result i32)
319+
;;@ inline_me.c:125:0
320+
(return
321+
(call $inlineMe
322+
(local.get $x)
323+
(local.get $y)
324+
)
325+
)
326+
)
290327
)

test/debugInfo.fromasm.clamp.no-opts.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/debugInfo.fromasm.imprecise

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
(export "fib" (func $fib))
66
(export "switch_reach" (func $switch_reach))
77
(export "nofile" (func $nofile))
8+
(export "inlineInto" (func $inlineInto))
89
(func $add (; 0 ;) (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32)
910
;;@ tests/other_file.cpp:314159:0
1011
(i32.add
@@ -161,4 +162,20 @@
161162
;;@ (unknown):1337:0
162163
(call $nofile)
163164
)
165+
(func $inlineInto (; 6 ;) (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32)
166+
;;@ inline_me.c:125:0
167+
(i32.add
168+
;;@ inline_me.c:120:0
169+
(local.tee $0
170+
(i32.add
171+
(local.get $0)
172+
(local.get $1)
173+
)
174+
)
175+
(i32.add
176+
(local.get $0)
177+
(local.get $1)
178+
)
179+
)
180+
)
164181
)

test/debugInfo.fromasm.imprecise.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)