WebAssembly JS API: check and test in-call / out-call values
[WebKit-https.git] / JSTests / wasm / fuzz / export-function.js
1 import * as assert from '../assert.js';
2 import Builder from '../Builder.js';
3
4 const numRandomIterations = 128;
5
6 // Generate wasm export functions of arity [0, max), using each valid
7 // WebAssembly type as parameters. Make sure this number is high enough to force
8 // non-register calls.
9 const maxArities = 64;
10
11 // Calls a "check" function for each parameter received.
12 const paramExporter = (params, returnedParam, imports) => {
13     const ret = params.length ? params[returnedParam] : "void";
14     let builder = (new Builder())
15         .Type().End()
16         .Import()
17             .Function("imp", "checki32", { params: ["i32"] })
18             .Function("imp", "checkf32", { params: ["f32"] })
19             .Function("imp", "checkf64", { params: ["f64"] })
20         .End()
21         .Function().End()
22         .Export()
23             .Function("func")
24         .End()
25         .Code()
26             .Function("func", { params: params, ret: ret });
27     for (let i = 0; i < params.length; ++i) {
28         builder = builder.GetLocal(i);
29         switch (params[i]) {
30         case "i32": builder = builder.Call(0); break;
31         case "f32": builder = builder.Call(1); break;
32         case "f64": builder = builder.Call(2); break;
33         default: throw new Error(`Unexpected type`);
34         }
35     }
36     if (ret !== "void")
37         builder = builder.GetLocal(returnedParam);
38     builder = builder.Return().End().End();
39     const bin = builder.WebAssembly().get();
40     const module = new WebAssembly.Module(bin);
41     return new WebAssembly.Instance(module, { imp: imports });
42 };
43
44 var buffer = new ArrayBuffer(8);
45 var viewi16 = new Int16Array(buffer);
46 var viewi32 = new Int32Array(buffer);
47 var viewf32 = new Float32Array(buffer);
48 var viewf64 = new Float64Array(buffer);
49 const random16 = () => (Math.random() * (1 + 0xffff)) | 0;
50 const setBuffer = () => {
51     for (let i = 0; i < 4; ++i)
52         viewi16[i] = random16();
53 };
54 const types = [
55     { type: "i32", generate: () => { setBuffer(); return viewi32[0]; } },
56     // i64 isn't supported.
57     { type: "f32", generate: () => { setBuffer(); return viewf32[0]; } },
58     { type: "f64", generate: () => { setBuffer(); return viewf64[0]; } },
59 ];
60
61 for (let iteration = 0; iteration < numRandomIterations; ++iteration) {
62     const arity = (Math.random() * (maxArities + 1)) | 0;
63     let params = [];
64     let args = [];
65     for (let a = 0; a < arity; ++a) {
66         const type =( Math.random() * types.length) | 0;
67         params.push(types[type].type);
68         args.push(types[type].generate());
69     }
70     let numChecked = 0;
71     const imports = {
72         checki32: v => assert.eq(v, args[numChecked++]),
73         checkf32: v => assert.eq(v, args[numChecked++]),
74         checkf64: v => assert.eq(v, args[numChecked++]),
75     };
76     const returnedParam = (Math.random() * params.length) | 0;
77     const instance = paramExporter(params, returnedParam, imports);
78     const result = instance.exports.func(...args);
79     assert.eq(result, args.length ? args[returnedParam] : undefined);
80 }