summaryrefslogtreecommitdiff
path: root/src/wasm/wasm.cpp
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2017-02-16 14:27:23 -0800
committerGitHub <noreply@github.com>2017-02-16 14:27:23 -0800
commit5e29a613bb8bf059f5f7b9ec2f166f8d2e413ac5 (patch)
tree64eb41cbef50830367255672091c62fd10724ce2 /src/wasm/wasm.cpp
parent97077693a6458d51bd5b3dc85187d5a4bd16c3ee (diff)
downloadbinaryen-5e29a613bb8bf059f5f7b9ec2f166f8d2e413ac5.tar.gz
binaryen-5e29a613bb8bf059f5f7b9ec2f166f8d2e413ac5.tar.bz2
binaryen-5e29a613bb8bf059f5f7b9ec2f166f8d2e413ac5.zip
Fix emitting of unreachable block/if/loop (#911)
* an unreachable block is one with an unreachable child, plus no breaks * document new difference between binaryen IR and wasm * fix relooper missing finalize * add a bunch of tests * don't assume that test/*.wast files print to themselves exactly; print to from.wast. this allows wast tests with comments in them * emit unreachable blocks as (block .. unreachable) unreachable * if without else and unreachable ifTrue is still not unreachable, it should be none * update wasm.js * cleanups * empty blocks have none type
Diffstat (limited to 'src/wasm/wasm.cpp')
-rw-r--r--src/wasm/wasm.cpp31
1 files changed, 24 insertions, 7 deletions
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index cf58949de..c80d10c83 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -133,14 +133,30 @@ static WasmType mergeTypes(std::vector<WasmType>& types) {
return type;
}
+// a block is unreachable if one of its elements is unreachable,
+// and there are no branches to it
+static void handleUnreachable(Block* block) {
+ if (block->type == unreachable) return; // nothing to do
+ for (auto* child : block->list) {
+ if (child->type == unreachable) {
+ // there is an unreachable child, so we are unreachable, unless we have a break
+ BreakSeeker seeker(block->name);
+ Expression* expr = block;
+ seeker.walk(expr);
+ if (!seeker.found) {
+ block->type = unreachable;
+ } else {
+ block->type = seeker.valueType;
+ }
+ return;
+ }
+ }
+}
+
void Block::finalize(WasmType type_) {
type = type_;
if (type == none && list.size() > 0) {
- if (list.back()->type == unreachable) {
- if (!BreakSeeker::has(this, name)) {
- type = unreachable; // the last element is unreachable, and this block truly cannot be exited, so it is unreachable itself
- }
- }
+ handleUnreachable(this);
}
}
@@ -150,18 +166,19 @@ void Block::finalize() {
if (list.size() > 0) {
type = list.back()->type;
} else {
- type = unreachable;
+ type = none;
}
return;
}
TypeSeeker seeker(this, this->name);
type = mergeTypes(seeker.types);
+ handleUnreachable(this);
}
void If::finalize(WasmType type_) {
type = type_;
- if (type == none && (condition->type == unreachable || (ifTrue->type == unreachable && (!ifFalse || ifFalse->type == unreachable)))) {
+ if (type == none && (condition->type == unreachable || (ifFalse && ifTrue->type && ifFalse->type == unreachable))) {
type = unreachable;
}
}