Source code

Revision control

Copy as Markdown

Other Tools

// |jit-test| skip-if: true
// Common code for the ad-hack test cases.
function get(arr, loc, len) {
let res = [];
for ( let i=0; i < len; i++ ) {
res.push(arr[loc+i]);
}
return res;
}
function getUnaligned(arr, width, loc, len) {
assertEq(arr.constructor, Uint8Array);
assertEq(width <= 4, true);
let res = [];
for ( let i=0; i < len; i++ ) {
let x = 0;
for ( let j=width-1; j >=0; j-- )
x = (x << 8) | arr[loc+i*width+j];
res.push(x);
}
return res;
}
function set(arr, loc, vals) {
for ( let i=0; i < vals.length; i++ ) {
if (arr instanceof BigInt64Array) {
arr[loc+i] = BigInt(vals[i]);
} else {
arr[loc+i] = vals[i];
}
}
}
function setUnaligned(arr, width, loc, vals) {
assertEq(arr.constructor, Uint8Array);
assertEq(width <= 4, true);
for ( let i=0; i < vals.length; i++ ) {
let x = vals[i];
for ( let j=0 ; j < width ; j++ ) {
arr[loc+i*width + j] = x & 255;
x >>= 8;
}
}
}
function equal(a, b) {
return a === b || isNaN(a) && isNaN(b);
}
function upd(xs, at, val) {
let ys = Array.from(xs);
ys[at] = val;
return ys;
}
// The following operations are not always generalized fully, they are just
// functional enough for the existing test cases to pass.
function sign_extend(n, bits) {
if (bits < 32) {
n = Number(n);
return (n << (32 - bits)) >> (32 - bits);
}
if (typeof n == "bigint") {
if (bits == 32)
return Number(n & 0xFFFF_FFFFn) | 0;
assertEq(bits, 64);
n = (n & 0xFFFF_FFFF_FFFF_FFFFn)
if (n > 0x7FFF_FFFF_FFFF_FFFFn)
return n - 0x1_0000_0000_0000_0000n;
return n;
}
assertEq(bits, 32);
return n|0;
}
function zero_extend(n, bits) {
if (bits < 32) {
return n & ((1 << bits) - 1);
}
if (n < 0)
n = 0x100000000 + n;
return n;
}
function signed_saturate(z, bits) {
let min = -(1 << (bits-1));
if (z <= min) {
return min;
}
let max = (1 << (bits-1)) - 1;
if (z > max) {
return max;
}
return z;
}
function unsigned_saturate(z, bits) {
if (z <= 0) {
return 0;
}
let max = (1 << bits) - 1;
if (z > max) {
return max;
}
return z;
}
function shl(count, width) {
if (width == 64) {
count = BigInt(count);
return (v) => {
v = BigInt(v);
if (v < 0)
v = (1n << 64n) + v;
let r = (v << count) & ((1n << 64n) - 1n);
if (r & (1n << 63n))
r = -((1n << 64n) - r);
return r;
}
} else {
return (v) => {
let mask = (width == 32) ? -1 : ((1 << width) - 1);
return (v << count) & mask;
}
}
}
function popcount(n) {
n = n - ((n >> 1) & 0x55555555)
n = (n & 0x33333333) + ((n >> 2) & 0x33333333)
return ((n + (n >> 4) & 0xF0F0F0F) * 0x1010101) >> 24
}
function jsValueToWasmName(x) {
if (typeof x == "number") {
if (x == 0) return 1 / x < 0 ? "-0" : "0";
if (isNaN(x)) return "+nan";
if (!isFinite(x)) return (x < 0 ? "-" : "+") + "inf";
}
return x;
}
// For each input array, a set of arrays of the proper length for v128, with
// values in range but possibly of the wrong signedness (eg, for Int8Array, 128
// is in range but is really -128). Also a unary operator `rectify` that
// transforms the value to the proper sign and bitwidth.
Int8Array.inputs = [iota(16).map((x) => (x+1) * (x % 3 == 0 ? -1 : 1)),
iota(16).map((x) => (x*2+3) * (x % 3 == 1 ? -1 : 1)),
[1,2,128,127,1,4,128,127,1,2,129,125,1,2,254,0],
[2,1,127,128,5,1,127,128,2,1,126,130,2,1,1,255],
iota(16).map((x) => ((x + 37) * 8 + 12) % 256),
iota(16).map((x) => ((x + 12) * 4 + 9) % 256)];
Int8Array.rectify = (x) => sign_extend(x,8);
Int8Array.layoutName = 'i8x16';
Uint8Array.inputs = Int8Array.inputs;
Uint8Array.rectify = (x) => zero_extend(x,8);
Uint8Array.layoutName = 'i8x16';
Int16Array.inputs = [iota(8).map((x) => (x+1) * (x % 3 == 0 ? -1 : 1)),
iota(8).map((x) => (x*2+3) * (x % 3 == 1 ? -1 : 1)),
[1,2,32768,32767,1,4,32768,32767],
[2,1,32767,32768,5,1,32767,32768],
[1,2,128,127,1,4,128,127].map((x) => (x << 8) + x*2),
[2,1,127,128,1,1,128,128].map((x) => (x << 8) + x*3)];
Int16Array.rectify = (x) => sign_extend(x,16);
Int16Array.layoutName = 'i16x8';
Uint16Array.inputs = Int16Array.inputs;
Uint16Array.rectify = (x) => zero_extend(x,16);
Uint16Array.layoutName = 'i16x8';
Int32Array.inputs = [iota(4).map((x) => (x+1) * (x % 3 == 0 ? -1 : 1)),
iota(4).map((x) => (x*2+3) * (x % 3 == 1 ? -1 : 1)),
[1,2,32768 << 16,32767 << 16],
[2,1,32767 << 16,32768 << 16],
[1,2,128,127].map((x) => (x << 24) + (x << 8) + x*3),
[2,1,127,128].map((x) => (x << 24) + (x << 8) + x*4)];
Int32Array.rectify = (x) => sign_extend(x,32);
Int32Array.layoutName = 'i32x4';
Uint32Array.inputs = Int32Array.inputs;
Uint32Array.rectify = (x) => zero_extend(x,32);
Uint32Array.layoutName = 'i32x4';
BigInt64Array.inputs = [[1,2],[2,1],[-1,-2],[-2,-1],[2n ** 32n, 2n ** 32n - 5n],
[(2n ** 38n) / 5n, (2n ** 41n) / 7n],
[-((2n ** 38n) / 5n), (2n ** 41n) / 7n]];
BigInt64Array.rectify = (x) => BigInt(x);
BigInt64Array.layoutName = 'i64x2';
Float32Array.inputs = [[1, -1, 1e10, -1e10],
[-1, -2, -1e10, 1e10],
[5.1, -1.1, -4.3, -0],
...permute([1, -10, NaN, Infinity])];
Float32Array.rectify = (x) => Math.fround(x);
Float32Array.layoutName = 'f32x4';
Float64Array.inputs = Float32Array.inputs.map((x) => x.slice(0, 2))
Float64Array.rectify = (x) => x;
Float64Array.layoutName = 'f64x2';
// Tidy up all the inputs
for ( let A of [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, BigInt64Array,
Float32Array, Float64Array]) {
A.inputs = A.inputs.map((xs) => xs.map(A.rectify));
}