| ;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. |
| ;; RUN: wasm-opt %s -all --translate-to-exnref -S -o - | filecheck %s |
| ;; RUN: wasm-opt %s -all --translate-to-exnref -S -o %t |
| ;; RUN: wasm-opt %t -all --optimize-level=3 --generate-stack-ir --optimize-stack-ir --print-stack-ir | filecheck %s --check-prefix STACKIR-OPT |
| |
| (module |
| ;; CHECK: (type $0 (func (result i32 i64))) |
| |
| ;; CHECK: (type $1 (func)) |
| |
| ;; CHECK: (type $2 (func (result i32))) |
| |
| ;; CHECK: (type $3 (func (result i32 (ref exn)))) |
| |
| ;; CHECK: (type $4 (func (result i32 i64 (ref exn)))) |
| |
| ;; CHECK: (type $5 (func (param i32))) |
| |
| ;; CHECK: (type $6 (func (param i32 i64))) |
| |
| ;; CHECK: (tag $e-empty (type $1)) |
| ;; STACKIR-OPT: (type $0 (func (result i32 i64))) |
| |
| ;; STACKIR-OPT: (type $1 (func)) |
| |
| ;; STACKIR-OPT: (type $2 (func (result i32))) |
| |
| ;; STACKIR-OPT: (type $3 (func (result i32 (ref exn)))) |
| |
| ;; STACKIR-OPT: (type $4 (func (result i32 i64 (ref exn)))) |
| |
| ;; STACKIR-OPT: (type $5 (func (param i32))) |
| |
| ;; STACKIR-OPT: (type $6 (func (param i32 i64))) |
| |
| ;; STACKIR-OPT: (tag $e-empty (type $1)) |
| (tag $e-empty) |
| ;; CHECK: (tag $e-i32 (type $5) (param i32)) |
| ;; STACKIR-OPT: (tag $e-i32 (type $5) (param i32)) |
| (tag $e-i32 (param i32)) |
| ;; CHECK: (tag $e-i32-i64 (type $6) (param i32 i64)) |
| ;; STACKIR-OPT: (tag $e-i32-i64 (type $6) (param i32 i64)) |
| (tag $e-i32-i64 (param i32 i64)) |
| |
| ;; CHECK: (func $foo (type $1) |
| ;; CHECK-NEXT: ) |
| ;; STACKIR-OPT: (func $foo (type $1) |
| ;; STACKIR-OPT-NEXT: ) |
| (func $foo) |
| ;; CHECK: (func $bar (type $1) |
| ;; CHECK-NEXT: ) |
| ;; STACKIR-OPT: (func $bar (type $1) |
| ;; STACKIR-OPT-NEXT: ) |
| (func $bar) |
| ;; CHECK: (func $baz (type $1) |
| ;; CHECK-NEXT: ) |
| ;; STACKIR-OPT: (func $baz (type $1) |
| ;; STACKIR-OPT-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: ) |
| ;; STACKIR-OPT: (func $try-none-tag-none (type $1) |
| ;; STACKIR-OPT-NEXT: block $outer0 |
| ;; STACKIR-OPT-NEXT: block $catch_all2 |
| ;; STACKIR-OPT-NEXT: block $catch1 |
| ;; STACKIR-OPT-NEXT: try_table (catch $e-empty $catch1) (catch_all $catch_all2) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: call $bar |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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 (ref exn)) |
| ;; CHECK-NEXT: (local.set $0 |
| ;; CHECK-NEXT: (block $catch1 (result (ref exn)) |
| ;; 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: ) |
| ;; STACKIR-OPT: (func $try-none-tag-none-with-rethrow (type $1) |
| ;; STACKIR-OPT-NEXT: (local $0 exnref) |
| ;; STACKIR-OPT-NEXT: block $outer0 |
| ;; STACKIR-OPT-NEXT: block $catch_all2 (result (ref exn)) |
| ;; STACKIR-OPT-NEXT: block $catch1 (result (ref exn)) |
| ;; STACKIR-OPT-NEXT: try_table (catch_ref $e-empty $catch1) (catch_all_ref $catch_all2) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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: ) |
| ;; STACKIR-OPT: (func $try-none-tag-single (type $1) |
| ;; STACKIR-OPT-NEXT: (local $0 i32) |
| ;; STACKIR-OPT-NEXT: block $outer0 |
| ;; STACKIR-OPT-NEXT: block $catch_all2 |
| ;; STACKIR-OPT-NEXT: block $catch1 (result i32) |
| ;; STACKIR-OPT-NEXT: try_table (catch $e-i32 $catch1) (catch_all $catch_all2) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: drop |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: call $bar |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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 (ref exn))) |
| ;; CHECK-NEXT: (block $outer0 |
| ;; CHECK-NEXT: (local.set $0 |
| ;; CHECK-NEXT: (block $catch_all2 (result (ref exn)) |
| ;; CHECK-NEXT: (local.set $2 |
| ;; CHECK-NEXT: (block $catch1 (type $3) (result i32 (ref exn)) |
| ;; 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: ) |
| ;; STACKIR-OPT: (func $try-none-tag-single-with-rethrow (type $1) |
| ;; STACKIR-OPT-NEXT: (local $0 exnref) |
| ;; STACKIR-OPT-NEXT: (local $1 i32) |
| ;; STACKIR-OPT-NEXT: (local $2 (tuple i32 (ref exn))) |
| ;; STACKIR-OPT-NEXT: block $outer0 |
| ;; STACKIR-OPT-NEXT: block $catch_all2 (result (ref exn)) |
| ;; STACKIR-OPT-NEXT: block $catch1 (type $3) (result i32 (ref exn)) |
| ;; STACKIR-OPT-NEXT: try_table (catch_ref $e-i32 $catch1) (catch_all_ref $catch_all2) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: local.set $2 |
| ;; STACKIR-OPT-NEXT: local.get $2 |
| ;; STACKIR-OPT-NEXT: tuple.extract 2 0 |
| ;; STACKIR-OPT-NEXT: local.get $2 |
| ;; STACKIR-OPT-NEXT: tuple.extract 2 1 |
| ;; STACKIR-OPT-NEXT: local.set $0 |
| ;; STACKIR-OPT-NEXT: drop |
| ;; STACKIR-OPT-NEXT: local.get $0 |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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: ) |
| ;; STACKIR-OPT: (func $try-none-tag-tuple (type $1) |
| ;; STACKIR-OPT-NEXT: (local $0 (tuple i32 i64)) |
| ;; STACKIR-OPT-NEXT: block $outer0 |
| ;; STACKIR-OPT-NEXT: block $catch_all2 |
| ;; STACKIR-OPT-NEXT: block $catch1 (type $0) (result i32 i64) |
| ;; STACKIR-OPT-NEXT: try_table (catch $e-i32-i64 $catch1) (catch_all $catch_all2) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: local.set $0 |
| ;; STACKIR-OPT-NEXT: local.get $0 |
| ;; STACKIR-OPT-NEXT: tuple.drop 2 |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: call $bar |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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 (ref exn))) |
| ;; CHECK-NEXT: (block $outer0 |
| ;; CHECK-NEXT: (local.set $0 |
| ;; CHECK-NEXT: (block $catch_all2 (result (ref exn)) |
| ;; CHECK-NEXT: (local.set $2 |
| ;; CHECK-NEXT: (block $catch1 (type $4) (result i32 i64 (ref exn)) |
| ;; 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: ) |
| ;; STACKIR-OPT: (func $try-none-tag-tuple-with-rethrow (type $1) |
| ;; STACKIR-OPT-NEXT: (local $0 exnref) |
| ;; STACKIR-OPT-NEXT: (local $1 (tuple i32 i64)) |
| ;; STACKIR-OPT-NEXT: (local $2 (tuple i32 i64 (ref exn))) |
| ;; STACKIR-OPT-NEXT: block $outer0 |
| ;; STACKIR-OPT-NEXT: block $catch_all2 (result (ref exn)) |
| ;; STACKIR-OPT-NEXT: block $catch1 (type $4) (result i32 i64 (ref exn)) |
| ;; STACKIR-OPT-NEXT: try_table (catch_ref $e-i32-i64 $catch1) (catch_all_ref $catch_all2) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: local.set $2 |
| ;; STACKIR-OPT-NEXT: local.get $2 |
| ;; STACKIR-OPT-NEXT: tuple.extract 3 0 |
| ;; STACKIR-OPT-NEXT: local.get $2 |
| ;; STACKIR-OPT-NEXT: tuple.extract 3 1 |
| ;; STACKIR-OPT-NEXT: tuple.make 2 |
| ;; STACKIR-OPT-NEXT: local.set $1 |
| ;; STACKIR-OPT-NEXT: local.get $2 |
| ;; STACKIR-OPT-NEXT: tuple.extract 3 2 |
| ;; STACKIR-OPT-NEXT: local.get $1 |
| ;; STACKIR-OPT-NEXT: tuple.drop 2 |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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: ) |
| ;; STACKIR-OPT: (func $try-single-tag-none (type $2) (result i32) |
| ;; STACKIR-OPT-NEXT: block $outer0 (result i32) |
| ;; STACKIR-OPT-NEXT: block $catch_all2 |
| ;; STACKIR-OPT-NEXT: block $catch1 |
| ;; STACKIR-OPT-NEXT: try_table (result i32) (catch $e-empty $catch1) (catch_all $catch_all2) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: i32.const 0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: i32.const 1 |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: i32.const 2 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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 (ref exn)) |
| ;; CHECK-NEXT: (local.set $0 |
| ;; CHECK-NEXT: (block $catch1 (result (ref exn)) |
| ;; 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: ) |
| ;; STACKIR-OPT: (func $try-single-tag-none-with-rethrow (type $2) (result i32) |
| ;; STACKIR-OPT-NEXT: (local $0 exnref) |
| ;; STACKIR-OPT-NEXT: block $outer0 (result i32) |
| ;; STACKIR-OPT-NEXT: block $catch_all2 (result (ref exn)) |
| ;; STACKIR-OPT-NEXT: block $catch1 (result (ref exn)) |
| ;; STACKIR-OPT-NEXT: try_table (result i32) (catch_ref $e-empty $catch1) (catch_all_ref $catch_all2) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: i32.const 0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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: ) |
| ;; STACKIR-OPT: (func $try-single-tag-single (type $2) (result i32) |
| ;; STACKIR-OPT-NEXT: (local $0 i32) |
| ;; STACKIR-OPT-NEXT: block $outer0 (result i32) |
| ;; STACKIR-OPT-NEXT: block $catch_all2 |
| ;; STACKIR-OPT-NEXT: block $catch1 (result i32) |
| ;; STACKIR-OPT-NEXT: try_table (result i32) (catch $e-i32 $catch1) (catch_all $catch_all2) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: i32.const 0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: i32.const 2 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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 (ref exn))) |
| ;; CHECK-NEXT: (block $outer0 (result i32) |
| ;; CHECK-NEXT: (local.set $0 |
| ;; CHECK-NEXT: (block $catch_all2 (result (ref exn)) |
| ;; CHECK-NEXT: (local.set $2 |
| ;; CHECK-NEXT: (block $catch1 (type $3) (result i32 (ref exn)) |
| ;; 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: ) |
| ;; STACKIR-OPT: (func $try-single-tag-single-with-rethrow (type $2) (result i32) |
| ;; STACKIR-OPT-NEXT: (local $0 exnref) |
| ;; STACKIR-OPT-NEXT: (local $1 i32) |
| ;; STACKIR-OPT-NEXT: (local $2 (tuple i32 (ref exn))) |
| ;; STACKIR-OPT-NEXT: block $outer0 (result i32) |
| ;; STACKIR-OPT-NEXT: block $catch_all2 (result (ref exn)) |
| ;; STACKIR-OPT-NEXT: block $catch1 (type $3) (result i32 (ref exn)) |
| ;; STACKIR-OPT-NEXT: try_table (result i32) (catch_ref $e-i32 $catch1) (catch_all_ref $catch_all2) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: i32.const 0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: local.set $2 |
| ;; STACKIR-OPT-NEXT: local.get $2 |
| ;; STACKIR-OPT-NEXT: tuple.extract 2 0 |
| ;; STACKIR-OPT-NEXT: local.get $2 |
| ;; STACKIR-OPT-NEXT: tuple.extract 2 1 |
| ;; STACKIR-OPT-NEXT: local.set $0 |
| ;; STACKIR-OPT-NEXT: drop |
| ;; STACKIR-OPT-NEXT: local.get $0 |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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: ) |
| ;; STACKIR-OPT: (func $try-single-tag-tuple (type $2) (result i32) |
| ;; STACKIR-OPT-NEXT: (local $0 (tuple i32 i64)) |
| ;; STACKIR-OPT-NEXT: block $outer0 (result i32) |
| ;; STACKIR-OPT-NEXT: block $catch_all2 |
| ;; STACKIR-OPT-NEXT: block $catch1 (type $0) (result i32 i64) |
| ;; STACKIR-OPT-NEXT: try_table (result i32) (catch $e-i32-i64 $catch1) (catch_all $catch_all2) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: i32.const 0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: local.set $0 |
| ;; STACKIR-OPT-NEXT: local.get $0 |
| ;; STACKIR-OPT-NEXT: tuple.drop 2 |
| ;; STACKIR-OPT-NEXT: i32.const 1 |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: i32.const 2 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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 (ref exn))) |
| ;; CHECK-NEXT: (block $outer0 (result i32) |
| ;; CHECK-NEXT: (local.set $0 |
| ;; CHECK-NEXT: (block $catch_all2 (result (ref exn)) |
| ;; CHECK-NEXT: (local.set $2 |
| ;; CHECK-NEXT: (block $catch1 (type $4) (result i32 i64 (ref exn)) |
| ;; 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: ) |
| ;; STACKIR-OPT: (func $try-single-tag-tuple-with-rethrow (type $2) (result i32) |
| ;; STACKIR-OPT-NEXT: (local $0 exnref) |
| ;; STACKIR-OPT-NEXT: (local $1 (tuple i32 i64)) |
| ;; STACKIR-OPT-NEXT: (local $2 (tuple i32 i64 (ref exn))) |
| ;; STACKIR-OPT-NEXT: block $outer0 (result i32) |
| ;; STACKIR-OPT-NEXT: block $catch_all2 (result (ref exn)) |
| ;; STACKIR-OPT-NEXT: block $catch1 (type $4) (result i32 i64 (ref exn)) |
| ;; STACKIR-OPT-NEXT: try_table (result i32) (catch_ref $e-i32-i64 $catch1) (catch_all_ref $catch_all2) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: i32.const 0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: local.set $2 |
| ;; STACKIR-OPT-NEXT: local.get $2 |
| ;; STACKIR-OPT-NEXT: tuple.extract 3 0 |
| ;; STACKIR-OPT-NEXT: local.get $2 |
| ;; STACKIR-OPT-NEXT: tuple.extract 3 1 |
| ;; STACKIR-OPT-NEXT: tuple.make 2 |
| ;; STACKIR-OPT-NEXT: local.set $1 |
| ;; STACKIR-OPT-NEXT: local.get $2 |
| ;; STACKIR-OPT-NEXT: tuple.extract 3 2 |
| ;; STACKIR-OPT-NEXT: local.get $1 |
| ;; STACKIR-OPT-NEXT: tuple.drop 2 |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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: ) |
| ;; STACKIR-OPT: (func $try-tuple-tag-none (type $0) (result i32 i64) |
| ;; STACKIR-OPT-NEXT: block $outer0 (type $0) (result i32 i64) |
| ;; STACKIR-OPT-NEXT: block $catch_all2 |
| ;; STACKIR-OPT-NEXT: block $catch1 |
| ;; STACKIR-OPT-NEXT: try_table (type $0) (result i32 i64) (catch $e-empty $catch1) (catch_all $catch_all2) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: i32.const 0 |
| ;; STACKIR-OPT-NEXT: i64.const 0 |
| ;; STACKIR-OPT-NEXT: tuple.make 2 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: i32.const 1 |
| ;; STACKIR-OPT-NEXT: i64.const 1 |
| ;; STACKIR-OPT-NEXT: tuple.make 2 |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: i32.const 2 |
| ;; STACKIR-OPT-NEXT: i64.const 0 |
| ;; STACKIR-OPT-NEXT: tuple.make 2 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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 (ref exn)) |
| ;; CHECK-NEXT: (local.set $0 |
| ;; CHECK-NEXT: (block $catch1 (result (ref exn)) |
| ;; 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: ) |
| ;; STACKIR-OPT: (func $try-tuple-tag-none-with-rethrow (type $0) (result i32 i64) |
| ;; STACKIR-OPT-NEXT: (local $0 exnref) |
| ;; STACKIR-OPT-NEXT: block $outer0 (type $0) (result i32 i64) |
| ;; STACKIR-OPT-NEXT: block $catch_all2 (result (ref exn)) |
| ;; STACKIR-OPT-NEXT: block $catch1 (result (ref exn)) |
| ;; STACKIR-OPT-NEXT: try_table (type $0) (result i32 i64) (catch_ref $e-empty $catch1) (catch_all_ref $catch_all2) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: i32.const 0 |
| ;; STACKIR-OPT-NEXT: i64.const 0 |
| ;; STACKIR-OPT-NEXT: tuple.make 2 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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: ) |
| ;; STACKIR-OPT: (func $try-tuple-tag-single (type $0) (result i32 i64) |
| ;; STACKIR-OPT-NEXT: (local $0 i32) |
| ;; STACKIR-OPT-NEXT: block $outer0 (type $0) (result i32 i64) |
| ;; STACKIR-OPT-NEXT: block $catch_all2 |
| ;; STACKIR-OPT-NEXT: block $catch1 (result i32) |
| ;; STACKIR-OPT-NEXT: try_table (type $0) (result i32 i64) (catch $e-i32 $catch1) (catch_all $catch_all2) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: i32.const 0 |
| ;; STACKIR-OPT-NEXT: i64.const 0 |
| ;; STACKIR-OPT-NEXT: tuple.make 2 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: i64.const 0 |
| ;; STACKIR-OPT-NEXT: tuple.make 2 |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: i32.const 2 |
| ;; STACKIR-OPT-NEXT: i64.const 2 |
| ;; STACKIR-OPT-NEXT: tuple.make 2 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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 (ref exn))) |
| ;; CHECK-NEXT: (block $outer0 (type $0) (result i32 i64) |
| ;; CHECK-NEXT: (local.set $0 |
| ;; CHECK-NEXT: (block $catch_all2 (result (ref exn)) |
| ;; CHECK-NEXT: (local.set $2 |
| ;; CHECK-NEXT: (block $catch1 (type $3) (result i32 (ref exn)) |
| ;; 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: ) |
| ;; STACKIR-OPT: (func $try-tuple-tag-single-with-rethrow (type $0) (result i32 i64) |
| ;; STACKIR-OPT-NEXT: (local $0 exnref) |
| ;; STACKIR-OPT-NEXT: (local $1 i32) |
| ;; STACKIR-OPT-NEXT: (local $2 (tuple i32 (ref exn))) |
| ;; STACKIR-OPT-NEXT: block $outer0 (type $0) (result i32 i64) |
| ;; STACKIR-OPT-NEXT: block $catch_all2 (result (ref exn)) |
| ;; STACKIR-OPT-NEXT: block $catch1 (type $3) (result i32 (ref exn)) |
| ;; STACKIR-OPT-NEXT: try_table (type $0) (result i32 i64) (catch_ref $e-i32 $catch1) (catch_all_ref $catch_all2) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: i32.const 0 |
| ;; STACKIR-OPT-NEXT: i64.const 0 |
| ;; STACKIR-OPT-NEXT: tuple.make 2 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: local.set $2 |
| ;; STACKIR-OPT-NEXT: local.get $2 |
| ;; STACKIR-OPT-NEXT: tuple.extract 2 0 |
| ;; STACKIR-OPT-NEXT: local.get $2 |
| ;; STACKIR-OPT-NEXT: tuple.extract 2 1 |
| ;; STACKIR-OPT-NEXT: local.set $0 |
| ;; STACKIR-OPT-NEXT: drop |
| ;; STACKIR-OPT-NEXT: local.get $0 |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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: ) |
| ;; STACKIR-OPT: (func $try-tuple-tag-tuple (type $0) (result i32 i64) |
| ;; STACKIR-OPT-NEXT: (local $0 (tuple i32 i64)) |
| ;; STACKIR-OPT-NEXT: block $outer0 (type $0) (result i32 i64) |
| ;; STACKIR-OPT-NEXT: block $catch_all2 |
| ;; STACKIR-OPT-NEXT: block $catch1 (type $0) (result i32 i64) |
| ;; STACKIR-OPT-NEXT: try_table (type $0) (result i32 i64) (catch $e-i32-i64 $catch1) (catch_all $catch_all2) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: i32.const 0 |
| ;; STACKIR-OPT-NEXT: i64.const 0 |
| ;; STACKIR-OPT-NEXT: tuple.make 2 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: local.set $0 |
| ;; STACKIR-OPT-NEXT: local.get $0 |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: i32.const 2 |
| ;; STACKIR-OPT-NEXT: i64.const 2 |
| ;; STACKIR-OPT-NEXT: tuple.make 2 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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 (ref exn))) |
| ;; CHECK-NEXT: (block $outer0 (type $0) (result i32 i64) |
| ;; CHECK-NEXT: (local.set $0 |
| ;; CHECK-NEXT: (block $catch_all2 (result (ref exn)) |
| ;; CHECK-NEXT: (local.set $2 |
| ;; CHECK-NEXT: (block $catch1 (type $4) (result i32 i64 (ref exn)) |
| ;; 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: ) |
| ;; STACKIR-OPT: (func $try-tuple-tag-tuple-with-rethrow (type $0) (result i32 i64) |
| ;; STACKIR-OPT-NEXT: (local $0 exnref) |
| ;; STACKIR-OPT-NEXT: (local $1 (tuple i32 i64)) |
| ;; STACKIR-OPT-NEXT: (local $2 (tuple i32 i64 (ref exn))) |
| ;; STACKIR-OPT-NEXT: block $outer0 (type $0) (result i32 i64) |
| ;; STACKIR-OPT-NEXT: block $catch_all2 (result (ref exn)) |
| ;; STACKIR-OPT-NEXT: block $catch1 (type $4) (result i32 i64 (ref exn)) |
| ;; STACKIR-OPT-NEXT: try_table (type $0) (result i32 i64) (catch_ref $e-i32-i64 $catch1) (catch_all_ref $catch_all2) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: i32.const 0 |
| ;; STACKIR-OPT-NEXT: i64.const 0 |
| ;; STACKIR-OPT-NEXT: tuple.make 2 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: local.set $2 |
| ;; STACKIR-OPT-NEXT: local.get $2 |
| ;; STACKIR-OPT-NEXT: tuple.extract 3 0 |
| ;; STACKIR-OPT-NEXT: local.get $2 |
| ;; STACKIR-OPT-NEXT: tuple.extract 3 1 |
| ;; STACKIR-OPT-NEXT: tuple.make 2 |
| ;; STACKIR-OPT-NEXT: local.set $1 |
| ;; STACKIR-OPT-NEXT: local.get $2 |
| ;; STACKIR-OPT-NEXT: tuple.extract 3 2 |
| ;; STACKIR-OPT-NEXT: local.get $1 |
| ;; STACKIR-OPT-NEXT: tuple.drop 2 |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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: ) |
| ;; STACKIR-OPT: (func $catchless-delegateless-try (type $1) |
| ;; STACKIR-OPT-NEXT: try_table |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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 (ref exn))) |
| ;; CHECK-NEXT: (local $4 (tuple i32 i64 (ref exn))) |
| ;; CHECK-NEXT: (block $outer0 |
| ;; CHECK-NEXT: (local.set $0 |
| ;; CHECK-NEXT: (block $catch_all4 (result (ref exn)) |
| ;; CHECK-NEXT: (local.set $4 |
| ;; CHECK-NEXT: (block $catch3 (type $4) (result i32 i64 (ref exn)) |
| ;; CHECK-NEXT: (local.set $3 |
| ;; CHECK-NEXT: (block $catch2 (type $3) (result i32 (ref exn)) |
| ;; CHECK-NEXT: (local.set $0 |
| ;; CHECK-NEXT: (block $catch1 (result (ref exn)) |
| ;; 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: ) |
| ;; STACKIR-OPT: (func $multiple-catches-and-catch_all (type $1) |
| ;; STACKIR-OPT-NEXT: (local $0 exnref) |
| ;; STACKIR-OPT-NEXT: (local $1 i32) |
| ;; STACKIR-OPT-NEXT: (local $2 (tuple i32 i64)) |
| ;; STACKIR-OPT-NEXT: (local $3 (tuple i32 (ref exn))) |
| ;; STACKIR-OPT-NEXT: (local $4 (tuple i32 i64 (ref exn))) |
| ;; STACKIR-OPT-NEXT: block $outer0 |
| ;; STACKIR-OPT-NEXT: block $catch_all4 (result (ref exn)) |
| ;; STACKIR-OPT-NEXT: block $catch3 (type $4) (result i32 i64 (ref exn)) |
| ;; STACKIR-OPT-NEXT: block $catch2 (type $3) (result i32 (ref exn)) |
| ;; STACKIR-OPT-NEXT: block $catch1 (result (ref exn)) |
| ;; STACKIR-OPT-NEXT: try_table (catch_ref $e-empty $catch1) (catch_ref $e-i32 $catch2) (catch_ref $e-i32-i64 $catch3) (catch_all_ref $catch_all4) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: local.set $3 |
| ;; STACKIR-OPT-NEXT: local.get $3 |
| ;; STACKIR-OPT-NEXT: tuple.extract 2 0 |
| ;; STACKIR-OPT-NEXT: local.get $3 |
| ;; STACKIR-OPT-NEXT: tuple.extract 2 1 |
| ;; STACKIR-OPT-NEXT: local.set $0 |
| ;; STACKIR-OPT-NEXT: drop |
| ;; STACKIR-OPT-NEXT: local.get $0 |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: local.set $4 |
| ;; STACKIR-OPT-NEXT: local.get $4 |
| ;; STACKIR-OPT-NEXT: tuple.extract 3 0 |
| ;; STACKIR-OPT-NEXT: local.get $4 |
| ;; STACKIR-OPT-NEXT: tuple.extract 3 1 |
| ;; STACKIR-OPT-NEXT: tuple.make 2 |
| ;; STACKIR-OPT-NEXT: local.set $2 |
| ;; STACKIR-OPT-NEXT: local.get $4 |
| ;; STACKIR-OPT-NEXT: tuple.extract 3 2 |
| ;; STACKIR-OPT-NEXT: local.get $2 |
| ;; STACKIR-OPT-NEXT: tuple.drop 2 |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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 (ref exn)) |
| ;; 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 (ref exn)) |
| ;; 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: ) |
| ;; STACKIR-OPT: (func $nested-catch-rethrows (type $1) |
| ;; STACKIR-OPT-NEXT: (local $0 exnref) |
| ;; STACKIR-OPT-NEXT: (local $1 exnref) |
| ;; STACKIR-OPT-NEXT: block $outer3 |
| ;; STACKIR-OPT-NEXT: block $catch_all4 (result (ref exn)) |
| ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $catch_all4) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer3 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: local.set $0 |
| ;; STACKIR-OPT-NEXT: block $outer0 |
| ;; STACKIR-OPT-NEXT: block $catch2 (result (ref exn)) |
| ;; STACKIR-OPT-NEXT: block $catch1 |
| ;; STACKIR-OPT-NEXT: try_table (catch $e-empty $catch1) (catch_ref $e-empty $catch2) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: local.get $0 |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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: (block |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; STACKIR-OPT: (func $delegate-target-outer-try-none (type $1) |
| ;; STACKIR-OPT-NEXT: block $outer1 |
| ;; STACKIR-OPT-NEXT: block $catch_all2 |
| ;; STACKIR-OPT-NEXT: try_table (catch_all $catch_all2) |
| ;; STACKIR-OPT-NEXT: block $l00 (result exnref) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $l00) |
| ;; STACKIR-OPT-NEXT: call $bar |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: call $baz |
| ;; STACKIR-OPT-NEXT: br $outer1 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: unreachable |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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: (block |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; STACKIR-OPT: (func $multiple-delegates-target-outer-try-none (type $1) |
| ;; STACKIR-OPT-NEXT: block $outer1 |
| ;; STACKIR-OPT-NEXT: block $catch_all2 |
| ;; STACKIR-OPT-NEXT: try_table (catch_all $catch_all2) |
| ;; STACKIR-OPT-NEXT: block $l00 (result exnref) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $l00) |
| ;; STACKIR-OPT-NEXT: call $bar |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $l00) |
| ;; STACKIR-OPT-NEXT: call $bar |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: call $baz |
| ;; STACKIR-OPT-NEXT: br $outer1 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: unreachable |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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: ) |
| ;; STACKIR-OPT: (func $delegate-target-outer-try-concrete (type $2) (result i32) |
| ;; STACKIR-OPT-NEXT: block $outer1 (result i32) |
| ;; STACKIR-OPT-NEXT: block $catch_all2 |
| ;; STACKIR-OPT-NEXT: try_table (result i32) (catch_all $catch_all2) |
| ;; STACKIR-OPT-NEXT: block $l00 (result exnref) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: try_table (result i32) (catch_all_ref $l00) |
| ;; STACKIR-OPT-NEXT: call $bar |
| ;; STACKIR-OPT-NEXT: i32.const 0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer1 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer1 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: i32.const 1 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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: ) |
| ;; STACKIR-OPT: (func $deletate-target-outer-try-unreachable (type $1) |
| ;; STACKIR-OPT-NEXT: try_table |
| ;; STACKIR-OPT-NEXT: block $l00 (result exnref) |
| ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $l00) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: return |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: unreachable |
| ;; STACKIR-OPT-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: ) |
| ;; STACKIR-OPT: (func $delegate-target-caller-none (type $1) |
| ;; STACKIR-OPT-NEXT: block $__binaryen_delegate_caller_target0 (result exnref) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $__binaryen_delegate_caller_target0) |
| ;; STACKIR-OPT-NEXT: call $bar |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: call $baz |
| ;; STACKIR-OPT-NEXT: return |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-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: ) |
| ;; STACKIR-OPT: (func $multiple-delegates-target-caller-none (type $1) |
| ;; STACKIR-OPT-NEXT: block $__binaryen_delegate_caller_target0 (result exnref) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $__binaryen_delegate_caller_target0) |
| ;; STACKIR-OPT-NEXT: call $bar |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $__binaryen_delegate_caller_target0) |
| ;; STACKIR-OPT-NEXT: call $bar |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: call $baz |
| ;; STACKIR-OPT-NEXT: return |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-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: ) |
| ;; STACKIR-OPT: (func $delegate-target-caller-concrete (type $2) (result i32) |
| ;; STACKIR-OPT-NEXT: block $__binaryen_delegate_caller_target0 (result exnref) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: try_table (result i32) (catch_all_ref $__binaryen_delegate_caller_target0) |
| ;; STACKIR-OPT-NEXT: call $bar |
| ;; STACKIR-OPT-NEXT: i32.const 0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: return |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-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: (block |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (br $outer3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (block |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; STACKIR-OPT: (func $delegate-nested-more (type $1) |
| ;; STACKIR-OPT-NEXT: block $outer3 |
| ;; STACKIR-OPT-NEXT: block $catch_all4 |
| ;; STACKIR-OPT-NEXT: try_table (catch_all $catch_all4) |
| ;; STACKIR-OPT-NEXT: block $l00 (result exnref) |
| ;; STACKIR-OPT-NEXT: block $outer1 |
| ;; STACKIR-OPT-NEXT: block $catch_all2 |
| ;; STACKIR-OPT-NEXT: try_table (catch_all $catch_all2) |
| ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $l00) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer1 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer3 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: unreachable |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-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: ) |
| ;; STACKIR-OPT: (func $delegate-target-outer-try-delegate (type $1) |
| ;; STACKIR-OPT-NEXT: block $__binaryen_delegate_caller_target0 (result exnref) |
| ;; STACKIR-OPT-NEXT: block $outer2 |
| ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $__binaryen_delegate_caller_target0) |
| ;; STACKIR-OPT-NEXT: block $l01 (result exnref) |
| ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $l01) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer2 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: unreachable |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: return |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-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: ) |
| ;; STACKIR-OPT: (func $delegate-target-outer-try-delegate-concrete (type $2) (result i32) |
| ;; STACKIR-OPT-NEXT: block $__binaryen_delegate_caller_target0 (result exnref) |
| ;; STACKIR-OPT-NEXT: block $outer2 (result i32) |
| ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $__binaryen_delegate_caller_target0) |
| ;; STACKIR-OPT-NEXT: block $l01 (result exnref) |
| ;; STACKIR-OPT-NEXT: try_table (result i32) (catch_all_ref $l01) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: i32.const 0 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer2 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: unreachable |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: return |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-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) |
| ) |
| ) |
| |
| ;; CHECK: (func $throw_ref-in-resultless-block (type $2) (result i32) |
| ;; CHECK-NEXT: (throw_ref |
| ;; CHECK-NEXT: (block $__binaryen_delegate_caller_target0 (result exnref) |
| ;; CHECK-NEXT: (return |
| ;; CHECK-NEXT: (block |
| ;; CHECK-NEXT: (try_table (catch_all_ref $__binaryen_delegate_caller_target0) |
| ;; CHECK-NEXT: (call $foo) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; STACKIR-OPT: (func $throw_ref-in-resultless-block (type $2) (result i32) |
| ;; STACKIR-OPT-NEXT: block $__binaryen_delegate_caller_target0 (result exnref) |
| ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $__binaryen_delegate_caller_target0) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: unreachable |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: ) |
| (func $throw_ref-in-resultless-block (result i32) |
| ;; When the function return type is concrete, try-delegate that targets the |
| ;; caller is translated to |
| ;; (throw_ref |
| ;; (block $__binaryen_delegate_caller_target (result exnref) |
| ;; (return |
| ;; function body |
| ;; ) |
| ;; ) |
| ;; ) |
| ;; We should do that even if the function body's type is not concrete. |
| (block ;; This block doesn't have concrete result type |
| (try |
| (do |
| (call $foo) |
| ) |
| (delegate 1) |
| ) |
| (unreachable) |
| ) |
| ) |
| |
| ;; CHECK: (func $try-delegate-within-catchless-try (type $1) |
| ;; CHECK-NEXT: (block $outer1 |
| ;; 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: (br $outer1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; STACKIR-OPT: (func $try-delegate-within-catchless-try (type $1) |
| ;; STACKIR-OPT-NEXT: block $outer1 |
| ;; STACKIR-OPT-NEXT: try_table |
| ;; STACKIR-OPT-NEXT: block $l00 (result exnref) |
| ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $l00) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer1 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: unreachable |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: ) |
| (func $try-delegate-within-catchless-try |
| (try $l0 |
| (do |
| (try |
| (do |
| (call $foo) |
| ) |
| (delegate $l0) |
| ) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (func $try-catch-rethrow-with-inner-delegate (type $1) |
| ;; CHECK-NEXT: (local $0 exnref) |
| ;; CHECK-NEXT: (block $outer2 |
| ;; CHECK-NEXT: (local.set $0 |
| ;; CHECK-NEXT: (block $catch3 (result (ref exn)) |
| ;; CHECK-NEXT: (try_table (catch_ref $e-empty $catch3) |
| ;; CHECK-NEXT: (call $foo) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (br $outer2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (block |
| ;; CHECK-NEXT: (block $outer1 |
| ;; CHECK-NEXT: (try_table |
| ;; CHECK-NEXT: (throw_ref |
| ;; CHECK-NEXT: (block $l10 (result exnref) |
| ;; CHECK-NEXT: (try_table (catch_all_ref $l10) |
| ;; CHECK-NEXT: (call $foo) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (br $outer1) |
| ;; 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: ) |
| ;; STACKIR-OPT: (func $try-catch-rethrow-with-inner-delegate (type $1) |
| ;; STACKIR-OPT-NEXT: (local $0 exnref) |
| ;; STACKIR-OPT-NEXT: block $outer2 |
| ;; STACKIR-OPT-NEXT: block $catch3 (result (ref exn)) |
| ;; STACKIR-OPT-NEXT: try_table (catch_ref $e-empty $catch3) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer2 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: block $outer1 |
| ;; STACKIR-OPT-NEXT: try_table |
| ;; STACKIR-OPT-NEXT: block $l10 (result exnref) |
| ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $l10) |
| ;; STACKIR-OPT-NEXT: call $foo |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: br $outer1 |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: unreachable |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: throw_ref |
| ;; STACKIR-OPT-NEXT: end |
| ;; STACKIR-OPT-NEXT: ) |
| (func $try-catch-rethrow-with-inner-delegate |
| (try $l0 |
| (do |
| (call $foo) |
| ) |
| (catch $e-empty |
| (try $l1 |
| (do |
| (try |
| (do |
| (call $foo) |
| ) |
| (delegate $l1) |
| ) |
| ) |
| ) |
| (rethrow $l0) |
| ) |
| ) |
| ) |
| ) |