summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2017-03-14 14:06:36 -0700
committerGitHub <noreply@github.com>2017-03-14 14:06:36 -0700
commita407b989ecc0c57ed4862ceaaa25acb0a41af63c (patch)
tree736ec0349a9429430b1995fe7d913d40ad01b67a
parentc1e18d8aded2b86cfd8fb86886ad74cee2f14535 (diff)
downloadbinaryen-a407b989ecc0c57ed4862ceaaa25acb0a41af63c.tar.gz
binaryen-a407b989ecc0c57ed4862ceaaa25acb0a41af63c.tar.bz2
binaryen-a407b989ecc0c57ed4862ceaaa25acb0a41af63c.zip
fix emitting of unreachable ifs (#944)
-rw-r--r--src/wasm/wasm-binary.cpp24
-rw-r--r--test/unit.wast12
-rw-r--r--test/unit.wast.from-wast45
-rw-r--r--test/unit.wast.fromBinary46
-rw-r--r--test/unit.wast.fromBinary.noDebugInfo46
5 files changed, 160 insertions, 13 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 4d5d7e176..c723dfe32 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -507,17 +507,12 @@ void WasmBinaryWriter::recursePossibleBlockContents(Expression* curr) {
void WasmBinaryWriter::visitIf(If *curr) {
if (debug) std::cerr << "zz node: If" << std::endl;
- if (curr->type == unreachable && curr->ifFalse) {
- if (curr->condition->type == unreachable) {
- // this if-else is unreachable because of the condition, i.e., the condition
- // does not exit. So don't emit the if, but do consume the condition
- recurse(curr->condition);
- o << int8_t(BinaryConsts::Unreachable);
- return;
- }
- // an unreachable if-else (with reachable condition) is one where both sides do not fall through.
- // wasm does not allow this to be emitted directly, so we must do something more. we could do
- // better, but for now we emit an extra unreachable instruction after the if, so it is not consumed itself
+ if (curr->condition->type == unreachable) {
+ // this if-else is unreachable because of the condition, i.e., the condition
+ // does not exit. So don't emit the if, but do consume the condition
+ recurse(curr->condition);
+ o << int8_t(BinaryConsts::Unreachable);
+ return;
}
recurse(curr->condition);
o << int8_t(BinaryConsts::If);
@@ -533,8 +528,11 @@ void WasmBinaryWriter::visitIf(If *curr) {
}
o << int8_t(BinaryConsts::End);
if (curr->type == unreachable) {
- // see explanation above - we emitted an if without a return type, so it must not be consumed
- assert(curr->ifFalse); // otherwise, if without else, that is unreachable, must have an unreachable condition, which was handled earlier
+ // we already handled the case of the condition being unreachable. otherwise,
+ // we may still be unreachable, if we are an if-else with both sides unreachable.
+ // wasm does not allow this to be emitted directly, so we must do something more. we could do
+ // better, but for now we emit an extra unreachable instruction after the if, so it is not consumed itself,
+ assert(curr->ifFalse);
o << int8_t(BinaryConsts::Unreachable);
}
}
diff --git a/test/unit.wast b/test/unit.wast
index 6c3d8e0fa..2cd164238 100644
--- a/test/unit.wast
+++ b/test/unit.wast
@@ -525,4 +525,16 @@
(return (i32.const 1))
)
)
+ (func $unreachable-ifs
+ (if (unreachable) (nop))
+ (if (unreachable) (unreachable))
+ (if (unreachable) (nop) (nop))
+ (if (unreachable) (unreachable) (nop))
+ (if (unreachable) (nop) (unreachable))
+ (if (unreachable) (unreachable) (unreachable))
+ ;;
+ (if (i32.const 1) (unreachable) (nop))
+ (if (i32.const 1) (nop) (unreachable))
+ (if (i32.const 1) (unreachable) (unreachable))
+ )
)
diff --git a/test/unit.wast.from-wast b/test/unit.wast.from-wast
index b7b914795..99def6ded 100644
--- a/test/unit.wast.from-wast
+++ b/test/unit.wast.from-wast
@@ -557,4 +557,49 @@
)
)
)
+ (func $unreachable-ifs (type $FUNCSIG$v)
+ (if
+ (unreachable)
+ (nop)
+ )
+ (if
+ (unreachable)
+ (unreachable)
+ )
+ (if
+ (unreachable)
+ (nop)
+ (nop)
+ )
+ (if
+ (unreachable)
+ (unreachable)
+ (nop)
+ )
+ (if
+ (unreachable)
+ (nop)
+ (unreachable)
+ )
+ (if
+ (unreachable)
+ (unreachable)
+ (unreachable)
+ )
+ (if
+ (i32.const 1)
+ (unreachable)
+ (nop)
+ )
+ (if
+ (i32.const 1)
+ (nop)
+ (unreachable)
+ )
+ (if
+ (i32.const 1)
+ (unreachable)
+ (unreachable)
+ )
+ )
)
diff --git a/test/unit.wast.fromBinary b/test/unit.wast.fromBinary
index 7a9b1c58d..266cd2246 100644
--- a/test/unit.wast.fromBinary
+++ b/test/unit.wast.fromBinary
@@ -595,5 +595,51 @@
)
(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)
+ )
)
diff --git a/test/unit.wast.fromBinary.noDebugInfo b/test/unit.wast.fromBinary.noDebugInfo
index 704da90f3..6818db1bb 100644
--- a/test/unit.wast.fromBinary.noDebugInfo
+++ b/test/unit.wast.fromBinary.noDebugInfo
@@ -595,5 +595,51 @@
)
(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)
+ )
)