summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2016-10-04 20:05:45 -0700
committerGitHub <noreply@github.com>2016-10-04 20:05:45 -0700
commit45ba1270e8d99c0c7fdc008c0db7c9d7fa0a4f38 (patch)
tree62ff9e2320b4b5c33b8a57f7ed3f85dd97a1e1d1 /src
parent4e1667aa3454f56b3e96df674c504cb16366b628 (diff)
downloadbinaryen-45ba1270e8d99c0c7fdc008c0db7c9d7fa0a4f38.tar.gz
binaryen-45ba1270e8d99c0c7fdc008c0db7c9d7fa0a4f38.tar.bz2
binaryen-45ba1270e8d99c0c7fdc008c0db7c9d7fa0a4f38.zip
DCE bugfix (#736)
* fix a dce bug where it is invalid to truncate a block if it leaves a final element with a bad type (wasm doesn't always allow removing unreachable code) * add wast pass fuzzer
Diffstat (limited to 'src')
-rw-r--r--src/passes/DeadCodeElimination.cpp15
1 files changed, 13 insertions, 2 deletions
diff --git a/src/passes/DeadCodeElimination.cpp b/src/passes/DeadCodeElimination.cpp
index b30b8ffbd..c2799f13a 100644
--- a/src/passes/DeadCodeElimination.cpp
+++ b/src/passes/DeadCodeElimination.cpp
@@ -110,12 +110,23 @@ struct DeadCodeElimination : public WalkerPass<PostWalker<DeadCodeElimination, V
Index i = self->blockStack.back();
self->blockStack.back()++;
if (!self->reachable) {
- // control flow ended in the middle of the block
+ // control flow ended in the middle of the block, so we can truncate the rest.
// note that we still visit the rest, so if we already truncated, do not lengthen.
// note that it is ok that we visit the others even though the list was shortened;
// our arena vectors leave things as they are when shrinking.
if (block->list.size() > i + 1) {
- block->list.resize(i + 1);
+ // but note that it is not legal to truncate a block if it leaves a bad last element,
+ // given the wasm type rules. For example, if the last element is a return, then
+ // the block doesn't care about it for type checking purposes, but if removing
+ // it would leave an element with type none as the last, that could be a problem,
+ // see https://github.com/WebAssembly/spec/issues/355
+ if (!(isConcreteWasmType(block->type) && block->list[i]->type == none)) {
+ block->list.resize(i + 1);
+ // note that we do *not* finalize here. it is incorrect to re-finalize a block
+ // after removing elements, as it may no longer have branches to it that would
+ // determine its type, so re-finalizing would just wipe out an existing type
+ // that it had.
+ }
}
}
}