PR-URL: https://github.com/nodejs/node/pull/58070 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Darshan Sen <raisinten@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
402 lines
12 KiB
JavaScript
402 lines
12 KiB
JavaScript
// Copyright 2023 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
// Flags: --wasm-staging --no-liftoff --no-wasm-lazy-compilation
|
|
|
|
d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
|
|
|
|
(function TrivialFunctions() {
|
|
print(arguments.callee.name);
|
|
let builder = new WasmModuleBuilder();
|
|
builder.addFunction("id", makeSig([kWasmI32], [kWasmI32]))
|
|
.addBody([kExprLocalGet, 0])
|
|
.exportFunc();
|
|
|
|
let wasm = builder.instantiate().exports;
|
|
assertEquals(42, wasm.id(42));
|
|
|
|
})();
|
|
|
|
(function ArithmeticInt32() {
|
|
print(arguments.callee.name);
|
|
let builder = new WasmModuleBuilder();
|
|
let maddSig = makeSig([kWasmI32, kWasmI32, kWasmI32], [kWasmI32]);
|
|
builder.addFunction("madd", maddSig)
|
|
.addBody([
|
|
// local[0] + (local[1] * local[2])
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 1,
|
|
kExprLocalGet, 2,
|
|
kExprI32Mul,
|
|
kExprI32Add
|
|
])
|
|
.exportFunc();
|
|
builder.addFunction("madd2", maddSig)
|
|
.addBody([
|
|
// (local[0] * local[1]) + local[2]
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 1,
|
|
kExprI32Mul,
|
|
kExprLocalGet, 2,
|
|
kExprI32Add
|
|
])
|
|
.exportFunc();
|
|
builder.addFunction("addConstant", makeSig([kWasmI32], [kWasmI32]))
|
|
.addBody([kExprLocalGet, 0, ...wasmI32Const(-7), kExprI32Add])
|
|
.exportFunc();
|
|
builder.addFunction("add", makeSig([kWasmI32, kWasmI32], [kWasmI32]))
|
|
.addBody([kExprLocalGet, 0, kExprLocalGet, 1, kExprI32Add])
|
|
.exportFunc();
|
|
builder.addFunction("msub", maddSig)
|
|
.addBody([
|
|
// local[0] - (local[1] * local[2])
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 1,
|
|
kExprLocalGet, 2,
|
|
kExprI32Mul,
|
|
kExprI32Sub
|
|
])
|
|
.exportFunc();
|
|
builder.addFunction("subConstant", makeSig([kWasmI32], [kWasmI32]))
|
|
.addBody([kExprLocalGet, 0, ...wasmI32Const(-7), kExprI32Sub])
|
|
.exportFunc();
|
|
builder.addFunction("sub", makeSig([kWasmI32, kWasmI32], [kWasmI32]))
|
|
.addBody([kExprLocalGet, 0, kExprLocalGet, 1, kExprI32Sub])
|
|
.exportFunc();
|
|
builder.addFunction("mulConstant", makeSig([kWasmI32], [kWasmI32]))
|
|
// Can be lowered to local[0] + local[0] << 3.
|
|
.addBody([kExprLocalGet, 0, ...wasmI32Const(9), kExprI32Mul])
|
|
.exportFunc();
|
|
builder.addFunction("mulNegate", makeSig([kWasmI32, kWasmI32], [kWasmI32]))
|
|
.addBody([
|
|
// (0 - local[0]) * local[1]
|
|
kExprI32Const, 0,
|
|
kExprLocalGet, 0,
|
|
kExprI32Sub,
|
|
kExprLocalGet, 1,
|
|
kExprI32Mul])
|
|
.exportFunc();
|
|
builder.addFunction("mulNegate2", makeSig([kWasmI32, kWasmI32], [kWasmI32]))
|
|
.addBody([
|
|
// local[0] * (0 - local[1])
|
|
kExprLocalGet, 0,
|
|
kExprI32Const, 0,
|
|
kExprLocalGet, 1,
|
|
kExprI32Sub,
|
|
kExprI32Mul])
|
|
.exportFunc();
|
|
builder.addFunction("mul", makeSig([kWasmI32, kWasmI32], [kWasmI32]))
|
|
.addBody([kExprLocalGet, 0, kExprLocalGet, 1, kExprI32Mul])
|
|
.exportFunc();
|
|
|
|
let wasm = builder.instantiate().exports;
|
|
assertEquals(3 + (4 * 5), wasm.madd(3, 4, 5));
|
|
assertEquals((3 * 4) + 5, wasm.madd2(3, 4, 5));
|
|
assertEquals(5 + -7, wasm.addConstant(5));
|
|
assertEquals(5 + -7, wasm.add(5, -7));
|
|
|
|
assertEquals(3 - (4 * 5), wasm.msub(3, 4, 5));
|
|
assertEquals(5 - -7, wasm.subConstant(5));
|
|
assertEquals(5 - -7, wasm.sub(5, -7));
|
|
|
|
assertEquals(42 * 9, wasm.mulConstant(42));
|
|
assertEquals(-42 * 4, wasm.mulNegate(42, 4));
|
|
assertEquals(42 * -4, wasm.mulNegate2(42, 4));
|
|
assertEquals(5 * -7, wasm.mul(5, -7));
|
|
})();
|
|
|
|
(function ArithmeticInt64() {
|
|
print(arguments.callee.name);
|
|
let builder = new WasmModuleBuilder();
|
|
let maddSig = makeSig([kWasmI64, kWasmI64, kWasmI64], [kWasmI64]);
|
|
builder.addFunction("madd", maddSig)
|
|
.addBody([
|
|
// local[0] + (local[1] * local[2])
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 1,
|
|
kExprLocalGet, 2,
|
|
kExprI64Mul,
|
|
kExprI64Add
|
|
])
|
|
.exportFunc();
|
|
builder.addFunction("madd2", maddSig)
|
|
.addBody([
|
|
// (local[0] * local[1]) + local[2]
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 1,
|
|
kExprI64Mul,
|
|
kExprLocalGet, 2,
|
|
kExprI64Add
|
|
])
|
|
.exportFunc();
|
|
builder.addFunction("addConstant", makeSig([kWasmI64], [kWasmI64]))
|
|
.addBody([kExprLocalGet, 0, ...wasmI64Const(-7), kExprI64Add])
|
|
.exportFunc();
|
|
builder.addFunction("add", makeSig([kWasmI64, kWasmI64], [kWasmI64]))
|
|
.addBody([kExprLocalGet, 0, kExprLocalGet, 1, kExprI64Add])
|
|
.exportFunc();
|
|
builder.addFunction("msub", maddSig)
|
|
.addBody([
|
|
// local[0] - (local[1] * local[2])
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 1,
|
|
kExprLocalGet, 2,
|
|
kExprI64Mul,
|
|
kExprI64Sub
|
|
])
|
|
.exportFunc();
|
|
builder.addFunction("subConstant", makeSig([kWasmI64], [kWasmI64]))
|
|
.addBody([kExprLocalGet, 0, ...wasmI64Const(-7), kExprI64Sub])
|
|
.exportFunc();
|
|
builder.addFunction("sub", makeSig([kWasmI64, kWasmI64], [kWasmI64]))
|
|
.addBody([kExprLocalGet, 0, kExprLocalGet, 1, kExprI64Sub])
|
|
.exportFunc();
|
|
builder.addFunction("mulConstant", makeSig([kWasmI64], [kWasmI64]))
|
|
// Can be lowered to local[0] + local[0] << 3.
|
|
.addBody([kExprLocalGet, 0, ...wasmI64Const(9), kExprI64Mul])
|
|
.exportFunc();
|
|
builder.addFunction("mulNegate", makeSig([kWasmI64, kWasmI64], [kWasmI64]))
|
|
.addBody([
|
|
// (0 - local[0]) * local[1]
|
|
kExprI64Const, 0,
|
|
kExprLocalGet, 0,
|
|
kExprI64Sub,
|
|
kExprLocalGet, 1,
|
|
kExprI64Mul])
|
|
.exportFunc();
|
|
builder.addFunction("mulNegate2", makeSig([kWasmI64, kWasmI64], [kWasmI64]))
|
|
.addBody([
|
|
// local[0] * (0 - local[1])
|
|
kExprLocalGet, 0,
|
|
kExprI64Const, 0,
|
|
kExprLocalGet, 1,
|
|
kExprI64Sub,
|
|
kExprI64Mul])
|
|
.exportFunc();
|
|
builder.addFunction("mul", makeSig([kWasmI64, kWasmI64], [kWasmI64]))
|
|
.addBody([kExprLocalGet, 0, kExprLocalGet, 1, kExprI64Mul])
|
|
.exportFunc();
|
|
|
|
let wasm = builder.instantiate().exports;
|
|
assertEquals(3n + (4n * 5n), wasm.madd(3n, 4n, 5n));
|
|
assertEquals((3n * 4n) + 5n, wasm.madd2(3n, 4n, 5n));
|
|
assertEquals(5n + -7n, wasm.addConstant(5n));
|
|
assertEquals(5n + -7n, wasm.add(5n, -7n));
|
|
|
|
assertEquals(3n - (4n * 5n), wasm.msub(3n, 4n, 5n));
|
|
assertEquals(5n - -7n, wasm.subConstant(5n));
|
|
assertEquals(5n - -7n, wasm.sub(5n, -7n));
|
|
|
|
assertEquals(42n * 9n, wasm.mulConstant(42n));
|
|
assertEquals(-42n * 4n, wasm.mulNegate(42n, 4n));
|
|
assertEquals(42n * -4n, wasm.mulNegate2(42n, 4n));
|
|
assertEquals(5n * -7n, wasm.mul(5n, -7n));
|
|
})();
|
|
|
|
(function Loads() {
|
|
print(arguments.callee.name);
|
|
let builder = new WasmModuleBuilder();
|
|
|
|
builder.addFunction("isString", makeSig([kWasmExternRef], [kWasmI32]))
|
|
.addBody([
|
|
kExprLocalGet, 0,
|
|
kGCPrefix, kExprAnyConvertExtern,
|
|
kGCPrefix, kExprRefTest, kStringRefCode,
|
|
])
|
|
.exportFunc();
|
|
|
|
// Loops emit stack checks (which includes loading from the root register).
|
|
let loop_sig = builder.addType(kSig_i_i);
|
|
// Works for positive numbers only.
|
|
builder.addFunction("factorial", kSig_i_i)
|
|
.addBody([
|
|
kExprI32Const, 1,
|
|
kExprLoop, loop_sig,
|
|
kExprLocalGet, 0,
|
|
kExprI32Mul,
|
|
kExprLocalGet, 0,
|
|
kExprI32Const, 1,
|
|
kExprI32Sub,
|
|
kExprLocalTee, 0,
|
|
kExprI32Const, 1,
|
|
kExprI32GtS,
|
|
kExprBrIf, 0,
|
|
kExprEnd])
|
|
.exportFunc();
|
|
|
|
let wasm = builder.instantiate().exports;
|
|
assertEquals(0, wasm.isString({}));
|
|
assertEquals(0, wasm.isString(1));
|
|
assertEquals(0, wasm.isString(1.5));
|
|
assertEquals(0, wasm.isString(-0.0));
|
|
assertEquals(0, wasm.isString(null));
|
|
assertEquals(1, wasm.isString("test"));
|
|
|
|
assertEquals(1, wasm.factorial(1));
|
|
assertEquals(24, wasm.factorial(4));
|
|
assertEquals(720, wasm.factorial(6));
|
|
})();
|
|
|
|
(function LoadsAndStoresArrays() {
|
|
print(arguments.callee.name);
|
|
let builder = new WasmModuleBuilder();
|
|
let arrayI32 = builder.addArray(kWasmI32, true);
|
|
let arrayI8 = builder.addArray(kWasmI8, true);
|
|
|
|
let tests = [
|
|
["I32", arrayI32, kExprArrayGet],
|
|
["I8", arrayI8, kExprArrayGetS],
|
|
];
|
|
|
|
for (let [name, arrayIndex, arrayGetOp] of tests) {
|
|
let createSig = makeSig([kWasmI32], [kWasmAnyRef]);
|
|
let setSig = makeSig([kWasmAnyRef, kWasmI32, kWasmI32], []);
|
|
let getSig = makeSig([kWasmAnyRef, kWasmI32], [kWasmI32]);
|
|
|
|
builder.addFunction(`createArray${name}`, createSig)
|
|
.addBody([
|
|
kExprLocalGet, 0,
|
|
kGCPrefix, kExprArrayNewDefault, arrayIndex,
|
|
])
|
|
.exportFunc();
|
|
|
|
builder.addFunction(`set${name}`, setSig)
|
|
.addBody([
|
|
kExprLocalGet, 0,
|
|
kGCPrefix, kExprRefCastNull, arrayIndex,
|
|
kExprLocalGet, 1,
|
|
kExprLocalGet, 2,
|
|
kGCPrefix, kExprArraySet, arrayIndex,
|
|
])
|
|
.exportFunc();
|
|
|
|
builder.addFunction(`get${name}`, getSig)
|
|
.addBody([
|
|
kExprLocalGet, 0,
|
|
kGCPrefix, kExprRefCastNull, arrayIndex,
|
|
kExprLocalGet, 1,
|
|
kGCPrefix, arrayGetOp, arrayIndex,
|
|
])
|
|
.exportFunc();
|
|
}
|
|
|
|
let wasm = builder.instantiate().exports;
|
|
|
|
for (let [name, arrayIndex, arrayGetOp] of tests) {
|
|
print(`- test array${name}`);
|
|
let size = 20;
|
|
let array = wasm[`createArray${name}`](size);
|
|
for (let i = 0; i < size; ++i) {
|
|
wasm[`set${name}`](array, i, i * 2);
|
|
}
|
|
for (let i = 0; i < size; ++i) {
|
|
assertEquals(i * 2, wasm[`get${name}`](array, i));
|
|
}
|
|
assertTraps(kTrapNullDereference, () => wasm[`get${name}`](null, 1, 1));
|
|
assertTraps(kTrapNullDereference, () => wasm[`set${name}`](null, 1));
|
|
}
|
|
})();
|
|
|
|
(function LoadsAndStoresStruct() {
|
|
print(arguments.callee.name);
|
|
let builder = new WasmModuleBuilder();
|
|
let struct = builder.addStruct([
|
|
makeField(kWasmI8, false),
|
|
makeField(kWasmI32, false),
|
|
makeField(kWasmI64, false),
|
|
makeField(kWasmAnyRef, false)
|
|
]);
|
|
|
|
builder.addFunction(`createStruct`,
|
|
makeSig([kWasmI32, kWasmI32, kWasmI64, kWasmAnyRef], [kWasmAnyRef]))
|
|
.addBody([
|
|
kExprLocalGet, 0, kExprLocalGet, 1, kExprLocalGet, 2, kExprLocalGet, 3,
|
|
kGCPrefix, kExprStructNew, struct,
|
|
])
|
|
.exportFunc();
|
|
|
|
|
|
builder.addFunction(`get`,
|
|
makeSig([kWasmAnyRef], [kWasmI32, kWasmI32, kWasmI64, kWasmAnyRef]))
|
|
.addLocals(wasmRefNullType(struct), 1 )
|
|
.addBody([
|
|
kExprLocalGet, 0,
|
|
kGCPrefix, kExprRefCastNull, struct,
|
|
kExprLocalTee, 1,
|
|
kGCPrefix, kExprStructGetS, struct, 0,
|
|
kExprLocalGet, 1,
|
|
kGCPrefix, kExprStructGet, struct, 1,
|
|
kExprLocalGet, 1,
|
|
kGCPrefix, kExprStructGet, struct, 2,
|
|
kExprLocalGet, 1,
|
|
kGCPrefix, kExprStructGet, struct, 3,
|
|
])
|
|
.exportFunc();
|
|
|
|
let wasm = builder.instantiate().exports;
|
|
let myStruct = wasm.createStruct(1, 2, 3n, null);
|
|
assertEquals([1, 2, 3n, null], wasm.get(myStruct));
|
|
assertTraps(kTrapNullDereference, () => wasm.get(null));
|
|
|
|
})();
|
|
|
|
(function I64BitAnd() {
|
|
print(arguments.callee.name);
|
|
let builder = new WasmModuleBuilder();
|
|
builder.addFunction("and", makeSig([kWasmI64, kWasmI64], [kWasmI64]))
|
|
.addBody([
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 1,
|
|
kExprI64And,
|
|
])
|
|
.exportFunc();
|
|
|
|
builder.addFunction("maskAfterShift", makeSig([kWasmI64], [kWasmI64]))
|
|
.addBody([
|
|
// return (local[0] >> 3) & 7;
|
|
kExprLocalGet, 0,
|
|
kExprI64Const, 3,
|
|
kExprI64ShrU,
|
|
kExprI64Const, 7,
|
|
kExprI64And,
|
|
])
|
|
.exportFunc();
|
|
|
|
builder.addFunction("shiftAfterMask", makeSig([kWasmI64], [kWasmI64]))
|
|
.addBody([
|
|
// return (local[0] & 56) >> 3;
|
|
kExprLocalGet, 0,
|
|
kExprI64Const, 56,
|
|
kExprI64And,
|
|
kExprI64Const, 3,
|
|
kExprI64ShrU,
|
|
])
|
|
.exportFunc();
|
|
|
|
let wasm = builder.instantiate().exports;
|
|
assertEquals(
|
|
0b10101010_00000000_01010101_00000000n, wasm.and(
|
|
0b10101010_00000000_11111111_01010101n,
|
|
0b11111111_11111111_01010101_00000000n));
|
|
assertEquals(0b101n, wasm.maskAfterShift(0b1010101010101010n));
|
|
assertEquals(0b101n, wasm.shiftAfterMask(0b1010101010101010n));
|
|
})();
|
|
|
|
(function SignedExtendRightShiftValue() {
|
|
print(arguments.callee.name);
|
|
let builder = new WasmModuleBuilder();
|
|
builder.addFunction("shrsExtend", makeSig([kWasmI32], [kWasmI64]))
|
|
.addBody([
|
|
kExprLocalGet, 0,
|
|
kExprI32Const, 11,
|
|
kExprI32ShrS,
|
|
kExprI64SConvertI32,
|
|
])
|
|
.exportFunc();
|
|
|
|
let wasm = builder.instantiate().exports;
|
|
assertEquals(42n, wasm.shrsExtend(42 << 11));
|
|
assertEquals(-41n, wasm.shrsExtend(-41 << 11));
|
|
})();
|