| import * as assert from '../assert.js'; |
| import Builder from '../Builder.js'; |
| |
| const numRandomIterations = 128; |
| |
| // Generate wasm export functions of arity [0, max), using each valid |
| // WebAssembly type as parameters. Make sure this number is high enough to force |
| // non-register calls. |
| const maxArities = 64; |
| |
| // Calls a "check" function for each parameter received. |
| const paramExporter = (params, returnedParam, imports) => { |
| const ret = params.length ? params[returnedParam] : "void"; |
| let builder = (new Builder()) |
| .Type().End() |
| .Import() |
| .Function("imp", "checki32", { params: ["i32"] }) |
| .Function("imp", "checkf32", { params: ["f32"] }) |
| .Function("imp", "checkf64", { params: ["f64"] }) |
| .End() |
| .Function().End() |
| .Export() |
| .Function("func") |
| .End() |
| .Code() |
| .Function("func", { params: params, ret: ret }); |
| for (let i = 0; i < params.length; ++i) { |
| builder = builder.GetLocal(i); |
| switch (params[i]) { |
| case "i32": builder = builder.Call(0); break; |
| case "f32": builder = builder.Call(1); break; |
| case "f64": builder = builder.Call(2); break; |
| default: throw new Error(`Unexpected type`); |
| } |
| } |
| if (ret !== "void") |
| builder = builder.GetLocal(returnedParam); |
| builder = builder.Return().End().End(); |
| const bin = builder.WebAssembly().get(); |
| const module = new WebAssembly.Module(bin); |
| return new WebAssembly.Instance(module, { imp: imports }); |
| }; |
| |
| var buffer = new ArrayBuffer(8); |
| var viewi16 = new Int16Array(buffer); |
| var viewi32 = new Int32Array(buffer); |
| var viewf32 = new Float32Array(buffer); |
| var viewf64 = new Float64Array(buffer); |
| const random16 = () => (Math.random() * (1 + 0xffff)) | 0; |
| const setBuffer = () => { |
| for (let i = 0; i < 4; ++i) |
| viewi16[i] = random16(); |
| }; |
| const types = [ |
| { type: "i32", generate: () => { setBuffer(); return viewi32[0]; } }, |
| // i64 isn't supported. |
| { type: "f32", generate: () => { setBuffer(); return viewf32[0]; } }, |
| { type: "f64", generate: () => { setBuffer(); return viewf64[0]; } }, |
| ]; |
| |
| for (let iteration = 0; iteration < numRandomIterations; ++iteration) { |
| const arity = (Math.random() * (maxArities + 1)) | 0; |
| let params = []; |
| let args = []; |
| for (let a = 0; a < arity; ++a) { |
| const type =( Math.random() * types.length) | 0; |
| params.push(types[type].type); |
| args.push(types[type].generate()); |
| } |
| let numChecked = 0; |
| const imports = { |
| checki32: v => assert.eq(v, args[numChecked++]), |
| checkf32: v => assert.eq(v, args[numChecked++]), |
| checkf64: v => assert.eq(v, args[numChecked++]), |
| }; |
| const returnedParam = (Math.random() * params.length) | 0; |
| const instance = paramExporter(params, returnedParam, imports); |
| const result = instance.exports.func(...args); |
| assert.eq(result, args.length ? args[returnedParam] : undefined); |
| } |