Skip to content

Commit 5295929

Browse files
authored
when inlining, we must zero out non-param locals, as their initial zero value may be depended on (#1127)
1 parent 4f0bf33 commit 5295929

File tree

6 files changed

+154
-11
lines changed

6 files changed

+154
-11
lines changed

src/passes/Inlining.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <pass.h>
2929
#include <wasm-builder.h>
3030
#include <ast_utils.h>
31+
#include <ast/literal-utils.h>
3132
#include <parsing.h>
3233

3334
namespace wasm {
@@ -121,11 +122,12 @@ struct Planner : public WalkerPass<PostWalker<Planner>> {
121122
// Core inlining logic. Modifies the outside function (adding locals as
122123
// needed), and returns the inlined code.
123124
static Expression* doInlining(Module* module, Function* into, InliningAction& action) {
125+
Function* from = action.contents;
124126
auto* call = (*action.callSite)->cast<Call>();
125127
Builder builder(*module);
126128
auto* block = Builder(*module).makeBlock();
127129
block->type = call->type;
128-
block->name = Name(std::string("__inlined_func$") + action.contents->name.str);
130+
block->name = Name(std::string("__inlined_func$") + from->name.str);
129131
*action.callSite = block;
130132
// set up a locals mapping
131133
struct Updater : public PostWalker<Updater> {
@@ -145,15 +147,19 @@ static Expression* doInlining(Module* module, Function* into, InliningAction& ac
145147
} updater;
146148
updater.returnName = block->name;
147149
updater.builder = &builder;
148-
for (Index i = 0; i < action.contents->getNumLocals(); i++) {
149-
updater.localMapping[i] = builder.addVar(into, action.contents->getLocalType(i));
150+
for (Index i = 0; i < from->getNumLocals(); i++) {
151+
updater.localMapping[i] = builder.addVar(into, from->getLocalType(i));
150152
}
151153
// assign the operands into the params
152-
for (Index i = 0; i < action.contents->params.size(); i++) {
154+
for (Index i = 0; i < from->params.size(); i++) {
153155
block->list.push_back(builder.makeSetLocal(updater.localMapping[i], call->operands[i]));
154156
}
157+
// zero out the vars (as we may be in a loop, and may depend on their zero-init value
158+
for (Index i = 0; i < from->vars.size(); i++) {
159+
block->list.push_back(builder.makeSetLocal(updater.localMapping[from->getVarIndexBase() + i], LiteralUtils::makeZero(from->vars[i], *module)));
160+
}
155161
// generate and update the inlined contents
156-
auto* contents = ExpressionManipulator::copy(action.contents->body, *module);
162+
auto* contents = ExpressionManipulator::copy(from->body, *module);
157163
updater.walk(contents);
158164
block->list.push_back(contents);
159165
return block;

test/passes/inlining.txt

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,19 @@
5757
)
5858
(block
5959
(block $__inlined_func$with-local
60+
(set_local $2
61+
(f32.const 0)
62+
)
6063
(set_local $2
6164
(f32.const 2.1418280601501465)
6265
)
6366
)
6467
)
6568
(block
6669
(block $__inlined_func$with-local2
70+
(set_local $3
71+
(i64.const 0)
72+
)
6773
(set_local $3
6874
(i64.const 4)
6975
)
@@ -97,6 +103,9 @@
97103
(set_local $5
98104
(i64.const 890005350012)
99105
)
106+
(set_local $6
107+
(f32.const 0)
108+
)
100109
(block
101110
(drop
102111
(get_local $4)
@@ -143,3 +152,69 @@
143152
)
144153
)
145154
)
155+
(module
156+
(type $0 (func (result i32)))
157+
(type $1 (func (param f32 i32) (result i32)))
158+
(type $2 (func))
159+
(global $hangLimit (mut i32) (i32.const 25))
160+
(memory $0 1 1)
161+
(export "hangLimitInitializer" (func $hangLimitInitializer))
162+
(func $func_4 (type $1) (param $0 f32) (param $1 i32) (result i32)
163+
(local $2 i64)
164+
(local $3 f64)
165+
(local $4 f32)
166+
(local $5 i32)
167+
(local $6 i32)
168+
(local $7 f64)
169+
(local $8 i32)
170+
(loop $label$0 (result i32)
171+
(block $block
172+
(if
173+
(i32.eqz
174+
(get_global $hangLimit)
175+
)
176+
(return
177+
(i32.const 54)
178+
)
179+
)
180+
(set_global $hangLimit
181+
(i32.sub
182+
(get_global $hangLimit)
183+
(i32.const 1)
184+
)
185+
)
186+
)
187+
(i32.eqz
188+
(if (result i32)
189+
(i32.const 1)
190+
(if (result i32)
191+
(i32.eqz
192+
(block (result i32)
193+
(block $__inlined_func$func_3 (result i32)
194+
(set_local $8
195+
(i32.const 0)
196+
)
197+
(select
198+
(get_local $8)
199+
(tee_local $8
200+
(i32.const -1)
201+
)
202+
(i32.const 1)
203+
)
204+
)
205+
)
206+
)
207+
(br $label$0)
208+
(i32.const 0)
209+
)
210+
(unreachable)
211+
)
212+
)
213+
)
214+
)
215+
(func $hangLimitInitializer (type $2)
216+
(set_global $hangLimit
217+
(i32.const 25)
218+
)
219+
)
220+
)

test/passes/inlining.wast

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,63 @@
8686
)
8787
)
8888
)
89+
(module
90+
(global $hangLimit (mut i32) (i32.const 25))
91+
(memory $0 1 1)
92+
(export "hangLimitInitializer" (func $hangLimitInitializer))
93+
(func $func_3 (result i32)
94+
(local $0 i32)
95+
(select
96+
(get_local $0) ;; we depend on the zero-init value here, so it must be set when inlining!
97+
(tee_local $0
98+
(i32.const -1)
99+
)
100+
(i32.const 1)
101+
)
102+
)
103+
(func $func_4 (param $0 f32) (param $1 i32) (result i32)
104+
(local $2 i64)
105+
(local $3 f64)
106+
(local $4 f32)
107+
(local $5 i32)
108+
(local $6 i32)
109+
(local $7 f64)
110+
(loop $label$0 (result i32)
111+
(block
112+
(if
113+
(i32.eqz
114+
(get_global $hangLimit)
115+
)
116+
(return
117+
(i32.const 54)
118+
)
119+
)
120+
(set_global $hangLimit
121+
(i32.sub
122+
(get_global $hangLimit)
123+
(i32.const 1)
124+
)
125+
)
126+
)
127+
(i32.eqz
128+
(if (result i32)
129+
(i32.const 1)
130+
(if (result i32)
131+
(i32.eqz
132+
(call $func_3)
133+
)
134+
(br $label$0)
135+
(i32.const 0)
136+
)
137+
(unreachable)
138+
)
139+
)
140+
)
141+
)
142+
(func $hangLimitInitializer
143+
(set_global $hangLimit
144+
(i32.const 25)
145+
)
146+
)
147+
)
89148

test/unit.fromasm

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,7 +1164,6 @@
11641164
)
11651165
(func $keepAlive
11661166
(local $0 i32)
1167-
(local $1 i32)
11681167
(drop
11691168
(call $sqrts
11701169
(f64.const 3.14159)
@@ -1200,7 +1199,9 @@
12001199
(i32.const 17)
12011200
)
12021201
(call_indirect $FUNCSIG$vi
1203-
(get_local $1)
1202+
(tee_local $0
1203+
(i32.const 0)
1204+
)
12041205
(block (result i32)
12051206
(set_global $Int
12061207
(i32.const 1)

test/unit.fromasm.clamp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,7 +1188,6 @@
11881188
)
11891189
(func $keepAlive
11901190
(local $0 i32)
1191-
(local $1 i32)
11921191
(drop
11931192
(call $sqrts
11941193
(f64.const 3.14159)
@@ -1224,7 +1223,9 @@
12241223
(i32.const 17)
12251224
)
12261225
(call_indirect $FUNCSIG$vi
1227-
(get_local $1)
1226+
(tee_local $0
1227+
(i32.const 0)
1228+
)
12281229
(block (result i32)
12291230
(set_global $Int
12301231
(i32.const 1)

test/unit.fromasm.imprecise

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,7 +1126,6 @@
11261126
)
11271127
(func $keepAlive
11281128
(local $0 i32)
1129-
(local $1 i32)
11301129
(drop
11311130
(call $sqrts
11321131
(f64.const 3.14159)
@@ -1152,7 +1151,9 @@
11521151
(i32.const 17)
11531152
)
11541153
(call_indirect $FUNCSIG$vi
1155-
(get_local $1)
1154+
(tee_local $0
1155+
(i32.const 0)
1156+
)
11561157
(block (result i32)
11571158
(set_global $Int
11581159
(i32.const 1)

0 commit comments

Comments
 (0)