summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-binary.cpp
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2017-11-13 15:48:16 -0800
committerGitHub <noreply@github.com>2017-11-13 15:48:16 -0800
commit0cc695efaf1423fb8615a302ed28f9142252eb16 (patch)
treec52688d12d1868e3a263bf718c5773140389e6fe /src/wasm/wasm-binary.cpp
parentca09203416a556f0a895f6cfa32426bdd46f9824 (diff)
downloadbinaryen-0cc695efaf1423fb8615a302ed28f9142252eb16.tar.gz
binaryen-0cc695efaf1423fb8615a302ed28f9142252eb16.tar.bz2
binaryen-0cc695efaf1423fb8615a302ed28f9142252eb16.zip
a stacky value in the middle of a block may be consumed (#1267)
Diffstat (limited to 'src/wasm/wasm-binary.cpp')
-rw-r--r--src/wasm/wasm-binary.cpp21
1 files changed, 20 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) {