Add test cases for the requirements of "gc-aot" feature (#3399)

This commit is contained in:
Zhang, Yi
2024-05-09 16:15:44 +08:00
committed by GitHub
parent 480ee02615
commit f729da7656
30 changed files with 9995 additions and 4 deletions

View File

@ -0,0 +1,308 @@
;; Type syntax
(module
(type (array i8))
(type (array i16))
(type (array i32))
(type (array i64))
(type (array f32))
(type (array f64))
(type (array anyref))
(type (array (ref struct)))
(type (array (ref 0)))
(type (array (ref null 1)))
(type (array (mut i8)))
(type (array (mut i16)))
(type (array (mut i32)))
(type (array (mut i64)))
(type (array (mut i32)))
(type (array (mut i64)))
(type (array (mut anyref)))
(type (array (mut (ref struct))))
(type (array (mut (ref 0))))
(type (array (mut (ref null i31))))
)
(assert_invalid
(module
(type (array (mut (ref null 10))))
)
"unknown type"
)
;; Binding structure
(module
(rec
(type $s0 (array (ref $s1)))
(type $s1 (array (ref $s0)))
)
(func (param (ref $forward)))
(type $forward (array i32))
)
(assert_invalid
(module (type (array (ref 1))))
"unknown type"
)
(assert_invalid
(module (type (array (mut (ref 1)))))
"unknown type"
)
;; Basic instructions
(module
(type $vec (array f32))
(type $mvec (array (mut f32)))
(global (ref $vec) (array.new $vec (f32.const 1) (i32.const 3)))
(global (ref $vec) (array.new_default $vec (i32.const 3)))
(func $new (export "new") (result (ref $vec))
(array.new_default $vec (i32.const 3))
)
(func $get (param $i i32) (param $v (ref $vec)) (result f32)
(array.get $vec (local.get $v) (local.get $i))
)
(func (export "get") (param $i i32) (result f32)
(call $get (local.get $i) (call $new))
)
(func $set_get (param $i i32) (param $v (ref $mvec)) (param $y f32) (result f32)
(array.set $mvec (local.get $v) (local.get $i) (local.get $y))
(array.get $mvec (local.get $v) (local.get $i))
)
(func (export "set_get") (param $i i32) (param $y f32) (result f32)
(call $set_get (local.get $i)
(array.new_default $mvec (i32.const 3))
(local.get $y)
)
)
(func $len (param $v (ref array)) (result i32)
(array.len (local.get $v))
)
(func (export "len") (result i32)
(call $len (call $new))
)
)
(assert_return (invoke "new") (ref.array))
;; (assert_return (invoke "new") (ref.eq))
(assert_return (invoke "get" (i32.const 0)) (f32.const 0))
(assert_return (invoke "set_get" (i32.const 1) (f32.const 7)) (f32.const 7))
(assert_return (invoke "len") (i32.const 3))
(assert_trap (invoke "get" (i32.const 10)) "out of bounds array access")
(assert_trap (invoke "set_get" (i32.const 10) (f32.const 7)) "out of bounds array access")
(module
(type $vec (array f32))
(type $mvec (array (mut f32)))
(global (ref $vec) (array.new_fixed $vec 2 (f32.const 1) (f32.const 2)))
(func $new (export "new") (result (ref $vec))
(array.new_fixed $vec 2 (f32.const 1) (f32.const 2))
)
(func $get (param $i i32) (param $v (ref $vec)) (result f32)
(array.get $vec (local.get $v) (local.get $i))
)
(func (export "get") (param $i i32) (result f32)
(call $get (local.get $i) (call $new))
)
(func $set_get (param $i i32) (param $v (ref $mvec)) (param $y f32) (result f32)
(array.set $mvec (local.get $v) (local.get $i) (local.get $y))
(array.get $mvec (local.get $v) (local.get $i))
)
(func (export "set_get") (param $i i32) (param $y f32) (result f32)
(call $set_get (local.get $i)
(array.new_fixed $mvec 3 (f32.const 1) (f32.const 2) (f32.const 3))
(local.get $y)
)
)
(func $len (param $v (ref array)) (result i32)
(array.len (local.get $v))
)
(func (export "len") (result i32)
(call $len (call $new))
)
)
(assert_return (invoke "new") (ref.array))
;; (assert_return (invoke "new") (ref.eq))
(assert_return (invoke "get" (i32.const 0)) (f32.const 1))
(assert_return (invoke "set_get" (i32.const 1) (f32.const 7)) (f32.const 7))
(assert_return (invoke "len") (i32.const 2))
(assert_trap (invoke "get" (i32.const 10)) "out of bounds array access")
(assert_trap (invoke "set_get" (i32.const 10) (f32.const 7)) "out of bounds array access")
(module
(type $vec (array i8))
(type $mvec (array (mut i8)))
(data $d "\00\01\02\03\04")
(func $new (export "new") (result (ref $vec))
(array.new_data $vec $d (i32.const 1) (i32.const 3))
)
(func $get (param $i i32) (param $v (ref $vec)) (result i32)
(array.get_u $vec (local.get $v) (local.get $i))
)
(func (export "get") (param $i i32) (result i32)
(call $get (local.get $i) (call $new))
)
(func $set_get (param $i i32) (param $v (ref $mvec)) (param $y i32) (result i32)
(array.set $mvec (local.get $v) (local.get $i) (local.get $y))
(array.get_u $mvec (local.get $v) (local.get $i))
)
(func (export "set_get") (param $i i32) (param $y i32) (result i32)
(call $set_get (local.get $i)
(array.new_data $mvec $d (i32.const 1) (i32.const 3))
(local.get $y)
)
)
(func $len (param $v (ref array)) (result i32)
(array.len (local.get $v))
)
(func (export "len") (result i32)
(call $len (call $new))
)
)
(assert_return (invoke "new") (ref.array))
;; (assert_return (invoke "new") (ref.eq))
(assert_return (invoke "get" (i32.const 0)) (i32.const 1))
(assert_return (invoke "set_get" (i32.const 1) (i32.const 7)) (i32.const 7))
(assert_return (invoke "len") (i32.const 3))
(assert_trap (invoke "get" (i32.const 10)) "out of bounds array access")
(assert_trap (invoke "set_get" (i32.const 10) (i32.const 7)) "out of bounds array access")
(; array.new_elem not supported
(module
(type $bvec (array i8))
(type $vec (array (ref $bvec)))
(type $mvec (array (mut (ref $bvec))))
(type $nvec (array (ref null $bvec)))
(type $avec (array (mut anyref)))
(elem $e (ref $bvec)
(array.new $bvec (i32.const 7) (i32.const 3))
(array.new_fixed $bvec 2 (i32.const 1) (i32.const 2))
)
(func $new (export "new") (result (ref $vec))
(array.new_elem $vec $e (i32.const 0) (i32.const 2))
)
(func $sub1 (result (ref $nvec))
(array.new_elem $nvec $e (i32.const 0) (i32.const 2))
)
(func $sub2 (result (ref $avec))
(array.new_elem $avec $e (i32.const 0) (i32.const 2))
)
(func $get (param $i i32) (param $j i32) (param $v (ref $vec)) (result i32)
(array.get_u $bvec (array.get $vec (local.get $v) (local.get $i)) (local.get $j))
)
(func (export "get") (param $i i32) (param $j i32) (result i32)
(call $get (local.get $i) (local.get $j) (call $new))
)
(func $set_get (param $i i32) (param $j i32) (param $v (ref $mvec)) (param $y i32) (result i32)
(array.set $mvec (local.get $v) (local.get $i) (array.get $mvec (local.get $v) (local.get $y)))
(array.get_u $bvec (array.get $mvec (local.get $v) (local.get $i)) (local.get $j))
)
(func (export "set_get") (param $i i32) (param $j i32) (param $y i32) (result i32)
(call $set_get (local.get $i) (local.get $j)
(array.new_elem $mvec $e (i32.const 0) (i32.const 2))
(local.get $y)
)
)
(func $len (param $v (ref array)) (result i32)
(array.len (local.get $v))
)
(func (export "len") (result i32)
(call $len (call $new))
)
)
(assert_return (invoke "new") (ref.array))
(assert_return (invoke "new") (ref.eq))
(assert_return (invoke "get" (i32.const 0) (i32.const 0)) (i32.const 7))
(assert_return (invoke "get" (i32.const 1) (i32.const 0)) (i32.const 1))
(assert_return (invoke "set_get" (i32.const 0) (i32.const 1) (i32.const 1)) (i32.const 2))
(assert_return (invoke "len") (i32.const 2))
(assert_trap (invoke "get" (i32.const 10) (i32.const 0)) "out of bounds array access")
(assert_trap (invoke "set_get" (i32.const 10) (i32.const 0) (i32.const 0)) "out of bounds array access")
;)
(assert_invalid
(module
(type $a (array i64))
(func (export "array.set-immutable") (param $a (ref $a))
(array.set $a (local.get $a) (i32.const 0) (i64.const 1))
)
)
"array is immutable"
)
(assert_invalid
(module
(type $bvec (array i8))
(data $d "\00\01\02\03\04")
(global (ref $bvec)
(array.new_data $bvec $d (i32.const 1) (i32.const 3))
)
)
"constant expression required"
)
(assert_invalid
(module
(type $bvec (array i8))
(type $vvec (array (ref $bvec)))
(elem $e (ref $bvec) (ref.null $bvec))
(global (ref $vvec)
(array.new_elem $vvec $e (i32.const 0) (i32.const 1))
)
)
"constant expression required"
)
;; Null dereference
(module
(type $t (array (mut i32)))
(func (export "array.get-null")
(local (ref null $t)) (drop (array.get $t (local.get 0) (i32.const 0)))
)
(func (export "array.set-null")
(local (ref null $t)) (array.set $t (local.get 0) (i32.const 0) (i32.const 0))
)
)
(assert_trap (invoke "array.get-null") "null array")
(assert_trap (invoke "array.set-null") "null array")

View File

@ -0,0 +1,139 @@
;; Bulk instructions
;; invalid uses
(assert_invalid
(module
(type $a (array i8))
(type $b (array (mut i8)))
(func (export "array.copy-immutable") (param $1 (ref $a)) (param $2 (ref $b))
(array.copy $a $b (local.get $1) (i32.const 0) (local.get $2) (i32.const 0) (i32.const 0))
)
)
"array is immutable"
)
(assert_invalid
(module
(type $a (array (mut i8)))
(type $b (array i16))
(func (export "array.copy-packed-invalid") (param $1 (ref $a)) (param $2 (ref $b))
(array.copy $a $b (local.get $1) (i32.const 0) (local.get $2) (i32.const 0) (i32.const 0))
)
)
"array types do not match"
)
(assert_invalid
(module
(type $a (array (mut i8)))
(type $b (array (mut (ref $a))))
(func (export "array.copy-ref-invalid-1") (param $1 (ref $a)) (param $2 (ref $b))
(array.copy $a $b (local.get $1) (i32.const 0) (local.get $2) (i32.const 0) (i32.const 0))
)
)
"array types do not match"
)
(assert_invalid
(module
(type $a (array (mut i8)))
(type $b (array (mut (ref $a))))
(type $c (array (mut (ref $b))))
(func (export "array.copy-ref-invalid-1") (param $1 (ref $b)) (param $2 (ref $c))
(array.copy $b $c (local.get $1) (i32.const 0) (local.get $2) (i32.const 0) (i32.const 0))
)
)
"array types do not match"
)
(module
(type $arr8 (array i8))
(type $arr8_mut (array (mut i8)))
(global $g_arr8 (ref $arr8) (array.new $arr8 (i32.const 10) (i32.const 12)))
(global $g_arr8_mut (mut (ref $arr8_mut)) (array.new_default $arr8_mut (i32.const 12)))
(data $d1 "abcdefghijkl")
(func (export "array_get_nth") (param $1 i32) (result i32)
(array.get_u $arr8_mut (global.get $g_arr8_mut) (local.get $1))
)
(func (export "array_copy-null-left")
(array.copy $arr8_mut $arr8 (ref.null $arr8_mut) (i32.const 0) (global.get $g_arr8) (i32.const 0) (i32.const 0))
)
(func (export "array_copy-null-right")
(array.copy $arr8_mut $arr8 (global.get $g_arr8_mut) (i32.const 0) (ref.null $arr8) (i32.const 0) (i32.const 0))
)
(func (export "array_copy") (param $1 i32) (param $2 i32) (param $3 i32)
(array.copy $arr8_mut $arr8 (global.get $g_arr8_mut) (local.get $1) (global.get $g_arr8) (local.get $2) (local.get $3))
)
(func (export "array_copy_overlap_test-1")
(local $1 (ref $arr8_mut))
(array.new_data $arr8_mut $d1 (i32.const 0) (i32.const 12))
(local.set $1)
(array.copy $arr8_mut $arr8_mut (local.get $1) (i32.const 1) (local.get $1) (i32.const 0) (i32.const 11))
(global.set $g_arr8_mut (local.get $1))
)
(func (export "array_copy_overlap_test-2")
(local $1 (ref $arr8_mut))
(array.new_data $arr8_mut $d1 (i32.const 0) (i32.const 12))
(local.set $1)
(array.copy $arr8_mut $arr8_mut (local.get $1) (i32.const 0) (local.get $1) (i32.const 1) (i32.const 11))
(global.set $g_arr8_mut (local.get $1))
)
)
;; null array argument traps
(assert_trap (invoke "array_copy-null-left") "null array reference")
(assert_trap (invoke "array_copy-null-right") "null array reference")
;; OOB initial index traps
(assert_trap (invoke "array_copy" (i32.const 13) (i32.const 0) (i32.const 0)) "out of bounds array access")
(assert_trap (invoke "array_copy" (i32.const 0) (i32.const 13) (i32.const 0)) "out of bounds array access")
;; OOB length traps
(assert_trap (invoke "array_copy" (i32.const 0) (i32.const 0) (i32.const 13)) "out of bounds array access")
(assert_trap (invoke "array_copy" (i32.const 0) (i32.const 0) (i32.const 13)) "out of bounds array access")
;; start index = array size, len = 0 doesn't trap
(assert_return (invoke "array_copy" (i32.const 12) (i32.const 0) (i32.const 0)))
(assert_return (invoke "array_copy" (i32.const 0) (i32.const 12) (i32.const 0)))
;; check arrays were not modified
(assert_return (invoke "array_get_nth" (i32.const 0)) (i32.const 0))
(assert_return (invoke "array_get_nth" (i32.const 5)) (i32.const 0))
(assert_return (invoke "array_get_nth" (i32.const 11)) (i32.const 0))
(assert_trap (invoke "array_get_nth" (i32.const 12)) "out of bounds array access")
;; normal case
(assert_return (invoke "array_copy" (i32.const 0) (i32.const 0) (i32.const 2)))
(assert_return (invoke "array_get_nth" (i32.const 0)) (i32.const 10))
(assert_return (invoke "array_get_nth" (i32.const 1)) (i32.const 10))
(assert_return (invoke "array_get_nth" (i32.const 2)) (i32.const 0))
;; test that overlapping array.copy works as if intermediate copy taken
(assert_return (invoke "array_copy_overlap_test-1"))
(assert_return (invoke "array_get_nth" (i32.const 0)) (i32.const 97))
(assert_return (invoke "array_get_nth" (i32.const 1)) (i32.const 97))
(assert_return (invoke "array_get_nth" (i32.const 2)) (i32.const 98))
(assert_return (invoke "array_get_nth" (i32.const 5)) (i32.const 101))
(assert_return (invoke "array_get_nth" (i32.const 10)) (i32.const 106))
(assert_return (invoke "array_get_nth" (i32.const 11)) (i32.const 107))
(assert_return (invoke "array_copy_overlap_test-2"))
(assert_return (invoke "array_get_nth" (i32.const 0)) (i32.const 98))
(assert_return (invoke "array_get_nth" (i32.const 1)) (i32.const 99))
(assert_return (invoke "array_get_nth" (i32.const 5)) (i32.const 103))
(assert_return (invoke "array_get_nth" (i32.const 9)) (i32.const 107))
(assert_return (invoke "array_get_nth" (i32.const 10)) (i32.const 108))
(assert_return (invoke "array_get_nth" (i32.const 11)) (i32.const 108))

View File

@ -0,0 +1,81 @@
;; Bulk instructions
;; invalid uses
(assert_invalid
(module
(type $a (array i8))
(func (export "array.fill-immutable") (param $1 (ref $a)) (param $2 i32)
(array.fill $a (local.get $1) (i32.const 0) (local.get $2) (i32.const 0))
)
)
"array is immutable"
)
(assert_invalid
(module
(type $a (array (mut i8)))
(func (export "array.fill-invalid-1") (param $1 (ref $a)) (param $2 funcref)
(array.fill $a (local.get $1) (i32.const 0) (local.get $2) (i32.const 0))
)
)
"type mismatch"
)
(assert_invalid
(module
(type $b (array (mut funcref)))
(func (export "array.fill-invalid-1") (param $1 (ref $b)) (param $2 i32)
(array.fill $b (local.get $1) (i32.const 0) (local.get $2) (i32.const 0))
)
)
"type mismatch"
)
(module
(type $arr8 (array i8))
(type $arr8_mut (array (mut i8)))
(global $g_arr8 (ref $arr8) (array.new $arr8 (i32.const 10) (i32.const 12)))
(global $g_arr8_mut (mut (ref $arr8_mut)) (array.new_default $arr8_mut (i32.const 12)))
(func (export "array_get_nth") (param $1 i32) (result i32)
(array.get_u $arr8_mut (global.get $g_arr8_mut) (local.get $1))
)
(func (export "array_fill-null")
(array.fill $arr8_mut (ref.null $arr8_mut) (i32.const 0) (i32.const 0) (i32.const 0))
)
(func (export "array_fill") (param $1 i32) (param $2 i32) (param $3 i32)
(array.fill $arr8_mut (global.get $g_arr8_mut) (local.get $1) (local.get $2) (local.get $3))
)
)
;; null array argument traps
(assert_trap (invoke "array_fill-null") "null array reference")
;; OOB initial index traps
(assert_trap (invoke "array_fill" (i32.const 13) (i32.const 0) (i32.const 0)) "out of bounds array access")
;; OOB length traps
(assert_trap (invoke "array_fill" (i32.const 0) (i32.const 0) (i32.const 13)) "out of bounds array access")
;; start index = array size, len = 0 doesn't trap
(assert_return (invoke "array_fill" (i32.const 12) (i32.const 0) (i32.const 0)))
;; check arrays were not modified
(assert_return (invoke "array_get_nth" (i32.const 0)) (i32.const 0))
(assert_return (invoke "array_get_nth" (i32.const 5)) (i32.const 0))
(assert_return (invoke "array_get_nth" (i32.const 11)) (i32.const 0))
(assert_trap (invoke "array_get_nth" (i32.const 12)) "out of bounds array access")
;; normal case
(assert_return (invoke "array_fill" (i32.const 2) (i32.const 11) (i32.const 2)))
(assert_return (invoke "array_get_nth" (i32.const 1)) (i32.const 0))
(assert_return (invoke "array_get_nth" (i32.const 2)) (i32.const 11))
(assert_return (invoke "array_get_nth" (i32.const 3)) (i32.const 11))
(assert_return (invoke "array_get_nth" (i32.const 4)) (i32.const 0))

View File

@ -0,0 +1,267 @@
;; Abstract Types
(module
(type $ft (func (result i32)))
(type $st (struct (field i16)))
(type $at (array i8))
(table 10 anyref)
(elem declare func $f)
(func $f (result i32) (i32.const 9))
(func (export "init") (param $x externref)
(table.set (i32.const 0) (ref.null any))
(table.set (i32.const 1) (ref.i31 (i32.const 7)))
(table.set (i32.const 2) (struct.new $st (i32.const 6)))
(table.set (i32.const 3) (array.new $at (i32.const 5) (i32.const 3)))
(table.set (i32.const 4) (any.convert_extern (local.get $x)))
)
(func (export "br_on_null") (param $i i32) (result i32)
(block $l
(br_on_null $l (table.get (local.get $i)))
(return (i32.const -1))
)
(i32.const 0)
)
(func (export "br_on_i31") (param $i i32) (result i32)
(block $l (result (ref i31))
(br_on_cast $l anyref (ref i31) (table.get (local.get $i)))
(return (i32.const -1))
)
(i31.get_u)
)
(func (export "br_on_struct") (param $i i32) (result i32)
(block $l (result (ref struct))
(br_on_cast $l anyref (ref struct) (table.get (local.get $i)))
(return (i32.const -1))
)
(block $l2 (param structref) (result (ref $st))
(block $l3 (param structref) (result (ref $at))
(br_on_cast $l2 structref (ref $st))
(br_on_cast $l3 anyref (ref $at))
(return (i32.const -2))
)
(return (array.get_u $at (i32.const 0)))
)
(struct.get_s $st 0)
)
(func (export "br_on_array") (param $i i32) (result i32)
(block $l (result (ref array))
(br_on_cast $l anyref (ref array) (table.get (local.get $i)))
(return (i32.const -1))
)
(array.len)
)
(func (export "null-diff") (param $i i32) (result i32)
(block $l (result (ref null struct))
(block (result (ref any))
(br_on_cast $l (ref null any) (ref null struct) (table.get (local.get $i)))
)
(return (i32.const 0))
)
(return (i32.const 1))
)
)
(invoke "init" (ref.extern 0))
(assert_return (invoke "br_on_null" (i32.const 0)) (i32.const 0))
(assert_return (invoke "br_on_null" (i32.const 1)) (i32.const -1))
(assert_return (invoke "br_on_null" (i32.const 2)) (i32.const -1))
(assert_return (invoke "br_on_null" (i32.const 3)) (i32.const -1))
(assert_return (invoke "br_on_null" (i32.const 4)) (i32.const -1))
(assert_return (invoke "br_on_i31" (i32.const 0)) (i32.const -1))
(assert_return (invoke "br_on_i31" (i32.const 1)) (i32.const 7))
(assert_return (invoke "br_on_i31" (i32.const 2)) (i32.const -1))
(assert_return (invoke "br_on_i31" (i32.const 3)) (i32.const -1))
(assert_return (invoke "br_on_i31" (i32.const 4)) (i32.const -1))
(assert_return (invoke "br_on_struct" (i32.const 0)) (i32.const -1))
(assert_return (invoke "br_on_struct" (i32.const 1)) (i32.const -1))
(assert_return (invoke "br_on_struct" (i32.const 2)) (i32.const 6))
(assert_return (invoke "br_on_struct" (i32.const 3)) (i32.const -1))
(assert_return (invoke "br_on_struct" (i32.const 4)) (i32.const -1))
(assert_return (invoke "br_on_array" (i32.const 0)) (i32.const -1))
(assert_return (invoke "br_on_array" (i32.const 1)) (i32.const -1))
(assert_return (invoke "br_on_array" (i32.const 2)) (i32.const -1))
(assert_return (invoke "br_on_array" (i32.const 3)) (i32.const 3))
(assert_return (invoke "br_on_array" (i32.const 4)) (i32.const -1))
(assert_return (invoke "null-diff" (i32.const 0)) (i32.const 1))
(assert_return (invoke "null-diff" (i32.const 1)) (i32.const 0))
(assert_return (invoke "null-diff" (i32.const 2)) (i32.const 1))
(assert_return (invoke "null-diff" (i32.const 3)) (i32.const 0))
(assert_return (invoke "null-diff" (i32.const 4)) (i32.const 0))
;; Concrete Types
(module
(type $t0 (sub (struct)))
(type $t1 (sub $t0 (struct (field i32))))
(type $t1' (sub $t0 (struct (field i32))))
(type $t2 (sub $t1 (struct (field i32 i32))))
(type $t2' (sub $t1' (struct (field i32 i32))))
(type $t3 (sub $t0 (struct (field i32 i32))))
(type $t0' (sub $t0 (struct)))
(type $t4 (sub $t0' (struct (field i32 i32))))
(table 20 structref)
(func $init
(table.set (i32.const 0) (struct.new_default $t0))
(table.set (i32.const 10) (struct.new_default $t0'))
(table.set (i32.const 1) (struct.new_default $t1))
(table.set (i32.const 11) (struct.new_default $t1'))
(table.set (i32.const 2) (struct.new_default $t2))
(table.set (i32.const 12) (struct.new_default $t2'))
(table.set (i32.const 3) (struct.new_default $t3))
(table.set (i32.const 4) (struct.new_default $t4))
)
(func (export "test-sub")
(call $init)
(block $l (result structref)
;; must succeed
(drop (block (result structref) (br_on_cast 0 structref (ref $t0) (ref.null struct))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t0) (table.get (i32.const 0)))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t0) (table.get (i32.const 1)))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t0) (table.get (i32.const 2)))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t0) (table.get (i32.const 3)))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t0) (table.get (i32.const 4)))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t1) (ref.null struct))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t1) (table.get (i32.const 1)))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t1) (table.get (i32.const 2)))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t2) (ref.null struct))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t2) (table.get (i32.const 2)))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t3) (ref.null struct))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t3) (table.get (i32.const 3)))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t4) (ref.null struct))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t4) (table.get (i32.const 4)))))
;; must not succeed
(br_on_cast $l anyref (ref $t1) (table.get (i32.const 0)))
(br_on_cast $l anyref (ref $t1) (table.get (i32.const 3)))
(br_on_cast $l anyref (ref $t1) (table.get (i32.const 4)))
(br_on_cast $l anyref (ref $t2) (table.get (i32.const 0)))
(br_on_cast $l anyref (ref $t2) (table.get (i32.const 1)))
(br_on_cast $l anyref (ref $t2) (table.get (i32.const 3)))
(br_on_cast $l anyref (ref $t2) (table.get (i32.const 4)))
(br_on_cast $l anyref (ref $t3) (table.get (i32.const 0)))
(br_on_cast $l anyref (ref $t3) (table.get (i32.const 1)))
(br_on_cast $l anyref (ref $t3) (table.get (i32.const 2)))
(br_on_cast $l anyref (ref $t3) (table.get (i32.const 4)))
(br_on_cast $l anyref (ref $t4) (table.get (i32.const 0)))
(br_on_cast $l anyref (ref $t4) (table.get (i32.const 1)))
(br_on_cast $l anyref (ref $t4) (table.get (i32.const 2)))
(br_on_cast $l anyref (ref $t4) (table.get (i32.const 3)))
(return)
)
(unreachable)
)
(func (export "test-canon")
(call $init)
(block $l
(drop (block (result structref) (br_on_cast 0 structref (ref $t0') (table.get (i32.const 0)))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t0') (table.get (i32.const 1)))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t0') (table.get (i32.const 2)))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t0') (table.get (i32.const 3)))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t0') (table.get (i32.const 4)))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t0) (table.get (i32.const 10)))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t0) (table.get (i32.const 11)))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t0) (table.get (i32.const 12)))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t1') (table.get (i32.const 1)))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t1') (table.get (i32.const 2)))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t1) (table.get (i32.const 11)))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t1) (table.get (i32.const 12)))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t2') (table.get (i32.const 2)))))
(drop (block (result structref) (br_on_cast 0 structref (ref $t2) (table.get (i32.const 12)))))
(return)
)
(unreachable)
)
)
(invoke "test-sub")
(invoke "test-canon")
;; Cases of nullability
(module
(type $t (struct))
(func (param (ref any)) (result (ref $t))
(block (result (ref any)) (br_on_cast 1 (ref any) (ref $t) (local.get 0))) (unreachable)
)
(func (param (ref null any)) (result (ref $t))
(block (result (ref null any)) (br_on_cast 1 (ref null any) (ref $t) (local.get 0))) (unreachable)
)
(func (param (ref null any)) (result (ref null $t))
(block (result (ref null any)) (br_on_cast 1 (ref null any) (ref null $t) (local.get 0))) (unreachable)
)
)
(assert_invalid
(module
(type $t (struct))
(func (param (ref any)) (result (ref $t))
(block (result (ref any)) (br_on_cast 1 (ref null any) (ref null $t) (local.get 0))) (unreachable)
)
)
"type mismatch"
)
(assert_invalid
(module
(type $t (struct))
(func (param (ref any)) (result (ref null $t))
(block (result (ref any)) (br_on_cast 1 (ref any) (ref null $t) (local.get 0))) (unreachable)
)
)
"type mismatch"
)
(assert_invalid
(module
(type $t (struct))
(func (param (ref null any)) (result (ref $t))
(block (result (ref any)) (br_on_cast 1 (ref null any) (ref $t) (local.get 0))) (unreachable)
)
)
"type mismatch"
)
(assert_invalid
(module
(func (result anyref)
(br_on_cast 0 eqref anyref (unreachable))
)
)
"type mismatch"
)
(assert_invalid
(module
(func (result anyref)
(br_on_cast 0 structref arrayref (unreachable))
)
)
"type mismatch"
)

