summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeejin Ahn <aheejin@gmail.com>2021-06-08 13:15:59 -0700
committerGitHub <noreply@github.com>2021-06-08 13:15:59 -0700
commiteac90b56d4a749f10d440e4bb7fd744e4bc756e8 (patch)
treeaeb562b523b3a610cb716962c36cc4ee6367c2dc
parent28f227fb90d18d8c1fc2c52b592d2934469aef8e (diff)
downloadbinaryen-eac90b56d4a749f10d440e4bb7fd744e4bc756e8.tar.gz
binaryen-eac90b56d4a749f10d440e4bb7fd744e4bc756e8.tar.bz2
binaryen-eac90b56d4a749f10d440e4bb7fd744e4bc756e8.zip
[EH] Convert EH tests into lit tests (#3923)
This converts most EH tests in test/passes into test/lit/passes. Fixed some files to follow 2-space indentation and improved some comments.
-rw-r--r--test/lit/passes/coalesce-locals-eh.wast43
-rw-r--r--test/lit/passes/code-folding-eh.wast153
-rw-r--r--test/lit/passes/code-pushing-eh.wast208
-rw-r--r--test/lit/passes/dce-eh.wast125
-rw-r--r--test/lit/passes/inlining-eh.wast99
-rw-r--r--test/lit/passes/instrument-locals-eh.wast30
-rw-r--r--test/lit/passes/optimize-instructions-eh.wast249
-rw-r--r--test/lit/passes/remove-unused-module-elements-eh.wast30
-rw-r--r--test/lit/passes/remove-unused-names-eh.wast70
-rw-r--r--test/lit/passes/rse-eh.wast449
-rw-r--r--test/lit/passes/simplify-locals-eh.wast153
-rw-r--r--test/lit/passes/stack-ir-eh.wast60
-rw-r--r--test/lit/passes/stack-ir-roundtrip-eh.wast61
-rw-r--r--test/lit/passes/vacuum-eh.wast126
-rw-r--r--test/passes/coalesce-locals_all-features.txt21
-rw-r--r--test/passes/coalesce-locals_all-features.wast19
-rw-r--r--test/passes/code-pushing_all-features.txt127
-rw-r--r--test/passes/code-pushing_all-features.wast86
-rw-r--r--test/passes/dce_all-features.txt58
-rw-r--r--test/passes/dce_all-features.wast70
-rw-r--r--test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_all-features.txt71
-rw-r--r--test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_all-features.wast34
-rw-r--r--test/passes/generate-stack-ir_roundtrip_all-features.txt32
-rw-r--r--test/passes/generate-stack-ir_roundtrip_all-features.wast31
-rw-r--r--test/passes/inlining_all-features.txt56
-rw-r--r--test/passes/inlining_all-features.wast46
-rw-r--r--test/passes/instrument-locals_all-features_disable-typed-function-references.txt12
-rw-r--r--test/passes/instrument-locals_all-features_disable-typed-function-references.wast10
-rw-r--r--test/passes/remove-unused-module-elements_all-features.txt24
-rw-r--r--test/passes/remove-unused-module-elements_all-features.wast20
-rw-r--r--test/passes/remove-unused-names_all-features.txt37
-rw-r--r--test/passes/remove-unused-names_all-features.wast34
-rw-r--r--test/passes/remove-unused-names_code-folding.txt (renamed from test/passes/remove-unused-names_code-folding_all-features.txt)83
-rw-r--r--test/passes/remove-unused-names_code-folding.wast (renamed from test/passes/remove-unused-names_code-folding_all-features.wast)69
-rw-r--r--test/passes/remove-unused-names_optimize-instructions_all-features.txt125
-rw-r--r--test/passes/remove-unused-names_optimize-instructions_all-features.wast101
-rw-r--r--test/passes/rse_all-features.txt252
-rw-r--r--test/passes/rse_all-features.wast188
-rw-r--r--test/passes/simplify-locals_all-features.txt86
-rw-r--r--test/passes/simplify-locals_all-features.wast71
-rw-r--r--test/passes/vacuum_all-features.txt54
-rw-r--r--test/passes/vacuum_all-features.wast73
42 files changed, 1857 insertions, 1889 deletions
diff --git a/test/lit/passes/coalesce-locals-eh.wast b/test/lit/passes/coalesce-locals-eh.wast
new file mode 100644
index 000000000..f564c2991
--- /dev/null
+++ b/test/lit/passes/coalesce-locals-eh.wast
@@ -0,0 +1,43 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
+;; RUN: wasm-opt %s --coalesce-locals -all -S -o - | filecheck %s
+
+(module
+ ;; CHECK: (func $bar (result i32)
+ ;; CHECK-NEXT: (i32.const 1984)
+ ;; CHECK-NEXT: )
+ (func $bar (result i32)
+ (i32.const 1984)
+ )
+
+ (event $e (attr 0))
+ ;; CHECK: (func $bug-cfg-traversal (param $0 i32) (result i32)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (call $bar)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ (func $bug-cfg-traversal (param $0 i32) (result i32)
+ (local $x i32)
+ ;; This is a regrssion test case for a bug in cfg-traversal for EH.
+ ;; See https://github.com/WebAssembly/binaryen/pull/3594
+ (try
+ (do
+ (local.set $x
+ ;; the call may or may not throw, so we may reach the get of $x
+ (call $bar)
+ )
+ )
+ (catch_all
+ (unreachable)
+ )
+ )
+ (local.get $x)
+ )
+)
diff --git a/test/lit/passes/code-folding-eh.wast b/test/lit/passes/code-folding-eh.wast
new file mode 100644
index 000000000..6a1a1eb36
--- /dev/null
+++ b/test/lit/passes/code-folding-eh.wast
@@ -0,0 +1,153 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
+;; RUN: wasm-opt %s --remove-unused-names --code-folding -all -S -o - \
+;; RUN: | filecheck %s
+
+(module
+ (event $e-i32 (attr 0) (param i32))
+
+ ;; CHECK: (func $pop-test
+ ;; CHECK-NEXT: (block $folding-inner0
+ ;; CHECK-NEXT: (try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $e-i32
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (pop i32)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $folding-inner0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $e-i32
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (pop i32)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $folding-inner0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (return)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 111)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 222)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 333)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ (func $pop-test
+ (try
+ (do
+ (try
+ (do)
+ (catch $e-i32
+ ;; Expressions containing a pop should NOT be taken out and folded.
+ (drop (pop i32))
+ (drop (i32.const 111))
+ (drop (i32.const 222))
+ (drop (i32.const 333))
+ (unreachable)
+ )
+ )
+ )
+ (catch $e-i32
+ (drop (pop i32))
+ (drop (i32.const 111))
+ (drop (i32.const 222))
+ (drop (i32.const 333))
+ (unreachable)
+ )
+ )
+ )
+
+ (func $foo)
+ ;; CHECK: (func $try-call-optimize-terminating-tails (result i32)
+ ;; CHECK-NEXT: (try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (return
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (return
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ (func $try-call-optimize-terminating-tails (result i32)
+ (try
+ (do
+ ;; Expressions that can throw should NOT be taken out of 'try' scope.
+ (call $foo)
+ (call $foo)
+ (call $foo)
+ (call $foo)
+ (return (i32.const 0))
+ )
+ (catch_all
+ (call $foo)
+ (call $foo)
+ (call $foo)
+ (call $foo)
+ (return (i32.const 0))
+ )
+ )
+ (i32.const 0)
+ )
+
+ ;; CHECK: (func $try-call-optimize-expression-tails
+ ;; CHECK-NEXT: (block $x
+ ;; CHECK-NEXT: (try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (br $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (br $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try-call-optimize-expression-tails
+ (block $x
+ (try
+ (do
+ ;; Expressions that can throw should NOT be taken out of 'try' scope.
+ (call $foo)
+ (call $foo)
+ (call $foo)
+ (br $x)
+ )
+ (catch_all
+ (call $foo)
+ (call $foo)
+ (call $foo)
+ (br $x)
+ )
+ )
+ (unreachable)
+ )
+ )
+)
diff --git a/test/lit/passes/code-pushing-eh.wast b/test/lit/passes/code-pushing-eh.wast
new file mode 100644
index 000000000..fe406ec2b
--- /dev/null
+++ b/test/lit/passes/code-pushing-eh.wast
@@ -0,0 +1,208 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
+;; RUN: wasm-opt %s --code-pushing -all -S -o - | filecheck %s
+
+(module
+ (event $e (attr 0) (param i32))
+
+ ;; CHECK: (func $cant-push-past-call
+ ;; CHECK-NEXT: (local $x i32)
+ ;; CHECK-NEXT: (block $out
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call $cant-push-past-call)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br_if $out
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $cant-push-past-call
+ (local $x i32)
+ (block $out
+ ;; This local.set cannot be pushed down, because the call below can throw
+ (local.set $x (i32.const 1))
+ (call $cant-push-past-call)
+ (drop (i32.const 1))
+ (br_if $out (i32.const 2))
+ (drop (local.get $x))
+ )
+ )
+
+ ;; CHECK: (func $cant-push-past-throw
+ ;; CHECK-NEXT: (local $x i32)
+ ;; CHECK-NEXT: (block $out
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw $e
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br_if $out
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $cant-push-past-throw
+ (local $x i32)
+ (block $out
+ ;; This local.set cannot be pushed down, because there is 'throw' below
+ (local.set $x (i32.const 1))
+ (throw $e (i32.const 0))
+ (drop (i32.const 1))
+ (br_if $out (i32.const 2))
+ (drop (local.get $x))
+ )
+ )
+
+ ;; CHECK: (func $can-push-past-try
+ ;; CHECK-NEXT: (local $x i32)
+ ;; CHECK-NEXT: (block $out
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (throw $e
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br_if $out
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $can-push-past-try
+ (local $x i32)
+ (block $out
+ ;; This local.set can be pushed down, because the 'throw' below is going
+ ;; to be caught by the inner catch_all
+ (local.set $x (i32.const 1))
+ (try
+ (do
+ (throw $e (i32.const 0))
+ )
+ (catch_all)
+ )
+ (drop (i32.const 1))
+ (br_if $out (i32.const 2))
+ (drop (local.get $x))
+ )
+ )
+
+ (func $foo)
+ ;; CHECK: (func $cant-push-past-try
+ ;; CHECK-NEXT: (local $x i32)
+ ;; CHECK-NEXT: (block $out
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $e
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (pop i32)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br_if $out
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $cant-push-past-try
+ (local $x i32)
+ (block $out
+ ;; This local.set cannot be pushed down, because the exception thrown by
+ ;; 'call $foo' below may not be caught by 'catch $e'
+ (local.set $x (i32.const 1))
+ (try
+ (do
+ (call $foo)
+ )
+ (catch $e
+ (drop (pop i32))
+ )
+ )
+ (drop (i32.const 1))
+ (br_if $out (i32.const 2))
+ (drop (local.get $x))
+ )
+ )
+
+ ;; CHECK: (func $cant-push-past-rethrow-within-catch
+ ;; CHECK-NEXT: (local $x i32)
+ ;; CHECK-NEXT: (block $out
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (try $l0
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (throw $e
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (rethrow $l0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br_if $out
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $cant-push-past-rethrow-within-catch
+ (local $x i32)
+ (block $out
+ ;; This local.set cannot be pushed down, because there is 'rethrow' within
+ ;; the inner catch_all
+ (local.set $x (i32.const 1))
+ (try $l0
+ (do
+ (throw $e (i32.const 0))
+ )
+ (catch_all
+ (rethrow $l0)
+ )
+ )
+ (drop (i32.const 1))
+ (br_if $out (i32.const 2))
+ (drop (local.get $x))
+ )
+ )
+)
diff --git a/test/lit/passes/dce-eh.wast b/test/lit/passes/dce-eh.wast
new file mode 100644
index 000000000..1bb6358dd
--- /dev/null
+++ b/test/lit/passes/dce-eh.wast
@@ -0,0 +1,125 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
+;; RUN: wasm-opt %s --dce -all -S -o - | filecheck %s
+
+;; If either try body or catch body is reachable, the whole try construct is
+;; reachable
+(module
+ (func $foo)
+ (event $e (attr 0))
+
+ ;; CHECK: (func $try_unreachable
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: )
+ (func $try_unreachable
+ (try
+ (do
+ (unreachable)
+ )
+ (catch_all)
+ )
+ (call $foo) ;; shouldn't be dce'd
+ )
+
+ ;; CHECK: (func $catch_unreachable
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: )
+ (func $catch_unreachable
+ (try
+ (do)
+ (catch_all
+ (unreachable)
+ )
+ )
+ (call $foo) ;; shouldn't be dce'd
+ )
+
+ ;; CHECK: (func $both_unreachable
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $both_unreachable
+ (try
+ (do
+ (unreachable)
+ )
+ (catch_all
+ (unreachable)
+ )
+ )
+ (call $foo) ;; should be dce'd
+ )
+
+ ;; CHECK: (func $throw
+ ;; CHECK-NEXT: (block $label$0
+ ;; CHECK-NEXT: (block $label$1
+ ;; CHECK-NEXT: (throw $e)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $throw
+ ;; All these wrapping expressions before 'throw' will be dce'd
+ (drop
+ (block $label$0 (result externref)
+ (if
+ (i32.clz
+ (block $label$1 (result i32)
+ (throw $e)
+ )
+ )
+ (nop)
+ )
+ (ref.null extern)
+ )
+ )
+ )
+
+ ;; CHECK: (func $rethrow
+ ;; CHECK-NEXT: (try $l0
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $e
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (rethrow $l0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $rethrow
+ (try $l0
+ (do)
+ (catch $e
+ (drop
+ ;; This i32.add will be dce'd
+ (i32.add
+ (i32.const 0)
+ (rethrow $l0)
+ )
+ )
+ )
+ )
+ )
+)
diff --git a/test/lit/passes/inlining-eh.wast b/test/lit/passes/inlining-eh.wast
new file mode 100644
index 000000000..9879978e1
--- /dev/null
+++ b/test/lit/passes/inlining-eh.wast
@@ -0,0 +1,99 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
+;; RUN: wasm-opt %s --inlining -all -S -o - | filecheck %s
+
+(module
+ ;; ---------------------------------------------------------------------------
+ (import "a" "b" (func $foo (result i32)))
+ (event $event$0 (attr 0) (param i32))
+ (func $callee-with-label
+ (try $label
+ (do)
+ (catch $event$0
+ (nop)
+ )
+ )
+ )
+
+ ;; Properly ensure unique try labels after an inlining
+
+ ;; CHECK: (func $caller-with-label (param $x i32)
+ ;; CHECK-NEXT: (loop $label
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block $__inlined_func$callee-with-label
+ ;; CHECK-NEXT: (try $label0
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $event$0
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br_if $label
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $caller-with-label (param $x i32)
+ (loop $label ;; The same label as the try that will be inlined into here
+ (call $callee-with-label)
+ (br_if $label
+ (call $foo)
+ )
+ )
+ )
+
+ ;; ---------------------------------------------------------------------------
+ ;; CHECK: (func $callee-with-try-delegate
+ ;; CHECK-NEXT: (try $label$3
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (delegate 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $callee-with-try-delegate
+ (try $label$3
+ (do)
+ (delegate 0)
+ )
+ )
+
+ ;; For now, do not inline a try-delegate
+
+ ;; CHECK: (func $caller
+ ;; CHECK-NEXT: (call $callee-with-try-delegate)
+ ;; CHECK-NEXT: )
+ (func $caller
+ (call $callee-with-try-delegate)
+ )
+
+ ;; ---------------------------------------------------------------------------
+ (func $callee (result i32)
+ (i32.const 42)
+ )
+
+ ;; Properly support inlining into a function with a try-delegate
+
+ ;; CHECK: (func $caller-with-try-delegate (result i32)
+ ;; CHECK-NEXT: (try $label$3
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (delegate 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block (result i32)
+ ;; CHECK-NEXT: (block $__inlined_func$callee (result i32)
+ ;; CHECK-NEXT: (i32.const 42)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $caller-with-try-delegate (result i32)
+ (try $label$3
+ (do)
+ (delegate 0)
+ )
+ (call $callee)
+ )
+)
diff --git a/test/lit/passes/instrument-locals-eh.wast b/test/lit/passes/instrument-locals-eh.wast
new file mode 100644
index 000000000..99ba94583
--- /dev/null
+++ b/test/lit/passes/instrument-locals-eh.wast
@@ -0,0 +1,30 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
+;; RUN: wasm-opt %s --instrument-locals -all -S -o - | filecheck %s
+
+(module
+ (event $e (attr 0) (param i32))
+
+ ;; CHECK: (func $test
+ ;; CHECK-NEXT: (local $x i32)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $e
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (pop i32)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $test
+ (local $x i32)
+ (try
+ (do)
+ (catch $e
+ ;; Pop instructions should not be instrumented
+ (local.set $x (pop i32))
+ )
+ )
+ )
+)
diff --git a/test/lit/passes/optimize-instructions-eh.wast b/test/lit/passes/optimize-instructions-eh.wast
new file mode 100644
index 000000000..50ae665e2
--- /dev/null
+++ b/test/lit/passes/optimize-instructions-eh.wast
@@ -0,0 +1,249 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
+;; RUN: wasm-opt %s --remove-unused-names --optimize-instructions -all -S -o - \
+;; RUN: | filecheck %s
+
+(module
+ (func $dummy)
+ (event $e (attr 0) (param i32))
+
+ ;; The following are the unit tests for Properties::getFallthrough for EH
+ ;; instructions, which are used in one of binary optimizations in
+ ;; OptimizeInstructions::visitBinary().
+
+ ;; When a pattern of (i32.add (expr) (expr with all 1s)) is detected and
+ ;; 'expr' is guaranteed to take equal or less bits than the number of bits in
+ ;; the second expression, the i32.add can be dropped and we can only leave
+ ;; (expr). For example:
+ ;; (i32.add (local.get $x) (i32.const 7)) can be just (local.get $x) when $x
+ ;; is guaranteed to contain a value equal to or less than 7.
+
+ ;; CHECK: (func $getFallthrough-try-no-throw
+ ;; CHECK-NEXT: (local $x i32)
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (try (result i32)
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (i32.const 3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $getFallthrough-try-no-throw
+ (local $x i32)
+ (local.set $x
+ (try (result i32)
+ (do
+ (i32.const 1)
+ )
+ (catch_all
+ (i32.const 3)
+ )
+ )
+ )
+ ;; The 'try' above is guaranteed not to throw, so we can be sure the $x
+ ;; contains 1 at this point, which is smaller than 7 (0b111), so we know the
+ ;; masking with 0b111 is not ncessary and we can only leave (local.set $x).
+ (drop (i32.and (local.get $x) (i32.const 7)))
+ )
+
+ ;; CHECK: (func $getFallthrough-try-may-throw
+ ;; CHECK-NEXT: (local $x i32)
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (try (result i32)
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (call $dummy)
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (i32.const 3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.and
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (i32.const 7)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $getFallthrough-try-may-throw
+ (local $x i32)
+ (local.set $x
+ (try (result i32)
+ (do
+ (call $dummy)
+ (i32.const 1)
+ )
+ (catch_all
+ (i32.const 3)
+ )
+ )
+ )
+ ;; The 'try' body above may throw because of the call, so we are not sure
+ ;; what $x contains at this point, so we can't remove the masking here.
+ (drop (i32.and (local.get $x) (i32.const 7)))
+ )
+
+ ;; CHECK: (func $getFallthrough-nested-try-0
+ ;; CHECK-NEXT: (local $x i32)
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (try (result i32)
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (call $dummy)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $e
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (pop i32)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $e
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (pop i32)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.and
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (i32.const 7)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $getFallthrough-nested-try-0
+ (local $x i32)
+ (local.set $x
+ (try (result i32)
+ (do
+ (try
+ (do
+ (call $dummy)
+ )
+ (catch $e
+ (drop (pop i32))
+ )
+ )
+ (i32.const 1)
+ )
+ (catch $e
+ (drop (pop i32))
+ (i32.const 3)
+ )
+ )
+ )
+ ;; The inner 'try' may throw and it may not be caught by both the inner and
+ ;; outer catches, so we are not sure what $x contains at this point, which
+ ;; prevents the masking optimization.
+ (drop (i32.and (local.get $x) (i32.const 7)))
+ )
+
+ ;; CHECK: (func $getFallthrough-nested-try-1
+ ;; CHECK-NEXT: (local $x i32)
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (try (result i32)
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (call $dummy)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (i32.const 3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $getFallthrough-nested-try-1
+ (local $x i32)
+ (local.set $x
+ (try (result i32)
+ (do
+ (try
+ (do
+ (call $dummy)
+ )
+ (catch_all)
+ )
+ (i32.const 1)
+ )
+ (catch_all
+ (i32.const 3)
+ )
+ )
+ )
+ ;; The inner try may throw, but it will caught by the inner catch_all, and
+ ;; $x will be set to 1. So we can do the masking optimization and remove
+ ;; i32.and here.
+ (drop (i32.and (local.get $x) (i32.const 7)))
+ )
+
+ ;; CHECK: (func $getFallthrough-nested-try-2
+ ;; CHECK-NEXT: (local $x i32)
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (try (result i32)
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (call $dummy)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.and
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (i32.const 7)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $getFallthrough-nested-try-2
+ (local $x i32)
+ (local.set $x
+ (try (result i32)
+ (do
+ (try
+ (do)
+ (catch_all
+ (call $dummy)
+ )
+ )
+ (i32.const 3)
+ )
+ (catch_all
+ (i32.const 1)
+ )
+ )
+ )
+ ;; Depending on whether (call $dummy) throws or not, we are not sure whether
+ ;; $x will contain 1 or 3 at this point, which prevents the masking
+ ;; optimization.
+ (drop (i32.and (local.get $x) (i32.const 7)))
+ )
+)
diff --git a/test/lit/passes/remove-unused-module-elements-eh.wast b/test/lit/passes/remove-unused-module-elements-eh.wast
new file mode 100644
index 000000000..7e0c66af4
--- /dev/null
+++ b/test/lit/passes/remove-unused-module-elements-eh.wast
@@ -0,0 +1,30 @@
+;; RUN: wasm-opt %s --remove-unused-module-elements -all -S -o - | filecheck %s
+
+;; Non-exported and unused events can be removed
+(module
+ (type $0 (func (param i32)))
+
+ ;; CHECK-NOT: (event $e-remove
+ ;; CHECK: (event $e-export
+ ;; CHECK: (event $e-throw
+ ;; CHECK: (event $e-catch
+ (event $e-remove (attr 0) (type $0)) ;; can be removed
+ (event $e-export (attr 0) (param i64)) ;; cannot be removed (exported)
+ (event $e-throw (attr 0) (type $0)) ;; cannot be removed (used in throw)
+ (event $e-catch (attr 0) (type $0)) ;; cannot be removed (used in catch)
+
+ (export "e-export" (event $e-export))
+ (import "env" "e" (event $e-import (attr 0) (param i32)))
+
+ (start $start)
+ (func $start
+ (try
+ (do
+ (throw $e-throw (i32.const 0))
+ )
+ (catch $e-catch
+ (drop (pop i32))
+ )
+ )
+ )
+)
diff --git a/test/lit/passes/remove-unused-names-eh.wast b/test/lit/passes/remove-unused-names-eh.wast
new file mode 100644
index 000000000..fd20c07e4
--- /dev/null
+++ b/test/lit/passes/remove-unused-names-eh.wast
@@ -0,0 +1,70 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
+;; RUN: wasm-opt %s --remove-unused-names -all -S -o - | filecheck %s
+
+(module
+ (event $event$0 (attr 0) (param i32))
+
+ ;; CHECK: (func $func0
+ ;; CHECK-NEXT: (try $label$9
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $event$0
+ ;; CHECK-NEXT: (try $label$8
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (rethrow $label$9)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (delegate $label$8)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $event$0
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (pop i32)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $func0
+ (try $label$9 ;; needed due to a rethrow
+ (do)
+ (catch $event$0
+ (try $label$8 ;; needed due to a delegate
+ (do
+ (try $label$6 ;; this one is not needed
+ (do
+ (rethrow $label$9)
+ )
+ (delegate $label$8)
+ )
+ )
+ (catch $event$0
+ (drop
+ (pop i32)
+ )
+ )
+ )
+ )
+ )
+ )
+
+ ;; CHECK: (func $func1
+ ;; CHECK-NEXT: (try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (delegate 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $func1
+ (try $label$3 ;; this one is not needed
+ (do
+ (nop)
+ )
+ (delegate 0) ;; delegates to the caller
+ )
+ )
+)
diff --git a/test/lit/passes/rse-eh.wast b/test/lit/passes/rse-eh.wast
new file mode 100644
index 000000000..d6f7074e7
--- /dev/null
+++ b/test/lit/passes/rse-eh.wast
@@ -0,0 +1,449 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
+;; RUN: wasm-opt %s --rse -all -S -o - | filecheck %s
+
+(module
+ (event $e (attr 0) (param i32))
+ (event $e2 (attr 0))
+
+ ;; CHECK: (func $try1
+ ;; CHECK-NEXT: (local $x i32)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try1
+ (local $x i32)
+ (try
+ (do)
+ (catch_all
+ (local.set $x (i32.const 1))
+ )
+ )
+ ;; try will not throw. So this should NOT be dropped
+ (local.set $x (i32.const 1))
+ )
+
+ ;; CHECK: (func $try2
+ ;; CHECK-NEXT: (local $x i32)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (throw $e
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try2
+ (local $x i32)
+ (try
+ (do
+ (throw $e (i32.const 0))
+ (local.set $x (i32.const 1))
+ )
+ (catch_all)
+ )
+ ;; local.set is after 'throw' so it will not run. This should NOT be
+ ;; dropped.
+ (local.set $x (i32.const 1))
+ )
+
+ ;; CHECK: (func $try3
+ ;; CHECK-NEXT: (local $x i32)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (throw $e
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try3
+ (local $x i32)
+ (try
+ (do
+ (throw $e (i32.const 0))
+ )
+ (catch_all
+ (local.set $x (i32.const 1))
+ )
+ )
+ ;; try body will throw and catch_all contains the same local.set. This
+ ;; should be dropped.
+ (local.set $x (i32.const 1))
+ )
+
+ (func $foo)
+ ;; CHECK: (func $try4
+ ;; CHECK-NEXT: (local $x i32)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try4
+ (local $x i32)
+ (try
+ (do
+ (call $foo)
+ (local.set $x (i32.const 1))
+ )
+ (catch_all)
+ )
+ ;; (call $foo) may throw and the local.set may not run, so this should NOT
+ ;; be dropped
+ (local.set $x (i32.const 1))
+ )
+
+ ;; CHECK: (func $try5
+ ;; CHECK-NEXT: (local $x i32)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try5
+ (local $x i32)
+ (try
+ (do
+ (local.set $x (i32.const 1))
+ (call $foo)
+ )
+ (catch_all)
+ )
+ ;; Even if (call $foo) throws, local.set runs before it, so this should be
+ ;; dropped
+ (local.set $x (i32.const 1))
+ )
+
+ ;; CHECK: (func $nested-try1
+ ;; CHECK-NEXT: (local $x i32)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (try $l0
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (throw $e
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (rethrow $l0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $nested-try1
+ (local $x i32)
+ (try
+ (do
+ (try $l0
+ (do
+ (throw $e (i32.const 0))
+ )
+ (catch_all
+ (rethrow $l0)
+ )
+ )
+ )
+ (catch_all
+ (local.set $x (i32.const 1))
+ )
+ )
+ ;; The exception is caught by the inner catch_all and rethrown and again
+ ;; caught by the outer catch_all, which runs the local.set. So this should
+ ;; be dropped.
+ (local.set $x (i32.const 1))
+ )
+
+ ;; CHECK: (func $nested-try2
+ ;; CHECK-NEXT: (local $x i32)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (try $l0
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (throw $e
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (rethrow $l0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $nested-try2
+ (local $x i32)
+ (try
+ (do
+ (try $l0
+ (do
+ (throw $e (i32.const 0))
+ )
+ (catch_all
+ (local.set $x (i32.const 1))
+ (rethrow $l0)
+ )
+ )
+ )
+ (catch_all)
+ )
+ ;; The exception is caught by the inner catch_all, which runs the local.set,
+ ;; so this should be dropped
+ (local.set $x (i32.const 1))
+ )
+
+ ;; CHECK: (func $nested-try3
+ ;; CHECK-NEXT: (local $x i32)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (try $l0
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (throw $e
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $e
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (pop i32)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (rethrow $l0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $nested-try3
+ (local $x i32)
+ (try
+ (do
+ (try $l0
+ (do
+ (throw $e (i32.const 0))
+ )
+ (catch $e
+ (drop (pop i32))
+ (local.set $x (i32.const 1))
+ (rethrow $l0)
+ )
+ )
+ )
+ (catch_all)
+ )
+ ;; Unlike nested-try2, the exception may not be caught by the inner catch,
+ ;; so the local.set may not run. So this should NOT be dropped.
+ (local.set $x (i32.const 1))
+ )
+
+ ;; CHECK: (func $nested-catch1
+ ;; CHECK-NEXT: (local $x i32)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (throw $e
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $e
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (pop i32)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $e2
+ ;; CHECK-NEXT: (try $try0
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (throw $e
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $e
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (pop i32)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $e2
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $nested-catch1
+ (local $x i32)
+ (try
+ (do
+ (throw $e (i32.const 0))
+ )
+ (catch $e
+ (drop (pop i32))
+ )
+ (catch $e2
+ (try
+ (do
+ (throw $e (i32.const 0))
+ )
+ (catch $e
+ (drop (pop i32))
+ )
+ (catch $e2
+ (local.set $x (i32.const 1))
+ )
+ )
+ )
+ )
+ ;; This should NOT be dropped because the exception might not be caught by
+ ;; the inner catches, and the local.set above us may not have run, and
+ ;; other possible code paths do not even set the local.
+ (local.set $x (i32.const 1))
+ )
+
+ ;; CHECK: (func $nested-catch2
+ ;; CHECK-NEXT: (local $x i32)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (throw $e
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $e
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (pop i32)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (try $try1
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (throw $e
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $e
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (pop i32)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $nested-catch2
+ (local $x i32)
+ (try
+ (do
+ (throw $e (i32.const 0))
+ )
+ (catch $e
+ (drop (pop i32))
+ (local.set $x (i32.const 1))
+ )
+ (catch_all
+ (try
+ (do
+ (throw $e (i32.const 0))
+ )
+ (catch $e
+ (drop (pop i32))
+ (local.set $x (i32.const 1))
+ )
+ (catch_all
+ (local.set $x (i32.const 1))
+ )
+ )
+ )
+ )
+ ;; This should be dropped because the exception is guaranteed to be caught
+ ;; by one of the catches and it will set the local to 1.
+ (local.set $x (i32.const 1))
+ )
+)
diff --git a/test/lit/passes/simplify-locals-eh.wast b/test/lit/passes/simplify-locals-eh.wast
new file mode 100644
index 000000000..fb5f671f3
--- /dev/null
+++ b/test/lit/passes/simplify-locals-eh.wast
@@ -0,0 +1,153 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
+;; RUN: wasm-opt %s --simplify-locals -all -S -o - | filecheck %s
+
+(module
+ (event $e-i32 (attr 0) (param i32))
+ ;; CHECK: (func $foo (param $0 i32) (param $1 i32)
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ (func $foo (param i32 i32))
+ ;; CHECK: (func $pop-cannot-be-sinked
+ ;; CHECK-NEXT: (local $0 i32)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $e-i32
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (pop i32)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call $foo
+ ;; CHECK-NEXT: (i32.const 3)
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $pop-cannot-be-sinked (local $0 i32)
+ (try
+ (do)
+ (catch $e-i32
+ ;; This (local.set $0) of (pop i32) cannot be sunk to (local.get $0)
+ ;; below, because the pop should follow right after 'catch'.
+ (local.set $0 (pop i32))
+ (call $foo
+ (i32.const 3)
+ (local.get $0)
+ )
+ )
+ )
+ )
+
+ ;; CHECK: (func $pop-within-catch-can-be-sinked
+ ;; CHECK-NEXT: (local $0 i32)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: (call $foo
+ ;; CHECK-NEXT: (i32.const 3)
+ ;; CHECK-NEXT: (try $try0 (result i32)
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $e-i32
+ ;; CHECK-NEXT: (pop i32)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $pop-within-catch-can-be-sinked (local $0 i32)
+ (try
+ (do)
+ (catch_all
+ ;; This whole 'try' body can be sinked to eliminate local.set /
+ ;; local.get. Even though it contains a pop, it is enclosed within
+ ;; try-catch, so it is OK.
+ (local.set $0
+ (try (result i32)
+ (do (i32.const 0))
+ (catch $e-i32 (pop i32))
+ )
+ )
+ (call $foo
+ (i32.const 3)
+ (local.get $0)
+ )
+ )
+ )
+ )
+
+ ;; CHECK: (func $bar (result i32)
+ ;; CHECK-NEXT: (i32.const 3)
+ ;; CHECK-NEXT: )
+ (func $bar (result i32) (i32.const 3))
+ ;; CHECK: (func $call-cannot-be-sinked-into-try
+ ;; CHECK-NEXT: (local $0 i32)
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (call $bar)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $e-i32
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (pop i32)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (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 $e-i32
+ (drop (pop i32))
+ )
+ )
+ )
+
+ ;; CHECK: (func $non-call-can-be-sinked-into-try
+ ;; CHECK-NEXT: (local $0 i32)
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $e-i32
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (pop i32)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (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 $e-i32
+ (drop (pop i32))
+ )
+ )
+ )
+)
diff --git a/test/lit/passes/stack-ir-eh.wast b/test/lit/passes/stack-ir-eh.wast
new file mode 100644
index 000000000..a398be325
--- /dev/null
+++ b/test/lit/passes/stack-ir-eh.wast
@@ -0,0 +1,60 @@
+;; RUN: wasm-opt %s --generate-stack-ir --optimize-stack-ir --print-stack-ir \
+;; RUN: -all -S -o - | filecheck %s
+
+(module
+ (event $e0 (attr 0) (param i32))
+
+ ;; CHECK: (func $eh
+ ;; CHECK-NEXT: try $l0
+ ;; CHECK-NEXT: i32.const 0
+ ;; CHECK-NEXT: throw $e0
+ ;; CHECK-NEXT: catch $e0
+ ;; CHECK-NEXT:
+ ;; CHECK-NEXT: drop
+ ;; CHECK-NEXT: catch_all
+ ;; CHECK-NEXT: rethrow $l0
+ ;; CHECK-NEXT: end
+ ;; CHECK-NEXT: try $l00
+ ;; CHECK-NEXT: try $try
+ ;; CHECK-NEXT: i32.const 0
+ ;; CHECK-NEXT: throw $e0
+ ;; CHECK-NEXT: delegate $l00
+ ;; CHECK-NEXT: unreachable
+ ;; CHECK-NEXT: catch_all
+ ;; CHECK-NEXT: nop
+ ;; CHECK-NEXT: end
+ ;; CHECK-NEXT: try $l01
+ ;; CHECK-NEXT: nop
+ ;; CHECK-NEXT: delegate 0
+ ;; CHECK-NEXT: )
+ (func $eh
+ (try $l0
+ (do
+ (throw $e0 (i32.const 0))
+ )
+ (catch $e0
+ (drop (pop i32))
+ )
+ (catch_all
+ (rethrow $l0)
+ )
+ )
+
+ (try $l0
+ (do
+ (try
+ (do
+ (throw $e0 (i32.const 0))
+ )
+ (delegate $l0)
+ )
+ )
+ (catch_all)
+ )
+
+ (try $l0
+ (do)
+ (delegate 0) ;; delegate to caller
+ )
+ )
+)
diff --git a/test/lit/passes/stack-ir-roundtrip-eh.wast b/test/lit/passes/stack-ir-roundtrip-eh.wast
new file mode 100644
index 000000000..b9bb22d3e
--- /dev/null
+++ b/test/lit/passes/stack-ir-roundtrip-eh.wast
@@ -0,0 +1,61 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
+;; RUN: wasm-opt %s --generate-stack-ir --roundtrip -all -S -o - | filecheck %s
+
+(module
+ (event $event (attr 0) (param i32))
+ ;; CHECK: (func $delegate-child
+ ;; CHECK-NEXT: (try $label$9
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (try $label$7
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $event$0
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (pop i32)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (try $label$6
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (delegate 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $event$0
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (pop i32)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $delegate-child
+ (try
+ (do
+ (try
+ (do)
+ (catch $event
+ (drop
+ (pop i32)
+ )
+ (try
+ (do)
+ ;; the binary writer must properly handle this delegate which is
+ ;; the child of other try's, and not get confused by their
+ ;; information on the stack (this is a regression test for us
+ ;; properly ending the scope with a delegate and popping the
+ ;; relevant stack).
+ (delegate 2)
+ )
+ )
+ )
+ )
+ (catch $event
+ (drop
+ (pop i32)
+ )
+ )
+ )
+ )
+)
diff --git a/test/lit/passes/vacuum-eh.wast b/test/lit/passes/vacuum-eh.wast
new file mode 100644
index 000000000..d69278319
--- /dev/null
+++ b/test/lit/passes/vacuum-eh.wast
@@ -0,0 +1,126 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
+;; RUN: wasm-opt %s --vacuum -all -S -o - | filecheck %s
+
+(module
+ (event $e (attr 0) (param i32))
+ (event $e2 (attr 0) (param i32))
+
+ ;; CHECK: (func $try-test
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ (func $try-test
+ ;; When try body does not throw, try-body can be replaced with the try body
+ (try
+ (do
+ (drop (i32.const 0))
+ )
+ (catch $e
+ (drop (pop i32))
+ )
+ )
+ )
+
+ ;; CHECK: (func $inner-try-catch_all-test
+ ;; CHECK-NEXT: (local $0 i32)
+ ;; CHECK-NEXT: (try $try0
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (throw $e
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $inner-try-catch_all-test (local $0 i32)
+ ;; The exception thrown in the inner try is caught by the inner catch_all,
+ ;; so the outer try body does not throw and the outer try-catch can be
+ ;; removed
+ (try
+ (do
+ (try
+ (do
+ (throw $e (i32.const 0))
+ )
+ (catch_all
+ (local.set $0 (i32.const 1))
+ )
+ )
+ )
+ (catch $e
+ (drop (pop i32))
+ )
+ )
+ )
+
+ ;; CHECK: (func $inner-try-catch-test
+ ;; CHECK-NEXT: (local $0 i32)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (try $try1
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (throw $e2
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $e
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (pop i32)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $e
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (pop i32)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $inner-try-catch-test (local $0 i32)
+ ;; The exception thrown in the inner try will not be caught by the inner
+ ;; catch, so the outer try-catch cannot be removed
+ (try
+ (do
+ (try
+ (do
+ (throw $e2 (i32.const 0))
+ )
+ (catch $e
+ (drop (pop i32))
+ (local.set $0 (i32.const 1))
+ )
+ )
+ )
+ (catch $e
+ (drop (pop i32))
+ )
+ )
+ )
+
+ ;; CHECK: (func $br-in-catch
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ (func $br-in-catch
+ ;; When catch body is removed, the removal of 'br' inside the catch body
+ ;; should be propagated up to the outer block, so that its type will be
+ ;; correctly updated to unreachable.
+ (block $label$1
+ (try
+ (do
+ (unreachable)
+ )
+ (catch $e
+ (drop (pop i32))
+ (br $label$1)
+ )
+ )
+ )
+ )
+)
diff --git a/test/passes/coalesce-locals_all-features.txt b/test/passes/coalesce-locals_all-features.txt
deleted file mode 100644
index f532f5d0e..000000000
--- a/test/passes/coalesce-locals_all-features.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-(module
- (type $none_=>_i32 (func (result i32)))
- (type $i32_=>_i32 (func (param i32) (result i32)))
- (export "foo" (func $1))
- (func $bar (result i32)
- (i32.const 1984)
- )
- (func $1 (param $0 i32) (result i32)
- (try $try
- (do
- (local.set $0
- (call $bar)
- )
- )
- (catch_all
- (unreachable)
- )
- )
- (local.get $0)
- )
-)
diff --git a/test/passes/coalesce-locals_all-features.wast b/test/passes/coalesce-locals_all-features.wast
deleted file mode 100644
index ff7f04f0c..000000000
--- a/test/passes/coalesce-locals_all-features.wast
+++ /dev/null
@@ -1,19 +0,0 @@
-(module
- (func $bar (result i32)
- (i32.const 1984)
- )
- (func "foo" (param $0 i32) (result i32)
- (local $1 i32)
- (try
- (do
- (local.set $1
- (call $bar) ;; the call may or may not throw, so we may reach the get of $1
- )
- )
- (catch_all
- (unreachable)
- )
- )
- (local.get $1)
- )
-)
diff --git a/test/passes/code-pushing_all-features.txt b/test/passes/code-pushing_all-features.txt
deleted file mode 100644
index 4bcdf5bc3..000000000
--- a/test/passes/code-pushing_all-features.txt
+++ /dev/null
@@ -1,127 +0,0 @@
-(module
- (type $none_=>_none (func))
- (type $i32_=>_none (func (param i32)))
- (event $e (attr 0) (param i32))
- (func $cant-push-past-call
- (local $x i32)
- (block $out
- (local.set $x
- (i32.const 1)
- )
- (call $cant-push-past-call)
- (drop
- (i32.const 1)
- )
- (br_if $out
- (i32.const 2)
- )
- (drop
- (local.get $x)
- )
- )
- )
- (func $cant-push-past-throw
- (local $x i32)
- (block $out
- (local.set $x
- (i32.const 1)
- )
- (throw $e
- (i32.const 0)
- )
- (drop
- (i32.const 1)
- )
- (br_if $out
- (i32.const 2)
- )
- (drop
- (local.get $x)
- )
- )
- )
- (func $can-push-past-try
- (local $x i32)
- (block $out
- (try $try
- (do
- (throw $e
- (i32.const 0)
- )
- )
- (catch_all
- (nop)
- )
- )
- (drop
- (i32.const 1)
- )
- (br_if $out
- (i32.const 2)
- )
- (local.set $x
- (i32.const 1)
- )
- (drop
- (local.get $x)
- )
- )
- )
- (func $foo
- (nop)
- )
- (func $cant-push-past-try
- (local $x i32)
- (block $out
- (local.set $x
- (i32.const 1)
- )
- (try $try
- (do
- (call $foo)
- )
- (catch $e
- (drop
- (pop i32)
- )
- )
- )
- (drop
- (i32.const 1)
- )
- (br_if $out
- (i32.const 2)
- )
- (drop
- (local.get $x)
- )
- )
- )
- (func $cant-push-past-rethrow-within-catch
- (local $x i32)
- (block $out
- (local.set $x
- (i32.const 1)
- )
- (try $l0
- (do
- (throw $e
- (i32.const 0)
- )
- )
- (catch_all
- (rethrow $l0)
- )
- )
- (drop
- (i32.const 1)
- )
- (br_if $out
- (i32.const 2)
- )
- (drop
- (local.get $x)
- )
- )
- )
-)
diff --git a/test/passes/code-pushing_all-features.wast b/test/passes/code-pushing_all-features.wast
deleted file mode 100644
index d9c7cecd4..000000000
--- a/test/passes/code-pushing_all-features.wast
+++ /dev/null
@@ -1,86 +0,0 @@
-(module
- (event $e (attr 0) (param i32))
-
- (func $cant-push-past-call
- (local $x i32)
- (block $out
- ;; This local.set cannot be pushed down, because the call below can throw
- (local.set $x (i32.const 1))
- (call $cant-push-past-call)
- (drop (i32.const 1))
- (br_if $out (i32.const 2))
- (drop (local.get $x))
- )
- )
-
- (func $cant-push-past-throw
- (local $x i32)
- (block $out
- ;; This local.set cannot be pushed down, because there is 'throw' below
- (local.set $x (i32.const 1))
- (throw $e (i32.const 0))
- (drop (i32.const 1))
- (br_if $out (i32.const 2))
- (drop (local.get $x))
- )
- )
-
- (func $can-push-past-try
- (local $x i32)
- (block $out
- ;; This local.set can be pushed down, because the 'throw' below is going
- ;; to be caught by the inner catch_all
- (local.set $x (i32.const 1))
- (try
- (do
- (throw $e (i32.const 0))
- )
- (catch_all)
- )
- (drop (i32.const 1))
- (br_if $out (i32.const 2))
- (drop (local.get $x))
- )
- )
-
- (func $foo)
- (func $cant-push-past-try
- (local $x i32)
- (block $out
- ;; This local.set cannot be pushed down, because the exception thrown by
- ;; 'call $foo' below may not be caught by 'catch $e'
- (local.set $x (i32.const 1))
- (try
- (do
- (call $foo)
- )
- (catch $e
- (drop (pop i32))
- )
- )
- (drop (i32.const 1))
- (br_if $out (i32.const 2))
- (drop (local.get $x))
- )
- )
-
- (func $cant-push-past-rethrow-within-catch
- (local $x i32)
- (block $out
- ;; This local.set cannot be pushed down, because there is 'rethrow' within
- ;; the inner catch_all
- (local.set $x (i32.const 1))
- (try $l0
- (do
- (throw $e (i32.const 0))
- )
- (catch_all
- (rethrow $l0)
- )
- )
- (drop (i32.const 1))
- (br_if $out (i32.const 2))
- (drop (local.get $x))
- )
- )
-)
diff --git a/test/passes/dce_all-features.txt b/test/passes/dce_all-features.txt
index 790e32595..bc1e24951 100644
--- a/test/passes/dce_all-features.txt
+++ b/test/passes/dce_all-features.txt
@@ -540,64 +540,8 @@
)
)
(module
- (type $none_=>_none (func))
(type $none_=>_i32 (func (result i32)))
- (event $e (attr 0) (param))
- (func $foo
- (nop)
- )
- (func $try_unreachable
- (try $try
- (do
- (unreachable)
- )
- (catch_all
- (nop)
- )
- )
- (call $foo)
- )
- (func $catch_unreachable
- (try $try
- (do
- (nop)
- )
- (catch_all
- (unreachable)
- )
- )
- (call $foo)
- )
- (func $both_unreachable
- (try $try
- (do
- (unreachable)
- )
- (catch_all
- (unreachable)
- )
- )
- )
- (func $throw
- (block $label$0
- (block $label$1
- (throw $e)
- )
- )
- )
- (func $rethrow
- (try $l0
- (do
- (nop)
- )
- (catch $e
- (drop
- (i32.const 0)
- )
- (rethrow $l0)
- )
- )
- )
+ (type $none_=>_none (func))
(func $unnecessary-concrete-block (result i32)
(block $foo
(nop)
diff --git a/test/passes/dce_all-features.wast b/test/passes/dce_all-features.wast
index 104093d08..0f0416f66 100644
--- a/test/passes/dce_all-features.wast
+++ b/test/passes/dce_all-features.wast
@@ -734,77 +734,7 @@
)
)
-;; Exception handling instruction support
-;; If either try body or catch body is reachable, the whole try construct is
-;; reachable
(module
- (func $foo)
- (event $e (attr 0))
-
- (func $try_unreachable
- (try
- (do
- (unreachable)
- )
- (catch_all)
- )
- (call $foo) ;; shouldn't be dce'd
- )
-
- (func $catch_unreachable
- (try
- (do)
- (catch_all
- (unreachable)
- )
- )
- (call $foo) ;; shouldn't be dce'd
- )
-
- (func $both_unreachable
- (try
- (do
- (unreachable)
- )
- (catch_all
- (unreachable)
- )
- )
- (call $foo) ;; should be dce'd
- )
-
- (func $throw
- ;; All these wrapping expressions before 'throw' will be dce'd
- (drop
- (block $label$0 (result externref)
- (if
- (i32.clz
- (block $label$1 (result i32)
- (throw $e)
- )
- )
- (nop)
- )
- (ref.null extern)
- )
- )
- )
-
- (func $rethrow
- (try $l0
- (do)
- (catch $e
- (drop
- ;; This i32.add will be dce'd
- (i32.add
- (i32.const 0)
- (rethrow $l0)
- )
- )
- )
- )
- )
-
(func $unnecessary-concrete-block (result i32)
(block $foo (result i32) ;; unnecessary type
(nop)
diff --git a/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_all-features.txt b/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_all-features.txt
deleted file mode 100644
index 8c86126d5..000000000
--- a/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_all-features.txt
+++ /dev/null
@@ -1,71 +0,0 @@
-(module
- (type $i32_=>_none (func (param i32)))
- (type $none_=>_none (func))
- (event $e0 (attr 0) (param i32))
- (func $eh
- try $l0
- i32.const 0
- throw $e0
- catch $e0
-
- drop
- catch_all
- rethrow $l0
- end
- try $l00
- try $try
- i32.const 0
- throw $e0
- delegate $l00
- unreachable
- catch_all
- nop
- end
- try $l01
- nop
- delegate 0
- )
-)
-(module
- (type $i32_=>_none (func (param i32)))
- (type $none_=>_none (func))
- (event $e0 (attr 0) (param i32))
- (func $eh (; has Stack IR ;)
- (try $l0
- (do
- (throw $e0
- (i32.const 0)
- )
- )
- (catch $e0
- (drop
- (pop i32)
- )
- )
- (catch_all
- (rethrow $l0)
- )
- )
- (try $l00
- (do
- (try $try
- (do
- (throw $e0
- (i32.const 0)
- )
- )
- (delegate $l00)
- )
- )
- (catch_all
- (nop)
- )
- )
- (try $l01
- (do
- (nop)
- )
- (delegate 0)
- )
- )
-)
diff --git a/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_all-features.wast b/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_all-features.wast
deleted file mode 100644
index 298cb3a3c..000000000
--- a/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_all-features.wast
+++ /dev/null
@@ -1,34 +0,0 @@
-(module
- (event $e0 (attr 0) (param i32))
-
- (func $eh
- (try $l0
- (do
- (throw $e0 (i32.const 0))
- )
- (catch $e0
- (drop (pop i32))
- )
- (catch_all
- (rethrow $l0)
- )
- )
-
- (try $l0
- (do
- (try
- (do
- (throw $e0 (i32.const 0))
- )
- (delegate $l0)
- )
- )
- (catch_all)
- )
-
- (try $l0
- (do)
- (delegate 0) ;; delegate to caller
- )
- )
-)
diff --git a/test/passes/generate-stack-ir_roundtrip_all-features.txt b/test/passes/generate-stack-ir_roundtrip_all-features.txt
deleted file mode 100644
index 8d6b95b64..000000000
--- a/test/passes/generate-stack-ir_roundtrip_all-features.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-(module
- (type $i32_=>_none (func (param i32)))
- (type $none_=>_none (func))
- (event $event$0 (attr 0) (param i32))
- (func $delegate-child
- (try $label$9
- (do
- (try $label$7
- (do
- (nop)
- )
- (catch $event$0
- (drop
- (pop i32)
- )
- (try $label$6
- (do
- (nop)
- )
- (delegate 2)
- )
- )
- )
- )
- (catch $event$0
- (drop
- (pop i32)
- )
- )
- )
- )
-)
diff --git a/test/passes/generate-stack-ir_roundtrip_all-features.wast b/test/passes/generate-stack-ir_roundtrip_all-features.wast
deleted file mode 100644
index dc6c68d67..000000000
--- a/test/passes/generate-stack-ir_roundtrip_all-features.wast
+++ /dev/null
@@ -1,31 +0,0 @@
-(module
- (event $event (attr 0) (param i32))
- (func $delegate-child
- (try
- (do
- (try
- (do)
- (catch $event
- (drop
- (pop i32)
- )
- (try
- (do)
- ;; the binary writer must properly handle this delegate which is the
- ;; child of other try's, and not get confused by their information on the
- ;; stack (this is a regression test for us properly ending the scope with
- ;; a delegate and popping the relevant stack).
- (delegate 2)
- )
- )
- )
- )
- (catch $event
- (drop
- (pop i32)
- )
- )
- )
- )
-)
-
diff --git a/test/passes/inlining_all-features.txt b/test/passes/inlining_all-features.txt
index 03af9517d..ac9b00559 100644
--- a/test/passes/inlining_all-features.txt
+++ b/test/passes/inlining_all-features.txt
@@ -55,62 +55,6 @@
)
)
(module
- (type $i32_=>_none (func (param i32)))
- (type $none_=>_i32 (func (result i32)))
- (import "a" "b" (func $foo (result i32)))
- (event $event$0 (attr 0) (param i32))
- (export "exported" (func $1))
- (func $1 (param $x i32)
- (loop $label
- (block
- (block $__inlined_func$0
- (try $label0
- (do
- (nop)
- )
- (catch $event$0
- (nop)
- )
- )
- )
- )
- (br_if $label
- (call $foo)
- )
- )
- )
-)
-(module
- (type $none_=>_none (func))
- (func $0
- (try $label$3
- (do
- (nop)
- )
- (delegate 0)
- )
- )
- (func $1
- (call $0)
- )
-)
-(module
- (type $none_=>_i32 (func (result i32)))
- (func $1 (result i32)
- (try $label$3
- (do
- (nop)
- )
- (delegate 0)
- )
- (block (result i32)
- (block $__inlined_func$0 (result i32)
- (i32.const 42)
- )
- )
- )
-)
-(module
(type $none_=>_ref|func| (func (result (ref func))))
(elem declare func $1)
(func $1 (result (ref func))
diff --git a/test/passes/inlining_all-features.wast b/test/passes/inlining_all-features.wast
index 0aa324e1a..99fab7d26 100644
--- a/test/passes/inlining_all-features.wast
+++ b/test/passes/inlining_all-features.wast
@@ -43,52 +43,6 @@
(call $0)
)
)
-;; properly ensure unique try labels after an inlining
-(module
- (import "a" "b" (func $foo (result i32)))
- (event $event$0 (attr 0) (param i32))
- (func $0
- (try $label
- (do)
- (catch $event$0
- (nop)
- )
- )
- )
- (func "exported" (param $x i32)
- (loop $label ;; the same label as the try that will be inlined into here
- (call $0)
- (br_if $label
- (call $foo)
- )
- )
- )
-)
-;; for now, do not inline a try-delegate
-(module
- (func $0
- (try $label$3
- (do)
- (delegate 0)
- )
- )
- (func $1
- (call $0)
- )
-)
-;; properly support inlining into a function with a try-delegate
-(module
- (func $0 (result i32)
- (i32.const 42)
- )
- (func $1 (result i32)
- (try $label$3
- (do)
- (delegate 0)
- )
- (call $0)
- )
-)
;; handle non-nullable parameter types (which turn into local types after
;; inlining)
(module
diff --git a/test/passes/instrument-locals_all-features_disable-typed-function-references.txt b/test/passes/instrument-locals_all-features_disable-typed-function-references.txt
index 0b00ee493..e80161497 100644
--- a/test/passes/instrument-locals_all-features_disable-typed-function-references.txt
+++ b/test/passes/instrument-locals_all-features_disable-typed-function-references.txt
@@ -10,7 +10,6 @@
(type $i32_i32_i31ref_=>_i31ref (func (param i32 i32 i31ref) (result i31ref)))
(type $i32_i32_dataref_=>_dataref (func (param i32 i32 dataref) (result dataref)))
(type $i32_i32_v128_=>_v128 (func (param i32 i32 v128) (result v128)))
- (type $i32_=>_none (func (param i32)))
(type $none_=>_none (func))
(import "env" "get_i32" (func $get_i32 (param i32 i32 i32) (result i32)))
(import "env" "get_i64" (func $get_i64 (param i32 i32 i64) (result i64)))
@@ -35,7 +34,6 @@
(import "env" "get_v128" (func $get_v128 (param i32 i32 v128) (result v128)))
(import "env" "set_v128" (func $set_v128 (param i32 i32 v128) (result v128)))
(elem declare func $test)
- (event $e (attr 0) (param i32))
(func $test
(local $x i32)
(local $y i64)
@@ -204,16 +202,6 @@
)
)
)
- (try $try
- (do
- (nop)
- )
- (catch $e
- (local.set $x
- (pop i32)
- )
- )
- )
(drop
(call $get_v128
(i32.const 22)
diff --git a/test/passes/instrument-locals_all-features_disable-typed-function-references.wast b/test/passes/instrument-locals_all-features_disable-typed-function-references.wast
index 29de7964e..45785c5f1 100644
--- a/test/passes/instrument-locals_all-features_disable-typed-function-references.wast
+++ b/test/passes/instrument-locals_all-features_disable-typed-function-references.wast
@@ -1,6 +1,4 @@
(module
- (event $e (attr 0) (param i32))
-
(func $test
(local $x i32)
(local $y i64)
@@ -38,14 +36,6 @@
(local.set $F (local.get $F))
(local.set $X (local.get $X))
- ;; Pop instructions should not be instrumented
- (try
- (do)
- (catch $e
- (local.set $x (pop i32))
- )
- )
-
;; Add new instructions here so expected output doesn't change too much, it
;; depends on order of instructions in this file.
(drop (local.get $S))
diff --git a/test/passes/remove-unused-module-elements_all-features.txt b/test/passes/remove-unused-module-elements_all-features.txt
index 9cfd05ab2..864624c7e 100644
--- a/test/passes/remove-unused-module-elements_all-features.txt
+++ b/test/passes/remove-unused-module-elements_all-features.txt
@@ -296,30 +296,6 @@
)
)
(module
- (type $0 (func (param i32)))
- (type $i64_=>_none (func (param i64)))
- (type $none_=>_none (func))
- (event $e-export (attr 0) (param i64))
- (event $e-throw (attr 0) (param i32))
- (event $e-catch (attr 0) (param i32))
- (export "e-export" (event $e-export))
- (start $start)
- (func $start
- (try $try
- (do
- (throw $e-throw
- (i32.const 0)
- )
- )
- (catch $e-catch
- (drop
- (pop i32)
- )
- )
- )
- )
-)
-(module
(type $none_=>_none (func))
(elem declare func $foo)
(export "test" (func $test))
diff --git a/test/passes/remove-unused-module-elements_all-features.wast b/test/passes/remove-unused-module-elements_all-features.wast
index 3b2b031ad..09f3ab0e3 100644
--- a/test/passes/remove-unused-module-elements_all-features.wast
+++ b/test/passes/remove-unused-module-elements_all-features.wast
@@ -286,26 +286,6 @@
)
)
)
-(module ;; non-exported and unused events can be removed
- (type $0 (func (param i32)))
- (event $e-remove (attr 0) (type $0)) ;; can be removed
- (event $e-export (attr 0) (param i64)) ;; cannot be removed (exported)
- (event $e-throw (attr 0) (type $0)) ;; cannot be removed (used in throw)
- (event $e-catch (attr 0) (type $0)) ;; cannot be removed (used in catch)
- (export "e-export" (event $e-export))
- (import "env" "e" (event $e-import (attr 0) (param i32)))
- (start $start)
- (func $start
- (try
- (do
- (throw $e-throw (i32.const 0))
- )
- (catch $e-catch
- (drop (pop i32))
- )
- )
- )
-)
(module ;; functions referenced by ref.func cannot be removed
(export "test" $test)
(func $foo)
diff --git a/test/passes/remove-unused-names_all-features.txt b/test/passes/remove-unused-names_all-features.txt
deleted file mode 100644
index d3a9146c8..000000000
--- a/test/passes/remove-unused-names_all-features.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-(module
- (type $none_=>_none (func))
- (type $i32_=>_none (func (param i32)))
- (event $event$0 (attr 0) (param i32))
- (func $0
- (try $label$9
- (do
- (nop)
- )
- (catch $event$0
- (try $label$8
- (do
- (try
- (do
- (rethrow $label$9)
- )
- (delegate $label$8)
- )
- )
- (catch $event$0
- (drop
- (pop i32)
- )
- )
- )
- )
- )
- )
- (func $1
- (try
- (do
- (nop)
- )
- (delegate 0)
- )
- )
-)
diff --git a/test/passes/remove-unused-names_all-features.wast b/test/passes/remove-unused-names_all-features.wast
deleted file mode 100644
index c55268a7a..000000000
--- a/test/passes/remove-unused-names_all-features.wast
+++ /dev/null
@@ -1,34 +0,0 @@
-(module
- (event $event$0 (attr 0) (param i32))
- (func $0
- (try $label$9 ;; needed due to a rethrow
- (do
- )
- (catch $event$0
- (try $label$8 ;; needed due to a delegate
- (do
- (try $label$6 ;; this one is not needed
- (do
- (rethrow $label$9)
- )
- (delegate $label$8)
- )
- )
- (catch $event$0
- (drop
- (pop i32)
- )
- )
- )
- )
- )
- )
- (func $1
- (try $label$3
- (do
- (nop)
- )
- (delegate 0) ;; delegates to the caller
- )
- )
-)
diff --git a/test/passes/remove-unused-names_code-folding_all-features.txt b/test/passes/remove-unused-names_code-folding.txt
index 5437e22db..3f21ae0b3 100644
--- a/test/passes/remove-unused-names_code-folding_all-features.txt
+++ b/test/passes/remove-unused-names_code-folding.txt
@@ -1,10 +1,8 @@
(module
(type $none_=>_none (func))
(type $none_=>_i32 (func (result i32)))
- (type $i32_=>_none (func (param i32)))
(type $i32_i32_=>_i32 (func (param i32 i32) (result i32)))
(type $i32_=>_i32 (func (param i32) (result i32)))
- (event $e-i32 (attr 0) (param i32))
(func $ifs
(if
(i32.const 0)
@@ -1710,85 +1708,4 @@
(i32.const 2)
)
)
- (func $pop-test
- (block $folding-inner0
- (try
- (do
- (try
- (do
- (nop)
- )
- (catch $e-i32
- (drop
- (pop i32)
- )
- (br $folding-inner0)
- )
- )
- )
- (catch $e-i32
- (drop
- (pop i32)
- )
- (br $folding-inner0)
- )
- )
- (return)
- )
- (drop
- (i32.const 111)
- )
- (drop
- (i32.const 222)
- )
- (drop
- (i32.const 333)
- )
- (unreachable)
- )
- (func $foo
- (nop)
- )
- (func $try-call-optimize-terminating-tails (result i32)
- (try
- (do
- (call $foo)
- (call $foo)
- (call $foo)
- (call $foo)
- (return
- (i32.const 0)
- )
- )
- (catch_all
- (call $foo)
- (call $foo)
- (call $foo)
- (call $foo)
- (return
- (i32.const 0)
- )
- )
- )
- (i32.const 0)
- )
- (func $try-call-optimize-expression-tails
- (block $x
- (try
- (do
- (call $foo)
- (call $foo)
- (call $foo)
- (br $x)
- )
- (catch_all
- (call $foo)
- (call $foo)
- (call $foo)
- (br $x)
- )
- )
- (unreachable)
- )
- )
)
diff --git a/test/passes/remove-unused-names_code-folding_all-features.wast b/test/passes/remove-unused-names_code-folding.wast
index 320e820d8..9979a0a3c 100644
--- a/test/passes/remove-unused-names_code-folding_all-features.wast
+++ b/test/passes/remove-unused-names_code-folding.wast
@@ -1191,73 +1191,4 @@
)
)
)
-
- (event $e-i32 (attr 0) (param i32))
- (func $pop-test
- (try
- (do
- (try
- (do)
- (catch $e-i32
- ;; Expressions containing a pop should NOT be taken out and folded.
- (drop (pop i32))
- (drop (i32.const 111))
- (drop (i32.const 222))
- (drop (i32.const 333))
- (unreachable)
- )
- )
- )
- (catch $e-i32
- (drop (pop i32))
- (drop (i32.const 111))
- (drop (i32.const 222))
- (drop (i32.const 333))
- (unreachable)
- )
- )
- )
-
- (func $foo)
- (func $try-call-optimize-terminating-tails (result i32)
- (try
- (do
- ;; Expressions that can throw should NOT be taken out of 'try' scope.
- (call $foo)
- (call $foo)
- (call $foo)
- (call $foo)
- (return (i32.const 0))
- )
- (catch_all
- (call $foo)
- (call $foo)
- (call $foo)
- (call $foo)
- (return (i32.const 0))
- )
- )
- (i32.const 0)
- )
-
- (func $try-call-optimize-expression-tails
- (block $x
- (try
- (do
- ;; Expressions that can throw should NOT be taken out of 'try' scope.
- (call $foo)
- (call $foo)
- (call $foo)
- (br $x)
- )
- (catch_all
- (call $foo)
- (call $foo)
- (call $foo)
- (br $x)
- )
- )
- (unreachable)
- )
- )
)
diff --git a/test/passes/remove-unused-names_optimize-instructions_all-features.txt b/test/passes/remove-unused-names_optimize-instructions_all-features.txt
deleted file mode 100644
index cf1e44132..000000000
--- a/test/passes/remove-unused-names_optimize-instructions_all-features.txt
+++ /dev/null
@@ -1,125 +0,0 @@
-(module
- (type $none_=>_none (func))
- (type $i32_=>_none (func (param i32)))
- (event $e (attr 0) (param i32))
- (func $dummy
- (nop)
- )
- (func $getFallthrough
- (local $x0 i32)
- (local $x1 i32)
- (local $x2 i32)
- (local $x3 i32)
- (local $x4 i32)
- (local.set $x0
- (try (result i32)
- (do
- (i32.const 1)
- )
- (catch_all
- (i32.const 3)
- )
- )
- )
- (drop
- (local.get $x0)
- )
- (local.set $x1
- (try (result i32)
- (do
- (call $dummy)
- (i32.const 1)
- )
- (catch_all
- (i32.const 3)
- )
- )
- )
- (drop
- (i32.and
- (local.get $x1)
- (i32.const 7)
- )
- )
- (local.set $x2
- (try (result i32)
- (do
- (try
- (do
- (throw $e
- (i32.const 0)
- )
- )
- (catch $e
- (drop
- (pop i32)
- )
- )
- )
- (i32.const 1)
- )
- (catch $e
- (drop
- (pop i32)
- )
- (i32.const 3)
- )
- )
- )
- (drop
- (i32.and
- (local.get $x2)
- (i32.const 7)
- )
- )
- (local.set $x3
- (try (result i32)
- (do
- (try
- (do
- (throw $e
- (i32.const 0)
- )
- )
- (catch_all
- (nop)
- )
- )
- (i32.const 1)
- )
- (catch_all
- (i32.const 3)
- )
- )
- )
- (drop
- (local.get $x3)
- )
- (local.set $x4
- (try (result i32)
- (do
- (try
- (do
- (nop)
- )
- (catch_all
- (throw $e
- (i32.const 0)
- )
- )
- )
- (i32.const 1)
- )
- (catch_all
- (i32.const 3)
- )
- )
- )
- (drop
- (i32.and
- (local.get $x4)
- (i32.const 7)
- )
- )
- )
-)
diff --git a/test/passes/remove-unused-names_optimize-instructions_all-features.wast b/test/passes/remove-unused-names_optimize-instructions_all-features.wast
deleted file mode 100644
index e08c42169..000000000
--- a/test/passes/remove-unused-names_optimize-instructions_all-features.wast
+++ /dev/null
@@ -1,101 +0,0 @@
-(module
- (func $dummy)
- (event $e (attr 0) (param i32))
-
- (func $getFallthrough ;; unit tests for Properties::getFallthrough
- (local $x0 i32)
- (local $x1 i32)
- (local $x2 i32)
- (local $x3 i32)
- (local $x4 i32)
-
- ;; try - try body does not throw, can
- (local.set $x0
- (try (result i32)
- (do
- (i32.const 1)
- )
- (catch_all
- (i32.const 3)
- )
- )
- )
- (drop (i32.and (local.get $x0) (i32.const 7)))
-
- ;; try - try body may throw, can't
- (local.set $x1
- (try (result i32)
- (do
- (call $dummy)
- (i32.const 1)
- )
- (catch_all
- (i32.const 3)
- )
- )
- )
- (drop (i32.and (local.get $x1) (i32.const 7)))
-
- ;; nested try - inner try may throw and may not be caught by inner catch,
- ;; can't
- (local.set $x2
- (try (result i32)
- (do
- (try
- (do
- (throw $e (i32.const 0))
- )
- (catch $e
- (drop (pop i32))
- )
- )
- (i32.const 1)
- )
- (catch $e
- (drop (pop i32))
- (i32.const 3)
- )
- )
- )
- (drop (i32.and (local.get $x2) (i32.const 7)))
-
- ;; nested try - inner try may throw but will be caught by inner catch_all,
- ;; can
- (local.set $x3
- (try (result i32)
- (do
- (try
- (do
- (throw $e (i32.const 0))
- )
- (catch_all)
- )
- (i32.const 1)
- )
- (catch_all
- (i32.const 3)
- )
- )
- )
- (drop (i32.and (local.get $x3) (i32.const 7)))
-
- ;; nested try - inner catch_all may throw, can't
- (local.set $x4
- (try (result i32)
- (do
- (try
- (do)
- (catch_all
- (throw $e (i32.const 0))
- )
- )
- (i32.const 1)
- )
- (catch_all
- (i32.const 3)
- )
- )
- )
- (drop (i32.and (local.get $x4) (i32.const 7)))
- )
-)
diff --git a/test/passes/rse_all-features.txt b/test/passes/rse_all-features.txt
index 1594425cf..8ad883d9f 100644
--- a/test/passes/rse_all-features.txt
+++ b/test/passes/rse_all-features.txt
@@ -3,8 +3,6 @@
(type $i32_=>_none (func (param i32)))
(type $i32_i32_=>_none (func (param i32 i32)))
(type $i32_f64_=>_none (func (param i32 f64)))
- (event $e (attr 0) (param i32))
- (event $e2 (attr 0) (param))
(func $basic (param $x i32) (param $y f64)
(local $a f32)
(local $b i64)
@@ -476,254 +474,4 @@
)
)
)
- (func $try1
- (local $x i32)
- (try $try
- (do
- (nop)
- )
- (catch_all
- (local.set $x
- (i32.const 1)
- )
- )
- )
- (local.set $x
- (i32.const 1)
- )
- )
- (func $try2
- (local $x i32)
- (try $try
- (do
- (throw $e
- (i32.const 0)
- )
- (local.set $x
- (i32.const 1)
- )
- )
- (catch_all
- (nop)
- )
- )
- (local.set $x
- (i32.const 1)
- )
- )
- (func $try3
- (local $x i32)
- (try $try
- (do
- (throw $e
- (i32.const 0)
- )
- )
- (catch_all
- (local.set $x
- (i32.const 1)
- )
- )
- )
- (drop
- (i32.const 1)
- )
- )
- (func $foo
- (nop)
- )
- (func $try4
- (local $x i32)
- (try $try
- (do
- (call $foo)
- (local.set $x
- (i32.const 1)
- )
- )
- (catch_all
- (nop)
- )
- )
- (local.set $x
- (i32.const 1)
- )
- )
- (func $try5
- (local $x i32)
- (try $try
- (do
- (local.set $x
- (i32.const 1)
- )
- (call $foo)
- )
- (catch_all
- (nop)
- )
- )
- (drop
- (i32.const 1)
- )
- )
- (func $nested-try1
- (local $x i32)
- (try $try
- (do
- (try $l0
- (do
- (throw $e
- (i32.const 0)
- )
- )
- (catch_all
- (rethrow $l0)
- )
- )
- )
- (catch_all
- (local.set $x
- (i32.const 1)
- )
- )
- )
- (drop
- (i32.const 1)
- )
- )
- (func $nested-try2
- (local $x i32)
- (try $try
- (do
- (try $l0
- (do
- (throw $e
- (i32.const 0)
- )
- )
- (catch_all
- (local.set $x
- (i32.const 1)
- )
- (rethrow $l0)
- )
- )
- )
- (catch_all
- (nop)
- )
- )
- (drop
- (i32.const 1)
- )
- )
- (func $nested-try3
- (local $x i32)
- (try $try
- (do
- (try $l0
- (do
- (throw $e
- (i32.const 0)
- )
- )
- (catch $e
- (drop
- (pop i32)
- )
- (local.set $x
- (i32.const 1)
- )
- (rethrow $l0)
- )
- )
- )
- (catch_all
- (nop)
- )
- )
- (local.set $x
- (i32.const 1)
- )
- )
- (func $nested-catch1
- (local $x i32)
- (try $try
- (do
- (throw $e
- (i32.const 0)
- )
- )
- (catch $e
- (drop
- (pop i32)
- )
- )
- (catch $e2
- (try $try6
- (do
- (throw $e
- (i32.const 0)
- )
- )
- (catch $e
- (drop
- (pop i32)
- )
- )
- (catch $e2
- (local.set $x
- (i32.const 1)
- )
- )
- )
- )
- )
- (local.set $x
- (i32.const 1)
- )
- )
- (func $nested-catch2
- (local $x i32)
- (try $try
- (do
- (throw $e
- (i32.const 0)
- )
- )
- (catch $e
- (drop
- (pop i32)
- )
- (local.set $x
- (i32.const 1)
- )
- )
- (catch_all
- (try $try7
- (do
- (throw $e
- (i32.const 0)
- )
- )
- (catch $e
- (drop
- (pop i32)
- )
- (local.set $x
- (i32.const 1)
- )
- )
- (catch_all
- (local.set $x
- (i32.const 1)
- )
- )
- )
- )
- )
- (drop
- (i32.const 1)
- )
- )
)
diff --git a/test/passes/rse_all-features.wast b/test/passes/rse_all-features.wast
index 8192ecea1..8700c232c 100644
--- a/test/passes/rse_all-features.wast
+++ b/test/passes/rse_all-features.wast
@@ -286,192 +286,4 @@
)
)
)
-
- (event $e (attr 0) (param i32))
- (event $e2 (attr 0))
- (func $try1
- (local $x i32)
- (try
- (do)
- (catch_all
- (local.set $x (i32.const 1))
- )
- )
- ;; try will not throw. So this should NOT be dropped
- (local.set $x (i32.const 1))
- )
- (func $try2
- (local $x i32)
- (try
- (do
- (throw $e (i32.const 0))
- (local.set $x (i32.const 1))
- )
- (catch_all)
- )
- ;; local.set is after 'throw' so it will not run. This should NOT be
- ;; dropped.
- (local.set $x (i32.const 1))
- )
- (func $try3
- (local $x i32)
- (try
- (do
- (throw $e (i32.const 0))
- )
- (catch_all
- (local.set $x (i32.const 1))
- )
- )
- ;; try body will throw and catch_all contains the same local.set. This
- ;; should be dropped.
- (local.set $x (i32.const 1))
- )
- (func $foo)
- (func $try4
- (local $x i32)
- (try
- (do
- (call $foo)
- (local.set $x (i32.const 1))
- )
- (catch_all)
- )
- ;; (call $foo) may throw and the local.set may not run, so this should NOT
- ;; be dropped
- (local.set $x (i32.const 1))
- )
- (func $try5
- (local $x i32)
- (try
- (do
- (local.set $x (i32.const 1))
- (call $foo)
- )
- (catch_all)
- )
- ;; Even if (call $foo) throws, local.set runs before it, so this should be
- ;; dropped
- (local.set $x (i32.const 1))
- )
- (func $nested-try1
- (local $x i32)
- (try
- (do
- (try $l0
- (do
- (throw $e (i32.const 0))
- )
- (catch_all
- (rethrow $l0)
- )
- )
- )
- (catch_all
- (local.set $x (i32.const 1))
- )
- )
- ;; The exception is caught by the inner catch_all and rethrown and again
- ;; caught by the outer catch_all, which runs the local.set. So this should
- ;; be dropped.
- (local.set $x (i32.const 1))
- )
- (func $nested-try2
- (local $x i32)
- (try
- (do
- (try $l0
- (do
- (throw $e (i32.const 0))
- )
- (catch_all
- (local.set $x (i32.const 1))
- (rethrow $l0)
- )
- )
- )
- (catch_all)
- )
- ;; The exception is caught by the inner catch_all, which runs the local.set,
- ;; so this should be dropped
- (local.set $x (i32.const 1))
- )
- (func $nested-try3
- (local $x i32)
- (try
- (do
- (try $l0
- (do
- (throw $e (i32.const 0))
- )
- (catch $e
- (drop (pop i32))
- (local.set $x (i32.const 1))
- (rethrow $l0)
- )
- )
- )
- (catch_all)
- )
- ;; Unlike nested-try2, the exception may not be caught by the inner catch,
- ;; so the local.set may not run. So this should NOT be dropped.
- (local.set $x (i32.const 1))
- )
- (func $nested-catch1
- (local $x i32)
- (try
- (do
- (throw $e (i32.const 0))
- )
- (catch $e
- (drop (pop i32))
- )
- (catch $e2
- (try
- (do
- (throw $e (i32.const 0))
- )
- (catch $e
- (drop (pop i32))
- )
- (catch $e2
- (local.set $x (i32.const 1))
- )
- )
- )
- )
- ;; This should NOT be dropped because the exception might not be caught by
- ;; the inner catches, and the local.set above us may not have run, and
- ;; other possible code paths do not even set the local.
- (local.set $x (i32.const 1))
- )
- (func $nested-catch2
- (local $x i32)
- (try
- (do
- (throw $e (i32.const 0))
- )
- (catch $e
- (drop (pop i32))
- (local.set $x (i32.const 1))
- )
- (catch_all
- (try
- (do
- (throw $e (i32.const 0))
- )
- (catch $e
- (drop (pop i32))
- (local.set $x (i32.const 1))
- )
- (catch_all
- (local.set $x (i32.const 1))
- )
- )
- )
- )
- ;; This should be dropped because the exception is guaranteed to be caught
- ;; by one of the catches and it will set the local to 1.
- (local.set $x (i32.const 1))
- )
)
diff --git a/test/passes/simplify-locals_all-features.txt b/test/passes/simplify-locals_all-features.txt
index 0cf412863..de387c27b 100644
--- a/test/passes/simplify-locals_all-features.txt
+++ b/test/passes/simplify-locals_all-features.txt
@@ -1895,92 +1895,6 @@
)
)
(module
- (type $none_=>_none (func))
- (type $i32_=>_none (func (param i32)))
- (type $i32_i32_=>_none (func (param i32 i32)))
- (type $none_=>_i32 (func (result i32)))
- (event $e-i32 (attr 0) (param i32))
- (func $foo (param $0 i32) (param $1 i32)
- (nop)
- )
- (func $pop-cannot-be-sinked
- (local $0 i32)
- (try $try
- (do
- (nop)
- )
- (catch $e-i32
- (local.set $0
- (pop i32)
- )
- (call $foo
- (i32.const 3)
- (local.get $0)
- )
- )
- )
- )
- (func $pop-within-catch-can-be-sinked
- (local $0 i32)
- (try $try
- (do
- (nop)
- )
- (catch_all
- (nop)
- (call $foo
- (i32.const 3)
- (try $try0 (result i32)
- (do
- (i32.const 0)
- )
- (catch $e-i32
- (pop i32)
- )
- )
- )
- )
- )
- )
- (func $bar (result i32)
- (i32.const 3)
- )
- (func $call-cannot-be-sinked-into-try
- (local $0 i32)
- (local.set $0
- (call $bar)
- )
- (try $try
- (do
- (drop
- (local.get $0)
- )
- )
- (catch $e-i32
- (drop
- (pop i32)
- )
- )
- )
- )
- (func $non-call-can-be-sinked-into-try
- (local $0 i32)
- (nop)
- (try $try
- (do
- (drop
- (i32.const 3)
- )
- )
- (catch $e-i32
- (drop
- (pop i32)
- )
- )
- )
- )
-)
-(module
(type $none_=>_i32 (func (result i32)))
(memory $0 (shared 1 1))
(data "data")
diff --git a/test/passes/simplify-locals_all-features.wast b/test/passes/simplify-locals_all-features.wast
index d37af9b6d..7d153efd9 100644
--- a/test/passes/simplify-locals_all-features.wast
+++ b/test/passes/simplify-locals_all-features.wast
@@ -1671,77 +1671,6 @@
(local.get $1)
)
)
-(module
- (event $e-i32 (attr 0) (param i32))
- (func $foo (param i32 i32))
- (func $pop-cannot-be-sinked (local $0 i32)
- (try
- (do)
- (catch $e-i32
- ;; This (local.set $0) of (pop i32) cannot be sunk to (local.get $0)
- ;; below, because the pop should follow right after 'catch'.
- (local.set $0 (pop i32))
- (call $foo
- (i32.const 3)
- (local.get $0)
- )
- )
- )
- )
-
- (func $pop-within-catch-can-be-sinked (local $0 i32)
- (try
- (do)
- (catch_all
- ;; This whole 'try' body can be sinked to eliminate local.set /
- ;; local.get. Even though it contains a pop, it is enclosed within
- ;; try-catch, so it is OK.
- (local.set $0
- (try (result i32)
- (do (i32.const 0))
- (catch $e-i32 (pop i32))
- )
- )
- (call $foo
- (i32.const 3)
- (local.get $0)
- )
- )
- )
- )
-
- (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 $e-i32
- (drop (pop i32))
- )
- )
- )
-
- (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 $e-i32
- (drop (pop i32))
- )
- )
- )
-)
;; data.drop has global side effects
(module
(memory $0 (shared 1 1))
diff --git a/test/passes/vacuum_all-features.txt b/test/passes/vacuum_all-features.txt
index 3dd051992..b95959552 100644
--- a/test/passes/vacuum_all-features.txt
+++ b/test/passes/vacuum_all-features.txt
@@ -436,60 +436,6 @@
)
(module
(type $none_=>_none (func))
- (type $i32_=>_none (func (param i32)))
- (event $e (attr 0) (param i32))
- (event $e2 (attr 0) (param i32))
- (func $try-test
- (nop)
- )
- (func $inner-try-catch_all-test
- (local $0 i32)
- (try $try0
- (do
- (throw $e
- (i32.const 0)
- )
- )
- (catch_all
- (local.set $0
- (i32.const 1)
- )
- )
- )
- )
- (func $inner-try-catch-test
- (local $0 i32)
- (try $try
- (do
- (try $try1
- (do
- (throw $e2
- (i32.const 0)
- )
- )
- (catch $e
- (drop
- (pop i32)
- )
- (local.set $0
- (i32.const 1)
- )
- )
- )
- )
- (catch $e
- (drop
- (pop i32)
- )
- )
- )
- )
- (func $br-in-catch
- (unreachable)
- )
-)
-(module
- (type $none_=>_none (func))
(func $foo
(nop)
)
diff --git a/test/passes/vacuum_all-features.wast b/test/passes/vacuum_all-features.wast
index c074fe234..8a6d52022 100644
--- a/test/passes/vacuum_all-features.wast
+++ b/test/passes/vacuum_all-features.wast
@@ -797,79 +797,6 @@
)
(module
- (event $e (attr 0) (param i32))
- (event $e2 (attr 0) (param i32))
- ;; When try body does not throw, try-body can be replaced with the try body
- (func $try-test
- (try
- (do
- (drop (i32.const 0))
- )
- (catch $e
- (drop (pop i32))
- )
- )
- )
-
- ;; The exception thrown in the inner try is caught by the inner catch_all, so
- ;; the outer try body does not throw and the outer try-catch can be removed
- (func $inner-try-catch_all-test (local $0 i32)
- (try
- (do
- (try
- (do
- (throw $e (i32.const 0))
- )
- (catch_all
- (local.set $0 (i32.const 1))
- )
- )
- )
- (catch $e
- (drop (pop i32))
- )
- )
- )
-
- ;; The exception thrown in the inner try will not be caught by the inner
- ;; catch, so the outer try-catch cannot be removed
- (func $inner-try-catch-test (local $0 i32)
- (try
- (do
- (try
- (do
- (throw $e2 (i32.const 0))
- )
- (catch $e
- (drop (pop i32))
- (local.set $0 (i32.const 1))
- )
- )
- )
- (catch $e
- (drop (pop i32))
- )
- )
- )
-
- ;; When catch body is removed, the removal of 'br' inside the catch body
- ;; should be propagated up to the outer block, so that its type will be
- ;; correctly updated to unreachable.
- (func $br-in-catch
- (block $label$1
- (try
- (do
- (unreachable)
- )
- (catch $e
- (drop (pop i32))
- (br $label$1)
- )
- )
- )
- )
-)
-(module
(type $A (struct (field (mut i32))))
(func $foo
(drop