;; RUN: wast --assert default,no-test-folded --snapshot tests/snapshots % -f legacy-exceptions
;; Test try-catch blocks.
(module
(tag $e0 (export "e0"))
(func (export "throw") (throw $e0))
)
(register "test")
(module
(tag $imported-e0 (import "test" "e0"))
(func $imported-throw (import "test" "throw"))
(tag $e0)
(tag $e1)
(tag $e2)
(tag $e-i32 (param i32))
(tag $e-f32 (param f32))
(tag $e-i64 (param i64))
(tag $e-f64 (param f64))
(func $throw-if (param i32) (result i32)
(local.get 0)
(i32.const 0) (if (i32.ne) (then (throw $e0)))
(i32.const 0)
)
(func (export "empty-catch")
try
catch $e0
end
)
(func (export "simple-throw-catch") (param i32) (result i32)
try (result i32)
local.get 0
i32.eqz
if
throw 1
end
i32.const 42
catch 1
i32.const 23
end
)
(func (export "unreachable-not-caught") try unreachable catch_all end)
(func $div (param i32 i32) (result i32)
(local.get 0) (local.get 1) (i32.div_u)
)
(func (export "trap-in-callee") (param i32 i32) (result i32)
try (result i32)
local.get 0
local.get 1
call 5
catch_all
i32.const 11
end
)
(func (export "catch-complex-1") (param i32) (result i32)
try (result i32)
try (result i32)
local.get 0
i32.eqz
if
throw 1
else
local.get 0
i32.const 1
i32.eq
if
throw 2
else
throw 3
end
end
i32.const 2
catch 1
i32.const 3
end
catch 2
i32.const 4
end
)
(func (export "catch-complex-2") (param i32) (result i32)
try (result i32)
local.get 0
i32.eqz
if
throw 1
else
local.get 0
i32.const 1
i32.eq
if
throw 2
else
throw 3
end
end
i32.const 2
catch 1
i32.const 3
catch 2
i32.const 4
end
)
(func (export "throw-catch-param-i32") (param i32) (result i32)
try (result i32)
local.get 0
throw 4
i32.const 2
catch 4
return
end
)
(func (export "throw-catch-param-f32") (param f32) (result f32)
try (result f32)
local.get 0
throw 5
f32.const 0
catch 5
return
end
)
(func (export "throw-catch-param-i64") (param i64) (result i64)
try (result i64)
local.get 0
throw 6
i64.const 2
catch 6
return
end
)
(func (export "throw-catch-param-f64") (param f64) (result f64)
try (result f64)
local.get 0
throw 7
f64.const 0
catch 7
return
end
)
(func $throw-param-i32 (param i32) (local.get 0) (throw $e-i32))
(func (export "catch-param-i32") (param i32) (result i32)
try (result i32)
i32.const 0
local.get 0
call 13
catch 4
end
)
(func (export "catch-imported") (result i32)
try (result i32)
i32.const 1
call 0
catch 0
i32.const 2
end
)
(func (export "catchless-try") (param i32) (result i32)
try (result i32)
try (result i32)
local.get 0
call 1
end
catch 1
i32.const 1
end
)
(func $throw-void (throw $e0))
(func (export "return-call-in-try-catch")
try
return_call 17
catch 1
end
)
(table funcref (elem $throw-void))
(func (export "return-call-indirect-in-try-catch")
try
i32.const 0
return_call_indirect (type 0)
catch 1
end
)
(func (export "break-try-catch")
try
br 0
catch 1
end
)
(func (export "break-try-catch_all")
try
br 0
catch_all
end
)
)
(assert_return (invoke "empty-catch"))
(assert_return (invoke "simple-throw-catch" (i32.const 0)) (i32.const 23))
(assert_return (invoke "simple-throw-catch" (i32.const 1)) (i32.const 42))
(assert_trap (invoke "unreachable-not-caught") "unreachable")
(assert_return (invoke "trap-in-callee" (i32.const 7) (i32.const 2)) (i32.const 3))
(assert_trap (invoke "trap-in-callee" (i32.const 1) (i32.const 0)) "integer divide by zero")
(assert_return (invoke "catch-complex-1" (i32.const 0)) (i32.const 3))
(assert_return (invoke "catch-complex-1" (i32.const 1)) (i32.const 4))
(assert_exception (invoke "catch-complex-1" (i32.const 2)))
(assert_return (invoke "catch-complex-2" (i32.const 0)) (i32.const 3))
(assert_return (invoke "catch-complex-2" (i32.const 1)) (i32.const 4))
(assert_exception (invoke "catch-complex-2" (i32.const 2)))
(assert_return (invoke "throw-catch-param-i32" (i32.const 0)) (i32.const 0))
(assert_return (invoke "throw-catch-param-i32" (i32.const 1)) (i32.const 1))
(assert_return (invoke "throw-catch-param-i32" (i32.const 10)) (i32.const 10))
(assert_return (invoke "throw-catch-param-f32" (f32.const 5.0)) (f32.const 5.0))
(assert_return (invoke "throw-catch-param-f32" (f32.const 10.5)) (f32.const 10.5))
(assert_return (invoke "throw-catch-param-i64" (i64.const 5)) (i64.const 5))
(assert_return (invoke "throw-catch-param-i64" (i64.const 0)) (i64.const 0))
(assert_return (invoke "throw-catch-param-i64" (i64.const -1)) (i64.const -1))
(assert_return (invoke "throw-catch-param-f64" (f64.const 5.0)) (f64.const 5.0))
(assert_return (invoke "throw-catch-param-f64" (f64.const 10.5)) (f64.const 10.5))
(assert_return (invoke "catch-param-i32" (i32.const 5)) (i32.const 5))
(assert_return (invoke "catch-imported") (i32.const 2))
(assert_return (invoke "catchless-try" (i32.const 0)) (i32.const 0))
(assert_return (invoke "catchless-try" (i32.const 1)) (i32.const 1))
(assert_exception (invoke "return-call-in-try-catch"))
(assert_exception (invoke "return-call-indirect-in-try-catch"))
(assert_return (invoke "break-try-catch"))
(assert_return (invoke "break-try-catch_all"))
(module
(func $imported-throw (import "test" "throw"))
(tag $e0)
(func (export "imported-mismatch") (result i32)
try (result i32) ;; label = @1
try (result i32) ;; label = @2
i32.const 1
call 0
catch 0
i32.const 2
end
catch_all
i32.const 3
end
)
)
(assert_return (invoke "imported-mismatch") (i32.const 3))
;; Ignore per https://github.com/bytecodealliance/wasm-tools/issues/1671
;;
;; (assert_malformed
;; (module quote "(module (func (catch_all)))")
;; "unexpected token"
;; )
;; (assert_malformed
;; (module quote "(module (tag $e) (func (catch $e)))")
;; "unexpected token"
;; )
;; (assert_malformed
;; (module quote
;; "(module (func try catch_all catch_all end))"
;; )
;; "unexpected token"
;; )
(assert_invalid (module (func (result i32) try (result i32) end))
"type mismatch")
(assert_invalid (module (func (result i32) try (result i32) i64.const 42 end))
"type mismatch")
(assert_invalid (module (tag) (func try catch 0 i32.const 42 end))
"type mismatch")
(assert_invalid (module
(tag (param i64))
(func (result i32)
try (result i32) i32.const 42 catch 0 end))
"type mismatch")
(assert_invalid (module (func try catch_all i32.const 32 end))
"type mismatch")