summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md5
-rw-r--r--src/wasm-binary.h6
-rw-r--r--src/wasm/wasm-binary.cpp68
-rw-r--r--test/example/c-api-unused-mem.txt11
-rw-r--r--test/fib-dbg.wasm.fromBinary5
-rw-r--r--test/min.wast.fromBinary1
-rw-r--r--test/min.wast.fromBinary.noDebugInfo1
-rw-r--r--test/passes/flatten-control-flow.bin.txt46
-rw-r--r--test/polymorphic_stack.wast15
-rw-r--r--test/polymorphic_stack.wast.from-wast15
-rw-r--r--test/polymorphic_stack.wast.fromBinary104
-rw-r--r--test/polymorphic_stack.wast.fromBinary.noDebugInfo106
-rw-r--r--test/unit.wast.fromBinary82
-rw-r--r--test/unit.wast.fromBinary.noDebugInfo82
-rw-r--r--test/unreachable-code.wast85
-rw-r--r--test/unreachable-code.wast.from-wast94
-rw-r--r--test/unreachable-code.wast.fromBinary122
-rw-r--r--test/unreachable-code.wast.fromBinary.noDebugInfo122
-rw-r--r--test/unreachable-pops.wasmbin0 -> 30 bytes
-rw-r--r--test/unreachable-pops.wasm.fromBinary10
-rw-r--r--test/untaken-br_if.wast.fromBinary6
-rw-r--r--test/untaken-br_if.wast.fromBinary.noDebugInfo6
22 files changed, 569 insertions, 423 deletions
diff --git a/README.md b/README.md
index c8c22e320..c67dc0179 100644
--- a/README.md
+++ b/README.md
@@ -36,7 +36,10 @@ The differences between Binaryen IR and WebAssembly are:
* Binaryen IR [is an AST](https://github.com/WebAssembly/binaryen/issues/663), for convenience of optimization. This differs from the WebAssembly binary format which is a stack machine.
* WebAssembly limits block/if/loop types to none and the concrete value types (i32, i64, f32, f64). Binaryen IR has an unreachable type, and it allows block/if/loop to take it, allowing [local transforms that don't need to know the global context](https://github.com/WebAssembly/binaryen/issues/903).
- * Binaryen IR's text format requires the names of blocks and loops to be unique. This differs from the WebAssembly s-expression format which allows duplicate names (and depends on scoping to disambiguate).
+ * Binaryen IR requires the names of blocks and loops to be unique. (Reading wast files with duplicate names is supported, by disambiguating them).
+ * Binaryen IR has only one node with a list: blocks. WebAssembly on the other hand allows lists in loops and ifs (Binaryen would represent those with additional blocks as necessary). The motivation here is that many passes need special code for iterating on lists, so having a single IR node with a list simplifies things.
+ * Binaryen's text format allows only s-expressions. WebAssembly's official text format is a stack machine with s-expression extensions. Binaryen can't read stack machine code, but it can read a wast if it contains only s-expressions.
+ * Binaryen ignores unreachable code when reading WebAssembly binaries. That means that if you read a wasm file with unreachable code, that code will be discarded as if it were optimized out (often this is what you want anyhow, and optimized programs have no unreachable code anyway, but if you write an unoptimized file and then read it, it may look different). The reason for this behavior is that unreachable code in WebAssembly has corner cases that are tricky to handle in Binaryen IR (it can be very unstructured, and Binaryen IR is more structured than WebAssembly as noted earlier). Note that Binaryen does support unreachable code in wast text files, since as we saw Binaryen only supports s-expressions there, which are structured.
As a result, you might notice that round-trip conversions (wasm => Binaryen IR => wasm) change code a little in some corner cases.
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 55a97743f..9724bc93d 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -855,9 +855,15 @@ public:
std::vector<Expression*> expressionStack;
+ bool definitelyUnreachable; // set when we know code is definitely unreachable. this helps parse
+ // stacky wasm code, which can be unsuitable for our IR when unreachable
+
BinaryConsts::ASTNodes lastSeparator = BinaryConsts::End;
+ // process a block-type scope, until an end or else marker, or the end of the function
void processExpressions();
+ void skipUnreachableCode();
+
Expression* popExpression();
Expression* popNonVoidExpression();
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index eb41ae8a7..b114b81fb 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -1807,12 +1807,61 @@ void WasmBinaryBuilder::readGlobals() {
}
}
-void WasmBinaryBuilder::processExpressions() { // until an end or else marker, or the end of the function
+void WasmBinaryBuilder::processExpressions() {
+ if (debug) std::cerr << "== processExpressions" << std::endl;
+ definitelyUnreachable = false;
while (1) {
Expression* curr;
auto ret = readExpression(curr);
if (!curr) {
lastSeparator = ret;
+ if (debug) std::cerr << "== processExpressions finished" << std::endl;
+ return;
+ }
+ expressionStack.push_back(curr);
+ if (curr->type == unreachable) {
+ // once we see something unreachable, we don't want to add anything else
+ // to the stack, as it could be stacky code that is non-representable in
+ // our AST. but we do need to skip it
+ // if there is nothing else here, just stop. otherwise, go into unreachable
+ // mode. peek to see what to do
+ if (pos == endOfFunction) {
+ throw ParseException("Reached function end without seeing End opcode");
+ }
+ auto peek = input[pos];
+ if (peek == BinaryConsts::End || peek == BinaryConsts::Else) {
+ if (debug) std::cerr << "== processExpressions finished with unreachable" << std::endl;
+ lastSeparator = BinaryConsts::ASTNodes(peek);
+ pos++;
+ return;
+ } else {
+ skipUnreachableCode();
+ return;
+ }
+ }
+ }
+}
+
+void WasmBinaryBuilder::skipUnreachableCode() {
+ if (debug) std::cerr << "== skipUnreachableCode" << std::endl;
+ // preserve the stack, and restore it. it contains the instruction that made us
+ // unreachable, and we can ignore anything after it. things after it may pop,
+ // we want to undo that
+ auto savedStack = expressionStack;
+ // clear the stack. nothing should be popped from there anyhow, just stuff
+ // can be pushed and then popped. Popping past the top of the stack will
+ // result in uneachables being returned
+ expressionStack.clear();
+ while (1) {
+ // set the definitelyUnreachable flag each time, as sub-blocks may set and unset it
+ definitelyUnreachable = true;
+ Expression* curr;
+ auto ret = readExpression(curr);
+ if (!curr) {
+ if (debug) std::cerr << "== skipUnreachableCode finished" << std::endl;
+ lastSeparator = ret;
+ definitelyUnreachable = false;
+ expressionStack = savedStack;
return;
}
expressionStack.push_back(curr);
@@ -1820,15 +1869,19 @@ void WasmBinaryBuilder::processExpressions() { // until an end or else marker, o
}
Expression* WasmBinaryBuilder::popExpression() {
+ if (debug) std::cerr << "== popExpression" << std::endl;
if (expressionStack.empty()) {
- throw ParseException("attempted pop from empty stack at " + std::to_string(pos));
+ if (definitelyUnreachable) {
+ // in unreachable code, trying to pop past the polymorphic stack
+ // area results in receiving unreachables
+ if (debug) std::cerr << "== popping unreachable from polymorphic stack" << std::endl;
+ return allocator.alloc<Unreachable>();
+ }
+ throw ParseException("attempted pop from empty stack / beyond block start boundary at " + std::to_string(pos));
}
+ // the stack is not empty, and we would not be going out of the current block
auto ret = expressionStack.back();
- // to simulate the wasm polymorphic stack mode, leave a final
- // unreachable, don't empty the stack in that case
- if (!(expressionStack.size() == 1 && ret->type == unreachable)) {
- expressionStack.pop_back();
- }
+ expressionStack.pop_back();
return ret;
}
@@ -2222,7 +2275,6 @@ void WasmBinaryBuilder::visitBreak(Break *curr, uint8_t code) {
void WasmBinaryBuilder::visitSwitch(Switch *curr) {
if (debug) std::cerr << "zz node: Switch" << std::endl;
curr->condition = popNonVoidExpression();
-
auto numTargets = getU32LEB();
if (debug) std::cerr << "targets: "<< numTargets<<std::endl;
for (size_t i = 0; i < numTargets; i++) {
diff --git a/test/example/c-api-unused-mem.txt b/test/example/c-api-unused-mem.txt
index c6ac48235..60bdbe51d 100644
--- a/test/example/c-api-unused-mem.txt
+++ b/test/example/c-api-unused-mem.txt
@@ -67,9 +67,7 @@
)
(block $label$2
(br $label$1)
- (unreachable)
)
- (unreachable)
)
(block $label$3
(block $label$4
@@ -77,9 +75,7 @@
)
(block $label$6
(br $label$4)
- (unreachable)
)
- (unreachable)
)
(block $label$7
(block $label$8
@@ -88,18 +84,11 @@
(get_local $var$0)
)
(return)
- (unreachable)
)
(unreachable)
- (unreachable)
)
- (unreachable)
- (unreachable)
)
- (unreachable)
- (unreachable)
)
- (unreachable)
)
(func $__wasm_start (type $1)
(block $label$0
diff --git a/test/fib-dbg.wasm.fromBinary b/test/fib-dbg.wasm.fromBinary
index 3f940fa8a..8f7193f8a 100644
--- a/test/fib-dbg.wasm.fromBinary
+++ b/test/fib-dbg.wasm.fromBinary
@@ -72,9 +72,7 @@
(return
(get_local $var$1)
)
- (unreachable)
)
- (unreachable)
)
(func $stackSave (type $2) (result i32)
(return
@@ -214,10 +212,7 @@
(return
(get_local $var$4)
)
- (unreachable)
- (unreachable)
)
- (unreachable)
)
(func $runPostSets (type $4)
(local $var$0 i32)
diff --git a/test/min.wast.fromBinary b/test/min.wast.fromBinary
index b39388c46..f25c51044 100644
--- a/test/min.wast.fromBinary
+++ b/test/min.wast.fromBinary
@@ -46,7 +46,6 @@
(br $label$0
(i32.const 2)
)
- (i32.const 0)
)
)
(func $f1 (type $3) (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (result i32)
diff --git a/test/min.wast.fromBinary.noDebugInfo b/test/min.wast.fromBinary.noDebugInfo
index d6ad4be85..b7407584e 100644
--- a/test/min.wast.fromBinary.noDebugInfo
+++ b/test/min.wast.fromBinary.noDebugInfo
@@ -46,7 +46,6 @@
(br $label$0
(i32.const 2)
)
- (i32.const 0)
)
)
(func $3 (type $3) (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (result i32)
diff --git a/test/passes/flatten-control-flow.bin.txt b/test/passes/flatten-control-flow.bin.txt
index 9b33f976e..5de52bb3c 100644
--- a/test/passes/flatten-control-flow.bin.txt
+++ b/test/passes/flatten-control-flow.bin.txt
@@ -119,51 +119,7 @@
(local $var$8 f64)
(block $label$0
(nop)
- (block
- (block
- (unreachable)
- )
- )
- (drop
- (f32.neg
- (get_local $var$1)
- )
- )
- (drop
- (f64.neg
- (get_local $var$2)
- )
- )
- (drop
- (i32.eqz
- (get_local $var$3)
- )
- )
- (drop
- (i32.eqz
- (get_local $var$4)
- )
- )
- (drop
- (f32.neg
- (get_local $var$7)
- )
- )
- (drop
- (i64.eqz
- (get_local $var$5)
- )
- )
- (drop
- (i64.eqz
- (get_local $var$6)
- )
- )
- (drop
- (f64.neg
- (get_local $var$8)
- )
- )
+ (unreachable)
)
)
(func $9 (type $9) (param $var$0 i64) (param $var$1 f32) (param $var$2 f64) (param $var$3 i32) (param $var$4 i32) (result f64)
diff --git a/test/polymorphic_stack.wast b/test/polymorphic_stack.wast
index b618fbb6c..1b2459148 100644
--- a/test/polymorphic_stack.wast
+++ b/test/polymorphic_stack.wast
@@ -86,6 +86,21 @@
)
)
)
+ (func $unreachable-in-block-but-code-before (param $0 i32) (result i32)
+ (if
+ (get_local $0)
+ (return
+ (i32.const 127)
+ )
+ )
+ (block $label$0 (result i32)
+ (br_if $label$0
+ (return
+ (i32.const -32)
+ )
+ )
+ )
+ )
(func $br_table_unreachable_to_also_unreachable (result i32)
(block $a (result i32)
(block $b
diff --git a/test/polymorphic_stack.wast.from-wast b/test/polymorphic_stack.wast.from-wast
index c20f9218d..82f88f4af 100644
--- a/test/polymorphic_stack.wast.from-wast
+++ b/test/polymorphic_stack.wast.from-wast
@@ -90,6 +90,21 @@
)
)
)
+ (func $unreachable-in-block-but-code-before (type $FUNCSIG$ii) (param $0 i32) (result i32)
+ (if
+ (get_local $0)
+ (return
+ (i32.const 127)
+ )
+ )
+ (block $label$0 (result i32)
+ (br_if $label$0
+ (return
+ (i32.const -32)
+ )
+ )
+ )
+ )
(func $br_table_unreachable_to_also_unreachable (type $1) (result i32)
(block $a (result i32)
(block $b
diff --git a/test/polymorphic_stack.wast.fromBinary b/test/polymorphic_stack.wast.fromBinary
index b139c9c06..68bb7ecf7 100644
--- a/test/polymorphic_stack.wast.fromBinary
+++ b/test/polymorphic_stack.wast.fromBinary
@@ -8,81 +8,18 @@
(func $break-and-binary (type $1) (result i32)
(block $label$0 (result i32)
(unreachable)
- (i32.trunc_u/f64
- (unreachable)
- )
- (unreachable)
- (br_if $label$0
- (i32.trunc_u/f64
- (unreachable)
- )
- (unreachable)
- )
- (f32.add
- (unreachable)
- (f32.const 1)
- )
- (unreachable)
)
)
(func $call-and-unary (type $0) (param $var$0 i32) (result i32)
(block $label$0 (result i32)
(unreachable)
- (call $call-and-unary
- (unreachable)
- )
- (i64.eqz
- (unreachable)
- )
- (drop
- (unreachable)
- )
- (i32.eqz
- (unreachable)
- )
- (i64.eqz
- (unreachable)
- )
- (drop
- (unreachable)
- )
- (call_indirect $0
- (unreachable)
- (unreachable)
- )
- (i64.eqz
- (unreachable)
- )
- (drop
- (unreachable)
- )
)
)
(func $tee (type $2) (param $var$0 i32)
(local $var$1 f32)
(block $label$0
(unreachable)
- (tee_local $var$0
- (unreachable)
- )
- (i64.eqz
- (unreachable)
- )
- (drop
- (unreachable)
- )
- (i64.eqz
- (unreachable)
- )
- (tee_local $var$1
- (unreachable)
- )
- (drop
- (unreachable)
- )
- (unreachable)
)
- (unreachable)
)
(func $tee2 (type $3)
(local $var$0 f32)
@@ -90,48 +27,41 @@
(i32.const 259)
(block $label$0
(unreachable)
- (tee_local $var$0
- (unreachable)
- )
- (unreachable)
)
)
)
(func $select (type $3)
(unreachable)
- (select
- (unreachable)
- (i32.const 1)
- (i32.const 2)
- )
- (i64.eqz
- (unreachable)
- )
- (drop
- (unreachable)
- )
)
(func $untaken-break-should-have-value (type $1) (result i32)
(block $label$0 (result i32)
(block $label$1
(unreachable)
- (br_if $label$0
- (unreachable)
- (unreachable)
- )
- (unreachable)
- (unreachable)
)
(unreachable)
)
)
+ (func $unreachable-in-block-but-code-before (type $0) (param $var$0 i32) (result i32)
+ (block $label$0 (result i32)
+ (if
+ (get_local $var$0)
+ (block $label$1
+ (return
+ (i32.const 127)
+ )
+ )
+ )
+ (block $label$2 (result i32)
+ (return
+ (i32.const -32)
+ )
+ )
+ )
+ )
(func $br_table_unreachable_to_also_unreachable (type $1) (result i32)
(block $label$0 (result i32)
(block $label$1
(unreachable)
- (unreachable)
- (unreachable)
- (unreachable)
)
(unreachable)
)
diff --git a/test/polymorphic_stack.wast.fromBinary.noDebugInfo b/test/polymorphic_stack.wast.fromBinary.noDebugInfo
index e707d5046..69292952e 100644
--- a/test/polymorphic_stack.wast.fromBinary.noDebugInfo
+++ b/test/polymorphic_stack.wast.fromBinary.noDebugInfo
@@ -8,81 +8,18 @@
(func $0 (type $1) (result i32)
(block $label$0 (result i32)
(unreachable)
- (i32.trunc_u/f64
- (unreachable)
- )
- (unreachable)
- (br_if $label$0
- (i32.trunc_u/f64
- (unreachable)
- )
- (unreachable)
- )
- (f32.add
- (unreachable)
- (f32.const 1)
- )
- (unreachable)
)
)
(func $1 (type $0) (param $var$0 i32) (result i32)
(block $label$0 (result i32)
(unreachable)
- (call $1
- (unreachable)
- )
- (i64.eqz
- (unreachable)
- )
- (drop
- (unreachable)
- )
- (i32.eqz
- (unreachable)
- )
- (i64.eqz
- (unreachable)
- )
- (drop
- (unreachable)
- )
- (call_indirect $0
- (unreachable)
- (unreachable)
- )
- (i64.eqz
- (unreachable)
- )
- (drop
- (unreachable)
- )
)
)
(func $2 (type $2) (param $var$0 i32)
(local $var$1 f32)
(block $label$0
(unreachable)
- (tee_local $var$0
- (unreachable)
- )
- (i64.eqz
- (unreachable)
- )
- (drop
- (unreachable)
- )
- (i64.eqz
- (unreachable)
- )
- (tee_local $var$1
- (unreachable)
- )
- (drop
- (unreachable)
- )
- (unreachable)
)
- (unreachable)
)
(func $3 (type $3)
(local $var$0 f32)
@@ -90,48 +27,41 @@
(i32.const 259)
(block $label$0
(unreachable)
- (tee_local $var$0
- (unreachable)
- )
- (unreachable)
)
)
)
(func $4 (type $3)
(unreachable)
- (select
- (unreachable)
- (i32.const 1)
- (i32.const 2)
- )
- (i64.eqz
- (unreachable)
- )
- (drop
- (unreachable)
- )
)
(func $5 (type $1) (result i32)
(block $label$0 (result i32)
(block $label$1
(unreachable)
- (br_if $label$0
- (unreachable)
- (unreachable)
- )
- (unreachable)
- (unreachable)
)
(unreachable)
)
)
- (func $6 (type $1) (result i32)
+ (func $6 (type $0) (param $var$0 i32) (result i32)
+ (block $label$0 (result i32)
+ (if
+ (get_local $var$0)
+ (block $label$1
+ (return
+ (i32.const 127)
+ )
+ )
+ )
+ (block $label$2 (result i32)
+ (return
+ (i32.const -32)
+ )
+ )
+ )
+ )
+ (func $7 (type $1) (result i32)
(block $label$0 (result i32)
(block $label$1
(unreachable)
- (unreachable)
- (unreachable)
- (unreachable)
)
(unreachable)
)
diff --git a/test/unit.wast.fromBinary b/test/unit.wast.fromBinary
index 8bb80bcca..817cc3c7a 100644
--- a/test/unit.wast.fromBinary
+++ b/test/unit.wast.fromBinary
@@ -270,22 +270,14 @@
(block $label$15
(loop $label$16
(br $label$15)
- (br $label$16)
)
- (unreachable)
- (br $label$9)
)
)
(block $label$17
(loop $label$18
(br $label$9)
- (br $label$18)
)
- (unreachable)
- (br $label$9)
- (unreachable)
)
- (unreachable)
)
(nop)
)
@@ -474,12 +466,7 @@
(return
(i32.const 2)
)
- (unreachable)
- )
- (f64.abs
- (unreachable)
)
- (unreachable)
)
(func $unreachable-block-toplevel (type $5) (result i32)
(block $label$0
@@ -489,30 +476,21 @@
(return
(i32.const 2)
)
- (unreachable)
)
- (unreachable)
)
(func $unreachable-block0 (type $5) (result i32)
(block $label$0
(return
(i32.const 2)
)
- (unreachable)
)
- (f64.abs
- (unreachable)
- )
- (unreachable)
)
(func $unreachable-block0-toplevel (type $5) (result i32)
(block $label$0
(return
(i32.const 2)
)
- (unreachable)
)
- (unreachable)
)
(func $unreachable-block-with-br (type $5) (result i32)
(block $label$0 (result i32)
@@ -539,10 +517,6 @@
)
)
)
- (f64.abs
- (unreachable)
- )
- (unreachable)
)
(func $unreachable-if-toplevel (type $5) (result i32)
(if
@@ -558,7 +532,6 @@
)
)
)
- (unreachable)
)
(func $unreachable-loop (type $5) (result i32)
(loop $label$0
@@ -567,10 +540,6 @@
(i32.const 1)
)
)
- (f64.abs
- (unreachable)
- )
- (unreachable)
)
(func $unreachable-loop0 (type $5) (result i32)
(loop $label$0
@@ -578,10 +547,6 @@
(i32.const 1)
)
)
- (f64.abs
- (unreachable)
- )
- (unreachable)
)
(func $unreachable-loop-toplevel (type $5) (result i32)
(loop $label$0
@@ -590,7 +555,6 @@
(i32.const 1)
)
)
- (unreachable)
)
(func $unreachable-loop0-toplevel (type $5) (result i32)
(loop $label$0
@@ -598,53 +562,11 @@
(i32.const 1)
)
)
- (unreachable)
)
(func $unreachable-ifs (type $1)
(block $label$0
(unreachable)
- (unreachable)
- (unreachable)
- (unreachable)
- (unreachable)
- (unreachable)
- (unreachable)
- (unreachable)
- (unreachable)
- (unreachable)
- (unreachable)
- (unreachable)
- (if
- (i32.const 1)
- (block $label$1
- (unreachable)
- )
- (block $label$2
- (nop)
- )
- )
- (if
- (i32.const 1)
- (block $label$3
- (nop)
- )
- (block $label$4
- (unreachable)
- )
- )
- (if
- (i32.const 1)
- (block $label$5
- (unreachable)
- )
- (block $label$6
- (unreachable)
- )
- )
- (unreachable)
- (unreachable)
)
- (unreachable)
)
(func $unreachable-if-arm (type $1)
(if
@@ -654,10 +576,6 @@
)
(block $label$1
(unreachable)
- (drop
- (i32.const 1)
- )
- (unreachable)
)
)
)
diff --git a/test/unit.wast.fromBinary.noDebugInfo b/test/unit.wast.fromBinary.noDebugInfo
index 09da9a15b..46b86e86b 100644
--- a/test/unit.wast.fromBinary.noDebugInfo
+++ b/test/unit.wast.fromBinary.noDebugInfo
@@ -270,22 +270,14 @@
(block $label$15
(loop $label$16
(br $label$15)
- (br $label$16)
)
- (unreachable)
- (br $label$9)
)
)
(block $label$17
(loop $label$18
(br $label$9)
- (br $label$18)
)
- (unreachable)
- (br $label$9)
- (unreachable)
)
- (unreachable)
)
(nop)
)
@@ -474,12 +466,7 @@
(return
(i32.const 2)
)
- (unreachable)
- )
- (f64.abs
- (unreachable)
)
- (unreachable)
)
(func $25 (type $5) (result i32)
(block $label$0
@@ -489,30 +476,21 @@
(return
(i32.const 2)
)
- (unreachable)
)
- (unreachable)
)
(func $26 (type $5) (result i32)
(block $label$0
(return
(i32.const 2)
)
- (unreachable)
)
- (f64.abs
- (unreachable)
- )
- (unreachable)
)
(func $27 (type $5) (result i32)
(block $label$0
(return
(i32.const 2)
)
- (unreachable)
)
- (unreachable)
)
(func $28 (type $5) (result i32)
(block $label$0 (result i32)
@@ -539,10 +517,6 @@
)
)
)
- (f64.abs
- (unreachable)
- )
- (unreachable)
)
(func $30 (type $5) (result i32)
(if
@@ -558,7 +532,6 @@
)
)
)
- (unreachable)
)
(func $31 (type $5) (result i32)
(loop $label$0
@@ -567,10 +540,6 @@
(i32.const 1)
)
)
- (f64.abs
- (unreachable)
- )
- (unreachable)
)
(func $32 (type $5) (result i32)
(loop $label$0
@@ -578,10 +547,6 @@
(i32.const 1)
)
)
- (f64.abs
- (unreachable)
- )
- (unreachable)
)
(func $33 (type $5) (result i32)
(loop $label$0
@@ -590,7 +555,6 @@
(i32.const 1)
)
)
- (unreachable)
)
(func $34 (type $5) (result i32)
(loop $label$0
@@ -598,53 +562,11 @@
(i32.const 1)
)
)
- (unreachable)
)
(func $35 (type $1)
(block $label$0
(unreachable)
- (unreachable)
- (unreachable)
- (unreachable)
- (unreachable)
- (unreachable)
- (unreachable)
- (unreachable)
- (unreachable)
- (unreachable)
- (unreachable)
- (unreachable)
- (if
- (i32.const 1)
- (block $label$1
- (unreachable)
- )
- (block $label$2
- (nop)
- )
- )
- (if
- (i32.const 1)
- (block $label$3
- (nop)
- )
- (block $label$4
- (unreachable)
- )
- )
- (if
- (i32.const 1)
- (block $label$5
- (unreachable)
- )
- (block $label$6
- (unreachable)
- )
- )
- (unreachable)
- (unreachable)
)
- (unreachable)
)
(func $36 (type $1)
(if
@@ -654,10 +576,6 @@
)
(block $label$1
(unreachable)
- (drop
- (i32.const 1)
- )
- (unreachable)
)
)
)
diff --git a/test/unreachable-code.wast b/test/unreachable-code.wast
new file mode 100644
index 000000000..f67d10e52
--- /dev/null
+++ b/test/unreachable-code.wast
@@ -0,0 +1,85 @@
+(module
+ (func $a
+ (if (i32.const 1)
+ (unreachable)
+ )
+ )
+ (func $b
+ (if (i32.const 1)
+ (unreachable)
+ (unreachable)
+ )
+ )
+ (func $a-block
+ (block
+ (if (i32.const 1)
+ (unreachable)
+ )
+ )
+ )
+ (func $b-block
+ (block
+ (if (i32.const 1)
+ (unreachable)
+ (unreachable)
+ )
+ )
+ )
+ (func $a-prepost
+ (nop)
+ (if (i32.const 1)
+ (unreachable)
+ )
+ (nop)
+ )
+ (func $b-prepost
+ (nop)
+ (if (i32.const 1)
+ (unreachable)
+ (unreachable)
+ )
+ (nop)
+ )
+ (func $a-block-prepost
+ (nop)
+ (block
+ (if (i32.const 1)
+ (unreachable)
+ )
+ )
+ (nop)
+ )
+ (func $b-block-prepost
+ (nop)
+ (block
+ (if (i32.const 1)
+ (unreachable)
+ (unreachable)
+ )
+ )
+ (nop)
+ )
+ (func $recurse
+ (block $a
+ (nop)
+ (block $b
+ (nop)
+ (br $b)
+ (nop)
+ )
+ (nop)
+ )
+ )
+ (func $recurse-b
+ (block $a
+ (nop)
+ (block $b
+ (nop)
+ (br $a)
+ (nop)
+ )
+ (nop)
+ )
+ )
+)
+
diff --git a/test/unreachable-code.wast.from-wast b/test/unreachable-code.wast.from-wast
new file mode 100644
index 000000000..2196056b3
--- /dev/null
+++ b/test/unreachable-code.wast.from-wast
@@ -0,0 +1,94 @@
+(module
+ (type $0 (func))
+ (memory $0 0)
+ (func $a (type $0)
+ (if
+ (i32.const 1)
+ (unreachable)
+ )
+ )
+ (func $b (type $0)
+ (if
+ (i32.const 1)
+ (unreachable)
+ (unreachable)
+ )
+ )
+ (func $a-block (type $0)
+ (block $block
+ (if
+ (i32.const 1)
+ (unreachable)
+ )
+ )
+ )
+ (func $b-block (type $0)
+ (block $block
+ (if
+ (i32.const 1)
+ (unreachable)
+ (unreachable)
+ )
+ )
+ )
+ (func $a-prepost (type $0)
+ (nop)
+ (if
+ (i32.const 1)
+ (unreachable)
+ )
+ (nop)
+ )
+ (func $b-prepost (type $0)
+ (nop)
+ (if
+ (i32.const 1)
+ (unreachable)
+ (unreachable)
+ )
+ (nop)
+ )
+ (func $a-block-prepost (type $0)
+ (nop)
+ (block $block
+ (if
+ (i32.const 1)
+ (unreachable)
+ )
+ )
+ (nop)
+ )
+ (func $b-block-prepost (type $0)
+ (nop)
+ (block $block
+ (if
+ (i32.const 1)
+ (unreachable)
+ (unreachable)
+ )
+ )
+ (nop)
+ )
+ (func $recurse (type $0)
+ (block $a
+ (nop)
+ (block $b
+ (nop)
+ (br $b)
+ (nop)
+ )
+ (nop)
+ )
+ )
+ (func $recurse-b (type $0)
+ (block $a
+ (nop)
+ (block $b
+ (nop)
+ (br $a)
+ (nop)
+ )
+ (nop)
+ )
+ )
+)
diff --git a/test/unreachable-code.wast.fromBinary b/test/unreachable-code.wast.fromBinary
new file mode 100644
index 000000000..d27da2201
--- /dev/null
+++ b/test/unreachable-code.wast.fromBinary
@@ -0,0 +1,122 @@
+(module
+ (type $0 (func))
+ (memory $0 0)
+ (func $a (type $0)
+ (if
+ (i32.const 1)
+ (block $label$0
+ (unreachable)
+ )
+ )
+ )
+ (func $b (type $0)
+ (if
+ (i32.const 1)
+ (block $label$0
+ (unreachable)
+ )
+ (block $label$1
+ (unreachable)
+ )
+ )
+ )
+ (func $a-block (type $0)
+ (block $label$0
+ (if
+ (i32.const 1)
+ (block $label$1
+ (unreachable)
+ )
+ )
+ )
+ )
+ (func $b-block (type $0)
+ (block $label$0
+ (if
+ (i32.const 1)
+ (block $label$1
+ (unreachable)
+ )
+ (block $label$2
+ (unreachable)
+ )
+ )
+ )
+ )
+ (func $a-prepost (type $0)
+ (block $label$0
+ (nop)
+ (if
+ (i32.const 1)
+ (block $label$1
+ (unreachable)
+ )
+ )
+ (nop)
+ )
+ )
+ (func $b-prepost (type $0)
+ (block $label$0
+ (nop)
+ (if
+ (i32.const 1)
+ (block $label$1
+ (unreachable)
+ )
+ (block $label$2
+ (unreachable)
+ )
+ )
+ )
+ )
+ (func $a-block-prepost (type $0)
+ (block $label$0
+ (nop)
+ (block $label$1
+ (if
+ (i32.const 1)
+ (block $label$2
+ (unreachable)
+ )
+ )
+ )
+ (nop)
+ )
+ )
+ (func $b-block-prepost (type $0)
+ (block $label$0
+ (nop)
+ (block $label$1
+ (if
+ (i32.const 1)
+ (block $label$2
+ (unreachable)
+ )
+ (block $label$3
+ (unreachable)
+ )
+ )
+ )
+ )
+ )
+ (func $recurse (type $0)
+ (block $label$0
+ (nop)
+ (block $label$1
+ (nop)
+ (br $label$1)
+ )
+ (nop)
+ )
+ )
+ (func $recurse-b (type $0)
+ (block $label$0
+ (nop)
+ (block $label$1
+ (nop)
+ (br $label$0)
+ )
+ )
+ )
+)
+
diff --git a/test/unreachable-code.wast.fromBinary.noDebugInfo b/test/unreachable-code.wast.fromBinary.noDebugInfo
new file mode 100644
index 000000000..288a24f4a
--- /dev/null
+++ b/test/unreachable-code.wast.fromBinary.noDebugInfo
@@ -0,0 +1,122 @@
+(module
+ (type $0 (func))
+ (memory $0 0)
+ (func $0 (type $0)
+ (if
+ (i32.const 1)
+ (block $label$0
+ (unreachable)
+ )
+ )
+ )
+ (func $1 (type $0)
+ (if
+ (i32.const 1)
+ (block $label$0
+ (unreachable)
+ )
+ (block $label$1
+ (unreachable)
+ )
+ )
+ )
+ (func $2 (type $0)
+ (block $label$0
+ (if
+ (i32.const 1)
+ (block $label$1
+ (unreachable)
+ )
+ )
+ )
+ )
+ (func $3 (type $0)
+ (block $label$0
+ (if
+ (i32.const 1)
+ (block $label$1
+ (unreachable)
+ )
+ (block $label$2
+ (unreachable)
+ )
+ )
+ )
+ )
+ (func $4 (type $0)
+ (block $label$0
+ (nop)
+ (if
+ (i32.const 1)
+ (block $label$1
+ (unreachable)
+ )
+ )
+ (nop)
+ )
+ )
+ (func $5 (type $0)
+ (block $label$0
+ (nop)
+ (if
+ (i32.const 1)
+ (block $label$1
+ (unreachable)
+ )
+ (block $label$2
+ (unreachable)
+ )
+ )
+ )
+ )
+ (func $6 (type $0)
+ (block $label$0
+ (nop)
+ (block $label$1
+ (if
+ (i32.const 1)
+ (block $label$2
+ (unreachable)
+ )
+ )
+ )
+ (nop)
+ )
+ )
+ (func $7 (type $0)
+ (block $label$0
+ (nop)
+ (block $label$1
+ (if
+ (i32.const 1)
+ (block $label$2
+ (unreachable)
+ )
+ (block $label$3
+ (unreachable)
+ )
+ )
+ )
+ )
+ )
+ (func $8 (type $0)
+ (block $label$0
+ (nop)
+ (block $label$1
+ (nop)
+ (br $label$1)
+ )
+ (nop)
+ )
+ )
+ (func $9 (type $0)
+ (block $label$0
+ (nop)
+ (block $label$1
+ (nop)
+ (br $label$0)
+ )
+ )
+ )
+)
+
diff --git a/test/unreachable-pops.wasm b/test/unreachable-pops.wasm
new file mode 100644
index 000000000..f3e0ae11c
--- /dev/null
+++ b/test/unreachable-pops.wasm
Binary files differ
diff --git a/test/unreachable-pops.wasm.fromBinary b/test/unreachable-pops.wasm.fromBinary
new file mode 100644
index 000000000..4e14995cf
--- /dev/null
+++ b/test/unreachable-pops.wasm.fromBinary
@@ -0,0 +1,10 @@
+(module
+ (type $0 (func (result i32)))
+ (memory $0 0)
+ (func $0 (type $0) (result i32)
+ (block $label$0 (result i32)
+ (unreachable)
+ )
+ )
+)
+
diff --git a/test/untaken-br_if.wast.fromBinary b/test/untaken-br_if.wast.fromBinary
index 87dd9c757..815789c35 100644
--- a/test/untaken-br_if.wast.fromBinary
+++ b/test/untaken-br_if.wast.fromBinary
@@ -12,16 +12,10 @@
(drop
(i32.const 1)
)
- (br_if $label$2
- (unreachable)
- )
- (unreachable)
(unreachable)
)
- (unreachable)
)
)
- (unreachable)
)
)
diff --git a/test/untaken-br_if.wast.fromBinary.noDebugInfo b/test/untaken-br_if.wast.fromBinary.noDebugInfo
index ad71cd874..9b31417eb 100644
--- a/test/untaken-br_if.wast.fromBinary.noDebugInfo
+++ b/test/untaken-br_if.wast.fromBinary.noDebugInfo
@@ -12,16 +12,10 @@
(drop
(i32.const 1)
)
- (br_if $label$2
- (unreachable)
- )
- (unreachable)
(unreachable)
)
- (unreachable)
)
)
- (unreachable)
)
)