tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ad-hack.js (63195B)


      1 // |jit-test| skip-if: !wasmSimdEnabled()
      2 
      3 // Ad-hoc test cases used during development.  Generally these are ordered from
      4 // easier toward harder.
      5 //
      6 // The test cases here are usually those that require some special processing.
      7 // Simple binary operators (v128 x v128 -> v128) and unary operators (v128 ->
      8 // v128) are tested in ad-hack-simple-binops*.js and ad-hack-simple-unops.js.
      9 
     10 // Do not include this in the preamble, it must be loaded after lib/wasm.js
     11 load(scriptdir + "ad-hack-preamble.js")
     12 
     13 // v128.store
     14 // oob store
     15 // v128.const
     16 
     17 for ( let offset of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) {
     18    var ins = wasmEvalText(`
     19  (module
     20    (memory (export "mem") 1 1)
     21    (func (export "f") (param $loc i32)
     22      (v128.store offset=${offset} (local.get $loc) (v128.const i32x4 ${1+offset} 2 3 ${4+offset*2}))))`);
     23    var mem8 = new Uint8Array(ins.exports.mem.buffer);
     24    ins.exports.f(160);
     25    assertSame(getUnaligned(mem8, 4, 160 + offset, 4), [1+offset, 2, 3, 4+offset*2]);
     26 
     27    // OOB write should trap
     28    assertErrorMessage(() => ins.exports.f(65536-15),
     29                       WebAssembly.RuntimeError,
     30                       /index out of bounds/)
     31 
     32    // Ensure that OOB writes don't write anything: moved to simd-partial-oob-store.js
     33 }
     34 
     35 // v128.load
     36 // oob load
     37 // v128.store
     38 // temp register
     39 
     40 for ( let offset of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) {
     41    var ins = wasmEvalText(`
     42  (module
     43    (memory (export "mem") 1 1)
     44    (func (export "copy") (param $dest i32) (param $src i32)
     45      (v128.store (local.get $dest) (v128.load offset=${offset} (local.get $src)))))`);
     46    var mem32 = new Uint32Array(ins.exports.mem.buffer);
     47    var mem8 = new Uint8Array(ins.exports.mem.buffer);
     48    setUnaligned(mem8, 4, 4*4 + offset, [8+offset, 10, 12, 14+offset*2]);
     49    ins.exports.copy(40*4, 4*4);
     50    assertSame(get(mem32, 40, 4), [8+offset, 10, 12, 14+offset*2]);
     51    assertErrorMessage(() => ins.exports.copy(40*4, 65536-15),
     52                       WebAssembly.RuntimeError,
     53                       /index out of bounds/);
     54 }
     55 
     56 // call [with register params]
     57 // parameters [in registers]
     58 // return [with register values]
     59 // locals
     60 //
     61 // local.get
     62 // local.set
     63 // v128.const
     64 // v128.store
     65 
     66 var ins = wasmEvalText(`
     67  (module
     68    (memory (export "mem") 1 1)
     69    (func $g (param $param v128) (result v128)
     70      (local $tmp v128)
     71      (local.set $tmp (local.get $param))
     72      (local.get $tmp))
     73    (func (export "f")
     74      (v128.store (i32.const 160) (call $g (v128.const i32x4 1 2 3 4)))))`);
     75 var mem = new Uint32Array(ins.exports.mem.buffer);
     76 ins.exports.f();
     77 assertSame(get(mem, 40, 4), [1, 2, 3, 4]);
     78 
     79 // Same test but with local.tee
     80 
     81 var ins = wasmEvalText(`
     82  (module
     83    (memory (export "mem") 1 1)
     84    (func $g (param $param v128) (result v128)
     85      (local $tmp v128)
     86      (local.tee $tmp (local.get $param)))
     87    (func (export "f")
     88      (v128.store (i32.const 160) (call $g (v128.const i32x4 1 2 3 4)))))`);
     89 var mem = new Uint32Array(ins.exports.mem.buffer);
     90 ins.exports.f();
     91 assertSame(get(mem, 40, 4), [1, 2, 3, 4]);
     92 
     93 // Locals that end up on the stack.  Try to create unaligned placement (in the
     94 // baseline compiler anyway) by inserting i32 locals before or after and
     95 // inbetween the v128 ones and by having so many locals that we run out of
     96 // registers.
     97 
     98 var nlocals = 64;
     99 for ( let start of [0, 1]) {
    100    let decl = "";
    101    let set = "";
    102    let sum = "(v128.const i32x4 0 0 0 0)";
    103    var res = [0,0,0,0];
    104    var locno = start;
    105    for ( let i=start ; i < start + nlocals ; i++ ) {
    106        decl += "(local v128) ";
    107        set += `(local.set ${locno} (v128.const i32x4 ${i} ${i+1} ${i+2} ${i+3})) `;
    108        sum = `(i32x4.add ${sum} (local.get ${locno}))`;
    109        locno++;
    110        res[0] += i;
    111        res[1] += i+1;
    112        res[2] += i+2;
    113        res[3] += i+3;
    114        if ((i % 5) == 3) {
    115            decl += "(local i32) ";
    116            locno++;
    117        }
    118    }
    119    if (start)
    120        decl = "(local i32) " + decl;
    121    else
    122        decl += "(local i32) ";
    123    var ins = wasmEvalText(`
    124  (module
    125    (memory (export "mem") 1 1)
    126    (func $g (result v128)
    127      ${decl}
    128      ${set}
    129      ${sum})
    130    (func (export "f")
    131      (v128.store (i32.const 160) (call $g))))`);
    132 
    133    var mem = new Uint32Array(ins.exports.mem.buffer);
    134    ins.exports.f();
    135    assertSame(get(mem, 40, 4), res);
    136 }
    137 
    138 // Ditto parameters.  This is like the case above but values are passed rather
    139 // than set.
    140 //
    141 // call
    142 // call_indirect
    143 
    144 var nlocals = 64;
    145 for ( let start of [0, 1]) {
    146    let decl = "";
    147    let pass = "";
    148    let sum = "(v128.const i32x4 0 0 0 0)";
    149    var res = [0,0,0,0];
    150    var locno = start;
    151    for ( let i=start ; i < start + nlocals ; i++ ) {
    152        decl += "(param v128) ";
    153        pass += `(v128.const i32x4 ${i} ${i+1} ${i+2} ${i+3}) `;
    154        sum = `(i32x4.add ${sum} (local.get ${locno}))`;
    155        locno++;
    156        res[0] += i;
    157        res[1] += i+1;
    158        res[2] += i+2;
    159        res[3] += i+3;
    160        if ((i % 5) == 3) {
    161            decl += "(param i32) ";
    162            pass += "(i32.const 0) ";
    163            locno++;
    164        }
    165    }
    166    if (start) {
    167        decl = "(param i32) " + decl;
    168        pass = "(i32.const 0) " + pass;
    169    } else {
    170        decl += "(param i32) ";
    171        pass += "(i32.const 0) ";
    172    }
    173    var txt = `
    174  (module
    175    (memory (export "mem") 1 1)
    176    (type $t1 (func ${decl} (result v128)))
    177    (table funcref (elem $h))
    178    (func $g ${decl} (result v128)
    179      ${sum})
    180    (func (export "f1")
    181      (v128.store (i32.const 160) (call $g ${pass})))
    182    (func $h ${decl} (result v128)
    183      ${sum})
    184    (func (export "f2")
    185      (v128.store (i32.const 512) (call_indirect (type $t1) ${pass} (i32.const 0)))))`;
    186    var ins = wasmEvalText(txt);
    187 
    188    var mem = new Uint32Array(ins.exports.mem.buffer);
    189    ins.exports.f1();
    190    assertSame(get(mem, 40, 4), res);
    191    ins.exports.f2();
    192    assertSame(get(mem, 128, 4), res);
    193 }
    194 
    195 // Widening integer dot product
    196 
    197 var ins = wasmEvalText(`
    198  (module
    199    (memory (export "mem") 1 1)
    200    (func (export "run")
    201      (v128.store (i32.const 0)
    202        (i32x4.dot_i16x8_s (v128.load (i32.const 16)) (v128.load (i32.const 32))))))`);
    203 
    204 var xs = [5, 1, -4, 2, 20, -15, 12, 3];
    205 var ys = [6, 0, -7, 3, 8, -1, -3, 7];
    206 var ans = [xs[0]*ys[0] + xs[1]*ys[1],
    207           xs[2]*ys[2] + xs[3]*ys[3],
    208           xs[4]*ys[4] + xs[5]*ys[5],
    209           xs[6]*ys[6] + xs[7]*ys[7]];
    210 
    211 var mem16 = new Int16Array(ins.exports.mem.buffer);
    212 var mem32 = new Int32Array(ins.exports.mem.buffer);
    213 set(mem16, 8, xs);
    214 set(mem16, 16, ys);
    215 ins.exports.run();
    216 var result = get(mem32, 0, 4);
    217 assertSame(result, ans);
    218 
    219 // Splat, with and without constants (different code paths in ion)
    220 
    221 var ins = wasmEvalText(`
    222  (module
    223    (memory (export "mem") 1 1)
    224    (func (export "splat_i8x16") (param $src i32)
    225      (v128.store (i32.const 0) (i8x16.splat (local.get $src))))
    226    (func (export "csplat_i8x16")
    227      (v128.store (i32.const 0) (i8x16.splat (i32.const 37))))
    228    (func (export "splat_i16x8") (param $src i32)
    229      (v128.store (i32.const 0) (i16x8.splat (local.get $src))))
    230    (func (export "csplat_i16x8")
    231      (v128.store (i32.const 0) (i16x8.splat (i32.const 1175))))
    232    (func (export "splat_i32x4") (param $src i32)
    233      (v128.store (i32.const 0) (i32x4.splat (local.get $src))))
    234    (func (export "csplat_i32x4")
    235      (v128.store (i32.const 0) (i32x4.splat (i32.const 127639))))
    236    (func (export "splat_i64x2") (param $src i64)
    237      (v128.store (i32.const 0) (i64x2.splat (local.get $src))))
    238    (func (export "csplat_i64x2")
    239      (v128.store (i32.const 0) (i64x2.splat (i64.const 0x1234_5678_4365))))
    240    (func (export "splat_f32x4") (param $src f32)
    241      (v128.store (i32.const 0) (f32x4.splat (local.get $src))))
    242    (func (export "csplat_f32x4")
    243      (v128.store (i32.const 0) (f32x4.splat (f32.const 9121.25))))
    244    (func (export "splat_f64x2") (param $src f64)
    245      (v128.store (i32.const 0) (f64x2.splat (local.get $src))))
    246    (func (export "csplat_f64x2")
    247      (v128.store (i32.const 0) (f64x2.splat (f64.const 26789.125))))
    248 )`);
    249 
    250 var mem8 = new Uint8Array(ins.exports.mem.buffer);
    251 ins.exports.splat_i8x16(3);
    252 assertSame(get(mem8, 0, 16), iota(16).map(_=>3));
    253 ins.exports.csplat_i8x16();
    254 assertSame(get(mem8, 0, 16), iota(16).map(_=>37));
    255 
    256 var mem16 = new Uint16Array(ins.exports.mem.buffer);
    257 ins.exports.splat_i16x8(976);
    258 assertSame(get(mem16, 0, 8), iota(8).map(_=>976));
    259 ins.exports.csplat_i16x8();
    260 assertSame(get(mem16, 0, 8), iota(8).map(_=>1175));
    261 
    262 var mem32 = new Uint32Array(ins.exports.mem.buffer);
    263 ins.exports.splat_i32x4(147812);
    264 assertSame(get(mem32, 0, 4), [147812, 147812, 147812, 147812]);
    265 ins.exports.csplat_i32x4();
    266 assertSame(get(mem32, 0, 4), [127639, 127639, 127639, 127639]);
    267 
    268 var mem64 = new BigInt64Array(ins.exports.mem.buffer);
    269 ins.exports.splat_i64x2(147812n);
    270 assertSame(get(mem64, 0, 2), [147812, 147812]);
    271 ins.exports.csplat_i64x2();
    272 assertSame(get(mem64, 0, 2), [0x1234_5678_4365n, 0x1234_5678_4365n]);
    273 
    274 var memf32 = new Float32Array(ins.exports.mem.buffer);
    275 ins.exports.splat_f32x4(147812.5);
    276 assertSame(get(memf32, 0, 4), [147812.5, 147812.5, 147812.5, 147812.5]);
    277 ins.exports.csplat_f32x4();
    278 assertSame(get(memf32, 0, 4), [9121.25, 9121.25, 9121.25, 9121.25]);
    279 
    280 var memf64 = new Float64Array(ins.exports.mem.buffer);
    281 ins.exports.splat_f64x2(147812.5);
    282 assertSame(get(memf64, 0, 2), [147812.5, 147812.5]);
    283 ins.exports.csplat_f64x2();
    284 assertSame(get(memf64, 0, 2), [26789.125, 26789.125]);
    285 
    286 // AnyTrue.  Ion constant folds, so test that too.
    287 
    288 var ins = wasmEvalText(`
    289  (module
    290    (memory (export "mem") 1 1)
    291    (func (export "anytrue_i8x16") (result i32)
    292      (v128.any_true (v128.load (i32.const 16))))
    293    (func (export "true_anytrue_i8x16") (result i32)
    294      (v128.any_true (v128.const i8x16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0)))
    295    (func (export "false_anytrue_i8x16") (result i32)
    296      (v128.any_true (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0))))`);
    297 
    298 var mem = new Uint8Array(ins.exports.mem.buffer);
    299 set(mem, 16, iota(16).map((_) => 0));
    300 assertEq(ins.exports.anytrue_i8x16(), 0);
    301 
    302 for ( let dope of [1, 7, 32, 195 ] ) {
    303    set(mem, 16, iota(16).map((x) => x == 7 ? dope : 0));
    304    assertEq(ins.exports.anytrue_i8x16(), 1);
    305 }
    306 
    307 assertEq(ins.exports.true_anytrue_i8x16(), 1);
    308 assertEq(ins.exports.false_anytrue_i8x16(), 0);
    309 
    310 // AllTrue.  Ion constant folds, so test that too.
    311 
    312 var ins = wasmEvalText(`
    313  (module
    314    (memory (export "mem") 1 1)
    315    (func (export "alltrue_i8x16") (result i32)
    316      (i8x16.all_true (v128.load (i32.const 16))))
    317    (func (export "true_alltrue_i8x16") (result i32)
    318      (i8x16.all_true (v128.const i8x16 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16)))
    319    (func (export "false_alltrue_i8x16") (result i32)
    320      (i8x16.all_true (v128.const i8x16 1 2 3 4 5 6 0 8 9 10 11 12 13 14 15 16)))
    321    (func (export "alltrue_i16x8") (result i32)
    322      (i16x8.all_true (v128.load (i32.const 16))))
    323    (func (export "true_alltrue_i16x8") (result i32)
    324      (i16x8.all_true (v128.const i16x8 1 2 3 4 5 6 7 8)))
    325    (func (export "false_alltrue_i16x8") (result i32)
    326      (i16x8.all_true (v128.const i16x8 1 2 3 4 5 0 7 8)))
    327    (func (export "alltrue_i32x4") (result i32)
    328      (i32x4.all_true (v128.load (i32.const 16))))
    329    (func (export "true_alltrue_i32x4") (result i32)
    330      (i32x4.all_true (v128.const i32x4 1 2 3 4)))
    331    (func (export "false_alltrue_i32x4") (result i32)
    332      (i32x4.all_true (v128.const i32x4 1 2 3 0))))`);
    333 
    334 var mem8 = new Uint8Array(ins.exports.mem.buffer);
    335 var mem16 = new Uint16Array(ins.exports.mem.buffer);
    336 var mem32 = new Uint32Array(ins.exports.mem.buffer);
    337 
    338 set(mem8, 16, iota(16).map((_) => 0));
    339 assertEq(ins.exports.alltrue_i8x16(), 0);
    340 assertEq(ins.exports.alltrue_i16x8(), 0);
    341 assertEq(ins.exports.alltrue_i32x4(), 0);
    342 
    343 set(mem8, 16, iota(16).map((_) => 1));
    344 assertEq(ins.exports.alltrue_i8x16(), 1);
    345 
    346 set(mem16, 8, iota(8).map((_) => 1));
    347 assertEq(ins.exports.alltrue_i16x8(), 1);
    348 
    349 set(mem32, 4, iota(4).map((_) => 1));
    350 assertEq(ins.exports.alltrue_i32x4(), 1);
    351 
    352 for ( let dope of [1, 7, 32, 195 ] ) {
    353    set(mem8, 16, iota(16).map((x) => x == 7 ? 0 : dope));
    354    assertEq(ins.exports.alltrue_i8x16(), 0);
    355 
    356    set(mem16, 8, iota(8).map((x) => x == 4 ? 0 : dope));
    357    assertEq(ins.exports.alltrue_i16x8(), 0);
    358 
    359    set(mem32, 4, iota(4).map((x) => x == 2 ? 0 : dope));
    360    assertEq(ins.exports.alltrue_i32x4(), 0);
    361 }
    362 
    363 assertEq(ins.exports.true_alltrue_i8x16(), 1);
    364 assertEq(ins.exports.false_alltrue_i8x16(), 0);
    365 assertEq(ins.exports.true_alltrue_i16x8(), 1);
    366 assertEq(ins.exports.false_alltrue_i16x8(), 0);
    367 assertEq(ins.exports.true_alltrue_i32x4(), 1);
    368 assertEq(ins.exports.false_alltrue_i32x4(), 0);
    369 
    370 // Bitmask.  Ion constant folds, so test that too.
    371 
    372 var ins = wasmEvalText(`
    373  (module
    374    (memory (export "mem") 1 1)
    375    (func (export "bitmask_i8x16") (result i32)
    376      (i8x16.bitmask (v128.load (i32.const 16))))
    377    (func (export "const_bitmask_i8x16") (result i32)
    378      (i8x16.bitmask (v128.const i8x16 0x80 0x7f 0xff 0x33 0x42 0x98 0x01 0x00
    379                                       0x31 0xcc 0xdd 0x12 0xf0 0x40 0x02 0xa0)))
    380    (func (export "bitmask_i16x8") (result i32)
    381      (i16x8.bitmask (v128.load (i32.const 16))))
    382    (func (export "const_bitmask_i16x8") (result i32)
    383      (i16x8.bitmask (v128.const i16x8 0x7f80 0xff33 0x9842 0x0001 0xcc31 0x12dd 0x40f0 0xa002)))
    384    (func (export "bitmask_i32x4") (result i32)
    385      (i32x4.bitmask (v128.load (i32.const 16))))
    386    (func (export "const_bitmask_i32x4") (result i32)
    387      (i32x4.bitmask (v128.const i32x4 0xff337f80 0x00019842 0xcc3112dd 0xa00240f0))))`);
    388 
    389 var mem8 = new Uint8Array(ins.exports.mem.buffer);
    390 var mem16 = new Uint16Array(ins.exports.mem.buffer);
    391 var mem32 = new Uint32Array(ins.exports.mem.buffer);
    392 
    393 set(mem8, 16, iota(16).map((_) => 0));
    394 assertEq(ins.exports.bitmask_i8x16(), 0);
    395 assertEq(ins.exports.bitmask_i16x8(), 0);
    396 assertEq(ins.exports.bitmask_i32x4(), 0);
    397 
    398 set(mem8, 16, iota(16).map((_) => 0x80));
    399 assertEq(ins.exports.bitmask_i8x16(), 0xFFFF);
    400 
    401 set(mem8, 16, iota(16).map((_) => 0x7F));
    402 assertEq(ins.exports.bitmask_i8x16(), 0);
    403 
    404 set(mem8, 16, iota(16).map((i) => popcount(i) == 1 ? 0x80 : 0));
    405 assertEq(ins.exports.bitmask_i8x16(), (1 << 1) | (1 << 2) | (1 << 4) | (1 << 8));
    406 
    407 assertEq(ins.exports.const_bitmask_i8x16(), 0x9625);
    408 
    409 set(mem16, 8, iota(8).map((i) => 0x8000))
    410 assertEq(ins.exports.bitmask_i16x8(), 0xFF)
    411 
    412 set(mem16, 8, iota(8).map((i) => 0x7FFF))
    413 assertEq(ins.exports.bitmask_i16x8(), 0)
    414 
    415 set(mem16, 8, iota(8).map((i) => popcount(i) == 1 ? 0x8000 : 0))
    416 assertEq(ins.exports.bitmask_i16x8(), (1 << 1) | (1 << 2) | (1 << 4));
    417 
    418 assertEq(ins.exports.const_bitmask_i16x8(), 0x96);
    419 
    420 set(mem32, 4, iota(4).map((_) => 0x80000000))
    421 assertEq(ins.exports.bitmask_i32x4(), 0xF);
    422 
    423 set(mem32, 4, iota(4).map((_) => 0x7FFFFFFF))
    424 assertEq(ins.exports.bitmask_i32x4(), 0);
    425 
    426 set(mem32, 4, iota(4).map((i) => popcount(i) == 1 ? 0x80000000 : 0))
    427 assertEq(ins.exports.bitmask_i32x4(), (1 << 1) | (1 << 2));
    428 
    429 assertEq(ins.exports.const_bitmask_i32x4(), 0xd);
    430 
    431 // Shifts
    432 //
    433 // lhs is v128 in memory
    434 // rhs is i32 (passed directly)
    435 // result is v128 in memory
    436 
    437 function shr(count, width) {
    438    return (v) => {
    439        if (count == 0)
    440            return v;
    441        if (width == 64) {
    442            if (v < 0) {
    443                // This basically mirrors what the SIMD code does, so if there's
    444                // a bug there then there's a bug here too.  Seems OK though.
    445                let s = 0x1_0000_0000_0000_0000n + BigInt(v);
    446                let t = s / (1n << BigInt(count));
    447                let u = ((1n << BigInt(count)) - 1n) * (2n ** BigInt(64-count));
    448                let w = t + u;
    449                return w - 0x1_0000_0000_0000_0000n;
    450            }
    451            return BigInt(v) / (1n << BigInt(count));
    452        } else {
    453            let mask = (width == 32) ? -1 : ((1 << width) - 1);
    454            return (sign_extend(v, width) >> count) & mask;
    455        }
    456    }
    457 }
    458 
    459 function shru(count, width) {
    460    if (width == 64) {
    461        return (v) => {
    462            if (count == 0)
    463                return v;
    464            if (v < 0) {
    465                v = 0x1_0000_0000_0000_0000n + BigInt(v);
    466            }
    467            return BigInt(v) / (1n << BigInt(count));
    468        }
    469    } else {
    470        return (v) => {
    471            let mask = (width == 32) ? -1 : ((1 << width) - 1);
    472            return (v >>> count) & mask;
    473        }
    474    }
    475 }
    476 
    477 var constantI8Shifts = "";
    478 for ( let i of iota(10).concat([-7]) ) {
    479    constantI8Shifts += `
    480    (func (export "shl_i8x16_${i}")
    481      (v128.store (i32.const 0) (i8x16.shl (v128.load (i32.const 16)) (i32.const ${i}))))
    482    (func (export "shr_i8x16_${i}")
    483      (v128.store (i32.const 0) (i8x16.shr_s (v128.load (i32.const 16)) (i32.const ${i}))))
    484    (func (export "shr_u8x16_${i}")
    485      (v128.store (i32.const 0) (i8x16.shr_u (v128.load (i32.const 16)) (i32.const ${i}))))`;
    486 }
    487 
    488 var ins = wasmEvalText(`
    489  (module
    490    (memory (export "mem") 1 1)
    491    (func (export "shl_i8x16") (param $count i32)
    492      (v128.store (i32.const 0) (i8x16.shl (v128.load (i32.const 16)) (local.get $count))))
    493    (func (export "shr_i8x16") (param $count i32)
    494      (v128.store (i32.const 0) (i8x16.shr_s (v128.load (i32.const 16)) (local.get $count))))
    495    (func (export "shr_u8x16") (param $count i32)
    496      (v128.store (i32.const 0) (i8x16.shr_u (v128.load (i32.const 16)) (local.get $count))))
    497    ${constantI8Shifts}
    498    (func (export "shl_i16x8") (param $count i32)
    499      (v128.store (i32.const 0) (i16x8.shl (v128.load (i32.const 16)) (local.get $count))))
    500    (func (export "shl_i16x8_3")
    501      (v128.store (i32.const 0) (i16x8.shl (v128.load (i32.const 16)) (i32.const 3))))
    502    (func (export "shl_i16x8_15")
    503      (v128.store (i32.const 0) (i16x8.shl (v128.load (i32.const 16)) (i32.const 15))))
    504    (func (export "shl_i16x8_16")
    505      (v128.store (i32.const 0) (i16x8.shl (v128.load (i32.const 16)) (i32.const 16))))
    506    (func (export "shl_i16x8_-15")
    507      (v128.store (i32.const 0) (i16x8.shl (v128.load (i32.const 16)) (i32.const -15))))
    508    (func (export "shr_i16x8") (param $count i32)
    509      (v128.store (i32.const 0) (i16x8.shr_s (v128.load (i32.const 16)) (local.get $count))))
    510    (func (export "shr_i16x8_3")
    511      (v128.store (i32.const 0) (i16x8.shr_s (v128.load (i32.const 16)) (i32.const 3))))
    512    (func (export "shr_i16x8_15")
    513      (v128.store (i32.const 0) (i16x8.shr_s (v128.load (i32.const 16)) (i32.const 15))))
    514    (func (export "shr_i16x8_16")
    515      (v128.store (i32.const 0) (i16x8.shr_s (v128.load (i32.const 16)) (i32.const 16))))
    516    (func (export "shr_i16x8_-15")
    517      (v128.store (i32.const 0) (i16x8.shr_s (v128.load (i32.const 16)) (i32.const -15))))
    518    (func (export "shr_u16x8") (param $count i32)
    519      (v128.store (i32.const 0) (i16x8.shr_u (v128.load (i32.const 16)) (local.get $count))))
    520    (func (export "shr_u16x8_3")
    521      (v128.store (i32.const 0) (i16x8.shr_u (v128.load (i32.const 16)) (i32.const 3))))
    522    (func (export "shr_u16x8_15")
    523      (v128.store (i32.const 0) (i16x8.shr_u (v128.load (i32.const 16)) (i32.const 15))))
    524    (func (export "shr_u16x8_16")
    525      (v128.store (i32.const 0) (i16x8.shr_u (v128.load (i32.const 16)) (i32.const 16))))
    526    (func (export "shr_u16x8_-15")
    527      (v128.store (i32.const 0) (i16x8.shr_u (v128.load (i32.const 16)) (i32.const -15))))
    528    (func (export "shl_i32x4") (param $count i32)
    529      (v128.store (i32.const 0) (i32x4.shl (v128.load (i32.const 16)) (local.get $count))))
    530    (func (export "shl_i32x4_12")
    531      (v128.store (i32.const 0) (i32x4.shl (v128.load (i32.const 16)) (i32.const 12))))
    532    (func (export "shl_i32x4_31")
    533      (v128.store (i32.const 0) (i32x4.shl (v128.load (i32.const 16)) (i32.const 31))))
    534    (func (export "shl_i32x4_32")
    535      (v128.store (i32.const 0) (i32x4.shl (v128.load (i32.const 16)) (i32.const 32))))
    536    (func (export "shl_i32x4_-27")
    537      (v128.store (i32.const 0) (i32x4.shl (v128.load (i32.const 16)) (i32.const -27))))
    538    (func (export "shr_i32x4") (param $count i32)
    539      (v128.store (i32.const 0) (i32x4.shr_s (v128.load (i32.const 16)) (local.get $count))))
    540    (func (export "shr_i32x4_12")
    541      (v128.store (i32.const 0) (i32x4.shr_s (v128.load (i32.const 16)) (i32.const 12))))
    542    (func (export "shr_i32x4_31")
    543      (v128.store (i32.const 0) (i32x4.shr_s (v128.load (i32.const 16)) (i32.const 31))))
    544    (func (export "shr_i32x4_32")
    545      (v128.store (i32.const 0) (i32x4.shr_s (v128.load (i32.const 16)) (i32.const 32))))
    546    (func (export "shr_i32x4_-27")
    547      (v128.store (i32.const 0) (i32x4.shr_s (v128.load (i32.const 16)) (i32.const -27))))
    548    (func (export "shr_u32x4") (param $count i32)
    549      (v128.store (i32.const 0) (i32x4.shr_u (v128.load (i32.const 16)) (local.get $count))))
    550    (func (export "shr_u32x4_12")
    551      (v128.store (i32.const 0) (i32x4.shr_u (v128.load (i32.const 16)) (i32.const 12))))
    552    (func (export "shr_u32x4_31")
    553      (v128.store (i32.const 0) (i32x4.shr_u (v128.load (i32.const 16)) (i32.const 31))))
    554    (func (export "shr_u32x4_32")
    555      (v128.store (i32.const 0) (i32x4.shr_u (v128.load (i32.const 16)) (i32.const 32))))
    556    (func (export "shr_u32x4_-27")
    557      (v128.store (i32.const 0) (i32x4.shr_u (v128.load (i32.const 16)) (i32.const -27))))
    558    (func (export "shl_i64x2") (param $count i32)
    559      (v128.store (i32.const 0) (i64x2.shl (v128.load (i32.const 16)) (local.get $count))))
    560    (func (export "shl_i64x2_27")
    561      (v128.store (i32.const 0) (i64x2.shl (v128.load (i32.const 16)) (i32.const 27))))
    562    (func (export "shl_i64x2_63")
    563      (v128.store (i32.const 0) (i64x2.shl (v128.load (i32.const 16)) (i32.const 63))))
    564    (func (export "shl_i64x2_64")
    565      (v128.store (i32.const 0) (i64x2.shl (v128.load (i32.const 16)) (i32.const 64))))
    566    (func (export "shl_i64x2_-231")
    567      (v128.store (i32.const 0) (i64x2.shl (v128.load (i32.const 16)) (i32.const -231))))
    568    (func (export "shr_i64x2") (param $count i32)
    569      (v128.store (i32.const 0) (i64x2.shr_s (v128.load (i32.const 16)) (local.get $count))))
    570    (func (export "shr_i64x2_27")
    571      (v128.store (i32.const 0) (i64x2.shr_s (v128.load (i32.const 16)) (i32.const 27))))
    572    (func (export "shr_i64x2_45")
    573      (v128.store (i32.const 0) (i64x2.shr_s (v128.load (i32.const 16)) (i32.const 45))))
    574    (func (export "shr_i64x2_63")
    575      (v128.store (i32.const 0) (i64x2.shr_s (v128.load (i32.const 16)) (i32.const 63))))
    576    (func (export "shr_i64x2_64")
    577      (v128.store (i32.const 0) (i64x2.shr_s (v128.load (i32.const 16)) (i32.const 64))))
    578    (func (export "shr_i64x2_-231")
    579      (v128.store (i32.const 0) (i64x2.shr_s (v128.load (i32.const 16)) (i32.const -231))))
    580    (func (export "shr_i64x2_-1")
    581      (v128.store (i32.const 0) (i64x2.shr_s (v128.load (i32.const 16)) (i32.const -1))))
    582    (func (export "shr_u64x2") (param $count i32)
    583      (v128.store (i32.const 0) (i64x2.shr_u (v128.load (i32.const 16)) (local.get $count))))
    584    (func (export "shr_u64x2_27")
    585      (v128.store (i32.const 0) (i64x2.shr_u (v128.load (i32.const 16)) (i32.const 27))))
    586    (func (export "shr_u64x2_63")
    587      (v128.store (i32.const 0) (i64x2.shr_u (v128.load (i32.const 16)) (i32.const 63))))
    588    (func (export "shr_u64x2_64")
    589      (v128.store (i32.const 0) (i64x2.shr_u (v128.load (i32.const 16)) (i32.const 64))))
    590    (func (export "shr_u64x2_-231")
    591      (v128.store (i32.const 0) (i64x2.shr_u (v128.load (i32.const 16)) (i32.const -231)))))`);
    592 
    593 var mem8 = new Uint8Array(ins.exports.mem.buffer);
    594 var as = [1, 2, 4, 8, 16, 32, 64, 128, 129, 130, 132, 136, 144, 160, 192, 255];
    595 
    596 set(mem8, 16, as);
    597 
    598 for (let [meth,op] of [["shl_i8x16",shl], ["shr_i8x16",shr], ["shr_u8x16",shru]]) {
    599    for ( let i=0 ; i < 8 ; i++ ) {
    600        ins.exports[meth](i);
    601        assertSame(get(mem8, 0, 16), as.map(op(i, 8)))
    602        ins.exports[meth + "_" + i]();
    603        assertSame(get(mem8, 0, 16), as.map(op(i, 8)))
    604    }
    605 
    606    ins.exports[meth](1);
    607    let a = get(mem8, 0, 16);
    608    ins.exports[meth](9);
    609    let b = get(mem8, 0, 16);
    610    assertSame(a, b);
    611    ins.exports[meth](-7);
    612    let c = get(mem8, 0, 16);
    613    assertSame(a, c);
    614 
    615    ins.exports[meth + "_1"]();
    616    let x = get(mem8, 0, 16);
    617    ins.exports[meth + "_9"]();
    618    let y = get(mem8, 0, 16);
    619    ins.exports[meth + "_-7"]();
    620    let z = get(mem8, 0, 16);
    621    assertSame(x, y);
    622    assertSame(x, z);
    623 }
    624 
    625 var mem16 = new Uint16Array(ins.exports.mem.buffer);
    626 var as = [1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000];
    627 set(mem16, 8, as)
    628 
    629 ins.exports.shl_i16x8(2);
    630 var res = get(mem16, 0, 8);
    631 assertSame(res, as.map(shl(2, 16)))
    632 
    633 ins.exports.shl_i16x8(18);      // Masked count
    634 assertSame(get(mem16, 0, 8), res);
    635 
    636 ins.exports.shl_i16x8(-14);      // Masked count
    637 assertSame(get(mem16, 0, 8), res);
    638 
    639 for ( let shift of [3, 15, 16, -15] ) {
    640    ins.exports["shl_i16x8_" + shift]();
    641    assertSame(get(mem16, 0, 8), as.map(shl(shift & 15, 16)))
    642 }
    643 
    644 ins.exports.shr_i16x8(1);
    645 var res = get(mem16, 0, 8);
    646 assertSame(res, as.map(shr(1, 16)))
    647 
    648 ins.exports.shr_i16x8(17);      // Masked count
    649 assertSame(get(mem16, 0, 8), res);
    650 
    651 ins.exports.shr_i16x8(-15);      // Masked count
    652 assertSame(get(mem16, 0, 8), res);
    653 
    654 for ( let shift of [3, 15, 16, -15] ) {
    655    ins.exports["shr_i16x8_" + shift]();
    656    assertSame(get(mem16, 0, 8), as.map(shr(shift & 15, 16)))
    657 }
    658 
    659 ins.exports.shr_u16x8(1);
    660 var res = get(mem16, 0, 8);
    661 assertSame(res, as.map(shru(1, 16)))
    662 
    663 ins.exports.shr_u16x8(17);      // Masked count
    664 assertSame(get(mem16, 0, 8), res);
    665 
    666 ins.exports.shr_u16x8(-15);      // Masked count
    667 assertSame(get(mem16, 0, 8), res);
    668 
    669 for ( let shift of [3, 15, 16, -15] ) {
    670    ins.exports["shr_u16x8_" + shift]();
    671    assertSame(get(mem16, 0, 8), as.map(shru(shift & 15, 16)))
    672 }
    673 
    674 var mem32 = new Uint32Array(ins.exports.mem.buffer);
    675 var as = [5152, 6768, 7074, 800811];
    676 
    677 set(mem32, 4, as)
    678 ins.exports.shl_i32x4(2);
    679 var res = get(mem32, 0, 4);
    680 assertSame(res, as.map(shl(2, 32)))
    681 
    682 ins.exports.shl_i32x4(34);      // Masked count
    683 assertSame(get(mem32, 0, 4), res);
    684 
    685 ins.exports.shl_i32x4(-30);      // Masked count
    686 assertSame(get(mem32, 0, 4), res);
    687 
    688 for ( let shift of [12, 31, 32, -27] ) {
    689    ins.exports["shl_i32x4_" + shift]();
    690    assertSame(get(mem32, 0, 4), as.map(shl(shift & 31, 32)).map(x => x>>>0))
    691 }
    692 
    693 ins.exports.shr_i32x4(1);
    694 var res = get(mem32, 0, 4);
    695 assertSame(res, as.map(shr(1, 32)))
    696 
    697 ins.exports.shr_i32x4(33);      // Masked count
    698 assertSame(get(mem32, 0, 4), res);
    699 
    700 ins.exports.shr_i32x4(-31);      // Masked count
    701 assertSame(get(mem32, 0, 4), res);
    702 
    703 for ( let shift of [12, 31, 32, -27] ) {
    704    ins.exports["shr_i32x4_" + shift]();
    705    assertSame(get(mem32, 0, 4), as.map(shr(shift & 31, 32)))
    706 }
    707 
    708 ins.exports.shr_u32x4(1);
    709 var res = get(mem32, 0, 4);
    710 assertSame(res, as.map(shru(1, 32)))
    711 
    712 ins.exports.shr_u32x4(33);      // Masked count
    713 assertSame(get(mem32, 0, 4), res);
    714 
    715 ins.exports.shr_u32x4(-31);      // Masked count
    716 assertSame(get(mem32, 0, 4), res);
    717 
    718 for ( let shift of [12, 31, 32, -27] ) {
    719    ins.exports["shr_u32x4_" + shift]();
    720    assertSame(get(mem32, 0, 4), as.map(shru(shift & 31, 32)))
    721 }
    722 
    723 var mem64 = new BigInt64Array(ins.exports.mem.buffer);
    724 var as = [50515253, -616263];
    725 
    726 set(mem64, 2, as)
    727 ins.exports.shl_i64x2(2);
    728 var res = get(mem64, 0, 2);
    729 assertSame(res, as.map(shl(2, 64)))
    730 
    731 ins.exports.shl_i64x2(66);      // Masked count
    732 assertSame(get(mem64, 0, 2), res);
    733 
    734 ins.exports.shl_i64x2(-62);      // Masked count
    735 assertSame(get(mem64, 0, 2), res);
    736 
    737 for ( let shift of [27, 63, 64, -231] ) {
    738    ins.exports["shl_i64x2_" + shift]();
    739    assertSame(get(mem64, 0, 2), as.map(shl(shift & 63, 64)))
    740 }
    741 
    742 ins.exports.shr_u64x2(1);
    743 var res = get(mem64, 0, 2);
    744 assertSame(res, as.map(shru(1, 64)))
    745 
    746 ins.exports.shr_u64x2(65);      // Masked count
    747 assertSame(get(mem64, 0, 2), res);
    748 
    749 ins.exports.shr_u64x2(-63);      // Masked count
    750 assertSame(get(mem64, 0, 2), res);
    751 
    752 for ( let shift of [27, 63, 64, -231] ) {
    753    ins.exports["shr_u64x2_" + shift]();
    754    assertSame(get(mem64, 0, 2), as.map(shru(shift & 63, 64)))
    755 }
    756 
    757 ins.exports.shr_i64x2(2);
    758 var res = get(mem64, 0, 2);
    759 assertSame(res, as.map(shr(2, 64)))
    760 
    761 ins.exports.shr_i64x2(66);      // Masked count
    762 assertSame(get(mem64, 0, 2), res);
    763 
    764 ins.exports.shr_i64x2(-62);      // Masked count
    765 assertSame(get(mem64, 0, 2), res);
    766 
    767 // The ion code generator has multiple paths here, for < 32 and >= 32
    768 for ( let shift of [27, 45, 63, 64, -1, -231] ) {
    769    ins.exports["shr_i64x2_" + shift]();
    770    assertSame(get(mem64, 0, 2), as.map(shr(shift & 63, 64)))
    771 }
    772 
    773 // Narrow
    774 
    775 var ins = wasmEvalText(`
    776  (module
    777    (memory (export "mem") 1 1)
    778    (func (export "narrow_i16x8_s")
    779      (v128.store (i32.const 0) (i8x16.narrow_i16x8_s (v128.load (i32.const 16)) (v128.load (i32.const 32)))))
    780    (func (export "narrow_i16x8_u")
    781      (v128.store (i32.const 0) (i8x16.narrow_i16x8_u (v128.load (i32.const 16)) (v128.load (i32.const 32)))))
    782    (func (export "narrow_i32x4_s")
    783      (v128.store (i32.const 0) (i16x8.narrow_i32x4_s (v128.load (i32.const 16)) (v128.load (i32.const 32)))))
    784    (func (export "narrow_i32x4_u")
    785      (v128.store (i32.const 0) (i16x8.narrow_i32x4_u (v128.load (i32.const 16)) (v128.load (i32.const 32))))))`);
    786 
    787 var mem8 = new Int8Array(ins.exports.mem.buffer);
    788 var mem8u = new Uint8Array(ins.exports.mem.buffer);
    789 var mem16 = new Int16Array(ins.exports.mem.buffer);
    790 var mem16u = new Uint16Array(ins.exports.mem.buffer);
    791 var mem32 = new Int32Array(ins.exports.mem.buffer);
    792 
    793 var as = [1, 267, 3987, 14523, 32768, 3, 312, 4876].map((x) => sign_extend(x, 16));
    794 var bs = [2, 312, 4876, 15987, 33777, 1, 267, 3987].map((x) => sign_extend(x, 16));
    795 
    796 set(mem16, 8, as);
    797 set(mem16, 16, bs);
    798 
    799 ins.exports.narrow_i16x8_s();
    800 var cs = as.concat(...bs).map((x) => signed_saturate(x, 8));
    801 assertSame(get(mem8, 0, 16), cs);
    802 
    803 ins.exports.narrow_i16x8_u();
    804 var cs = as.concat(...bs).map((x) => unsigned_saturate(x, 8));
    805 assertSame(get(mem8u, 0, 16), cs);
    806 
    807 var xs = [1, 3987, 14523, 32768].map((x) => x << 16).map((x) => sign_extend(x, 32));
    808 var ys = [2, 4876, 15987, 33777].map((x) => x << 16).map((x) => sign_extend(x, 32));
    809 
    810 set(mem32, 4, xs);
    811 set(mem32, 8, ys);
    812 
    813 ins.exports.narrow_i32x4_s();
    814 var cs = xs.concat(...ys).map((x) => signed_saturate(x, 16));
    815 assertSame(get(mem16, 0, 8), cs);
    816 
    817 ins.exports.narrow_i32x4_u();
    818 var cs = xs.concat(...ys).map((x) => unsigned_saturate(x, 16));
    819 assertSame(get(mem16u, 0, 8), cs);
    820 
    821 // Extend low/high
    822 
    823 var ins = wasmEvalText(`
    824  (module
    825    (memory (export "mem") 1 1)
    826    (func (export "extend_low_i8x16_s")
    827      (v128.store (i32.const 0) (i16x8.extend_low_i8x16_s (v128.load (i32.const 16)))))
    828    (func (export "extend_high_i8x16_s")
    829      (v128.store (i32.const 0) (i16x8.extend_high_i8x16_s (v128.load (i32.const 16)))))
    830    (func (export "extend_low_i8x16_u")
    831      (v128.store (i32.const 0) (i16x8.extend_low_i8x16_u (v128.load (i32.const 16)))))
    832    (func (export "extend_high_i8x16_u")
    833      (v128.store (i32.const 0) (i16x8.extend_high_i8x16_u (v128.load (i32.const 16)))))
    834    (func (export "extend_low_i16x8_s")
    835      (v128.store (i32.const 0) (i32x4.extend_low_i16x8_s (v128.load (i32.const 16)))))
    836    (func (export "extend_high_i16x8_s")
    837      (v128.store (i32.const 0) (i32x4.extend_high_i16x8_s (v128.load (i32.const 16)))))
    838    (func (export "extend_low_i16x8_u")
    839      (v128.store (i32.const 0) (i32x4.extend_low_i16x8_u (v128.load (i32.const 16)))))
    840    (func (export "extend_high_i16x8_u")
    841      (v128.store (i32.const 0) (i32x4.extend_high_i16x8_u (v128.load (i32.const 16))))))`);
    842 
    843 var mem16 = new Int16Array(ins.exports.mem.buffer);
    844 var mem16u = new Uint16Array(ins.exports.mem.buffer);
    845 var mem8 =  new Int8Array(ins.exports.mem.buffer);
    846 var as = [0, 1, 192, 3, 205, 5, 6, 133, 8, 9, 129, 11, 201, 13, 14, 255];
    847 
    848 set(mem8, 16, as);
    849 
    850 ins.exports.extend_low_i8x16_s();
    851 assertSame(get(mem16, 0, 8), iota(8).map((n) => sign_extend(as[n], 8)));
    852 
    853 ins.exports.extend_high_i8x16_s();
    854 assertSame(get(mem16, 0, 8), iota(8).map((n) => sign_extend(as[n+8], 8)));
    855 
    856 ins.exports.extend_low_i8x16_u();
    857 assertSame(get(mem16u, 0, 8), iota(8).map((n) => zero_extend(as[n], 8)));
    858 
    859 ins.exports.extend_high_i8x16_u();
    860 assertSame(get(mem16u, 0, 8), iota(8).map((n) => zero_extend(as[n+8], 8)));
    861 
    862 var mem32 = new Int32Array(ins.exports.mem.buffer);
    863 var mem32u = new Uint32Array(ins.exports.mem.buffer);
    864 
    865 var as = [0, 1, 192, 3, 205, 5, 6, 133].map((x) => x << 8);
    866 
    867 set(mem16, 8, as);
    868 
    869 ins.exports.extend_low_i16x8_s();
    870 assertSame(get(mem32, 0, 4), iota(4).map((n) => sign_extend(as[n], 16)));
    871 
    872 ins.exports.extend_high_i16x8_s();
    873 assertSame(get(mem32, 0, 4), iota(4).map((n) => sign_extend(as[n+4], 16)));
    874 
    875 ins.exports.extend_low_i16x8_u();
    876 assertSame(get(mem32u, 0, 4), iota(4).map((n) => zero_extend(as[n], 16)));
    877 
    878 ins.exports.extend_high_i16x8_u();
    879 assertSame(get(mem32u, 0, 4), iota(4).map((n) => zero_extend(as[n+4], 16)));
    880 
    881 
    882 // Extract lane.  Ion constant folds, so test that too.
    883 //
    884 // operand is v128 in memory (or constant)
    885 // lane index is immediate so we're testing something randomish but not zero
    886 // result is scalar (returned directly)
    887 
    888 var ins = wasmEvalText(`
    889  (module
    890    (memory (export "mem") 1 1)
    891    (func (export "extract_i8x16_9") (result i32)
    892      (i8x16.extract_lane_s 9 (v128.load (i32.const 16))))
    893    (func (export "const_extract_i8x16_9") (result i32)
    894      (i8x16.extract_lane_s 9 (v128.const i8x16 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16)))
    895    (func (export "extract_u8x16_6") (result i32)
    896      (i8x16.extract_lane_u 6 (v128.load (i32.const 16))))
    897    (func (export "const_extract_u8x16_9") (result i32)
    898      (i8x16.extract_lane_u 9 (v128.const i8x16 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16)))
    899    (func (export "extract_i16x8_5") (result i32)
    900      (i16x8.extract_lane_s 5 (v128.load (i32.const 16))))
    901    (func (export "const_extract_i16x8_5") (result i32)
    902      (i16x8.extract_lane_s 5 (v128.const i16x8 -1 -2 -3 -4 -5 -6 -7 -8)))
    903    (func (export "extract_u16x8_3") (result i32)
    904      (i16x8.extract_lane_u 3 (v128.load (i32.const 16))))
    905    (func (export "const_extract_u16x8_3") (result i32)
    906      (i16x8.extract_lane_u 3 (v128.const i16x8 -1 -2 -3 -4 -5 -6 -7 -8)))
    907    (func (export "extract_i32x4_2") (result i32)
    908      (i32x4.extract_lane 2 (v128.load (i32.const 16))))
    909    (func (export "const_extract_i32x4_2") (result i32)
    910      (i32x4.extract_lane 2 (v128.const i32x4 -1 -2 -3 -4)))
    911    (func (export "extract_i64x2_1") (result i64)
    912      (i64x2.extract_lane 1 (v128.load (i32.const 16))))
    913    (func (export "const_extract_i64x2_1") (result i64)
    914      (i64x2.extract_lane 1 (v128.const i64x2 -1 -2)))
    915    (func (export "extract_f32x4_2") (result f32)
    916      (f32x4.extract_lane 2 (v128.load (i32.const 16))))
    917    (func (export "const_extract_f32x4_2") (result f32)
    918      (f32x4.extract_lane 2 (v128.const f32x4 -1 -2 -3 -4)))
    919    (func (export "extract_f64x2_1") (result f64)
    920      (f64x2.extract_lane 1 (v128.load (i32.const 16))))
    921    (func (export "const_extract_f64x2_1") (result f64)
    922      (f64x2.extract_lane 1 (v128.const f64x2 -1 -2))))`);
    923 
    924 var mem8 = new Uint8Array(ins.exports.mem.buffer);
    925 var as = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
    926 var bs = as.map((x) => -x);
    927 
    928 set(mem8, 16, as)
    929 assertEq(ins.exports.extract_i8x16_9(), as[9]);
    930 
    931 set(mem8, 16, bs)
    932 assertEq(ins.exports.extract_u8x16_6(), 256 - as[6]);
    933 
    934 assertEq(ins.exports.const_extract_i8x16_9(), -10);
    935 assertEq(ins.exports.const_extract_u8x16_9(), 256-10);
    936 
    937 var mem16 = new Uint16Array(ins.exports.mem.buffer);
    938 var as = [1, 2, 3, 4, 5, 6, 7, 8];
    939 var bs = as.map((x) => -x);
    940 
    941 set(mem16, 8, as)
    942 assertEq(ins.exports.extract_i16x8_5(), as[5]);
    943 
    944 set(mem16, 8, bs)
    945 assertEq(ins.exports.extract_u16x8_3(), 65536 - as[3]);
    946 
    947 assertEq(ins.exports.const_extract_i16x8_5(), -6);
    948 assertEq(ins.exports.const_extract_u16x8_3(), 65536-4);
    949 
    950 var mem32 = new Uint32Array(ins.exports.mem.buffer);
    951 var as = [1, 2, 3, 4];
    952 
    953 set(mem32, 4, as)
    954 assertEq(ins.exports.extract_i32x4_2(), as[2]);
    955 
    956 assertEq(ins.exports.const_extract_i32x4_2(), -3);
    957 
    958 var mem32 = new Float32Array(ins.exports.mem.buffer);
    959 var as = [1.5, 2.5, 3.5, 4.5];
    960 
    961 set(mem32, 4, as)
    962 assertEq(ins.exports.extract_f32x4_2(), as[2]);
    963 
    964 assertEq(ins.exports.const_extract_f32x4_2(), -3);
    965 
    966 var mem64 = new Float64Array(ins.exports.mem.buffer);
    967 var as = [1.5, 2.5];
    968 
    969 set(mem64, 2, as)
    970 assertEq(ins.exports.extract_f64x2_1(), as[1]);
    971 
    972 assertEq(ins.exports.const_extract_f64x2_1(), -2);
    973 
    974 var mem64 = new BigInt64Array(ins.exports.mem.buffer);
    975 var as = [12345, 67890];
    976 
    977 set(mem64, 2, as)
    978 assertSame(ins.exports.extract_i64x2_1(), as[1]);
    979 
    980 assertEq(ins.exports.const_extract_i64x2_1(), -2n);
    981 
    982 // Replace lane
    983 //
    984 // operand 1 is v128 in memory
    985 // operand 2 is immediate scalar
    986 // lane index is immediate so we're testing something randomish but not zero
    987 // (note though that fp operations have special cases for zero)
    988 // result is v128 in memory
    989 
    990 var ins = wasmEvalText(`
    991  (module
    992    (memory (export "mem") 1 1)
    993    (func (export "replace_i8x16_9") (param $value i32)
    994      (v128.store (i32.const 0)
    995        (i8x16.replace_lane 9 (v128.load (i32.const 16)) (local.get $value))))
    996    (func (export "replace_i16x8_5") (param $value i32)
    997      (v128.store (i32.const 0)
    998        (i16x8.replace_lane 5 (v128.load (i32.const 16)) (local.get $value))))
    999    (func (export "replace_i32x4_3") (param $value i32)
   1000      (v128.store (i32.const 0)
   1001        (i32x4.replace_lane 3 (v128.load (i32.const 16)) (local.get $value))))
   1002    (func (export "replace_i64x2_1") (param $value i64)
   1003      (v128.store (i32.const 0)
   1004        (i64x2.replace_lane 1 (v128.load (i32.const 16)) (local.get $value))))
   1005    (func (export "replace_f32x4_0") (param $value f32)
   1006      (v128.store (i32.const 0)
   1007        (f32x4.replace_lane 0 (v128.load (i32.const 16)) (local.get $value))))
   1008    (func (export "replace_f32x4_3") (param $value f32)
   1009      (v128.store (i32.const 0)
   1010        (f32x4.replace_lane 3 (v128.load (i32.const 16)) (local.get $value))))
   1011    (func (export "replace_f64x2_0") (param $value f64)
   1012      (v128.store (i32.const 0)
   1013        (f64x2.replace_lane 0 (v128.load (i32.const 16)) (local.get $value))))
   1014    (func (export "replace_f64x2_1") (param $value f64)
   1015      (v128.store (i32.const 0)
   1016        (f64x2.replace_lane 1 (v128.load (i32.const 16)) (local.get $value)))))`);
   1017 
   1018 
   1019 var mem8 = new Uint8Array(ins.exports.mem.buffer);
   1020 var as = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
   1021 
   1022 set(mem8, 16, as)
   1023 ins.exports.replace_i8x16_9(42);
   1024 assertSame(get(mem8, 0, 16), upd(as, 9, 42));
   1025 
   1026 var mem16 = new Uint16Array(ins.exports.mem.buffer);
   1027 var as = [1, 2, 3, 4, 5, 6, 7, 8];
   1028 
   1029 set(mem16, 8, as)
   1030 ins.exports.replace_i16x8_5(42);
   1031 assertSame(get(mem16, 0, 8), upd(as, 5, 42));
   1032 
   1033 var mem32 = new Uint32Array(ins.exports.mem.buffer);
   1034 var as = [1, 2, 3, 4];
   1035 
   1036 set(mem32, 4, as)
   1037 ins.exports.replace_i32x4_3(42);
   1038 assertSame(get(mem32, 0, 4), upd(as, 3, 42));
   1039 
   1040 var mem64 = new BigInt64Array(ins.exports.mem.buffer);
   1041 var as = [1, 2];
   1042 
   1043 set(mem64, 2, as)
   1044 ins.exports.replace_i64x2_1(42n);
   1045 assertSame(get(mem64, 0, 2), upd(as, 1, 42));
   1046 
   1047 var mem32 = new Float32Array(ins.exports.mem.buffer);
   1048 var as = [1.5, 2.5, 3.5, 4.5];
   1049 
   1050 set(mem32, 4, as)
   1051 ins.exports.replace_f32x4_0(42.5);
   1052 assertSame(get(mem32, 0, 4), upd(as, 0, 42.5));
   1053 
   1054 set(mem32, 4, as)
   1055 ins.exports.replace_f32x4_3(42.5);
   1056 assertSame(get(mem32, 0, 4), upd(as, 3, 42.5));
   1057 
   1058 var mem64 = new Float64Array(ins.exports.mem.buffer);
   1059 var as = [1.5, 2.5];
   1060 
   1061 set(mem64, 2, as)
   1062 ins.exports.replace_f64x2_0(42.5);
   1063 assertSame(get(mem64, 0, 2), upd(as, 0, 42.5));
   1064 
   1065 set(mem64, 2, as)
   1066 ins.exports.replace_f64x2_1(42.5);
   1067 assertSame(get(mem64, 0, 2), upd(as, 1, 42.5));
   1068 
   1069 // Load and splat
   1070 //
   1071 // Operand is memory address of scalar
   1072 // Result is v128 in memory
   1073 
   1074 var ins = wasmEvalText(`
   1075  (module
   1076    (memory (export "mem") 1 1)
   1077    (func (export "load_splat_v8x16") (param $addr i32)
   1078      (v128.store (i32.const 0) (v128.load8_splat (local.get $addr))))
   1079    (func (export "load_splat_v16x8") (param $addr i32)
   1080      (v128.store (i32.const 0) (v128.load16_splat (local.get $addr))))
   1081    (func (export "load_splat_v32x4") (param $addr i32)
   1082      (v128.store (i32.const 0) (v128.load32_splat (local.get $addr))))
   1083    (func (export "load_splat_v64x2") (param $addr i32)
   1084      (v128.store (i32.const 0) (v128.load64_splat (local.get $addr)))))`);
   1085 
   1086 var mem8 = new Uint8Array(ins.exports.mem.buffer);
   1087 mem8[37] = 42;
   1088 ins.exports.load_splat_v8x16(37);
   1089 assertSame(get(mem8, 0, 16), [42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42]);
   1090 
   1091 var mem16 = new Uint16Array(ins.exports.mem.buffer);
   1092 mem16[37] = 69;
   1093 ins.exports.load_splat_v16x8(37*2);
   1094 assertSame(get(mem16, 0, 8), [69, 69, 69, 69, 69, 69, 69, 69]);
   1095 
   1096 var mem32 = new Int32Array(ins.exports.mem.buffer);
   1097 mem32[37] = 83;
   1098 ins.exports.load_splat_v32x4(37*4);
   1099 assertSame(get(mem32, 0, 4), [83, 83, 83, 83]);
   1100 
   1101 var mem64 = new BigInt64Array(ins.exports.mem.buffer);
   1102 mem64[37] = 83n;
   1103 ins.exports.load_splat_v64x2(37*8);
   1104 assertSame(get(mem64, 0, 2), [83, 83]);
   1105 
   1106 // Load and zero
   1107 //
   1108 // Operand is memory address of scalar
   1109 // Result is v128 in memory
   1110 
   1111 var ins = wasmEvalText(`
   1112  (module
   1113    (memory (export "mem") 1 1)
   1114    (func (export "load32_zero") (param $addr i32)
   1115      (v128.store (i32.const 0) (v128.load32_zero (local.get $addr))))
   1116    (func (export "load64_zero") (param $addr i32)
   1117      (v128.store (i32.const 0) (v128.load64_zero (local.get $addr)))))`);
   1118 
   1119 var mem32 = new Int32Array(ins.exports.mem.buffer);
   1120 mem32[37] = 0x12345678;
   1121 mem32[38] = 0xffffffff;
   1122 mem32[39] = 0xfffffffe;
   1123 mem32[40] = 0xfffffffd;
   1124 ins.exports.load32_zero(37*4);
   1125 assertSame(get(mem32, 0, 4), [0x12345678, 0, 0, 0]);
   1126 
   1127 var mem64 = new BigInt64Array(ins.exports.mem.buffer);
   1128 mem64[37] = 0x12345678abcdef01n;
   1129 mem64[38] = 0xffffffffffffffffn;
   1130 ins.exports.load64_zero(37*8);
   1131 assertSame(get(mem64, 0, 2), [0x12345678abcdef01n, 0n]);
   1132 
   1133 // Load and extend
   1134 //
   1135 // Operand is memory address of 64-bit scalar representing 8, 4, or 2 values
   1136 // Result is v128 in memory
   1137 
   1138 var ins = wasmEvalText(`
   1139  (module
   1140    (memory (export "mem") 1 1)
   1141    (func (export "load8x8_s") (param $addr i32)
   1142      (v128.store (i32.const 0) (v128.load8x8_s (local.get $addr))))
   1143    (func (export "load8x8_u") (param $addr i32)
   1144      (v128.store (i32.const 0) (v128.load8x8_u (local.get $addr))))
   1145    (func (export "load16x4_s") (param $addr i32)
   1146      (v128.store (i32.const 0) (v128.load16x4_s (local.get $addr))))
   1147    (func (export "load16x4_u") (param $addr i32)
   1148      (v128.store (i32.const 0) (v128.load16x4_u (local.get $addr))))
   1149    (func (export "load32x2_s") (param $addr i32)
   1150      (v128.store (i32.const 0) (v128.load32x2_s (local.get $addr))))
   1151    (func (export "load32x2_u") (param $addr i32)
   1152      (v128.store (i32.const 0) (v128.load32x2_u (local.get $addr)))))`);
   1153 
   1154 var mem8 = new Uint8Array(ins.exports.mem.buffer);
   1155 var mem16s = new Int16Array(ins.exports.mem.buffer);
   1156 var mem16u = new Uint16Array(ins.exports.mem.buffer);
   1157 var mem32s = new Int32Array(ins.exports.mem.buffer);
   1158 var mem32u = new Uint32Array(ins.exports.mem.buffer);
   1159 var mem64s = new BigInt64Array(ins.exports.mem.buffer);
   1160 var mem64u = new BigUint64Array(ins.exports.mem.buffer);
   1161 var xs = [42, 129, 2, 212, 44, 27, 12, 199];
   1162 set(mem8, 48, xs);
   1163 
   1164 ins.exports.load8x8_s(48);
   1165 assertSame(get(mem16s, 0, 8), xs.map((x) => sign_extend(x, 8)));
   1166 
   1167 ins.exports.load8x8_u(48);
   1168 assertSame(get(mem16u, 0, 8), xs.map((x) => zero_extend(x, 8)));
   1169 
   1170 var xs = [(42 << 8) | 129, (212 << 8) | 2, (44 << 8) | 27, (199 << 8) | 12];
   1171 set(mem16u, 24, xs);
   1172 
   1173 ins.exports.load16x4_s(48);
   1174 assertSame(get(mem32s, 0, 4), xs.map((x) => sign_extend(x, 16)));
   1175 
   1176 ins.exports.load16x4_u(48);
   1177 assertSame(get(mem32u, 0, 4), xs.map((x) => zero_extend(x, 16)));
   1178 
   1179 var xs = [5, -8];
   1180 set(mem32u, 12, xs);
   1181 
   1182 ins.exports.load32x2_s(48);
   1183 assertSame(get(mem64s, 0, 2), xs.map((x) => sign_extend(x, 32)));
   1184 
   1185 ins.exports.load32x2_u(48);
   1186 assertSame(get(mem64s, 0, 2), xs.map((x) => zero_extend(x, 32)));
   1187 
   1188 // Vector select
   1189 //
   1190 // Operands and results are all in memory
   1191 
   1192 var ins = wasmEvalText(`
   1193  (module
   1194    (memory (export "mem") 1 1)
   1195    (func (export "bitselect_v128")
   1196      (v128.store (i32.const 0)
   1197        (v128.bitselect (v128.load (i32.const 16))
   1198                        (v128.load (i32.const 32))
   1199                        (v128.load (i32.const 48))))))`);
   1200 
   1201 var mem8 = new Uint8Array(ins.exports.mem.buffer);
   1202 set(mem8, 16, iota(16).map((_) => 0xAA));
   1203 set(mem8, 32, iota(16).map((_) => 0x55));
   1204 
   1205 set(mem8, 48, iota(16).map((_) => 0x99));
   1206 ins.exports.bitselect_v128();
   1207 assertSame(get(mem8, 0, 16), iota(16).map((_) => 0xCC));
   1208 
   1209 set(mem8, 48, iota(16).map((_) => 0x77));
   1210 ins.exports.bitselect_v128();
   1211 assertSame(get(mem8, 0, 16), iota(16).map((_) => 0x22));
   1212 
   1213 // Vector shuffle
   1214 //
   1215 // Operands and results are all in memory
   1216 
   1217 var ins = wasmEvalText(`
   1218  (module
   1219    (memory (export "mem") 1 1)
   1220    ;; the result interleaves the low eight bytes of the inputs
   1221    (func (export "shuffle1")
   1222      (v128.store (i32.const 0)
   1223        (i8x16.shuffle 0 16 1 17 2 18 3 19 4 20 5 21 6 22 7 23
   1224           (v128.load (i32.const 16))
   1225           (v128.load (i32.const 32)))))
   1226    ;; ditto the high eight bytes
   1227    (func (export "shuffle2")
   1228      (v128.store (i32.const 0)
   1229        (i8x16.shuffle 8 24 9 25 10 26 11 27 12 28 13 29 14 30 15 31
   1230           (v128.load (i32.const 16))
   1231           (v128.load (i32.const 32))))))`);
   1232 
   1233 var mem8 = new Uint8Array(ins.exports.mem.buffer);
   1234 var xs = iota(16).map((n) => 0xA0 + n);
   1235 var ys = iota(16).map((n) => 0x50 + n);
   1236 set(mem8, 16, xs);
   1237 set(mem8, 32, ys);
   1238 
   1239 ins.exports.shuffle1();
   1240 assertSame(get(mem8, 0, 16), iota(16).map((x) => ((x & 1) ? ys : xs)[x >>> 1]))
   1241 
   1242 ins.exports.shuffle2();
   1243 assertSame(get(mem8, 0, 16), iota(32).map((x) => ((x & 1) ? ys : xs)[x >>> 1]).slice(16));
   1244 
   1245 // Vector swizzle (variable permute).
   1246 //
   1247 // Case 1: Operands and results are all in memory
   1248 
   1249 var ins = wasmEvalText(`
   1250  (module
   1251    (memory (export "mem") 1 1)
   1252    (func (export "swizzle")
   1253      (v128.store (i32.const 0)
   1254        (i8x16.swizzle (v128.load (i32.const 16)) (v128.load (i32.const 32))))))`);
   1255 
   1256 var mem8 = new Uint8Array(ins.exports.mem.buffer);
   1257 
   1258 var xs = [100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115];
   1259 set(mem8, 16, xs);
   1260 
   1261 set(mem8, 32, [1,0,3,2,5,4,7,6,9,8,11,10,13,12,15,14]);
   1262 ins.exports.swizzle();
   1263 assertSame(get(mem8, 0, 16), [101,100,103,102,105,104,107,106,109,108,111,110,113,112,115,114]);
   1264 
   1265 set(mem8, 32, [9,8,11,10,13,12,16,14,1,0,3,2,5,192,7,6]);
   1266 ins.exports.swizzle();
   1267 assertSame(get(mem8, 0, 16), [109,108,111,110,113,112,0,114,101,100,103,102,105,0,107,106]);
   1268 
   1269 // Case 2: The mask operand is a constant; the swizzle gets optimized into a
   1270 // shuffle (also see ion-analysis.js).
   1271 
   1272 for ( let [mask, expected] of [[[1,0,3,2,5,4,7,6,9,8,11,10,13,12,15,14],
   1273                                [101,100,103,102,105,104,107,106,109,108,111,110,113,112,115,114]],
   1274                               [[9,8,11,10,13,12,16,14,1,0,3,2,5,192,7,6],
   1275                                [109,108,111,110,113,112,0,114,101,100,103,102,105,0,107,106]]] ) {
   1276 
   1277    let ins = wasmEvalText(`
   1278  (module
   1279    (memory (export "mem") 1 1)
   1280    (func (export "swizzle")
   1281      (v128.store (i32.const 0)
   1282        (i8x16.swizzle (v128.load (i32.const 16)) (v128.const i8x16 ${mask.join(' ')})))))
   1283 `);
   1284 
   1285    let mem8 = new Uint8Array(ins.exports.mem.buffer);
   1286    set(mem8, 16, [100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115]);
   1287    ins.exports.swizzle();
   1288    assertSame(get(mem8, 0, 16), expected);
   1289 }
   1290 
   1291 // Convert integer to floating point
   1292 
   1293 var ins = wasmEvalText(`
   1294  (module
   1295    (memory (export "mem") 1 1)
   1296    (func (export "convert_s")
   1297      (v128.store (i32.const 0)
   1298        (f32x4.convert_i32x4_s (v128.load (i32.const 16)))))
   1299    (func (export "convert_u")
   1300      (v128.store (i32.const 0)
   1301        (f32x4.convert_i32x4_u (v128.load (i32.const 16))))))`);
   1302 
   1303 var mem32s = new Int32Array(ins.exports.mem.buffer);
   1304 var mem32f = new Float32Array(ins.exports.mem.buffer);
   1305 var xs = [1, -9, 77987, -34512];
   1306 
   1307 set(mem32s, 4, xs);
   1308 ins.exports.convert_s();
   1309 assertSame(get(mem32f, 0, 4), xs);
   1310 
   1311 var mem32u = new Uint32Array(ins.exports.mem.buffer);
   1312 var ys = xs.map((x) => x>>>0);
   1313 
   1314 set(mem32u, 4, ys);
   1315 ins.exports.convert_u();
   1316 assertSame(get(mem32f, 0, 4), ys.map(Math.fround));
   1317 
   1318 // Convert floating point to integer with saturating truncation
   1319 
   1320 var ins = wasmEvalText(`
   1321  (module
   1322    (memory (export "mem") 1 1)
   1323    (func (export "trunc_sat_s")
   1324      (v128.store (i32.const 0)
   1325        (i32x4.trunc_sat_f32x4_s (v128.load (i32.const 16)))))
   1326    (func (export "trunc_sat_u")
   1327      (v128.store (i32.const 0)
   1328        (i32x4.trunc_sat_f32x4_u (v128.load (i32.const 16))))))`);
   1329 
   1330 var mem32s = new Int32Array(ins.exports.mem.buffer);
   1331 var mem32u = new Uint32Array(ins.exports.mem.buffer);
   1332 var mem32f = new Float32Array(ins.exports.mem.buffer);
   1333 var xs = [1.5, -9.5, 7.5e12, -8e13];
   1334 
   1335 set(mem32f, 4, xs);
   1336 ins.exports.trunc_sat_s();
   1337 assertSame(get(mem32s, 0, 4), [1, -9, 0x7FFFFFFF, -0x80000000]);
   1338 
   1339 var xs = [1.5, -9.5, 7.5e12, 812];
   1340 set(mem32f, 4, xs);
   1341 ins.exports.trunc_sat_u();
   1342 assertSame(get(mem32u, 0, 4), [1, 0, 0xFFFFFFFF, 812]);
   1343 
   1344 var xs = [0, -0, 0x80860000, 0x100000000];
   1345 set(mem32f, 4, xs);
   1346 ins.exports.trunc_sat_u();
   1347 assertSame(get(mem32u, 0, 4), [0, 0, 0x80860000, 0xFFFFFFFF]);
   1348 
   1349 // Loops and blocks.  This should at least test "sync" in the baseline compiler.
   1350 
   1351 var ins = wasmEvalText(`
   1352  (module
   1353    (memory (export "mem") 1 1)
   1354    (func $f (param $count i32) (param $v v128) (result v128)
   1355      (local $tmp v128)
   1356      (block $B1
   1357        (loop $L1
   1358          (br_if $B1 (i32.eqz (local.get $count)))
   1359          (local.set $tmp (i32x4.add (local.get $tmp) (local.get $v)))
   1360          (local.set $count (i32.sub (local.get $count) (i32.const 1)))
   1361          (br $L1)))
   1362      (local.get $tmp))
   1363    (func (export "run") (param $count i32)
   1364      (v128.store (i32.const 0)
   1365        (call $f (local.get $count) (v128.load (i32.const 16))))))`);
   1366 
   1367 var mem32 = new Int32Array(ins.exports.mem.buffer);
   1368 set(mem32, 4, [1,2,3,4]);
   1369 ins.exports.run(7);
   1370 assertSame(get(mem32, 0, 4), [7,14,21,28]);
   1371 
   1372 // Lots of parameters, this should trigger stack parameter passing
   1373 //
   1374 // 10 parameters in memory, we load them and pass them and operate on them.
   1375 
   1376 var ins = wasmEvalText(`
   1377  (module
   1378    (memory (export "mem") 1 1)
   1379    (func $f (param $v0 v128) (param $v1 v128) (param $v2 v128) (param $v3 v128) (param $v4 v128)
   1380             (param $v5 v128) (param $v6 v128) (param $v7 v128) (param $v8 v128) (param $v9 v128)
   1381             (result v128)
   1382      (i32x4.add (local.get $v0)
   1383        (i32x4.add (local.get $v1)
   1384          (i32x4.add (local.get $v2)
   1385            (i32x4.add (local.get $v3)
   1386              (i32x4.add (local.get $v4)
   1387                (i32x4.add (local.get $v5)
   1388                  (i32x4.add (local.get $v6)
   1389                    (i32x4.add (local.get $v7)
   1390                      (i32x4.add (local.get $v8) (local.get $v9)))))))))))
   1391    (func (export "run")
   1392      (v128.store (i32.const 0)
   1393        (call $f (v128.load (i32.const ${16*1}))
   1394                 (v128.load (i32.const ${16*2}))
   1395                 (v128.load (i32.const ${16*3}))
   1396                 (v128.load (i32.const ${16*4}))
   1397                 (v128.load (i32.const ${16*5}))
   1398                 (v128.load (i32.const ${16*6}))
   1399                 (v128.load (i32.const ${16*7}))
   1400                 (v128.load (i32.const ${16*8}))
   1401                 (v128.load (i32.const ${16*9}))
   1402                 (v128.load (i32.const ${16*10}))))))`);
   1403 
   1404 
   1405 var mem32 = new Int32Array(ins.exports.mem.buffer);
   1406 var sum = [0, 0, 0, 0];
   1407 for ( let i=1; i <= 10; i++ ) {
   1408    let v = [1,2,3,4].map((x) => x*i);
   1409    set(mem32, 4*i, v);
   1410    for ( let j=0; j < 4; j++ )
   1411        sum[j] += v[j];
   1412 }
   1413 
   1414 ins.exports.run();
   1415 
   1416 assertSame(get(mem32, 0, 4), sum);
   1417 
   1418 // Globals.
   1419 //
   1420 // We have a number of different code paths and representations and
   1421 // need to test them all.
   1422 //
   1423 // Cases:
   1424 //  - private global, mutable / immutable, initialized from constant or imported immutable global
   1425 //  - exported global, mutable / immutable, initialized from constant or imported immutable global
   1426 //  - imported global, mutable / immutable
   1427 //  - imported global that's re-exported, mutable / immutable
   1428 
   1429 // Global used for initialization below.
   1430 
   1431 var init = (function () {
   1432    var ins = wasmEvalText(`
   1433      (module
   1434        (global (export "init") v128 (v128.const i32x4 9 8 7 6)))`);
   1435    return ins.exports;
   1436 })();
   1437 
   1438 for ( let exportspec of ['', '(export "g")'] ) {
   1439 
   1440    // Private/exported immutable initialized from constant
   1441 
   1442    let ins1 = wasmEvalText(`
   1443  (module
   1444    (memory (export "mem") 1 1)
   1445    (global $g ${exportspec} v128 (v128.const i32x4 9 8 7 6))
   1446    (func (export "get") (param $dest i32)
   1447      (v128.store (local.get $dest) (global.get $g))))`);
   1448 
   1449    let mem1 = new Int32Array(ins1.exports.mem.buffer);
   1450    ins1.exports.get(0);
   1451    assertSame(get(mem1, 0, 4), [9, 8, 7, 6]);
   1452 
   1453    // Private/exported mutable initialized from constant
   1454 
   1455    let ins2 = wasmEvalText(`
   1456  (module
   1457    (memory (export "mem") 1 1)
   1458    (global $g ${exportspec} (mut v128) (v128.const i32x4 9 8 7 6))
   1459    (func (export "put") (param $val i32)
   1460      (global.set $g (i32x4.splat (local.get $val))))
   1461    (func (export "get") (param $dest i32)
   1462      (v128.store (local.get $dest) (global.get $g))))`);
   1463 
   1464    let mem2 = new Int32Array(ins2.exports.mem.buffer);
   1465    ins2.exports.get(0);
   1466    assertSame(get(mem2, 0, 4), [9, 8, 7, 6]);
   1467    ins2.exports.put(37);
   1468    ins2.exports.get(0);
   1469    assertSame(get(mem2, 0, 4), [37, 37, 37, 37]);
   1470 
   1471    // Private/exported immutable initialized from imported immutable global
   1472 
   1473    let ins3 = wasmEvalText(`
   1474  (module
   1475    (global $init (import "m" "init") v128)
   1476    (memory (export "mem") 1 1)
   1477    (global $g ${exportspec} v128 (global.get $init))
   1478    (func (export "get") (param $dest i32)
   1479      (v128.store (local.get $dest) (global.get $g))))`,
   1480                       {m:init});
   1481 
   1482    let mem3 = new Int32Array(ins3.exports.mem.buffer);
   1483    ins3.exports.get(0);
   1484    assertSame(get(mem3, 0, 4), [9, 8, 7, 6]);
   1485 
   1486    // Private/exported mutable initialized from imported immutable global
   1487 
   1488    let ins4 = wasmEvalText(`
   1489  (module
   1490    (global $init (import "m" "init") v128)
   1491    (memory (export "mem") 1 1)
   1492    (global $g ${exportspec} (mut v128) (global.get $init))
   1493    (func (export "put") (param $val i32)
   1494      (global.set $g (i32x4.splat (local.get $val))))
   1495    (func (export "get") (param $dest i32)
   1496      (v128.store (local.get $dest) (global.get $g))))`,
   1497                       {m:init});
   1498 
   1499    let mem4 = new Int32Array(ins4.exports.mem.buffer);
   1500    ins4.exports.get(0);
   1501    assertSame(get(mem4, 0, 4), [9, 8, 7, 6]);
   1502    ins4.exports.put(37);
   1503    ins4.exports.get(0);
   1504    assertSame(get(mem4, 0, 4), [37, 37, 37, 37]);
   1505 
   1506    // Imported private/re-exported immutable
   1507 
   1508    let ins5 = wasmEvalText(`
   1509  (module
   1510    (global $g ${exportspec} (import "m" "init") v128)
   1511    (memory (export "mem") 1 1)
   1512    (func (export "get") (param $dest i32)
   1513      (v128.store (local.get $dest) (global.get $g))))`,
   1514                       {m:init});
   1515 
   1516    let mem5 = new Int32Array(ins5.exports.mem.buffer);
   1517    ins5.exports.get(0);
   1518    assertSame(get(mem5, 0, 4), [9, 8, 7, 6]);
   1519 
   1520    // Imported private/re-exported mutable
   1521 
   1522    let mutg = (function () {
   1523        var ins = wasmEvalText(`
   1524      (module
   1525        (global (export "mutg") (mut v128) (v128.const i32x4 19 18 17 16)))`);
   1526        return ins.exports;
   1527    })();
   1528 
   1529    let ins6 = wasmEvalText(`
   1530  (module
   1531    (global $g ${exportspec} (import "m" "mutg") (mut v128))
   1532    (memory (export "mem") 1 1)
   1533    (func (export "put") (param $val i32)
   1534      (global.set $g (i32x4.splat (local.get $val))))
   1535    (func (export "get") (param $dest i32)
   1536      (v128.store (local.get $dest) (global.get $g))))`,
   1537                       {m:mutg});
   1538 
   1539    let mem6 = new Int32Array(ins6.exports.mem.buffer);
   1540    ins6.exports.get(0);
   1541    assertSame(get(mem6, 0, 4), [19, 18, 17, 16]);
   1542    ins6.exports.put(37);
   1543    ins6.exports.get(0);
   1544    assertSame(get(mem6, 0, 4), [37, 37, 37, 37]);
   1545 }
   1546 
   1547 // Imports and exports that pass and return v128
   1548 
   1549 var insworker = wasmEvalText(`
   1550  (module
   1551    (func (export "worker") (param v128) (result v128)
   1552      (i8x16.add (local.get 0) (v128.const i8x16 ${iota(16).join(' ')}))))`);
   1553 
   1554 var insrun = wasmEvalText(`
   1555  (module
   1556    (import "" "worker" (func $worker (param v128) (result v128)))
   1557    (memory (export "mem") 1 1)
   1558    (func (export "run") (param $srcloc i32) (param $destloc i32)
   1559      (v128.store (local.get $destloc)
   1560        (call $worker (v128.load (local.get $srcloc))))))`,
   1561                          {"":insworker.exports});
   1562 
   1563 var mem = new Uint8Array(insrun.exports.mem.buffer);
   1564 var xs = iota(16).map((x) => x+5);
   1565 set(mem, 0, xs);
   1566 insrun.exports.run(0, 16);
   1567 assertSame(get(mem, 16, 16), xs.map((x,i) => x+i))
   1568 
   1569 // Make sure JS<->wasm call guards are sensible.
   1570 
   1571 // Calling from JS to export that accepts v128.
   1572 assertErrorMessage(() => insworker.exports.worker(),
   1573                   TypeError,
   1574                   /cannot pass.*value.*to or from JS/);
   1575 
   1576 // Calling from wasm with v128 to import that comes from JS.  The instantiation
   1577 // will succeed even if the param type of the import is v128 (see "create a host
   1578 // function" in the Wasm JSAPI spec), it is the act of invoking it that checks
   1579 // that verboten types are not used (see "run a host function", ibid.).
   1580 var badImporter = wasmEvalText(`
   1581  (module
   1582    (import "" "worker" (func $worker (param v128) (result v128)))
   1583    (func (export "run")
   1584      (drop (call $worker (v128.const i32x4 0 1 2 3)))))`,
   1585             {"":{worker: function(a) { return a; }}});
   1586 
   1587 assertErrorMessage(() => badImporter.exports.run(),
   1588                   TypeError,
   1589                   /cannot pass.*value.*to or from JS/);
   1590 
   1591 // Imports and exports that pass and return v128 as stack (not register) args.
   1592 
   1593 var exportWithStackArgs = wasmEvalText(`
   1594  (module
   1595    (func (export "worker") (param v128) (param v128) (param v128) (param v128)
   1596                            (param v128) (param v128) (param v128) (param v128)
   1597                            (param v128) (param v128) (param v128) (param v128)
   1598                            (param v128) (param v128)
   1599           (result v128 v128)
   1600      (i8x16.add (local.get 3) (local.get 12))
   1601      (local.get 7)))`);
   1602 
   1603 var importWithStackArgs = wasmEvalText(`
   1604  (module
   1605    (type $t1 (func (param v128) (param v128) (param v128) (param v128)
   1606                    (param v128) (param v128) (param v128) (param v128)
   1607                    (param v128) (param v128) (param v128) (param v128)
   1608                    (param v128) (param v128)
   1609                    (result v128 v128)))
   1610    (import "" "worker" (func $worker (type $t1)))
   1611    (memory (export "mem") 1 1)
   1612    (table funcref (elem $worker))
   1613    (func (export "run")
   1614      (i32.const 16)
   1615      (call_indirect (type $t1) (v128.const i32x4 1 1 1 1) (v128.const i32x4 2 2 2 2) (v128.const i32x4 3 3 3 3)
   1616                    (v128.const i32x4 4 4 4 4) (v128.const i32x4 5 5 5 5) (v128.const i32x4 6 6 6 6)
   1617                    (v128.const i32x4 7 7 7 7) (v128.const i32x4 8 8 8 8) (v128.const i32x4 9 9 9 9)
   1618                    (v128.const i32x4 10 10 10 10) (v128.const i32x4 11 11 11 11) (v128.const i32x4 12 12 12 12)
   1619                    (v128.const i32x4 13 13 13 13) (v128.const i32x4 14 14 14 14)
   1620           (i32.const 0))
   1621      drop
   1622      v128.store
   1623      (i32.const 0)
   1624      (call $worker (v128.const i32x4 1 1 1 1) (v128.const i32x4 2 2 2 2) (v128.const i32x4 3 3 3 3)
   1625                    (v128.const i32x4 4 4 4 4) (v128.const i32x4 5 5 5 5) (v128.const i32x4 6 6 6 6)
   1626                    (v128.const i32x4 7 7 7 7) (v128.const i32x4 8 8 8 8) (v128.const i32x4 9 9 9 9)
   1627                    (v128.const i32x4 10 10 10 10) (v128.const i32x4 11 11 11 11) (v128.const i32x4 12 12 12 12)
   1628                    (v128.const i32x4 13 13 13 13) (v128.const i32x4 14 14 14 14))
   1629      drop
   1630      v128.store))`,
   1631                                       {"": exportWithStackArgs.exports});
   1632 
   1633 var mem = new Int32Array(importWithStackArgs.exports.mem.buffer);
   1634 importWithStackArgs.exports.run();
   1635 assertSame(get(mem, 0, 4), [17, 17, 17, 17]);
   1636 assertSame(get(mem, 4, 4), [17, 17, 17, 17]);
   1637 
   1638 // Imports and exports of v128 globals
   1639 
   1640 var insexporter = wasmEvalText(`
   1641  (module
   1642    (global (export "myglobal") (mut v128) (v128.const i8x16 ${iota(16).join(' ')})))`);
   1643 
   1644 var insimporter = wasmEvalText(`
   1645  (module
   1646    (import "m" "myglobal" (global $g (mut v128)))
   1647    (memory (export "mem") 1 1)
   1648    (func (export "run") (param $dest i32)
   1649      (v128.store (local.get $dest) (global.get $g))))`,
   1650                               {m:insexporter.exports});
   1651 
   1652 var mem = new Uint8Array(insimporter.exports.mem.buffer);
   1653 insimporter.exports.run(16);
   1654 assertSame(get(mem, 16, 16), iota(16));
   1655 
   1656 // Guards on accessing v128 globals from JS
   1657 
   1658 assertErrorMessage(() => insexporter.exports.myglobal.value = 0,
   1659                   TypeError,
   1660                   /cannot pass.*value.*to or from JS/);
   1661 
   1662 assertErrorMessage(function () { let v = insexporter.exports.myglobal.value },
   1663                   TypeError,
   1664                   /cannot pass.*value.*to or from JS/);
   1665 
   1666 // Multi-value cases + v128 parameters to if, block, loop
   1667 
   1668 var ins = wasmEvalText(`
   1669  (module
   1670    (memory (export "mem") 1 1)
   1671    (func $mvreturn (result v128 v128 v128)
   1672      (v128.load (i32.const 16))
   1673      (v128.load (i32.const 0))
   1674      (v128.load (i32.const 32)))
   1675    (func (export "runreturn")
   1676      i32.const 48
   1677      (call $mvreturn)
   1678      i32x4.sub ;; [-20, -20, -20, -20]
   1679      i32x4.sub ;; [31, 32, 33, 34]
   1680      v128.store)
   1681    (func (export "runif") (param $cond i32)
   1682      i32.const 48
   1683      (v128.load (i32.const 0))
   1684      (v128.load (i32.const 16))
   1685      (if (param v128) (param v128) (result v128 v128)
   1686          (local.get $cond)
   1687          (then i32x4.add
   1688                (v128.load (i32.const 32)))
   1689          (else i32x4.sub
   1690                (v128.load (i32.const 0))))
   1691      i32x4.add
   1692      v128.store)
   1693    (func (export "runblock")
   1694      i32.const 48
   1695      (v128.load (i32.const 0))
   1696      (v128.load (i32.const 16))
   1697      (block (param v128 v128) (result v128 v128)
   1698          i32x4.add
   1699          (v128.load (i32.const 32)))
   1700      i32x4.add
   1701      v128.store)
   1702    (func (export "runloop") (param $count i32)
   1703      i32.const 48
   1704      (v128.load (i32.const 0))
   1705      (v128.load (i32.const 16))
   1706      (block $B (param v128 v128) (result v128 v128)
   1707        (loop $L (param v128 v128) (result v128 v128)
   1708          i32x4.add
   1709          (v128.load (i32.const 32))
   1710          (local.set $count (i32.sub (local.get $count) (i32.const 1)))
   1711          (br_if $B (i32.eqz (local.get $count)))
   1712          (br $L)))
   1713      i32x4.add
   1714      v128.store))`);
   1715 
   1716 var mem = new Int32Array(ins.exports.mem.buffer);
   1717 set(mem, 0, [1, 2, 3, 4]);
   1718 set(mem, 4, [11, 12, 13, 14]);
   1719 set(mem, 8, [21, 22, 23, 24]);
   1720 
   1721 // Multi-value returns
   1722 
   1723 ins.exports.runreturn();
   1724 assertSame(get(mem, 12, 4), [31, 32, 33, 34]);
   1725 
   1726 // Multi-parameters to and multi-returns from "if"
   1727 
   1728 // This should be vector@0 + vector@16 + vector@32
   1729 ins.exports.runif(1);
   1730 assertSame(get(mem, 12, 4),
   1731           [33, 36, 39, 42]);
   1732 
   1733 // This should be vector@0 - vector@16 + vector@0
   1734 ins.exports.runif(0);
   1735 assertSame(get(mem, 12, 4),
   1736           [-9, -8, -7, -6]);
   1737 
   1738 // This should be vector@0 + vector@16 + vector@32
   1739 ins.exports.runblock();
   1740 assertSame(get(mem, 12, 4),
   1741           [33, 36, 39, 42]);
   1742 
   1743 // This should be vector@0 + vector@16 + N * vector@32 where
   1744 // N is the parameter to runloop.
   1745 ins.exports.runloop(3);
   1746 assertSame(get(mem, 12, 4),
   1747           [12+3*21, 14+3*22, 16+3*23, 18+3*24]);