mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-04 05:20:30 +00:00
Meta: Generate bigint values for v128 constants in Wasm tests
This commit is contained in:
parent
2462064fcd
commit
5f013e5374
Notes:
sideshowbarker
2024-07-17 04:49:48 +09:00
Author: https://github.com/alimpfard Commit: https://github.com/SerenityOS/serenity/commit/5f013e5374 Pull-request: https://github.com/SerenityOS/serenity/pull/19623 Reviewed-by: https://github.com/ADKaster Reviewed-by: https://github.com/DanShaders
2 changed files with 93 additions and 3 deletions
|
@ -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':
|
||||
|
|
|
@ -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(); },
|
||||
|
|
Loading…
Reference in a new issue