blob: 35ef1ab4b978395608cc15660996245644315ad6 [file] [edit]
//@ requireOptions("--useWasmWideArithmetic=1")
import * as assert from '../assert.js';
// Tests that wide arithmetic instructions work when operands come from i64.const
// rather than local.get. This exercises the BBQ JIT's materializeToGPR path for
// const values.
//
// Functions:
// f0: add128 all const () -> (i64, i64)
// f1: sub128 all const () -> (i64, i64)
// f2: mul_wide_u all const () -> (i64, i64)
// f3: mul_wide_s all const () -> (i64, i64)
// f4: add128 (p0, c0, p1, c0) (i64, i64) -> (i64, i64)
// f5: sub128 (p0, c0, p1, c0) (i64, i64) -> (i64, i64)
// f6: add128 (c1, p0, c0, p1) (i64, i64) -> (i64, i64)
// f7: mul_wide_u (p0, c3) (i64) -> (i64, i64)
// f8: mul_wide_s (c-1, p0) (i64) -> (i64, i64)
const bytes = new Uint8Array([
0x00, 0x61, 0x73, 0x6d, // magic
0x01, 0x00, 0x00, 0x00, // version
// type section (19 bytes)
0x01, 0x13,
0x03, // 3 types
0x60, 0x00, 0x02, 0x7e, 0x7e, // type 0: () -> (i64, i64)
0x60, 0x02, 0x7e, 0x7e, 0x02, 0x7e, 0x7e, // type 1: (i64, i64) -> (i64, i64)
0x60, 0x01, 0x7e, 0x02, 0x7e, 0x7e, // type 2: (i64) -> (i64, i64)
// function section (10 bytes)
0x03, 0x0a,
0x09, // 9 functions
0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02,
// export section (46 bytes)
0x07, 0x2e,
0x09, // 9 exports
0x02, 0x66, 0x30, 0x00, 0x00, // "f0" -> func 0
0x02, 0x66, 0x31, 0x00, 0x01, // "f1" -> func 1
0x02, 0x66, 0x32, 0x00, 0x02, // "f2" -> func 2
0x02, 0x66, 0x33, 0x00, 0x03, // "f3" -> func 3
0x02, 0x66, 0x34, 0x00, 0x04, // "f4" -> func 4
0x02, 0x66, 0x35, 0x00, 0x05, // "f5" -> func 5
0x02, 0x66, 0x36, 0x00, 0x06, // "f6" -> func 6
0x02, 0x66, 0x37, 0x00, 0x07, // "f7" -> func 7
0x02, 0x66, 0x38, 0x00, 0x08, // "f8" -> func 8
// code section (102 bytes)
0x0a, 0x66,
0x09, // 9 functions
// func 0: add128 all const — (5, 0) + (3, 0) = (8, 0)
0x0c, // body length = 12
0x00, // no locals
0x42, 0x05, // i64.const 5 (lhsLo)
0x42, 0x00, // i64.const 0 (lhsHi)
0x42, 0x03, // i64.const 3 (rhsLo)
0x42, 0x00, // i64.const 0 (rhsHi)
0xfc, 0x13, // i64.add128
0x0b, // end
// func 1: sub128 all const — (10, 1) - (3, 0) = (7, 1)
0x0c, // body length = 12
0x00, // no locals
0x42, 0x0a, // i64.const 10 (lhsLo)
0x42, 0x01, // i64.const 1 (lhsHi)
0x42, 0x03, // i64.const 3 (rhsLo)
0x42, 0x00, // i64.const 0 (rhsHi)
0xfc, 0x14, // i64.sub128
0x0b, // end
// func 2: mul_wide_u all const — 5 * 3 = (15, 0)
0x08, // body length = 8
0x00, // no locals
0x42, 0x05, // i64.const 5
0x42, 0x03, // i64.const 3
0xfc, 0x16, // i64.mul_wide_u
0x0b, // end
// func 3: mul_wide_s all const — (-2) * 3 = (-6, -1)
0x08, // body length = 8
0x00, // no locals
0x42, 0x7e, // i64.const -2
0x42, 0x03, // i64.const 3
0xfc, 0x15, // i64.mul_wide_s
0x0b, // end
// func 4: add128 mixed — (param0, const 0, param1, const 0)
0x0c, // body length = 12
0x00, // no locals
0x20, 0x00, // local.get 0 (lhsLo)
0x42, 0x00, // i64.const 0 (lhsHi)
0x20, 0x01, // local.get 1 (rhsLo)
0x42, 0x00, // i64.const 0 (rhsHi)
0xfc, 0x13, // i64.add128
0x0b, // end
// func 5: sub128 mixed — (param0, const 0, param1, const 0)
0x0c, // body length = 12
0x00, // no locals
0x20, 0x00, // local.get 0 (lhsLo)
0x42, 0x00, // i64.const 0 (lhsHi)
0x20, 0x01, // local.get 1 (rhsLo)
0x42, 0x00, // i64.const 0 (rhsHi)
0xfc, 0x14, // i64.sub128
0x0b, // end
// func 6: add128 mixed — (const 1, param0, const 0, param1)
0x0c, // body length = 12
0x00, // no locals
0x42, 0x01, // i64.const 1 (lhsLo)
0x20, 0x00, // local.get 0 (lhsHi)
0x42, 0x00, // i64.const 0 (rhsLo)
0x20, 0x01, // local.get 1 (rhsHi)
0xfc, 0x13, // i64.add128
0x0b, // end
// func 7: mul_wide_u mixed — (param0, const 3)
0x08, // body length = 8
0x00, // no locals
0x20, 0x00, // local.get 0
0x42, 0x03, // i64.const 3
0xfc, 0x16, // i64.mul_wide_u
0x0b, // end
// func 8: mul_wide_s mixed — (const -1, param0)
0x08, // body length = 8
0x00, // no locals
0x42, 0x7f, // i64.const -1
0x20, 0x00, // local.get 0
0xfc, 0x15, // i64.mul_wide_s
0x0b, // end
]);
function test() {
const module = new WebAssembly.Module(bytes);
const instance = new WebAssembly.Instance(module);
const { f0, f1, f2, f3, f4, f5, f6, f7, f8 } = instance.exports;
let r;
for (let i = 0; i < wasmTestLoopCount; ++i) {
// All-const tests
r = f0();
assert.eq(r[0], 8n);
assert.eq(r[1], 0n);
r = f1();
assert.eq(r[0], 7n);
assert.eq(r[1], 1n);
r = f2();
assert.eq(r[0], 15n);
assert.eq(r[1], 0n);
r = f3();
assert.eq(r[0], -6n);
assert.eq(r[1], -1n);
// Mixed add128: (param0, 0) + (param1, 0)
r = f4(5n, 3n);
assert.eq(r[0], 8n);
assert.eq(r[1], 0n);
r = f4(-1n, 1n);
assert.eq(r[0], 0n);
assert.eq(r[1], 1n);
// Mixed sub128: (param0, 0) - (param1, 0)
r = f5(10n, 3n);
assert.eq(r[0], 7n);
assert.eq(r[1], 0n);
r = f5(1n, 3n);
assert.eq(r[0], -2n);
assert.eq(r[1], -1n);
// Mixed add128: (1, param0) + (0, param1)
r = f6(2n, 3n);
assert.eq(r[0], 1n);
assert.eq(r[1], 5n);
r = f6(0n, -1n);
assert.eq(r[0], 1n);
assert.eq(r[1], -1n);
// Mixed mul_wide_u: param0 * 3
r = f7(5n);
assert.eq(r[0], 15n);
assert.eq(r[1], 0n);
r = f7(-1n);
assert.eq(r[0], -3n);
assert.eq(r[1], 2n);
// Mixed mul_wide_s: (-1) * param0
r = f8(5n);
assert.eq(r[0], -5n);
assert.eq(r[1], -1n);
r = f8(-1n);
assert.eq(r[0], 1n);
assert.eq(r[1], 0n);
}
}
noInline(test);
test();