From cf14a9fa9cd6f99ef78a5ffa70cfcb024a524919 Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Tue, 30 Jan 2024 17:26:39 -0800 Subject: [EH] Change translator option name (#6259) The previous name feels too verbose and unwieldy. This also removes the "new-to-old EH" placeholder. I think it'd be better to add it back when it is actually added. --- test/lit/help/wasm-opt.test | 2 +- test/lit/help/wasm2js.test | 2 +- test/lit/passes/translate-eh-old-to-new.wast | 1479 -------------------------- test/lit/passes/translate-to-new-eh.wast | 1479 ++++++++++++++++++++++++++ 4 files changed, 1481 insertions(+), 1481 deletions(-) delete mode 100644 test/lit/passes/translate-eh-old-to-new.wast create mode 100644 test/lit/passes/translate-to-new-eh.wast (limited to 'test') diff --git a/test/lit/help/wasm-opt.test b/test/lit/help/wasm-opt.test index 07d218007..fc33fce8d 100644 --- a/test/lit/help/wasm-opt.test +++ b/test/lit/help/wasm-opt.test @@ -486,7 +486,7 @@ ;; 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: --translate-to-new-eh translate old EH instructions to ;; CHECK-NEXT: new ones ;; CHECK-NEXT: ;; CHECK-NEXT: --trap-mode-clamp replace trapping operations with diff --git a/test/lit/help/wasm2js.test b/test/lit/help/wasm2js.test index e81d07718..7db564101 100644 --- a/test/lit/help/wasm2js.test +++ b/test/lit/help/wasm2js.test @@ -445,7 +445,7 @@ ;; 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: --translate-to-new-eh translate old EH instructions to ;; CHECK-NEXT: new ones ;; CHECK-NEXT: ;; CHECK-NEXT: --trap-mode-clamp replace trapping operations with diff --git a/test/lit/passes/translate-eh-old-to-new.wast b/test/lit/passes/translate-eh-old-to-new.wast deleted file mode 100644 index 014661b27..000000000 --- a/test/lit/passes/translate-eh-old-to-new.wast +++ /dev/null @@ -1,1479 +0,0 @@ -;; 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 (tuple 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 (tuple 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 (tuple 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 (tuple i32 i64)) - ;; CHECK-NEXT: (local $2 (tuple 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 (tuple 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 (tuple 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 (tuple 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 (tuple 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 (tuple i32 i64)) - ;; CHECK-NEXT: (local $2 (tuple 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 (tuple 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 (tuple 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 (tuple 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 (tuple 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 (tuple i32 i64)) - ;; CHECK-NEXT: (local $2 (tuple 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 (tuple 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 (tuple i32 i64)) - ;; CHECK-NEXT: (local $3 (tuple i32 exnref)) - ;; CHECK-NEXT: (local $4 (tuple 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 (tuple 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) - ) - ) -) diff --git a/test/lit/passes/translate-to-new-eh.wast b/test/lit/passes/translate-to-new-eh.wast new file mode 100644 index 000000000..da429bea4 --- /dev/null +++ b/test/lit/passes/translate-to-new-eh.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-to-new-eh -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 (tuple 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 (tuple 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 (tuple 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 (tuple i32 i64)) + ;; CHECK-NEXT: (local $2 (tuple 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 (tuple 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 (tuple 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 (tuple 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 (tuple 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 (tuple i32 i64)) + ;; CHECK-NEXT: (local $2 (tuple 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 (tuple 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 (tuple 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 (tuple 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 (tuple 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 (tuple i32 i64)) + ;; CHECK-NEXT: (local $2 (tuple 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 (tuple 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 (tuple i32 i64)) + ;; CHECK-NEXT: (local $3 (tuple i32 exnref)) + ;; CHECK-NEXT: (local $4 (tuple 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 (tuple 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) + ) + ) +) -- cgit v1.2.3