mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 07:34:57 +00:00
Meta: Generate bigint values for v128 constants in Wasm tests
This commit is contained in:
parent
2462064fcd
commit
5f013e5374
2 changed files with 93 additions and 3 deletions
|
@ -8,6 +8,7 @@ import math
|
||||||
from tempfile import NamedTemporaryFile
|
from tempfile import NamedTemporaryFile
|
||||||
from subprocess import call
|
from subprocess import call
|
||||||
import json
|
import json
|
||||||
|
import array
|
||||||
|
|
||||||
atom_end = set('()"' + whitespace)
|
atom_end = set('()"' + whitespace)
|
||||||
|
|
||||||
|
@ -61,8 +62,89 @@ def parse_typed_value(ast):
|
||||||
'i64.const': 'i64',
|
'i64.const': 'i64',
|
||||||
'f32.const': 'float',
|
'f32.const': 'float',
|
||||||
'f64.const': 'double',
|
'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": types[ast[0][0]], "value": ast[1][0]}
|
||||||
|
|
||||||
return {"type": "error"}
|
return {"type": "error"}
|
||||||
|
@ -285,6 +367,9 @@ def genarg(spec):
|
||||||
|
|
||||||
def gen():
|
def gen():
|
||||||
x = spec['value']
|
x = spec['value']
|
||||||
|
if spec['type'] == 'bigint':
|
||||||
|
return f"0x{x}n"
|
||||||
|
|
||||||
if spec['type'] in ('i32', 'i64'):
|
if spec['type'] in ('i32', 'i64'):
|
||||||
if x.startswith('0x'):
|
if x.startswith('0x'):
|
||||||
if spec['type'] == 'i32':
|
if spec['type'] == 'i32':
|
||||||
|
|
|
@ -235,7 +235,9 @@ JS_DEFINE_NATIVE_FUNCTION(WebAssemblyModule::wasm_invoke)
|
||||||
}
|
}
|
||||||
|
|
||||||
u128 bits;
|
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));
|
arguments.append(Wasm::Value(bits));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -269,7 +271,10 @@ JS_DEFINE_NATIVE_FUNCTION(WebAssemblyModule::wasm_invoke)
|
||||||
[](auto const& value) { return JS::Value(static_cast<double>(value)); },
|
[](auto const& value) { return JS::Value(static_cast<double>(value)); },
|
||||||
[](i32 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 })); },
|
[&](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) {
|
[](Wasm::Reference const& reference) {
|
||||||
return reference.ref().visit(
|
return reference.ref().visit(
|
||||||
[](const Wasm::Reference::Null&) { return JS::js_null(); },
|
[](const Wasm::Reference::Null&) { return JS::js_null(); },
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue