Skip to content

Commit 0cc695e

Browse files
authored
a stacky value in the middle of a block may be consumed (#1267)
1 parent ca09203 commit 0cc695e

3 files changed

Lines changed: 36 additions & 1 deletion

File tree

src/wasm/wasm-binary.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2173,17 +2173,36 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
21732173
}
21742174

21752175
void WasmBinaryBuilder::pushBlockElements(Block* curr, size_t start, size_t end) {
2176+
// the first dropped element may be consumed by code later - it was on the stack first,
2177+
// and is the only thing left on the stack. there must be just one thing on the stack
2178+
// since we are at the end of a block context. note that we may need to drop more than
2179+
// one thing, since a bunch of concrete values may be all "consumed" by an unreachable
2180+
// (in which case, the first value can't be consumed anyhow, so it doesn't matter)
2181+
const Index NONE = -1;
2182+
Index consumable = NONE;
21762183
for (size_t i = start; i < end; i++) {
21772184
auto* item = expressionStack[i];
21782185
curr->list.push_back(item);
21792186
if (i < end - 1) {
21802187
// stacky&unreachable code may introduce elements that need to be dropped in non-final positions
21812188
if (isConcreteWasmType(item->type)) {
2182-
curr->list.back() = Builder(wasm).makeDrop(curr->list.back());
2189+
curr->list.back() = Builder(wasm).makeDrop(item);
2190+
if (consumable == NONE) {
2191+
// this is the first, and hence consumable value. note the location
2192+
consumable = curr->list.size() - 1;
2193+
}
21832194
}
21842195
}
21852196
}
21862197
expressionStack.resize(start);
2198+
// if we have a consumable item and need it, use it
2199+
if (consumable != NONE && curr->list.back()->type == none) {
2200+
Builder builder(wasm);
2201+
auto* item = curr->list[consumable]->cast<Drop>()->value;
2202+
auto temp = builder.addVar(currFunction, item->type);
2203+
curr->list[consumable] = builder.makeSetLocal(temp, item);
2204+
curr->list.push_back(builder.makeGetLocal(temp, item->type));
2205+
}
21872206
}
21882207

21892208
void WasmBinaryBuilder::visitBlock(Block *curr) {

test/consume-stacky.wasm

40 Bytes
Binary file not shown.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
(module
2+
(type $0 (func (result i32)))
3+
(memory $0 1 1)
4+
(func $0 (; 0 ;) (type $0) (result i32)
5+
(local $0 i32)
6+
(set_local $0
7+
(i32.const 1)
8+
)
9+
(i32.store
10+
(i32.const 2)
11+
(i32.const 3)
12+
)
13+
(get_local $0)
14+
)
15+
)
16+

0 commit comments

Comments
 (0)