View File

@ -0,0 +1,282 @@
;; Abstract Types
(module
(type $ft (func (result i32)))
(type $st (struct (field i16)))
(type $at (array i8))
(table 10 anyref)
(elem declare func $f)
(func $f (result i32) (i32.const 9))
(func (export "init") (param $x externref)
(table.set (i32.const 0) (ref.null any))
(table.set (i32.const 1) (ref.i31 (i32.const 7)))
(table.set (i32.const 2) (struct.new $st (i32.const 6)))
(table.set (i32.const 3) (array.new $at (i32.const 5) (i32.const 3)))
(table.set (i32.const 4) (any.convert_extern (local.get $x)))
)
(func (export "br_on_non_null") (param $i i32) (result i32)
(block $l (result (ref any))
(br_on_non_null $l (table.get (local.get $i)))
(return (i32.const 0))
)
(return (i32.const -1))
)
(func (export "br_on_non_i31") (param $i i32) (result i32)
(block $l (result anyref)
(br_on_cast_fail $l anyref (ref i31) (table.get (local.get $i)))
(return (i31.get_u))
)
(return (i32.const -1))
)
(func (export "br_on_non_struct") (param $i i32) (result i32)
(block $l (result anyref)
(br_on_cast_fail $l anyref (ref struct) (table.get (local.get $i)))
(block $l2 (param structref) (result (ref $st))
(block $l3 (param structref) (result (ref $at))
(br_on_cast $l2 structref (ref $st))
(br_on_cast $l3 anyref (ref $at))
(return (i32.const -2))
)
(return (array.get_u $at (i32.const 0)))
)
(return (struct.get_s $st 0))
)
(return (i32.const -1))
)
(func (export "br_on_non_array") (param $i i32) (result i32)
(block $l (result anyref)
(br_on_cast_fail $l anyref (ref array) (table.get (local.get $i)))
(return (array.len))
)
(return (i32.const -1))
)
(func (export "null-diff") (param $i i32) (result i32)
(block $l (result (ref any))
(block (result (ref null struct))
(br_on_cast_fail $l (ref null any) (ref null struct) (table.get (local.get $i)))
)
(return (i32.const 1))
)
(return (i32.const 0))
)
)
(invoke "init" (ref.extern 0))
(assert_return (invoke "br_on_non_null" (i32.const 0)) (i32.const 0))
(assert_return (invoke "br_on_non_null" (i32.const 1)) (i32.const -1))
(assert_return (invoke "br_on_non_null" (i32.const 2)) (i32.const -1))
(assert_return (invoke "br_on_non_null" (i32.const 3)) (i32.const -1))
(assert_return (invoke "br_on_non_null" (i32.const 4)) (i32.const -1))
(assert_return (invoke "br_on_non_i31" (i32.const 0)) (i32.const -1))
(assert_return (invoke "br_on_non_i31" (i32.const 1)) (i32.const 7))
(assert_return (invoke "br_on_non_i31" (i32.const 2)) (i32.const -1))
(assert_return (invoke "br_on_non_i31" (i32.const 3)) (i32.const -1))
(assert_return (invoke "br_on_non_i31" (i32.const 4)) (i32.const -1))
(assert_return (invoke "br_on_non_struct" (i32.const 0)) (i32.const -1))
(assert_return (invoke "br_on_non_struct" (i32.const 1)) (i32.const -1))
(assert_return (invoke "br_on_non_struct" (i32.const 2)) (i32.const 6))
(assert_return (invoke "br_on_non_struct" (i32.const 3)) (i32.const -1))
(assert_return (invoke "br_on_non_struct" (i32.const 4)) (i32.const -1))
(assert_return (invoke "br_on_non_array" (i32.const 0)) (i32.const -1))
(assert_return (invoke "br_on_non_array" (i32.const 1)) (i32.const -1))
(assert_return (invoke "br_on_non_array" (i32.const 2)) (i32.const -1))
(assert_return (invoke "br_on_non_array" (i32.const 3)) (i32.const 3))
(assert_return (invoke "br_on_non_array" (i32.const 4)) (i32.const -1))
(assert_return (invoke "null-diff" (i32.const 0)) (i32.const 1))
(assert_return (invoke "null-diff" (i32.const 1)) (i32.const 0))
(assert_return (invoke "null-diff" (i32.const 2)) (i32.const 1))
(assert_return (invoke "null-diff" (i32.const 3)) (i32.const 0))
(assert_return (invoke "null-diff" (i32.const 4)) (i32.const 0))
;; Concrete Types
(module
(type $t0 (sub (struct)))
(type $t1 (sub $t0 (struct (field i32))))
(type $t1' (sub $t0 (struct (field i32))))
(type $t2 (sub $t1 (struct (field i32 i32))))
(type $t2' (sub $t1' (struct (field i32 i32))))
(type $t3 (sub $t0 (struct (field i32 i32))))
(type $t0' (sub $t0 (struct)))
(type $t4 (sub $t0' (struct (field i32 i32))))
(table 20 structref)
(func $init
(table.set (i32.const 0) (struct.new_default $t0))
(table.set (i32.const 10) (struct.new_default $t0))
(table.set (i32.const 1) (struct.new_default $t1))
(table.set (i32.const 11) (struct.new_default $t1'))
(table.set (i32.const 2) (struct.new_default $t2))
(table.set (i32.const 12) (struct.new_default $t2'))
(table.set (i32.const 3) (struct.new_default $t3 ))
(table.set (i32.const 4) (struct.new_default $t4))
)
(func (export "test-sub")
(call $init)
(block $l (result structref)
;; must not succeed
(br_on_cast_fail $l structref (ref null $t0) (ref.null struct))
(br_on_cast_fail $l structref (ref null $t0) (table.get (i32.const 0)))
(br_on_cast_fail $l structref (ref null $t0) (table.get (i32.const 1)))
(br_on_cast_fail $l structref (ref null $t0) (table.get (i32.const 2)))
(br_on_cast_fail $l structref (ref null $t0) (table.get (i32.const 3)))
(br_on_cast_fail $l structref (ref null $t0) (table.get (i32.const 4)))
(br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 0)))
(br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 1)))
(br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 2)))
(br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 3)))
(br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 4)))
(br_on_cast_fail $l structref (ref null $t1) (ref.null struct))
(br_on_cast_fail $l structref (ref null $t1) (table.get (i32.const 1)))
(br_on_cast_fail $l structref (ref null $t1) (table.get (i32.const 2)))
(br_on_cast_fail $l structref (ref $t1) (table.get (i32.const 1)))
(br_on_cast_fail $l structref (ref $t1) (table.get (i32.const 2)))
(br_on_cast_fail $l structref (ref null $t2) (ref.null struct))
(br_on_cast_fail $l structref (ref null $t2) (table.get (i32.const 2)))
(br_on_cast_fail $l structref (ref $t2) (table.get (i32.const 2)))
(br_on_cast_fail $l structref (ref null $t3) (ref.null struct))
(br_on_cast_fail $l structref (ref null $t3) (table.get (i32.const 3)))
(br_on_cast_fail $l structref (ref $t3) (table.get (i32.const 3)))
(br_on_cast_fail $l structref (ref null $t4) (ref.null struct))
(br_on_cast_fail $l structref (ref null $t4) (table.get (i32.const 4)))
(br_on_cast_fail $l structref (ref $t4) (table.get (i32.const 4)))
;; must succeed
(drop (block (result structref) (br_on_cast_fail 0 structref (ref $t0) (ref.null struct))))
(drop (block (result structref) (br_on_cast_fail 0 structref (ref $t1) (ref.null struct))))
(drop (block (result structref) (br_on_cast_fail 0 structref (ref $t1) (table.get (i32.const 0)))))
(drop (block (result structref) (br_on_cast_fail 0 structref (ref $t1) (table.get (i32.const 3)))))
(drop (block (result structref) (br_on_cast_fail 0 structref (ref $t1) (table.get (i32.const 4)))))
(drop (block (result structref) (br_on_cast_fail 0 structref (ref $t2) (ref.null struct))))
(drop (block (result structref) (br_on_cast_fail 0 structref (ref $t2) (table.get (i32.const 0)))))
(drop (block (result structref) (br_on_cast_fail 0 structref (ref $t2) (table.get (i32.const 1)))))
(drop (block (result structref) (br_on_cast_fail 0 structref (ref $t2) (table.get (i32.const 3)))))
(drop (block (result structref) (br_on_cast_fail 0 structref (ref $t2) (table.get (i32.const 4)))))
(drop (block (result structref) (br_on_cast_fail 0 structref (ref $t3) (ref.null struct))))
(drop (block (result structref) (br_on_cast_fail 0 structref (ref $t3) (table.get (i32.const 0)))))
(drop (block (result structref) (br_on_cast_fail 0 structref (ref $t3) (table.get (i32.const 1)))))
(drop (block (result structref) (br_on_cast_fail 0 structref (ref $t3) (table.get (i32.const 2)))))
(drop (block (result structref) (br_on_cast_fail 0 structref (ref $t3) (table.get (i32.const 4)))))
(drop (block (result structref) (br_on_cast_fail 0 structref (ref $t4) (ref.null struct))))
(drop (block (result structref) (br_on_cast_fail 0 structref (ref $t4) (table.get (i32.const 0)))))
(drop (block (result structref) (br_on_cast_fail 0 structref (ref $t4) (table.get (i32.const 1)))))
(drop (block (result structref) (br_on_cast_fail 0 structref (ref $t4) (table.get (i32.const 2)))))
(drop (block (result structref) (br_on_cast_fail 0 structref (ref $t4) (table.get (i32.const 3)))))
(return)
)
(unreachable)
)
(func (export "test-canon")
(call $init)
(block $l (result structref)
(br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 0)))
(br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 1)))
(br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 2)))
(br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 3)))
(br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 4)))
(br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 10)))
(br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 11)))
(br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 12)))
(br_on_cast_fail $l structref (ref $t1') (table.get (i32.const 1)))
(br_on_cast_fail $l structref (ref $t1') (table.get (i32.const 2)))
(br_on_cast_fail $l structref (ref $t1) (table.get (i32.const 11)))
(br_on_cast_fail $l structref (ref $t1) (table.get (i32.const 12)))
(br_on_cast_fail $l structref (ref $t2') (table.get (i32.const 2)))
(br_on_cast_fail $l structref (ref $t2) (table.get (i32.const 12)))
(return)
)
(unreachable)
)
)
(invoke "test-sub")
(invoke "test-canon")
;; Cases of nullability
(module
(type $t (struct))
(func (param (ref any)) (result (ref any))
(block (result (ref $t)) (br_on_cast_fail 1 (ref any) (ref $t) (local.get 0)))
)
(func (param (ref null any)) (result (ref null any))
(block (result (ref $t)) (br_on_cast_fail 1 (ref null any) (ref $t) (local.get 0)))
)
(func (param (ref null any)) (result (ref null any))
(block (result (ref null $t)) (br_on_cast_fail 1 (ref null any) (ref null $t) (local.get 0)))
)
)
(assert_invalid
(module
(type $t (struct))
(func (param (ref any)) (result (ref any))
(block (result (ref $t)) (br_on_cast_fail 1 (ref null any) (ref null $t) (local.get 0)))
)
)
"type mismatch"
)
(assert_invalid
(module
(type $t (struct))
(func (param (ref any)) (result (ref any))
(block (result (ref null $t)) (br_on_cast_fail 1 (ref any) (ref null $t) (local.get 0))) (ref.as_non_null)
)
)
"type mismatch"
)
(assert_invalid
(module
(type $t (struct))
(func (param (ref null any)) (result (ref any))
(block (result (ref $t)) (br_on_cast_fail 1 (ref null any) (ref $t) (local.get 0)))
)
)
"type mismatch"
)
(assert_invalid
(module
(func (result anyref)
(br_on_cast_fail 0 eqref anyref (unreachable))
)
)
"type mismatch"
)
(assert_invalid
(module
(func (result anyref)
(br_on_cast_fail 0 structref arrayref (unreachable))
)
)
"type mismatch"
)

View File

@ -0,0 +1,208 @@
(module
(type $ii (func (param i32) (result i32)))
(func $apply (param $f (ref $ii)) (param $x i32) (result i32)
(call_ref $ii (local.get $x) (local.get $f))
)
(func $f (type $ii) (i32.mul (local.get 0) (local.get 0)))
(func $g (type $ii) (i32.sub (i32.const 0) (local.get 0)))
(elem declare func $f $g)
(func (export "run") (param $x i32) (result i32)
(local $rf (ref null $ii))
(local $rg (ref null $ii))
(local.set $rf (ref.func $f))
(local.set $rg (ref.func $g))
(call_ref $ii (call_ref $ii (local.get $x) (local.get $rf)) (local.get $rg))
)
(func (export "null") (result i32)
(call_ref $ii (i32.const 1) (ref.null $ii))
)
;; Recursion
(type $ll (func (param i64) (result i64)))
(type $lll (func (param i64 i64) (result i64)))
(elem declare func $fac)
(global $fac (ref $ll) (ref.func $fac))
(func $fac (export "fac") (type $ll)
(if (result i64) (i64.eqz (local.get 0))
(then (i64.const 1))
(else
(i64.mul
(local.get 0)
(call_ref $ll (i64.sub (local.get 0) (i64.const 1)) (global.get $fac))
)
)
)
)
(elem declare func $fac-acc)
(global $fac-acc (ref $lll) (ref.func $fac-acc))
(func $fac-acc (export "fac-acc") (type $lll)
(if (result i64) (i64.eqz (local.get 0))
(then (local.get 1))
(else
(call_ref $lll
(i64.sub (local.get 0) (i64.const 1))
(i64.mul (local.get 0) (local.get 1))
(global.get $fac-acc)
)
)
)
)
(elem declare func $fib)
(global $fib (ref $ll) (ref.func $fib))
(func $fib (export "fib") (type $ll)
(if (result i64) (i64.le_u (local.get 0) (i64.const 1))
(then (i64.const 1))
(else
(i64.add
(call_ref $ll (i64.sub (local.get 0) (i64.const 2)) (global.get $fib))
(call_ref $ll (i64.sub (local.get 0) (i64.const 1)) (global.get $fib))
)
)
)
)
(elem declare func $even $odd)
(global $even (ref $ll) (ref.func $even))
(global $odd (ref $ll) (ref.func $odd))
(func $even (export "even") (type $ll)
(if (result i64) (i64.eqz (local.get 0))
(then (i64.const 44))
(else (call_ref $ll (i64.sub (local.get 0) (i64.const 1)) (global.get $odd)))
)
)
(func $odd (export "odd") (type $ll)
(if (result i64) (i64.eqz (local.get 0))
(then (i64.const 99))
(else (call_ref $ll (i64.sub (local.get 0) (i64.const 1)) (global.get $even)))
)
)
)
(assert_return (invoke "run" (i32.const 0)) (i32.const 0))
(assert_return (invoke "run" (i32.const 3)) (i32.const -9))
(assert_trap (invoke "null") "null function")
(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 "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 "fib" (i64.const 0)) (i64.const 1))
(assert_return (invoke "fib" (i64.const 1)) (i64.const 1))
(assert_return (invoke "fib" (i64.const 2)) (i64.const 2))
(assert_return (invoke "fib" (i64.const 5)) (i64.const 8))
(assert_return (invoke "fib" (i64.const 20)) (i64.const 10946))
(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 "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))
;; Unreachable typing.
(module
(type $t (func))
(func (export "unreachable") (result i32)
(unreachable)
(call_ref $t)
)
)
(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)
(ref.func $f)
(call_ref $t)
)
)
(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)
(i32.const 0)
(ref.func $f)
(call_ref $t)
(drop)
(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)
(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)
(call_ref $t)
(drop)
(i64.const 0)
)
)
"type mismatch"
)
(assert_invalid
(module
(type $t (func))
(func $f (param $r externref)
(call_ref $t (local.get $r))
)
)
"type mismatch"
)

View File

@ -0,0 +1,54 @@
(module
(type $ft (func))
(type $st (struct))
(type $at (array i8))
(table 10 anyref)
(elem declare func $f)
(func $f)
(func (export "init") (param $x externref)
(table.set (i32.const 0) (ref.null any))
(table.set (i32.const 1) (ref.i31 (i32.const 7)))
(table.set (i32.const 2) (struct.new_default $st))
(table.set (i32.const 3) (array.new_default $at (i32.const 0)))
(table.set (i32.const 4) (any.convert_extern (local.get $x)))
)
(func (export "internalize") (param externref) (result anyref)
(any.convert_extern (local.get 0))
)
(func (export "externalize") (param anyref) (result externref)
(extern.convert_any (local.get 0))
)
(func (export "externalize-i") (param i32) (result externref)
(extern.convert_any (table.get (local.get 0)))
)
(func (export "externalize-ii") (param i32) (result anyref)
(any.convert_extern (extern.convert_any (table.get (local.get 0))))
)
)
(invoke "init" (ref.extern 0))
(assert_return (invoke "internalize" (ref.extern 1)) (ref.host 1))
(assert_return (invoke "internalize" (ref.null extern)) (ref.null any))
(assert_return (invoke "externalize" (ref.host 2)) (ref.extern 2))
(assert_return (invoke "externalize" (ref.null any)) (ref.null extern))
(assert_return (invoke "externalize-i" (i32.const 0)) (ref.null extern))
(assert_return (invoke "externalize-i" (i32.const 1)) (ref.extern))
(assert_return (invoke "externalize-i" (i32.const 2)) (ref.extern))
(assert_return (invoke "externalize-i" (i32.const 3)) (ref.extern))
(assert_return (invoke "externalize-i" (i32.const 4)) (ref.extern 0))
(assert_return (invoke "externalize-i" (i32.const 5)) (ref.null extern))
(assert_return (invoke "externalize-ii" (i32.const 0)) (ref.null any))
(assert_return (invoke "externalize-ii" (i32.const 1)) (ref.i31))
(assert_return (invoke "externalize-ii" (i32.const 2)) (ref.struct))
(assert_return (invoke "externalize-ii" (i32.const 3)) (ref.array))
(assert_return (invoke "externalize-ii" (i32.const 4)) (ref.host 0))
(assert_return (invoke "externalize-ii" (i32.const 5)) (ref.null any))

View File

@ -0,0 +1,51 @@
(module
(func (export "new") (param $i i32) (result (ref i31))
(ref.i31 (local.get $i))
)
(func (export "get_u") (param $i i32) (result i32)
(i31.get_u (ref.i31 (local.get $i)))
)
(func (export "get_s") (param $i i32) (result i32)
(i31.get_s (ref.i31 (local.get $i)))
)
(func (export "get_u-null") (result i32)
(i31.get_u (ref.null i31))
)
(func (export "get_s-null") (result i32)
(i31.get_u (ref.null i31))
)
(global $i (ref i31) (ref.i31 (i32.const 2)))
(global $m (mut (ref i31)) (ref.i31 (i32.const 3)))
(func (export "get_globals") (result i32 i32)
(i31.get_u (global.get $i))
(i31.get_u (global.get $m))
)
)
(assert_return (invoke "new" (i32.const 1)) (ref.i31))
(assert_return (invoke "get_u" (i32.const 0)) (i32.const 0))
(assert_return (invoke "get_u" (i32.const 100)) (i32.const 100))
(assert_return (invoke "get_u" (i32.const -1)) (i32.const 0x7fff_ffff))
(assert_return (invoke "get_u" (i32.const 0x3fff_ffff)) (i32.const 0x3fff_ffff))
(assert_return (invoke "get_u" (i32.const 0x4000_0000)) (i32.const 0x4000_0000))
(assert_return (invoke "get_u" (i32.const 0x7fff_ffff)) (i32.const 0x7fff_ffff))
(assert_return (invoke "get_u" (i32.const 0xaaaa_aaaa)) (i32.const 0x2aaa_aaaa))
(assert_return (invoke "get_u" (i32.const 0xcaaa_aaaa)) (i32.const 0x4aaa_aaaa))
(assert_return (invoke "get_s" (i32.const 0)) (i32.const 0))
(assert_return (invoke "get_s" (i32.const 100)) (i32.const 100))
(assert_return (invoke "get_s" (i32.const -1)) (i32.const -1))
(assert_return (invoke "get_s" (i32.const 0x3fff_ffff)) (i32.const 0x3fff_ffff))
(assert_return (invoke "get_s" (i32.const 0x4000_0000)) (i32.const -0x4000_0000))
(assert_return (invoke "get_s" (i32.const 0x7fff_ffff)) (i32.const -1))
(assert_return (invoke "get_s" (i32.const 0xaaaa_aaaa)) (i32.const 0x2aaa_aaaa))
(assert_return (invoke "get_s" (i32.const 0xcaaa_aaaa)) (i32.const 0xcaaa_aaaa))
(assert_trap (invoke "get_u-null") "null i31 reference")
(assert_trap (invoke "get_s-null") "null i31 reference")
(assert_return (invoke "get_globals") (i32.const 2) (i32.const 3))

