summaryrefslogtreecommitdiff
path: root/test/spec/exception-handling-legacy.wast
diff options
context:
space:
mode:
Diffstat (limited to 'test/spec/exception-handling-legacy.wast')
-rw-r--r--test/spec/exception-handling-legacy.wast653
1 files changed, 653 insertions, 0 deletions
diff --git a/test/spec/exception-handling-legacy.wast b/test/spec/exception-handling-legacy.wast
new file mode 100644
index 000000000..6b4631877
--- /dev/null
+++ b/test/spec/exception-handling-legacy.wast
@@ -0,0 +1,653 @@
+(module
+ (tag $e-v)
+ (tag $e-i32 (param i32))
+ (tag $e-f32 (param f32))
+ (tag $e-i32-f32 (param i32 f32))
+
+ (func $throw_single_value (export "throw_single_value")
+ (throw $e-i32 (i32.const 5))
+ )
+
+ (func (export "throw_multiple_values")
+ (throw $e-i32-f32 (i32.const 3) (f32.const 3.5))
+ )
+
+ (func (export "try_nothrow") (result i32)
+ (try (result i32)
+ (do
+ (i32.const 3)
+ )
+ (catch $e-i32
+ (drop (pop i32))
+ (i32.const 0)
+ )
+ )
+ )
+
+ (func (export "try_throw_catch") (result i32)
+ (try (result i32)
+ (do
+ (throw $e-i32 (i32.const 5))
+ )
+ (catch $e-i32
+ (drop (pop i32))
+ (i32.const 3)
+ )
+ )
+ )
+
+ (func (export "try_throw_nocatch") (result i32)
+ (try (result i32)
+ (do
+ (throw $e-i32 (i32.const 5))
+ )
+ (catch $e-f32
+ (drop (pop f32))
+ (i32.const 3)
+ )
+ )
+ )
+
+ (func (export "try_throw_catchall") (result i32)
+ (try (result i32)
+ (do
+ (throw $e-i32 (i32.const 5))
+ )
+ (catch $e-f32
+ (drop (pop f32))
+ (i32.const 4)
+ )
+ (catch_all
+ (i32.const 3)
+ )
+ )
+ )
+
+ (func (export "try_call_catch") (result i32)
+ (try (result i32)
+ (do
+ (call $throw_single_value)
+ (unreachable)
+ )
+ (catch $e-i32
+ (pop i32)
+ )
+ )
+ )
+
+ (func (export "try_throw_multivalue_catch") (result i32) (local $x (tuple i32 f32))
+ (try (result i32)
+ (do
+ (throw $e-i32-f32 (i32.const 5) (f32.const 1.5))
+ )
+ (catch $e-i32-f32
+ (local.set $x
+ (pop (tuple i32 f32))
+ )
+ (tuple.extract 2 0
+ (local.get $x)
+ )
+ )
+ )
+ )
+
+ (func (export "try_throw_rethrow")
+ (try $l0
+ (do
+ (throw $e-i32 (i32.const 5))
+ )
+ (catch $e-i32
+ (drop (pop i32))
+ (rethrow $l0)
+ )
+ )
+ )
+
+ (func (export "try_call_rethrow")
+ (try $l0
+ (do
+ (call $throw_single_value)
+ )
+ (catch_all
+ (rethrow $l0)
+ )
+ )
+ )
+
+ (func (export "rethrow_target_test1") (result i32)
+ (try (result i32)
+ (do
+ (try
+ (do
+ (throw $e-i32 (i32.const 1))
+ )
+ (catch_all
+ (try $l0
+ (do
+ (throw $e-i32 (i32.const 2))
+ )
+ (catch $e-i32
+ (drop (pop i32))
+ (rethrow $l0) ;; rethrow (i32.const 2)
+ )
+ )
+ )
+ )
+ )
+ (catch $e-i32
+ (pop i32) ;; result is (i32.const 2)
+ )
+ )
+ )
+
+ ;; Can we handle rethrows with the depth > 0?
+ (func (export "rethrow_target_test2") (result i32)
+ (try (result i32)
+ (do
+ (try $l0
+ (do
+ (throw $e-i32 (i32.const 1))
+ )
+ (catch_all
+ (try
+ (do
+ (throw $e-i32 (i32.const 2))
+ )
+ (catch $e-i32
+ (drop (pop i32))
+ (rethrow 1) ;; rethrow (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ (catch $e-i32
+ (pop i32) ;; result is (i32.const 1)
+ )
+ )
+ )
+
+ ;; Tests whether the exception stack is managed correctly after rethrows
+ (func (export "rethrow_target_test3") (result i32)
+ (try (result i32)
+ (do
+ (try $l0
+ (do
+ (try $l1
+ (do
+ (throw $e-i32 (i32.const 1))
+ )
+ (catch_all
+ (try
+ (do
+ (throw $e-i32 (i32.const 2))
+ )
+ (catch $e-i32
+ (drop (pop i32))
+ (rethrow $l1) ;; rethrow (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ (catch $e-i32
+ (drop (pop i32))
+ (rethrow $l0) ;; rethrow (i32.const 1) again
+ )
+ )
+ )
+ (catch $e-i32
+ (pop i32) ;; result is (i32.const 1)
+ )
+ )
+ )
+
+ (func (export "try_delegate_caught") (result i32)
+ (try $l0 (result i32)
+ (do
+ (try (result i32)
+ (do
+ (try (result i32)
+ (do
+ (throw $e-i32 (i32.const 3))
+ )
+ (delegate $l0)
+ )
+ )
+ (catch_all
+ (i32.const 0)
+ )
+ )
+ )
+ (catch $e-i32
+ (pop i32)
+ )
+ )
+ )
+
+ (func (export "try_delegate_to_catchless_try") (result i32)
+ (try $l0 (result i32)
+ (do
+ (try (result i32)
+ (do
+ (try (result i32)
+ (do
+ (throw $e-i32 (i32.const 3))
+ )
+ (delegate $l0)
+ )
+ )
+ (catch_all
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ )
+
+ (func (export "try_delegate_to_delegate") (result i32)
+ (try $l0 (result i32)
+ (do
+ (try $l1 (result i32)
+ (do
+ (try (result i32)
+ (do
+ (throw $e-i32 (i32.const 3))
+ )
+ (delegate $l1)
+ )
+ )
+ (delegate $l0)
+ )
+ )
+ (catch $e-i32
+ (pop i32)
+ )
+ )
+ )
+
+ (func (export "try_delegate_to_caller")
+ (try $l0
+ (do
+ (try $l1
+ (do
+ (try
+ (do
+ (throw $e-i32 (i32.const 3))
+ )
+ (delegate 2) ;; to caller
+ )
+ )
+ )
+ )
+ (catch_all)
+ )
+ )
+)
+
+(assert_exception (invoke "throw_single_value"))
+(assert_exception (invoke "throw_multiple_values"))
+(assert_return (invoke "try_nothrow") (i32.const 3))
+(assert_return (invoke "try_throw_catch") (i32.const 3))
+(assert_exception (invoke "try_throw_nocatch"))
+(assert_return (invoke "try_throw_catchall") (i32.const 3))
+(assert_return (invoke "try_call_catch") (i32.const 5))
+(assert_return (invoke "try_throw_multivalue_catch") (i32.const 5))
+(assert_exception (invoke "try_throw_rethrow"))
+(assert_exception (invoke "try_call_rethrow"))
+(assert_return (invoke "rethrow_target_test1") (i32.const 2))
+(assert_return (invoke "rethrow_target_test2") (i32.const 1))
+(assert_return (invoke "rethrow_target_test3") (i32.const 1))
+(assert_return (invoke "try_delegate_caught") (i32.const 3))
+(assert_exception (invoke "try_delegate_to_catchless_try"))
+(assert_return (invoke "try_delegate_to_delegate") (i32.const 3))
+(assert_exception (invoke "try_delegate_to_caller"))
+
+(assert_invalid
+ (module
+ (func $f0
+ (try
+ (do (nop))
+ (catch $e-i32
+ (pop i32)
+ )
+ )
+ )
+ )
+ "try's body type must match catch's body type"
+)
+
+(assert_invalid
+ (module
+ (tag $e-i32 (param i32))
+ (func $f0
+ (try
+ (do (i32.const 0))
+ (catch $e-i32
+ (pop i32)
+ )
+ )
+ )
+ )
+ "try's type does not match try body's type"
+)
+
+(assert_invalid
+ (module
+ (tag $e-i32 (param i32))
+ (func $f0
+ (throw $e-i32 (f32.const 0))
+ )
+ )
+ "tag param types must match"
+)
+
+(assert_invalid
+ (module
+ (tag $e-i32 (param i32 f32))
+ (func $f0
+ (throw $e-i32 (f32.const 0))
+ )
+ )
+ "tag's param numbers must match"
+)
+
+(module
+ (func $f0
+ (block $l0
+ (try
+ (do
+ (try
+ (do)
+ (delegate $l0) ;; target is a block
+ )
+ )
+ (catch_all)
+ )
+ )
+ )
+)
+
+(module
+ (func $f0
+ (try $l0
+ (do)
+ (catch_all
+ (try
+ (do)
+ (delegate $l0) ;; the target catch is above the delegate
+ )
+ )
+ )
+ )
+)
+
+(assert_invalid
+ (module
+ (func $f0
+ (block $l0
+ (try
+ (do)
+ (catch_all
+ (rethrow $l0) ;; target is a block
+ )
+ )
+ )
+ )
+ )
+ "all rethrow targets must be valid"
+)
+
+(assert_invalid
+ (module
+ (func $f0
+ (try $l0
+ (do
+ (rethrow $l0) ;; Not within the target try's catch
+ )
+ (catch_all)
+ )
+ )
+ )
+ "all rethrow targets must be valid"
+)
+
+(assert_invalid
+ (module
+ (func $f0
+ (try
+ (do)
+ (catch $e)
+ )
+ )
+ )
+ "catch's tag name is invalid: e"
+)
+
+(assert_invalid
+ (module
+ (tag $e-none (param))
+ (func $f0 (result i32)
+ (try (result i32)
+ (do
+ (i32.const 0)
+ )
+ (catch $e-none
+ (pop i32)
+ )
+ )
+ )
+ )
+ "catch's tag (e-none) doesn't have any params, but there are pops"
+)
+
+(assert_invalid
+ (module
+ (tag $e-i32 (param i32))
+ (func $f0
+ (try
+ (do)
+ (catch $e-i32)
+ )
+ )
+ )
+ "catch's tag (e-i32) has params, so there should be a single pop within the catch body"
+)
+
+(assert_invalid
+ (module
+ (tag $e-i32 (param i32))
+ (func $f0
+ (try
+ (do)
+ (catch $e-i32
+ (drop
+ (pop i32)
+ )
+ (drop
+ (pop i32)
+ )
+ )
+ )
+ )
+ )
+ "catch's tag (e-i32) has params, so there should be a single pop within the catch body"
+)
+
+(assert_invalid
+ (module
+ (func $f0 (result i32)
+ (try (result i32)
+ (do
+ (i32.const 0)
+ )
+ (catch_all
+ (pop i32)
+ )
+ )
+ )
+ )
+ "catch_all's body should not have pops"
+)
+
+(assert_invalid
+ (module
+ (tag $e-i32 (param i32))
+ (func $f0 (result f32)
+ (try (result f32)
+ (do
+ (f32.const 0)
+ )
+ (catch $e-i32
+ (pop f32)
+ )
+ )
+ )
+ )
+ "catch's tag (e-i32)'s pop doesn't have the same type as the tag's params"
+)
+
+(assert_invalid
+ (module
+ (tag $e-i32 (param i32))
+ (func $f0 (result i32)
+ (try (result i32)
+ (do
+ (i32.const 0)
+ )
+ (catch $e-i32
+ (drop
+ (i32.const 0)
+ )
+ (pop i32) ;; Not the first children within 'catch'
+ )
+ )
+ )
+ )
+ "catch's body (e-i32)'s pop's location is not valid"
+)
+
+(assert_invalid
+ (module
+ (tag $e-i32 (param i32))
+ (func $f0
+ (try
+ (do)
+ (catch $e-i32
+ (throw $e-i32
+ (block (result i32)
+ (pop i32) ;; pop is within a block
+ )
+ )
+ )
+ )
+ )
+ )
+ "catch's body (e-i32)'s pop's location is not valid"
+)
+
+(assert_invalid
+ (module
+ (tag $e-i32 (param i32))
+ (func $f0
+ (try
+ (do)
+ (catch $e-i32
+ (throw $e-i32
+ (loop (result i32)
+ (pop i32) ;; pop is within a loop
+ )
+ )
+ )
+ )
+ )
+ )
+ "catch's body (e-i32)'s pop's location is not valid"
+)
+
+(assert_invalid
+ (module
+ (tag $e-i32 (param i32))
+ (func $f0
+ (try
+ (do)
+ (catch $e-i32
+ (throw $e-i32
+ (try (result i32)
+ (do
+ (pop i32) ;; pop is within a try
+ )
+ (catch_all
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ "catch's body (e-i32)'s pop's location is not valid"
+)
+
+(assert_invalid
+ (module
+ (tag $e-i32 (param i32))
+ (func $f0
+ (try
+ (do)
+ (catch $e-i32
+ (throw $e-i32
+ (if (result i32)
+ (i32.const 0)
+ (then
+ (pop i32) ;; pop is within an if true body
+ )
+ (else
+ (i32.const 3)
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ "catch's body (e-i32)'s pop's location is not valid"
+)
+
+(assert_invalid
+ (module
+ (tag $e-i32 (param i32) (result i32))
+ (tag $e-f32 (param f32))
+ (func (export "try_throw_nocatch") (result i32)
+ (try (result i32)
+ (do
+ (throw $e-i32 (i32.const 5))
+ )
+ (catch $e-f32
+ (drop (pop f32))
+ (i32.const 3)
+ )
+ )
+ )
+ )
+ "tags with result types must not be used for exception handling"
+)
+
+(assert_invalid
+ (module
+ (tag $e-i32 (param i32))
+ (tag $e-f32 (param f32) (result i32))
+ (func (export "try_throw_nocatch") (result i32)
+ (try (result i32)
+ (do
+ (throw $e-i32 (i32.const 5))
+ )
+ (catch $e-f32
+ (drop (pop f32))
+ (i32.const 3)
+ )
+ )
+ )
+ )
+ "catch's tag (e-f32) has result values, which is not allowed for exception handling"
+)