diff options
author | Heejin Ahn <aheejin@gmail.com> | 2020-05-15 13:29:40 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-15 13:29:40 -0700 |
commit | be61c69e3921d969fdb4743d31b289429aa280c0 (patch) | |
tree | 9460cc126f08105a069d48a837c84adf00ef5e5b | |
parent | 954acedd317817708ad4a20a29bd6b879086396a (diff) | |
download | binaryen-be61c69e3921d969fdb4743d31b289429aa280c0.tar.gz binaryen-be61c69e3921d969fdb4743d31b289429aa280c0.tar.bz2 binaryen-be61c69e3921d969fdb4743d31b289429aa280c0.zip |
Fix br_on_exn handling in ReFinalize (#2854)
In `ReFinalize`'s branch handling, `updateBreakValueType` is supposed to
be executed only when the branch itself is not replaced with its
argument (because it is guaranteed not to be taken).
Also this moves `visitBrOnExn` from `RuntimeExpressionRunner` to its
base class `ExpressionRunner`, because it does not depend on anything on
the runtime instance to work. This is effectively NFC for now because
`visitTry` is still only implemented only in `RuntimeExpressionRunner`
because it relies on multivalue handling of it, and without it we cannot
create a valid exception `Literal`.
-rw-r--r-- | src/ir/ReFinalize.cpp | 3 | ||||
-rw-r--r-- | src/wasm-interpreter.h | 41 | ||||
-rw-r--r-- | test/passes/precompute_all-features.txt | 10 | ||||
-rw-r--r-- | test/passes/precompute_all-features.wast | 15 |
4 files changed, 45 insertions, 24 deletions
diff --git a/src/ir/ReFinalize.cpp b/src/ir/ReFinalize.cpp index a81182832..1de2e97a6 100644 --- a/src/ir/ReFinalize.cpp +++ b/src/ir/ReFinalize.cpp @@ -130,8 +130,9 @@ void ReFinalize::visitBrOnExn(BrOnExn* curr) { curr->finalize(); if (curr->exnref->type == Type::unreachable) { replaceUntaken(curr->exnref, nullptr); + } else { + updateBreakValueType(curr->name, curr->sent); } - updateBreakValueType(curr->name, curr->sent); } void ReFinalize::visitNop(Nop* curr) { curr->finalize(); } void ReFinalize::visitUnreachable(Unreachable* curr) { curr->finalize(); } diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 257a0670f..b0118231e 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1270,7 +1270,24 @@ public: throwException(flow.getSingleValue()); WASM_UNREACHABLE("rethrow"); } - Flow visitBrOnExn(BrOnExn* curr) { WASM_UNREACHABLE("unimp"); } + Flow visitBrOnExn(BrOnExn* curr) { + NOTE_ENTER("BrOnExn"); + Flow flow = this->visit(curr->exnref); + if (flow.breaking()) { + return flow; + } + if (flow.getType() == Type::nullref) { + trap("br_on_exn: argument is null"); + } + const ExceptionPackage& ex = flow.getSingleValue().getExceptionPackage(); + if (curr->event != ex.event) { // Not taken + return flow; + } + // Taken + flow.values = ex.values; + flow.breakTo = curr->name; + return flow; + } virtual void trap(const char* why) { WASM_UNREACHABLE("unimp"); } @@ -1514,10 +1531,6 @@ public: NOTE_ENTER("Try"); return Flow(NONCONSTANT_FLOW); } - Flow visitBrOnExn(BrOnExn* curr) { - NOTE_ENTER("BrOnExn"); - return Flow(NONCONSTANT_FLOW); - } void trap(const char* why) override { throw NonconstantException(); } @@ -2410,24 +2423,6 @@ private: return this->visit(curr->catchBody); } } - Flow visitBrOnExn(BrOnExn* curr) { - NOTE_ENTER("BrOnExn"); - Flow flow = this->visit(curr->exnref); - if (flow.breaking()) { - return flow; - } - if (flow.getType() == Type::nullref) { - trap("br_on_exn: argument is null"); - } - const ExceptionPackage& ex = flow.getSingleValue().getExceptionPackage(); - if (curr->event != ex.event) { // Not taken - return flow; - } - // Taken - flow.values = ex.values; - flow.breakTo = curr->name; - return flow; - } Flow visitPush(Push* curr) { NOTE_ENTER("Push"); Flow value = this->visit(curr->value); diff --git a/test/passes/precompute_all-features.txt b/test/passes/precompute_all-features.txt index 9c7f4eab1..4253d3c42 100644 --- a/test/passes/precompute_all-features.txt +++ b/test/passes/precompute_all-features.txt @@ -10,6 +10,7 @@ (data (i32.const 0) "passive") (global $global i32 (i32.const 1)) (global $global-mut (mut i32) (i32.const 2)) + (event $event$0 (attr 0) (param)) (func $x (param $x i32) (call $x (i32.const 2300) @@ -314,4 +315,13 @@ ) ) ) + (func $unreachable-br_on_exn + (block $label$1 + (drop + (loop $label$2 + (br $label$2) + ) + ) + ) + ) ) diff --git a/test/passes/precompute_all-features.wast b/test/passes/precompute_all-features.wast index bbe984704..343b01ff1 100644 --- a/test/passes/precompute_all-features.wast +++ b/test/passes/precompute_all-features.wast @@ -461,4 +461,19 @@ ) ) ) + + ;; br_on_exn's argument becomes unreachable, so br_on_exn itself is replaced + ;; with its argument in ReFinalize process after precompute. + (event $event$0 (attr 0) (param)) + (func $unreachable-br_on_exn + (block $label$1 + (drop + (br_on_exn $label$1 $event$0 + (loop $label$2 (result nullref) + (br $label$2) + ) + ) + ) + ) + ) ) |