diff options
Diffstat (limited to 'test/spec')
-rw-r--r-- | test/spec/return_call.wast | 202 | ||||
-rw-r--r-- | test/spec/return_call_eh.wast | 35 | ||||
-rw-r--r-- | test/spec/return_call_indirect.wast | 536 | ||||
-rw-r--r-- | test/spec/return_call_ref.wast | 377 |
4 files changed, 1150 insertions, 0 deletions
diff --git a/test/spec/return_call.wast b/test/spec/return_call.wast new file mode 100644 index 000000000..9423159ff --- /dev/null +++ b/test/spec/return_call.wast @@ -0,0 +1,202 @@ +;; Test `return_call` operator + +(module + ;; Auxiliary definitions + (func $const-i32 (result i32) (i32.const 0x132)) + (func $const-i64 (result i64) (i64.const 0x164)) + (func $const-f32 (result f32) (f32.const 0xf32)) + (func $const-f64 (result f64) (f64.const 0xf64)) + + (func $id-i32 (param i32) (result i32) (local.get 0)) + (func $id-i64 (param i64) (result i64) (local.get 0)) + (func $id-f32 (param f32) (result f32) (local.get 0)) + (func $id-f64 (param f64) (result f64) (local.get 0)) + + (func $f32-i32 (param f32 i32) (result i32) (local.get 1)) + (func $i32-i64 (param i32 i64) (result i64) (local.get 1)) + (func $f64-f32 (param f64 f32) (result f32) (local.get 1)) + (func $i64-f64 (param i64 f64) (result f64) (local.get 1)) + + ;; Typing + + (func (export "type-i32") (result i32) (return_call $const-i32)) + (func (export "type-i64") (result i64) (return_call $const-i64)) + (func (export "type-f32") (result f32) (return_call $const-f32)) + (func (export "type-f64") (result f64) (return_call $const-f64)) + + (func (export "type-first-i32") (result i32) (return_call $id-i32 (i32.const 32))) + (func (export "type-first-i64") (result i64) (return_call $id-i64 (i64.const 64))) + (func (export "type-first-f32") (result f32) (return_call $id-f32 (f32.const 1.32))) + (func (export "type-first-f64") (result f64) (return_call $id-f64 (f64.const 1.64))) + + (func (export "type-second-i32") (result i32) + (return_call $f32-i32 (f32.const 32.1) (i32.const 32)) + ) + (func (export "type-second-i64") (result i64) + (return_call $i32-i64 (i32.const 32) (i64.const 64)) + ) + (func (export "type-second-f32") (result f32) + (return_call $f64-f32 (f64.const 64) (f32.const 32)) + ) + (func (export "type-second-f64") (result f64) + (return_call $i64-f64 (i64.const 64) (f64.const 64.1)) + ) + + ;; Recursion + + (func $fac-acc (export "fac-acc") (param i64 i64) (result i64) + (if (result i64) (i64.eqz (local.get 0)) + (then (local.get 1)) + (else + (return_call $fac-acc + (i64.sub (local.get 0) (i64.const 1)) + (i64.mul (local.get 0) (local.get 1)) + ) + ) + ) + ) + + (func $count (export "count") (param i64) (result i64) + (if (result i64) (i64.eqz (local.get 0)) + (then (local.get 0)) + (else (return_call $count (i64.sub (local.get 0) (i64.const 1)))) + ) + ) + + (func $even (export "even") (param i64) (result i32) + (if (result i32) (i64.eqz (local.get 0)) + (then (i32.const 44)) + (else (return_call $odd (i64.sub (local.get 0) (i64.const 1)))) + ) + ) + (func $odd (export "odd") (param i64) (result i32) + (if (result i32) (i64.eqz (local.get 0)) + (then (i32.const 99)) + (else (return_call $even (i64.sub (local.get 0) (i64.const 1)))) + ) + ) +) + +(assert_return (invoke "type-i32") (i32.const 0x132)) +(assert_return (invoke "type-i64") (i64.const 0x164)) +(assert_return (invoke "type-f32") (f32.const 0xf32)) +(assert_return (invoke "type-f64") (f64.const 0xf64)) + +(assert_return (invoke "type-first-i32") (i32.const 32)) +(assert_return (invoke "type-first-i64") (i64.const 64)) +(assert_return (invoke "type-first-f32") (f32.const 1.32)) +(assert_return (invoke "type-first-f64") (f64.const 1.64)) + +(assert_return (invoke "type-second-i32") (i32.const 32)) +(assert_return (invoke "type-second-i64") (i64.const 64)) +(assert_return (invoke "type-second-f32") (f32.const 32)) +(assert_return (invoke "type-second-f64") (f64.const 64.1)) + +(assert_return (invoke "fac-acc" (i64.const 0) (i64.const 1)) (i64.const 1)) +(assert_return (invoke "fac-acc" (i64.const 1) (i64.const 1)) (i64.const 1)) +(assert_return (invoke "fac-acc" (i64.const 5) (i64.const 1)) (i64.const 120)) +(assert_return + (invoke "fac-acc" (i64.const 25) (i64.const 1)) + (i64.const 7034535277573963776) +) + +(assert_return (invoke "count" (i64.const 0)) (i64.const 0)) +(assert_return (invoke "count" (i64.const 1000)) (i64.const 0)) +(assert_return (invoke "count" (i64.const 1000000)) (i64.const 0)) + +(assert_return (invoke "even" (i64.const 0)) (i32.const 44)) +(assert_return (invoke "even" (i64.const 1)) (i32.const 99)) +(assert_return (invoke "even" (i64.const 100)) (i32.const 44)) +(assert_return (invoke "even" (i64.const 77)) (i32.const 99)) +(assert_return (invoke "even" (i64.const 1000000)) (i32.const 44)) +(assert_return (invoke "even" (i64.const 1000001)) (i32.const 99)) +(assert_return (invoke "odd" (i64.const 0)) (i32.const 99)) +(assert_return (invoke "odd" (i64.const 1)) (i32.const 44)) +(assert_return (invoke "odd" (i64.const 200)) (i32.const 99)) +(assert_return (invoke "odd" (i64.const 77)) (i32.const 44)) +(assert_return (invoke "odd" (i64.const 1000000)) (i32.const 99)) +(assert_return (invoke "odd" (i64.const 999999)) (i32.const 44)) + + +;; Invalid typing + +(assert_invalid + (module + (func $type-void-vs-num (result i32) (return_call 1) (i32.const 0)) + (func) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-num-vs-num (result i32) (return_call 1) (i32.const 0)) + (func (result i64) (i64.const 1)) + ) + "type mismatch" +) + +(assert_invalid + (module + (func $arity-0-vs-1 (return_call 1)) + (func (param i32)) + ) + "type mismatch" +) +(assert_invalid + (module + (func $arity-0-vs-2 (return_call 1)) + (func (param f64 i32)) + ) + "type mismatch" +) + +;; (module +;; (func $arity-1-vs-0 (i32.const 1) (return_call 1)) +;; (func) +;; ) + +;; (module +;; (func $arity-2-vs-0 (f64.const 2) (i32.const 1) (return_call 1)) +;; (func) +;; ) + +(assert_invalid + (module + (func $type-first-void-vs-num (return_call 1 (nop) (i32.const 1))) + (func (param i32 i32)) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-second-void-vs-num (return_call 1 (i32.const 1) (nop))) + (func (param i32 i32)) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-first-num-vs-num (return_call 1 (f64.const 1) (i32.const 1))) + (func (param i32 f64)) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-second-num-vs-num (return_call 1 (i32.const 1) (f64.const 1))) + (func (param f64 i32)) + ) + "type mismatch" +) + + +;; Unbound function + +(assert_invalid + (module (func $unbound-func (return_call 1))) + "unknown function" +) +(assert_invalid + (module (func $large-func (return_call 1012321300))) + "unknown function" +) diff --git a/test/spec/return_call_eh.wast b/test/spec/return_call_eh.wast new file mode 100644 index 000000000..e85fdf7c6 --- /dev/null +++ b/test/spec/return_call_eh.wast @@ -0,0 +1,35 @@ +;; Test the combination of 'return_call' with exception handling + +(module + (tag $t) + + (func $test (export "test") (result i32) + (try (result i32) + (do + (call $return-call-in-try) + ) + (catch_all + ;; Catch the exception thrown from $return-callee + (i32.const 42) + ) + ) + + ) + + (func $return-call-in-try (result i32) + (try (result i32) + (do + (return_call $return-callee) + ) + (catch_all + (unreachable) + ) + ) + ) + + (func $return-callee (result i32) + (throw $t) + ) +) + +(assert_return (invoke "test") (i32.const 42)) diff --git a/test/spec/return_call_indirect.wast b/test/spec/return_call_indirect.wast new file mode 100644 index 000000000..27f1dcdbf --- /dev/null +++ b/test/spec/return_call_indirect.wast @@ -0,0 +1,536 @@ +;; Test `return_call_indirect` operator + +(module + ;; Auxiliary definitions + (type $proc (func)) + (type $out-i32 (func (result i32))) + (type $out-i64 (func (result i64))) + (type $out-f32 (func (result f32))) + (type $out-f64 (func (result f64))) + (type $over-i32 (func (param i32) (result i32))) + (type $over-i64 (func (param i64) (result i64))) + (type $over-f32 (func (param f32) (result f32))) + (type $over-f64 (func (param f64) (result f64))) + (type $f32-i32 (func (param f32 i32) (result i32))) + (type $i32-i64 (func (param i32 i64) (result i64))) + (type $f64-f32 (func (param f64 f32) (result f32))) + (type $i64-f64 (func (param i64 f64) (result f64))) + (type $over-i32-duplicate (func (param i32) (result i32))) + (type $over-i64-duplicate (func (param i64) (result i64))) + (type $over-f32-duplicate (func (param f32) (result f32))) + (type $over-f64-duplicate (func (param f64) (result f64))) + + (func $const-i32 (type $out-i32) (i32.const 0x132)) + (func $const-i64 (type $out-i64) (i64.const 0x164)) + (func $const-f32 (type $out-f32) (f32.const 0xf32)) + (func $const-f64 (type $out-f64) (f64.const 0xf64)) + + (func $id-i32 (type $over-i32) (local.get 0)) + (func $id-i64 (type $over-i64) (local.get 0)) + (func $id-f32 (type $over-f32) (local.get 0)) + (func $id-f64 (type $over-f64) (local.get 0)) + + (func $i32-i64 (type $i32-i64) (local.get 1)) + (func $i64-f64 (type $i64-f64) (local.get 1)) + (func $f32-i32 (type $f32-i32) (local.get 1)) + (func $f64-f32 (type $f64-f32) (local.get 1)) + + (func $over-i32-duplicate (type $over-i32-duplicate) (local.get 0)) + (func $over-i64-duplicate (type $over-i64-duplicate) (local.get 0)) + (func $over-f32-duplicate (type $over-f32-duplicate) (local.get 0)) + (func $over-f64-duplicate (type $over-f64-duplicate) (local.get 0)) + + (table funcref + (elem + $const-i32 $const-i64 $const-f32 $const-f64 + $id-i32 $id-i64 $id-f32 $id-f64 + $f32-i32 $i32-i64 $f64-f32 $i64-f64 + $fac $fac-acc $even $odd + $over-i32-duplicate $over-i64-duplicate + $over-f32-duplicate $over-f64-duplicate + ) + ) + + ;; Syntax + + (func + (return_call_indirect (i32.const 0)) + (return_call_indirect (param i64) (i64.const 0) (i32.const 0)) + (return_call_indirect (param i64) (param) (param f64 i32 i64) + (i64.const 0) (f64.const 0) (i32.const 0) (i64.const 0) (i32.const 0) + ) + (return_call_indirect (result) (i32.const 0)) + ) + + (func (result i32) + (return_call_indirect (result i32) (i32.const 0)) + (return_call_indirect (result i32) (result) (i32.const 0)) + (return_call_indirect (param i64) (result i32) (i64.const 0) (i32.const 0)) + (return_call_indirect + (param) (param i64) (param) (param f64 i32 i64) (param) (param) + (result) (result i32) (result) (result) + (i64.const 0) (f64.const 0) (i32.const 0) (i64.const 0) (i32.const 0) + ) + ) + + (func (result i64) + (return_call_indirect (type $over-i64) (param i64) (result i64) + (i64.const 0) (i32.const 0) + ) + ) + + ;; Typing + + (func (export "type-i32") (result i32) + (return_call_indirect (type $out-i32) (i32.const 0)) + ) + (func (export "type-i64") (result i64) + (return_call_indirect (type $out-i64) (i32.const 1)) + ) + (func (export "type-f32") (result f32) + (return_call_indirect (type $out-f32) (i32.const 2)) + ) + (func (export "type-f64") (result f64) + (return_call_indirect (type $out-f64) (i32.const 3)) + ) + + (func (export "type-index") (result i64) + (return_call_indirect (type $over-i64) (i64.const 100) (i32.const 5)) + ) + + (func (export "type-first-i32") (result i32) + (return_call_indirect (type $over-i32) (i32.const 32) (i32.const 4)) + ) + (func (export "type-first-i64") (result i64) + (return_call_indirect (type $over-i64) (i64.const 64) (i32.const 5)) + ) + (func (export "type-first-f32") (result f32) + (return_call_indirect (type $over-f32) (f32.const 1.32) (i32.const 6)) + ) + (func (export "type-first-f64") (result f64) + (return_call_indirect (type $over-f64) (f64.const 1.64) (i32.const 7)) + ) + + (func (export "type-second-i32") (result i32) + (return_call_indirect (type $f32-i32) + (f32.const 32.1) (i32.const 32) (i32.const 8) + ) + ) + (func (export "type-second-i64") (result i64) + (return_call_indirect (type $i32-i64) + (i32.const 32) (i64.const 64) (i32.const 9) + ) + ) + (func (export "type-second-f32") (result f32) + (return_call_indirect (type $f64-f32) + (f64.const 64) (f32.const 32) (i32.const 10) + ) + ) + (func (export "type-second-f64") (result f64) + (return_call_indirect (type $i64-f64) + (i64.const 64) (f64.const 64.1) (i32.const 11) + ) + ) + + ;; Dispatch + + (func (export "dispatch") (param i32 i64) (result i64) + (return_call_indirect (type $over-i64) (local.get 1) (local.get 0)) + ) + + (func (export "dispatch-structural") (param i32) (result i64) + (return_call_indirect (type $over-i64-duplicate) + (i64.const 9) (local.get 0) + ) + ) + + ;; Multiple tables + + (table $tab2 funcref (elem $tab-f1)) + (table $tab3 funcref (elem $tab-f2)) + + (func $tab-f1 (result i32) (i32.const 0x133)) + (func $tab-f2 (result i32) (i32.const 0x134)) + + (func (export "call-tab") (param $i i32) (result i32) + (if (i32.eq (local.get $i) (i32.const 0)) + (then (return_call_indirect (type $out-i32) (i32.const 0))) + ) + (if (i32.eq (local.get $i) (i32.const 1)) + (then (return_call_indirect $tab2 (type $out-i32) (i32.const 0))) + ) + (if (i32.eq (local.get $i) (i32.const 2)) + (then (return_call_indirect $tab3 (type $out-i32) (i32.const 0))) + ) + (i32.const 0) + ) + + ;; Recursion + + (func $fac (export "fac") (type $over-i64) + (return_call_indirect (param i64 i64) (result i64) + (local.get 0) (i64.const 1) (i32.const 13) + ) + ) + + (func $fac-acc (param i64 i64) (result i64) + (if (result i64) (i64.eqz (local.get 0)) + (then (local.get 1)) + (else + (return_call_indirect (param i64 i64) (result i64) + (i64.sub (local.get 0) (i64.const 1)) + (i64.mul (local.get 0) (local.get 1)) + (i32.const 13) + ) + ) + ) + ) + + (func $even (export "even") (param i32) (result i32) + (if (result i32) (i32.eqz (local.get 0)) + (then (i32.const 44)) + (else + (return_call_indirect (type $over-i32) + (i32.sub (local.get 0) (i32.const 1)) + (i32.const 15) + ) + ) + ) + ) + (func $odd (export "odd") (param i32) (result i32) + (if (result i32) (i32.eqz (local.get 0)) + (then (i32.const 99)) + (else + (return_call_indirect (type $over-i32) + (i32.sub (local.get 0) (i32.const 1)) + (i32.const 14) + ) + ) + ) + ) +) + +(assert_return (invoke "type-i32") (i32.const 0x132)) +(assert_return (invoke "type-i64") (i64.const 0x164)) +(assert_return (invoke "type-f32") (f32.const 0xf32)) +(assert_return (invoke "type-f64") (f64.const 0xf64)) + +(assert_return (invoke "type-index") (i64.const 100)) + +(assert_return (invoke "type-first-i32") (i32.const 32)) +(assert_return (invoke "type-first-i64") (i64.const 64)) +(assert_return (invoke "type-first-f32") (f32.const 1.32)) +(assert_return (invoke "type-first-f64") (f64.const 1.64)) + +(assert_return (invoke "type-second-i32") (i32.const 32)) +(assert_return (invoke "type-second-i64") (i64.const 64)) +(assert_return (invoke "type-second-f32") (f32.const 32)) +(assert_return (invoke "type-second-f64") (f64.const 64.1)) + +(assert_return (invoke "dispatch" (i32.const 5) (i64.const 2)) (i64.const 2)) +(assert_return (invoke "dispatch" (i32.const 5) (i64.const 5)) (i64.const 5)) +(assert_return (invoke "dispatch" (i32.const 12) (i64.const 5)) (i64.const 120)) +(assert_return (invoke "dispatch" (i32.const 17) (i64.const 2)) (i64.const 2)) +(assert_trap (invoke "dispatch" (i32.const 0) (i64.const 2)) "indirect call type mismatch") +(assert_trap (invoke "dispatch" (i32.const 15) (i64.const 2)) "indirect call type mismatch") +(assert_trap (invoke "dispatch" (i32.const 20) (i64.const 2)) "undefined element") +(assert_trap (invoke "dispatch" (i32.const -1) (i64.const 2)) "undefined element") +(assert_trap (invoke "dispatch" (i32.const 1213432423) (i64.const 2)) "undefined element") + +(assert_return (invoke "dispatch-structural" (i32.const 5)) (i64.const 9)) +(assert_return (invoke "dispatch-structural" (i32.const 5)) (i64.const 9)) +(assert_return (invoke "dispatch-structural" (i32.const 12)) (i64.const 362880)) +(assert_return (invoke "dispatch-structural" (i32.const 17)) (i64.const 9)) +(assert_trap (invoke "dispatch-structural" (i32.const 11)) "indirect call type mismatch") +(assert_trap (invoke "dispatch-structural" (i32.const 16)) "indirect call type mismatch") + +(assert_return (invoke "call-tab" (i32.const 0)) (i32.const 0x132)) +(assert_return (invoke "call-tab" (i32.const 1)) (i32.const 0x133)) +(assert_return (invoke "call-tab" (i32.const 2)) (i32.const 0x134)) + +(assert_return (invoke "fac" (i64.const 0)) (i64.const 1)) +(assert_return (invoke "fac" (i64.const 1)) (i64.const 1)) +(assert_return (invoke "fac" (i64.const 5)) (i64.const 120)) +(assert_return (invoke "fac" (i64.const 25)) (i64.const 7034535277573963776)) + +(assert_return (invoke "even" (i32.const 0)) (i32.const 44)) +(assert_return (invoke "even" (i32.const 1)) (i32.const 99)) +(assert_return (invoke "even" (i32.const 100)) (i32.const 44)) +(assert_return (invoke "even" (i32.const 77)) (i32.const 99)) +(assert_return (invoke "even" (i32.const 100000)) (i32.const 44)) +(assert_return (invoke "even" (i32.const 111111)) (i32.const 99)) +(assert_return (invoke "odd" (i32.const 0)) (i32.const 99)) +(assert_return (invoke "odd" (i32.const 1)) (i32.const 44)) +(assert_return (invoke "odd" (i32.const 200)) (i32.const 99)) +(assert_return (invoke "odd" (i32.const 77)) (i32.const 44)) +(assert_return (invoke "odd" (i32.const 200002)) (i32.const 99)) +(assert_return (invoke "odd" (i32.const 300003)) (i32.const 44)) + + +;; Invalid syntax + +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(table 0 funcref)" + "(func (result i32)" + " (return_call_indirect (type $sig) (result i32) (param i32)" + " (i32.const 0) (i32.const 0)" + " )" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(table 0 funcref)" + "(func (result i32)" + " (return_call_indirect (param i32) (type $sig) (result i32)" + " (i32.const 0) (i32.const 0)" + " )" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(table 0 funcref)" + "(func (result i32)" + " (return_call_indirect (param i32) (result i32) (type $sig)" + " (i32.const 0) (i32.const 0)" + " )" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(table 0 funcref)" + "(func (result i32)" + " (return_call_indirect (result i32) (type $sig) (param i32)" + " (i32.const 0) (i32.const 0)" + " )" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(table 0 funcref)" + "(func (result i32)" + " (return_call_indirect (result i32) (param i32) (type $sig)" + " (i32.const 0) (i32.const 0)" + " )" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(table 0 funcref)" + "(func (result i32)" + " (return_call_indirect (result i32) (param i32)" + " (i32.const 0) (i32.const 0)" + " )" + ")" + ) + "unexpected token" +) + +(assert_malformed + (module quote + "(table 0 funcref)" + "(func (return_call_indirect (param $x i32) (i32.const 0) (i32.const 0)))" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(type $sig (func))" + "(table 0 funcref)" + "(func (result i32)" + " (return_call_indirect (type $sig) (result i32) (i32.const 0))" + ")" + ) + "inline function type" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(table 0 funcref)" + "(func (result i32)" + " (return_call_indirect (type $sig) (result i32) (i32.const 0))" + ")" + ) + "inline function type" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(table 0 funcref)" + "(func" + " (return_call_indirect (type $sig) (param i32)" + " (i32.const 0) (i32.const 0)" + " )" + ")" + ) + "inline function type" +) +(assert_malformed + (module quote + "(type $sig (func (param i32 i32) (result i32)))" + "(table 0 funcref)" + "(func (result i32)" + " (return_call_indirect (type $sig) (param i32) (result i32)" + " (i32.const 0) (i32.const 0)" + " )" + ")" + ) + "inline function type" +) + +;; Invalid typing + +(assert_invalid + (module + (type (func)) + (func $no-table (return_call_indirect (type 0) (i32.const 0))) + ) + "unknown table" +) + +;; (assert_invalid +;; (module +;; (type (func)) +;; (table 0 funcref) +;; (func $type-void-vs-num (i32.eqz (return_call_indirect (type 0) (i32.const 0)))) +;; ) +;; "type mismatch" +;; ) +(assert_invalid + (module + (type (func (result i64))) + (table 0 funcref) + (func $type-num-vs-num (i32.eqz (return_call_indirect (type 0) (i32.const 0)))) + ) + "type mismatch" +) + +(assert_invalid + (module + (type (func (param i32))) + (table 0 funcref) + (func $arity-0-vs-1 (return_call_indirect (type 0) (i32.const 0))) + ) + "type mismatch" +) +(assert_invalid + (module + (type (func (param f64 i32))) + (table 0 funcref) + (func $arity-0-vs-2 (return_call_indirect (type 0) (i32.const 0))) + ) + "type mismatch" +) + +;; (module +;; (type (func)) +;; (table 0 funcref) +;; (func $arity-1-vs-0 (return_call_indirect (type 0) (i32.const 1) (i32.const 0))) +;; ) + +;; (module +;; (type (func)) +;; (table 0 funcref) +;; (func $arity-2-vs-0 +;; (return_call_indirect (type 0) (f64.const 2) (i32.const 1) (i32.const 0)) +;; ) +;; ) + +(assert_invalid + (module + (type (func (param i32))) + (table 0 funcref) + (func $type-func-void-vs-i32 (return_call_indirect (type 0) (i32.const 1) (nop))) + ) + "type mismatch" +) +(assert_invalid + (module + (type (func (param i32))) + (table 0 funcref) + (func $type-func-num-vs-i32 (return_call_indirect (type 0) (i32.const 0) (i64.const 1))) + ) + "type mismatch" +) + +(assert_invalid + (module + (type (func (param i32 i32))) + (table 0 funcref) + (func $type-first-void-vs-num + (return_call_indirect (type 0) (nop) (i32.const 1) (i32.const 0)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (type (func (param i32 i32))) + (table 0 funcref) + (func $type-second-void-vs-num + (return_call_indirect (type 0) (i32.const 1) (nop) (i32.const 0)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (type (func (param i32 f64))) + (table 0 funcref) + (func $type-first-num-vs-num + (return_call_indirect (type 0) (f64.const 1) (i32.const 1) (i32.const 0)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (type (func (param f64 i32))) + (table 0 funcref) + (func $type-second-num-vs-num + (return_call_indirect (type 0) (i32.const 1) (f64.const 1) (i32.const 0)) + ) + ) + "type mismatch" +) + + +;; Unbound type + +(assert_invalid + (module + (table 0 funcref) + (func $unbound-type (return_call_indirect (type 1) (i32.const 0))) + ) + "unknown type" +) +(assert_invalid + (module + (table 0 funcref) + (func $large-type (return_call_indirect (type 1012321300) (i32.const 0))) + ) + "unknown type" +) + + +;; Unbound function in table + +(assert_invalid + (module (table funcref (elem 0 0))) + "unknown function 0" +) diff --git a/test/spec/return_call_ref.wast b/test/spec/return_call_ref.wast new file mode 100644 index 000000000..6bb5d2a14 --- /dev/null +++ b/test/spec/return_call_ref.wast @@ -0,0 +1,377 @@ +;; Test `return_call_ref` operator + +(module + ;; Auxiliary definitions + (type $proc (func)) + (type $-i32 (func (result i32))) + (type $-i64 (func (result i64))) + (type $-f32 (func (result f32))) + (type $-f64 (func (result f64))) + + (type $i32-i32 (func (param i32) (result i32))) + (type $i64-i64 (func (param i64) (result i64))) + (type $f32-f32 (func (param f32) (result f32))) + (type $f64-f64 (func (param f64) (result f64))) + + (type $f32-i32 (func (param f32 i32) (result i32))) + (type $i32-i64 (func (param i32 i64) (result i64))) + (type $f64-f32 (func (param f64 f32) (result f32))) + (type $i64-f64 (func (param i64 f64) (result f64))) + + (type $i64i64-i64 (func (param i64 i64) (result i64))) + + (func $const-i32 (result i32) (i32.const 0x132)) + (func $const-i64 (result i64) (i64.const 0x164)) + (func $const-f32 (result f32) (f32.const 0xf32)) + (func $const-f64 (result f64) (f64.const 0xf64)) + + (func $id-i32 (param i32) (result i32) (local.get 0)) + (func $id-i64 (param i64) (result i64) (local.get 0)) + (func $id-f32 (param f32) (result f32) (local.get 0)) + (func $id-f64 (param f64) (result f64) (local.get 0)) + + (func $f32-i32 (param f32 i32) (result i32) (local.get 1)) + (func $i32-i64 (param i32 i64) (result i64) (local.get 1)) + (func $f64-f32 (param f64 f32) (result f32) (local.get 1)) + (func $i64-f64 (param i64 f64) (result f64) (local.get 1)) + + (global $const-i32 (ref $-i32) (ref.func $const-i32)) + (global $const-i64 (ref $-i64) (ref.func $const-i64)) + (global $const-f32 (ref $-f32) (ref.func $const-f32)) + (global $const-f64 (ref $-f64) (ref.func $const-f64)) + + (global $id-i32 (ref $i32-i32) (ref.func $id-i32)) + (global $id-i64 (ref $i64-i64) (ref.func $id-i64)) + (global $id-f32 (ref $f32-f32) (ref.func $id-f32)) + (global $id-f64 (ref $f64-f64) (ref.func $id-f64)) + + (global $f32-i32 (ref $f32-i32) (ref.func $f32-i32)) + (global $i32-i64 (ref $i32-i64) (ref.func $i32-i64)) + (global $f64-f32 (ref $f64-f32) (ref.func $f64-f32)) + (global $i64-f64 (ref $i64-f64) (ref.func $i64-f64)) + + (elem declare func + $const-i32 $const-i64 $const-f32 $const-f64 + $id-i32 $id-i64 $id-f32 $id-f64 + $f32-i32 $i32-i64 $f64-f32 $i64-f64 + ) + + ;; Typing + + (func (export "type-i32") (result i32) + (return_call_ref $-i32 (global.get $const-i32)) + ) + (func (export "type-i64") (result i64) + (return_call_ref $-i64 (global.get $const-i64)) + ) + (func (export "type-f32") (result f32) + (return_call_ref $-f32 (global.get $const-f32)) + ) + (func (export "type-f64") (result f64) + (return_call_ref $-f64 (global.get $const-f64)) + ) + + (func (export "type-first-i32") (result i32) + (return_call_ref $i32-i32 (i32.const 32) (global.get $id-i32)) + ) + (func (export "type-first-i64") (result i64) + (return_call_ref $i64-i64 (i64.const 64) (global.get $id-i64)) + ) + (func (export "type-first-f32") (result f32) + (return_call_ref $f32-f32 (f32.const 1.32) (global.get $id-f32)) + ) + (func (export "type-first-f64") (result f64) + (return_call_ref $f64-f64 (f64.const 1.64) (global.get $id-f64)) + ) + + (func (export "type-second-i32") (result i32) + (return_call_ref $f32-i32 (f32.const 32.1) (i32.const 32) (global.get $f32-i32)) + ) + (func (export "type-second-i64") (result i64) + (return_call_ref $i32-i64 (i32.const 32) (i64.const 64) (global.get $i32-i64)) + ) + (func (export "type-second-f32") (result f32) + (return_call_ref $f64-f32 (f64.const 64) (f32.const 32) (global.get $f64-f32)) + ) + (func (export "type-second-f64") (result f64) + (return_call_ref $i64-f64 (i64.const 64) (f64.const 64.1) (global.get $i64-f64)) + ) + + ;; Null + + (func (export "null") + (return_call_ref $proc (ref.null $proc)) + ) + + ;; Recursion + + (global $fac-acc (ref $i64i64-i64) (ref.func $fac-acc)) + + (elem declare func $fac-acc) + (func $fac-acc (export "fac-acc") (param i64 i64) (result i64) + (if (result i64) (i64.eqz (local.get 0)) + (then (local.get 1)) + (else + (return_call_ref $i64i64-i64 + (i64.sub (local.get 0) (i64.const 1)) + (i64.mul (local.get 0) (local.get 1)) + (global.get $fac-acc) + ) + ) + ) + ) + + (global $count (ref $i64-i64) (ref.func $count)) + + (elem declare func $count) + (func $count (export "count") (param i64) (result i64) + (if (result i64) (i64.eqz (local.get 0)) + (then (local.get 0)) + (else + (return_call_ref $i64-i64 + (i64.sub (local.get 0) (i64.const 1)) + (global.get $count) + ) + ) + ) + ) + + (global $even (ref $i64-i64) (ref.func $even)) + (global $odd (ref $i64-i64) (ref.func $odd)) + + (elem declare func $even) + (func $even (export "even") (param i64) (result i64) + (if (result i64) (i64.eqz (local.get 0)) + (then (i64.const 44)) + (else + (return_call_ref $i64-i64 + (i64.sub (local.get 0) (i64.const 1)) + (global.get $odd) + ) + ) + ) + ) + (elem declare func $odd) + (func $odd (export "odd") (param i64) (result i64) + (if (result i64) (i64.eqz (local.get 0)) + (then (i64.const 99)) + (else + (return_call_ref $i64-i64 + (i64.sub (local.get 0) (i64.const 1)) + (global.get $even) + ) + ) + ) + ) +) + +(assert_return (invoke "type-i32") (i32.const 0x132)) +(assert_return (invoke "type-i64") (i64.const 0x164)) +(assert_return (invoke "type-f32") (f32.const 0xf32)) +(assert_return (invoke "type-f64") (f64.const 0xf64)) + +(assert_return (invoke "type-first-i32") (i32.const 32)) +(assert_return (invoke "type-first-i64") (i64.const 64)) +(assert_return (invoke "type-first-f32") (f32.const 1.32)) +(assert_return (invoke "type-first-f64") (f64.const 1.64)) + +(assert_return (invoke "type-second-i32") (i32.const 32)) +(assert_return (invoke "type-second-i64") (i64.const 64)) +(assert_return (invoke "type-second-f32") (f32.const 32)) +(assert_return (invoke "type-second-f64") (f64.const 64.1)) + +(assert_trap (invoke "null") "null function reference") + +(assert_return (invoke "fac-acc" (i64.const 0) (i64.const 1)) (i64.const 1)) +(assert_return (invoke "fac-acc" (i64.const 1) (i64.const 1)) (i64.const 1)) +(assert_return (invoke "fac-acc" (i64.const 5) (i64.const 1)) (i64.const 120)) +(assert_return + (invoke "fac-acc" (i64.const 25) (i64.const 1)) + (i64.const 7034535277573963776) +) + +(assert_return (invoke "count" (i64.const 0)) (i64.const 0)) +(assert_return (invoke "count" (i64.const 1000)) (i64.const 0)) +(assert_return (invoke "count" (i64.const 1000000)) (i64.const 0)) + +(assert_return (invoke "even" (i64.const 0)) (i64.const 44)) +(assert_return (invoke "even" (i64.const 1)) (i64.const 99)) +(assert_return (invoke "even" (i64.const 100)) (i64.const 44)) +(assert_return (invoke "even" (i64.const 77)) (i64.const 99)) +(assert_return (invoke "even" (i64.const 1000000)) (i64.const 44)) +(assert_return (invoke "even" (i64.const 1000001)) (i64.const 99)) +(assert_return (invoke "odd" (i64.const 0)) (i64.const 99)) +(assert_return (invoke "odd" (i64.const 1)) (i64.const 44)) +(assert_return (invoke "odd" (i64.const 200)) (i64.const 99)) +(assert_return (invoke "odd" (i64.const 77)) (i64.const 44)) +(assert_return (invoke "odd" (i64.const 1000000)) (i64.const 99)) +(assert_return (invoke "odd" (i64.const 999999)) (i64.const 44)) + + +;; More typing + +(module + (type $t (func)) + (type $t1 (func (result (ref $t)))) + (type $t2 (func (result (ref null $t)))) + (type $t3 (func (result (ref func)))) + (type $t4 (func (result (ref null func)))) + (elem declare func $f11 $f22 $f33 $f44) + (func $f11 (result (ref $t)) (return_call_ref $t1 (ref.func $f11))) + (func $f21 (result (ref null $t)) (return_call_ref $t1 (ref.func $f11))) + (func $f22 (result (ref null $t)) (return_call_ref $t2 (ref.func $f22))) + (func $f31 (result (ref func)) (return_call_ref $t1 (ref.func $f11))) + (func $f33 (result (ref func)) (return_call_ref $t3 (ref.func $f33))) + (func $f41 (result (ref null func)) (return_call_ref $t1 (ref.func $f11))) + (func $f42 (result (ref null func)) (return_call_ref $t2 (ref.func $f22))) + (func $f43 (result (ref null func)) (return_call_ref $t3 (ref.func $f33))) + (func $f44 (result (ref null func)) (return_call_ref $t4 (ref.func $f44))) +) + +(assert_invalid + (module + (type $t (func)) + (type $t2 (func (result (ref null $t)))) + (elem declare func $f22) + (func $f12 (result (ref $t)) (return_call_ref $t2 (ref.func $f22))) + (func $f22 (result (ref null $t)) (return_call_ref $t2 (ref.func $f22))) + ) + "type mismatch" +) + +(assert_invalid + (module + (type $t (func)) + (type $t3 (func (result (ref func)))) + (elem declare func $f33) + (func $f13 (result (ref $t)) (return_call_ref $t3 (ref.func $f33))) + (func $f33 (result (ref func)) (return_call_ref $t3 (ref.func $f33))) + ) + "type mismatch" +) + +(assert_invalid + (module + (type $t (func)) + (type $t4 (func (result (ref null func)))) + (elem declare func $f44) + (func $f14 (result (ref $t)) (return_call_ref $t4 (ref.func $f44))) + (func $f44 (result (ref null func)) (return_call_ref $t4 (ref.func $f44))) + ) + "type mismatch" +) + +(assert_invalid + (module + (type $t (func)) + (type $t3 (func (result (ref func)))) + (elem declare func $f33) + (func $f23 (result (ref null $t)) (return_call_ref $t3 (ref.func $f33))) + (func $f33 (result (ref func)) (return_call_ref $t3 (ref.func $f33))) + ) + "type mismatch" +) + +(assert_invalid + (module + (type $t (func)) + (type $t4 (func (result (ref null func)))) + (elem declare func $f44) + (func $f24 (result (ref null $t)) (return_call_ref $t4 (ref.func $f44))) + (func $f44 (result (ref null func)) (return_call_ref $t4 (ref.func $f44))) + ) + "type mismatch" +) + +(assert_invalid + (module + (type $t4 (func (result (ref null func)))) + (elem declare func $f44) + (func $f34 (result (ref func)) (return_call_ref $t4 (ref.func $f44))) + (func $f44 (result (ref null func)) (return_call_ref $t4 (ref.func $f44))) + ) + "type mismatch" +) + + +;; Unreachable typing. + +(module + (type $t (func (result i32))) + (func (export "unreachable") (result i32) + (return_call_ref $t (unreachable)) + ) +) +(assert_trap (invoke "unreachable") "unreachable") + +(module + (elem declare func $f) + (type $t (func (param i32) (result i32))) + (func $f (param i32) (result i32) (local.get 0)) + + (func (export "unreachable") (result i32) + (return_call_ref $t + (unreachable) + (ref.func $f) + ) + ) +) +(assert_trap (invoke "unreachable") "unreachable") + +(module + (elem declare func $f) + (type $t (func (param i32) (result i32))) + (func $f (param i32) (result i32) (local.get 0)) + + (func (export "unreachable") (result i32) + (unreachable) + (return_call_ref $t + (i32.const 0) + (ref.func $f) + ) + (i32.const 0) + ) +) +(assert_trap (invoke "unreachable") "unreachable") + +(assert_invalid + (module + (elem declare func $f) + (type $t (func (param i32) (result i32))) + (func $f (param i32) (result i32) (local.get 0)) + + (func (export "unreachable") (result i32) + (unreachable) + (i64.const 0) + (ref.func $f) + (return_call_ref $t) + ) + ) + "type mismatch" +) + +(assert_invalid + (module + (elem declare func $f) + (type $t (func (param i32) (result i32))) + (func $f (param i32) (result i32) (local.get 0)) + + (func (export "unreachable") (result i32) + (unreachable) + (ref.func $f) + (return_call_ref $t) + (i64.const 0) + ) + ) + "type mismatch" +) + +(assert_invalid + (module + (type $t (func)) + (func $f (param $r externref) + (return_call_ref $t (local.get $r)) + ) + ) + "type mismatch" +) |