View File

@ -0,0 +1,362 @@
;; Test `local.set` operator
(module
;; Typing
(func (export "type-local-i32") (local i32) (local.set 0 (i32.const 0)))
(func (export "type-local-i64") (local i64) (local.set 0 (i64.const 0)))
(func (export "type-local-f32") (local f32) (local.set 0 (f32.const 0)))
(func (export "type-local-f64") (local f64) (local.set 0 (f64.const 0)))
(func (export "type-param-i32") (param i32) (local.set 0 (i32.const 10)))
(func (export "type-param-i64") (param i64) (local.set 0 (i64.const 11)))
(func (export "type-param-f32") (param f32) (local.set 0 (f32.const 11.1)))
(func (export "type-param-f64") (param f64) (local.set 0 (f64.const 12.2)))
(func (export "type-mixed") (param i64 f32 f64 i32 i32) (local f32 i64 i64 f64)
(local.set 0 (i64.const 0))
(local.set 1 (f32.const 0))
(local.set 2 (f64.const 0))
(local.set 3 (i32.const 0))
(local.set 4 (i32.const 0))
(local.set 5 (f32.const 0))
(local.set 6 (i64.const 0))
(local.set 7 (i64.const 0))
(local.set 8 (f64.const 0))
)
;; Writing
(func (export "write") (param i64 f32 f64 i32 i32) (result i64)
(local f32 i64 i64 f64)
(local.set 1 (f32.const -0.3))
(local.set 3 (i32.const 40))
(local.set 4 (i32.const -7))
(local.set 5 (f32.const 5.5))
(local.set 6 (i64.const 6))
(local.set 8 (f64.const 8))
(i64.trunc_f64_s
(f64.add
(f64.convert_i64_u (local.get 0))
(f64.add
(f64.promote_f32 (local.get 1))
(f64.add
(local.get 2)
(f64.add
(f64.convert_i32_u (local.get 3))
(f64.add
(f64.convert_i32_s (local.get 4))
(f64.add
(f64.promote_f32 (local.get 5))
(f64.add
(f64.convert_i64_u (local.get 6))
(f64.add
(f64.convert_i64_u (local.get 7))
(local.get 8)
)
)
)
)
)
)
)
)
)
)
;; As parameter of control constructs and instructions
(func (export "as-block-value") (param i32)
(block (local.set 0 (i32.const 1)))
)
(func (export "as-loop-value") (param i32)
(loop (local.set 0 (i32.const 3)))
)
(func (export "as-br-value") (param i32)
(block (br 0 (local.set 0 (i32.const 9))))
)
(func (export "as-br_if-value") (param i32)
(block
(br_if 0 (local.set 0 (i32.const 8)) (i32.const 1))
)
)
(func (export "as-br_if-value-cond") (param i32)
(block
(br_if 0 (i32.const 6) (local.set 0 (i32.const 9)))
)
)
(func (export "as-br_table-value") (param i32)
(block
(br_table 0 (local.set 0 (i32.const 10)) (i32.const 1))
)
)
(func (export "as-return-value") (param i32)
(return (local.set 0 (i32.const 7)))
)
(func (export "as-if-then") (param i32)
(if (local.get 0) (then (local.set 0 (i32.const 3))))
)
(func (export "as-if-else") (param i32)
(if (local.get 0) (then) (else (local.set 0 (i32.const 1))))
)
)
(assert_return (invoke "type-local-i32"))
(assert_return (invoke "type-local-i64"))
(assert_return (invoke "type-local-f32"))
(assert_return (invoke "type-local-f64"))
(assert_return (invoke "type-param-i32" (i32.const 2)))
(assert_return (invoke "type-param-i64" (i64.const 3)))
(assert_return (invoke "type-param-f32" (f32.const 4.4)))
(assert_return (invoke "type-param-f64" (f64.const 5.5)))
(assert_return (invoke "as-block-value" (i32.const 0)))
(assert_return (invoke "as-loop-value" (i32.const 0)))
(assert_return (invoke "as-br-value" (i32.const 0)))
(assert_return (invoke "as-br_if-value" (i32.const 0)))
(assert_return (invoke "as-br_if-value-cond" (i32.const 0)))
(assert_return (invoke "as-br_table-value" (i32.const 0)))
(assert_return (invoke "as-return-value" (i32.const 0)))
(assert_return (invoke "as-if-then" (i32.const 1)))
(assert_return (invoke "as-if-else" (i32.const 0)))
(assert_return
(invoke "type-mixed"
(i64.const 1) (f32.const 2.2) (f64.const 3.3) (i32.const 4) (i32.const 5)
)
)
(assert_return
(invoke "write"
(i64.const 1) (f32.const 2) (f64.const 3.3) (i32.const 4) (i32.const 5)
)
(i64.const 56)
)
;; Invalid typing of access to locals
(assert_invalid
(module (func $type-local-arg-void-vs-num (local i32) (local.set 0 (nop))))
"type mismatch"
)
(assert_invalid
(module (func $type-local-arg-num-vs-num (local i32) (local.set 0 (f32.const 0))))
"type mismatch"
)
(assert_invalid
(module (func $type-local-arg-num-vs-num (local f32) (local.set 0 (f64.const 0))))
"type mismatch"
)
(assert_invalid
(module (func $type-local-arg-num-vs-num (local f64 i64) (local.set 1 (f64.const 0))))
"type mismatch"
)
;; Invalid typing of access to parameters
(assert_invalid
(module (func $type-param-arg-void-vs-num (param i32) (local.set 0 (nop))))
"type mismatch"
)
(assert_invalid
(module (func $type-param-arg-num-vs-num (param i32) (local.set 0 (f32.const 0))))
"type mismatch"
)
(assert_invalid
(module (func $type-param-arg-num-vs-num (param f32) (local.set 0 (f64.const 0))))
"type mismatch"
)
(assert_invalid
(module (func $type-param-arg-num-vs-num (param f64 i64) (local.set 1 (f64.const 0))))
"type mismatch"
)
(assert_invalid
(module
(func $type-param-arg-empty-vs-num (param i32)
(local.set 0)
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-param-arg-empty-vs-num-in-block (param i32)
(i32.const 0)
(block (local.set 0))
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-param-arg-empty-vs-num-in-loop (param i32)
(i32.const 0)
(loop (local.set 0))
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-param-arg-empty-vs-num-in-then (param i32)
(i32.const 0)
(if (i32.const 1) (then (local.set 0)))
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-param-arg-empty-vs-num-in-else (param i32)
(i32.const 0)
(if (result i32) (i32.const 0) (then (i32.const 0)) (else (local.set 0)))
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-param-arg-empty-vs-num-in-br (param i32)
(i32.const 0)
(block (br 0 (local.set 0)))
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-param-arg-empty-vs-num-in-br_if (param i32)
(i32.const 0)
(block (br_if 0 (local.set 0)))
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-param-arg-empty-vs-num-in-br_table (param i32)
(i32.const 0)
(block (br_table 0 (local.set 0)))
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-param-arg-empty-vs-num-in-return (param i32)
(return (local.set 0))
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-param-arg-empty-vs-num-in-select (param i32)
(select (local.set 0) (i32.const 1) (i32.const 2))
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-param-arg-empty-vs-num-in-call (param i32)
(call 1 (local.set 0))
)
(func (param i32) (result i32) (local.get 0))
)
"type mismatch"
)
(assert_invalid
(module
(func $f (param i32) (result i32) (local.get 0))
(type $sig (func (param i32) (result i32)))
(table funcref (elem $f))
(func $type-param-arg-empty-vs-num-in-call_indirect (param i32)
(block (result i32)
(call_indirect (type $sig)
(local.set 0) (i32.const 0)
)
)
)
)
"type mismatch"
)
;; Invalid typing of access to mixed args
(assert_invalid
(module (func $type-mixed-arg-num-vs-num (param f32) (local i32) (local.set 1 (f32.const 0))))
"type mismatch"
)
(assert_invalid
(module (func $type-mixed-arg-num-vs-num (param i64 i32) (local f32) (local.set 1 (f32.const 0))))
"type mismatch"
)
(assert_invalid
(module (func $type-mixed-arg-num-vs-num (param i64) (local f64 i64) (local.set 1 (i64.const 0))))
"type mismatch"
)
;; local.set should have no retval
(assert_invalid
(module (func $type-empty-vs-i32 (param i32) (result i32) (local.set 0 (i32.const 1))))
"type mismatch"
)
(assert_invalid
(module (func $type-empty-vs-i64 (param i64) (result i64) (local.set 0 (i64.const 1))))
"type mismatch"
)
(assert_invalid
(module (func $type-empty-vs-f32 (param f32) (result f32) (local.set 0 (f32.const 1))))
"type mismatch"
)
(assert_invalid
(module (func $type-empty-vs-f64 (param f64) (result f64) (local.set 0 (f64.const 1))))
"type mismatch"
)
;; Invalid local index
(assert_invalid
(module (func $unbound-local (local i32 i64) (local.set 3 (i32.const 0))))
"unknown local"
)
(assert_invalid
(module (func $large-local (local i32 i64) (local.set 14324343 (i32.const 0))))
"unknown local"
)
(assert_invalid
(module (func $unbound-param (param i32 i64) (local.set 2 (i32.const 0))))
"unknown local"
)
(assert_invalid
(module (func $large-param (param i32 i64) (local.set 714324343 (i32.const 0))))
"unknown local"
)
(assert_invalid
(module (func $unbound-mixed (param i32) (local i32 i64) (local.set 3 (i32.const 0))))
"unknown local"
)
(assert_invalid
(module (func $large-mixed (param i64) (local i32 i64) (local.set 214324343 (i32.const 0))))
"unknown local"
)

View File

@ -0,0 +1,639 @@
;; Test `local.tee` operator
(module
;; Typing
(func (export "type-local-i32") (result i32) (local i32) (local.tee 0 (i32.const 0)))
(func (export "type-local-i64") (result i64) (local i64) (local.tee 0 (i64.const 0)))
(func (export "type-local-f32") (result f32) (local f32) (local.tee 0 (f32.const 0)))
(func (export "type-local-f64") (result f64) (local f64) (local.tee 0 (f64.const 0)))
(func (export "type-param-i32") (param i32) (result i32) (local.tee 0 (i32.const 10)))
(func (export "type-param-i64") (param i64) (result i64) (local.tee 0 (i64.const 11)))
(func (export "type-param-f32") (param f32) (result f32) (local.tee 0 (f32.const 11.1)))
(func (export "type-param-f64") (param f64) (result f64) (local.tee 0 (f64.const 12.2)))
(func (export "type-mixed") (param i64 f32 f64 i32 i32) (local f32 i64 i64 f64)
(drop (i64.eqz (local.tee 0 (i64.const 0))))
(drop (f32.neg (local.tee 1 (f32.const 0))))
(drop (f64.neg (local.tee 2 (f64.const 0))))
(drop (i32.eqz (local.tee 3 (i32.const 0))))
(drop (i32.eqz (local.tee 4 (i32.const 0))))
(drop (f32.neg (local.tee 5 (f32.const 0))))
(drop (i64.eqz (local.tee 6 (i64.const 0))))
(drop (i64.eqz (local.tee 7 (i64.const 0))))
(drop (f64.neg (local.tee 8 (f64.const 0))))
)
;; Writing
(func (export "write") (param i64 f32 f64 i32 i32) (result i64) (local f32 i64 i64 f64)
(drop (local.tee 1 (f32.const -0.3)))
(drop (local.tee 3 (i32.const 40)))
(drop (local.tee 4 (i32.const -7)))
(drop (local.tee 5 (f32.const 5.5)))
(drop (local.tee 6 (i64.const 6)))
(drop (local.tee 8 (f64.const 8)))
(i64.trunc_f64_s
(f64.add
(f64.convert_i64_u (local.get 0))
(f64.add
(f64.promote_f32 (local.get 1))
(f64.add
(local.get 2)
(f64.add
(f64.convert_i32_u (local.get 3))
(f64.add
(f64.convert_i32_s (local.get 4))
(f64.add
(f64.promote_f32 (local.get 5))
(f64.add
(f64.convert_i64_u (local.get 6))
(f64.add
(f64.convert_i64_u (local.get 7))
(local.get 8)
)
)
)
)
)
)
)
)
)
)
;; Result
(func (export "result") (param i64 f32 f64 i32 i32) (result f64)
(local f32 i64 i64 f64)
(f64.add
(f64.convert_i64_u (local.tee 0 (i64.const 1)))
(f64.add
(f64.promote_f32 (local.tee 1 (f32.const 2)))
(f64.add
(local.tee 2 (f64.const 3.3))
(f64.add
(f64.convert_i32_u (local.tee 3 (i32.const 4)))
(f64.add
(f64.convert_i32_s (local.tee 4 (i32.const 5)))
(f64.add
(f64.promote_f32 (local.tee 5 (f32.const 5.5)))
(f64.add
(f64.convert_i64_u (local.tee 6 (i64.const 6)))
(f64.add
(f64.convert_i64_u (local.tee 7 (i64.const 0)))
(local.tee 8 (f64.const 8))
)
)
)
)
)
)
)
)
)
(func $dummy)
(func (export "as-block-first") (param i32) (result i32)
(block (result i32) (local.tee 0 (i32.const 1)) (call $dummy))
)
(func (export "as-block-mid") (param i32) (result i32)
(block (result i32) (call $dummy) (local.tee 0 (i32.const 1)) (call $dummy))
)
(func (export "as-block-last") (param i32) (result i32)
(block (result i32) (call $dummy) (call $dummy) (local.tee 0 (i32.const 1)))
)
(func (export "as-loop-first") (param i32) (result i32)
(loop (result i32) (local.tee 0 (i32.const 3)) (call $dummy))
)
(func (export "as-loop-mid") (param i32) (result i32)
(loop (result i32) (call $dummy) (local.tee 0 (i32.const 4)) (call $dummy))
)
(func (export "as-loop-last") (param i32) (result i32)
(loop (result i32) (call $dummy) (call $dummy) (local.tee 0 (i32.const 5)))
)
(func (export "as-br-value") (param i32) (result i32)
(block (result i32) (br 0 (local.tee 0 (i32.const 9))))
)
(func (export "as-br_if-cond") (param i32)
(block (br_if 0 (local.tee 0 (i32.const 1))))
)
(func (export "as-br_if-value") (param i32) (result i32)
(block (result i32)
(drop (br_if 0 (local.tee 0 (i32.const 8)) (i32.const 1))) (i32.const 7)
)
)
(func (export "as-br_if-value-cond") (param i32) (result i32)
(block (result i32)
(drop (br_if 0 (i32.const 6) (local.tee 0 (i32.const 9)))) (i32.const 7)
)
)
(func (export "as-br_table-index") (param i32)
(block (br_table 0 0 0 (local.tee 0 (i32.const 0))))
)
(func (export "as-br_table-value") (param i32) (result i32)
(block (result i32)
(br_table 0 0 0 (local.tee 0 (i32.const 10)) (i32.const 1)) (i32.const 7)
)
)
(func (export "as-br_table-value-index") (param i32) (result i32)
(block (result i32)
(br_table 0 0 (i32.const 6) (local.tee 0 (i32.const 11))) (i32.const 7)
)
)
(func (export "as-return-value") (param i32) (result i32)
(return (local.tee 0 (i32.const 7)))
)
(func (export "as-if-cond") (param i32) (result i32)
(if (result i32) (local.tee 0 (i32.const 2))
(then (i32.const 0)) (else (i32.const 1))
)
)
(func (export "as-if-then") (param i32) (result i32)
(if (result i32) (local.get 0)
(then (local.tee 0 (i32.const 3))) (else (local.get 0))
)
)
(func (export "as-if-else") (param i32) (result i32)
(if (result i32) (local.get 0)
(then (local.get 0)) (else (local.tee 0 (i32.const 4)))
)
)
(func (export "as-select-first") (param i32 i32) (result i32)
(select (local.tee 0 (i32.const 5)) (local.get 0) (local.get 1))
)
(func (export "as-select-second") (param i32 i32) (result i32)
(select (local.get 0) (local.tee 0 (i32.const 6)) (local.get 1))
)
(func (export "as-select-cond") (param i32) (result i32)
(select (i32.const 0) (i32.const 1) (local.tee 0 (i32.const 7)))
)
(func $f (param i32 i32 i32) (result i32) (i32.const -1))
(func (export "as-call-first") (param i32) (result i32)
(call $f (local.tee 0 (i32.const 12)) (i32.const 2) (i32.const 3))
)
(func (export "as-call-mid") (param i32) (result i32)
(call $f (i32.const 1) (local.tee 0 (i32.const 13)) (i32.const 3))
)
(func (export "as-call-last") (param i32) (result i32)
(call $f (i32.const 1) (i32.const 2) (local.tee 0 (i32.const 14)))
)
(type $sig (func (param i32 i32 i32) (result i32)))
(table funcref (elem $f))
(func (export "as-call_indirect-first") (param i32) (result i32)
(call_indirect (type $sig)
(local.tee 0 (i32.const 1)) (i32.const 2) (i32.const 3) (i32.const 0)
)
)
(func (export "as-call_indirect-mid") (param i32) (result i32)
(call_indirect (type $sig)
(i32.const 1) (local.tee 0 (i32.const 2)) (i32.const 3) (i32.const 0)
)
)
(func (export "as-call_indirect-last") (param i32) (result i32)
(call_indirect (type $sig)
(i32.const 1) (i32.const 2) (local.tee 0 (i32.const 3)) (i32.const 0)
)
)
(func (export "as-call_indirect-index") (param i32) (result i32)
(call_indirect (type $sig)
(i32.const 1) (i32.const 2) (i32.const 3) (local.tee 0 (i32.const 0))
)
)
(func (export "as-local.set-value") (local i32)
(local.set 0 (local.tee 0 (i32.const 1)))
)
(func (export "as-local.tee-value") (param i32) (result i32)
(local.tee 0 (local.tee 0 (i32.const 1)))
)
(global $g (mut i32) (i32.const 0))
(func (export "as-global.set-value") (local i32)
(global.set $g (local.tee 0 (i32.const 1)))
)
(memory 1)
(func (export "as-load-address") (param i32) (result i32)
(i32.load (local.tee 0 (i32.const 1)))
)
(func (export "as-loadN-address") (param i32) (result i32)
(i32.load8_s (local.tee 0 (i32.const 3)))
)
(func (export "as-store-address") (param i32)
(i32.store (local.tee 0 (i32.const 30)) (i32.const 7))
)
(func (export "as-store-value") (param i32)
(i32.store (i32.const 2) (local.tee 0 (i32.const 1)))
)
(func (export "as-storeN-address") (param i32)
(i32.store8 (local.tee 0 (i32.const 1)) (i32.const 7))
)
(func (export "as-storeN-value") (param i32)
(i32.store16 (i32.const 2) (local.tee 0 (i32.const 1)))
)
(func (export "as-unary-operand") (param f32) (result f32)
(f32.neg (local.tee 0 (f32.const nan:0x0f1e2)))
)
(func (export "as-binary-left") (param i32) (result i32)
(i32.add (local.tee 0 (i32.const 3)) (i32.const 10))
)
(func (export "as-binary-right") (param i32) (result i32)
(i32.sub (i32.const 10) (local.tee 0 (i32.const 4)))
)
(func (export "as-test-operand") (param i32) (result i32)
(i32.eqz (local.tee 0 (i32.const 0)))
)
(func (export "as-compare-left") (param i32) (result i32)
(i32.le_s (local.tee 0 (i32.const 43)) (i32.const 10))
)
(func (export "as-compare-right") (param i32) (result i32)
(i32.ne (i32.const 10) (local.tee 0 (i32.const 42)))
)
(func (export "as-convert-operand") (param i64) (result i32)
(i32.wrap_i64 (local.tee 0 (i64.const 41)))
)
(func (export "as-memory.grow-size") (param i32) (result i32)
(memory.grow (local.tee 0 (i32.const 40)))
)
)
(assert_return (invoke "type-local-i32") (i32.const 0))
(assert_return (invoke "type-local-i64") (i64.const 0))
(assert_return (invoke "type-local-f32") (f32.const 0))
(assert_return (invoke "type-local-f64") (f64.const 0))
(assert_return (invoke "type-param-i32" (i32.const 2)) (i32.const 10))
(assert_return (invoke "type-param-i64" (i64.const 3)) (i64.const 11))
(assert_return (invoke "type-param-f32" (f32.const 4.4)) (f32.const 11.1))
(assert_return (invoke "type-param-f64" (f64.const 5.5)) (f64.const 12.2))
(assert_return (invoke "as-block-first" (i32.const 0)) (i32.const 1))
(assert_return (invoke "as-block-mid" (i32.const 0)) (i32.const 1))
(assert_return (invoke "as-block-last" (i32.const 0)) (i32.const 1))
(assert_return (invoke "as-loop-first" (i32.const 0)) (i32.const 3))
(assert_return (invoke "as-loop-mid" (i32.const 0)) (i32.const 4))
(assert_return (invoke "as-loop-last" (i32.const 0)) (i32.const 5))
(assert_return (invoke "as-br-value" (i32.const 0)) (i32.const 9))
(assert_return (invoke "as-br_if-cond" (i32.const 0)))
(assert_return (invoke "as-br_if-value" (i32.const 0)) (i32.const 8))
(assert_return (invoke "as-br_if-value-cond" (i32.const 0)) (i32.const 6))
(assert_return (invoke "as-br_table-index" (i32.const 0)))
(assert_return (invoke "as-br_table-value" (i32.const 0)) (i32.const 10))
(assert_return (invoke "as-br_table-value-index" (i32.const 0)) (i32.const 6))
(assert_return (invoke "as-return-value" (i32.const 0)) (i32.const 7))
(assert_return (invoke "as-if-cond" (i32.const 0)) (i32.const 0))
(assert_return (invoke "as-if-then" (i32.const 1)) (i32.const 3))
(assert_return (invoke "as-if-else" (i32.const 0)) (i32.const 4))
(assert_return (invoke "as-select-first" (i32.const 0) (i32.const 1)) (i32.const 5))
(assert_return (invoke "as-select-second" (i32.const 0) (i32.const 0)) (i32.const 6))
(assert_return (invoke "as-select-cond" (i32.const 0)) (i32.const 0))
(assert_return (invoke "as-call-first" (i32.const 0)) (i32.const -1))
(assert_return (invoke "as-call-mid" (i32.const 0)) (i32.const -1))
(assert_return (invoke "as-call-last" (i32.const 0)) (i32.const -1))
(assert_return (invoke "as-call_indirect-first" (i32.const 0)) (i32.const -1))
(assert_return (invoke "as-call_indirect-mid" (i32.const 0)) (i32.const -1))
(assert_return (invoke "as-call_indirect-last" (i32.const 0)) (i32.const -1))
(assert_return (invoke "as-call_indirect-index" (i32.const 0)) (i32.const -1))
(assert_return (invoke "as-local.set-value"))
(assert_return (invoke "as-local.tee-value" (i32.const 0)) (i32.const 1))
(assert_return (invoke "as-global.set-value"))
(assert_return (invoke "as-load-address" (i32.const 0)) (i32.const 0))
(assert_return (invoke "as-loadN-address" (i32.const 0)) (i32.const 0))
(assert_return (invoke "as-store-address" (i32.const 0)))
(assert_return (invoke "as-store-value" (i32.const 0)))
(assert_return (invoke "as-storeN-address" (i32.const 0)))
(assert_return (invoke "as-storeN-value" (i32.const 0)))
(assert_return (invoke "as-unary-operand" (f32.const 0)) (f32.const -nan:0x0f1e2))
(assert_return (invoke "as-binary-left" (i32.const 0)) (i32.const 13))
(assert_return (invoke "as-binary-right" (i32.const 0)) (i32.const 6))
(assert_return (invoke "as-test-operand" (i32.const 0)) (i32.const 1))
(assert_return (invoke "as-compare-left" (i32.const 0)) (i32.const 0))
(assert_return (invoke "as-compare-right" (i32.const 0)) (i32.const 1))
(assert_return (invoke "as-convert-operand" (i64.const 0)) (i32.const 41))
(assert_return (invoke "as-memory.grow-size" (i32.const 0)) (i32.const 1))
(assert_return
(invoke "type-mixed"
(i64.const 1) (f32.const 2.2) (f64.const 3.3) (i32.const 4) (i32.const 5)
)
)
(assert_return
(invoke "write"
(i64.const 1) (f32.const 2) (f64.const 3.3) (i32.const 4) (i32.const 5)
)
(i64.const 56)
)
(assert_return
(invoke "result"
(i64.const -1) (f32.const -2) (f64.const -3.3) (i32.const -4) (i32.const -5)
)
(f64.const 34.8)
)
;; Invalid typing of access to locals
(assert_invalid
(module (func $type-local-num-vs-num (result i64) (local i32) (local.tee 0 (i32.const 0))))
"type mismatch"
)
(assert_invalid
(module (func $type-local-num-vs-num (local f32) (i32.eqz (local.tee 0 (f32.const 0)))))
"type mismatch"
)
(assert_invalid
(module (func $type-local-num-vs-num (local f64 i64) (f64.neg (local.tee 1 (i64.const 0)))))
"type mismatch"
)
(assert_invalid
(module (func $type-local-arg-void-vs-num (local i32) (local.tee 0 (nop))))
"type mismatch"
)
(assert_invalid
(module (func $type-local-arg-num-vs-num (local i32) (local.tee 0 (f32.const 0))))
"type mismatch"
)
(assert_invalid
(module (func $type-local-arg-num-vs-num (local f32) (local.tee 0 (f64.const 0))))
"type mismatch"
)
(assert_invalid
(module (func $type-local-arg-num-vs-num (local f64 i64) (local.tee 1 (f64.const 0))))
"type mismatch"
)
;; Invalid typing of access to parameters
(assert_invalid
(module (func $type-param-num-vs-num (param i32) (result i64) (local.get 0)))
"type mismatch"
)
(assert_invalid
(module (func $type-param-num-vs-num (param f32) (i32.eqz (local.get 0))))
"type mismatch"
)
(assert_invalid
(module (func $type-param-num-vs-num (param f64 i64) (f64.neg (local.get 1))))
"type mismatch"
)
(assert_invalid
(module (func $type-param-arg-void-vs-num (param i32) (local.tee 0 (nop))))
"type mismatch"
)
(assert_invalid
(module (func $type-param-arg-num-vs-num (param i32) (local.tee 0 (f32.const 0))))
"type mismatch"
)
(assert_invalid
(module (func $type-param-arg-num-vs-num (param f32) (local.tee 0 (f64.const 0))))
"type mismatch"
)
(assert_invalid
(module (func $type-param-arg-num-vs-num (param f64 i64) (local.tee 1 (f64.const 0))))
"type mismatch"
)
(assert_invalid
(module
(func $type-param-arg-empty-vs-num (param i32)
(local.tee 0) (drop)
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-param-arg-empty-vs-num-in-block (param i32)
(i32.const 0)
(block (local.tee 0) (drop))
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-param-arg-empty-vs-num-in-loop (param i32)
(i32.const 0)
(loop (local.tee 0) (drop))
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-param-arg-empty-vs-num-in-then (param i32)
(i32.const 0) (i32.const 0)
(if (then (local.tee 0) (drop)))
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-param-arg-empty-vs-num-in-else (param i32)
(i32.const 0) (i32.const 0)
(if (result i32) (then (i32.const 0)) (else (local.tee 0))) (drop)
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-param-arg-empty-vs-num-in-br (param i32)
(i32.const 0)
(block (br 0 (local.tee 0)) (drop))
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-param-arg-empty-vs-num-in-br_if (param i32)
(i32.const 0)
(block (br_if 0 (local.tee 0) (i32.const 1)) (drop))
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-param-arg-empty-vs-num-in-br_table (param i32)
(i32.const 0)
(block (br_table 0 (local.tee 0)) (drop))
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-param-arg-empty-vs-num-in-return (param i32)
(return (local.tee 0)) (drop)
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-param-arg-empty-vs-num-in-select (param i32)
(select (local.tee 0) (i32.const 1) (i32.const 2)) (drop)
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-param-arg-empty-vs-num-in-call (param i32)
(call 1 (local.tee 0)) (drop)
)
(func (param i32) (result i32) (local.get 0))
)
"type mismatch"
)
(assert_invalid
(module
(func $f (param i32) (result i32) (local.get 0))
(type $sig (func (param i32) (result i32)))
(table funcref (elem $f))
(func $type-param-arg-empty-vs-num-in-call_indirect (param i32)
(block (result i32)
(call_indirect (type $sig)
(local.tee 0) (i32.const 0)
)
(drop)
)
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-param-arg-empty-vs-num-in-local.set (param i32)
(local.set 0 (local.tee 0)) (local.get 0) (drop)
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-param-arg-empty-vs-num-in-local.tee (param i32)
(local.tee 0 (local.tee 0)) (drop)
)
)
"type mismatch"
)
(assert_invalid
(module
(global $x (mut i32) (i32.const 0))
(func $type-param-arg-empty-vs-num-in-global.set (param i32)
(global.set $x (local.tee 0)) (global.get $x) (drop)
)
)
"type mismatch"
)
(assert_invalid
(module
(memory 0)
(func $type-param-arg-empty-vs-num-in-memory.grow (param i32)
(memory.grow (local.tee 0)) (drop)
)
)
"type mismatch"
)
(assert_invalid
(module
(memory 0)
(func $type-param-arg-empty-vs-num-in-load (param i32)
(i32.load (local.tee 0)) (drop)
)
)
"type mismatch"
)
(assert_invalid
(module
(memory 1)
(func $type-param-arg-empty-vs-num-in-store (param i32)
(i32.store (local.tee 0) (i32.const 1))
)
)
"type mismatch"
)
(assert_invalid
(module (func $type-mixed-arg-num-vs-num (param f32) (local i32) (local.tee 1 (f32.const 0))))
"type mismatch"
)
(assert_invalid
(module (func $type-mixed-arg-num-vs-num (param i64 i32) (local f32) (local.tee 1 (f32.const 0))))
"type mismatch"
)
(assert_invalid
(module (func $type-mixed-arg-num-vs-num (param i64) (local f64 i64) (local.tee 1 (i64.const 0))))
"type mismatch"
)
;; Invalid local index
(assert_invalid
(module (func $unbound-local (local i32 i64) (local.tee 3 (i32.const 0)) drop))
"unknown local"
)
(assert_invalid
(module (func $large-local (local i32 i64) (local.tee 14324343 (i32.const 0)) drop))
"unknown local"
)
(assert_invalid
(module (func $unbound-param (param i32 i64) (local.tee 2 (i32.const 0)) drop))
"unknown local"
)
(assert_invalid
(module (func $large-param (param i32 i64) (local.tee 714324343 (i32.const 0)) drop))
"unknown local"
)
(assert_invalid
(module (func $unbound-mixed (param i32) (local i32 i64) (local.tee 3 (i32.const 0)) drop))
"unknown local"
)
(assert_invalid
(module (func $large-mixed (param i64) (local i32 i64) (local.tee 214324343 (i32.const 0)) drop))
"unknown local"
)

