diff options
author | Alon Zakai <alonzakai@gmail.com> | 2017-02-16 14:27:23 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-02-16 14:27:23 -0800 |
commit | 5e29a613bb8bf059f5f7b9ec2f166f8d2e413ac5 (patch) | |
tree | 64eb41cbef50830367255672091c62fd10724ce2 /src/wasm/wasm.cpp | |
parent | 97077693a6458d51bd5b3dc85187d5a4bd16c3ee (diff) | |
download | binaryen-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.cpp | 31 |
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; } } |