Source code

Revision control

Copy as Markdown

Other Tools

// |jit-test| skip-if: !wasmSimdEnabled()
function testValid(code) {
assertEq(WebAssembly.validate(wasmTextToBinary(code)), true);
}
function testInvalid(code) {
assertEq(WebAssembly.validate(wasmTextToBinary(code)), false);
}
// v128 -> v128
for (let op of [
'i8x16.neg',
'i8x16.abs',
'i16x8.neg',
'i16x8.abs',
'i16x8.extend_low_i8x16_s',
'i16x8.extend_high_i8x16_s',
'i16x8.extend_low_i8x16_u',
'i16x8.extend_high_i8x16_u',
'i32x4.neg',
'i32x4.abs',
'i32x4.extend_low_i16x8_s',
'i32x4.extend_high_i16x8_s',
'i32x4.extend_low_i16x8_u',
'i32x4.extend_high_i16x8_u',
'i32x4.trunc_sat_f32x4_s',
'i32x4.trunc_sat_f32x4_u',
'i64x2.neg',
'f32x4.abs',
'f32x4.neg',
'f32x4.sqrt',
'f32x4.convert_i32x4_s',
'f32x4.convert_i32x4_s',
'f64x2.abs',
'f64x2.neg',
'f64x2.sqrt',
'v128.not'])
{
testValid(`(module
(func (param v128) (result v128)
(${op} (local.get 0))))`);
}
for (let [prefix, result, suffix] of [['i8x16', 'i32', '_s'],
['i8x16', 'i32', '_u'],
['i16x8', 'i32', '_s'],
['i16x8', 'i32', '_u'],
['i32x4', 'i32', ''],
['i64x2', 'i64', ''],
['f32x4', 'f32', ''],
['f64x2', 'f64', '']])
{
testValid(`(module
(func (param v128) (result ${result})
(${prefix}.extract_lane${suffix} 1 (local.get 0))))`);
}
// The wat parser accepts small out-of-range lane indices, but they must be
// caught in validation.
testInvalid(
`(module
(func (param v128) (result i32)
(i8x16.extract_lane_u 16 (local.get 0))))`);
// (v128, v128) -> v128
for (let op of [
'i8x16.eq',
'i8x16.ne',
'i8x16.lt_s',
'i8x16.lt_u',
'i8x16.gt_s',
'i8x16.gt_u',
'i8x16.le_s',
'i8x16.le_u',
'i8x16.ge_s',
'i8x16.ge_u',
'i16x8.eq',
'i16x8.ne',
'i16x8.lt_s',
'i16x8.lt_u',
'i16x8.gt_s',
'i16x8.gt_u',
'i16x8.le_s',
'i16x8.le_u',
'i16x8.ge_s',
'i16x8.ge_u',
'i32x4.eq',
'i32x4.ne',
'i32x4.lt_s',
'i32x4.lt_u',
'i32x4.gt_s',
'i32x4.gt_u',
'i32x4.le_s',
'i32x4.le_u',
'i32x4.ge_s',
'i32x4.ge_u',
'f32x4.eq',
'f32x4.ne',
'f32x4.lt',
'f32x4.gt',
'f32x4.le',
'f32x4.ge',
'f64x2.eq',
'f64x2.ne',
'f64x2.lt',
'f64x2.gt',
'f64x2.le',
'f64x2.ge',
'v128.and',
'v128.or',
'v128.xor',
'v128.andnot',
'i8x16.avgr_u',
'i16x8.avgr_u',
'i8x16.add',
'i8x16.add_sat_s',
'i8x16.add_sat_u',
'i8x16.sub',
'i8x16.sub_sat_s',
'i8x16.sub_sat_u',
'i8x16.min_s',
'i8x16.max_s',
'i8x16.min_u',
'i8x16.max_u',
'i16x8.add',
'i16x8.add_sat_s',
'i16x8.add_sat_u',
'i16x8.sub',
'i16x8.sub_sat_s',
'i16x8.sub_sat_u',
'i16x8.mul',
'i16x8.min_s',
'i16x8.max_s',
'i16x8.min_u',
'i16x8.max_u',
'i32x4.add',
'i32x4.sub',
'i32x4.mul',
'i32x4.min_s',
'i32x4.max_s',
'i32x4.min_u',
'i32x4.max_u',
'i64x2.add',
'i64x2.sub',
'i64x2.mul',
'f32x4.add',
'f32x4.sub',
'f32x4.mul',
'f32x4.div',
'f32x4.min',
'f32x4.max',
'f64x2.add',
'f64x2.sub',
'f64x2.mul',
'f64x2.div',
'f64x2.min',
'f64x2.max',
'i8x16.narrow_i16x8_s',
'i8x16.narrow_i16x8_u',
'i16x8.narrow_i32x4_s',
'i16x8.narrow_i32x4_u',
'i8x16.swizzle'])
{
testValid(`(module
(func (param v128) (param v128) (result v128)
(${op} (local.get 0) (local.get 1))))`);
}
testValid(`(module
(func (param v128) (param v128) (result v128)
(i8x16.shuffle 0 16 1 17 2 18 3 19 4 20 5 21 6 22 7 23 (local.get 0) (local.get 1))))`);
assertErrorMessage(() => testValid(
`(module
(func (param v128) (param v128) (result v128)
(i8x16.shuffle 0 16 1 17 2 18 3 19 4 20 5 21 6 22 7 (local.get 0) (local.get 1))))`),
SyntaxError,
/expected a u8/);
// (v128, i32) -> v128
for (let op of [
'i8x16.shl',
'i8x16.shr_s',
'i8x16.shr_u',
'i16x8.shl',
'i16x8.shr_s',
'i16x8.shr_u',
'i32x4.shl',
'i32x4.shr_s',
'i32x4.shr_u',
'i64x2.shl',
'i64x2.shr_s',
'i64x2.shr_u'])
{
testValid(`(module
(func (param v128) (param i32) (result v128)
(${op} (local.get 0) (local.get 1))))`);
}
// v128 -> i32
for (let op of [
'v128.any_true',
'i8x16.all_true',
'i16x8.all_true',
'i32x4.all_true',
'i8x16.bitmask',
'i16x8.bitmask',
'i32x4.bitmask'])
{
testValid(`(module
(func (param v128) (result i32)
(${op} (local.get 0))))`);
}
// T -> V128
for (let [op, input] of [
['i8x16.splat', 'i32'],
['i16x8.splat', 'i32'],
['i32x4.splat', 'i32'],
['i64x2.splat', 'i64'],
['f32x4.splat', 'f32'],
['f64x2.splat', 'f64']])
{
testValid(`(module
(func (param ${input}) (result v128)
(${op} (local.get 0))))`);
}
// i32 -> v128
for (let op of [
'v128.load',
'v128.load8_splat',
'v128.load16_splat',
'v128.load32_splat',
'v128.load64_splat',
'v128.load8x8_s',
'v128.load8x8_u',
'v128.load16x4_s',
'v128.load16x4_u',
'v128.load32x2_s',
'v128.load32x2_u'])
{
testValid(`(module
(memory 1 1)
(func (param i32) (result v128)
(${op} (local.get 0))))`);
}
testValid(`(module
(func (result v128)
(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
(func (result v128)
(v128.const i16x8 0 1 2 3 4 5 6 7))
(func (result v128)
(v128.const i32x4 0 1 2 3))
(func (result v128)
(v128.const i64x2 0 1))
(func (result v128)
(v128.const f32x4 0 1 2 3))
(func (result v128)
(v128.const f32x4 0.5 1.5 2.5 3.5))
(func (result v128)
(v128.const f64x2 0 1))
(func (result v128)
(v128.const f64x2 0.5 1.5)))`);
assertErrorMessage(() => testValid(
`(module
(func (result v128)
(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14)))`),
SyntaxError,
/expected a i8/);
assertErrorMessage(() => testValid(
`(module
(func (result v128)
(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 256 15)))`),
SyntaxError,
/invalid i8 number/);
assertErrorMessage(() => testValid(
`(module
(func (result v128)
(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 3.14 15)))`),
SyntaxError,
/expected a i8/);
assertErrorMessage(() => testValid(
`(module
(func (result v128)
(v128.const f32x4 0.5 1.5 2.5))`),
SyntaxError,
/expected a float/);
assertErrorMessage(() => testValid(
`(module
(func (result v128)
(v128.const i8x8 0 1 2 3 4 5 6 7)))`),
SyntaxError,
/expected one of/);
// v128 -> ()
testValid(`(module
(memory 1 1)
(func (param i32) (param v128)
(v128.store (local.get 0) (local.get 1))))`);
// (v128, v128, v128) -> v128
testValid(`(module
(func (param v128) (param v128) (param v128) (result v128)
(v128.bitselect (local.get 0) (local.get 1) (local.get 2))))`);
// (v128, t) -> v128
for (let [prefix, input] of [['i8x16', 'i32'],
['i16x8', 'i32'],
['i32x4', 'i32'],
['i64x2', 'i64'],
['f32x4', 'f32'],
['f64x2', 'f64']])
{
testValid(`(module
(func (param v128) (param ${input}) (result v128)
(${prefix}.replace_lane 1 (local.get 0) (local.get 1))))`);
}
testInvalid(
`(module
(func (param v128) (param i32) (result v128)
(i8x16.replace_lane 16 (local.get 0) (local.get 1))))`);
// Global variables
testValid(`(module
(global $g (mut v128) (v128.const f32x4 1 2 3 4)))`);
testValid(`(module
(global $g (import "m" "g") v128)
(global $h (mut v128) (global.get $g)))`);
testValid(`(module
(global $g (export "g") v128 (v128.const f32x4 1 2 3 4)))`);
testValid(`(module
(global $g (export "g") (mut v128) (v128.const f32x4 1 2 3 4)))`);
// Imports, exports, calls
testValid(`(module
(import "m" "g" (func (param v128) (result v128)))
(func (export "f") (param v128) (result v128)
(f64x2.add (local.get 0) (v128.const f64x2 1 2))))`);
testValid(`(module
(func $f (param v128) (result v128)
(i8x16.neg (local.get 0)))
(func $g (export "g") (param v128) (result v128)
(call $f (local.get 0))))`);