View File

@ -0,0 +1,186 @@
;; Abstract Types
(module
(type $ft (func))
(type $st (struct))
(type $at (array i8))
(table 10 anyref)
(elem declare func $f)
(func $f)
(func (export "init") (param $x externref)
(table.set (i32.const 0) (ref.null any))
(table.set (i32.const 1) (ref.i31 (i32.const 7)))
(table.set (i32.const 2) (struct.new_default $st))
(table.set (i32.const 3) (array.new_default $at (i32.const 0)))
(table.set (i32.const 4) (any.convert_extern (local.get $x)))
(table.set (i32.const 5) (ref.null i31))
(table.set (i32.const 6) (ref.null struct))
(table.set (i32.const 7) (ref.null none))
)
(func (export "ref_cast_non_null") (param $i i32)
(drop (ref.as_non_null (table.get (local.get $i))))
(drop (ref.cast (ref null any) (table.get (local.get $i))))
)
(func (export "ref_cast_null") (param $i i32)
(drop (ref.cast anyref (table.get (local.get $i))))
(drop (ref.cast structref (table.get (local.get $i))))
(drop (ref.cast arrayref (table.get (local.get $i))))
(drop (ref.cast i31ref (table.get (local.get $i))))
(drop (ref.cast nullref (table.get (local.get $i))))
)
(func (export "ref_cast_i31") (param $i i32)
(drop (ref.cast (ref i31) (table.get (local.get $i))))
(drop (ref.cast i31ref (table.get (local.get $i))))
)
(func (export "ref_cast_struct") (param $i i32)
(drop (ref.cast (ref struct) (table.get (local.get $i))))
(drop (ref.cast structref (table.get (local.get $i))))
)
(func (export "ref_cast_array") (param $i i32)
(drop (ref.cast (ref array) (table.get (local.get $i))))
(drop (ref.cast arrayref (table.get (local.get $i))))
)
)
(invoke "init" (ref.extern 0))
(assert_trap (invoke "ref_cast_non_null" (i32.const 0)) "null reference")
(assert_return (invoke "ref_cast_non_null" (i32.const 1)))
(assert_return (invoke "ref_cast_non_null" (i32.const 2)))
(assert_return (invoke "ref_cast_non_null" (i32.const 3)))
(assert_return (invoke "ref_cast_non_null" (i32.const 4)))
(assert_trap (invoke "ref_cast_non_null" (i32.const 5)) "null reference")
(assert_trap (invoke "ref_cast_non_null" (i32.const 6)) "null reference")
(assert_trap (invoke "ref_cast_non_null" (i32.const 7)) "null reference")
(assert_return (invoke "ref_cast_null" (i32.const 0)))
(assert_trap (invoke "ref_cast_null" (i32.const 1)) "cast failure")
(assert_trap (invoke "ref_cast_null" (i32.const 2)) "cast failure")
(assert_trap (invoke "ref_cast_null" (i32.const 3)) "cast failure")
(assert_trap (invoke "ref_cast_null" (i32.const 4)) "cast failure")
(assert_return (invoke "ref_cast_null" (i32.const 5)))
(assert_return (invoke "ref_cast_null" (i32.const 6)))
(assert_return (invoke "ref_cast_null" (i32.const 7)))
(assert_trap (invoke "ref_cast_i31" (i32.const 0)) "cast failure")
(assert_return (invoke "ref_cast_i31" (i32.const 1)))
(assert_trap (invoke "ref_cast_i31" (i32.const 2)) "cast failure")
(assert_trap (invoke "ref_cast_i31" (i32.const 3)) "cast failure")
(assert_trap (invoke "ref_cast_i31" (i32.const 4)) "cast failure")
(assert_trap (invoke "ref_cast_i31" (i32.const 5)) "cast failure")
(assert_trap (invoke "ref_cast_i31" (i32.const 6)) "cast failure")
(assert_trap (invoke "ref_cast_i31" (i32.const 7)) "cast failure")
(assert_trap (invoke "ref_cast_struct" (i32.const 0)) "cast failure")
(assert_trap (invoke "ref_cast_struct" (i32.const 1)) "cast failure")
(assert_return (invoke "ref_cast_struct" (i32.const 2)))
(assert_trap (invoke "ref_cast_struct" (i32.const 3)) "cast failure")
(assert_trap (invoke "ref_cast_struct" (i32.const 4)) "cast failure")
(assert_trap (invoke "ref_cast_struct" (i32.const 5)) "cast failure")
(assert_trap (invoke "ref_cast_struct" (i32.const 6)) "cast failure")
(assert_trap (invoke "ref_cast_struct" (i32.const 7)) "cast failure")
(assert_trap (invoke "ref_cast_array" (i32.const 0)) "cast failure")
(assert_trap (invoke "ref_cast_array" (i32.const 1)) "cast failure")
(assert_trap (invoke "ref_cast_array" (i32.const 2)) "cast failure")
(assert_return (invoke "ref_cast_array" (i32.const 3)))
(assert_trap (invoke "ref_cast_array" (i32.const 4)) "cast failure")
(assert_trap (invoke "ref_cast_array" (i32.const 5)) "cast failure")
(assert_trap (invoke "ref_cast_array" (i32.const 6)) "cast failure")
(assert_trap (invoke "ref_cast_array" (i32.const 7)) "cast failure")
;; Concrete Types
(module
(type $t0 (sub (struct)))
(type $t1 (sub $t0 (struct (field i32))))
(type $t1' (sub $t0 (struct (field i32))))
(type $t2 (sub $t1 (struct (field i32 i32))))
(type $t2' (sub $t1' (struct (field i32 i32))))
(type $t3 (sub $t0 (struct (field i32 i32))))
(type $t0' (sub $t0 (struct)))
(type $t4 (sub $t0' (struct (field i32 i32))))
(table 20 (ref null struct))
(func $init
(table.set (i32.const 0) (struct.new_default $t0))
(table.set (i32.const 10) (struct.new_default $t0))
(table.set (i32.const 1) (struct.new_default $t1))
(table.set (i32.const 11) (struct.new_default $t1'))
(table.set (i32.const 2) (struct.new_default $t2))
(table.set (i32.const 12) (struct.new_default $t2'))
(table.set (i32.const 3) (struct.new_default $t3))
(table.set (i32.const 4) (struct.new_default $t4))
)
(func (export "test-sub")
(call $init)
(drop (ref.cast (ref null $t0) (ref.null struct)))
(drop (ref.cast (ref null $t0) (table.get (i32.const 0))))
(drop (ref.cast (ref null $t0) (table.get (i32.const 1))))
(drop (ref.cast (ref null $t0) (table.get (i32.const 2))))
(drop (ref.cast (ref null $t0) (table.get (i32.const 3))))
(drop (ref.cast (ref null $t0) (table.get (i32.const 4))))
(drop (ref.cast (ref null $t0) (ref.null struct)))
(drop (ref.cast (ref null $t1) (table.get (i32.const 1))))
(drop (ref.cast (ref null $t1) (table.get (i32.const 2))))
(drop (ref.cast (ref null $t0) (ref.null struct)))
(drop (ref.cast (ref null $t2) (table.get (i32.const 2))))
(drop (ref.cast (ref null $t0) (ref.null struct)))
(drop (ref.cast (ref null $t3) (table.get (i32.const 3))))
(drop (ref.cast (ref null $t4) (table.get (i32.const 4))))
(drop (ref.cast (ref $t0) (table.get (i32.const 0))))
(drop (ref.cast (ref $t0) (table.get (i32.const 1))))
(drop (ref.cast (ref $t0) (table.get (i32.const 2))))
(drop (ref.cast (ref $t0) (table.get (i32.const 3))))
(drop (ref.cast (ref $t0) (table.get (i32.const 4))))
(drop (ref.cast (ref $t1) (table.get (i32.const 1))))
(drop (ref.cast (ref $t1) (table.get (i32.const 2))))
(drop (ref.cast (ref $t2) (table.get (i32.const 2))))
(drop (ref.cast (ref $t3) (table.get (i32.const 3))))
(drop (ref.cast (ref $t4) (table.get (i32.const 4))))
)
(func (export "test-canon")
(call $init)
(drop (ref.cast (ref $t0) (table.get (i32.const 0))))
(drop (ref.cast (ref $t0) (table.get (i32.const 1))))
(drop (ref.cast (ref $t0) (table.get (i32.const 2))))
(drop (ref.cast (ref $t0) (table.get (i32.const 3))))
(drop (ref.cast (ref $t0) (table.get (i32.const 4))))
(drop (ref.cast (ref $t0) (table.get (i32.const 10))))
(drop (ref.cast (ref $t0) (table.get (i32.const 11))))
(drop (ref.cast (ref $t0) (table.get (i32.const 12))))
(drop (ref.cast (ref $t1') (table.get (i32.const 1))))
(drop (ref.cast (ref $t1') (table.get (i32.const 2))))
(drop (ref.cast (ref $t1) (table.get (i32.const 11))))
(drop (ref.cast (ref $t1) (table.get (i32.const 12))))
(drop (ref.cast (ref $t2') (table.get (i32.const 2))))
(drop (ref.cast (ref $t2) (table.get (i32.const 12))))
)
)
(invoke "test-sub")
(invoke "test-canon")

View File

@ -0,0 +1,168 @@
(module
(type $st (sub (struct)))
(type $st' (sub (struct (field i32))))
(type $at (array i8))
(type $st-sub1 (sub $st (struct)))
(type $st-sub2 (sub $st (struct)))
(type $st'-sub1 (sub $st' (struct (field i32))))
(type $st'-sub2 (sub $st' (struct (field i32))))
(table 20 (ref null eq))
(func (export "init")
(table.set (i32.const 0) (ref.null eq))
(table.set (i32.const 1) (ref.null i31))
(table.set (i32.const 2) (ref.i31 (i32.const 7)))
(table.set (i32.const 3) (ref.i31 (i32.const 7)))
(table.set (i32.const 4) (ref.i31 (i32.const 8)))
(table.set (i32.const 5) (struct.new_default $st))
(table.set (i32.const 6) (struct.new_default $st))
(table.set (i32.const 7) (array.new_default $at (i32.const 0)))
(table.set (i32.const 8) (array.new_default $at (i32.const 0)))
)
(func (export "eq") (param $i i32) (param $j i32) (result i32)
(ref.eq (table.get (local.get $i)) (table.get (local.get $j)))
)
)
(invoke "init")
(assert_return (invoke "eq" (i32.const 0) (i32.const 0)) (i32.const 1))
(assert_return (invoke "eq" (i32.const 0) (i32.const 1)) (i32.const 1))
(assert_return (invoke "eq" (i32.const 0) (i32.const 2)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 0) (i32.const 3)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 0) (i32.const 4)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 0) (i32.const 5)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 0) (i32.const 6)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 0) (i32.const 7)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 0) (i32.const 8)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 1) (i32.const 0)) (i32.const 1))
(assert_return (invoke "eq" (i32.const 1) (i32.const 1)) (i32.const 1))
(assert_return (invoke "eq" (i32.const 1) (i32.const 2)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 1) (i32.const 3)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 1) (i32.const 4)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 1) (i32.const 5)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 1) (i32.const 6)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 1) (i32.const 7)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 1) (i32.const 8)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 2) (i32.const 0)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 2) (i32.const 1)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 2) (i32.const 2)) (i32.const 1))
(assert_return (invoke "eq" (i32.const 2) (i32.const 3)) (i32.const 1))
(assert_return (invoke "eq" (i32.const 2) (i32.const 4)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 2) (i32.const 5)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 2) (i32.const 6)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 2) (i32.const 7)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 2) (i32.const 8)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 3) (i32.const 0)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 3) (i32.const 1)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 3) (i32.const 2)) (i32.const 1))
(assert_return (invoke "eq" (i32.const 3) (i32.const 3)) (i32.const 1))
(assert_return (invoke "eq" (i32.const 3) (i32.const 4)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 3) (i32.const 5)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 3) (i32.const 6)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 3) (i32.const 7)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 3) (i32.const 8)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 4) (i32.const 0)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 4) (i32.const 1)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 4) (i32.const 2)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 4) (i32.const 3)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 4) (i32.const 4)) (i32.const 1))
(assert_return (invoke "eq" (i32.const 4) (i32.const 5)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 4) (i32.const 6)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 4) (i32.const 7)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 4) (i32.const 8)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 5) (i32.const 0)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 5) (i32.const 1)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 5) (i32.const 2)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 5) (i32.const 3)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 5) (i32.const 4)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 5) (i32.const 5)) (i32.const 1))
(assert_return (invoke "eq" (i32.const 5) (i32.const 6)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 5) (i32.const 7)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 5) (i32.const 8)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 6) (i32.const 0)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 6) (i32.const 1)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 6) (i32.const 2)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 6) (i32.const 3)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 6) (i32.const 4)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 6) (i32.const 5)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 6) (i32.const 6)) (i32.const 1))
(assert_return (invoke "eq" (i32.const 6) (i32.const 7)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 6) (i32.const 8)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 7) (i32.const 0)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 7) (i32.const 1)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 7) (i32.const 2)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 7) (i32.const 3)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 7) (i32.const 4)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 7) (i32.const 5)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 7) (i32.const 6)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 7) (i32.const 7)) (i32.const 1))
(assert_return (invoke "eq" (i32.const 7) (i32.const 8)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 8) (i32.const 0)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 8) (i32.const 1)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 8) (i32.const 2)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 8) (i32.const 3)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 8) (i32.const 4)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 8) (i32.const 5)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 8) (i32.const 6)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 8) (i32.const 7)) (i32.const 0))
(assert_return (invoke "eq" (i32.const 8) (i32.const 8)) (i32.const 1))
(assert_invalid
(module
(func (export "eq") (param $r (ref any)) (result i32)
(ref.eq (local.get $r) (local.get $r))
)
)
"type mismatch"
)
(assert_invalid
(module
(func (export "eq") (param $r (ref null any)) (result i32)
(ref.eq (local.get $r) (local.get $r))
)
)
"type mismatch"
)
(assert_invalid
(module
(func (export "eq") (param $r (ref func)) (result i32)
(ref.eq (local.get $r) (local.get $r))
)
)
"type mismatch"
)
(assert_invalid
(module
(func (export "eq") (param $r (ref null func)) (result i32)
(ref.eq (local.get $r) (local.get $r))
)
)
"type mismatch"
)
(assert_invalid
(module
(func (export "eq") (param $r (ref extern)) (result i32)
(ref.eq (local.get $r) (local.get $r))
)
)
"type mismatch"
)
(assert_invalid
(module
(func (export "eq") (param $r (ref null extern)) (result i32)
(ref.eq (local.get $r) (local.get $r))
)
)
"type mismatch"
)

View File

