nodejs/deps/v8/test/mjsunit/wasm/turboshaft/instruction-selection.js
Michaël Zasso 918fe04351
deps: update V8 to 13.6.233.8
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>
2025-05-02 15:06:53 +02:00

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));
})();