...
1;; Functions
2
3(module $Mf
4 (func (export "call") (result i32) (call $g))
5 (func $g (result i32) (i32.const 2))
6)
7(register "Mf" $Mf)
8
9(module $Nf
10 (func $f (import "Mf" "call") (result i32))
11 (export "Mf.call" (func $f))
12 (func (export "call Mf.call") (result i32) (call $f))
13 (func (export "call") (result i32) (call $g))
14 (func $g (result i32) (i32.const 3))
15)
16
17(assert_return (invoke $Mf "call") (i32.const 2))
18(assert_return (invoke $Nf "Mf.call") (i32.const 2))
19(assert_return (invoke $Nf "call") (i32.const 3))
20(assert_return (invoke $Nf "call Mf.call") (i32.const 2))
21
22(module
23 (import "spectest" "print_i32" (func $f (param i32)))
24 (export "print" (func $f))
25)
26(register "reexport_f")
27(assert_unlinkable
28 (module (import "reexport_f" "print" (func (param i64))))
29 "incompatible import type"
30)
31(assert_unlinkable
32 (module (import "reexport_f" "print" (func (param i32) (result i32))))
33 "incompatible import type"
34)
35
36
37;; Globals
38
39(module $Mg
40 (global $glob (export "glob") i32 (i32.const 42))
41 (func (export "get") (result i32) (global.get $glob))
42
43 ;; export mutable globals
44 (global $mut_glob (export "mut_glob") (mut i32) (i32.const 142))
45 (func (export "get_mut") (result i32) (global.get $mut_glob))
46 (func (export "set_mut") (param i32) (global.set $mut_glob (local.get 0)))
47)
48(register "Mg" $Mg)
49
50(module $Ng
51 (global $x (import "Mg" "glob") i32)
52 (global $mut_glob (import "Mg" "mut_glob") (mut i32))
53 (func $f (import "Mg" "get") (result i32))
54 (func $get_mut (import "Mg" "get_mut") (result i32))
55 (func $set_mut (import "Mg" "set_mut") (param i32))
56
57 (export "Mg.glob" (global $x))
58 (export "Mg.get" (func $f))
59 (global $glob (export "glob") i32 (i32.const 43))
60 (func (export "get") (result i32) (global.get $glob))
61
62 (export "Mg.mut_glob" (global $mut_glob))
63 (export "Mg.get_mut" (func $get_mut))
64 (export "Mg.set_mut" (func $set_mut))
65)
66
67(assert_return (get $Mg "glob") (i32.const 42))
68(assert_return (get $Ng "Mg.glob") (i32.const 42))
69(assert_return (get $Ng "glob") (i32.const 43))
70(assert_return (invoke $Mg "get") (i32.const 42))
71(assert_return (invoke $Ng "Mg.get") (i32.const 42))
72(assert_return (invoke $Ng "get") (i32.const 43))
73
74(assert_return (get $Mg "mut_glob") (i32.const 142))
75(assert_return (get $Ng "Mg.mut_glob") (i32.const 142))
76(assert_return (invoke $Mg "get_mut") (i32.const 142))
77(assert_return (invoke $Ng "Mg.get_mut") (i32.const 142))
78
79(assert_return (invoke $Mg "set_mut" (i32.const 241)))
80(assert_return (get $Mg "mut_glob") (i32.const 241))
81(assert_return (get $Ng "Mg.mut_glob") (i32.const 241))
82(assert_return (invoke $Mg "get_mut") (i32.const 241))
83(assert_return (invoke $Ng "Mg.get_mut") (i32.const 241))
84
85
86(assert_unlinkable
87 (module (import "Mg" "mut_glob" (global i32)))
88 "incompatible import type"
89)
90(assert_unlinkable
91 (module (import "Mg" "glob" (global (mut i32))))
92 "incompatible import type"
93)
94
95
96(module $Mref_ex
97 (global (export "g-const-func") funcref (ref.null func))
98 (global (export "g-var-func") (mut funcref) (ref.null func))
99 (global (export "g-const-extern") externref (ref.null extern))
100 (global (export "g-var-extern") (mut externref) (ref.null extern))
101)
102(register "Mref_ex" $Mref_ex)
103
104(module $Mref_im
105 (global (import "Mref_ex" "g-const-func") funcref)
106 (global (import "Mref_ex" "g-const-extern") externref)
107
108 (global (import "Mref_ex" "g-var-func") (mut funcref))
109 (global (import "Mref_ex" "g-var-extern") (mut externref))
110)
111
112(assert_unlinkable
113 (module (global (import "Mref_ex" "g-const-extern") funcref))
114 "incompatible import type"
115)
116(assert_unlinkable
117 (module (global (import "Mref_ex" "g-const-func") externref))
118 "incompatible import type"
119)
120
121
122(assert_unlinkable
123 (module (global (import "Mref_ex" "g-var-func") (mut externref)))
124 "incompatible import type"
125)
126(assert_unlinkable
127 (module (global (import "Mref_ex" "g-var-extern") (mut funcref)))
128 "incompatible import type"
129)
130
131
132;; Tables
133
134(module $Mt
135 (type (func (result i32)))
136 (type (func))
137
138 (table (export "tab") 10 funcref)
139 (elem (i32.const 2) $g $g $g $g)
140 (func $g (result i32) (i32.const 4))
141 (func (export "h") (result i32) (i32.const -4))
142
143 (func (export "call") (param i32) (result i32)
144 (call_indirect (type 0) (local.get 0))
145 )
146)
147(register "Mt" $Mt)
148
149(module $Nt
150 (type (func))
151 (type (func (result i32)))
152
153 (func $f (import "Mt" "call") (param i32) (result i32))
154 (func $h (import "Mt" "h") (result i32))
155
156 (table funcref (elem $g $g $g $h $f))
157 (func $g (result i32) (i32.const 5))
158
159 (export "Mt.call" (func $f))
160 (func (export "call Mt.call") (param i32) (result i32)
161 (call $f (local.get 0))
162 )
163 (func (export "call") (param i32) (result i32)
164 (call_indirect (type 1) (local.get 0))
165 )
166)
167
168(assert_return (invoke $Mt "call" (i32.const 2)) (i32.const 4))
169(assert_return (invoke $Nt "Mt.call" (i32.const 2)) (i32.const 4))
170(assert_return (invoke $Nt "call" (i32.const 2)) (i32.const 5))
171(assert_return (invoke $Nt "call Mt.call" (i32.const 2)) (i32.const 4))
172
173(assert_trap (invoke $Mt "call" (i32.const 1)) "uninitialized element")
174(assert_trap (invoke $Nt "Mt.call" (i32.const 1)) "uninitialized element")
175(assert_return (invoke $Nt "call" (i32.const 1)) (i32.const 5))
176(assert_trap (invoke $Nt "call Mt.call" (i32.const 1)) "uninitialized element")
177
178(assert_trap (invoke $Mt "call" (i32.const 0)) "uninitialized element")
179(assert_trap (invoke $Nt "Mt.call" (i32.const 0)) "uninitialized element")
180(assert_return (invoke $Nt "call" (i32.const 0)) (i32.const 5))
181(assert_trap (invoke $Nt "call Mt.call" (i32.const 0)) "uninitialized element")
182
183(assert_trap (invoke $Mt "call" (i32.const 20)) "undefined element")
184(assert_trap (invoke $Nt "Mt.call" (i32.const 20)) "undefined element")
185(assert_trap (invoke $Nt "call" (i32.const 7)) "undefined element")
186(assert_trap (invoke $Nt "call Mt.call" (i32.const 20)) "undefined element")
187
188(assert_return (invoke $Nt "call" (i32.const 3)) (i32.const -4))
189(assert_trap (invoke $Nt "call" (i32.const 4)) "indirect call type mismatch")
190
191(module $Ot
192 (type (func (result i32)))
193
194 (func $h (import "Mt" "h") (result i32))
195 (table (import "Mt" "tab") 5 funcref)
196 (elem (i32.const 1) $i $h)
197 (func $i (result i32) (i32.const 6))
198
199 (func (export "call") (param i32) (result i32)
200 (call_indirect (type 0) (local.get 0))
201 )
202)
203
204(assert_return (invoke $Mt "call" (i32.const 3)) (i32.const 4))
205(assert_return (invoke $Nt "Mt.call" (i32.const 3)) (i32.const 4))
206(assert_return (invoke $Nt "call Mt.call" (i32.const 3)) (i32.const 4))
207(assert_return (invoke $Ot "call" (i32.const 3)) (i32.const 4))
208
209(assert_return (invoke $Mt "call" (i32.const 2)) (i32.const -4))
210(assert_return (invoke $Nt "Mt.call" (i32.const 2)) (i32.const -4))
211(assert_return (invoke $Nt "call" (i32.const 2)) (i32.const 5))
212(assert_return (invoke $Nt "call Mt.call" (i32.const 2)) (i32.const -4))
213(assert_return (invoke $Ot "call" (i32.const 2)) (i32.const -4))
214
215(assert_return (invoke $Mt "call" (i32.const 1)) (i32.const 6))
216(assert_return (invoke $Nt "Mt.call" (i32.const 1)) (i32.const 6))
217(assert_return (invoke $Nt "call" (i32.const 1)) (i32.const 5))
218(assert_return (invoke $Nt "call Mt.call" (i32.const 1)) (i32.const 6))
219(assert_return (invoke $Ot "call" (i32.const 1)) (i32.const 6))
220
221(assert_trap (invoke $Mt "call" (i32.const 0)) "uninitialized element")
222(assert_trap (invoke $Nt "Mt.call" (i32.const 0)) "uninitialized element")
223(assert_return (invoke $Nt "call" (i32.const 0)) (i32.const 5))
224(assert_trap (invoke $Nt "call Mt.call" (i32.const 0)) "uninitialized element")
225(assert_trap (invoke $Ot "call" (i32.const 0)) "uninitialized element")
226
227(assert_trap (invoke $Ot "call" (i32.const 20)) "undefined element")
228
229(module
230 (table (import "Mt" "tab") 0 funcref)
231 (elem (i32.const 9) $f)
232 (func $f)
233)
234
235(module $G1 (global (export "g") i32 (i32.const 5)))
236(register "G1" $G1)
237(module $G2
238 (global (import "G1" "g") i32)
239 (global (export "g") i32 (global.get 0))
240)
241(assert_return (get $G2 "g") (i32.const 5))
242
243(assert_trap
244 (module
245 (table (import "Mt" "tab") 0 funcref)
246 (elem (i32.const 10) $f)
247 (func $f)
248 )
249 "out of bounds table access"
250)
251
252(assert_unlinkable
253 (module
254 (table (import "Mt" "tab") 10 funcref)
255 (memory (import "Mt" "mem") 1) ;; does not exist
256 (func $f (result i32) (i32.const 0))
257 (elem (i32.const 7) $f)
258 (elem (i32.const 9) $f)
259 )
260 "unknown import"
261)
262(assert_trap (invoke $Mt "call" (i32.const 7)) "uninitialized element")
263
264;; Unlike in the v1 spec, active element segments stored before an
265;; out-of-bounds access persist after the instantiation failure.
266(assert_trap
267 (module
268 (table (import "Mt" "tab") 10 funcref)
269 (func $f (result i32) (i32.const 0))
270 (elem (i32.const 7) $f)
271 (elem (i32.const 8) $f $f $f $f $f) ;; (partially) out of bounds
272 )
273 "out of bounds table access"
274)
275(assert_return (invoke $Mt "call" (i32.const 7)) (i32.const 0))
276(assert_trap (invoke $Mt "call" (i32.const 8)) "uninitialized element")
277
278(assert_trap
279 (module
280 (table (import "Mt" "tab") 10 funcref)
281 (func $f (result i32) (i32.const 0))
282 (elem (i32.const 7) $f)
283 (memory 1)
284 (data (i32.const 0x10000) "d") ;; out of bounds
285 )
286 "out of bounds memory access"
287)
288(assert_return (invoke $Mt "call" (i32.const 7)) (i32.const 0))
289
290
291(module $Mtable_ex
292 (table $t1 (export "t-func") 1 funcref)
293 (table $t2 (export "t-extern") 1 externref)
294)
295(register "Mtable_ex" $Mtable_ex)
296
297(module
298 (table (import "Mtable_ex" "t-func") 1 funcref)
299 (table (import "Mtable_ex" "t-extern") 1 externref)
300)
301
302(assert_unlinkable
303 (module (table (import "Mtable_ex" "t-func") 1 externref))
304 "incompatible import type"
305)
306(assert_unlinkable
307 (module (table (import "Mtable_ex" "t-extern") 1 funcref))
308 "incompatible import type"
309)
310
311
312;; Memories
313
314(module $Mm
315 (memory (export "mem") 1 5)
316 (data (i32.const 10) "\00\01\02\03\04\05\06\07\08\09")
317
318 (func (export "load") (param $a i32) (result i32)
319 (i32.load8_u (local.get 0))
320 )
321)
322(register "Mm" $Mm)
323
324(module $Nm
325 (func $loadM (import "Mm" "load") (param i32) (result i32))
326
327 (memory 1)
328 (data (i32.const 10) "\f0\f1\f2\f3\f4\f5")
329
330 (export "Mm.load" (func $loadM))
331 (func (export "load") (param $a i32) (result i32)
332 (i32.load8_u (local.get 0))
333 )
334)
335
336(assert_return (invoke $Mm "load" (i32.const 12)) (i32.const 2))
337(assert_return (invoke $Nm "Mm.load" (i32.const 12)) (i32.const 2))
338(assert_return (invoke $Nm "load" (i32.const 12)) (i32.const 0xf2))
339
340(module $Om
341 (memory (import "Mm" "mem") 1)
342 (data (i32.const 5) "\a0\a1\a2\a3\a4\a5\a6\a7")
343
344 (func (export "load") (param $a i32) (result i32)
345 (i32.load8_u (local.get 0))
346 )
347)
348
349(assert_return (invoke $Mm "load" (i32.const 12)) (i32.const 0xa7))
350(assert_return (invoke $Nm "Mm.load" (i32.const 12)) (i32.const 0xa7))
351(assert_return (invoke $Nm "load" (i32.const 12)) (i32.const 0xf2))
352(assert_return (invoke $Om "load" (i32.const 12)) (i32.const 0xa7))
353
354(module
355 (memory (import "Mm" "mem") 0)
356 (data (i32.const 0xffff) "a")
357)
358
359(assert_trap
360 (module
361 (memory (import "Mm" "mem") 0)
362 (data (i32.const 0x10000) "a")
363 )
364 "out of bounds memory access"
365)
366
367(module $Pm
368 (memory (import "Mm" "mem") 1 8)
369
370 (func (export "grow") (param $a i32) (result i32)
371 (memory.grow (local.get 0))
372 )
373)
374
375(assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 1))
376(assert_return (invoke $Pm "grow" (i32.const 2)) (i32.const 1))
377(assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 3))
378(assert_return (invoke $Pm "grow" (i32.const 1)) (i32.const 3))
379(assert_return (invoke $Pm "grow" (i32.const 1)) (i32.const 4))
380(assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 5))
381(assert_return (invoke $Pm "grow" (i32.const 1)) (i32.const -1))
382(assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 5))
383
384(assert_unlinkable
385 (module
386 (func $host (import "spectest" "print"))
387 (memory (import "Mm" "mem") 1)
388 (table (import "Mm" "tab") 0 funcref) ;; does not exist
389 (data (i32.const 0) "abc")
390 )
391 "unknown import"
392)
393(assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 0))
394
395;; Unlike in v1 spec, active data segments written before an
396;; out-of-bounds access persist after the instantiation failure.
397(assert_trap
398 (module
399 ;; Note: the memory is 5 pages large by the time we get here.
400 (memory (import "Mm" "mem") 1)
401 (data (i32.const 0) "abc")
402 (data (i32.const 327670) "zzzzzzzzzzzzzzzzzz") ;; (partially) out of bounds
403 )
404 "out of bounds memory access"
405)
406(assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 97))
407(assert_return (invoke $Mm "load" (i32.const 327670)) (i32.const 0))
408
409(assert_trap
410 (module
411 (memory (import "Mm" "mem") 1)
412 (data (i32.const 0) "abc")
413 (table 0 funcref)
414 (func)
415 (elem (i32.const 0) 0) ;; out of bounds
416 )
417 "out of bounds table access"
418)
419(assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 97))
420
421;; Store is modified if the start function traps.
422(module $Ms
423 (type $t (func (result i32)))
424 (memory (export "memory") 1)
425 (table (export "table") 1 funcref)
426 (func (export "get memory[0]") (type $t)
427 (i32.load8_u (i32.const 0))
428 )
429 (func (export "get table[0]") (type $t)
430 (call_indirect (type $t) (i32.const 0))
431 )
432)
433(register "Ms" $Ms)
434
435(assert_trap
436 (module
437 (import "Ms" "memory" (memory 1))
438 (import "Ms" "table" (table 1 funcref))
439 (data (i32.const 0) "hello")
440 (elem (i32.const 0) $f)
441 (func $f (result i32)
442 (i32.const 0xdead)
443 )
444 (func $main
445 (unreachable)
446 )
447 (start $main)
448 )
449 "unreachable"
450)
451
452(assert_return (invoke $Ms "get memory[0]") (i32.const 104)) ;; 'h'
453(assert_return (invoke $Ms "get table[0]") (i32.const 0xdead))
View as plain text