@ -0,0 +1,331 @@
;; Abstract Types
(module
(type $ft (func))
(type $st (struct))
(type $at (array i8))
(table $ta 10 anyref)
(table $tf 10 funcref)
(table $te 10 externref)
(elem declare func $f)
(func $f)
(func (export "init") (param $x externref)
(table.set $ta (i32.const 0) (ref.null any))
(table.set $ta (i32.const 1) (ref.null struct))
(table.set $ta (i32.const 2) (ref.null none))
(table.set $ta (i32.const 3) (ref.i31 (i32.const 7)))
(table.set $ta (i32.const 4) (struct.new_default $st))
(table.set $ta (i32.const 5) (array.new_default $at (i32.const 0)))
(table.set $ta (i32.const 6) (any.convert_extern (local.get $x)))
(table.set $ta (i32.const 7) (any.convert_extern (ref.null extern)))
(table.set $tf (i32.const 0) (ref.null nofunc))
(table.set $tf (i32.const 1) (ref.null func))
(table.set $tf (i32.const 2) (ref.func $f))
(table.set $te (i32.const 0) (ref.null noextern))
(table.set $te (i32.const 1) (ref.null extern))
(table.set $te (i32.const 2) (local.get $x))
(table.set $te (i32.const 3) (extern.convert_any (ref.i31 (i32.const 8))))
(table.set $te (i32.const 4) (extern.convert_any (struct.new_default $st)))
(table.set $te (i32.const 5) (extern.convert_any (ref.null any)))
)
(func (export "ref_test_null_data") (param $i i32) (result i32)
(i32.add
(ref.is_null (table.get $ta (local.get $i)))
(ref.test nullref (table.get $ta (local.get $i)))
)
)
(func (export "ref_test_any") (param $i i32) (result i32)
(i32.add
(ref.test (ref any) (table.get $ta (local.get $i)))
(ref.test anyref (table.get $ta (local.get $i)))
)
)
(func (export "ref_test_eq") (param $i i32) (result i32)
(i32.add
(ref.test (ref eq) (table.get $ta (local.get $i)))
(ref.test eqref (table.get $ta (local.get $i)))
)
)
(func (export "ref_test_i31") (param $i i32) (result i32)
(i32.add
(ref.test (ref i31) (table.get $ta (local.get $i)))
(ref.test i31ref (table.get $ta (local.get $i)))
)
)
(func (export "ref_test_struct") (param $i i32) (result i32)
(i32.add
(ref.test (ref struct) (table.get $ta (local.get $i)))
(ref.test structref (table.get $ta (local.get $i)))
)
)
(func (export "ref_test_array") (param $i i32) (result i32)
(i32.add
(ref.test (ref array) (table.get $ta (local.get $i)))
(ref.test arrayref (table.get $ta (local.get $i)))
)
)
(func (export "ref_test_null_func") (param $i i32) (result i32)
(i32.add
(ref.is_null (table.get $tf (local.get $i)))
(ref.test (ref null nofunc) (table.get $tf (local.get $i)))
)
)
(func (export "ref_test_func") (param $i i32) (result i32)
(i32.add
(ref.test (ref func) (table.get $tf (local.get $i)))
(ref.test funcref (table.get $tf (local.get $i)))
)
)
(func (export "ref_test_null_extern") (param $i i32) (result i32)
(i32.add
(ref.is_null (table.get $te (local.get $i)))
(ref.test (ref null noextern) (table.get $te (local.get $i)))
)
)
(func (export "ref_test_extern") (param $i i32) (result i32)
(i32.add
(ref.test (ref extern) (table.get $te (local.get $i)))
(ref.test externref (table.get $te (local.get $i)))
)
)
)
(invoke "init" (ref.extern 0))
(assert_return (invoke "ref_test_null_data" (i32.const 0)) (i32.const 2))
(assert_return (invoke "ref_test_null_data" (i32.const 1)) (i32.const 2))
(assert_return (invoke "ref_test_null_data" (i32.const 2)) (i32.const 2))
(assert_return (invoke "ref_test_null_data" (i32.const 3)) (i32.const 0))
(assert_return (invoke "ref_test_null_data" (i32.const 4)) (i32.const 0))
(assert_return (invoke "ref_test_null_data" (i32.const 5)) (i32.const 0))
(assert_return (invoke "ref_test_null_data" (i32.const 6)) (i32.const 0))
(assert_return (invoke "ref_test_null_data" (i32.const 7)) (i32.const 2))
(assert_return (invoke "ref_test_any" (i32.const 0)) (i32.const 1))
(assert_return (invoke "ref_test_any" (i32.const 1)) (i32.const 1))
(assert_return (invoke "ref_test_any" (i32.const 2)) (i32.const 1))
(assert_return (invoke "ref_test_any" (i32.const 3)) (i32.const 2))
(assert_return (invoke "ref_test_any" (i32.const 4)) (i32.const 2))
(assert_return (invoke "ref_test_any" (i32.const 5)) (i32.const 2))
(assert_return (invoke "ref_test_any" (i32.const 6)) (i32.const 2))
(assert_return (invoke "ref_test_any" (i32.const 7)) (i32.const 1))
(assert_return (invoke "ref_test_eq" (i32.const 0)) (i32.const 1))
(assert_return (invoke "ref_test_eq" (i32.const 1)) (i32.const 1))
(assert_return (invoke "ref_test_eq" (i32.const 2)) (i32.const 1))
(assert_return (invoke "ref_test_eq" (i32.const 3)) (i32.const 2))
(assert_return (invoke "ref_test_eq" (i32.const 4)) (i32.const 2))
(assert_return (invoke "ref_test_eq" (i32.const 5)) (i32.const 2))
(assert_return (invoke "ref_test_eq" (i32.const 6)) (i32.const 0))
(assert_return (invoke "ref_test_eq" (i32.const 7)) (i32.const 1))
(assert_return (invoke "ref_test_i31" (i32.const 0)) (i32.const 1))
(assert_return (invoke "ref_test_i31" (i32.const 1)) (i32.const 1))
(assert_return (invoke "ref_test_i31" (i32.const 2)) (i32.const 1))
(assert_return (invoke "ref_test_i31" (i32.const 3)) (i32.const 2))
(assert_return (invoke "ref_test_i31" (i32.const 4)) (i32.const 0))
(assert_return (invoke "ref_test_i31" (i32.const 5)) (i32.const 0))
(assert_return (invoke "ref_test_i31" (i32.const 6)) (i32.const 0))
(assert_return (invoke "ref_test_i31" (i32.const 7)) (i32.const 1))
(assert_return (invoke "ref_test_struct" (i32.const 0)) (i32.const 1))
(assert_return (invoke "ref_test_struct" (i32.const 1)) (i32.const 1))
(assert_return (invoke "ref_test_struct" (i32.const 2)) (i32.const 1))
(assert_return (invoke "ref_test_struct" (i32.const 3)) (i32.const 0))
(assert_return (invoke "ref_test_struct" (i32.const 4)) (i32.const 2))
(assert_return (invoke "ref_test_struct" (i32.const 5)) (i32.const 0))
(assert_return (invoke "ref_test_struct" (i32.const 6)) (i32.const 0))
(assert_return (invoke "ref_test_struct" (i32.const 7)) (i32.const 1))
(assert_return (invoke "ref_test_array" (i32.const 0)) (i32.const 1))
(assert_return (invoke "ref_test_array" (i32.const 1)) (i32.const 1))
(assert_return (invoke "ref_test_array" (i32.const 2)) (i32.const 1))
(assert_return (invoke "ref_test_array" (i32.const 3)) (i32.const 0))
(assert_return (invoke "ref_test_array" (i32.const 4)) (i32.const 0))
(assert_return (invoke "ref_test_array" (i32.const 5)) (i32.const 2))
(assert_return (invoke "ref_test_array" (i32.const 6)) (i32.const 0))
(assert_return (invoke "ref_test_array" (i32.const 7)) (i32.const 1))
(assert_return (invoke "ref_test_null_func" (i32.const 0)) (i32.const 2))
(assert_return (invoke "ref_test_null_func" (i32.const 1)) (i32.const 2))
(assert_return (invoke "ref_test_null_func" (i32.const 2)) (i32.const 0))
(assert_return (invoke "ref_test_func" (i32.const 0)) (i32.const 1))
(assert_return (invoke "ref_test_func" (i32.const 1)) (i32.const 1))
(assert_return (invoke "ref_test_func" (i32.const 2)) (i32.const 2))
(assert_return (invoke "ref_test_null_extern" (i32.const 0)) (i32.const 2))
(assert_return (invoke "ref_test_null_extern" (i32.const 1)) (i32.const 2))
(assert_return (invoke "ref_test_null_extern" (i32.const 2)) (i32.const 0))
(assert_return (invoke "ref_test_null_extern" (i32.const 3)) (i32.const 0))
(assert_return (invoke "ref_test_null_extern" (i32.const 4)) (i32.const 0))
(assert_return (invoke "ref_test_null_extern" (i32.const 5)) (i32.const 2))
(assert_return (invoke "ref_test_extern" (i32.const 0)) (i32.const 1))
(assert_return (invoke "ref_test_extern" (i32.const 1)) (i32.const 1))
(assert_return (invoke "ref_test_extern" (i32.const 2)) (i32.const 2))
(assert_return (invoke "ref_test_extern" (i32.const 3)) (i32.const 2))
(assert_return (invoke "ref_test_extern" (i32.const 4)) (i32.const 2))
(assert_return (invoke "ref_test_extern" (i32.const 5)) (i32.const 1))
;; Concrete Types
(module
(type $t0 (sub (struct)))
(type $t1 (sub $t0 (struct (field i32))))
(type $t1' (sub $t0 (struct (field i32))))
(type $t2 (sub $t1 (struct (field i32 i32))))
(type $t2' (sub $t1' (struct (field i32 i32))))
(type $t3 (sub $t0 (struct (field i32 i32))))
(type $t0' (sub $t0 (struct)))
(type $t4 (sub $t0' (struct (field i32 i32))))
(table 20 (ref null struct))
(func $init
(table.set (i32.const 0) (struct.new_default $t0))
(table.set (i32.const 10) (struct.new_default $t0))
(table.set (i32.const 1) (struct.new_default $t1))
(table.set (i32.const 11) (struct.new_default $t1'))
(table.set (i32.const 2) (struct.new_default $t2))
(table.set (i32.const 12) (struct.new_default $t2'))
(table.set (i32.const 3) (struct.new_default $t3))
(table.set (i32.const 4) (struct.new_default $t4))
)
(func (export "test-sub")
(call $init)
(block $l
;; must hold
(br_if $l (i32.eqz (ref.test (ref null $t0) (ref.null struct))))
(br_if $l (i32.eqz (ref.test (ref null $t0) (ref.null $t0))))
(br_if $l (i32.eqz (ref.test (ref null $t0) (ref.null $t1))))
(br_if $l (i32.eqz (ref.test (ref null $t0) (ref.null $t2))))
(br_if $l (i32.eqz (ref.test (ref null $t0) (ref.null $t3))))
(br_if $l (i32.eqz (ref.test (ref null $t0) (ref.null $t4))))
(br_if $l (i32.eqz (ref.test (ref null $t0) (table.get (i32.const 0)))))
(br_if $l (i32.eqz (ref.test (ref null $t0) (table.get (i32.const 1)))))
(br_if $l (i32.eqz (ref.test (ref null $t0) (table.get (i32.const 2)))))
(br_if $l (i32.eqz (ref.test (ref null $t0) (table.get (i32.const 3)))))
(br_if $l (i32.eqz (ref.test (ref null $t0) (table.get (i32.const 4)))))
(br_if $l (i32.eqz (ref.test (ref null $t1) (ref.null struct))))
(br_if $l (i32.eqz (ref.test (ref null $t1) (ref.null $t0))))
(br_if $l (i32.eqz (ref.test (ref null $t1) (ref.null $t1))))
(br_if $l (i32.eqz (ref.test (ref null $t1) (ref.null $t2))))
(br_if $l (i32.eqz (ref.test (ref null $t1) (ref.null $t3))))
(br_if $l (i32.eqz (ref.test (ref null $t1) (ref.null $t4))))
(br_if $l (i32.eqz (ref.test (ref null $t1) (table.get (i32.const 1)))))
(br_if $l (i32.eqz (ref.test (ref null $t1) (table.get (i32.const 2)))))
(br_if $l (i32.eqz (ref.test (ref null $t2) (ref.null struct))))
(br_if $l (i32.eqz (ref.test (ref null $t2) (ref.null $t0))))
(br_if $l (i32.eqz (ref.test (ref null $t2) (ref.null $t1))))
(br_if $l (i32.eqz (ref.test (ref null $t2) (ref.null $t2))))
(br_if $l (i32.eqz (ref.test (ref null $t2) (ref.null $t3))))
(br_if $l (i32.eqz (ref.test (ref null $t2) (ref.null $t4))))
(br_if $l (i32.eqz (ref.test (ref null $t2) (table.get (i32.const 2)))))
(br_if $l (i32.eqz (ref.test (ref null $t3) (ref.null struct))))
(br_if $l (i32.eqz (ref.test (ref null $t3) (ref.null $t0))))
(br_if $l (i32.eqz (ref.test (ref null $t3) (ref.null $t1))))
(br_if $l (i32.eqz (ref.test (ref null $t3) (ref.null $t2))))
(br_if $l (i32.eqz (ref.test (ref null $t3) (ref.null $t3))))
(br_if $l (i32.eqz (ref.test (ref null $t3) (ref.null $t4))))
(br_if $l (i32.eqz (ref.test (ref null $t3) (table.get (i32.const 3)))))
(br_if $l (i32.eqz (ref.test (ref null $t4) (ref.null struct))))
(br_if $l (i32.eqz (ref.test (ref null $t4) (ref.null $t0))))
(br_if $l (i32.eqz (ref.test (ref null $t4) (ref.null $t1))))
(br_if $l (i32.eqz (ref.test (ref null $t4) (ref.null $t2))))
(br_if $l (i32.eqz (ref.test (ref null $t4) (ref.null $t3))))
(br_if $l (i32.eqz (ref.test (ref null $t4) (ref.null $t4))))
(br_if $l (i32.eqz (ref.test (ref null $t4) (table.get (i32.const 4)))))
(br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 0)))))
(br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 1)))))
(br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 2)))))
(br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 3)))))
(br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 4)))))
(br_if $l (i32.eqz (ref.test (ref $t1) (table.get (i32.const 1)))))
(br_if $l (i32.eqz (ref.test (ref $t1) (table.get (i32.const 2)))))
(br_if $l (i32.eqz (ref.test (ref $t2) (table.get (i32.const 2)))))
(br_if $l (i32.eqz (ref.test (ref $t3) (table.get (i32.const 3)))))
(br_if $l (i32.eqz (ref.test (ref $t4) (table.get (i32.const 4)))))
;; must not hold
(br_if $l (ref.test (ref $t0) (ref.null struct)))
(br_if $l (ref.test (ref $t1) (ref.null struct)))
(br_if $l (ref.test (ref $t2) (ref.null struct)))
(br_if $l (ref.test (ref $t3) (ref.null struct)))
(br_if $l (ref.test (ref $t4) (ref.null struct)))
(br_if $l (ref.test (ref $t1) (table.get (i32.const 0))))
(br_if $l (ref.test (ref $t1) (table.get (i32.const 3))))
(br_if $l (ref.test (ref $t1) (table.get (i32.const 4))))
(br_if $l (ref.test (ref $t2) (table.get (i32.const 0))))
(br_if $l (ref.test (ref $t2) (table.get (i32.const 1))))
(br_if $l (ref.test (ref $t2) (table.get (i32.const 3))))
(br_if $l (ref.test (ref $t2) (table.get (i32.const 4))))
(br_if $l (ref.test (ref $t3) (table.get (i32.const 0))))
(br_if $l (ref.test (ref $t3) (table.get (i32.const 1))))
(br_if $l (ref.test (ref $t3) (table.get (i32.const 2))))
(br_if $l (ref.test (ref $t3) (table.get (i32.const 4))))
(br_if $l (ref.test (ref $t4) (table.get (i32.const 0))))
(br_if $l (ref.test (ref $t4) (table.get (i32.const 1))))
(br_if $l (ref.test (ref $t4) (table.get (i32.const 2))))
(br_if $l (ref.test (ref $t4) (table.get (i32.const 3))))
(return)
)
(unreachable)
)
(func (export "test-canon")
(call $init)
(block $l
(br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 0)))))
(br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 1)))))
(br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 2)))))
(br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 3)))))
(br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 4)))))
(br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 10)))))
(br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 11)))))
(br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 12)))))
;; Must have explicit sub relationship
;; (br_if $l (i32.eqz (ref.test (ref $t1') (table.get (i32.const 1)))))
;; (br_if $l (i32.eqz (ref.test (ref $t1') (table.get (i32.const 2)))))
;; (br_if $l (i32.eqz (ref.test (ref $t1) (table.get (i32.const 11)))))
;; (br_if $l (i32.eqz (ref.test (ref $t1) (table.get (i32.const 12)))))
;; (br_if $l (i32.eqz (ref.test (ref $t2') (table.get (i32.const 2)))))
;; (br_if $l (i32.eqz (ref.test (ref $t2) (table.get (i32.const 12)))))
(return)
)
(unreachable)
)
)
(assert_return (invoke "test-sub"))
(assert_return (invoke "test-canon"))

View File

@ -0,0 +1,376 @@
;; 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")
(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 1200)) (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 1200)) (i64.const 44))
(assert_return (invoke "even" (i64.const 1201)) (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 1200)) (i64.const 99))
(assert_return (invoke "odd" (i64.const 1119)) (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)
(unreachable)
(return_call_ref $t)
)
)
(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)
(ref.func $f)
(return_call_ref $t)
)
)
(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)
(i32.const 0)
(ref.func $f)
(return_call_ref $t)
(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"
)

View File

@ -0,0 +1,592 @@
(module
;; Auxiliary
(func $dummy)
(table $tab funcref (elem $dummy))
(memory 1)
(func (export "select-i32") (param i32 i32 i32) (result i32)
(select (local.get 0) (local.get 1) (local.get 2))
)
(func (export "select-i64") (param i64 i64 i32) (result i64)
(select (local.get 0) (local.get 1) (local.get 2))
)
(func (export "select-f32") (param f32 f32 i32) (result f32)
(select (local.get 0) (local.get 1) (local.get 2))
)
(func (export "select-f64") (param f64 f64 i32) (result f64)
(select (local.get 0) (local.get 1) (local.get 2))
)
(func (export "select-i32-t") (param i32 i32 i32) (result i32)
(select (result i32) (local.get 0) (local.get 1) (local.get 2))
)
(func (export "select-i64-t") (param i64 i64 i32) (result i64)
(select (result i64) (local.get 0) (local.get 1) (local.get 2))
)
(func (export "select-f32-t") (param f32 f32 i32) (result f32)
(select (result f32) (local.get 0) (local.get 1) (local.get 2))
)
(func (export "select-f64-t") (param f64 f64 i32) (result f64)
(select (result f64) (local.get 0) (local.get 1) (local.get 2))
)
(func (export "select-funcref") (param funcref funcref i32) (result funcref)
(select (result funcref) (local.get 0) (local.get 1) (local.get 2))
)
(func (export "select-externref") (param externref externref i32) (result externref)
(select (result externref) (local.get 0) (local.get 1) (local.get 2))
)
(type $t (func))
(func $tf) (elem declare func $tf)
(func (export "join-funcnull") (param i32) (result (ref null func))
(select (result (ref null func))
(ref.func $tf)
(ref.null func)
(local.get 0)
)
)
;; Check that both sides of the select are evaluated
(func (export "select-trap-left") (param $cond i32) (result i32)
(select (unreachable) (i32.const 0) (local.get $cond))
)
(func (export "select-trap-right") (param $cond i32) (result i32)
(select (i32.const 0) (unreachable) (local.get $cond))
)
(func (export "select-unreached")
(unreachable) (select)
(unreachable) (i32.const 0) (select)
(unreachable) (i32.const 0) (i32.const 0) (select)
(unreachable) (i32.const 0) (i32.const 0) (i32.const 0) (select)
(unreachable) (f32.const 0) (i32.const 0) (select)
(unreachable)
)
(func (export "select_unreached_result_1") (result i32)
(unreachable) (i32.add (select))
)
(func (export "select_unreached_result_2") (result i64)
(unreachable) (i64.add (select (i64.const 0) (i32.const 0)))
)
;; As the argument of control constructs and instructions
(func (export "as-select-first") (param i32) (result i32)
(select (select (i32.const 0) (i32.const 1) (local.get 0)) (i32.const 2) (i32.const 3))
)
(func (export "as-select-mid") (param i32) (result i32)
(select (i32.const 2) (select (i32.const 0) (i32.const 1) (local.get 0)) (i32.const 3))
)
(func (export "as-select-last") (param i32) (result i32)
(select (i32.const 2) (i32.const 3) (select (i32.const 0) (i32.const 1) (local.get 0)))
)
(func (export "as-loop-first") (param i32) (result i32)
(loop (result i32) (select (i32.const 2) (i32.const 3) (local.get 0)) (call $dummy) (call $dummy))
)
(func (export "as-loop-mid") (param i32) (result i32)
(loop (result i32) (call $dummy) (select (i32.const 2) (i32.const 3) (local.get 0)) (call $dummy))
)
(func (export "as-loop-last") (param i32) (result i32)
(loop (result i32) (call $dummy) (call $dummy) (select (i32.const 2) (i32.const 3) (local.get 0)))
)
(func (export "as-if-condition") (param i32)
(select (i32.const 2) (i32.const 3) (local.get 0)) (if (then (call $dummy)))
)
(func (export "as-if-then") (param i32) (result i32)
(if (result i32) (i32.const 1) (then (select (i32.const 2) (i32.const 3) (local.get 0))) (else (i32.const 4)))
)
(func (export "as-if-else") (param i32) (result i32)
(if (result i32) (i32.const 0) (then (i32.const 2)) (else (select (i32.const 2) (i32.const 3) (local.get 0))))
)
(func (export "as-br_if-first") (param i32) (result i32)
(block (result i32) (br_if 0 (select (i32.const 2) (i32.const 3) (local.get 0)) (i32.const 4)))
)
(func (export "as-br_if-last") (param i32) (result i32)
(block (result i32) (br_if 0 (i32.const 2) (select (i32.const 2) (i32.const 3) (local.get 0))))
)
(func (export "as-br_table-first") (param i32) (result i32)
(block (result i32) (select (i32.const 2) (i32.const 3) (local.get 0)) (i32.const 2) (br_table 0 0))
)
(func (export "as-br_table-last") (param i32) (result i32)
(block (result i32) (i32.const 2) (select (i32.const 2) (i32.const 3) (local.get 0)) (br_table 0 0))
)
(func $func (param i32 i32) (result i32) (local.get 0))
(type $check (func (param i32 i32) (result i32)))
(table $t funcref (elem $func))
(func (export "as-call_indirect-first") (param i32) (result i32)
(block (result i32)
(call_indirect $t (type $check)
(select (i32.const 2) (i32.const 3) (local.get 0)) (i32.const 1) (i32.const 0)
)
)
)
(func (export "as-call_indirect-mid") (param i32) (result i32)
(block (result i32)
(call_indirect $t (type $check)
(i32.const 1) (select (i32.const 2) (i32.const 3) (local.get 0)) (i32.const 0)
)
)
)
(func (export "as-call_indirect-last") (param i32) (result i32)
(block (result i32)
(call_indirect $t (type $check)
(i32.const 1) (i32.const 4) (select (i32.const 2) (i32.const 3) (local.get 0))
)
)
)
(func (export "as-store-first") (param i32)
(select (i32.const 0) (i32.const 4) (local.get 0)) (i32.const 1) (i32.store)
)
(func (export "as-store-last") (param i32)
(i32.const 8) (select (i32.const 1) (i32.const 2) (local.get 0)) (i32.store)
)
(func (export "as-memory.grow-value") (param i32) (result i32)
(memory.grow (select (i32.const 1) (i32.const 2) (local.get 0)))
)
(func $f (param i32) (result i32) (local.get 0))
(func (export "as-call-value") (param i32) (result i32)
(call $f (select (i32.const 1) (i32.const 2) (local.get 0)))
)
(func (export "as-return-value") (param i32) (result i32)
(select (i32.const 1) (i32.const 2) (local.get 0)) (return)
)
(func (export "as-drop-operand") (param i32)
(drop (select (i32.const 1) (i32.const 2) (local.get 0)))
)
(func (export "as-br-value") (param i32) (result i32)
(block (result i32) (br 0 (select (i32.const 1) (i32.const 2) (local.get 0))))
)
(func (export "as-local.set-value") (param i32) (result i32)
(local i32) (local.set 0 (select (i32.const 1) (i32.const 2) (local.get 0))) (local.get 0)
)
(func (export "as-local.tee-value") (param i32) (result i32)
(local.tee 0 (select (i32.const 1) (i32.const 2) (local.get 0)))
)
(global $a (mut i32) (i32.const 10))
(func (export "as-global.set-value") (param i32) (result i32)
(global.set $a (select (i32.const 1) (i32.const 2) (local.get 0)))
(global.get $a)
)
(func (export "as-load-operand") (param i32) (result i32)
(i32.load (select (i32.const 0) (i32.const 4) (local.get 0)))
)
(func (export "as-unary-operand") (param i32) (result i32)
(i32.eqz (select (i32.const 0) (i32.const 1) (local.get 0)))
)
(func (export "as-binary-operand") (param i32) (result i32)
(i32.mul
(select (i32.const 1) (i32.const 2) (local.get 0))
(select (i32.const 1) (i32.const 2) (local.get 0))
)
)
(func (export "as-test-operand") (param i32) (result i32)
(block (result i32)
(i32.eqz (select (i32.const 0) (i32.const 1) (local.get 0)))
)
)
(func (export "as-compare-left") (param i32) (result i32)
(block (result i32)
(i32.le_s (select (i32.const 1) (i32.const 2) (local.get 0)) (i32.const 1))
)
)
(func (export "as-compare-right") (param i32) (result i32)
(block (result i32)
(i32.ne (i32.const 1) (select (i32.const 0) (i32.const 1) (local.get 0)))
)
)
(func (export "as-convert-operand") (param i32) (result i32)
(block (result i32)
(i32.wrap_i64 (select (i64.const 1) (i64.const 0) (local.get 0)))
)
)
)
(assert_return (invoke "select-i32" (i32.const 1) (i32.const 2) (i32.const 1)) (i32.const 1))
(assert_return (invoke "select-i64" (i64.const 2) (i64.const 1) (i32.const 1)) (i64.const 2))
(assert_return (invoke "select-f32" (f32.const 1) (f32.const 2) (i32.const 1)) (f32.const 1))
(assert_return (invoke "select-f64" (f64.const 1) (f64.const 2) (i32.const 1)) (f64.const 1))
(assert_return (invoke "select-i32" (i32.const 1) (i32.const 2) (i32.const 0)) (i32.const 2))
(assert_return (invoke "select-i32" (i32.const 2) (i32.const 1) (i32.const 0)) (i32.const 1))
(assert_return (invoke "select-i64" (i64.const 2) (i64.const 1) (i32.const -1)) (i64.const 2))
(assert_return (invoke "select-i64" (i64.const 2) (i64.const 1) (i32.const 0xf0f0f0f0)) (i64.const 2))
(assert_return (invoke "select-f32" (f32.const nan) (f32.const 1) (i32.const 1)) (f32.const nan))
(assert_return (invoke "select-f32" (f32.const nan:0x20304) (f32.const 1) (i32.const 1)) (f32.const nan:0x20304))
(assert_return (invoke "select-f32" (f32.const nan) (f32.const 1) (i32.const 0)) (f32.const 1))
(assert_return (invoke "select-f32" (f32.const nan:0x20304) (f32.const 1) (i32.const 0)) (f32.const 1))
(assert_return (invoke "select-f32" (f32.const 2) (f32.const nan) (i32.const 1)) (f32.const 2))
(assert_return (invoke "select-f32" (f32.const 2) (f32.const nan:0x20304) (i32.const 1)) (f32.const 2))
(assert_return (invoke "select-f32" (f32.const 2) (f32.const nan) (i32.const 0)) (f32.const nan))
(assert_return (invoke "select-f32" (f32.const 2) (f32.const nan:0x20304) (i32.const 0)) (f32.const nan:0x20304))
(assert_return (invoke "select-f64" (f64.const nan) (f64.const 1) (i32.const 1)) (f64.const nan))
(assert_return (invoke "select-f64" (f64.const nan:0x20304) (f64.const 1) (i32.const 1)) (f64.const nan:0x20304))
(assert_return (invoke "select-f64" (f64.const nan) (f64.const 1) (i32.const 0)) (f64.const 1))
(assert_return (invoke "select-f64" (f64.const nan:0x20304) (f64.const 1) (i32.const 0)) (f64.const 1))
(assert_return (invoke "select-f64" (f64.const 2) (f64.const nan) (i32.const 1)) (f64.const 2))
(assert_return (invoke "select-f64" (f64.const 2) (f64.const nan:0x20304) (i32.const 1)) (f64.const 2))
(assert_return (invoke "select-f64" (f64.const 2) (f64.const nan) (i32.const 0)) (f64.const nan))
(assert_return (invoke "select-f64" (f64.const 2) (f64.const nan:0x20304) (i32.const 0)) (f64.const nan:0x20304))
(assert_return (invoke "select-i32-t" (i32.const 1) (i32.const 2) (i32.const 1)) (i32.const 1))
(assert_return (invoke "select-i64-t" (i64.const 2) (i64.const 1) (i32.const 1)) (i64.const 2))
(assert_return (invoke "select-f32-t" (f32.const 1) (f32.const 2) (i32.const 1)) (f32.const 1))
(assert_return (invoke "select-f64-t" (f64.const 1) (f64.const 2) (i32.const 1)) (f64.const 1))
(assert_return (invoke "select-funcref" (ref.null func) (ref.null func) (i32.const 1)) (ref.null func))
(assert_return (invoke "select-externref" (ref.extern 1) (ref.extern 2) (i32.const 1)) (ref.extern 1))
(assert_return (invoke "select-i32-t" (i32.const 1) (i32.const 2) (i32.const 0)) (i32.const 2))
(assert_return (invoke "select-i32-t" (i32.const 2) (i32.const 1) (i32.const 0)) (i32.const 1))
(assert_return (invoke "select-i64-t" (i64.const 2) (i64.const 1) (i32.const -1)) (i64.const 2))
(assert_return (invoke "select-i64-t" (i64.const 2) (i64.const 1) (i32.const 0xf0f0f0f0)) (i64.const 2))
(assert_return (invoke "select-externref" (ref.extern 1) (ref.extern 2) (i32.const 0)) (ref.extern 2))
(assert_return (invoke "select-externref" (ref.extern 2) (ref.extern 1) (i32.const 0)) (ref.extern 1))
(assert_return (invoke "select-f32-t" (f32.const nan) (f32.const 1) (i32.const 1)) (f32.const nan))
(assert_return (invoke "select-f32-t" (f32.const nan:0x20304) (f32.const 1) (i32.const 1)) (f32.const nan:0x20304))
(assert_return (invoke "select-f32-t" (f32.const nan) (f32.const 1) (i32.const 0)) (f32.const 1))
(assert_return (invoke "select-f32-t" (f32.const nan:0x20304) (f32.const 1) (i32.const 0)) (f32.const 1))
(assert_return (invoke "select-f32-t" (f32.const 2) (f32.const nan) (i32.const 1)) (f32.const 2))
(assert_return (invoke "select-f32-t" (f32.const 2) (f32.const nan:0x20304) (i32.const 1)) (f32.const 2))
(assert_return (invoke "select-f32-t" (f32.const 2) (f32.const nan) (i32.const 0)) (f32.const nan))
(assert_return (invoke "select-f32-t" (f32.const 2) (f32.const nan:0x20304) (i32.const 0)) (f32.const nan:0x20304))
(assert_return (invoke "select-f64-t" (f64.const nan) (f64.const 1) (i32.const 1)) (f64.const nan))
(assert_return (invoke "select-f64-t" (f64.const nan:0x20304) (f64.const 1) (i32.const 1)) (f64.const nan:0x20304))
(assert_return (invoke "select-f64-t" (f64.const nan) (f64.const 1) (i32.const 0)) (f64.const 1))
(assert_return (invoke "select-f64-t" (f64.const nan:0x20304) (f64.const 1) (i32.const 0)) (f64.const 1))
(assert_return (invoke "select-f64-t" (f64.const 2) (f64.const nan) (i32.const 1)) (f64.const 2))
(assert_return (invoke "select-f64-t" (f64.const 2) (f64.const nan:0x20304) (i32.const 1)) (f64.const 2))
(assert_return (invoke "select-f64-t" (f64.const 2) (f64.const nan) (i32.const 0)) (f64.const nan))
(assert_return (invoke "select-f64-t" (f64.const 2) (f64.const nan:0x20304) (i32.const 0)) (f64.const nan:0x20304))
(assert_return (invoke "join-funcnull" (i32.const 1)) (ref.func))
(assert_return (invoke "join-funcnull" (i32.const 0)) (ref.null func)) ;; we require type in expected results
(assert_trap (invoke "select-trap-left" (i32.const 1)) "unreachable")
(assert_trap (invoke "select-trap-left" (i32.const 0)) "unreachable")
(assert_trap (invoke "select-trap-right" (i32.const 1)) "unreachable")
(assert_trap (invoke "select-trap-right" (i32.const 0)) "unreachable")
(assert_return (invoke "as-select-first" (i32.const 0)) (i32.const 1))
(assert_return (invoke "as-select-first" (i32.const 1)) (i32.const 0))
(assert_return (invoke "as-select-mid" (i32.const 0)) (i32.const 2))
(assert_return (invoke "as-select-mid" (i32.const 1)) (i32.const 2))
(assert_return (invoke "as-select-last" (i32.const 0)) (i32.const 2))
(assert_return (invoke "as-select-last" (i32.const 1)) (i32.const 3))
(assert_return (invoke "as-loop-first" (i32.const 0)) (i32.const 3))
(assert_return (invoke "as-loop-first" (i32.const 1)) (i32.const 2))
(assert_return (invoke "as-loop-mid" (i32.const 0)) (i32.const 3))
(assert_return (invoke "as-loop-mid" (i32.const 1)) (i32.const 2))
(assert_return (invoke "as-loop-last" (i32.const 0)) (i32.const 3))
(assert_return (invoke "as-loop-last" (i32.const 1)) (i32.const 2))
(assert_return (invoke "as-if-condition" (i32.const 0)))
(assert_return (invoke "as-if-condition" (i32.const 1)))
(assert_return (invoke "as-if-then" (i32.const 0)) (i32.const 3))
(assert_return (invoke "as-if-then" (i32.const 1)) (i32.const 2))
(assert_return (invoke "as-if-else" (i32.const 0)) (i32.const 3))
(assert_return (invoke "as-if-else" (i32.const 1)) (i32.const 2))
(assert_return (invoke "as-br_if-first" (i32.const 0)) (i32.const 3))
(assert_return (invoke "as-br_if-first" (i32.const 1)) (i32.const 2))
(assert_return (invoke "as-br_if-last" (i32.const 0)) (i32.const 2))
(assert_return (invoke "as-br_if-last" (i32.const 1)) (i32.const 2))
(assert_return (invoke "as-br_table-first" (i32.const 0)) (i32.const 3))
(assert_return (invoke "as-br_table-first" (i32.const 1)) (i32.const 2))
(assert_return (invoke "as-br_table-last" (i32.const 0)) (i32.const 2))
(assert_return (invoke "as-br_table-last" (i32.const 1)) (i32.const 2))
(assert_return (invoke "as-call_indirect-first" (i32.const 0)) (i32.const 3))
(assert_return (invoke "as-call_indirect-first" (i32.const 1)) (i32.const 2))
(assert_return (invoke "as-call_indirect-mid" (i32.const 0)) (i32.const 1))
(assert_return (invoke "as-call_indirect-mid" (i32.const 1)) (i32.const 1))
(assert_trap (invoke "as-call_indirect-last" (i32.const 0)) "undefined element")
(assert_trap (invoke "as-call_indirect-last" (i32.const 1)) "undefined element")
(assert_return (invoke "as-store-first" (i32.const 0)))
(assert_return (invoke "as-store-first" (i32.const 1)))
(assert_return (invoke "as-store-last" (i32.const 0)))
(assert_return (invoke "as-store-last" (i32.const 1)))
(assert_return (invoke "as-memory.grow-value" (i32.const 0)) (i32.const 1))
(assert_return (invoke "as-memory.grow-value" (i32.const 1)) (i32.const 3))
(assert_return (invoke "as-call-value" (i32.const 0)) (i32.const 2))
(assert_return (invoke "as-call-value" (i32.const 1)) (i32.const 1))
(assert_return (invoke "as-return-value" (i32.const 0)) (i32.const 2))
(assert_return (invoke "as-return-value" (i32.const 1)) (i32.const 1))
(assert_return (invoke "as-drop-operand" (i32.const 0)))
(assert_return (invoke "as-drop-operand" (i32.const 1)))
(assert_return (invoke "as-br-value" (i32.const 0)) (i32.const 2))
(assert_return (invoke "as-br-value" (i32.const 1)) (i32.const 1))
(assert_return (invoke "as-local.set-value" (i32.const 0)) (i32.const 2))
(assert_return (invoke "as-local.set-value" (i32.const 1)) (i32.const 1))
(assert_return (invoke "as-local.tee-value" (i32.const 0)) (i32.const 2))
(assert_return (invoke "as-local.tee-value" (i32.const 1)) (i32.const 1))
(assert_return (invoke "as-global.set-value" (i32.const 0)) (i32.const 2))
(assert_return (invoke "as-global.set-value" (i32.const 1)) (i32.const 1))
(assert_return (invoke "as-load-operand" (i32.const 0)) (i32.const 1))
(assert_return (invoke "as-load-operand" (i32.const 1)) (i32.const 1))
(assert_return (invoke "as-unary-operand" (i32.const 0)) (i32.const 0))
(assert_return (invoke "as-unary-operand" (i32.const 1)) (i32.const 1))
(assert_return (invoke "as-binary-operand" (i32.const 0)) (i32.const 4))
(assert_return (invoke "as-binary-operand" (i32.const 1)) (i32.const 1))
(assert_return (invoke "as-test-operand" (i32.const 0)) (i32.const 0))
(assert_return (invoke "as-test-operand" (i32.const 1)) (i32.const 1))
(assert_return (invoke "as-compare-left" (i32.const 0)) (i32.const 0))
(assert_return (invoke "as-compare-left" (i32.const 1)) (i32.const 1))
(assert_return (invoke "as-compare-right" (i32.const 0)) (i32.const 0))
(assert_return (invoke "as-compare-right" (i32.const 1)) (i32.const 1))
(assert_return (invoke "as-convert-operand" (i32.const 0)) (i32.const 0))
(assert_return (invoke "as-convert-operand" (i32.const 1)) (i32.const 1))
(assert_invalid
(module (func $arity-0-implicit (select (nop) (nop) (i32.const 1))))
"type mismatch"
)
(assert_invalid
(module (func $arity-0 (select (result) (nop) (nop) (i32.const 1))))
"invalid result arity"
)
(assert_invalid
(module (func $arity-2 (result i32 i32)
(select (result i32 i32)
(i32.const 0) (i32.const 0)
(i32.const 0) (i32.const 0)
(i32.const 1)
)
))
"invalid result arity"
)
(assert_invalid
(module (type $t (func))
(func $type-ref-implicit (param $r (ref $t))
(drop (select (local.get $r) (local.get $r) (i32.const 1)))
)
)
"type mismatch"
)
(assert_invalid
(module (func $type-funcref-implicit (param $r funcref)
(drop (select (local.get $r) (local.get $r) (i32.const 1)))
))
"type mismatch"
)
(assert_invalid
(module (func $type-externref-implicit (param $r externref)
(drop (select (local.get $r) (local.get $r) (i32.const 1)))
))
"type mismatch"
)
(module (func $type-unreachable-ref-implicit
(drop (ref.is_null (select (unreachable) (i32.const 1))))
))
(assert_invalid
(module (func $type-num-vs-num
(drop (select (i32.const 1) (i64.const 1) (i32.const 1)))
))
"type mismatch"
)
(assert_invalid
(module (func $type-num-vs-num
(drop (select (i32.const 1) (f32.const 1.0) (i32.const 1)))
))
"type mismatch"
)
(assert_invalid
(module (func $type-num-vs-num
(drop (select (i32.const 1) (f64.const 1.0) (i32.const 1)))
))
"type mismatch"
)
(assert_invalid
(module (func $type-num-vs-num (select (i32.const 1) (i64.const 1) (i32.const 1)) (drop)))
"type mismatch"
)
(assert_invalid
(module (func $type-num-vs-num (select (i32.const 1) (f32.const 1.0) (i32.const 1)) (drop)))
"type mismatch"
)
(assert_invalid
(module (func $type-num-vs-num (select (i32.const 1) (i64.const 1) (i32.const 1)) (drop)))
"type mismatch"
)
(assert_invalid
(module (func $type-num-vs-num (select (i32.const 1) (f32.const 1.0) (i32.const 1)) (drop)))
"type mismatch"
)
(assert_invalid
(module (func $type-num-vs-num (select (i32.const 1) (f64.const 1.0) (i32.const 1)) (drop)))
"type mismatch"
)
(assert_invalid
(module
(func $type-1st-operand-empty
(select) (drop)
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-2nd-operand-empty
(i32.const 0) (select) (drop)
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-3rd-operand-empty
(i32.const 0) (i32.const 0) (select) (drop)
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-1st-operand-empty-in-block
(i32.const 0) (i32.const 0) (i32.const 0)
(block (select) (drop))
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-2nd-operand-empty-in-block
(i32.const 0) (i32.const 0)
(block (i32.const 0) (select) (drop))
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-3rd-operand-empty-in-block
(i32.const 0)
(block (i32.const 0) (i32.const 0) (select) (drop))
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-1st-operand-empty-in-loop
(i32.const 0) (i32.const 0) (i32.const 0)
(loop (select) (drop))
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-2nd-operand-empty-in-loop
(i32.const 0) (i32.const 0)
(loop (i32.const 0) (select) (drop))
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-3rd-operand-empty-in-loop
(i32.const 0)
(loop (i32.const 0) (i32.const 0) (select) (drop))
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-1st-operand-empty-in-then
(i32.const 0) (i32.const 0) (i32.const 0)
(if (then (select) (drop)))
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-2nd-operand-empty-in-then
(i32.const 0) (i32.const 0)
(if (then (i32.const 0) (select) (drop)))
)
)
"type mismatch"
)
(assert_invalid
(module
(func $type-3rd-operand-empty-in-then
(i32.const 0)
(if (then (i32.const 0) (i32.const 0) (select) (drop)))
)
)
"type mismatch"
)
;; Third operand must be i32
(assert_invalid
(module (func (select (i32.const 1) (i32.const 1) (i64.const 1)) (drop)))
"type mismatch"
)
(assert_invalid
(module (func (select (i32.const 1) (i32.const 1) (f32.const 1)) (drop)))
"type mismatch"
)
(assert_invalid
(module (func (select (i32.const 1) (i32.const 1) (f64.const 1)) (drop)))
"type mismatch"
)
;; Result of select has type of first two operands
(assert_invalid
(module (func (result i32) (select (i64.const 1) (i64.const 1) (i32.const 1))))
"type mismatch"
)
;; Flat syntax
(module
(table 1 funcref)
(func (result i32) unreachable select)
(func (result i32) unreachable select nop)
(func (result i32) unreachable select (select))
(func (result i32) unreachable select select)
(func (result i32) unreachable select select select)
(func (result i32) unreachable select (result i32))
(func (result i32) unreachable select (result i32) (result))
(func (result i32) unreachable select (result i32) (result) select)
(func (result i32) unreachable select (result) (result i32) select (result i32))
(func (result i32) unreachable select call_indirect)
(func (result i32) unreachable select call_indirect select)
)

View File

@ -0,0 +1,229 @@
;; Type syntax
(module
(type (struct))
(type (struct (field)))
(type (struct (field i8)))
(type (struct (field i8 i8 i8 i8)))
(type (struct (field $x1 i32) (field $y1 i32)))
(type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1))))
(type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref)))
(type (struct (field $x2 i32) (field f32 f64) (field $y2 i32)))
)
(assert_malformed
(module quote
"(type (struct (field $x i32) (field $x i32)))"
)
"duplicate field"
)
;; Binding structure
(module
(rec
(type $s0 (struct (field (ref 0) (ref 1) (ref $s0) (ref $s1))))
(type $s1 (struct (field (ref 0) (ref 1) (ref $s0) (ref $s1))))
)
(func (param (ref $forward)))
(type $forward (struct))
)
(assert_invalid
(module (type (struct (field (ref 1)))))
"unknown type"
)
(assert_invalid
(module (type (struct (field (mut (ref 1))))))
"unknown type"
)
;; Field names
(module
(type (struct (field $x i32)))
(type $t1 (struct (field i32) (field $x f32)))
(type $t2 (struct (field i32 i32) (field $x i64)))
(func (param (ref 0)) (result i32) (struct.get 0 $x (local.get 0)))
(func (param (ref $t1)) (result f32) (struct.get 1 $x (local.get 0)))
(func (param (ref $t2)) (result i64) (struct.get $t2 $x (local.get 0)))
)
(assert_invalid
(module
(type (struct (field $x i64)))
(type $t (struct (field $x i32)))
(func (param (ref 0)) (result i32) (struct.get 0 $x (local.get 0)))
)
"type mismatch"
)
;; Basic instructions
(module
(type $vec (struct (field f32) (field $y (mut f32)) (field $z f32)))
(global (ref $vec) (struct.new $vec (f32.const 1) (f32.const 2) (f32.const 3)))
(global (ref $vec) (struct.new_default $vec))
(func (export "new") (result anyref)
(struct.new_default $vec)
)
(func $get_0_0 (param $v (ref $vec)) (result f32)
(struct.get 0 0 (local.get $v))
)
(func (export "get_0_0") (result f32)
(call $get_0_0 (struct.new_default $vec))
)
(func $get_vec_0 (param $v (ref $vec)) (result f32)
(struct.get $vec 0 (local.get $v))
)
(func (export "get_vec_0") (result f32)
(call $get_vec_0 (struct.new_default $vec))
)
(func $get_0_y (param $v (ref $vec)) (result f32)
(struct.get 0 $y (local.get $v))
)
(func (export "get_0_y") (result f32)
(call $get_0_y (struct.new_default $vec))
)
(func $get_vec_y (param $v (ref $vec)) (result f32)
(struct.get $vec $y (local.get $v))
)
(func (export "get_vec_y") (result f32)
(call $get_vec_y (struct.new_default $vec))
)
(func $set_get_y (param $v (ref $vec)) (param $y f32) (result f32)
(struct.set $vec $y (local.get $v) (local.get $y))
(struct.get $vec $y (local.get $v))
)
(func (export "set_get_y") (param $y f32) (result f32)
(call $set_get_y (struct.new_default $vec) (local.get $y))
)
(func $set_get_1 (param $v (ref $vec)) (param $y f32) (result f32)
(struct.set $vec 1 (local.get $v) (local.get $y))
(struct.get $vec $y (local.get $v))
)
(func (export "set_get_1") (param $y f32) (result f32)
(call $set_get_1 (struct.new_default $vec) (local.get $y))
)
)
(assert_return (invoke "new") (ref.struct))
(assert_return (invoke "get_0_0") (f32.const 0))
(assert_return (invoke "get_vec_0") (f32.const 0))
(assert_return (invoke "get_0_y") (f32.const 0))
(assert_return (invoke "get_vec_y") (f32.const 0))
(assert_return (invoke "set_get_y" (f32.const 7)) (f32.const 7))
(assert_return (invoke "set_get_1" (f32.const 7)) (f32.const 7))
(assert_invalid
(module
(type $s (struct (field i64)))
(func (export "struct.set-immutable") (param $s (ref $s))
(struct.set $s 0 (local.get $s) (i64.const 1))
)
)
"field is immutable"
)
;; Null dereference
(module
(type $t (struct (field i32 (mut i32))))
(func (export "struct.get-null")
(local (ref null $t)) (drop (struct.get $t 1 (local.get 0)))
)
(func (export "struct.set-null")
(local (ref null $t)) (struct.set $t 1 (local.get 0) (i32.const 0))
)
)
(assert_trap (invoke "struct.get-null") "null structure")
(assert_trap (invoke "struct.set-null") "null structure")
;; Packed field instructions
(module
(type $s (struct (field i8) (field (mut i8)) (field i16) (field (mut i16))))
(global (export "g0") (ref $s) (struct.new $s (i32.const 0) (i32.const 1) (i32.const 2) (i32.const 3)))
(global (export "g1") (ref $s) (struct.new $s (i32.const 254) (i32.const 255) (i32.const 65534) (i32.const 65535)))
(func (export "get_packed_g0_0") (result i32 i32)
(struct.get_s 0 0 (global.get 0))
(struct.get_u 0 0 (global.get 0))
)
(func (export "get_packed_g1_0") (result i32 i32)
(struct.get_s 0 0 (global.get 1))
(struct.get_u 0 0 (global.get 1))
)
(func (export "get_packed_g0_1") (result i32 i32)
(struct.get_s 0 1 (global.get 0))
(struct.get_u 0 1 (global.get 0))
)
(func (export "get_packed_g1_1") (result i32 i32)
(struct.get_s 0 1 (global.get 1))
(struct.get_u 0 1 (global.get 1))
)
(func (export "get_packed_g0_2") (result i32 i32)
(struct.get_s 0 2 (global.get 0))
(struct.get_u 0 2 (global.get 0))
)
(func (export "get_packed_g1_2") (result i32 i32)
(struct.get_s 0 2 (global.get 1))
(struct.get_u 0 2 (global.get 1))
)
(func (export "get_packed_g0_3") (result i32 i32)
(struct.get_s 0 3 (global.get 0))
(struct.get_u 0 3 (global.get 0))
)
(func (export "get_packed_g1_3") (result i32 i32)
(struct.get_s 0 3 (global.get 1))
(struct.get_u 0 3 (global.get 1))
)
(func (export "set_get_packed_g0_1") (param i32) (result i32 i32)
(struct.set 0 1 (global.get 0) (local.get 0))
(struct.get_s 0 1 (global.get 0))
(struct.get_u 0 1 (global.get 0))
)
(func (export "set_get_packed_g0_3") (param i32) (result i32 i32)
(struct.set 0 3 (global.get 0) (local.get 0))
(struct.get_s 0 3 (global.get 0))
(struct.get_u 0 3 (global.get 0))
)
)
(assert_return (invoke "get_packed_g0_0") (i32.const 0) (i32.const 0))
(assert_return (invoke "get_packed_g1_0") (i32.const -2) (i32.const 254))
(assert_return (invoke "get_packed_g0_1") (i32.const 1) (i32.const 1))
(assert_return (invoke "get_packed_g1_1") (i32.const -1) (i32.const 255))
(assert_return (invoke "get_packed_g0_2") (i32.const 2) (i32.const 2))
(assert_return (invoke "get_packed_g1_2") (i32.const -2) (i32.const 65534))
(assert_return (invoke "get_packed_g0_3") (i32.const 3) (i32.const 3))
(assert_return (invoke "get_packed_g1_3") (i32.const -1) (i32.const 65535))
(assert_return (invoke "set_get_packed_g0_1" (i32.const 257)) (i32.const 1) (i32.const 1))
(assert_return (invoke "set_get_packed_g0_3" (i32.const 257)) (i32.const 257) (i32.const 257))

