Upload Kmake

This commit is contained in:
Gorochu
2026-05-26 23:36:42 -07:00
parent ba051b2f74
commit 555ec72358
41615 changed files with 13344630 additions and 1 deletions

View File

@ -0,0 +1,53 @@
// 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
d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
(function TestArrayNewS128Unreachable() {
print(arguments.callee.name);
const builder = new WasmModuleBuilder();
let array = builder.addArray(kWasmS128, true);
let empty_sig = builder.addType(makeSig([], []));
builder.addFunction(undefined, empty_sig)
.addBody([
// The empty try will never jump to the catch making the catch block
// unreachable already during graph construction time.
kExprTry, kWasmVoid,
kExprCatchAll,
kExprI32Const, 0,
kSimdPrefix, kExprI8x16Splat,
kExprI32Const, 42,
kGCPrefix, kExprArrayNew, array, // array.new
kExprDrop,
kExprEnd,
]);
builder.addExport('main', 0);
const instance = builder.instantiate();
instance.exports.main();
})();
(function TestArrayNewUnreachableNoDefault() {
print(arguments.callee.name);
const builder = new WasmModuleBuilder();
let empty_sig = builder.addType(makeSig([], []));
let array = builder.addArray(wasmRefType(empty_sig), true);
let empty_func = builder.addFunction(undefined, empty_sig)
.addBody([]).exportFunc();
builder.addFunction("main", empty_sig)
.addBody([
// The empty try will never jump to the catch making the catch block
// unreachable already during graph construction time.
kExprTry, kWasmVoid,
kExprCatchAll,
kExprRefFunc, empty_func.index,
kExprI32Const, 42,
kGCPrefix, kExprArrayNew, array, // array.new
kExprDrop,
kExprEnd,
]).exportFunc();
const instance = builder.instantiate();
instance.exports.main();
})();

View File

@ -0,0 +1,254 @@
// 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: --no-liftoff --no-wasm-lazy-compilation
// Flags: --enable-testing-opcode-in-wasm
d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
(function I32Arithmetic() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("i32_arithmetic", kSig_i_v)
.addBody([kExprI32Const, 32, kExprI32Const, 10, kExprI32Add])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(42, wasm.i32_arithmetic());
})();
(function I32Locals() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("i32_locals", kSig_i_ii)
.addLocals(kWasmI32, 1)
.addBody([
// i = i + 1;
kExprLocalGet, 0, kExprI32Const, 1, kExprI32Add, kExprLocalSet, 0,
// k = j + 2; temp1 = k;
kExprLocalGet, 1, kExprI32Const, 2, kExprI32Add, kExprLocalTee, 2,
// temp2 = temp1 + i;
kExprLocalGet, 0, kExprI32Add,
// return temp2 * k;
kExprLocalGet, 2, kExprI32Mul])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals((22 + 11) * 22, wasm.i32_locals(10, 20));
})();
(function IfThenElse() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let if_sig_32 = builder.addType(kSig_ii_ii);
builder.addFunction("if_then_else_32", kSig_i_iii)
.addBody([
// f(x, y, z) {
// [temp1, temp2] = z ? [x + y, x] : [x - y, y];
// return temp1 * temp2;
// }
kExprLocalGet, 0, kExprLocalGet, 1,
kExprLocalGet, 2,
kExprIf, if_sig_32,
kExprI32Add, kExprLocalGet, 0,
kExprElse,
kExprI32Sub, kExprLocalGet, 1,
kExprEnd,
kExprI32Mul])
.exportFunc();
let if_sig_64 = builder.addType(
makeSig([kWasmI64, kWasmI64], [kWasmI64, kWasmI64]));
builder.addFunction(
"if_then_else_64",
makeSig([kWasmI64, kWasmI64, kWasmI32], [kWasmI64]))
.addBody([
// f(x, y, z) {
// [temp1, temp2] = z ? [x + y, x] : [x - y, y];
// return temp1 * temp2;
// }
kExprLocalGet, 0, kExprLocalGet, 1,
kExprLocalGet, 2,
kExprIf, if_sig_64,
kExprI64Add, kExprLocalGet, 0,
kExprElse,
kExprI64Sub, kExprLocalGet, 1,
kExprEnd,
kExprI64Mul])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(-200, wasm.if_then_else_32(10, 20, 0));
assertEquals(300, wasm.if_then_else_32(10, 20, 1));
assertEquals(-200n, wasm.if_then_else_64(10n, 20n, 0));
assertEquals(300n, wasm.if_then_else_64(10n, 20n, 1));
})();
(function OneArmedIf() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("one_armed_if", kSig_i_ii)
.addBody([
// f(x, y) {
// if (y) x = x + 1;
// return x;
// }
kExprLocalGet, 1,
kExprIf, kWasmVoid,
kExprLocalGet, 0, kExprI32Const, 1, kExprI32Add, kExprLocalSet, 0,
kExprEnd,
kExprLocalGet, 0])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(10, wasm.one_armed_if(10, 0));
assertEquals(11, wasm.one_armed_if(10, -1));
})();
(function BlockAndBr() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let block_sig = builder.addType(kSig_ii_ii);
builder.addFunction("block_and_br", kSig_i_iii)
.addBody([
// f(x, y, z) {
// temp1 = x + y;
// temp2 = x;
// if (z) goto block;
// temp2 = temp2 * y;
// block:
// return temp1 + temp2;
// }
kExprLocalGet, 0, kExprLocalGet, 1,
kExprBlock, block_sig,
kExprI32Add,
kExprLocalGet, 0,
kExprLocalGet, 2,
kExprBrIf, 0,
kExprLocalGet, 1,
kExprI32Mul,
kExprEnd,
kExprI32Add])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals((10 + 20) + (10 * 20), wasm.block_and_br(10, 20, 0));
assertEquals((10 + 20) + 10, wasm.block_and_br(10, 20, 1));
})();
(function Loop() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
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, kExprLocalSet, 0,
kExprLocalGet, 0,
kExprI32Const, 1,
kExprI32GtS,
kExprBrIf, 0,
kExprEnd])
.exportFunc();
builder.addFunction("factorial_with_br_if_return", kSig_i_i)
.addLocals(kWasmI32, 1)
.addBody([
kExprI32Const, 1, kExprLocalSet, 1,
kExprLoop, kWasmVoid,
kExprLocalGet, 1,
kExprLocalGet, 0, kExprI32Const, 1, kExprI32LtS,
kExprBrIf, 1,
kExprLocalGet, 0, kExprI32Mul, kExprLocalSet, 1,
kExprLocalGet, 0, kExprI32Const, 1, kExprI32Sub, kExprLocalSet, 0,
kExprBr, 0,
kExprEnd,
kExprUnreachable])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(1, wasm.factorial(1));
assertEquals(24, wasm.factorial(4));
assertEquals(720, wasm.factorial(6));
assertEquals(1, wasm.factorial_with_br_if_return(0));
assertEquals(1, wasm.factorial_with_br_if_return(1));
assertEquals(24, wasm.factorial_with_br_if_return(4));
assertEquals(720, wasm.factorial_with_br_if_return(6));
})();
(function Multireturn() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("swap", kSig_ii_ii)
.addBody([kExprI32Const, 42, // garbage
kExprLocalGet, 1, kExprLocalGet, 0, kExprReturn])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals([1, 0], wasm.swap(0, 1));
})();
(function BrTable() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let block_sig = builder.addType(kSig_i_i);
builder.addFunction("br_table", kSig_i_i)
.addBody([
kExprLocalGet, 0,
kExprBlock, block_sig,
kExprBlock, block_sig,
kExprLocalGet, 0,
kExprBrTable, 2, 2, 1, 0,
kExprEnd,
kExprI32Const, 1, kExprI32Add, kExprReturn,
kExprEnd,
kExprI32Const, 2, kExprI32Sub])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(0, wasm.br_table(0));
assertEquals(-1, wasm.br_table(1));
assertEquals(23, wasm.br_table(22));
})();
(function TestSubZeroFromTruncatedOptimization() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("subZeroFromTruncated", makeSig([kWasmI64], [kWasmI32]))
.exportFunc()
.addBody([
// i32.sub(i32.wrap_i64(local.get 0), 0)
// should be optimized to i32.wrap_i64(local.get 0)
kExprLocalGet, 0,
kExprI32ConvertI64,
kExprI32Const, 0,
kExprI32Sub,
]);
let instance = builder.instantiate();
assertEquals(123, instance.exports.subZeroFromTruncated(123n));
})();

View File

@ -0,0 +1,100 @@
// Copyright 2024 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: --no-liftoff --no-wasm-lazy-compilation
// Flags: --enable-testing-opcode-in-wasm
d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
(function BrTablePrimaryIsDefault() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let block_sig = builder.addType(kSig_i_i);
builder.addFunction("br_table", kSig_i_i)
.addBody([
kExprLocalGet, 0,
kExprBlock, block_sig,
kExprBlock, block_sig,
kExprLocalGet, 0,
kExprBrTable, 4, 2, 0, 1, 0, 1, 0,
kExprEnd,
kExprI32Const, 1, kExprI32Add, kExprReturn,
kExprEnd,
kExprI32Const, 2, kExprI32Sub])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(0, wasm.br_table(0));
assertEquals(2, wasm.br_table(1));
assertEquals(0, wasm.br_table(2));
assertEquals(4, wasm.br_table(3));
assertEquals(2, wasm.br_table(4));
assertEquals(3, wasm.br_table(5));
assertEquals(8, wasm.br_table(10));
})();
(function BrTablePrimaryIsNotDefault() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let block_sig = builder.addType(kSig_i_i);
builder.addFunction("br_table", kSig_i_i)
.addBody([
kExprLocalGet, 0,
kExprBlock, block_sig,
kExprBlock, block_sig,
kExprLocalGet, 0,
kExprBrTable, 5, 2, 1, 1, 1, 1, 0,
kExprEnd,
kExprI32Const, 1, kExprI32Add, kExprReturn,
kExprEnd,
kExprI32Const, 2, kExprI32Sub])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(0, wasm.br_table(0));
assertEquals(-1, wasm.br_table(1));
assertEquals(0, wasm.br_table(2));
assertEquals(1, wasm.br_table(3));
assertEquals(2, wasm.br_table(4));
assertEquals(6, wasm.br_table(5));
assertEquals(7, wasm.br_table(6));
assertEquals(11, wasm.br_table(10));
})();
(function BrTablePrimaryIsNotDefaultTwoOrOthers() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let block_sig = builder.addType(kSig_i_i);
builder.addFunction("br_table", kSig_i_i)
.addBody([
kExprLocalGet, 0,
kExprBlock, block_sig,
kExprBlock, block_sig,
kExprLocalGet, 0,
kExprBrTable, 6, 2, 1, 0, 0, 0, 2, 1,
kExprEnd,
kExprI32Const, 1, kExprI32Add, kExprReturn,
kExprEnd,
kExprI32Const, 2, kExprI32Sub])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(0, wasm.br_table(0));
assertEquals(-1, wasm.br_table(1));
assertEquals(3, wasm.br_table(2));
assertEquals(4, wasm.br_table(3));
assertEquals(5, wasm.br_table(4));
assertEquals(5, wasm.br_table(5));
assertEquals(4, wasm.br_table(6));
assertEquals(8, wasm.br_table(10));
})();

View File

@ -0,0 +1,401 @@
// 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));
})();

View File

@ -0,0 +1,693 @@
// 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: --no-liftoff --no-wasm-lazy-compilation
// Flags: --enable-testing-opcode-in-wasm
d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
// Make sure turboshaft bails out graciously for non-implemented features.
(function I64Identity() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("id", makeSig([kWasmI64], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(0n, wasm.id(0n));
assertEquals(1n, wasm.id(1n));
assertEquals(-1n, wasm.id(-1n));
assertEquals(0x123456789ABCn, wasm.id(0x123456789ABCn));
assertEquals(-0x123456789ABCn, wasm.id(-0x123456789ABCn));
})();
(function I64Constants() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("main", makeSig([], [kWasmI64, kWasmI64, kWasmI64]))
.addBody([
...wasmI64Const(0),
...wasmI64Const(-12345),
...wasmI64Const(0x123456789ABCDEFn),
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals([0n, -12345n, 0x123456789ABCDEFn], wasm.main());
})();
(function I64Multiplication() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("mul", makeSig([kWasmI64, kWasmI64], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprI64Mul,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(0n, wasm.mul(0n, 5n));
assertEquals(0n, wasm.mul(5n, 0n));
assertEquals(5n, wasm.mul(1n, 5n));
assertEquals(-5n, wasm.mul(5n, -1n));
assertEquals(35n, wasm.mul(-5n, -7n));
assertEquals(0xfffffffffn * 0xfn, wasm.mul(0xfffffffffn, 0xfn));
})();
(function I64Addition() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("add", makeSig([kWasmI64, kWasmI64], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprI64Add,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(3n, wasm.add(1n, 2n));
assertEquals(0n, wasm.add(100n, -100n));
assertEquals(0x12345678n + 0xABCDEF1234n,
wasm.add(0x12345678n, 0xABCDEF1234n));
})();
(function I64Subtraction() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("sub", makeSig([kWasmI64, kWasmI64], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprI64Sub,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(-1n, wasm.sub(1n, 2n));
assertEquals(200n, wasm.sub(100n, -100n));
assertEquals(0x12345678n - 0xABCDEF1234n,
wasm.sub(0x12345678n, 0xABCDEF1234n));
assertEquals(0n, wasm.sub(0x123456789ABCDEFn, 0x123456789ABCDEFn));
})();
(function I64BitAnd() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("and", makeSig([kWasmI64, kWasmI64], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprI64And,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(
0b10101010_00000000_11111111_01010101n, wasm.and(
0b10101010_00000000_11111111_01010101n,
0b10101010_00000000_11111111_01010101n));
assertEquals(
0b10101010_00000000_01010101_00000000n, wasm.and(
0b10101010_00000000_11111111_01010101n,
0b11111111_11111111_01010101_00000000n));
})();
(function I64BitOr() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("or", makeSig([kWasmI64, kWasmI64], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprI64Ior,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(
0b10101010_00000000_11111111_01010101n, wasm.or(
0b10101010_00000000_11111111_01010101n,
0b10101010_00000000_11111111_01010101n));
assertEquals(
0b11111111_11111111_11111111_01010101n, wasm.or(
0b10101010_00000000_11111111_01010101n,
0b11111111_11111111_01010101_00000000n));
})();
(function I64BitXor() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("xor", makeSig([kWasmI64, kWasmI64], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprI64Xor,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(
0b10101010_00000000_11111111_01010101n, wasm.xor(
0b10101010_00000000_11111111_01010101n,
0b00000000_00000000_00000000_00000000n));
assertEquals(
0b11111111_11111111_11111111_01010101n, wasm.xor(
0b10101010_00000000_11111111_01010101n,
0b01010101_11111111_00000000_00000000n));
})();
(function I64BitShl() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("shl", makeSig([kWasmI64, kWasmI64], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprI64Shl,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(0x123456789n, wasm.shl(0x123456789n, 0n));
assertEquals(0x1234567890000n, wasm.shl(0x123456789n, 16n));
assertEquals(0x3456789000000000n, wasm.shl(0x123456789n, 36n));
assertEquals(31n << 56n, wasm.shl(31n, -8n));
assertEquals(31n << 1n, wasm.shl(31n, 65n));
})();
(function I64BitShrs() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("shrs", makeSig([kWasmI64, kWasmI64], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprI64ShrS,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(0x123456789n, wasm.shrs(0x123456789n, 0n));
assertEquals(0x12345n, wasm.shrs(0x123456789n, 16n));
assertEquals(-0x2n, wasm.shrs(-0x123456789n, 32n));
assertEquals(-0x1n, wasm.shrs(-0x123456789n, 33n));
assertEquals(-0x1n, wasm.shrs(-0x123456789n, 40n));
assertEquals(-0x123456789n, wasm.shrs(-0x123456789n, 64n));
assertEquals(31n >> 56n, wasm.shrs(31n, -8n));
assertEquals(31n >> 1n, wasm.shrs(31n, 65n));
})();
(function I64BitShrU() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("shru", makeSig([kWasmI64, kWasmI64], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprI64ShrU,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(0x123456789n, wasm.shru(0x123456789n, 0n));
assertEquals(0x12345n, wasm.shru(0x123456789n, 16n));
assertEquals(0xFFFFFFFEn, wasm.shru(-0x123456789n, 32n));
assertEquals(0xFn, wasm.shru(-0x123456789n, 60n));
assertEquals(-0x123456789n, wasm.shru(-0x123456789n, 64n));
assertEquals(31n >> 56n, wasm.shru(31n, -8n));
assertEquals(31n >> 1n, wasm.shru(31n, 65n));
})();
(function I64BitRol() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("rol", makeSig([kWasmI64, kWasmI64], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprI64Rol,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(0x123456789n, wasm.rol(0x123456789n, 0n));
assertEquals(0x1234567890000n, wasm.rol(0x123456789n, 16n));
assertEquals(0x3456789000000012n, wasm.rol(0x123456789n, 36n));
assertEquals(0x34567890ABCDEF12n, wasm.rol(0xABCDEF1234567890n, 32n));
assertEquals(0x4D5E6F78091A2B3Cn, wasm.rol(0x123456789ABCDEF0n, 31n));
assertEquals(0x3579BDE02468ACF1n, wasm.rol(0x123456789ABCDEF0n, 33n));
assertEquals(31n << 56n, wasm.rol(31n, -8n));
assertEquals(31n << 1n, wasm.rol(31n, 65n));
})();
(function I64BitRolStaticRhs() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let tests = [
// [lhs, rhs, expected]
[0x123456789n, 0n, 0x123456789n],
[0x12345678_11111111n, 32n, 0x11111111_12345678n],
[0x1_23456789n, 16n, 0x12345_67890000n],
[0x1_23456789n, 36n, 0x34567890_00000012n],
[31n, -8, 31n << 56n],
[31n, 65n, 31n << 1n],
];
for (const [lhs, rhs, expected] of tests) {
builder.addFunction(`rol${rhs}`, makeSig([kWasmI64], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
...wasmI64Const(rhs),
kExprI64Rol,
])
.exportFunc();
}
let wasm = builder.instantiate().exports;
for (const [lhs, rhs, expected] of tests) {
print(`test i64.rol(${lhs}, ${rhs}) == ${expected}`);
assertEquals(expected, wasm[`rol${rhs}`](lhs));
}
})();
(function I64BitRor() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("ror", makeSig([kWasmI64, kWasmI64], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprI64Ror,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(0x123456789n, wasm.ror(0x123456789n, 0n));
assertEquals(0x6789000000012345n, wasm.ror(0x123456789n, 16n));
assertEquals(0x1234567890000000n, wasm.ror(0x123456789n, 36n));
assertEquals(0x34567890ABCDEF12n, wasm.ror(0xABCDEF1234567890n, 32n));
assertEquals(0x3579BDE02468ACF1n, wasm.ror(0x123456789ABCDEF0n, 31n));
assertEquals(0x4D5E6F78091A2B3Cn, wasm.ror(0x123456789ABCDEF0n, 33n));
assertEquals(31n << 8n, wasm.ror(31n, -8n));
assertEquals(31n << 1n, wasm.ror(31n, 127n));
})();
(function I64Equals() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("eq", makeSig([kWasmI64, kWasmI64], [kWasmI32]))
.addBody([
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprI64Eq,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(1, wasm.eq(0n, 0n));
assertEquals(1, wasm.eq(-123n, -123n));
assertEquals(0, wasm.eq(-123n, 123n));
assertEquals(0, wasm.eq(0x12345678_87654321n, 0x87654321_12345678n));
assertEquals(0, wasm.eq(0x12345678_87654321n, 0x1234567A_87654321n));
assertEquals(0, wasm.eq(0x12345678_87654321n, 0x12345678_8765432An));
})();
(function I64NotEquals() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("ne", makeSig([kWasmI64, kWasmI64], [kWasmI32]))
.addBody([
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprI64Ne,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(0, wasm.ne(0n, 0n));
assertEquals(0, wasm.ne(-123n, -123n));
assertEquals(1, wasm.ne(-123n, 123n));
assertEquals(1, wasm.ne(0x12345678_87654321n, 0x87654321_12345678n));
assertEquals(1, wasm.ne(0x12345678_87654321n, 0x1234567A_87654321n));
assertEquals(1, wasm.ne(0x12345678_87654321n, 0x12345678_8765432An));
})();
(function I64LessThanSigned() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("lts", makeSig([kWasmI64, kWasmI64], [kWasmI32]))
.addBody([
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprI64LtS,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(0, wasm.lts(0n, 0n));
assertEquals(1, wasm.lts(-123n, 123n));
assertEquals(0, wasm.lts(123n, -123n));
assertEquals(1, wasm.lts(0x12345678_12488421n, 0x12488421_12345678n));
assertEquals(0, wasm.lts(0x12488421_12345678n, 0x12345678_12488421n));
assertEquals(0, wasm.lts(0x12345678_87654321n, 0x12345678_87654320n));
assertEquals(1, wasm.lts(0x12345678_87654321n, 0x12345678_87654322n));
})();
(function I64LessThanOrEqualSigned() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("les", makeSig([kWasmI64, kWasmI64], [kWasmI32]))
.addBody([
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprI64LeS,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(1, wasm.les(0n, 0n));
assertEquals(1, wasm.les(-123n, 123n));
assertEquals(0, wasm.les(123n, -123n));
assertEquals(1, wasm.les(0x12345678_12488421n, 0x12488421_12345678n));
assertEquals(0, wasm.les(0x12488421_12345678n, 0x12345678_12488421n));
assertEquals(0, wasm.les(0x12345678_87654321n, 0x12345678_87654320n));
assertEquals(1, wasm.les(0x12345678_87654321n, 0x12345678_87654322n));
})();
(function I64LessThanUnsigned() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("ltu", makeSig([kWasmI64, kWasmI64], [kWasmI32]))
.addBody([
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprI64LtU,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(0, wasm.ltu(0n, 0n));
assertEquals(0, wasm.ltu(-123n, 123n));
assertEquals(1, wasm.ltu(123n, -123n));
assertEquals(1, wasm.ltu(0x12345678_12488421n, 0x12488421_12345678n));
assertEquals(0, wasm.ltu(0x12488421_12345678n, 0x12345678_12488421n));
assertEquals(0, wasm.ltu(0x12345678_87654321n, 0x12345678_87654320n));
assertEquals(1, wasm.ltu(0x12345678_87654321n, 0x12345678_87654322n));
})();
(function I64LessThanOrEqualUnsigned() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("leu", makeSig([kWasmI64, kWasmI64], [kWasmI32]))
.addBody([
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprI64LeU,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(1, wasm.leu(0n, 0n));
assertEquals(0, wasm.leu(-123n, 123n));
assertEquals(1, wasm.leu(123n, -123n));
assertEquals(1, wasm.leu(0x12345678_12488421n, 0x12488421_12345678n));
assertEquals(0, wasm.leu(0x12488421_12345678n, 0x12345678_12488421n));
assertEquals(0, wasm.leu(0x12345678_87654321n, 0x12345678_87654320n));
assertEquals(1, wasm.leu(0x12345678_87654321n, 0x12345678_87654322n));
})();
(function I64EqualsZero() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("eqz", makeSig([kWasmI64], [kWasmI32]))
.addBody([
kExprLocalGet, 0,
kExprI64Eqz,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(1, wasm.eqz(0n));
assertEquals(0, wasm.eqz(1n));
assertEquals(0, wasm.eqz(-1n));
assertEquals(0, wasm.eqz(0x100_00000000n));
})();
(function I64Call() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let callee = builder.addFunction("callee",
makeSig([kWasmI64], [kWasmI64]))
.addBody([kExprLocalGet, 0])
.exportFunc();
builder.addFunction("call", makeSig([kWasmI64], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
kExprCallFunction, callee.index,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(123n, wasm.callee(123n));
assertEquals(123n, wasm.call(123n));
})();
(function I64CallMultiReturn() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let callee = builder.addFunction("callee",
makeSig([kWasmI32, kWasmI64, kWasmI64, kWasmI32],
[kWasmI32, kWasmI64, kWasmI64, kWasmI32]))
.addBody([
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprLocalGet, 2,
kExprLocalGet, 3,
])
.exportFunc();
builder.addFunction("call",
makeSig([kWasmI64, kWasmI64], [kWasmI32, kWasmI64, kWasmI64, kWasmI32]))
.addBody([
kExprI32Const, 11,
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprI32Const, 22,
kExprCallFunction, callee.index,
])
.exportFunc();
builder.addFunction("tailCall",
makeSig([kWasmI64, kWasmI64], [kWasmI32, kWasmI64, kWasmI64, kWasmI32]))
.addBody([
kExprI32Const, 11,
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprI32Const, 22,
kExprReturnCall, callee.index,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals([11, 123n, -1n, 22], wasm.callee(11, 123n, -1n, 22));
assertEquals([11, 123n, -1n, 22], wasm.call(123n, -1n));
assertEquals([11, 123n, -1n, 22], wasm.tailCall(123n, -1n));
assertEquals([11, -123n, 123n, 22], wasm.callee(11, -123n, 123n, 22));
assertEquals([11, -123n, 123n, 22], wasm.call(-123n, 123n));
assertEquals([11, -123n, 123n, 22], wasm.tailCall(-123n, 123n));
})();
(function I64CountLeadingZeros() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("clz", makeSig([kWasmI64], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
kExprI64Clz,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(0n, wasm.clz(-1n));
assertEquals(64n, wasm.clz(0n));
assertEquals(47n, wasm.clz(0x1FFFFn));
})();
(function I64CountTrailingZeros() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("ctz", makeSig([kWasmI64], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
kExprI64Ctz,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(0n, wasm.ctz(-1n));
assertEquals(64n, wasm.ctz(0n));
assertEquals(17n, wasm.ctz(0xE0000n));
})();
(function I64PopCount() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("popcnt", makeSig([kWasmI64], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
kExprI64Popcnt,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(64n, wasm.popcnt(-1n));
assertEquals(0n, wasm.popcnt(0n));
assertEquals(10n, wasm.popcnt(0b10101011111100001n));
})();
(function I64ConvertFromInt32() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("fromI32", makeSig([kWasmI32], [kWasmI64, kWasmI64]))
.addBody([
kExprLocalGet, 0,
kExprI64SConvertI32,
kExprLocalGet, 0,
kExprI64UConvertI32,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals([0n, 0n], wasm.fromI32(0));
assertEquals([123n, 123n], wasm.fromI32(123));
assertEquals([-1n, 0xFFFFFFFFn], wasm.fromI32(-1));
assertEquals([-2147483648n, 2147483648n], wasm.fromI32(0x80000000));
})();
(function I64ConvertFromF64() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("reinterpretF64", makeSig([kWasmF64], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
kExprI64ReinterpretF64
])
.exportFunc();
builder.addFunction("signedF64", makeSig([kWasmF64], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
kExprI64SConvertF64,
])
.exportFunc();
builder.addFunction("unsignedF64", makeSig([kWasmF64], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
kExprI64UConvertF64,
])
.exportFunc();
builder.addFunction("signedSatF64", makeSig([kWasmF64], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
kNumericPrefix, kExprI64SConvertSatF64,
])
.exportFunc();
builder.addFunction("unsignedSatF64", makeSig([kWasmF64], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
kNumericPrefix, kExprI64UConvertSatF64,
])
.exportFunc();
let wasm = builder.instantiate().exports;
assertEquals(0n, wasm.reinterpretF64(0));
assertEquals(4638355772470722560n, wasm.reinterpretF64(123));
assertEquals(-4585016264384053248n, wasm.reinterpretF64(-123));
assertEquals(0xFF_12345678n, wasm.signedF64(0xFF_12345678));
assertEquals(-0xFF_12345678n, wasm.signedF64(-0xFF_12345678));
assertTraps(kTrapFloatUnrepresentable, () => wasm.signedF64(NaN));
assertTraps(kTrapFloatUnrepresentable, () => wasm.signedF64(Infinity));
assertTraps(kTrapFloatUnrepresentable, () => wasm.signedF64(-Infinity));
assertEquals(0xFF_12345678n, wasm.unsignedF64(0xFF_12345678));
assertTraps(kTrapFloatUnrepresentable, () => wasm.unsignedF64(-1));
assertTraps(kTrapFloatUnrepresentable, () => wasm.unsignedF64(NaN));
assertTraps(kTrapFloatUnrepresentable, () => wasm.unsignedF64(Infinity));
assertTraps(kTrapFloatUnrepresentable, () => wasm.unsignedF64(-Infinity));
assertEquals(0xFF_12345678n, wasm.signedSatF64(0xFF_12345678));
assertEquals(-0xFF_12345678n, wasm.signedSatF64(-0xFF_12345678));
assertEquals(0n, wasm.signedSatF64(NaN));
assertEquals(9223372036854775807n, wasm.signedSatF64(Infinity));
assertEquals(-9223372036854775808n, wasm.signedSatF64(-Infinity));
assertEquals(0xFF_12345678n, wasm.unsignedSatF64(0xFF_12345678));
assertEquals(0n, wasm.unsignedSatF64(-0xFF_12345678));
assertEquals(0n, wasm.unsignedSatF64(NaN));
assertEquals(-1n, wasm.unsignedSatF64(Infinity));
assertEquals(0n, wasm.unsignedSatF64(-Infinity));
})();
(function I64ConvertFromF32() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("signedF32", makeSig([kWasmF32], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
kExprI64SConvertF32,
])
.exportFunc();
builder.addFunction("unsignedF32", makeSig([kWasmF32], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
kExprI64UConvertF32,
])
.exportFunc();
builder.addFunction("signedSatF32", makeSig([kWasmF32], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
kNumericPrefix, kExprI64SConvertSatF32,
])
.exportFunc();
builder.addFunction("unsignedSatF32", makeSig([kWasmF32], [kWasmI64]))
.addBody([
kExprLocalGet, 0,
kNumericPrefix, kExprI64UConvertSatF32,
])
.exportFunc();
let wasm = builder.instantiate().exports;
// Loss of precision due to float32.
assertEquals(0xFF_12340000n, wasm.signedF32(0xFF_12345678));
assertEquals(-0xFF_12340000n, wasm.signedF32(-0xFF_12345678));
assertTraps(kTrapFloatUnrepresentable, () => wasm.signedF32(NaN));
assertTraps(kTrapFloatUnrepresentable, () => wasm.signedF32(Infinity));
assertTraps(kTrapFloatUnrepresentable, () => wasm.signedF32(-Infinity));
assertEquals(0xFF_12340000n, wasm.unsignedF32(0xFF_12345678));
assertTraps(kTrapFloatUnrepresentable, () => wasm.unsignedF32(-1));
assertTraps(kTrapFloatUnrepresentable, () => wasm.unsignedF32(NaN));
assertTraps(kTrapFloatUnrepresentable, () => wasm.unsignedF32(Infinity));
assertTraps(kTrapFloatUnrepresentable, () => wasm.unsignedF32(-Infinity));
assertEquals(0xFF_12340000n, wasm.signedSatF32(0xFF_12345678));
assertEquals(-0xFF_12340000n, wasm.signedSatF32(-0xFF_12345678));
assertEquals(0n, wasm.signedSatF32(NaN));
assertEquals(9223372036854775807n, wasm.signedSatF32(Infinity));
assertEquals(-9223372036854775808n, wasm.signedSatF32(-Infinity));
assertEquals(0xFF_12340000n, wasm.unsignedSatF32(0xFF_12345678));
assertEquals(0n, wasm.unsignedSatF32(-0xFF_12345678));
assertEquals(0n, wasm.unsignedSatF32(NaN));
assertEquals(-1n, wasm.unsignedSatF32(Infinity));
assertEquals(0n, wasm.unsignedSatF32(-Infinity));
})();

View File

@ -0,0 +1,95 @@
// 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: --no-liftoff --no-wasm-lazy-compilation
// Flags: --no-wasm-loop-unrolling --no-wasm-loop-peeling
// This test case creates nested loops which contain struct.get calls that
// can potentially be load-eliminated as they load from a struct allocation at
// the function entry. The inner-most loop contains a call which cannot be
// inlined invalidating the eliminated loads in the loop resulting in a required
// revisitation of the loop body.
// Due to a bug in this revisitation algorithm, this resulted in 2^n loop visits
// of the innermost loop for this particular case where n is the nesting depth
// of loops.
// Due to the SnapshotTable storing the state as deltas between previous states,
// every revisit results in more data being accumulated in the SnapshotTable
// finally reaching an out of memory for the zone as it seems to be limited to
// 4 GB.
d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
// Parameter to configure the nesting of loops.
// Note that initially 22 nested loops where enough to trigger the oom situation
// described above, so 30 should reliably reproduce this issue or run into
// timeouts due to the exponential runtime.
const nestedLoopCount = 30;
(function WasmLoadElimination() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let array = builder.addArray(kWasmAnyRef, true);
let struct = builder.addStruct([
makeField(wasmRefType(array), true)
]);
let sig = makeSig([wasmRefType(struct)], [kWasmI32]);
// An imported function that can not be inlined causing unknown side effects
// and invaliding all previous (mutable) loads.
let innerFct = builder.addImport('m', 'nonInlineableCallee', sig)
let local_index = 1;
// This function generates nested ops containing struct.get instructions that
// can be eliminated on the forward edge but get invalidated when reaching
// the call of the imported function in the innermost loop.
let inlineCallees = (count) => {
let local_1 = local_index++;
let local_2 = local_index++;
if (count == 0) {
return [
kExprLocalGet, local_1,
kExprRefAsNonNull,
kExprCallFunction, innerFct,
];
}
return [
kExprLoop, kWasmVoid,
kExprLocalGet, local_1,
kGCPrefix, kExprStructGet, struct, 0,
kExprLocalSet, local_2,
kExprI32Const, 1,
kExprIf, kWasmVoid,
kExprLocalGet, local_2,
kExprI32Const, 43, // dummy array index
kGCPrefix, kExprArrayGet, array,
kGCPrefix, kExprRefCast, struct,
...inlineCallees(count - 1),
kExprDrop,
kExprBr, 1,
kExprEnd,
kExprEnd,
kExprI32Const, 1,
];
};
let fct = builder.addFunction("loadEliminationLoop", sig)
.addBody([
kGCPrefix, kExprArrayNewFixed, array, 0,
kGCPrefix, kExprStructNew, struct,
kExprLocalSet, 1,
...inlineCallees(nestedLoopCount),
])
.exportFunc();
for (let i = 0; i < nestedLoopCount + 1; ++i) {
fct.addLocals(wasmRefNullType(struct), 1)
.addLocals(wasmRefType(array), 1)
}
let instance = builder.instantiate({m: {nonInlineableCallee: () => 1}});
// Calling it with a JS object will already fail on the boundary which is fine
// as we eagerly compile and do not care about the runtime behavior.
// (This program doesn't make much sense.)
assertThrows(() => instance.exports.loadEliminationLoop({}), TypeError);
})();

View File

@ -0,0 +1,426 @@
// Copyright 2024 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: --no-liftoff --no-wasm-lazy-compilation
// Flags: --enable-testing-opcode-in-wasm
d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
d8.file.execute('test/mjsunit/value-helper.js');
(function I8x16UpperToLowerReduce() {
print(arguments.callee.name);
const builder = new WasmModuleBuilder();
const shared_simd = [
kExprLocalGet, 0,
kSimdPrefix, kExprI8x16Splat,
kExprLocalGet, 1,
kSimdPrefix, kExprI8x16ReplaceLane, 1,
kExprLocalGet, 2,
kSimdPrefix, kExprI8x16ReplaceLane, 2,
kExprLocalGet, 3,
kSimdPrefix, kExprI8x16ReplaceLane, 3,
kExprLocalGet, 1,
kSimdPrefix, kExprI8x16ReplaceLane, 5,
kExprLocalGet, 2,
kSimdPrefix, kExprI8x16ReplaceLane, 6,
kExprLocalGet, 3,
kSimdPrefix, kExprI8x16ReplaceLane, 7,
kExprLocalGet, 1,
kSimdPrefix, kExprI8x16ReplaceLane, 9,
kExprLocalGet, 2,
kSimdPrefix, kExprI8x16ReplaceLane, 10,
kExprLocalGet, 3,
kSimdPrefix, kExprI8x16ReplaceLane, 11,
kExprLocalGet, 1,
kSimdPrefix, kExprI8x16ReplaceLane, 13,
kExprLocalGet, 2,
kSimdPrefix, kExprI8x16ReplaceLane, 14,
kExprLocalGet, 3,
kSimdPrefix, kExprI8x16ReplaceLane, 15,
kExprLocalTee, 4,
kExprLocalGet, 4,
kExprLocalGet, 4,
kSimdPrefix, kExprI8x16Shuffle, // upper-to-lower 8x16
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
kSimdPrefix, kExprI8x16Add, // first step of reduction
kExprLocalTee, 4,
kExprLocalGet, 4,
kExprLocalGet, 4,
kSimdPrefix, kExprI8x16Shuffle, // upper-to-lower 8x8
0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
kSimdPrefix, kExprI8x16Add, // second step of reduction
kExprLocalTee, 4,
kExprLocalGet, 4,
kExprLocalGet, 4,
kSimdPrefix, kExprI8x16Shuffle, // upper-to-lower 8x4
0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
kSimdPrefix, kExprI8x16Add, // third step of reduction
kExprLocalTee, 4,
kExprLocalGet, 4,
kExprLocalGet, 4,
kSimdPrefix, kExprI8x16Shuffle, // upper-to-lower 16x2
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
kSimdPrefix, kExprI8x16Add, // final step of reduction
]
const shared_scalar = wasmI32Const(0xFF).concat([
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprLocalGet, 2,
kExprLocalGet, 3,
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprLocalGet, 2,
kExprLocalGet, 3,
kExprI32Add,
kExprI32Add,
kExprI32Add,
kExprI32Add,
kExprI32Add,
kExprI32Add,
kExprI32Add,
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprLocalGet, 2,
kExprLocalGet, 3,
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprLocalGet, 2,
kExprLocalGet, 3,
kExprI32Add,
kExprI32Add,
kExprI32Add,
kExprI32Add,
kExprI32Add,
kExprI32Add,
kExprI32Add,
kExprI32Add,
kExprI32And,
]);
const s8x16 = shared_simd.concat([kSimdPrefix, kExprI8x16ExtractLaneS, 0]);
const u8x16 = shared_simd.concat([kSimdPrefix, kExprI8x16ExtractLaneU, 0]);
builder.addFunction("sadd_reduce", kSig_i_iiii).addLocals(kWasmS128, 1).addBody(s8x16).exportFunc();
builder.addFunction("uadd_reduce", kSig_i_iiii).addLocals(kWasmS128, 1).addBody(u8x16).exportFunc();
const signed_scalar = shared_scalar.concat([kExprI32SExtendI8]);
const unsigned_scalar = shared_scalar.concat([]);
builder.addFunction("sadd", kSig_i_iiii).addBody(signed_scalar).exportFunc();
builder.addFunction("uadd", kSig_i_iiii).addBody(unsigned_scalar).exportFunc();
const wasm = builder.instantiate().exports;
for (let a of int8_array) {
for (let b of int8_array) {
for (let c of int8_array) {
for (let d of int8_array) {
assertEquals(wasm.sadd(a, b, c, d),
wasm.sadd_reduce(a, b, c, d));
assertEquals(wasm.uadd(a, b, c, d),
wasm.uadd_reduce(a, b, c, d));
}
}
}
}
})();
(function I16x8UpperToLowerReduce() {
print(arguments.callee.name);
const builder = new WasmModuleBuilder();
const shared_simd = [
kExprLocalGet, 0,
kSimdPrefix, kExprI16x8Splat,
kExprLocalGet, 1,
kSimdPrefix, kExprI16x8ReplaceLane, 1,
kExprLocalGet, 2,
kSimdPrefix, kExprI16x8ReplaceLane, 2,
kExprLocalGet, 3,
kSimdPrefix, kExprI16x8ReplaceLane, 3,
kExprLocalGet, 1,
kSimdPrefix, kExprI16x8ReplaceLane, 5,
kExprLocalGet, 2,
kSimdPrefix, kExprI16x8ReplaceLane, 6,
kExprLocalGet, 3,
kSimdPrefix, kExprI16x8ReplaceLane, 7,
kExprLocalTee, 4,
kExprLocalGet, 4,
kExprLocalGet, 4,
kSimdPrefix, kExprI8x16Shuffle, // upper-to-lower 16x8
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
...SimdInstr(kExprI16x8Add), // first step of reduction
kExprLocalTee, 4,
kExprLocalGet, 4,
kExprLocalGet, 4,
kSimdPrefix, kExprI8x16Shuffle, // upper-to-lower 16x4
0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
...SimdInstr(kExprI16x8Add), // second step of reduction
kExprLocalTee, 4,
kExprLocalGet, 4,
kExprLocalGet, 4,
kSimdPrefix, kExprI8x16Shuffle, // upper-to-lower 8x2
0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
...SimdInstr(kExprI16x8Add), // final step of reduction
];
const shared_scalar = wasmI32Const(0xFFFF).concat([
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprLocalGet, 2,
kExprLocalGet, 3,
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprLocalGet, 2,
kExprLocalGet, 3,
kExprI32Add,
kExprI32Add,
kExprI32Add,
kExprI32Add,
kExprI32Add,
kExprI32Add,
kExprI32Add,
kExprI32And,
]);
const s16x8 = shared_simd.concat([kSimdPrefix, kExprI16x8ExtractLaneS, 0]);
const u16x8 = shared_simd.concat([kSimdPrefix, kExprI16x8ExtractLaneU, 0]);
builder.addFunction("sadd_reduce", kSig_i_iiii).addLocals(kWasmS128, 1).addBody(s16x8).exportFunc();
builder.addFunction("uadd_reduce", kSig_i_iiii).addLocals(kWasmS128, 1).addBody(u16x8).exportFunc();
const signed_scalar = shared_scalar.concat([kExprI32SExtendI16]);
const unsigned_scalar = shared_scalar.concat([]);
builder.addFunction("sadd", kSig_i_iiii).addBody(signed_scalar).exportFunc();
builder.addFunction("uadd", kSig_i_iiii).addBody(unsigned_scalar).exportFunc();
const wasm = builder.instantiate().exports;
for (let a of int16_array) {
for (let b of int16_array) {
for (let c of int16_array) {
for (let d of int16_array) {
assertEquals(wasm.sadd(a, b, c, d),
wasm.sadd_reduce(a, b, c, d));
assertEquals(wasm.uadd(a, b, c, d),
wasm.uadd_reduce(a, b, c, d));
}
}
}
}
})();
(function I32x4UpperToLowerReduce() {
print(arguments.callee.name);
const builder = new WasmModuleBuilder();
builder.addFunction("add_reduce", kSig_i_iiii).addLocals(kWasmS128, 1).addBody([
kExprLocalGet, 0,
kSimdPrefix, kExprI32x4Splat,
kExprLocalGet, 1,
kSimdPrefix, kExprI32x4ReplaceLane, 1,
kExprLocalGet, 2,
kSimdPrefix, kExprI32x4ReplaceLane, 2,
kExprLocalGet, 3,
kSimdPrefix, kExprI32x4ReplaceLane, 3,
kExprLocalTee, 4,
kExprLocalGet, 4,
kExprLocalGet, 4,
kSimdPrefix, kExprI8x16Shuffle, // upper-to-lower 32x4
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
...SimdInstr(kExprI32x4Add), // first step of reduction
kExprLocalTee, 4,
kExprLocalGet, 4,
kExprLocalGet, 4,
kSimdPrefix, kExprI8x16Shuffle, // upper-to-lower 32x2
0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
...SimdInstr(kExprI32x4Add), // final step of reduction
kSimdPrefix, kExprI32x4ExtractLane, 0,
]).exportFunc();
const wasm = builder.instantiate().exports;
for (let idxa = 0; idxa < int32_array.length; ++idxa) {
for (let idxb = 0; idxb < int32_array.length; ++idxb) {
const idxc = (idxa + 1) % int32_array.length;
const idxd = (idxb + 1) % int32_array.length;
const a = int32_array[idxa];
const b = int32_array[idxb];
const c = int32_array[idxc];
const d = int32_array[idxd];
const expected = 0xFFFFFFFF & (a + b + c + d);
assertEquals(expected, wasm.add_reduce(a, b, c, d));
}
}
})();
(function F32x4UpperToLowerReduce() {
print(arguments.callee.name);
const builder = new WasmModuleBuilder();
builder.addFunction("add_reduce", kSig_f_ffff).addLocals(kWasmS128, 1).addBody([
kExprLocalGet, 0,
kSimdPrefix, kExprF32x4Splat,
kExprLocalGet, 1,
kSimdPrefix, kExprF32x4ReplaceLane, 1,
kExprLocalGet, 2,
kSimdPrefix, kExprF32x4ReplaceLane, 2,
kExprLocalGet, 3,
kSimdPrefix, kExprF32x4ReplaceLane, 3,
kExprLocalTee, 4,
kExprLocalGet, 4,
kExprLocalGet, 4,
kSimdPrefix, kExprI8x16Shuffle, // upper-to-lower 32x4
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
...SimdInstr(kExprF32x4Add), // first step of reduction
kExprLocalTee, 4,
kExprLocalGet, 4,
kExprLocalGet, 4,
kSimdPrefix, kExprI8x16Shuffle, // upper-to-lower 32x2
0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
...SimdInstr(kExprF32x4Add), // final step of reduction
kSimdPrefix, kExprF32x4ExtractLane, 0,
]).exportFunc();
builder.addFunction("add", kSig_f_ffff).addBody([
kExprLocalGet, 0,
kExprLocalGet, 2,
kExprF32Add,
kExprLocalGet, 1,
kExprLocalGet, 3,
kExprF32Add,
kExprF32Add,
]).exportFunc();
const wasm = builder.instantiate().exports;
for (let idxa = 0; idxa < float32_array.length; ++idxa) {
for (let idxb = 0; idxb < float32_array.length; ++idxb) {
const idxc = (idxa + 1) % float32_array.length;
const idxd = (idxb + 1) % float32_array.length;
const a = float32_array[idxa];
const b = float32_array[idxb];
const c = float32_array[idxc];
const d = float32_array[idxd];
assertEquals(wasm.add(a, b, c, d), wasm.add_reduce(a, b, c, d));
}
}
})();
(function F32x4PairwiseReduce() {
print(arguments.callee.name);
const builder = new WasmModuleBuilder();
builder.addFunction("add_reduce", kSig_f_ffff).addLocals(kWasmS128, 1).addBody([
kExprLocalGet, 0,
kSimdPrefix, kExprF32x4Splat,
kExprLocalGet, 1,
kSimdPrefix, kExprF32x4ReplaceLane, 1,
kExprLocalGet, 2,
kSimdPrefix, kExprF32x4ReplaceLane, 2,
kExprLocalGet, 3,
kSimdPrefix, kExprF32x4ReplaceLane, 3,
kExprLocalTee, 4,
kExprLocalGet, 4,
kExprLocalGet, 4,
kSimdPrefix, kExprI8x16Shuffle, // pairwise 32x4
0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00,
...SimdInstr(kExprF32x4Add), // first step of reduction
kExprLocalTee, 4,
kExprLocalGet, 4,
kExprLocalGet, 4,
kSimdPrefix, kExprI8x16Shuffle, // pairwise 32x2
0x08, 0x09, 0xa, 0xb, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
...SimdInstr(kExprF32x4Add), // final step of reduction
kSimdPrefix, kExprF32x4ExtractLane, 0,
]).exportFunc();
builder.addFunction("add", kSig_f_ffff).addBody([
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprF32Add,
kExprLocalGet, 2,
kExprLocalGet, 3,
kExprF32Add,
kExprF32Add,
]).exportFunc();
const wasm = builder.instantiate().exports;
for (let idxa = 0; idxa < float32_array.length; ++idxa) {
for (let idxb = 0; idxb < float32_array.length; ++idxb) {
const idxc = (idxa + 1) % float32_array.length;
const idxd = (idxb + 1) % float32_array.length;
const a = float32_array[idxa];
const b = float32_array[idxb];
const c = float32_array[idxc];
const d = float32_array[idxd];
assertEquals(wasm.add(a, b, c, d), wasm.add_reduce(a, b, c, d));
}
}
})();
(function I64x2Reduce() {
print(arguments.callee.name);
const builder = new WasmModuleBuilder();
builder.addFunction("add_reduce", kSig_l_ll).addLocals(kWasmS128, 1).addBody([
kExprLocalGet, 0,
kSimdPrefix, kExprI64x2Splat,
kExprLocalGet, 1,
kSimdPrefix, kExprI64x2ReplaceLane, 1,
kExprLocalTee, 2,
kExprLocalGet, 2,
kExprLocalGet, 2,
kSimdPrefix, kExprI8x16Shuffle, // 64x2
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
...SimdInstr(kExprI64x2Add), // final step of reduction
kSimdPrefix, kExprI64x2ExtractLane, 0,
]).exportFunc();
const wasm = builder.instantiate().exports;
for (let idxa = 0; idxa < uint64_array.length; ++idxa) {
for (let idxb = 0; idxb < uint64_array.length; ++idxb) {
const a = uint64_array[idxa];
const b = uint64_array[idxb];
const expected = BigInt.asUintN(64, a + b);
assertEquals(expected, BigInt.asUintN(64, wasm.add_reduce(a, b)));
}
}
})();
(function F64x2Reduce() {
print(arguments.callee.name);
const builder = new WasmModuleBuilder();
builder.addFunction("add_reduce", kSig_d_dd).addLocals(kWasmS128, 1).addBody([
kExprLocalGet, 0,
kSimdPrefix, kExprF64x2Splat,
kExprLocalGet, 1,
kSimdPrefix, kExprF64x2ReplaceLane, 1,
kExprLocalTee, 2,
kExprLocalGet, 2,
kExprLocalGet, 2,
kSimdPrefix, kExprI8x16Shuffle, // 64x2
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
...SimdInstr(kExprF64x2Add), // final step of reduction
kSimdPrefix, kExprF64x2ExtractLane, 0,
]).exportFunc();
builder.addFunction("add", kSig_d_dd).addBody([
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprF64Add,
]).exportFunc();
const wasm = builder.instantiate().exports;
for (let idxa = 0; idxa < float64_array.length; ++idxa) {
for (let idxb = 0; idxb < float64_array.length; ++idxb) {
const a = float64_array[idxa];
const b = float64_array[idxb];
assertEquals(wasm.add(a, b), wasm.add_reduce(a, b));
}
}
})();

View File

@ -0,0 +1,26 @@
// 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: --no-liftoff
d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
const builder = new WasmModuleBuilder();
builder.addMemory(16, 32);
builder.addFunction(undefined, makeSig([], []))
.addBody([
kExprF64Const, 0x6b, 0xe5, 0xf4, 0xf6, 0x2e, 0x3f, 0xe1, 0x4e, // f64.const
kNumericPrefix, kExprI32SConvertSatF64, // i32.trunc_sat_f64_s
kExprI64Const, 1,
kAtomicPrefix, kExprI64AtomicStore, 0x03, 0xff, 0xfe, 0x01, // i64.atomic.store
]);
builder.addExport('main', 0);
const instance = builder.instantiate();
try {
instance.exports.main(1, 2, 3);
} catch (e) {
assertEquals("RuntimeError: operation does not support unaligned accesses",
e.toString());
}