Meta: Generate bigint values for v128 constants in Wasm tests

This commit is contained in:
Ali Mohammad Pur 2022-08-28 05:48:19 +04:30 committed by Ali Mohammad Pur
parent 2462064fcd
commit 5f013e5374
Notes: sideshowbarker 2024-07-17 04:49:48 +09:00
2 changed files with 93 additions and 3 deletions

View file

@ -8,6 +8,7 @@ import math
from tempfile import NamedTemporaryFile
from subprocess import call
import json
import array
atom_end = set('()"' + whitespace)
@ -61,8 +62,89 @@ def parse_typed_value(ast):
'i64.const': 'i64',
'f32.const': 'float',
'f64.const': 'double',
'v128.const': 'bigint',
}
if len(ast) == 2 and ast[0][0] in types:
v128_sizes = {
'i8x16': 1,
'i16x8': 2,
'i32x4': 4,
'i64x2': 8,
'f32x4': 4,
'f64x2': 8,
}
v128_format_names = {
'i8x16': 'b',
'i16x8': 'h',
'i32x4': 'i',
'i64x2': 'q',
'f32x4': 'f',
'f64x2': 'd',
}
v128_format_names_unsigned = {
'i8x16': 'B',
'i16x8': 'H',
'i32x4': 'I',
'i64x2': 'Q',
}
def parse_v128_chunk(num, type) -> array:
negative = 1
if num.startswith('-'):
negative = -1
num = num[1:]
elif num.startswith('+'):
num = num[1:]
# wtf spec test, split your wast tests already
while num.startswith('0') and not num.startswith('0x'):
num = num[1:]
if num == '':
num = '0'
if type.startswith('f'):
def generate():
if num == 'nan:canonical':
return float.fromhex('0x7fc00000')
if num == 'nan:arithmetic':
return float.fromhex('0x7ff00000')
if num == 'nan:signaling':
return float.fromhex('0x7ff80000')
if num.startswith('nan:'):
# FIXME: I have no idea if this is actually correct :P
rest = num[4:]
return float.fromhex('0x7ff80000') + int(rest, base=16)
if num.lower() == 'infinity':
return float.fromhex('0x7ff00000') * negative
try:
return float(num) * negative
except ValueError:
return float.fromhex(num) * negative
value = generate()
return struct.pack(f'={v128_format_names[type]}', value)
value = negative * int(num.replace('_', ''), base=0)
try:
return struct.pack(f'={v128_format_names[type]}', value)
except struct.error:
# The test format uses signed and unsigned values interchangeably, this is probably an unsigned value.
return struct.pack(f'={v128_format_names_unsigned[type]}', value)
if len(ast) >= 2 and ast[0][0] in types:
if ast[0][0] == 'v128.const':
value = array.array('b')
for i, num in enumerate(ast[2:]):
size = v128_sizes[ast[1][0]]
s = len(value)
value.frombytes(parse_v128_chunk(num[0], ast[1][0]))
assert len(value) - s == size, f'Expected {size} bytes, got {len(value) - s} bytes'
return {
'type': types[ast[0][0]],
'value': value.tobytes().hex()
}
return {"type": types[ast[0][0]], "value": ast[1][0]}
return {"type": "error"}
@ -285,6 +367,9 @@ def genarg(spec):
def gen():
x = spec['value']
if spec['type'] == 'bigint':
return f"0x{x}n"
if spec['type'] in ('i32', 'i64'):
if x.startswith('0x'):
if spec['type'] == 'i32':

View file

@ -235,7 +235,9 @@ JS_DEFINE_NATIVE_FUNCTION(WebAssemblyModule::wasm_invoke)
}
u128 bits;
(void)argument.as_bigint().big_integer().export_data({ bit_cast<u8*>(&bits), sizeof(bits) });
(void)argument.as_bigint().big_integer().unsigned_value().export_data({ bit_cast<u8*>(&bits), sizeof(bits) });
VERIFY(!argument.as_bigint().big_integer().is_negative());
arguments.append(Wasm::Value(bits));
break;
}
@ -269,7 +271,10 @@ JS_DEFINE_NATIVE_FUNCTION(WebAssemblyModule::wasm_invoke)
[](auto const& value) { return JS::Value(static_cast<double>(value)); },
[](i32 value) { return JS::Value(static_cast<double>(value)); },
[&](i64 value) { return JS::Value(JS::BigInt::create(vm, Crypto::SignedBigInteger { value })); },
[&](u128 value) { return JS::Value(JS::BigInt::create(vm, Crypto::SignedBigInteger::import_data(bit_cast<u8 const*>(&value), sizeof(value)))); },
[&](u128 value) {
auto unsigned_bigint_value = Crypto::UnsignedBigInteger::import_data(bit_cast<u8 const*>(&value), sizeof(value));
return JS::Value(JS::BigInt::create(vm, Crypto::SignedBigInteger(move(unsigned_bigint_value), false)));
},
[](Wasm::Reference const& reference) {
return reference.ref().visit(
[](const Wasm::Reference::Null&) { return JS::js_null(); },