summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xauto_update_tests.py11
-rwxr-xr-xcheck.py16
-rw-r--r--src/binaryen-c.cpp23
-rw-r--r--src/passes/PrintCallGraph.cpp24
-rw-r--r--src/wasm-binary.h4
-rw-r--r--src/wasm/wasm-binary.cpp77
-rw-r--r--test/example/c-api-unused-mem.cpp93
-rw-r--r--test/example/c-api-unused-mem.txt101
-rw-r--r--test/stacky.wasmbin0 -> 54 bytes
-rw-r--r--test/stacky.wasm.fromBinary21
10 files changed, 320 insertions, 50 deletions
diff --git a/auto_update_tests.py b/auto_update_tests.py
index f65a8c026..294bad750 100755
--- a/auto_update_tests.py
+++ b/auto_update_tests.py
@@ -177,4 +177,15 @@ for t in os.listdir('test'):
actual = actual.replace('printing before:\n', '')
open(t, 'w').write(actual)
+print '\n[ checking wasm-dis on provided binaries... ]\n'
+
+for t in os.listdir('test'):
+ if t.endswith('.wasm') and not t.startswith('spec'):
+ print '..', t
+ t = os.path.join('test', t)
+ cmd = [os.path.join('bin', 'wasm-dis'), t]
+ actual = run_command(cmd)
+
+ open(t + '.fromBinary', 'w').write(actual)
+
print '\n[ success! ]'
diff --git a/check.py b/check.py
index c958c3f2b..ce2ae4f50 100755
--- a/check.py
+++ b/check.py
@@ -23,7 +23,7 @@ import sys
from scripts.test.support import run_command, split_wast
from scripts.test.shared import (
ASM2WASM, BIN_DIR, EMCC, MOZJS, NATIVECC, NATIVEXX, NODEJS, S2WASM_EXE,
- WASM_AS, WASM_OPT, WASM_SHELL, WASM_SHELL_EXE,
+ WASM_AS, WASM_OPT, WASM_SHELL, WASM_SHELL_EXE, WASM_DIS,
binary_format_check, delete_from_orbit, fail, fail_with_error,
fail_if_not_identical, fail_if_not_contained, has_vanilla_emcc,
has_vanilla_llvm, minify_check, num_failures, options, tests,
@@ -175,6 +175,20 @@ for t in tests:
minify_check(t)
+print '\n[ checking wasm-dis on provided binaries... ]\n'
+
+for t in tests:
+ if t.endswith('.wasm') and not t.startswith('spec'):
+ print '..', t
+ t = os.path.join(options.binaryen_test, t)
+ cmd = WASM_DIS + [t]
+ actual = run_command(cmd)
+
+ with open(t + '.fromBinary') as f:
+ expected = f.read()
+ if actual != expected:
+ fail(actual, expected)
+
print '\n[ checking wasm-shell spec testcases... ]\n'
if len(requested) == 0:
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp
index b8933147f..c618f9d14 100644
--- a/src/binaryen-c.cpp
+++ b/src/binaryen-c.cpp
@@ -808,6 +808,7 @@ void BinaryenSetMemory(BinaryenModuleRef module, BinaryenIndex initial, Binaryen
auto* wasm = (Module*)module;
wasm->memory.initial = initial;
wasm->memory.max = maximum;
+ wasm->memory.exists = true;
if (exportName) {
auto memoryExport = make_unique<Export>();
memoryExport->name = exportName;
@@ -1012,17 +1013,17 @@ void BinaryenSetAPITracing(int on) {
tracing = on;
if (tracing) {
- std::cout << "// beginning a Binaryen API trace\n";
- std::cout << "#include <math.h>\n";
- std::cout << "#include <map>\n";
- std::cout << "#include \"src/binaryen-c.h\"\n";
- std::cout << "int main() {\n";
- std::cout << " std::map<size_t, BinaryenFunctionTypeRef> functionTypes;\n";
- std::cout << " std::map<size_t, BinaryenExpressionRef> expressions;\n";
- std::cout << " std::map<size_t, BinaryenFunctionRef> functions;\n";
- std::cout << " std::map<size_t, RelooperBlockRef> relooperBlocks;\n";
- std::cout << " BinaryenModuleRef the_module = NULL;\n";
- std::cout << " RelooperRef the_relooper = NULL;\n";
+ std::cout << "// beginning a Binaryen API trace\n"
+ "#include <math.h>\n"
+ "#include <map>\n"
+ "#include \"src/binaryen-c.h\"\n"
+ "int main() {\n"
+ " std::map<size_t, BinaryenFunctionTypeRef> functionTypes;\n"
+ " std::map<size_t, BinaryenExpressionRef> expressions;\n"
+ " std::map<size_t, BinaryenFunctionRef> functions;\n"
+ " std::map<size_t, RelooperBlockRef> relooperBlocks;\n"
+ " BinaryenModuleRef the_module = NULL;\n"
+ " RelooperRef the_relooper = NULL;\n";
} else {
std::cout << " return 0;\n";
std::cout << "}\n";
diff --git a/src/passes/PrintCallGraph.cpp b/src/passes/PrintCallGraph.cpp
index 233ae3a0c..d1bfbf04a 100644
--- a/src/passes/PrintCallGraph.cpp
+++ b/src/passes/PrintCallGraph.cpp
@@ -30,18 +30,18 @@ namespace wasm {
struct PrintCallGraph : public Pass {
void run(PassRunner* runner, Module* module) override {
std::ostream &o = std::cout;
- o << "digraph call {\n";
- o << " rankdir = LR;\n";
- o << " subgraph cluster_key {\n";
- o << " node [shape=box, fontname=courier, fontsize=10];\n";
- o << " edge [fontname=courier, fontsize=10];\n";
- o << " label = \"Key\";\n";
- o << " \"Import\" [style=\"filled\", fillcolor=\"turquoise\"];\n";
- o << " \"Export\" [style=\"filled\", fillcolor=\"gray\"];\n";
- o << " \"Indirect Target\" [style=\"filled, rounded\", fillcolor=\"white\"];\n";
- o << " \"A\" -> \"B\" [style=\"filled, rounded\", label = \"Direct Call\"];\n";
- o << " }\n\n";
- o << " node [shape=box, fontname=courier, fontsize=10];\n";
+ o << "digraph call {\n"
+ " rankdir = LR;\n"
+ " subgraph cluster_key {\n"
+ " node [shape=box, fontname=courier, fontsize=10];\n"
+ " edge [fontname=courier, fontsize=10];\n"
+ " label = \"Key\";\n"
+ " \"Import\" [style=\"filled\", fillcolor=\"turquoise\"];\n"
+ " \"Export\" [style=\"filled\", fillcolor=\"gray\"];\n"
+ " \"Indirect Target\" [style=\"filled, rounded\", fillcolor=\"white\"];\n"
+ " \"A\" -> \"B\" [style=\"filled, rounded\", label = \"Direct Call\"];\n"
+ " }\n\n"
+ " node [shape=box, fontname=courier, fontsize=10];\n";
// All Functions
for (auto& func : module->functions) {
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 1edd3fa12..e681f30e8 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -690,6 +690,7 @@ public:
void readFunctions();
std::map<Export*, Index> exportIndexes;
+ std::vector<Export*> exportOrder;
void readExports();
Expression* readExpression();
@@ -704,6 +705,7 @@ public:
void processExpressions();
Expression* popExpression();
+ Expression* popNonVoidExpression();
std::map<Index, Name> mappedGlobals; // index of the Global => name. first imported globals, then internal globals
@@ -736,7 +738,7 @@ public:
auto num = type->params.size();
call->operands.resize(num);
for (size_t i = 0; i < num; i++) {
- call->operands[num - i - 1] = popExpression();
+ call->operands[num - i - 1] = popNonVoidExpression();
}
call->type = type->result;
}
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index ebbc5a8ee..e6b33dbb0 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -1271,6 +1271,7 @@ void WasmBinaryBuilder::readExports() {
curr->kind = (ExternalKind)getU32LEB();
auto index = getU32LEB();
exportIndexes[curr] = index;
+ exportOrder.push_back(curr);
}
}
@@ -1319,6 +1320,32 @@ Expression* WasmBinaryBuilder::popExpression() {
return ret;
}
+Expression* WasmBinaryBuilder::popNonVoidExpression() {
+ auto* ret = popExpression();
+ if (ret->type != none) return ret;
+ // we found a void, so this is stacky code that we must handle carefully
+ Builder builder(wasm);
+ // add elements until we find a non-void
+ std::vector<Expression*> expressions;
+ expressions.push_back(ret);
+ while (1) {
+ auto* curr = popExpression();
+ expressions.push_back(curr);
+ if (curr->type != none) break;
+ }
+ auto* block = builder.makeBlock();
+ while (!expressions.empty()) {
+ block->list.push_back(expressions.back());
+ expressions.pop_back();
+ }
+ auto type = block->list[0]->type;
+ auto local = builder.addVar(currFunction, type);
+ block->list[0] = builder.makeSetLocal(local, block->list[0]);
+ block->list.push_back(builder.makeGetLocal(local, type));
+ block->finalize();
+ return block;
+}
+
Name WasmBinaryBuilder::getGlobalName(Index index) {
if (!mappedGlobals.size()) {
// Create name => index mapping.
@@ -1346,16 +1373,16 @@ void WasmBinaryBuilder::processFunctions() {
wasm.start = getFunctionIndexName(startIndex);
}
- for (auto& iter : exportIndexes) {
- Export* curr = iter.first;
+ for (auto* curr : exportOrder) {
+ auto index = exportIndexes[curr];
switch (curr->kind) {
case ExternalKind::Function: {
- curr->value = getFunctionIndexName(iter.second);
+ curr->value = getFunctionIndexName(index);
break;
}
case ExternalKind::Table: curr->value = Name::fromInt(0); break;
case ExternalKind::Memory: curr->value = Name::fromInt(0); break;
- case ExternalKind::Global: curr->value = getGlobalName(iter.second); break;
+ case ExternalKind::Global: curr->value = getGlobalName(index); break;
default: WASM_UNREACHABLE();
}
wasm.addExport(curr);
@@ -1562,7 +1589,7 @@ Expression* WasmBinaryBuilder::getBlock(WasmType type) {
void WasmBinaryBuilder::visitIf(If *curr) {
if (debug) std::cerr << "zz node: If" << std::endl;
curr->type = getWasmType();
- curr->condition = popExpression();
+ curr->condition = popNonVoidExpression();
curr->ifTrue = getBlock(curr->type);
if (lastSeparator == BinaryConsts::Else) {
curr->ifFalse = getBlock(curr->type);
@@ -1592,14 +1619,14 @@ void WasmBinaryBuilder::visitBreak(Break *curr, uint8_t code) {
if (debug) std::cerr << "zz node: Break, code "<< int32_t(code) << std::endl;
BreakTarget target = getBreakTarget(getU32LEB());
curr->name = target.name;
- if (code == BinaryConsts::BrIf) curr->condition = popExpression();
- if (target.arity) curr->value = popExpression();
+ if (code == BinaryConsts::BrIf) curr->condition = popNonVoidExpression();
+ if (target.arity) curr->value = popNonVoidExpression();
curr->finalize();
}
void WasmBinaryBuilder::visitSwitch(Switch *curr) {
if (debug) std::cerr << "zz node: Switch" << std::endl;
- curr->condition = popExpression();
+ curr->condition = popNonVoidExpression();
auto numTargets = getU32LEB();
if (debug) std::cerr << "targets: "<< numTargets<<std::endl;
@@ -1609,7 +1636,7 @@ void WasmBinaryBuilder::visitSwitch(Switch *curr) {
auto defaultTarget = getBreakTarget(getU32LEB());
curr->default_ = defaultTarget.name;
if (debug) std::cerr << "default: "<< curr->default_<<std::endl;
- if (defaultTarget.arity) curr->value = popExpression();
+ if (defaultTarget.arity) curr->value = popNonVoidExpression();
}
Expression* WasmBinaryBuilder::visitCall() {
@@ -1646,9 +1673,9 @@ void WasmBinaryBuilder::visitCallIndirect(CallIndirect *curr) {
curr->fullType = fullType->name;
auto num = fullType->params.size();
curr->operands.resize(num);
- curr->target = popExpression();
+ curr->target = popNonVoidExpression();
for (size_t i = 0; i < num; i++) {
- curr->operands[num - i - 1] = popExpression();
+ curr->operands[num - i - 1] = popNonVoidExpression();
}
curr->type = fullType->result;
}
@@ -1664,7 +1691,7 @@ void WasmBinaryBuilder::visitSetLocal(SetLocal *curr, uint8_t code) {
if (debug) std::cerr << "zz node: Set|TeeLocal" << std::endl;
curr->index = getU32LEB();
assert(curr->index < currFunction->getNumLocals());
- curr->value = popExpression();
+ curr->value = popNonVoidExpression();
curr->type = curr->value->type;
curr->setTee(code == BinaryConsts::TeeLocal);
}
@@ -1690,7 +1717,7 @@ void WasmBinaryBuilder::visitSetGlobal(SetGlobal *curr) {
if (debug) std::cerr << "zz node: SetGlobal" << std::endl;
auto index = getU32LEB();
curr->name = getGlobalName(index);
- curr->value = popExpression();
+ curr->value = popNonVoidExpression();
}
void WasmBinaryBuilder::readMemoryAccess(Address& alignment, size_t bytes, Address& offset) {
@@ -1719,7 +1746,7 @@ bool WasmBinaryBuilder::maybeVisitLoad(Expression*& out, uint8_t code) {
}
if (debug) std::cerr << "zz node: Load" << std::endl;
readMemoryAccess(curr->align, curr->bytes, curr->offset);
- curr->ptr = popExpression();
+ curr->ptr = popNonVoidExpression();
out = curr;
return true;
}
@@ -1740,8 +1767,8 @@ bool WasmBinaryBuilder::maybeVisitStore(Expression*& out, uint8_t code) {
}
if (debug) std::cerr << "zz node: Store" << std::endl;
readMemoryAccess(curr->align, curr->bytes, curr->offset);
- curr->value = popExpression();
- curr->ptr = popExpression();
+ curr->value = popNonVoidExpression();
+ curr->ptr = popNonVoidExpression();
curr->finalize();
out = curr;
return true;
@@ -1821,7 +1848,7 @@ bool WasmBinaryBuilder::maybeVisitUnary(Expression*& out, uint8_t code) {
default: return false;
}
if (debug) std::cerr << "zz node: Unary" << std::endl;
- curr->value = popExpression();
+ curr->value = popNonVoidExpression();
out = curr;
return true;
}
@@ -1878,8 +1905,8 @@ bool WasmBinaryBuilder::maybeVisitBinary(Expression*& out, uint8_t code) {
default: return false;
}
if (debug) std::cerr << "zz node: Binary" << std::endl;
- curr->right = popExpression();
- curr->left = popExpression();
+ curr->right = popNonVoidExpression();
+ curr->left = popNonVoidExpression();
curr->finalize();
out = curr;
return true;
@@ -1890,16 +1917,16 @@ bool WasmBinaryBuilder::maybeVisitBinary(Expression*& out, uint8_t code) {
void WasmBinaryBuilder::visitSelect(Select *curr) {
if (debug) std::cerr << "zz node: Select" << std::endl;
- curr->condition = popExpression();
- curr->ifFalse = popExpression();
- curr->ifTrue = popExpression();
+ curr->condition = popNonVoidExpression();
+ curr->ifFalse = popNonVoidExpression();
+ curr->ifTrue = popNonVoidExpression();
curr->finalize();
}
void WasmBinaryBuilder::visitReturn(Return *curr) {
if (debug) std::cerr << "zz node: Return" << std::endl;
if (currFunction->result != none) {
- curr->value = popExpression();
+ curr->value = popNonVoidExpression();
}
}
@@ -1916,7 +1943,7 @@ bool WasmBinaryBuilder::maybeVisitHost(Expression*& out, uint8_t code) {
curr = allocator.alloc<Host>();
curr->op = GrowMemory;
curr->operands.resize(1);
- curr->operands[0] = popExpression();
+ curr->operands[0] = popNonVoidExpression();
break;
}
default: return false;
@@ -1939,7 +1966,7 @@ void WasmBinaryBuilder::visitUnreachable(Unreachable *curr) {
void WasmBinaryBuilder::visitDrop(Drop *curr) {
if (debug) std::cerr << "zz node: Drop" << std::endl;
- curr->value = popExpression();
+ curr->value = popNonVoidExpression();
}
} // namespace wasm
diff --git a/test/example/c-api-unused-mem.cpp b/test/example/c-api-unused-mem.cpp
new file mode 100644
index 000000000..69bee351f
--- /dev/null
+++ b/test/example/c-api-unused-mem.cpp
@@ -0,0 +1,93 @@
+// beginning a Binaryen API trace
+#include <stdio.h>
+#include <math.h>
+#include <map>
+#include "binaryen-c.h"
+int main() {
+ std::map<size_t, BinaryenFunctionTypeRef> functionTypes;
+ std::map<size_t, BinaryenExpressionRef> expressions;
+ std::map<size_t, BinaryenFunctionRef> functions;
+ std::map<size_t, RelooperBlockRef> relooperBlocks;
+ BinaryenModuleRef the_module = NULL;
+ RelooperRef the_relooper = NULL;
+ the_module = BinaryenModuleCreate();
+ expressions[size_t(NULL)] = BinaryenExpressionRef(NULL);
+ BinaryenModuleAutoDrop(the_module);
+ {
+ const char* segments[] = { 0 };
+ BinaryenExpressionRef segmentOffsets[] = { 0 };
+ BinaryenIndex segmentSizes[] = { 0 };
+ BinaryenSetMemory(the_module, 256, 256, "memory", segments, segmentOffsets, segmentSizes, 0);
+ }
+ the_relooper = RelooperCreate();
+ {
+ BinaryenExpressionRef children[] = { 0 };
+ expressions[1] = BinaryenBlock(the_module, "bb0", children, 0);
+ }
+ relooperBlocks[0] = RelooperAddBlock(the_relooper, expressions[1]);
+ expressions[2] = BinaryenGetLocal(the_module, 0, 1);
+ expressions[3] = BinaryenConst(the_module, BinaryenLiteralInt32(0));
+ expressions[4] = BinaryenStore(the_module, 4, 0, 0, expressions[3], expressions[2], 1);
+ expressions[5] = BinaryenReturn(the_module, expressions[0]);
+ {
+ BinaryenExpressionRef children[] = { expressions[4], expressions[5] };
+ expressions[6] = BinaryenBlock(the_module, "bb1", children, 2);
+ }
+ relooperBlocks[1] = RelooperAddBlock(the_relooper, expressions[6]);
+ RelooperAddBranch(relooperBlocks[0], relooperBlocks[1], expressions[0], expressions[0]);
+ {
+ BinaryenIndex paramTypes[] = { 0 };
+ functionTypes[0] = BinaryenAddFunctionType(the_module, "rustfn-0-3", 0, paramTypes, 0);
+ }
+ expressions[7] = BinaryenConst(the_module, BinaryenLiteralInt32(0));
+ expressions[8] = BinaryenLoad(the_module, 4, 0, 0, 0, 1, expressions[7]);
+ expressions[9] = BinaryenSetLocal(the_module, 0, expressions[8]);
+ relooperBlocks[2] = RelooperAddBlock(the_relooper, expressions[9]);
+ RelooperAddBranch(relooperBlocks[2], relooperBlocks[0], expressions[0], expressions[0]);
+ expressions[10] = RelooperRenderAndDispose(the_relooper, relooperBlocks[2], 1, the_module);
+ {
+ BinaryenType varTypes[] = { 1, 1, 2 };
+ functions[0] = BinaryenAddFunction(the_module, "main", functionTypes[0], varTypes, 3, expressions[10]);
+ }
+ BinaryenAddExport(the_module, "main", "main");
+ {
+ BinaryenIndex paramTypes[] = { 0 };
+ functionTypes[1] = BinaryenAddFunctionType(the_module, "__wasm_start", 0, paramTypes, 0);
+ }
+ {
+ const char* segments[] = { 0 };
+ BinaryenExpressionRef segmentOffsets[] = { 0 };
+ BinaryenIndex segmentSizes[] = { 0 };
+ BinaryenSetMemory(the_module, 1024, 1024, NULL, segments, segmentOffsets, segmentSizes, 0);
+ }
+ expressions[11] = BinaryenConst(the_module, BinaryenLiteralInt32(65535));
+ expressions[12] = BinaryenConst(the_module, BinaryenLiteralInt32(0));
+ expressions[13] = BinaryenStore(the_module, 4, 0, 0, expressions[12], expressions[11], 1);
+ {
+ BinaryenExpressionRef operands[] = { 0 };
+ expressions[14] = BinaryenCall(the_module, "main", operands, 0, 0);
+ }
+ {
+ BinaryenExpressionRef children[] = { expressions[13], expressions[14] };
+ expressions[15] = BinaryenBlock(the_module, NULL, children, 2);
+ }
+ BinaryenAddExport(the_module, "__wasm_start", "rust_entry");
+ {
+ BinaryenType varTypes[] = { 0 };
+ functions[1] = BinaryenAddFunction(the_module, "__wasm_start", functionTypes[1], varTypes, 0, expressions[15]);
+ }
+ BinaryenModuleValidate(the_module);
+ BinaryenModulePrint(the_module);
+ // check that binary read-write works
+ {
+ char buffer[1024];
+ size_t size = BinaryenModuleWrite(the_module, buffer, 1024);
+ printf("%d\n", size);
+ BinaryenModuleRef copy = BinaryenModuleRead(buffer, size);
+ BinaryenModulePrint(copy);
+ BinaryenModuleDispose(copy);
+ }
+ BinaryenModuleDispose(the_module);
+ return 0;
+}
+
diff --git a/test/example/c-api-unused-mem.txt b/test/example/c-api-unused-mem.txt
new file mode 100644
index 000000000..cae196ea7
--- /dev/null
+++ b/test/example/c-api-unused-mem.txt
@@ -0,0 +1,101 @@
+(module
+ (type $rustfn-0-3 (func))
+ (type $__wasm_start (func))
+ (memory $0 1024 1024)
+ (export "memory" (memory $0))
+ (export "main" (func $main))
+ (export "rust_entry" (func $__wasm_start))
+ (func $main (type $rustfn-0-3)
+ (local $0 i32)
+ (local $1 i32)
+ (local $2 i64)
+ (block $block$1$break
+ (set_local $0
+ (i32.load
+ (i32.const 0)
+ )
+ )
+ (block
+ (br $block$1$break)
+ )
+ )
+ (block
+ (block $block$2$break
+ (block $bb0
+ )
+ (block
+ (br $block$2$break)
+ )
+ )
+ (block
+ (block $bb1
+ (i32.store
+ (i32.const 0)
+ (get_local $0)
+ )
+ (return)
+ )
+ )
+ )
+ )
+ (func $__wasm_start (type $__wasm_start)
+ (i32.store
+ (i32.const 0)
+ (i32.const 65535)
+ )
+ (call $main)
+ )
+)
+195
+(module
+ (type $0 (func))
+ (type $1 (func))
+ (memory $0 1024 1024)
+ (export "memory" (memory $0))
+ (export "main" (func $main))
+ (export "rust_entry" (func $__wasm_start))
+ (func $main (type $0)
+ (local $var$0 i32)
+ (local $var$1 i32)
+ (local $var$2 i64)
+ (block $label$0
+ (block $label$1
+ (set_local $var$0
+ (i32.load
+ (i32.const 0)
+ )
+ )
+ (block $label$2
+ (br $label$1)
+ )
+ )
+ (block $label$3
+ (block $label$4
+ (block $label$5
+ )
+ (block $label$6
+ (br $label$4)
+ )
+ )
+ (block $label$7
+ (block $label$8
+ (i32.store
+ (i32.const 0)
+ (get_local $var$0)
+ )
+ (return)
+ )
+ )
+ )
+ )
+ )
+ (func $__wasm_start (type $1)
+ (block $label$0
+ (i32.store
+ (i32.const 0)
+ (i32.const 65535)
+ )
+ (call $main)
+ )
+ )
+)
diff --git a/test/stacky.wasm b/test/stacky.wasm
new file mode 100644
index 000000000..27b86992a
--- /dev/null
+++ b/test/stacky.wasm
Binary files differ
diff --git a/test/stacky.wasm.fromBinary b/test/stacky.wasm.fromBinary
new file mode 100644
index 000000000..13250bd39
--- /dev/null
+++ b/test/stacky.wasm.fromBinary
@@ -0,0 +1,21 @@
+(module
+ (type $0 (func (param i32 i32) (result i32)))
+ (memory $0 256 256)
+ (export "add" (func $0))
+ (func $0 (type $0) (param $var$0 i32) (param $var$1 i32) (result i32)
+ (local $2 i32)
+ (i32.add
+ (block i32
+ (set_local $2
+ (get_local $var$0)
+ )
+ (set_local $var$0
+ (i32.const 100)
+ )
+ (get_local $2)
+ )
+ (get_local $var$1)
+ )
+ )
+)
+