diff options
-rw-r--r-- | src/wasm/wasm-binary.cpp | 21 | ||||
-rw-r--r-- | test/consume-stacky.wasm | bin | 0 -> 40 bytes | |||
-rw-r--r-- | test/consume-stacky.wasm.fromBinary | 16 |
3 files changed, 36 insertions, 1 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 43eb94601..aec2efe0e 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -2173,17 +2173,36 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { } void WasmBinaryBuilder::pushBlockElements(Block* curr, size_t start, size_t end) { + // the first dropped element may be consumed by code later - it was on the stack first, + // and is the only thing left on the stack. there must be just one thing on the stack + // since we are at the end of a block context. note that we may need to drop more than + // one thing, since a bunch of concrete values may be all "consumed" by an unreachable + // (in which case, the first value can't be consumed anyhow, so it doesn't matter) + const Index NONE = -1; + Index consumable = NONE; for (size_t i = start; i < end; i++) { auto* item = expressionStack[i]; curr->list.push_back(item); if (i < end - 1) { // stacky&unreachable code may introduce elements that need to be dropped in non-final positions if (isConcreteWasmType(item->type)) { - curr->list.back() = Builder(wasm).makeDrop(curr->list.back()); + curr->list.back() = Builder(wasm).makeDrop(item); + if (consumable == NONE) { + // this is the first, and hence consumable value. note the location + consumable = curr->list.size() - 1; + } } } } expressionStack.resize(start); + // if we have a consumable item and need it, use it + if (consumable != NONE && curr->list.back()->type == none) { + Builder builder(wasm); + auto* item = curr->list[consumable]->cast<Drop>()->value; + auto temp = builder.addVar(currFunction, item->type); + curr->list[consumable] = builder.makeSetLocal(temp, item); + curr->list.push_back(builder.makeGetLocal(temp, item->type)); + } } void WasmBinaryBuilder::visitBlock(Block *curr) { diff --git a/test/consume-stacky.wasm b/test/consume-stacky.wasm Binary files differnew file mode 100644 index 000000000..8193dab45 --- /dev/null +++ b/test/consume-stacky.wasm diff --git a/test/consume-stacky.wasm.fromBinary b/test/consume-stacky.wasm.fromBinary new file mode 100644 index 000000000..b92d207b0 --- /dev/null +++ b/test/consume-stacky.wasm.fromBinary @@ -0,0 +1,16 @@ +(module + (type $0 (func (result i32))) + (memory $0 1 1) + (func $0 (; 0 ;) (type $0) (result i32) + (local $0 i32) + (set_local $0 + (i32.const 1) + ) + (i32.store + (i32.const 2) + (i32.const 3) + ) + (get_local $0) + ) +) + |