View File

@ -0,0 +1,157 @@
(module
(table $t 10 externref)
(func (export "fill") (param $i i32) (param $r externref) (param $n i32)
(table.fill $t (local.get $i) (local.get $r) (local.get $n))
)
(func (export "fill-abbrev") (param $i i32) (param $r externref) (param $n i32)
(table.fill (local.get $i) (local.get $r) (local.get $n))
)
(func (export "get") (param $i i32) (result externref)
(table.get $t (local.get $i))
)
)
(assert_return (invoke "get" (i32.const 1)) (ref.null extern))
(assert_return (invoke "get" (i32.const 2)) (ref.null extern))
(assert_return (invoke "get" (i32.const 3)) (ref.null extern))
(assert_return (invoke "get" (i32.const 4)) (ref.null extern))
(assert_return (invoke "get" (i32.const 5)) (ref.null extern))
(assert_return (invoke "fill" (i32.const 2) (ref.extern 1) (i32.const 3)))
(assert_return (invoke "get" (i32.const 1)) (ref.null extern))
(assert_return (invoke "get" (i32.const 2)) (ref.extern 1))
(assert_return (invoke "get" (i32.const 3)) (ref.extern 1))
(assert_return (invoke "get" (i32.const 4)) (ref.extern 1))
(assert_return (invoke "get" (i32.const 5)) (ref.null extern))
(assert_return (invoke "fill" (i32.const 4) (ref.extern 2) (i32.const 2)))
(assert_return (invoke "get" (i32.const 3)) (ref.extern 1))
(assert_return (invoke "get" (i32.const 4)) (ref.extern 2))
(assert_return (invoke "get" (i32.const 5)) (ref.extern 2))
(assert_return (invoke "get" (i32.const 6)) (ref.null extern))
(assert_return (invoke "fill" (i32.const 4) (ref.extern 3) (i32.const 0)))
(assert_return (invoke "get" (i32.const 3)) (ref.extern 1))
(assert_return (invoke "get" (i32.const 4)) (ref.extern 2))
(assert_return (invoke "get" (i32.const 5)) (ref.extern 2))
(assert_return (invoke "fill" (i32.const 8) (ref.extern 4) (i32.const 2)))
(assert_return (invoke "get" (i32.const 7)) (ref.null extern))
(assert_return (invoke "get" (i32.const 8)) (ref.extern 4))
(assert_return (invoke "get" (i32.const 9)) (ref.extern 4))
(assert_return (invoke "fill-abbrev" (i32.const 9) (ref.null extern) (i32.const 1)))
(assert_return (invoke "get" (i32.const 8)) (ref.extern 4))
(assert_return (invoke "get" (i32.const 9)) (ref.null extern))
(assert_return (invoke "fill" (i32.const 10) (ref.extern 5) (i32.const 0)))
(assert_return (invoke "get" (i32.const 9)) (ref.null extern))
(assert_trap
(invoke "fill" (i32.const 8) (ref.extern 6) (i32.const 3))
"out of bounds table access"
)
(assert_return (invoke "get" (i32.const 7)) (ref.null extern))
(assert_return (invoke "get" (i32.const 8)) (ref.extern 4))
(assert_return (invoke "get" (i32.const 9)) (ref.null extern))
(assert_trap
(invoke "fill" (i32.const 11) (ref.null extern) (i32.const 0))
"out of bounds table access"
)
(assert_trap
(invoke "fill" (i32.const 11) (ref.null extern) (i32.const 10))
"out of bounds table access"
)
;; Type errors
(assert_invalid
(module
(table $t 10 externref)
(func $type-index-value-length-empty-vs-i32-i32
(table.fill $t)
)
)
"type mismatch"
)
(assert_invalid
(module
(table $t 10 externref)
(func $type-index-empty-vs-i32
(table.fill $t (ref.null extern) (i32.const 1))
)
)
"type mismatch"
)
(assert_invalid
(module
(table $t 10 externref)
(func $type-value-empty-vs
(table.fill $t (i32.const 1) (i32.const 1))
)
)
"type mismatch"
)
(assert_invalid
(module
(table $t 10 externref)
(func $type-length-empty-vs-i32
(table.fill $t (i32.const 1) (ref.null extern))
)
)
"type mismatch"
)
(assert_invalid
(module
(table $t 0 externref)
(func $type-index-f32-vs-i32
(table.fill $t (f32.const 1) (ref.null extern) (i32.const 1))
)
)
"type mismatch"
)
(assert_invalid
(module
(table $t 0 funcref)
(func $type-value-vs-funcref (param $r externref)
(table.fill $t (i32.const 1) (local.get $r) (i32.const 1))
)
)
"type mismatch"
)
(assert_invalid
(module
(table $t 0 externref)
(func $type-length-f32-vs-i32
(table.fill $t (i32.const 1) (ref.null extern) (f32.const 1))
)
)
"type mismatch"
)
(assert_invalid
(module
(table $t1 1 externref)
(table $t2 1 funcref)
(func $type-value-externref-vs-funcref-multi (param $r externref)
(table.fill $t2 (i32.const 0) (local.get $r) (i32.const 1))
)
)
"type mismatch"
)
(assert_invalid
(module
(table $t 1 externref)
(func $type-result-empty-vs-num (result i32)
(table.fill $t (i32.const 0) (ref.null extern) (i32.const 1))
)
)
"type mismatch"
)

