summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/SimplifyLocals.cpp14
-rw-r--r--test/passes/simplify-locals_all-features.txt38
-rw-r--r--test/passes/simplify-locals_all-features.wast32
3 files changed, 84 insertions, 0 deletions
diff --git a/src/passes/SimplifyLocals.cpp b/src/passes/SimplifyLocals.cpp
index 85c719d4c..ca3d714f4 100644
--- a/src/passes/SimplifyLocals.cpp
+++ b/src/passes/SimplifyLocals.cpp
@@ -302,6 +302,20 @@ struct SimplifyLocals
Expression** currp) {
Expression* curr = *currp;
+ // Expressions that may throw cannot be sinked into 'try'. At the start of
+ // 'try', we drop all sinkables that may throw.
+ if (curr->is<Try>()) {
+ std::vector<Index> invalidated;
+ for (auto& sinkable : self->sinkables) {
+ if (sinkable.second.effects.throws) {
+ invalidated.push_back(sinkable.first);
+ }
+ }
+ for (auto index : invalidated) {
+ self->sinkables.erase(index);
+ }
+ }
+
EffectAnalyzer effects(self->getPassOptions(), self->getModule()->features);
if (effects.checkPre(curr)) {
self->checkInvalidations(effects);
diff --git a/test/passes/simplify-locals_all-features.txt b/test/passes/simplify-locals_all-features.txt
index 0418e6bd1..fbb1f87ed 100644
--- a/test/passes/simplify-locals_all-features.txt
+++ b/test/passes/simplify-locals_all-features.txt
@@ -1896,6 +1896,7 @@
(type $none_=>_none (func))
(type $i32_exnref_=>_none (func (param i32 exnref)))
(type $exnref_=>_none (func (param exnref)))
+ (type $none_=>_i32 (func (result i32)))
(type $none_=>_exnref (func (result exnref)))
(event $event$0 (attr 0) (param))
(event $event$1 (attr 0) (param exnref))
@@ -1980,4 +1981,41 @@
)
)
)
+ (func $bar (result i32)
+ (i32.const 3)
+ )
+ (func $call-cannot-be-sinked-into-try
+ (local $0 i32)
+ (local.set $0
+ (call $bar)
+ )
+ (try
+ (do
+ (drop
+ (local.get $0)
+ )
+ )
+ (catch
+ (drop
+ (exnref.pop)
+ )
+ )
+ )
+ )
+ (func $non-call-can-be-sinked-into-try
+ (local $0 i32)
+ (nop)
+ (try
+ (do
+ (drop
+ (i32.const 3)
+ )
+ )
+ (catch
+ (drop
+ (exnref.pop)
+ )
+ )
+ )
+ )
)
diff --git a/test/passes/simplify-locals_all-features.wast b/test/passes/simplify-locals_all-features.wast
index 4fdedb2f9..a8e1a161f 100644
--- a/test/passes/simplify-locals_all-features.wast
+++ b/test/passes/simplify-locals_all-features.wast
@@ -1749,4 +1749,36 @@
)
)
)
+
+ (func $bar (result i32) (i32.const 3))
+ (func $call-cannot-be-sinked-into-try (local $0 i32)
+ (drop
+ ;; This local.tee should NOT be sinked into 'try' below, because it may
+ ;; throw
+ (local.tee $0 (call $bar))
+ )
+ (try
+ (do
+ (drop (local.get $0))
+ )
+ (catch
+ (drop (exnref.pop))
+ )
+ )
+ )
+
+ (func $non-call-can-be-sinked-into-try (local $0 i32)
+ (drop
+ ;; This local.tee can be sinked into 'try' below, because it cannot throw
+ (local.tee $0 (i32.const 3))
+ )
+ (try
+ (do
+ (drop (local.get $0))
+ )
+ (catch
+ (drop (exnref.pop))
+ )
+ )
+ )
)