summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/lit/help/wasm-opt.test3
-rw-r--r--test/lit/help/wasm2js.test3
-rw-r--r--test/lit/passes/translate-eh-old-to-new.wast1479
3 files changed, 1485 insertions, 0 deletions
diff --git a/test/lit/help/wasm-opt.test b/test/lit/help/wasm-opt.test
index 132296d5b..07d218007 100644
--- a/test/lit/help/wasm-opt.test
+++ b/test/lit/help/wasm-opt.test
@@ -486,6 +486,9 @@
;; CHECK-NEXT:
;; CHECK-NEXT: --symbolmap (alias for print-function-map)
;; CHECK-NEXT:
+;; CHECK-NEXT: --translate-eh-old-to-new translate old EH instructions to
+;; CHECK-NEXT: new ones
+;; CHECK-NEXT:
;; CHECK-NEXT: --trap-mode-clamp replace trapping operations with
;; CHECK-NEXT: clamping semantics
;; CHECK-NEXT:
diff --git a/test/lit/help/wasm2js.test b/test/lit/help/wasm2js.test
index 1d378f0ad..e81d07718 100644
--- a/test/lit/help/wasm2js.test
+++ b/test/lit/help/wasm2js.test
@@ -445,6 +445,9 @@
;; CHECK-NEXT:
;; CHECK-NEXT: --symbolmap (alias for print-function-map)
;; CHECK-NEXT:
+;; CHECK-NEXT: --translate-eh-old-to-new translate old EH instructions to
+;; CHECK-NEXT: new ones
+;; CHECK-NEXT:
;; CHECK-NEXT: --trap-mode-clamp replace trapping operations with
;; CHECK-NEXT: clamping semantics
;; CHECK-NEXT:
diff --git a/test/lit/passes/translate-eh-old-to-new.wast b/test/lit/passes/translate-eh-old-to-new.wast
new file mode 100644
index 000000000..b012a8536
--- /dev/null
+++ b/test/lit/passes/translate-eh-old-to-new.wast
@@ -0,0 +1,1479 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
+;; RUN: wasm-opt %s -all --translate-eh-old-to-new -S -o - | filecheck %s
+
+(module
+ ;; CHECK: (type $0 (func (result i32 i64)))
+
+ ;; CHECK: (type $1 (func))
+
+ ;; CHECK: (type $2 (func (result i32)))
+
+ ;; CHECK: (type $3 (func (result i32 exnref)))
+
+ ;; CHECK: (type $4 (func (result i32 i64 exnref)))
+
+ ;; CHECK: (type $5 (func (param i32)))
+
+ ;; CHECK: (type $6 (func (param i32 i64)))
+
+ ;; CHECK: (tag $e-empty)
+ (tag $e-empty)
+ ;; CHECK: (tag $e-i32 (param i32))
+ (tag $e-i32 (param i32))
+ ;; CHECK: (tag $e-i32-i64 (param i32 i64))
+ (tag $e-i32-i64 (param i32 i64))
+
+ ;; CHECK: (func $foo (type $1)
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ (func $foo)
+ ;; CHECK: (func $bar (type $1)
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ (func $bar)
+ ;; CHECK: (func $baz (type $1)
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ (func $baz)
+
+ ;; ---------------------------------------------------------------------------
+ ;; Basic tests for all combinations of try body's type (none, single, and
+ ;; tuple) and the catch's tag type (none, single, and tuple) and with /
+ ;; without rethrows
+
+ ;; CHECK: (func $try-none-tag-none (type $1)
+ ;; CHECK-NEXT: (block $outer0
+ ;; CHECK-NEXT: (block $catch_all2
+ ;; CHECK-NEXT: (block $catch1
+ ;; CHECK-NEXT: (try_table (catch $e-empty $catch1) (catch_all $catch_all2)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $outer0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (br $outer0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call $bar)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try-none-tag-none
+ ;; try's type is none and catch's tag type is none
+ (try $l0
+ (do
+ (call $foo)
+ )
+ (catch $e-empty ;; converted to catch
+ (call $foo)
+ )
+ (catch_all ;; converted to catch_all
+ (call $bar)
+ )
+ )
+ )
+
+ ;; CHECK: (func $try-none-tag-none-with-rethrow (type $1)
+ ;; CHECK-NEXT: (local $0 exnref)
+ ;; CHECK-NEXT: (block $outer0
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (block $catch_all2 (result exnref)
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (block $catch1 (result exnref)
+ ;; CHECK-NEXT: (try_table (catch_ref $e-empty $catch1) (catch_all_ref $catch_all2)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $outer0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try-none-tag-none-with-rethrow
+ ;; try's type is none and catch's tag type is none, and there are rethrows
+ (try $l0
+ (do
+ (call $foo)
+ )
+ (catch $e-empty ;; converted to catch_ref, because of rethrow
+ (rethrow $l0)
+ )
+ (catch_all ;; converted to catch_all_ref, because of rethrow
+ (rethrow $l0)
+ )
+ )
+ )
+
+ ;; CHECK: (func $try-none-tag-single (type $1)
+ ;; CHECK-NEXT: (local $0 i32)
+ ;; CHECK-NEXT: (block $outer0
+ ;; CHECK-NEXT: (block $catch_all2
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (block $catch1 (result i32)
+ ;; CHECK-NEXT: (try_table (catch $e-i32 $catch1) (catch_all $catch_all2)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $outer0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $outer0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call $bar)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try-none-tag-single
+ ;; try's type is none and catch's tag type is single
+ (try $l0
+ (do
+ (call $foo)
+ )
+ (catch $e-i32
+ (drop
+ (pop i32)
+ )
+ )
+ (catch_all
+ (call $bar)
+ )
+ )
+ )
+
+ ;; CHECK: (func $try-none-tag-single-with-rethrow (type $1)
+ ;; CHECK-NEXT: (local $0 exnref)
+ ;; CHECK-NEXT: (local $1 i32)
+ ;; CHECK-NEXT: (local $2 (i32 exnref))
+ ;; CHECK-NEXT: (block $outer0
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (block $catch_all2 (result exnref)
+ ;; CHECK-NEXT: (local.set $2
+ ;; CHECK-NEXT: (block $catch1 (type $3) (result i32 exnref)
+ ;; CHECK-NEXT: (try_table (catch_ref $e-i32 $catch1) (catch_all_ref $catch_all2)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $outer0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $1
+ ;; CHECK-NEXT: (tuple.extract 2 0
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (tuple.extract 2 1
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try-none-tag-single-with-rethrow
+ ;; try's type is none and catch's tag type is single, and there are rethrows
+ (try $l0
+ (do
+ (call $foo)
+ )
+ (catch $e-i32
+ (drop
+ (pop i32)
+ )
+ (rethrow $l0)
+ )
+ (catch_all
+ (rethrow $l0)
+ )
+ )
+ )
+
+ ;; CHECK: (func $try-none-tag-tuple (type $1)
+ ;; CHECK-NEXT: (local $0 (i32 i64))
+ ;; CHECK-NEXT: (block $outer0
+ ;; CHECK-NEXT: (block $catch_all2
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (block $catch1 (type $0) (result i32 i64)
+ ;; CHECK-NEXT: (try_table (catch $e-i32-i64 $catch1) (catch_all $catch_all2)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $outer0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (tuple.drop 2
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $outer0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call $bar)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try-none-tag-tuple
+ ;; try's type is none and catch's tag type is tuple
+ (try $l0
+ (do
+ (call $foo)
+ )
+ (catch $e-i32-i64
+ (tuple.drop 2
+ (pop i32 i64)
+ )
+ )
+ (catch_all
+ (call $bar)
+ )
+ )
+ )
+
+ ;; CHECK: (func $try-none-tag-tuple-with-rethrow (type $1)
+ ;; CHECK-NEXT: (local $0 exnref)
+ ;; CHECK-NEXT: (local $1 (i32 i64))
+ ;; CHECK-NEXT: (local $2 (i32 i64 exnref))
+ ;; CHECK-NEXT: (block $outer0
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (block $catch_all2 (result exnref)
+ ;; CHECK-NEXT: (local.set $2
+ ;; CHECK-NEXT: (block $catch1 (type $4) (result i32 i64 exnref)
+ ;; CHECK-NEXT: (try_table (catch_ref $e-i32-i64 $catch1) (catch_all_ref $catch_all2)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $outer0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $1
+ ;; CHECK-NEXT: (tuple.make 2
+ ;; CHECK-NEXT: (tuple.extract 3 0
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (tuple.extract 3 1
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (tuple.extract 3 2
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (tuple.drop 2
+ ;; CHECK-NEXT: (local.get $1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try-none-tag-tuple-with-rethrow
+ ;; try's type is none and catch's tag type is tuple, and there are rethrows
+ (try $l0
+ (do
+ (call $foo)
+ )
+ (catch $e-i32-i64
+ (tuple.drop 2
+ (pop i32 i64)
+ )
+ (rethrow $l0)
+ )
+ (catch_all
+ (rethrow $l0)
+ )
+ )
+ )
+
+ ;; CHECK: (func $try-single-tag-none (type $2) (result i32)
+ ;; CHECK-NEXT: (block $outer0 (result i32)
+ ;; CHECK-NEXT: (block $catch_all2
+ ;; CHECK-NEXT: (block $catch1
+ ;; CHECK-NEXT: (br $outer0
+ ;; CHECK-NEXT: (try_table (result i32) (catch $e-empty $catch1) (catch_all $catch_all2)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $outer0
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try-single-tag-none (result i32)
+ ;; try's type is single and catch's tag type is none
+ (try $l0 (result i32)
+ (do
+ (call $foo)
+ (i32.const 0)
+ )
+ (catch $e-empty
+ (i32.const 1)
+ )
+ (catch_all
+ (i32.const 2)
+ )
+ )
+ )
+
+ ;; CHECK: (func $try-single-tag-none-with-rethrow (type $2) (result i32)
+ ;; CHECK-NEXT: (local $0 exnref)
+ ;; CHECK-NEXT: (block $outer0 (result i32)
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (block $catch_all2 (result exnref)
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (block $catch1 (result exnref)
+ ;; CHECK-NEXT: (br $outer0
+ ;; CHECK-NEXT: (try_table (result i32) (catch_ref $e-empty $catch1) (catch_all_ref $catch_all2)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try-single-tag-none-with-rethrow (result i32)
+ ;; try's type is single and catch's tag type is none, and there are rethrows
+ (try $l0 (result i32)
+ (do
+ (call $foo)
+ (i32.const 0)
+ )
+ (catch $e-empty
+ (rethrow $l0)
+ )
+ (catch_all
+ (rethrow $l0)
+ )
+ )
+ )
+
+ ;; CHECK: (func $try-single-tag-single (type $2) (result i32)
+ ;; CHECK-NEXT: (local $0 i32)
+ ;; CHECK-NEXT: (block $outer0 (result i32)
+ ;; CHECK-NEXT: (block $catch_all2
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (block $catch1 (result i32)
+ ;; CHECK-NEXT: (br $outer0
+ ;; CHECK-NEXT: (try_table (result i32) (catch $e-i32 $catch1) (catch_all $catch_all2)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $outer0
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try-single-tag-single (result i32)
+ ;; try's type is single and catch's tag type is single
+ (try $l0 (result i32)
+ (do
+ (call $foo)
+ (i32.const 0)
+ )
+ (catch $e-i32
+ (pop i32)
+ )
+ (catch_all
+ (i32.const 2)
+ )
+ )
+ )
+
+ ;; CHECK: (func $try-single-tag-single-with-rethrow (type $2) (result i32)
+ ;; CHECK-NEXT: (local $0 exnref)
+ ;; CHECK-NEXT: (local $1 i32)
+ ;; CHECK-NEXT: (local $2 (i32 exnref))
+ ;; CHECK-NEXT: (block $outer0 (result i32)
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (block $catch_all2 (result exnref)
+ ;; CHECK-NEXT: (local.set $2
+ ;; CHECK-NEXT: (block $catch1 (type $3) (result i32 exnref)
+ ;; CHECK-NEXT: (br $outer0
+ ;; CHECK-NEXT: (try_table (result i32) (catch_ref $e-i32 $catch1) (catch_all_ref $catch_all2)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $1
+ ;; CHECK-NEXT: (tuple.extract 2 0
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (tuple.extract 2 1
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $outer0
+ ;; CHECK-NEXT: (block (result i32)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try-single-tag-single-with-rethrow (result i32)
+ ;; try's type is single and catch's tag type is single, and there are
+ ;; rethrows
+ (try $l0 (result i32)
+ (do
+ (call $foo)
+ (i32.const 0)
+ )
+ (catch $e-i32
+ (drop
+ (pop i32)
+ )
+ (rethrow $l0)
+ )
+ (catch_all
+ (rethrow $l0)
+ )
+ )
+ )
+
+ ;; CHECK: (func $try-single-tag-tuple (type $2) (result i32)
+ ;; CHECK-NEXT: (local $0 (i32 i64))
+ ;; CHECK-NEXT: (block $outer0 (result i32)
+ ;; CHECK-NEXT: (block $catch_all2
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (block $catch1 (type $0) (result i32 i64)
+ ;; CHECK-NEXT: (br $outer0
+ ;; CHECK-NEXT: (try_table (result i32) (catch $e-i32-i64 $catch1) (catch_all $catch_all2)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $outer0
+ ;; CHECK-NEXT: (block (result i32)
+ ;; CHECK-NEXT: (tuple.drop 2
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try-single-tag-tuple (result i32)
+ ;; try's type is single and catch's tag type is tuple
+ (try $l0 (result i32)
+ (do
+ (call $foo)
+ (i32.const 0)
+ )
+ (catch $e-i32-i64
+ (tuple.drop 2
+ (pop i32 i64)
+ )
+ (i32.const 1)
+ )
+ (catch_all
+ (i32.const 2)
+ )
+ )
+ )
+
+ ;; CHECK: (func $try-single-tag-tuple-with-rethrow (type $2) (result i32)
+ ;; CHECK-NEXT: (local $0 exnref)
+ ;; CHECK-NEXT: (local $1 (i32 i64))
+ ;; CHECK-NEXT: (local $2 (i32 i64 exnref))
+ ;; CHECK-NEXT: (block $outer0 (result i32)
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (block $catch_all2 (result exnref)
+ ;; CHECK-NEXT: (local.set $2
+ ;; CHECK-NEXT: (block $catch1 (type $4) (result i32 i64 exnref)
+ ;; CHECK-NEXT: (br $outer0
+ ;; CHECK-NEXT: (try_table (result i32) (catch_ref $e-i32-i64 $catch1) (catch_all_ref $catch_all2)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $1
+ ;; CHECK-NEXT: (tuple.make 2
+ ;; CHECK-NEXT: (tuple.extract 3 0
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (tuple.extract 3 1
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (tuple.extract 3 2
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $outer0
+ ;; CHECK-NEXT: (block (result i32)
+ ;; CHECK-NEXT: (tuple.drop 2
+ ;; CHECK-NEXT: (local.get $1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try-single-tag-tuple-with-rethrow (result i32)
+ ;; try's type is single and catch's tag type is tuple, and there are
+ ;; rethrows
+ (try $l0 (result i32)
+ (do
+ (call $foo)
+ (i32.const 0)
+ )
+ (catch $e-i32-i64
+ (tuple.drop 2
+ (pop i32 i64)
+ )
+ (rethrow $l0)
+ )
+ (catch_all
+ (rethrow $l0)
+ )
+ )
+ )
+
+ ;; CHECK: (func $try-tuple-tag-none (type $0) (result i32 i64)
+ ;; CHECK-NEXT: (block $outer0 (type $0) (result i32 i64)
+ ;; CHECK-NEXT: (block $catch_all2
+ ;; CHECK-NEXT: (block $catch1
+ ;; CHECK-NEXT: (br $outer0
+ ;; CHECK-NEXT: (try_table (type $0) (result i32 i64) (catch $e-empty $catch1) (catch_all $catch_all2)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (tuple.make 2
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i64.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $outer0
+ ;; CHECK-NEXT: (tuple.make 2
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: (i64.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (tuple.make 2
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: (i64.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try-tuple-tag-none (result i32 i64)
+ ;; try's type is tuple and catch's tag type is none
+ (try $l0 (result i32 i64)
+ (do
+ (call $foo)
+ (tuple.make 2
+ (i32.const 0)
+ (i64.const 0)
+ )
+ )
+ (catch $e-empty
+ (tuple.make 2
+ (i32.const 1)
+ (i64.const 1)
+ )
+ )
+ (catch_all
+ (tuple.make 2
+ (i32.const 2)
+ (i64.const 0)
+ )
+ )
+ )
+ )
+
+ ;; CHECK: (func $try-tuple-tag-none-with-rethrow (type $0) (result i32 i64)
+ ;; CHECK-NEXT: (local $0 exnref)
+ ;; CHECK-NEXT: (block $outer0 (type $0) (result i32 i64)
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (block $catch_all2 (result exnref)
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (block $catch1 (result exnref)
+ ;; CHECK-NEXT: (br $outer0
+ ;; CHECK-NEXT: (try_table (type $0) (result i32 i64) (catch_ref $e-empty $catch1) (catch_all_ref $catch_all2)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (tuple.make 2
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i64.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try-tuple-tag-none-with-rethrow (result i32 i64)
+ ;; try's type is tuple and catch's tag type is none, and there are rethrows
+ (try $l0 (result i32 i64)
+ (do
+ (call $foo)
+ (tuple.make 2
+ (i32.const 0)
+ (i64.const 0)
+ )
+ )
+ (catch $e-empty
+ (rethrow $l0)
+ )
+ (catch_all
+ (rethrow $l0)
+ )
+ )
+ )
+
+ ;; CHECK: (func $try-tuple-tag-single (type $0) (result i32 i64)
+ ;; CHECK-NEXT: (local $0 i32)
+ ;; CHECK-NEXT: (block $outer0 (type $0) (result i32 i64)
+ ;; CHECK-NEXT: (block $catch_all2
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (block $catch1 (result i32)
+ ;; CHECK-NEXT: (br $outer0
+ ;; CHECK-NEXT: (try_table (type $0) (result i32 i64) (catch $e-i32 $catch1) (catch_all $catch_all2)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (tuple.make 2
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i64.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $outer0
+ ;; CHECK-NEXT: (tuple.make 2
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: (i64.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (tuple.make 2
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: (i64.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try-tuple-tag-single (result i32 i64)
+ ;; try's type is tuple and catch's tag type is single
+ (try $l0 (result i32 i64)
+ (do
+ (call $foo)
+ (tuple.make 2
+ (i32.const 0)
+ (i64.const 0)
+ )
+ )
+ (catch $e-i32
+ (tuple.make 2
+ (pop i32)
+ (i64.const 0)
+ )
+ )
+ (catch_all
+ (tuple.make 2
+ (i32.const 2)
+ (i64.const 2)
+ )
+ )
+ )
+ )
+
+ ;; CHECK: (func $try-tuple-tag-single-with-rethrow (type $0) (result i32 i64)
+ ;; CHECK-NEXT: (local $0 exnref)
+ ;; CHECK-NEXT: (local $1 i32)
+ ;; CHECK-NEXT: (local $2 (i32 exnref))
+ ;; CHECK-NEXT: (block $outer0 (type $0) (result i32 i64)
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (block $catch_all2 (result exnref)
+ ;; CHECK-NEXT: (local.set $2
+ ;; CHECK-NEXT: (block $catch1 (type $3) (result i32 exnref)
+ ;; CHECK-NEXT: (br $outer0
+ ;; CHECK-NEXT: (try_table (type $0) (result i32 i64) (catch_ref $e-i32 $catch1) (catch_all_ref $catch_all2)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (tuple.make 2
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i64.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $1
+ ;; CHECK-NEXT: (tuple.extract 2 0
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (tuple.extract 2 1
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $outer0
+ ;; CHECK-NEXT: (block (type $0) (result i32 i64)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try-tuple-tag-single-with-rethrow (result i32 i64)
+ ;; try's type is tuple and catch's tag type is single, and there are
+ ;; rethrows
+ (try $l0 (result i32 i64)
+ (do
+ (call $foo)
+ (tuple.make 2
+ (i32.const 0)
+ (i64.const 0)
+ )
+ )
+ (catch $e-i32
+ (drop
+ (pop i32)
+ )
+ (rethrow $l0)
+ )
+ (catch_all
+ (rethrow $l0)
+ )
+ )
+ )
+
+ ;; CHECK: (func $try-tuple-tag-tuple (type $0) (result i32 i64)
+ ;; CHECK-NEXT: (local $0 (i32 i64))
+ ;; CHECK-NEXT: (block $outer0 (type $0) (result i32 i64)
+ ;; CHECK-NEXT: (block $catch_all2
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (block $catch1 (type $0) (result i32 i64)
+ ;; CHECK-NEXT: (br $outer0
+ ;; CHECK-NEXT: (try_table (type $0) (result i32 i64) (catch $e-i32-i64 $catch1) (catch_all $catch_all2)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (tuple.make 2
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i64.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $outer0
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (tuple.make 2
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: (i64.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try-tuple-tag-tuple (result i32 i64)
+ ;; try's type is tuple and catch's tag type is tuple
+ (try $l0 (result i32 i64)
+ (do
+ (call $foo)
+ (tuple.make 2
+ (i32.const 0)
+ (i64.const 0)
+ )
+ )
+ (catch $e-i32-i64
+ (pop i32 i64)
+ )
+ (catch_all
+ (tuple.make 2
+ (i32.const 2)
+ (i64.const 2)
+ )
+ )
+ )
+ )
+
+ ;; CHECK: (func $try-tuple-tag-tuple-with-rethrow (type $0) (result i32 i64)
+ ;; CHECK-NEXT: (local $0 exnref)
+ ;; CHECK-NEXT: (local $1 (i32 i64))
+ ;; CHECK-NEXT: (local $2 (i32 i64 exnref))
+ ;; CHECK-NEXT: (block $outer0 (type $0) (result i32 i64)
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (block $catch_all2 (result exnref)
+ ;; CHECK-NEXT: (local.set $2
+ ;; CHECK-NEXT: (block $catch1 (type $4) (result i32 i64 exnref)
+ ;; CHECK-NEXT: (br $outer0
+ ;; CHECK-NEXT: (try_table (type $0) (result i32 i64) (catch_ref $e-i32-i64 $catch1) (catch_all_ref $catch_all2)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (tuple.make 2
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i64.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $1
+ ;; CHECK-NEXT: (tuple.make 2
+ ;; CHECK-NEXT: (tuple.extract 3 0
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (tuple.extract 3 1
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (tuple.extract 3 2
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $outer0
+ ;; CHECK-NEXT: (block (type $0) (result i32 i64)
+ ;; CHECK-NEXT: (tuple.drop 2
+ ;; CHECK-NEXT: (local.get $1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try-tuple-tag-tuple-with-rethrow (result i32 i64)
+ ;; try's type is tuple and catch's tag type is tuple, and there are
+ ;; rethrows
+ (try $l0 (result i32 i64)
+ (do
+ (call $foo)
+ (tuple.make 2
+ (i32.const 0)
+ (i64.const 0)
+ )
+ )
+ (catch $e-i32-i64
+ (tuple.drop 2
+ (pop i32 i64)
+ )
+ (rethrow $l0)
+ )
+ (catch_all
+ (rethrow $l0)
+ )
+ )
+ )
+
+ ;; ---------------------------------------------------------------------------
+ ;; More try-catch tests
+
+ ;; CHECK: (func $catchless-delegateless-try (type $1)
+ ;; CHECK-NEXT: (try_table
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $catchless-delegateless-try
+ (try
+ (do
+ (call $foo)
+ )
+ )
+ )
+
+ ;; CHECK: (func $multiple-catches-and-catch_all (type $1)
+ ;; CHECK-NEXT: (local $0 exnref)
+ ;; CHECK-NEXT: (local $1 i32)
+ ;; CHECK-NEXT: (local $2 (i32 i64))
+ ;; CHECK-NEXT: (local $3 (i32 exnref))
+ ;; CHECK-NEXT: (local $4 (i32 i64 exnref))
+ ;; CHECK-NEXT: (block $outer0
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (block $catch_all4 (result exnref)
+ ;; CHECK-NEXT: (local.set $4
+ ;; CHECK-NEXT: (block $catch3 (type $4) (result i32 i64 exnref)
+ ;; CHECK-NEXT: (local.set $3
+ ;; CHECK-NEXT: (block $catch2 (type $3) (result i32 exnref)
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (block $catch1 (result exnref)
+ ;; CHECK-NEXT: (try_table (catch_ref $e-empty $catch1) (catch_ref $e-i32 $catch2) (catch_ref $e-i32-i64 $catch3) (catch_all_ref $catch_all4)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $outer0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $1
+ ;; CHECK-NEXT: (tuple.extract 2 0
+ ;; CHECK-NEXT: (local.get $3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (tuple.extract 2 1
+ ;; CHECK-NEXT: (local.get $3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $2
+ ;; CHECK-NEXT: (tuple.make 2
+ ;; CHECK-NEXT: (tuple.extract 3 0
+ ;; CHECK-NEXT: (local.get $4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (tuple.extract 3 1
+ ;; CHECK-NEXT: (local.get $4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (tuple.extract 3 2
+ ;; CHECK-NEXT: (local.get $4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (tuple.drop 2
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $multiple-catches-and-catch_all
+ (try $l0
+ (do
+ (call $foo)
+ )
+ (catch $e-empty
+ (rethrow $l0)
+ )
+ (catch $e-i32
+ (drop
+ (pop i32)
+ )
+ (rethrow $l0)
+ )
+ (catch $e-i32-i64
+ (tuple.drop 2
+ (pop i32 i64)
+ )
+ (rethrow $l0)
+ )
+ (catch_all
+ (rethrow $l0)
+ )
+ )
+ )
+
+ ;; CHECK: (func $nested-catch-rethrows (type $1)
+ ;; CHECK-NEXT: (local $0 exnref)
+ ;; CHECK-NEXT: (local $1 exnref)
+ ;; CHECK-NEXT: (block $outer3
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (block $catch_all4 (result exnref)
+ ;; CHECK-NEXT: (try_table (catch_all_ref $catch_all4)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $outer3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block $outer0
+ ;; CHECK-NEXT: (local.set $1
+ ;; CHECK-NEXT: (block $catch2 (result exnref)
+ ;; CHECK-NEXT: (block $catch1
+ ;; CHECK-NEXT: (try_table (catch $e-empty $catch1) (catch_ref $e-empty $catch2)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $outer0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (local.get $1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $nested-catch-rethrows
+ (try $l0
+ (do
+ (call $foo)
+ )
+ (catch_all
+ (try $l1
+ (do
+ (call $foo)
+ )
+ ;; This catch will be converted to a 'catch' clause in a try_table,
+ ;; because the rethrow in this catch body does not refer to the
+ ;; current try
+ (catch $e-empty
+ (rethrow $l0)
+ )
+ ;; This catch will be converted to a 'catch_ref' clause in a
+ ;; try_table, because the rethrow in this catch body refers to the
+ ;; current try
+ (catch $e-empty
+ (rethrow $l1)
+ )
+ )
+ )
+ )
+ )
+
+ ;; ---------------------------------------------------------------------------
+ ;; try-delegate tests
+
+ ;; CHECK: (func $delegate-target-outer-try-none (type $1)
+ ;; CHECK-NEXT: (block $outer1
+ ;; CHECK-NEXT: (block $catch_all2
+ ;; CHECK-NEXT: (try_table (catch_all $catch_all2)
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (block $l00 (result exnref)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (try_table (catch_all_ref $l00)
+ ;; CHECK-NEXT: (call $bar)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call $baz)
+ ;; CHECK-NEXT: (br $outer1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $delegate-target-outer-try-none
+ ;; An inner try-delegate targets an outer try whose type is none
+ (try $l0
+ (do
+ (call $foo)
+ (try
+ (do
+ (call $bar)
+ )
+ (delegate $l0)
+ )
+ (call $baz)
+ )
+ (catch_all)
+ )
+ )
+
+ ;; CHECK: (func $multiple-delegates-target-outer-try-none (type $1)
+ ;; CHECK-NEXT: (block $outer1
+ ;; CHECK-NEXT: (block $catch_all2
+ ;; CHECK-NEXT: (try_table (catch_all $catch_all2)
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (block $l00 (result exnref)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (try_table (catch_all_ref $l00)
+ ;; CHECK-NEXT: (call $bar)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (try_table (catch_all_ref $l00)
+ ;; CHECK-NEXT: (call $bar)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call $baz)
+ ;; CHECK-NEXT: (br $outer1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $multiple-delegates-target-outer-try-none
+ ;; Multiple inner try-delegates target an outer try whose type is none
+ (try $l0
+ (do
+ (call $foo)
+ (try
+ (do
+ (call $bar)
+ )
+ (delegate $l0)
+ )
+ (try
+ (do
+ (call $bar)
+ )
+ (delegate $l0)
+ )
+ (call $baz)
+ )
+ (catch_all)
+ )
+ )
+
+ ;; CHECK: (func $delegate-target-outer-try-concrete (type $2) (result i32)
+ ;; CHECK-NEXT: (block $outer1 (result i32)
+ ;; CHECK-NEXT: (block $catch_all2
+ ;; CHECK-NEXT: (br $outer1
+ ;; CHECK-NEXT: (try_table (result i32) (catch_all $catch_all2)
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (block $l00 (result exnref)
+ ;; CHECK-NEXT: (br $outer1
+ ;; CHECK-NEXT: (block (result i32)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (try_table (result i32) (catch_all_ref $l00)
+ ;; CHECK-NEXT: (call $bar)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $delegate-target-outer-try-concrete (result i32)
+ ;; An inner try-delegate targets an outer try whose type is concrete
+ (try $l0 (result i32)
+ (do
+ (call $foo)
+ (try (result i32)
+ (do
+ (call $bar)
+ (i32.const 0)
+ )
+ (delegate $l0)
+ )
+ )
+ (catch_all
+ (i32.const 1)
+ )
+ )
+ )
+
+ ;; CHECK: (func $deletate-target-outer-try-unreachable (type $1)
+ ;; CHECK-NEXT: (try_table
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (block $l00 (result exnref)
+ ;; CHECK-NEXT: (try_table (catch_all_ref $l00)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (return)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $deletate-target-outer-try-unreachable
+ ;; An inner try-delegate targets an outer try whose body type is unreachable
+ ;; (due to a return). In this case we don't need an additional 'br' to an
+ ;; outer block.
+ (try $l0
+ (do
+ (try
+ (do
+ (call $foo)
+ )
+ (delegate $l0)
+ )
+ (return)
+ )
+ )
+ )
+
+ ;; CHECK: (func $delegate-target-caller-none (type $1)
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (block $__binaryen_delegate_caller_target0 (result exnref)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (try_table (catch_all_ref $__binaryen_delegate_caller_target0)
+ ;; CHECK-NEXT: (call $bar)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call $baz)
+ ;; CHECK-NEXT: (return)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $delegate-target-caller-none
+ ;; A try-delegate targets the caller whose type is none
+ (call $foo)
+ (try
+ (do
+ (call $bar)
+ )
+ (delegate 0)
+ )
+ (call $baz)
+ )
+
+ ;; CHECK: (func $multiple-delegates-target-caller-none (type $1)
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (block $__binaryen_delegate_caller_target0 (result exnref)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (try_table (catch_all_ref $__binaryen_delegate_caller_target0)
+ ;; CHECK-NEXT: (call $bar)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (try_table (catch_all_ref $__binaryen_delegate_caller_target0)
+ ;; CHECK-NEXT: (call $bar)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call $baz)
+ ;; CHECK-NEXT: (return)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $multiple-delegates-target-caller-none
+ ;; Multiple try-delegates target the caller whose type is none
+ (call $foo)
+ (try
+ (do
+ (call $bar)
+ )
+ (delegate 0)
+ )
+ (try
+ (do
+ (call $bar)
+ )
+ (delegate 0)
+ )
+ (call $baz)
+ )
+
+ ;; CHECK: (func $delegate-target-caller-concrete (type $2) (result i32)
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (block $__binaryen_delegate_caller_target0 (result exnref)
+ ;; CHECK-NEXT: (return
+ ;; CHECK-NEXT: (block (result i32)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (try_table (result i32) (catch_all_ref $__binaryen_delegate_caller_target0)
+ ;; CHECK-NEXT: (call $bar)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $delegate-target-caller-concrete (result i32)
+ ;; A try-delegate targets the caller whose type is concrete
+ (call $foo)
+ (try (result i32)
+ (do
+ (call $bar)
+ (i32.const 0)
+ )
+ (delegate 0)
+ )
+ )
+
+ ;; CHECK: (func $delegate-nested-more (type $1)
+ ;; CHECK-NEXT: (block $outer3
+ ;; CHECK-NEXT: (block $catch_all4
+ ;; CHECK-NEXT: (try_table (catch_all $catch_all4)
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (block $l00 (result exnref)
+ ;; CHECK-NEXT: (block $outer1
+ ;; CHECK-NEXT: (block $catch_all2
+ ;; CHECK-NEXT: (try_table (catch_all $catch_all2)
+ ;; CHECK-NEXT: (try_table (catch_all_ref $l00)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $outer1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $outer3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $delegate-nested-more
+ (try $l0
+ (do
+ (try
+ (do
+ (try
+ (do
+ (call $foo)
+ )
+ (delegate $l0)
+ )
+ )
+ (catch_all)
+ )
+ )
+ (catch_all)
+ )
+ )
+
+ ;; CHECK: (func $delegate-target-outer-try-delegate (type $1)
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (block $__binaryen_delegate_caller_target0 (result exnref)
+ ;; CHECK-NEXT: (block $outer2
+ ;; CHECK-NEXT: (try_table (catch_all_ref $__binaryen_delegate_caller_target0)
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (block $l01 (result exnref)
+ ;; CHECK-NEXT: (try_table (catch_all_ref $l01)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $outer2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (return)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $delegate-target-outer-try-delegate
+ ;; An inner try-delegate targets an outer try-delegate that targets the
+ ;; caller
+ (try $l0
+ (do
+ (try
+ (do
+ (call $foo)
+ )
+ (delegate $l0)
+ )
+ )
+ (delegate 0)
+ )
+ )
+
+ ;; CHECK: (func $delegate-target-outer-try-delegate-concrete (type $2) (result i32)
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (block $__binaryen_delegate_caller_target0 (result exnref)
+ ;; CHECK-NEXT: (return
+ ;; CHECK-NEXT: (block $outer2 (result i32)
+ ;; CHECK-NEXT: (try_table (catch_all_ref $__binaryen_delegate_caller_target0)
+ ;; CHECK-NEXT: (throw_ref
+ ;; CHECK-NEXT: (block $l01 (result exnref)
+ ;; CHECK-NEXT: (br $outer2
+ ;; CHECK-NEXT: (try_table (result i32) (catch_all_ref $l01)
+ ;; CHECK-NEXT: (call $foo)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $delegate-target-outer-try-delegate-concrete (result i32)
+ ;; An inner try-delegate targets an outer try-delegate that targets the
+ ;; caller, where the type of the try-delegates and the caller is concrete
+ (try $l0 (result i32)
+ (do
+ (try (result i32)
+ (do
+ (call $foo)
+ (i32.const 0)
+ )
+ (delegate $l0)
+ )
+ )
+ (delegate 0)
+ )
+ )
+)