View File

@ -0,0 +1,88 @@
(module
(table $t2 2 externref)
(table $t3 3 funcref)
(elem (table $t3) (i32.const 1) func $dummy)
(func $dummy)
(func (export "init") (param $r externref)
(table.set $t2 (i32.const 1) (local.get $r))
(table.set $t3 (i32.const 2) (table.get $t3 (i32.const 1)))
)
(func (export "get-externref") (param $i i32) (result externref)
(table.get (local.get $i))
)
(func $f3 (export "get-funcref") (param $i i32) (result funcref)
(table.get $t3 (local.get $i))
)
(func (export "is_null-funcref") (param $i i32) (result i32)
(ref.is_null (call $f3 (local.get $i)))
)
)
(invoke "init" (ref.extern 1))
(assert_return (invoke "get-externref" (i32.const 0)) (ref.null extern))
(assert_return (invoke "get-externref" (i32.const 1)) (ref.extern 1))
(assert_return (invoke "get-funcref" (i32.const 0)) (ref.null func))
(assert_return (invoke "is_null-funcref" (i32.const 1)) (i32.const 0))
(assert_return (invoke "is_null-funcref" (i32.const 2)) (i32.const 0))
(assert_trap (invoke "get-externref" (i32.const 2)) "out of bounds table access")
(assert_trap (invoke "get-funcref" (i32.const 3)) "out of bounds table access")
(assert_trap (invoke "get-externref" (i32.const -1)) "out of bounds table access")
(assert_trap (invoke "get-funcref" (i32.const -1)) "out of bounds table access")
;; Type errors
(assert_invalid
(module
(table $t 10 externref)
(func $type-index-empty-vs-i32 (result externref)
(table.get $t)
)
)
"type mismatch"
)
(assert_invalid
(module
(table $t 10 externref)
(func $type-index-f32-vs-i32 (result externref)
(table.get $t (f32.const 1))
)
)
"type mismatch"
)
(assert_invalid
(module
(table $t 10 externref)
(func $type-result-externref-vs-empty
(table.get $t (i32.const 0))
)
)
"type mismatch"
)
(assert_invalid
(module
(table $t 10 externref)
(func $type-result-externref-vs-funcref (result funcref)
(table.get $t (i32.const 1))
)
)
"type mismatch"
)
(assert_invalid
(module
(table $t1 1 funcref)
(table $t2 1 externref)
(func $type-result-externref-vs-funcref-multi (result funcref)
(table.get $t2 (i32.const 0))
)
)
"type mismatch"
)

View File

@ -0,0 +1,176 @@
(module
(table $t 0 externref)
(func (export "get") (param $i i32) (result externref) (table.get $t (local.get $i)))
(func (export "set") (param $i i32) (param $r externref) (table.set $t (local.get $i) (local.get $r)))
(func (export "grow") (param $sz i32) (param $init externref) (result i32)
(table.grow $t (local.get $init) (local.get $sz))
)
(func (export "grow-abbrev") (param $sz i32) (param $init externref) (result i32)
(table.grow (local.get $init) (local.get $sz))
)
(func (export "size") (result i32) (table.size $t))
)
(assert_return (invoke "size") (i32.const 0))
(assert_trap (invoke "set" (i32.const 0) (ref.extern 2)) "out of bounds table access")
(assert_trap (invoke "get" (i32.const 0)) "out of bounds table access")
(assert_return (invoke "grow" (i32.const 1) (ref.null extern)) (i32.const 0))
(assert_return (invoke "size") (i32.const 1))
(assert_return (invoke "get" (i32.const 0)) (ref.null extern))
(assert_return (invoke "set" (i32.const 0) (ref.extern 2)))
(assert_return (invoke "get" (i32.const 0)) (ref.extern 2))
(assert_trap (invoke "set" (i32.const 1) (ref.extern 2)) "out of bounds table access")
(assert_trap (invoke "get" (i32.const 1)) "out of bounds table access")
(assert_return (invoke "grow-abbrev" (i32.const 4) (ref.extern 3)) (i32.const 1))
(assert_return (invoke "size") (i32.const 5))
(assert_return (invoke "get" (i32.const 0)) (ref.extern 2))
(assert_return (invoke "set" (i32.const 0) (ref.extern 2)))
(assert_return (invoke "get" (i32.const 0)) (ref.extern 2))
(assert_return (invoke "get" (i32.const 1)) (ref.extern 3))
(assert_return (invoke "get" (i32.const 4)) (ref.extern 3))
(assert_return (invoke "set" (i32.const 4) (ref.extern 4)))
(assert_return (invoke "get" (i32.const 4)) (ref.extern 4))
(assert_trap (invoke "set" (i32.const 5) (ref.extern 2)) "out of bounds table access")
(assert_trap (invoke "get" (i32.const 5)) "out of bounds table access")
;; Reject growing to size outside i32 value range
(module
(table $t 0x10 funcref)
(elem declare func $f)
(func $f (export "grow") (result i32)
(table.grow $t (ref.func $f) (i32.const 0xffff_fff0))
)
)
(assert_return (invoke "grow") (i32.const -1))
(module
(table $t 0 externref)
(func (export "grow") (param i32) (result i32)
(table.grow $t (ref.null extern) (local.get 0))
)
)
(assert_return (invoke "grow" (i32.const 0)) (i32.const 0))
(assert_return (invoke "grow" (i32.const 1)) (i32.const 0))
(assert_return (invoke "grow" (i32.const 0)) (i32.const 1))
(assert_return (invoke "grow" (i32.const 2)) (i32.const 1))
(assert_return (invoke "grow" (i32.const 800)) (i32.const 3))
(module
(table $t 0 10 externref)
(func (export "grow") (param i32) (result i32)
(table.grow $t (ref.null extern) (local.get 0))
)
)
(assert_return (invoke "grow" (i32.const 0)) (i32.const 0))
(assert_return (invoke "grow" (i32.const 1)) (i32.const 0))
(assert_return (invoke "grow" (i32.const 1)) (i32.const 1))
(assert_return (invoke "grow" (i32.const 2)) (i32.const 2))
(assert_return (invoke "grow" (i32.const 6)) (i32.const 4))
(assert_return (invoke "grow" (i32.const 0)) (i32.const 10))
(assert_return (invoke "grow" (i32.const 1)) (i32.const -1))
(assert_return (invoke "grow" (i32.const 0x10000)) (i32.const -1))
(module
(table $t 10 funcref)
(func (export "grow") (param i32) (result i32)
(table.grow $t (ref.null func) (local.get 0))
)
(elem declare func 1)
(func (export "check-table-null") (param i32 i32) (result funcref)
(local funcref)
(local.set 2 (ref.func 1))
(block
(loop
(local.set 2 (table.get $t (local.get 0)))
(br_if 1 (i32.eqz (ref.is_null (local.get 2))))
(br_if 1 (i32.ge_u (local.get 0) (local.get 1)))
(local.set 0 (i32.add (local.get 0) (i32.const 1)))
(br_if 0 (i32.le_u (local.get 0) (local.get 1)))
)
)
(local.get 2)
)
)
(assert_return (invoke "check-table-null" (i32.const 0) (i32.const 9)) (ref.null func))
(assert_return (invoke "grow" (i32.const 10)) (i32.const 10))
(assert_return (invoke "check-table-null" (i32.const 0) (i32.const 19)) (ref.null func))
;; Type errors
(assert_invalid
(module
(table $t 0 externref)
(func $type-init-size-empty-vs-i32-externref (result i32)
(table.grow $t)
)
)
"type mismatch"
)
(assert_invalid
(module
(table $t 0 externref)
(func $type-size-empty-vs-i32 (result i32)
(table.grow $t (ref.null extern))
)
)
"type mismatch"
)
(assert_invalid
(module
(table $t 0 externref)
(func $type-init-empty-vs-externref (result i32)
(table.grow $t (i32.const 1))
)
)
"type mismatch"
)
(assert_invalid
(module
(table $t 0 externref)
(func $type-size-f32-vs-i32 (result i32)
(table.grow $t (ref.null extern) (f32.const 1))
)
)
"type mismatch"
)
(assert_invalid
(module
(table $t 0 funcref)
(func $type-init-externref-vs-funcref (param $r externref) (result i32)
(table.grow $t (local.get $r) (i32.const 1))
)
)
"type mismatch"
)
(assert_invalid
(module
(table $t 1 externref)
(func $type-result-i32-vs-empty
(table.grow $t (ref.null extern) (i32.const 0))
)
)
"type mismatch"
)
(assert_invalid
(module
(table $t 1 externref)
(func $type-result-i32-vs-f32 (result f32)
(table.grow $t (ref.null extern) (i32.const 0))
)
)
"type mismatch"
)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,119 @@
(module
(table $t2 1 externref)
(table $t3 2 funcref)
(elem (table $t3) (i32.const 1) func $dummy)
(func $dummy)
(func (export "get-externref") (param $i i32) (result externref)
(table.get $t2 (local.get $i))
)
(func $f3 (export "get-funcref") (param $i i32) (result funcref)
(table.get $t3 (local.get $i))
)
(func (export "set-externref") (param $i i32) (param $r externref)
(table.set (local.get $i) (local.get $r))
)
(func (export "set-funcref") (param $i i32) (param $r funcref)
(table.set $t3 (local.get $i) (local.get $r))
)
(func (export "set-funcref-from") (param $i i32) (param $j i32)
(table.set $t3 (local.get $i) (table.get $t3 (local.get $j)))
)
(func (export "is_null-funcref") (param $i i32) (result i32)
(ref.is_null (call $f3 (local.get $i)))
)
)
(assert_return (invoke "get-externref" (i32.const 0)) (ref.null extern))
(assert_return (invoke "set-externref" (i32.const 0) (ref.extern 1)))
(assert_return (invoke "get-externref" (i32.const 0)) (ref.extern 1))
(assert_return (invoke "set-externref" (i32.const 0) (ref.null extern)))
(assert_return (invoke "get-externref" (i32.const 0)) (ref.null extern))
(assert_return (invoke "get-funcref" (i32.const 0)) (ref.null func))
(assert_return (invoke "set-funcref-from" (i32.const 0) (i32.const 1)))
(assert_return (invoke "is_null-funcref" (i32.const 0)) (i32.const 0))
(assert_return (invoke "set-funcref" (i32.const 0) (ref.null func)))
(assert_return (invoke "get-funcref" (i32.const 0)) (ref.null func))
(assert_trap (invoke "set-externref" (i32.const 2) (ref.null extern)) "out of bounds table access")
(assert_trap (invoke "set-funcref" (i32.const 3) (ref.null func)) "out of bounds table access")
(assert_trap (invoke "set-externref" (i32.const -1) (ref.null extern)) "out of bounds table access")
(assert_trap (invoke "set-funcref" (i32.const -1) (ref.null func)) "out of bounds table access")
(assert_trap (invoke "set-externref" (i32.const 2) (ref.extern 0)) "out of bounds table access")
(assert_trap (invoke "set-funcref-from" (i32.const 3) (i32.const 1)) "out of bounds table access")
(assert_trap (invoke "set-externref" (i32.const -1) (ref.extern 0)) "out of bounds table access")
(assert_trap (invoke "set-funcref-from" (i32.const -1) (i32.const 1)) "out of bounds table access")
;; Type errors
(assert_invalid
(module
(table $t 10 externref)
(func $type-index-value-empty-vs-i32-externref
(table.set $t)
)
)
"type mismatch"
)
(assert_invalid
(module
(table $t 10 externref)
(func $type-index-empty-vs-i32
(table.set $t (ref.null extern))
)
)
"type mismatch"
)
(assert_invalid
(module
(table $t 10 externref)
(func $type-value-empty-vs-externref
(table.set $t (i32.const 1))
)
)
"type mismatch"
)
(assert_invalid
(module
(table $t 10 externref)
(func $type-size-f32-vs-i32
(table.set $t (f32.const 1) (ref.null extern))
)
)
"type mismatch"
)
(assert_invalid
(module
(table $t 10 funcref)
(func $type-value-externref-vs-funcref (param $r externref)
(table.set $t (i32.const 1) (local.get $r))
)
)
"type mismatch"
)
(assert_invalid
(module
(table $t1 1 externref)
(table $t2 1 funcref)
(func $type-value-externref-vs-funcref-multi (param $r externref)
(table.set $t2 (i32.const 0) (local.get $r))
)
)
"type mismatch"
)
(assert_invalid
(module
(table $t 10 externref)
(func $type-result-empty-vs-num (result i32)
(table.set $t (i32.const 0) (ref.null extern))
)
)
"type mismatch"
)

View File

