[WASM-References] Rename anyfunc to funcref
[WebKit-https.git] / JSTests / wasm / references / multitable.js
1 import * as assert from '../assert.js';
2 import Builder from '../Builder.js';
3
4 {
5     const $1 = new WebAssembly.Instance(new WebAssembly.Module((new Builder())
6           .Type().End()
7           .Function().End()
8           .Table()
9                 .Table({initial: 0, maximum: 0, element: "anyref"})
10                 .Table({initial: 20, maximum: 30, element: "anyref"})
11           .End()
12           .Export()
13               .Function("set_tbl")
14               .Function("get_tbl")
15               .Function("get_tbl0")
16               .Function("set_tbl0")
17               .Table("tbl", 1)
18           .End()
19           .Code()
20             .Function("set_tbl", { params: ["anyref"], ret: "void" })
21               .I32Const(0)
22               .GetLocal(0)
23               .TableSet(1)
24             .End()
25
26             .Function("get_tbl", { params: [], ret: "anyref" })
27               .I32Const(0)
28               .TableGet(1)
29             .End()
30
31             .Function("get_tbl0", { params: [], ret: "anyref" })
32               .I32Const(0)
33               .TableGet(0)
34             .End()
35
36             .Function("set_tbl0", { params: ["anyref"], ret: "void" })
37               .I32Const(0)
38               .GetLocal(0)
39               .TableSet(0)
40             .End()
41           .End().WebAssembly().get()));
42
43     fullGC()
44
45     assert.eq($1.exports.get_tbl(), null)
46
47     $1.exports.set_tbl("hi")
48     fullGC()
49     assert.eq($1.exports.get_tbl(), "hi")
50     assert.eq($1.exports.tbl.get(0), "hi")
51     assert.eq($1.exports.tbl.get(1), null)
52
53     assert.throws(() => $1.exports.get_tbl0(), Error, "Out of bounds table access (evaluating 'func(...args)')");
54     assert.throws(() => $1.exports.set_tbl0(null), Error, "Out of bounds table access (evaluating 'func(...args)')");
55 }
56
57 {
58     const tbl = new WebAssembly.Table({initial:0, element:"anyref"});
59     const $1 = new WebAssembly.Instance(new WebAssembly.Module((new Builder())
60           .Type().End()
61           .Import()
62                 .Table("imp", "tbl", {initial: 0, element: "anyref"})
63           .End()
64           .Function().End()
65           .Table()
66                 .Table({initial: 20, maximum: 30, element: "anyref"})
67           .End()
68           .Export()
69               .Function("set_tbl")
70               .Function("get_tbl")
71               .Function("get_tbl0")
72               .Function("set_tbl0")
73               .Table("tbl", 1)
74           .End()
75           .Code()
76             .Function("set_tbl", { params: ["anyref"], ret: "void" })
77               .I32Const(0)
78               .GetLocal(0)
79               .TableSet(1)
80             .End()
81
82             .Function("get_tbl", { params: [], ret: "anyref" })
83               .I32Const(0)
84               .TableGet(1)
85             .End()
86
87             .Function("get_tbl0", { params: [], ret: "anyref" })
88               .I32Const(0)
89               .TableGet(0)
90             .End()
91
92             .Function("set_tbl0", { params: ["anyref"], ret: "void" })
93               .I32Const(0)
94               .GetLocal(0)
95               .TableSet(0)
96             .End()
97           .End().WebAssembly().get()), { imp: { tbl }});
98
99     fullGC()
100
101     assert.eq($1.exports.get_tbl(), null)
102
103     $1.exports.set_tbl("hi")
104     fullGC()
105     assert.eq($1.exports.get_tbl(), "hi")
106     assert.eq($1.exports.tbl.get(0), "hi")
107     assert.eq($1.exports.tbl.get(1), null)
108
109     assert.throws(() => $1.exports.get_tbl0(), Error, "Out of bounds table access (evaluating 'func(...args)')");
110     assert.throws(() => $1.exports.set_tbl0(null), Error, "Out of bounds table access (evaluating 'func(...args)')");
111 }
112
113 {
114     const tbl = new WebAssembly.Table({initial:1, element:"anyref"});
115     const $1 = new WebAssembly.Instance(new WebAssembly.Module((new Builder())
116           .Type().End()
117           .Import()
118                 .Table("imp", "tbl", {initial: 1, element: "anyref"})
119           .End()
120           .Function().End()
121           .Table()
122                 .Table({initial: 20, maximum: 30, element: "anyref"})
123           .End()
124           .Export()
125               .Function("set_tbl")
126               .Function("get_tbl")
127               .Function("get_tbl0")
128               .Function("set_tbl0")
129               .Table("tbl", 1)
130           .End()
131           .Code()
132             .Function("set_tbl", { params: ["anyref"], ret: "void" })
133               .I32Const(0)
134               .GetLocal(0)
135               .TableSet(1)
136             .End()
137
138             .Function("get_tbl", { params: [], ret: "anyref" })
139               .I32Const(0)
140               .TableGet(1)
141             .End()
142
143             .Function("get_tbl0", { params: [], ret: "anyref" })
144               .I32Const(0)
145               .TableGet(0)
146             .End()
147
148             .Function("set_tbl0", { params: ["anyref"], ret: "void" })
149               .I32Const(0)
150               .GetLocal(0)
151               .TableSet(0)
152             .End()
153           .End().WebAssembly().get()), { imp: { tbl }});
154
155     fullGC()
156
157     assert.eq($1.exports.get_tbl(), null)
158
159     $1.exports.set_tbl("hi")
160     fullGC()
161     $1.exports.set_tbl0(null)
162     assert.eq($1.exports.get_tbl(), "hi")
163     assert.eq($1.exports.get_tbl0(), null)
164     assert.eq($1.exports.tbl.get(0), "hi")
165     assert.eq($1.exports.tbl.get(1), null)
166     assert.eq(tbl.get(0), null)
167 }
168
169 {
170     const $1 = new WebAssembly.Instance(new WebAssembly.Module((new Builder())
171           .Type().End()
172           .Function().End()
173           .Table()
174                 .Table({initial: 3, maximum: 30, element: "funcref"})
175                 .Table({initial: 2, maximum: 30, element: "funcref"})
176           .End()
177           .Export()
178               .Function("call_tbl0")
179               .Function("call_tbl1")
180               .Function("ret42")
181               .Function("ret1337")
182               .Function("ret256")
183           .End()
184           .Element()
185                 .Element({tableIndex: 1, offset: 0, functionIndices: [2]})
186           .End()
187           .Code()
188             .Function("call_tbl0", { params: ["i32"], ret: "i32" })
189               .GetLocal(0)
190               .CallIndirect(1,0)
191             .End()
192
193             .Function("call_tbl1", { params: ["i32"], ret: "i32" })
194               .GetLocal(0)
195               .CallIndirect(1,1)
196             .End()
197
198             .Function("ret42", { params: [], ret: "i32" })
199               .I32Const(42)
200             .End()
201
202             .Function("ret1337", { params: [], ret: "i32" })
203               .I32Const(1337)
204             .End()
205
206             .Function("ret256", { params: [], ret: "i32" })
207               .I32Const(256)
208             .End()
209           .End().WebAssembly().get()));
210
211     fullGC()
212
213     assert.eq($1.exports.call_tbl1(0), 42)
214     assert.throws(() => $1.exports.call_tbl0(0), Error, "call_indirect to a null table entry (evaluating 'func(...args)')")
215     assert.throws(() => $1.exports.call_tbl1(1), Error, "call_indirect to a null table entry (evaluating 'func(...args)')")
216 }
217
218 {
219     const $1 = new WebAssembly.Instance(new WebAssembly.Module((new Builder())
220           .Type().End()
221           .Function().End()
222           .Table()
223                 .Table({initial: 3, maximum: 30, element: "funcref"})
224                 .Table({initial: 2, maximum: 30, element: "funcref"})
225           .End()
226           .Export()
227               .Function("call_tbl0")
228               .Function("call_tbl1")
229               .Function("ret42")
230               .Function("ret1337")
231               .Function("ret256")
232           .End()
233           .Element()
234                 .Element({tableIndex: 1, offset: 0, functionIndices: [2]})
235                 .Element({tableIndex: 0, offset: 0, functionIndices: [3]})
236                 .Element({tableIndex: 1, offset: 1, functionIndices: [4]})
237           .End()
238           .Code()
239             .Function("call_tbl0", { params: ["i32"], ret: "i32" })
240               .GetLocal(0)
241               .CallIndirect(1,0)
242             .End()
243
244             .Function("call_tbl1", { params: ["i32"], ret: "i32" })
245               .GetLocal(0)
246               .CallIndirect(1,1)
247             .End()
248
249             .Function("ret42", { params: [], ret: "i32" })
250               .I32Const(42)
251             .End()
252
253             .Function("ret1337", { params: [], ret: "i32" })
254               .I32Const(1337)
255             .End()
256
257             .Function("ret256", { params: [], ret: "i32" })
258               .I32Const(256)
259             .End()
260           .End().WebAssembly().get()));
261
262     fullGC()
263
264     assert.eq($1.exports.call_tbl1(0), 42)
265     assert.eq($1.exports.call_tbl0(0), 1337)
266     assert.eq($1.exports.call_tbl1(1), 256)
267     assert.throws(() => $1.exports.call_tbl0(1), Error, "call_indirect to a null table entry (evaluating 'func(...args)')")
268     assert.throws(() => $1.exports.call_tbl0(2), Error, "call_indirect to a null table entry (evaluating 'func(...args)')")
269     assert.throws(() => $1.exports.call_tbl1(2), Error, "Out of bounds call_indirect (evaluating 'func(...args)')")
270 }
271  assert.throws(() => new WebAssembly.Instance(new WebAssembly.Module((new Builder())
272           .Type().End()
273           .Function().End()
274           .Table()
275                 .Table({initial: 3, maximum: 3, element: "funcref"})
276                 .Table({initial: 2, maximum: 2, element: "funcref"})
277           .End()
278           .Element()
279                 .Element({tableIndex: 1, offset: 0, functionIndices: [0]})
280                 .Element({tableIndex: 0, offset: 0, functionIndices: [0]})
281                 .Element({tableIndex: 1, offset: 2, functionIndices: [0]})
282           .End()
283           .Code()
284             .Function("ret42", { params: [], ret: "i32" })
285               .I32Const(42)
286             .End()
287           .End().WebAssembly().get())), Error, "Element is trying to set an out of bounds table index (evaluating 'new WebAssembly.Instance')")
288
289 assert.throws(() => new WebAssembly.Instance(new WebAssembly.Module((new Builder())
290           .Type().End()
291           .Function().End()
292           .Table()
293                 .Table({initial: 3, maximum: 3, element: "anyref"})
294                 .Table({initial: 2, maximum: 3, element: "funcref"})
295           .End()
296           .Element()
297                 .Element({tableIndex: 1, offset: 0, functionIndices: [0]})
298                 .Element({tableIndex: 0, offset: 0, functionIndices: [0]})
299                 .Element({tableIndex: 1, offset: 2, functionIndices: [0]})
300           .End()
301           .Code()
302             .Function("ret42", { params: [], ret: "i32" })
303               .I32Const(42)
304             .End()
305           .End().WebAssembly().get())), Error, "WebAssembly.Module doesn't parse at byte 40: Table 0 must have type 'funcref' to have an element section (evaluating 'new WebAssembly.Module')")
306
307 assert.throws(() => new WebAssembly.Instance(new WebAssembly.Module((new Builder())
308           .Type().End()
309           .Function().End()
310           .Table()
311                 .Table({initial: 3, maximum: 3, element: "anyref"})
312                 .Table({initial: 2, maximum: 3, element: "funcref"})
313           .End()
314           .Code()
315             .Function("fun", { params: [], ret: "anyref" })
316               .I32Const(0)
317               .TableGet(2)
318             .End()
319           .End().WebAssembly().get())), Error, "WebAssembly.Module doesn't validate: table index 2 is invalid, limit is 2, in function at index 0 (evaluating 'new WebAssembly.Module')")
320
321 assert.throws(() => new WebAssembly.Instance(new WebAssembly.Module((new Builder())
322           .Type().End()
323           .Function().End()
324           .Table()
325                 .Table({initial: 3, maximum: 3, element: "anyref"})
326                 .Table({initial: 2, maximum: 3, element: "funcref"})
327           .End()
328           .Code()
329             .Function("fun", { params: [], ret: "void" })
330               .I32Const(0)
331               .RefNull()
332               .TableSet(2)
333             .End()
334           .End().WebAssembly().get())), Error, "WebAssembly.Module doesn't validate: table index 2 is invalid, limit is 2, in function at index 0 (evaluating 'new WebAssembly.Module')")
335
336 assert.throws(() => new WebAssembly.Instance(new WebAssembly.Module((new Builder())
337           .Type().End()
338           .Function().End()
339           .Table()
340                 .Table({initial: 3, maximum: 3, element: "anyref"})
341                 .Table({initial: 2, maximum: 3, element: "funcref"})
342           .End()
343           .Code()
344             .Function("fun", { params: [], ret: "void" })
345               .CallIndirect(0, 2)
346             .End()
347           .End().WebAssembly().get())), Error, "WebAssembly.Module doesn't parse at byte 4: call_indirect's table index 2 invalid, limit is 2, in function at index 0 (evaluating 'new WebAssembly.Module')")
348
349 assert.throws(() => new WebAssembly.Instance(new WebAssembly.Module((new Builder())
350           .Type().End()
351           .Function().End()
352           .Table()
353                 .Table({initial: 3, maximum: 3, element: "anyref"})
354                 .Table({initial: 2, maximum: 3, element: "funcref"})
355           .End()
356           .Code()
357             .Function("fun", { params: [], ret: "void" })
358               .CallIndirect(0,0)
359             .End()
360           .End().WebAssembly().get())), Error, "WebAssembly.Module doesn't parse at byte 4: call_indirect is only valid when a table has type funcref, in function at index 0 (evaluating 'new WebAssembly.Module')")
361
362 assert.throws(() => new WebAssembly.Instance(new WebAssembly.Module((new Builder())
363           .Type().End()
364           .Function().End()
365           .Table()
366                 .Table({initial: 3, maximum: 3, element: "anyref"})
367                 .Table({initial: 2, maximum: 3, element: "funcref"})
368           .End()
369           .Code()
370             .Function("fun", { params: [], ret: "void" })
371               .RefNull()
372               .TableGet(0)
373             .End()
374           .End().WebAssembly().get())), Error, "WebAssembly.Module doesn't validate: table.get index to type Funcref expected I32, in function at index 0 (evaluating 'new WebAssembly.Module')")
375
376
377 assert.throws(() => new WebAssembly.Instance(new WebAssembly.Module((new Builder())
378           .Type().End()
379           .Function().End()
380           .Table()
381                 .Table({initial: 3, maximum: 3, element: "anyref"})
382                 .Table({initial: 2, maximum: 3, element: "funcref"})
383           .End()
384           .Code()
385             .Function("fun", { params: [], ret: "void" })
386               .RefNull()
387               .RefNull()
388               .TableSet(0)
389             .End()
390           .End().WebAssembly().get())), Error, "WebAssembly.Module doesn't validate: table.set index to type Funcref expected I32, in function at index 0 (evaluating 'new WebAssembly.Module')")
391
392 assert.throws(() => new WebAssembly.Instance(new WebAssembly.Module((new Builder())
393           .Type().End()
394           .Function().End()
395           .Table()
396                 .Table({initial: 3, maximum: 3, element: "anyref"})
397                 .Table({initial: 2, maximum: 3, element: "funcref"})
398           .End()
399           .Code()
400             .Function("fun", { params: ["anyref"], ret: "void" })
401               .I32Const(0)
402               .GetLocal(0)
403               .TableSet(1)
404             .End()
405           .End().WebAssembly().get())), Error, "WebAssembly.Module doesn't validate: table.set value to type Anyref expected Funcref, in function at index 0 (evaluating 'new WebAssembly.Module')")
406
407 function tableInsanity(num, b) {
408     b = b.Import()
409     for (let i=0; i<100000-1; ++i)
410         b = b.Function("imp", "ref", { params: [], ret: "void" })
411     b = b.End().Function().End().Table()
412     for (let i=0; i<num; ++i)
413         b = b.Table({initial: 0, maximum: 3, element: "anyref"})
414     return b
415 }
416
417 assert.throws(() => new WebAssembly.Instance(new WebAssembly.Module(tableInsanity(1000000, (new Builder())
418           .Type().End())
419                 .Table({initial: 3, maximum: 3, element: "anyref"})
420           .End()
421           .Code()
422             .Function("fun", { params: ["anyref"], ret: "void" })
423               .I32Const(0)
424               .GetLocal(0)
425               .TableSet(1)
426             .End()
427           .End().WebAssembly().get())), Error, "WebAssembly.Module doesn't parse at byte 5000027: Table count of 1000000 is too big, maximum 1000000 (evaluating 'new WebAssembly.Module')")
428 {
429     const $1 = new WebAssembly.Instance(new WebAssembly.Module(tableInsanity(1000000-2, (new Builder())
430           .Type().End())
431                 .Table({initial: 3, maximum: 3, element: "funcref"})
432                 .Table({initial: 3, maximum: 3, element: "anyref"})
433           .End()
434           .Export()
435                 .Function("set_tbl")
436                 .Function("get_tbl")
437                 .Function("call")
438           .End()
439           .Element()
440                 .Element({tableIndex: 1000000-2, offset: 0, functionIndices: [0]})
441           .End()
442           .Code()
443             .Function("set_tbl", { params: ["anyref"], ret: "void" })
444               .I32Const(0)
445               .GetLocal(0)
446               .TableSet(1000000-1)
447             .End()
448             .Function("get_tbl", { params: [], ret: "anyref" })
449               .I32Const(0)
450               .TableGet(1000000-1)
451             .End()
452             .Function("call", { params: [], ret: "void" })
453               .I32Const(0)
454               .CallIndirect(0, 1000000-2)
455             .End()
456           .End().WebAssembly().get()), { imp: { ref: function () {} } })
457     $1.exports.set_tbl("hi")
458     assert.eq($1.exports.get_tbl(), "hi")
459     $1.exports.call()
460 }