diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/lit/help/wasm-opt.test | 3 | ||||
-rw-r--r-- | test/lit/help/wasm2js.test | 3 | ||||
-rw-r--r-- | test/lit/passes/translate-eh-old-to-new.wast | 1479 |
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) + ) + ) +) |