@ -0,0 +1,804 @@
;; Definitions
(module
(type $e0 (sub (array i32)))
(type $e1 (sub $e0 (array i32)))
(type $e2 (sub (array anyref)))
(type $e3 (sub (array (ref null $e0))))
(type $e4 (sub (array (ref $e1))))
(type $m1 (sub (array (mut i32))))
(type $m2 (sub $m1 (array (mut i32))))
)
(module
(type $e0 (sub (struct)))
(type $e1 (sub $e0 (struct)))
(type $e2 (sub $e1 (struct (field i32))))
(type $e3 (sub $e2 (struct (field i32 (ref null $e0)))))
(type $e4 (sub $e3 (struct (field i32 (ref $e0) (mut i64)))))
(type $e5 (sub $e4 (struct (field i32 (ref $e1) (mut i64)))))
)
(module
(type $s (sub (struct)))
(type $s' (sub $s (struct)))
(type $f1 (sub (func (param (ref $s')) (result anyref))))
(type $f2 (sub $f1 (func (param (ref $s)) (result (ref any)))))
(type $f3 (sub $f2 (func (param (ref null $s)) (result (ref $s)))))
(type $f4 (sub $f3 (func (param (ref null struct)) (result (ref $s')))))
)
;; Recursive definitions
(module
(type $t (sub (struct (field anyref))))
(rec (type $r (sub $t (struct (field (ref $r))))))
(type $t' (sub $r (struct (field (ref $r) i32))))
)
(module
(rec
(type $r1 (sub (struct (field i32 (ref $r1)))))
)
(rec
(type $r2 (sub $r1 (struct (field i32 (ref $r3)))))
(type $r3 (sub $r1 (struct (field i32 (ref $r2)))))
)
)
(module
(rec
(type $a1 (sub (struct (field i32 (ref $a2)))))
(type $a2 (sub (struct (field i64 (ref $a1)))))
)
(rec
(type $b1 (sub $a2 (struct (field i64 (ref $a1) i32))))
(type $b2 (sub $a1 (struct (field i32 (ref $a2) i32))))
(type $b3 (sub $a2 (struct (field i64 (ref $b2) i32))))
)
)
;; Subsumption
(module
(rec
(type $t1 (sub (func (param i32 (ref $t3)))))
(type $t2 (sub $t1 (func (param i32 (ref $t2)))))
(type $t3 (sub $t2 (func (param i32 (ref $t1)))))
)
(func $f1 (param $r (ref $t1))
(call $f1 (local.get $r))
)
(func $f2 (param $r (ref $t2))
(call $f1 (local.get $r))
(call $f2 (local.get $r))
)
(func $f3 (param $r (ref $t3))
(call $f1 (local.get $r))
(call $f2 (local.get $r))
(call $f3 (local.get $r))
)
)
(module
(rec
(type $t1 (sub (func (result i32 (ref $u1)))))
(type $u1 (sub (func (result f32 (ref $t1)))))
)
(rec
(type $t2 (sub $t1 (func (result i32 (ref $u3)))))
(type $u2 (sub $u1 (func (result f32 (ref $t3)))))
(type $t3 (sub $t1 (func (result i32 (ref $u2)))))
(type $u3 (sub $u1 (func (result f32 (ref $t2)))))
)
(func $f1 (param $r (ref $t1))
(call $f1 (local.get $r))
)
(func $f2 (param $r (ref $t2))
(call $f1 (local.get $r))
(call $f2 (local.get $r))
)
(func $f3 (param $r (ref $t3))
(call $f1 (local.get $r))
(call $f3 (local.get $r))
)
)
(module
(rec (type $f1 (sub (func))) (type (struct (field (ref $f1)))))
(rec (type $f2 (sub (func))) (type (struct (field (ref $f2)))))
(rec (type $g1 (sub $f1 (func))) (type (struct)))
(rec (type $g2 (sub $f2 (func))) (type (struct)))
(func $g (type $g2))
(global (ref $g1) (ref.func $g))
)
(module
(rec (type $f1 (sub (func))) (type $s1 (sub (struct (field (ref $f1))))))
(rec (type $f2 (sub (func))) (type $s2 (sub (struct (field (ref $f2))))))
(rec
(type $g1 (sub $f1 (func)))
(type (sub $s1 (struct (field (ref $f1) (ref $f1) (ref $f2) (ref $f2) (ref $g1)))))
)
(rec
(type $g2 (sub $f2 (func)))
(type (sub $s2 (struct (field (ref $f1) (ref $f2) (ref $f1) (ref $f2) (ref $g2)))))
)
(func $g (type $g2))
(global (ref $g1) (ref.func $g))
)
(assert_invalid
(module
(rec (type $f1 (sub (func))) (type (struct (field (ref $f1)))))
(rec (type $f2 (sub (func))) (type (struct (field (ref $f1)))))
(rec (type $g1 (sub $f1 (func))) (type (struct)))
(rec (type $g2 (sub $f2 (func))) (type (struct)))
(func $g (type $g2))
(global (ref $g1) (ref.func $g))
)
"type mismatch"
)
(module
(rec (type $f1 (sub (func))) (type (struct (field (ref $f1)))))
(rec (type $f2 (sub (func))) (type (struct (field (ref $f2)))))
(rec (type $g (sub $f1 (func))) (type (struct)))
(func $g (type $g))
(global (ref $f1) (ref.func $g))
)
(module
(rec (type $f1 (sub (func))) (type $s1 (sub (struct (field (ref $f1))))))
(rec (type $f2 (sub (func))) (type $s2 (sub (struct (field (ref $f2))))))
(rec
(type $g1 (sub $f1 (func)))
(type (sub $s1 (struct (field (ref $f1) (ref $f1) (ref $f2) (ref $f2) (ref $g1)))))
)
(rec
(type $g2 (sub $f2 (func)))
(type (sub $s2 (struct (field (ref $f1) (ref $f2) (ref $f1) (ref $f2) (ref $g2)))))
)
(rec (type $h (sub $g2 (func))) (type (struct)))
(func $h (type $h))
(global (ref $f1) (ref.func $h))
(global (ref $g1) (ref.func $h))
)
(module
(rec (type $f11 (sub (func (result (ref func))))) (type $f12 (sub $f11 (func (result (ref $f11))))))
(rec (type $f21 (sub (func (result (ref func))))) (type $f22 (sub $f21 (func (result (ref $f21))))))
(func $f11 (type $f11) (unreachable))
(func $f12 (type $f12) (unreachable))
(global (ref $f11) (ref.func $f11))
(global (ref $f21) (ref.func $f11))
(global (ref $f12) (ref.func $f12))
(global (ref $f22) (ref.func $f12))
)
(module
(rec (type $f11 (sub (func (result (ref func))))) (type $f12 (sub $f11 (func (result (ref $f11))))))
(rec (type $f21 (sub (func (result (ref func))))) (type $f22 (sub $f21 (func (result (ref $f21))))))
(rec (type $g11 (sub $f11 (func (result (ref func))))) (type $g12 (sub $g11 (func (result (ref $g11))))))
(rec (type $g21 (sub $f21 (func (result (ref func))))) (type $g22 (sub $g21 (func (result (ref $g21))))))
(func $g11 (type $g11) (unreachable))
(func $g12 (type $g12) (unreachable))
(global (ref $f11) (ref.func $g11))
(global (ref $f21) (ref.func $g11))
(global (ref $f11) (ref.func $g12))
(global (ref $f21) (ref.func $g12))
(global (ref $g11) (ref.func $g11))
(global (ref $g21) (ref.func $g11))
(global (ref $g12) (ref.func $g12))
(global (ref $g22) (ref.func $g12))
)
(assert_invalid
(module
(rec (type $f11 (sub (func))) (type $f12 (sub $f11 (func))))
(rec (type $f21 (sub (func))) (type $f22 (sub $f11 (func))))
(func $f (type $f21))
(global (ref $f11) (ref.func $f))
)
"type mismatch"
)
(assert_invalid
(module
(rec (type $f01 (sub (func))) (type $f02 (sub $f01 (func))))
(rec (type $f11 (sub (func))) (type $f12 (sub $f01 (func))))
(rec (type $f21 (sub (func))) (type $f22 (sub $f11 (func))))
(func $f (type $f21))
(global (ref $f11) (ref.func $f))
)
"type mismatch"
)
;; Runtime types
(module
(type $t0 (sub (func (result (ref null func)))))
(rec (type $t1 (sub $t0 (func (result (ref null $t1))))))
(rec (type $t2 (sub $t1 (func (result (ref null $t2))))))
(func $f0 (type $t0) (ref.null func))
(func $f1 (type $t1) (ref.null $t1))
(func $f2 (type $t2) (ref.null $t2))
(table funcref (elem $f0 $f1 $f2))
(func (export "run")
(block (result (ref null func)) (call_indirect (type $t0) (i32.const 0)))
(block (result (ref null func)) (call_indirect (type $t0) (i32.const 1)))
(block (result (ref null func)) (call_indirect (type $t0) (i32.const 2)))
(block (result (ref null $t1)) (call_indirect (type $t1) (i32.const 1)))
(block (result (ref null $t1)) (call_indirect (type $t1) (i32.const 2)))
(block (result (ref null $t2)) (call_indirect (type $t2) (i32.const 2)))
(block (result (ref null $t0)) (ref.cast (ref $t0) (table.get (i32.const 0))))
(block (result (ref null $t0)) (ref.cast (ref $t0) (table.get (i32.const 1))))
(block (result (ref null $t0)) (ref.cast (ref $t0) (table.get (i32.const 2))))
(block (result (ref null $t1)) (ref.cast (ref $t1) (table.get (i32.const 1))))
(block (result (ref null $t1)) (ref.cast (ref $t1) (table.get (i32.const 2))))
(block (result (ref null $t2)) (ref.cast (ref $t2) (table.get (i32.const 2))))
(br 0)
)
(func (export "fail1")
(block (result (ref null $t1)) (call_indirect (type $t1) (i32.const 0)))
(br 0)
)
(func (export "fail2")
(block (result (ref null $t1)) (call_indirect (type $t2) (i32.const 0)))
(br 0)
)
(func (export "fail3")
(block (result (ref null $t1)) (call_indirect (type $t2) (i32.const 1)))
(br 0)
)
(func (export "fail4")
(ref.cast (ref $t1) (table.get (i32.const 0)))
(br 0)
)
(func (export "fail5")
(ref.cast (ref $t2) (table.get (i32.const 0)))
(br 0)
)
(func (export "fail6")
(ref.cast (ref $t2) (table.get (i32.const 1)))
(br 0)
)
)
(assert_return (invoke "run"))
(assert_trap (invoke "fail1") "indirect call")
(assert_trap (invoke "fail2") "indirect call")
(assert_trap (invoke "fail3") "indirect call")
(assert_trap (invoke "fail4") "cast")
(assert_trap (invoke "fail5") "cast")
(assert_trap (invoke "fail6") "cast")
(module
(type $t1 (sub (func)))
(type $t2 (sub final (func)))
(func $f1 (type $t1))
(func $f2 (type $t2))
(table funcref (elem $f1 $f2))
(func (export "fail1")
(block (call_indirect (type $t1) (i32.const 1)))
)
(func (export "fail2")
(block (call_indirect (type $t2) (i32.const 0)))
)
(func (export "fail3")
(ref.cast (ref $t1) (table.get (i32.const 1)))
(drop)
)
(func (export "fail4")
(ref.cast (ref $t2) (table.get (i32.const 0)))
(drop)
)
)
(assert_trap (invoke "fail1") "indirect call")
(assert_trap (invoke "fail2") "indirect call")
(assert_trap (invoke "fail3") "cast")
(assert_trap (invoke "fail4") "cast")
(module
(rec (type $f1 (sub (func))) (type (struct (field (ref $f1)))))
(rec (type $f2 (sub (func))) (type (struct (field (ref $f2)))))
(rec (type $g1 (sub $f1 (func))) (type (struct)))
(rec (type $g2 (sub $f2 (func))) (type (struct)))
(func $g (type $g2)) (elem declare func $g)
(func (export "run") (result i32)
(ref.test (ref $g1) (ref.func $g))
)
)
(assert_return (invoke "run") (i32.const 1))
(module
(rec (type $f1 (sub (func))) (type $s1 (sub (struct (field (ref $f1))))))
(rec (type $f2 (sub (func))) (type $s2 (sub (struct (field (ref $f2))))))
(rec
(type $g1 (sub $f1 (func)))
(type (sub $s1 (struct (field (ref $f1) (ref $f1) (ref $f2) (ref $f2) (ref $g1)))))
)
(rec
(type $g2 (sub $f2 (func)))
(type (sub $s2 (struct (field (ref $f1) (ref $f2) (ref $f1) (ref $f2) (ref $g2)))))
)
(func $g (type $g2)) (elem declare func $g)
(func (export "run") (result i32)
(ref.test (ref $g1) (ref.func $g))
)
)
(assert_return (invoke "run") (i32.const 1))
(module
(rec (type $f1 (sub (func))) (type (struct (field (ref $f1)))))
(rec (type $f2 (sub (func))) (type (struct (field (ref $f1)))))
(rec (type $g1 (sub $f1 (func))) (type (struct)))
(rec (type $g2 (sub $f2 (func))) (type (struct)))
(func $g (type $g2)) (elem declare func $g)
(func (export "run") (result i32)
(ref.test (ref $g1) (ref.func $g))
)
)
(assert_return (invoke "run") (i32.const 0))
(module
(rec (type $f1 (sub (func))) (type (struct (field (ref $f1)))))
(rec (type $f2 (sub (func))) (type (struct (field (ref $f2)))))
(rec (type $g (sub $f1 (func))) (type (struct)))
(func $g (type $g)) (elem declare func $g)
(func (export "run") (result i32)
(ref.test (ref $f1) (ref.func $g))
)
)
(assert_return (invoke "run") (i32.const 1))
(module
(rec (type $f1 (sub (func))) (type $s1 (sub (struct (field (ref $f1))))))
(rec (type $f2 (sub (func))) (type $s2 (sub (struct (field (ref $f2))))))
(rec
(type $g1 (sub $f1 (func)))
(type (sub $s1 (struct (field (ref $f1) (ref $f1) (ref $f2) (ref $f2) (ref $g1)))))
)
(rec
(type $g2 (sub $f2 (func)))
(type (sub $s2 (struct (field (ref $f1) (ref $f2) (ref $f1) (ref $f2) (ref $g2)))))
)
(rec (type $h (sub $g2 (func))) (type (struct)))
(func $h (type $h)) (elem declare func $h)
(func (export "run") (result i32 i32)
(ref.test (ref $f1) (ref.func $h))
(ref.test (ref $g1) (ref.func $h))
)
)
(assert_return (invoke "run") (i32.const 1) (i32.const 1))
(module
(rec (type $f11 (sub (func (result (ref func))))) (type $f12 (sub $f11 (func (result (ref $f11))))))
(rec (type $f21 (sub (func (result (ref func))))) (type $f22 (sub $f21 (func (result (ref $f21))))))
(func $f11 (type $f11) (unreachable)) (elem declare func $f11)
(func $f12 (type $f12) (unreachable)) (elem declare func $f12)
(func (export "run") (result i32 i32 i32 i32)
(ref.test (ref $f11) (ref.func $f11))
(ref.test (ref $f21) (ref.func $f11))
(ref.test (ref $f12) (ref.func $f12))
(ref.test (ref $f22) (ref.func $f12))
)
)
(assert_return (invoke "run")
(i32.const 1) (i32.const 1) (i32.const 1) (i32.const 1)
)
(module
(rec (type $f11 (sub (func (result (ref func))))) (type $f12 (sub $f11 (func (result (ref $f11))))))
(rec (type $f21 (sub (func (result (ref func))))) (type $f22 (sub $f21 (func (result (ref $f21))))))
(rec (type $g11 (sub $f11 (func (result (ref func))))) (type $g12 (sub $g11 (func (result (ref $g11))))))
(rec (type $g21 (sub $f21 (func (result (ref func))))) (type $g22 (sub $g21 (func (result (ref $g21))))))
(func $g11 (type $g11) (unreachable)) (elem declare func $g11)
(func $g12 (type $g12) (unreachable)) (elem declare func $g12)
(func (export "run") (result i32 i32 i32 i32 i32 i32 i32 i32)
(ref.test (ref $f11) (ref.func $g11))
(ref.test (ref $f21) (ref.func $g11))
(ref.test (ref $f11) (ref.func $g12))
(ref.test (ref $f21) (ref.func $g12))
(ref.test (ref $g11) (ref.func $g11))
(ref.test (ref $g21) (ref.func $g11))
(ref.test (ref $g12) (ref.func $g12))
(ref.test (ref $g22) (ref.func $g12))
)
)
(assert_return (invoke "run")
(i32.const 1) (i32.const 1) (i32.const 1) (i32.const 1)
(i32.const 1) (i32.const 1) (i32.const 1) (i32.const 1)
)
(module
(rec (type $f11 (sub (func))) (type $f12 (sub $f11 (func))))
(rec (type $f21 (sub (func))) (type $f22 (sub $f11 (func))))
(func $f (type $f21)) (elem declare func $f)
(func (export "run") (result i32)
(ref.test (ref $f11) (ref.func $f))
)
)
(assert_return (invoke "run") (i32.const 0))
(module
(rec (type $f01 (sub (func))) (type $f02 (sub $f01 (func))))
(rec (type $f11 (sub (func))) (type $f12 (sub $f01 (func))))
(rec (type $f21 (sub (func))) (type $f22 (sub $f11 (func))))
(func $f (type $f21)) (elem declare func $f)
(func (export "run") (result i32)
(ref.test (ref $f11) (ref.func $f))
)
)
(assert_return (invoke "run") (i32.const 0))
;; Linking
(module
(type $t0 (sub (func (result (ref null func)))))
(rec (type $t1 (sub $t0 (func (result (ref null $t1))))))
(rec (type $t2 (sub $t1 (func (result (ref null $t2))))))
(func (export "f0") (type $t0) (ref.null func))
(func (export "f1") (type $t1) (ref.null $t1))
(func (export "f2") (type $t2) (ref.null $t2))
)
(register "M")
(module
(type $t0 (sub (func (result (ref null func)))))
(rec (type $t1 (sub $t0 (func (result (ref null $t1))))))
(rec (type $t2 (sub $t1 (func (result (ref null $t2))))))
(func (import "M" "f0") (type $t0))
(func (import "M" "f1") (type $t0))
(func (import "M" "f1") (type $t1))
(func (import "M" "f2") (type $t0))
(func (import "M" "f2") (type $t1))
(func (import "M" "f2") (type $t2))
)
(assert_unlinkable
(module
(type $t0 (sub (func (result (ref null func)))))
(rec (type $t1 (sub $t0 (func (result (ref null $t1))))))
(rec (type $t2 (sub $t1 (func (result (ref null $t2))))))
(func (import "M" "f0") (type $t1))
)
"incompatible import type"
)
(assert_unlinkable
(module
(type $t0 (sub (func (result (ref null func)))))
(rec (type $t1 (sub $t0 (func (result (ref null $t1))))))
(rec (type $t2 (sub $t1 (func (result (ref null $t2))))))
(func (import "M" "f0") (type $t2))
)
"incompatible import type"
)
(assert_unlinkable
(module
(type $t0 (sub (func (result (ref null func)))))
(rec (type $t1 (sub $t0 (func (result (ref null $t1))))))
(rec (type $t2 (sub $t1 (func (result (ref null $t2))))))
(func (import "M" "f1") (type $t2))
)
"incompatible import type"
)
(module
(type $t1 (sub (func)))
(type $t2 (sub final (func)))
(func (export "f1") (type $t1))
(func (export "f2") (type $t2))
)
(register "M2")
(assert_unlinkable
(module
(type $t1 (sub (func)))
(type $t2 (sub final (func)))
(func (import "M2" "f1") (type $t2))
)
"incompatible import type"
)
(assert_unlinkable
(module
(type $t1 (sub (func)))
(type $t2 (sub final (func)))
(func (import "M2" "f2") (type $t1))
)
"incompatible import type"
)
(module
(rec (type $f2 (sub (func))) (type (struct (field (ref $f2)))))
(rec (type $g2 (sub $f2 (func))) (type (struct)))
(func (export "g") (type $g2))
)
(register "M3")
(module
(rec (type $f1 (sub (func))) (type (struct (field (ref $f1)))))
(rec (type $g1 (sub $f1 (func))) (type (struct)))
(func (import "M3" "g") (type $g1))
)
(module
(rec (type $f1 (sub (func))) (type $s1 (sub (struct (field (ref $f1))))))
(rec (type $f2 (sub (func))) (type $s2 (sub (struct (field (ref $f2))))))
(rec
(type $g2 (sub $f2 (func)))
(type (sub $s2 (struct (field (ref $f1) (ref $f2) (ref $f1) (ref $f2) (ref $g2)))))
)
(func (export "g") (type $g2))
)
(register "M4")
(module
(rec (type $f1 (sub (func))) (type $s1 (sub (struct (field (ref $f1))))))
(rec (type $f2 (sub (func))) (type $s2 (sub (struct (field (ref $f2))))))
(rec
(type $g1 (sub $f1 (func)))
(type (sub $s1 (struct (field (ref $f1) (ref $f1) (ref $f2) (ref $f2) (ref $g1)))))
)
(func (import "M4" "g") (type $g1))
)
(module
(rec (type $f1 (sub (func))) (type (struct (field (ref $f1)))))
(rec (type $f2 (sub (func))) (type (struct (field (ref $f1)))))
(rec (type $g2 (sub $f2 (func))) (type (struct)))
(func (export "g") (type $g2))
)
(register "M5")
(assert_unlinkable
(module
(rec (type $f1 (sub (func))) (type (struct (field (ref $f1)))))
(rec (type $g1 (sub $f1 (func))) (type (struct)))
(func (import "M5" "g") (type $g1))
)
"incompatible import"
)
(module
(rec (type $f1 (sub (func))) (type (struct (field (ref $f1)))))
(rec (type $f2 (sub (func))) (type (struct (field (ref $f2)))))
(rec (type $g (sub $f1 (func))) (type (struct)))
(func (export "g") (type $g))
)
(register "M6")
(module
(rec (type $f1 (sub (func))) (type (struct (field (ref $f1)))))
(rec (type $f2 (sub (func))) (type (struct (field (ref $f2)))))
(rec (type $g (sub $f1 (func))) (type (struct)))
(func (import "M6" "g") (type $f1))
)
(module
(rec (type $f1 (sub (func))) (type $s1 (sub (struct (field (ref $f1))))))
(rec (type $f2 (sub (func))) (type $s2 (sub (struct (field (ref $f2))))))
(rec
(type $g2 (sub $f2 (func)))
(type (sub $s2 (struct (field (ref $f1) (ref $f2) (ref $f1) (ref $f2) (ref $g2)))))
)
(rec (type $h (sub $g2 (func))) (type (struct)))
(func (export "h") (type $h))
)
;; (register "M7")
(module
(rec (type $f1 (sub (func))) (type $s1 (sub (struct (field (ref $f1))))))
(rec (type $f2 (sub (func))) (type $s2 (sub (struct (field (ref $f2))))))
(rec
(type $g1 (sub $f1 (func)))
(type (sub $s1 (struct (field (ref $f1) (ref $f1) (ref $f2) (ref $f2) (ref $g1)))))
)
(rec (type $h (sub $g1 (func))) (type (struct)))
(func (import "M7" "h") (type $f1))
(func (import "M7" "h") (type $g1))
)
(module
(rec (type $f11 (sub (func (result (ref func))))) (type $f12 (sub $f11 (func (result (ref $f11))))))
(rec (type $f21 (sub (func (result (ref func))))) (type $f22 (sub $f21 (func (result (ref $f21))))))
(func (export "f11") (type $f11) (unreachable))
(func (export "f12") (type $f12) (unreachable))
)
(register "M8")
(module
(rec (type $f11 (sub (func (result (ref func))))) (type $f12 (sub $f11 (func (result (ref $f11))))))
(rec (type $f21 (sub (func (result (ref func))))) (type $f22 (sub $f21 (func (result (ref $f21))))))
(func (import "M8" "f11") (type $f11))
(func (import "M8" "f11") (type $f21))
(func (import "M8" "f12") (type $f12))
(func (import "M8" "f12") (type $f22))
)
(module
(rec (type $f11 (sub (func (result (ref func))))) (type $f12 (sub $f11 (func (result (ref $f11))))))
(rec (type $f21 (sub (func (result (ref func))))) (type $f22 (sub $f21 (func (result (ref $f21))))))
(rec (type $g11 (sub $f11 (func (result (ref func))))) (type $g12 (sub $g11 (func (result (ref $g11))))))
(rec (type $g21 (sub $f21 (func (result (ref func))))) (type $g22 (sub $g21 (func (result (ref $g21))))))
(func (export "g11") (type $g11) (unreachable))
(func (export "g12") (type $g12) (unreachable))
)
(register "M9")
(module
(rec (type $f11 (sub (func (result (ref func))))) (type $f12 (sub $f11 (func (result (ref $f11))))))
(rec (type $f21 (sub (func (result (ref func))))) (type $f22 (sub $f21 (func (result (ref $f21))))))
(rec (type $g11 (sub $f11 (func (result (ref func))))) (type $g12 (sub $g11 (func (result (ref $g11))))))
(rec (type $g21 (sub $f21 (func (result (ref func))))) (type $g22 (sub $g21 (func (result (ref $g21))))))
(func (import "M9" "g11") (type $f11))
(func (import "M9" "g11") (type $f21))
(func (import "M9" "g12") (type $f11))
(func (import "M9" "g12") (type $f21))
(func (import "M9" "g11") (type $g11))
(func (import "M9" "g11") (type $g21))
(func (import "M9" "g12") (type $g12))
(func (import "M9" "g12") (type $g22))
)
(module
(rec (type $f11 (sub (func))) (type $f12 (sub $f11 (func))))
(rec (type $f21 (sub (func))) (type $f22 (sub $f11 (func))))
(func (export "f") (type $f21))
)
(register "M10")
(assert_unlinkable
(module
(rec (type $f11 (sub (func))) (type $f12 (sub $f11 (func))))
(func (import "M10" "f") (type $f11))
)
"incompatible import"
)
(module
(rec (type $f01 (sub (func))) (type $f02 (sub $f01 (func))))
(rec (type $f11 (sub (func))) (type $f12 (sub $f01 (func))))
(rec (type $f21 (sub (func))) (type $f22 (sub $f11 (func))))
(func (export "f") (type $f21))
)
(register "M11")
(assert_unlinkable
(module
(rec (type $f01 (sub (func))) (type $f02 (sub $f01 (func))))
(rec (type $f11 (sub (func))) (type $f12 (sub $f01 (func))))
(func (import "M11" "f") (type $f11))
)
"incompatible import"
)
;; Finality violation
(assert_invalid
(module
(type $t (func))
(type $s (sub $t (func)))
)
"sub type"
)
(assert_invalid
(module
(type $t (struct))
(type $s (sub $t (struct)))
)
"sub type"
)
(assert_invalid
(module
(type $t (sub final (func)))
(type $s (sub $t (func)))
)
"sub type"
)
(assert_invalid
(module
(type $t (sub (func)))
(type $s (sub final $t (func)))
(type $u (sub $s (func)))
)
"sub type"
)
;; Invalid subtyping definitions
(assert_invalid
(module
(type $a0 (sub (array i32)))
(type $s0 (sub $a0 (struct)))
)
"sub type"
)
(assert_invalid
(module
(type $f0 (sub (func (param i32) (result i32))))
(type $s0 (sub $f0 (struct)))
)
"sub type"
)
(assert_invalid
(module
(type $s0 (sub (struct)))
(type $a0 (sub $s0 (array i32)))
)
"sub type"
)
(assert_invalid
(module
(type $f0 (sub (func (param i32) (result i32))))
(type $a0 (sub $f0 (array i32)))
)
"sub type"
)
(assert_invalid
(module
(type $s0 (sub (struct)))
(type $f0 (sub $s0 (func (param i32) (result i32))))
)
"sub type"
)
(assert_invalid
(module
(type $a0 (sub (array i32)))
(type $f0 (sub $a0 (func (param i32) (result i32))))
)
"sub type"
)
(assert_invalid
(module
(type $a0 (sub (array i32)))
(type $a1 (sub $a0 (array i64)))
)
"sub type"
)
(assert_invalid
(module
(type $s0 (sub (struct (field i32))))
(type $s1 (sub $s0 (struct (field i64))))
)
"sub type"
)
(assert_invalid
(module
(type $f0 (sub (func)))
(type $f1 (sub $f0 (func (param i32))))
)
"sub type"
)