1;;! reference_types = true
2
3(module
4  (type $i32-func (func (result i32)))
5
6  (func $returns-42 (type $i32-func) (i32.const 42))
7  (func $returns-7 (type $i32-func) (i32.const 7))
8  (func $dummy)
9
10  (table $t 10 funcref)
11  (elem (table $t) (i32.const 0) func $returns-42 $returns-7)
12
13  ;; ref.null func / ref.is_null
14  (func (export "null-is-null") (result i32)
15    (ref.is_null (ref.null func))
16  )
17
18  ;; ref.func + ref.is_null
19  (func (export "func-is-not-null") (result i32)
20    (ref.is_null (ref.func $returns-42))
21  )
22
23  ;; ref.func + call_indirect
24  (func (export "call-indirect-0") (result i32)
25    (call_indirect $t (type $i32-func) (i32.const 0))
26  )
27  (func (export "call-indirect-1") (result i32)
28    (call_indirect $t (type $i32-func) (i32.const 1))
29  )
30  (func (export "call-indirect-null") (result i32)
31    (call_indirect $t (type $i32-func) (i32.const 9))
32  )
33
34  ;; typed select between two funcrefs
35  (func (export "select-funcref") (param $c i32) (result funcref)
36    (select (result funcref) (ref.func $returns-42) (ref.func $returns-7) (local.get $c))
37  )
38  (func (export "select-null-first") (param $c i32) (result funcref)
39    (select (result funcref) (ref.null func) (ref.func $returns-7) (local.get $c))
40  )
41
42  ;; table.get / table.set
43  (func (export "table-get") (param $i i32) (result funcref)
44    (table.get $t (local.get $i))
45  )
46  (func (export "table-set-null") (param $i i32)
47    (table.set $t (local.get $i) (ref.null func))
48  )
49  (func (export "table-set-ref") (param $i i32)
50    (table.set $t (local.get $i) (ref.func $returns-42))
51  )
52
53  ;; ref.func -> table.set -> call_indirect
54  (func (export "set-and-call") (result i32)
55    (table.set $t (i32.const 5) (ref.func $returns-42))
56    (call_indirect $t (type $i32-func) (i32.const 5))
57  )
58
59  ;; table.grow
60  (func (export "table-grow") (param $n i32) (result i32)
61    (table.grow $t (ref.null func) (local.get $n))
62  )
63  (func (export "table-size") (result i32)
64    (table.size $t)
65  )
66)
67
68;; ref.null / ref.is_null
69(assert_return (invoke "null-is-null") (i32.const 1))
70(assert_return (invoke "func-is-not-null") (i32.const 0))
71
72;; call_indirect through elem-populated table
73(assert_return (invoke "call-indirect-0") (i32.const 42))
74(assert_return (invoke "call-indirect-1") (i32.const 7))
75(assert_trap (invoke "call-indirect-null") "uninitialized element")
76
77;; typed select
78(assert_return (invoke "select-funcref" (i32.const 1)) (ref.func 0))
79(assert_return (invoke "select-funcref" (i32.const 0)) (ref.func 1))
80(assert_return (invoke "select-null-first" (i32.const 1)) (ref.null func))
81(assert_return (invoke "select-null-first" (i32.const 0)) (ref.func 1))
82
83;; ref.func -> table.set -> call_indirect
84(assert_return (invoke "set-and-call") (i32.const 42))
85
86;; table.get
87(assert_return (invoke "table-get" (i32.const 0)) (ref.func 0))
88(assert_return (invoke "table-get" (i32.const 1)) (ref.func 1))
89(assert_return (invoke "table-get" (i32.const 2)) (ref.null func))
90(assert_trap (invoke "table-get" (i32.const 10)) "out of bounds table access")
91
92;; table.set
93(assert_return (invoke "table-set-null" (i32.const 0)))
94(assert_return (invoke "table-get" (i32.const 0)) (ref.null func))
95(assert_return (invoke "table-set-ref" (i32.const 0)))
96(assert_return (invoke "table-get" (i32.const 0)) (ref.func 0))
97(assert_trap (invoke "table-set-null" (i32.const 10)) "out of bounds table access")
98
99;; table.grow
100(assert_return (invoke "table-size") (i32.const 10))
101(assert_return (invoke "table-grow" (i32.const 5)) (i32.const 10))
102(assert_return (invoke "table-size") (i32.const 15))
103