LibWasm+LibWeb: Parse and validate all Wasm SIMD instructions

This commit is contained in:
Ali Mohammad Pur 2023-06-12 13:04:22 +03:30 committed by Ali Mohammad Pur
parent b005691497
commit 2462064fcd
Notes: sideshowbarker 2024-07-16 20:39:14 +09:00
13 changed files with 2474 additions and 78 deletions

View file

@ -711,7 +711,7 @@ if (BUILD_LAGOM)
add_executable(test-wasm
../../Tests/LibWasm/test-wasm.cpp
../../Userland/Libraries/LibTest/JavaScriptTestRunnerMain.cpp)
target_link_libraries(test-wasm LibCore LibFileSystem LibTest LibWasm LibJS)
target_link_libraries(test-wasm LibCore LibFileSystem LibTest LibWasm LibJS LibCrypto)
add_test(
NAME WasmParser
COMMAND test-wasm --show-progress=false ${CMAKE_CURRENT_BINARY_DIR}/Userland/Libraries/LibWasm/Tests

View file

@ -1,2 +1,2 @@
serenity_testjs_test(test-wasm.cpp test-wasm LIBS LibWasm LibJS)
serenity_testjs_test(test-wasm.cpp test-wasm LIBS LibWasm LibJS LibCrypto)
install(TARGETS test-wasm RUNTIME DESTINATION bin OPTIONAL)

View file

@ -173,6 +173,7 @@ JS_DEFINE_NATIVE_FUNCTION(WebAssemblyModule::get_export)
[&](auto const& value) -> JS::Value { return JS::Value(static_cast<double>(value)); },
[&](i32 value) { return JS::Value(static_cast<double>(value)); },
[&](i64 value) -> JS::Value { return JS::BigInt::create(vm, Crypto::SignedBigInteger { value }); },
[&](u128 value) -> JS::Value { return JS::BigInt::create(vm, Crypto::SignedBigInteger::import_data(bit_cast<u8 const*>(&value), sizeof(value))); },
[&](Wasm::Reference const& reference) -> JS::Value {
return reference.ref().visit(
[&](const Wasm::Reference::Null&) -> JS::Value { return JS::js_null(); },
@ -225,6 +226,19 @@ JS_DEFINE_NATIVE_FUNCTION(WebAssemblyModule::wasm_invoke)
case Wasm::ValueType::Kind::F64:
arguments.append(Wasm::Value(static_cast<double>(double_value)));
break;
case Wasm::ValueType::Kind::V128: {
if (!argument.is_bigint()) {
if (argument.is_number())
argument = JS::BigInt::create(vm, Crypto::SignedBigInteger { TRY(argument.to_double(vm)) });
else
argument = TRY(argument.to_bigint(vm));
}
u128 bits;
(void)argument.as_bigint().big_integer().export_data({ bit_cast<u8*>(&bits), sizeof(bits) });
arguments.append(Wasm::Value(bits));
break;
}
case Wasm::ValueType::Kind::FunctionReference:
arguments.append(Wasm::Value(Wasm::Reference { Wasm::Reference::Func { static_cast<u64>(double_value) } }));
break;
@ -255,6 +269,7 @@ 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)))); },
[](Wasm::Reference const& reference) {
return reference.ref().visit(
[](const Wasm::Reference::Null&) { return JS::js_null(); },

View file

@ -330,6 +330,7 @@ InstantiationResult AbstractMachine::instantiate(Module const& module, Vector<Ex
size_t offset = 0;
result.values().first().value().visit(
[&](auto const& value) { offset = value; },
[&](u128 const&) { instantiation_result = InstantiationError { "Data segment offset returned a vector type"sv }; },
[&](Reference const&) { instantiation_result = InstantiationError { "Data segment offset returned a reference"sv }; });
if (instantiation_result.has_value() && instantiation_result->is_error())
return;

View file

@ -12,6 +12,7 @@
#include <AK/OwnPtr.h>
#include <AK/Result.h>
#include <AK/StackInfo.h>
#include <AK/UFixedBigInt.h>
#include <LibWasm/Types.h>
// NOTE: Special case for Wasm::Result.
@ -74,7 +75,7 @@ public:
{
}
using AnyValueType = Variant<i32, i64, float, double, Reference>;
using AnyValueType = Variant<i32, i64, float, double, u128, Reference>;
explicit Value(AnyValueType value)
: m_value(move(value))
{
@ -111,11 +112,20 @@ public:
VERIFY(raw_value == 0);
m_value = Reference { Reference::Null { ValueType(ValueType::Kind::ExternReference) } };
break;
case ValueType::Kind::V128:
m_value = u128(0ull, bit_cast<u64>(raw_value));
break;
default:
VERIFY_NOT_REACHED();
}
}
template<SameAs<u128> T>
explicit Value(T raw_value)
: m_value(raw_value)
{
}
ALWAYS_INLINE Value(Value const& value) = default;
ALWAYS_INLINE Value(Value&& value) = default;
ALWAYS_INLINE Value& operator=(Value&& value) = default;
@ -158,6 +168,7 @@ public:
[](i64) { return ValueType::Kind::I64; },
[](float) { return ValueType::Kind::F32; },
[](double) { return ValueType::Kind::F64; },
[](u128) { return ValueType::Kind::V128; },
[&](Reference const& type) {
return type.ref().visit(
[](Reference::Func const&) { return ValueType::Kind::FunctionReference; },

File diff suppressed because it is too large Load diff

View file

@ -221,6 +221,17 @@ public:
return result;
}
template<auto... kinds>
ErrorOr<void, ValidationError> take_and_put(Wasm::ValueType::Kind kind, SourceLocation location = SourceLocation::current())
{
ErrorOr<void, ValidationError> result;
if (((result = take(Wasm::ValueType(kinds), location)).is_error(), ...)) {
return result;
}
append(Wasm::ValueType(kind));
return result;
}
size_t actual_size() const { return Vector<StackEntry>::size(); }
size_t size() const { return m_did_insert_unknown_entry ? static_cast<size_t>(-1) : actual_size(); }
@ -238,7 +249,7 @@ public:
};
ErrorOr<ExpressionTypeResult, ValidationError> validate(Expression const&, Vector<ValueType> const&);
ErrorOr<void, ValidationError> validate(Instruction const& instruction, Stack& stack, bool& is_constant);
template<u32 opcode>
template<u64 opcode>
ErrorOr<void, ValidationError> validate_instruction(Instruction const&, Stack& stack, bool& is_constant);
// Types

View file

@ -15,6 +15,7 @@ static constexpr auto i32_tag = 0x7f;
static constexpr auto i64_tag = 0x7e;
static constexpr auto f32_tag = 0x7d;
static constexpr auto f64_tag = 0x7c;
static constexpr auto v128_tag = 0x7b;
static constexpr auto function_reference_tag = 0x70;
static constexpr auto extern_reference_tag = 0x6f;

View file

@ -10,7 +10,7 @@
namespace Wasm {
AK_TYPEDEF_DISTINCT_ORDERED_ID(u32, OpCode);
AK_TYPEDEF_DISTINCT_ORDERED_ID(u64, OpCode);
namespace Instructions {
@ -198,27 +198,263 @@ namespace Instructions {
M(ref_func, 0xd2)
// These are synthetic opcodes, they are _not_ seen in wasm with these values.
#define ENUMERATE_MULTI_BYTE_WASM_OPCODES(M) \
M(i32_trunc_sat_f32_s, 0xfc00) \
M(i32_trunc_sat_f32_u, 0xfc01) \
M(i32_trunc_sat_f64_s, 0xfc02) \
M(i32_trunc_sat_f64_u, 0xfc03) \
M(i64_trunc_sat_f32_s, 0xfc04) \
M(i64_trunc_sat_f32_u, 0xfc05) \
M(i64_trunc_sat_f64_s, 0xfc06) \
M(i64_trunc_sat_f64_u, 0xfc07) \
M(memory_init, 0xfc08) \
M(data_drop, 0xfc09) \
M(memory_copy, 0xfc0a) \
M(memory_fill, 0x0fc0b) \
M(table_init, 0xfc0c) \
M(elem_drop, 0xfc0d) \
M(table_copy, 0xfc0e) \
M(table_grow, 0xfc0f) \
M(table_size, 0xfc10) \
M(table_fill, 0xfc11) \
M(structured_else, 0xff00) \
M(structured_end, 0xff01)
#define ENUMERATE_MULTI_BYTE_WASM_OPCODES(M) \
M(i32_trunc_sat_f32_s, 0xfc00000000000000ull) \
M(i32_trunc_sat_f32_u, 0xfc00000000000001ull) \
M(i32_trunc_sat_f64_s, 0xfc00000000000002ull) \
M(i32_trunc_sat_f64_u, 0xfc00000000000003ull) \
M(i64_trunc_sat_f32_s, 0xfc00000000000004ull) \
M(i64_trunc_sat_f32_u, 0xfc00000000000005ull) \
M(i64_trunc_sat_f64_s, 0xfc00000000000006ull) \
M(i64_trunc_sat_f64_u, 0xfc00000000000007ull) \
M(memory_init, 0xfc00000000000008ull) \
M(data_drop, 0xfc00000000000009ull) \
M(memory_copy, 0xfc0000000000000aull) \
M(memory_fill, 0xfc0000000000000bull) \
M(table_init, 0xfc0000000000000cull) \
M(elem_drop, 0xfc0000000000000dull) \
M(table_copy, 0xfc0000000000000eull) \
M(table_grow, 0xfc0000000000000full) \
M(table_size, 0xfc00000000000010ull) \
M(table_fill, 0xfc00000000000011ull) \
M(structured_else, 0xff00000000000000ull) \
M(structured_end, 0xff00000000000001ull) \
M(v128_load, 0xfd00000000000000ull) \
M(v128_load8x8_s, 0xfd00000000000001ull) \
M(v128_load8x8_u, 0xfd00000000000002ull) \
M(v128_load16x4_s, 0xfd00000000000003ull) \
M(v128_load16x4_u, 0xfd00000000000004ull) \
M(v128_load32x2_s, 0xfd00000000000005ull) \
M(v128_load32x2_u, 0xfd00000000000006ull) \
M(v128_load8_splat, 0xfd00000000000007ull) \
M(v128_load16_splat, 0xfd00000000000008ull) \
M(v128_load32_splat, 0xfd00000000000009ull) \
M(v128_load64_splat, 0xfd0000000000000aull) \
M(v128_store, 0xfd0000000000000bull) \
M(v128_const, 0xfd0000000000000cull) \
M(i8x16_shuffle, 0xfd0000000000000dull) \
M(i8x16_swizzle, 0xfd0000000000000eull) \
M(i8x16_splat, 0xfd0000000000000full) \
M(i16x8_splat, 0xfd00000000000010ull) \
M(i32x4_splat, 0xfd00000000000011ull) \
M(i64x2_splat, 0xfd00000000000012ull) \
M(f32x4_splat, 0xfd00000000000013ull) \
M(f64x2_splat, 0xfd00000000000014ull) \
M(i8x16_extract_lane_s, 0xfd00000000000015ull) \
M(i8x16_extract_lane_u, 0xfd00000000000016ull) \
M(i8x16_replace_lane, 0xfd00000000000017ull) \
M(i16x8_extract_lane_s, 0xfd00000000000018ull) \
M(i16x8_extract_lane_u, 0xfd00000000000019ull) \
M(i16x8_replace_lane, 0xfd0000000000001aull) \
M(i32x4_extract_lane, 0xfd0000000000001bull) \
M(i32x4_replace_lane, 0xfd0000000000001cull) \
M(i64x2_extract_lane, 0xfd0000000000001dull) \
M(i64x2_replace_lane, 0xfd0000000000001eull) \
M(f32x4_extract_lane, 0xfd0000000000001full) \
M(f32x4_replace_lane, 0xfd00000000000020ull) \
M(f64x2_extract_lane, 0xfd00000000000021ull) \
M(f64x2_replace_lane, 0xfd00000000000022ull) \
M(i8x16_eq, 0xfd00000000000023ull) \
M(i8x16_ne, 0xfd00000000000024ull) \
M(i8x16_lt_s, 0xfd00000000000025ull) \
M(i8x16_lt_u, 0xfd00000000000026ull) \
M(i8x16_gt_s, 0xfd00000000000027ull) \
M(i8x16_gt_u, 0xfd00000000000028ull) \
M(i8x16_le_s, 0xfd00000000000029ull) \
M(i8x16_le_u, 0xfd0000000000002aull) \
M(i8x16_ge_s, 0xfd0000000000002bull) \
M(i8x16_ge_u, 0xfd0000000000002cull) \
M(i16x8_eq, 0xfd0000000000002dull) \
M(i16x8_ne, 0xfd0000000000002eull) \
M(i16x8_lt_s, 0xfd0000000000002full) \
M(i16x8_lt_u, 0xfd00000000000030ull) \
M(i16x8_gt_s, 0xfd00000000000031ull) \
M(i16x8_gt_u, 0xfd00000000000032ull) \
M(i16x8_le_s, 0xfd00000000000033ull) \
M(i16x8_le_u, 0xfd00000000000034ull) \
M(i16x8_ge_s, 0xfd00000000000035ull) \
M(i16x8_ge_u, 0xfd00000000000036ull) \
M(i32x4_eq, 0xfd00000000000037ull) \
M(i32x4_ne, 0xfd00000000000038ull) \
M(i32x4_lt_s, 0xfd00000000000039ull) \
M(i32x4_lt_u, 0xfd0000000000003aull) \
M(i32x4_gt_s, 0xfd0000000000003bull) \
M(i32x4_gt_u, 0xfd0000000000003cull) \
M(i32x4_le_s, 0xfd0000000000003dull) \
M(i32x4_le_u, 0xfd0000000000003eull) \
M(i32x4_ge_s, 0xfd0000000000003full) \
M(i32x4_ge_u, 0xfd00000000000040ull) \
M(f32x4_eq, 0xfd00000000000041ull) \
M(f32x4_ne, 0xfd00000000000042ull) \
M(f32x4_lt, 0xfd00000000000043ull) \
M(f32x4_gt, 0xfd00000000000044ull) \
M(f32x4_le, 0xfd00000000000045ull) \
M(f32x4_ge, 0xfd00000000000046ull) \
M(f64x2_eq, 0xfd00000000000047ull) \
M(f64x2_ne, 0xfd00000000000048ull) \
M(f64x2_lt, 0xfd00000000000049ull) \
M(f64x2_gt, 0xfd0000000000004aull) \
M(f64x2_le, 0xfd0000000000004bull) \
M(f64x2_ge, 0xfd0000000000004cull) \
M(v128_not, 0xfd0000000000004dull) \
M(v128_and, 0xfd0000000000004eull) \
M(v128_andnot, 0xfd0000000000004full) \
M(v128_or, 0xfd00000000000050ull) \
M(v128_xor, 0xfd00000000000051ull) \
M(v128_bitselect, 0xfd00000000000052ull) \
M(v128_any_true, 0xfd00000000000053ull) \
M(v128_load8_lane, 0xfd00000000000054ull) \
M(v128_load16_lane, 0xfd00000000000055ull) \
M(v128_load32_lane, 0xfd00000000000056ull) \
M(v128_load64_lane, 0xfd00000000000057ull) \
M(v128_store8_lane, 0xfd00000000000058ull) \
M(v128_store16_lane, 0xfd00000000000059ull) \
M(v128_store32_lane, 0xfd0000000000005aull) \
M(v128_store64_lane, 0xfd0000000000005bull) \
M(v128_load32_zero, 0xfd0000000000005cull) \
M(v128_load64_zero, 0xfd0000000000005dull) \
M(f32x4_demote_f64x2_zero, 0xfd0000000000005eull) \
M(f64x2_promote_low_f32x4, 0xfd0000000000005full) \
M(i8x16_abs, 0xfd00000000000060ull) \
M(i8x16_neg, 0xfd00000000000061ull) \
M(i8x16_popcnt, 0xfd00000000000062ull) \
M(i8x16_all_true, 0xfd00000000000063ull) \
M(i8x16_bitmask, 0xfd00000000000064ull) \
M(i8x16_narrow_i16x8_s, 0xfd00000000000065ull) \
M(i8x16_narrow_i16x8_u, 0xfd00000000000066ull) \
M(f32x4_ceil, 0xfd00000000000067ull) \
M(f32x4_floor, 0xfd00000000000068ull) \
M(f32x4_trunc, 0xfd00000000000069ull) \
M(f32x4_nearest, 0xfd0000000000006aull) \
M(i8x16_shl, 0xfd0000000000006bull) \
M(i8x16_shr_s, 0xfd0000000000006cull) \
M(i8x16_shr_u, 0xfd0000000000006dull) \
M(i8x16_add, 0xfd0000000000006eull) \
M(i8x16_add_sat_s, 0xfd0000000000006full) \
M(i8x16_add_sat_u, 0xfd00000000000070ull) \
M(i8x16_sub, 0xfd00000000000071ull) \
M(i8x16_sub_sat_s, 0xfd00000000000072ull) \
M(i8x16_sub_sat_u, 0xfd00000000000073ull) \
M(f64x2_ceil, 0xfd00000000000074ull) \
M(f64x2_floor, 0xfd00000000000075ull) \
M(i8x16_min_s, 0xfd00000000000076ull) \
M(i8x16_min_u, 0xfd00000000000077ull) \
M(i8x16_max_s, 0xfd00000000000078ull) \
M(i8x16_max_u, 0xfd00000000000079ull) \
M(f64x2_trunc, 0xfd0000000000007aull) \
M(i8x16_avgr_u, 0xfd0000000000007bull) \
M(i16x8_extadd_pairwise_i8x16_s, 0xfd0000000000007cull) \
M(i16x8_extadd_pairwise_i8x16_u, 0xfd0000000000007dull) \
M(i32x4_extadd_pairwise_i16x8_s, 0xfd0000000000007eull) \
M(i32x4_extadd_pairwise_i16x8_u, 0xfd0000000000007full) \
M(i16x8_abs, 0xfd00000000000080ull) \
M(i16x8_neg, 0xfd00000000000081ull) \
M(i16x8_q15mulr_sat_s, 0xfd00000000000082ull) \
M(i16x8_all_true, 0xfd00000000000083ull) \
M(i16x8_bitmask, 0xfd00000000000084ull) \
M(i16x8_narrow_i32x4_s, 0xfd00000000000085ull) \
M(i16x8_narrow_i32x4_u, 0xfd00000000000086ull) \
M(i16x8_extend_low_i8x16_s, 0xfd00000000000087ull) \
M(i16x8_extend_high_i8x16_s, 0xfd00000000000088ull) \
M(i16x8_extend_low_i8x16_u, 0xfd00000000000089ull) \
M(i16x8_extend_high_i8x16_u, 0xfd0000000000008aull) \
M(i16x8_shl, 0xfd0000000000008bull) \
M(i16x8_shr_s, 0xfd0000000000008cull) \
M(i16x8_shr_u, 0xfd0000000000008dull) \
M(i16x8_add, 0xfd0000000000008eull) \
M(i16x8_add_sat_s, 0xfd0000000000008full) \
M(i16x8_add_sat_u, 0xfd00000000000090ull) \
M(i16x8_sub, 0xfd00000000000091ull) \
M(i16x8_sub_sat_s, 0xfd00000000000092ull) \
M(i16x8_sub_sat_u, 0xfd00000000000093ull) \
M(f64x2_nearest, 0xfd00000000000094ull) \
M(i16x8_mul, 0xfd00000000000095ull) \
M(i16x8_min_s, 0xfd00000000000096ull) \
M(i16x8_min_u, 0xfd00000000000097ull) \
M(i16x8_max_s, 0xfd00000000000098ull) \
M(i16x8_max_u, 0xfd00000000000099ull) \
M(i16x8_avgr_u, 0xfd0000000000009bull) \
M(i16x8_extmul_low_i8x16_s, 0xfd0000000000009cull) \
M(i16x8_extmul_high_i8x16_s, 0xfd0000000000009dull) \
M(i16x8_extmul_low_i8x16_u, 0xfd0000000000009eull) \
M(i16x8_extmul_high_i8x16_u, 0xfd0000000000009full) \
M(i32x4_abs, 0xfd000000000000a0ull) \
M(i32x4_neg, 0xfd000000000000a1ull) \
M(i32x4_all_true, 0xfd000000000000a3ull) \
M(i32x4_bitmask, 0xfd000000000000a4ull) \
M(i32x4_extend_low_i16x8_s, 0xfd000000000000a7ull) \
M(i32x4_extend_high_i16x8_s, 0xfd000000000000a8ull) \
M(i32x4_extend_low_i16x8_u, 0xfd000000000000a9ull) \
M(i32x4_extend_high_i16x8_u, 0xfd000000000000aaull) \
M(i32x4_shl, 0xfd000000000000abull) \
M(i32x4_shr_s, 0xfd000000000000acull) \
M(i32x4_shr_u, 0xfd000000000000adull) \
M(i32x4_add, 0xfd000000000000aeull) \
M(i32x4_sub, 0xfd000000000000b1ull) \
M(i32x4_mul, 0xfd000000000000b5ull) \
M(i32x4_min_s, 0xfd000000000000b6ull) \
M(i32x4_min_u, 0xfd000000000000b7ull) \
M(i32x4_max_s, 0xfd000000000000b8ull) \
M(i32x4_max_u, 0xfd000000000000b9ull) \
M(i32x4_dot_i16x8_s, 0xfd000000000000baull) \
M(i32x4_extmul_low_i16x8_s, 0xfd000000000000bcull) \
M(i32x4_extmul_high_i16x8_s, 0xfd000000000000bdull) \
M(i32x4_extmul_low_i16x8_u, 0xfd000000000000beull) \
M(i32x4_extmul_high_i16x8_u, 0xfd000000000000bfull) \
M(i64x2_abs, 0xfd000000000000c0ull) \
M(i64x2_neg, 0xfd000000000000c1ull) \
M(i64x2_all_true, 0xfd000000000000c3ull) \
M(i64x2_bitmask, 0xfd000000000000c4ull) \
M(i64x2_extend_low_i32x4_s, 0xfd000000000000c7ull) \
M(i64x2_extend_high_i32x4_s, 0xfd000000000000c8ull) \
M(i64x2_extend_low_i32x4_u, 0xfd000000000000c9ull) \
M(i64x2_extend_high_i32x4_u, 0xfd000000000000caull) \
M(i64x2_shl, 0xfd000000000000cbull) \
M(i64x2_shr_s, 0xfd000000000000ccull) \
M(i64x2_shr_u, 0xfd000000000000cdull) \
M(i64x2_add, 0xfd000000000000ceull) \
M(i64x2_sub, 0xfd000000000000d1ull) \
M(i64x2_mul, 0xfd000000000000d5ull) \
M(i64x2_eq, 0xfd000000000000d6ull) \
M(i64x2_ne, 0xfd000000000000d7ull) \
M(i64x2_lt_s, 0xfd000000000000d8ull) \
M(i64x2_gt_s, 0xfd000000000000d9ull) \
M(i64x2_le_s, 0xfd000000000000daull) \
M(i64x2_ge_s, 0xfd000000000000dbull) \
M(i64x2_extmul_low_i32x4_s, 0xfd000000000000dcull) \
M(i64x2_extmul_high_i32x4_s, 0xfd000000000000ddull) \
M(i64x2_extmul_low_i32x4_u, 0xfd000000000000deull) \
M(i64x2_extmul_high_i32x4_u, 0xfd000000000000dfull) \
M(f32x4_abs, 0xfd000000000000e0ull) \
M(f32x4_neg, 0xfd000000000000e1ull) \
M(f32x4_sqrt, 0xfd000000000000e3ull) \
M(f32x4_add, 0xfd000000000000e4ull) \
M(f32x4_sub, 0xfd000000000000e5ull) \
M(f32x4_mul, 0xfd000000000000e6ull) \
M(f32x4_div, 0xfd000000000000e7ull) \
M(f32x4_min, 0xfd000000000000e8ull) \
M(f32x4_max, 0xfd000000000000e9ull) \
M(f32x4_pmin, 0xfd000000000000eaull) \
M(f32x4_pmax, 0xfd000000000000ebull) \
M(f64x2_abs, 0xfd000000000000ecull) \
M(f64x2_neg, 0xfd000000000000edull) \
M(f64x2_sqrt, 0xfd000000000000efull) \
M(f64x2_add, 0xfd000000000000f0ull) \
M(f64x2_sub, 0xfd000000000000f1ull) \
M(f64x2_mul, 0xfd000000000000f2ull) \
M(f64x2_div, 0xfd000000000000f3ull) \
M(f64x2_min, 0xfd000000000000f4ull) \
M(f64x2_max, 0xfd000000000000f5ull) \
M(f64x2_pmin, 0xfd000000000000f6ull) \
M(f64x2_pmax, 0xfd000000000000f7ull) \
M(i32x4_trunc_sat_f32x4_s, 0xfd000000000000f8ull) \
M(i32x4_trunc_sat_f32x4_u, 0xfd000000000000f9ull) \
M(f32x4_convert_i32x4_s, 0xfd000000000000faull) \
M(f32x4_convert_i32x4_u, 0xfd000000000000fbull) \
M(i32x4_trunc_sat_f64x2_s_zero, 0xfd000000000000fcull) \
M(i32x4_trunc_sat_f64x2_u_zero, 0xfd000000000000fdull) \
M(f64x2_convert_low_i32x4_s, 0xfd000000000000feull) \
M(f64x2_convert_low_i32x4_u, 0xfd000000000000ffull)
#define ENUMERATE_WASM_OPCODES(M) \
ENUMERATE_SINGLE_BYTE_WASM_OPCODES(M) \
@ -228,25 +464,6 @@ namespace Instructions {
ENUMERATE_WASM_OPCODES(M)
#undef M
static constexpr u32 i32_trunc_sat_f32_s_second = 0,
i32_trunc_sat_f32_u_second = 1,
i32_trunc_sat_f64_s_second = 2,
i32_trunc_sat_f64_u_second = 3,
i64_trunc_sat_f32_s_second = 4,
i64_trunc_sat_f32_u_second = 5,
i64_trunc_sat_f64_s_second = 6,
i64_trunc_sat_f64_u_second = 7,
memory_init_second = 8,
data_drop_second = 9,
memory_copy_second = 10,
memory_fill_second = 11,
table_init_second = 12,
elem_drop_second = 13,
table_copy_second = 14,
table_grow_second = 15,
table_size_second = 16,
table_fill_second = 17;
}
}

View file

@ -11,6 +11,7 @@
#include <AK/MemoryStream.h>
#include <AK/ScopeGuard.h>
#include <AK/ScopeLogger.h>
#include <AK/UFixedBigInt.h>
#include <LibWasm/Types.h>
namespace Wasm {
@ -138,6 +139,8 @@ ParseResult<ValueType> ValueType::parse(Stream& stream)
return ValueType(F32);
case Constants::f64_tag:
return ValueType(F64);
case Constants::v128_tag:
return ValueType(V128);
case Constants::function_reference_tag:
return ValueType(FunctionReference);
case Constants::extern_reference_tag:
@ -677,24 +680,27 @@ ParseResult<Vector<Instruction>> Instruction::parse(Stream& stream, InstructionP
case Instructions::i64_extend32_s.value():
resulting_instructions.append(Instruction { opcode });
break;
case 0xfc: {
case 0xfc:
case 0xfd: {
// These are multibyte instructions.
auto selector_or_error = stream.read_value<LEB128<u32>>();
if (selector_or_error.is_error())
return with_eof_check(stream, ParseError::InvalidInput);
u32 selector = selector_or_error.release_value();
switch (selector) {
case Instructions::i32_trunc_sat_f32_s_second:
case Instructions::i32_trunc_sat_f32_u_second:
case Instructions::i32_trunc_sat_f64_s_second:
case Instructions::i32_trunc_sat_f64_u_second:
case Instructions::i64_trunc_sat_f32_s_second:
case Instructions::i64_trunc_sat_f32_u_second:
case Instructions::i64_trunc_sat_f64_s_second:
case Instructions::i64_trunc_sat_f64_u_second:
resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector } });
OpCode full_opcode = static_cast<u64>(opcode.value()) << 56 | selector;
switch (full_opcode.value()) {
case Instructions::i32_trunc_sat_f32_s.value():
case Instructions::i32_trunc_sat_f32_u.value():
case Instructions::i32_trunc_sat_f64_s.value():
case Instructions::i32_trunc_sat_f64_u.value():
case Instructions::i64_trunc_sat_f32_s.value():
case Instructions::i64_trunc_sat_f32_u.value():
case Instructions::i64_trunc_sat_f64_s.value():
case Instructions::i64_trunc_sat_f64_u.value():
resulting_instructions.append(Instruction { full_opcode });
break;
case Instructions::memory_init_second: {
case Instructions::memory_init.value(): {
auto index = GenericIndexParser<DataIndex>::parse(stream);
if (index.is_error())
return index.error();
@ -705,17 +711,17 @@ ParseResult<Vector<Instruction>> Instruction::parse(Stream& stream, InstructionP
auto unused = unused_or_error.release_value();
if (unused != 0x00)
return ParseError::InvalidImmediate;
resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector }, index.release_value() });
resulting_instructions.append(Instruction { full_opcode, index.release_value() });
break;
}
case Instructions::data_drop_second: {
case Instructions::data_drop.value(): {
auto index = GenericIndexParser<DataIndex>::parse(stream);
if (index.is_error())
return index.error();
resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector }, index.release_value() });
resulting_instructions.append(Instruction { full_opcode, index.release_value() });
break;
}
case Instructions::memory_copy_second: {
case Instructions::memory_copy.value(): {
for (size_t i = 0; i < 2; ++i) {
auto unused_or_error = stream.read_value<u8>();
if (unused_or_error.is_error())
@ -725,10 +731,10 @@ ParseResult<Vector<Instruction>> Instruction::parse(Stream& stream, InstructionP
if (unused != 0x00)
return ParseError::InvalidImmediate;
}
resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector } });
resulting_instructions.append(Instruction { full_opcode });
break;
}
case Instructions::memory_fill_second: {
case Instructions::memory_fill.value(): {
auto unused_or_error = stream.read_value<u8>();
if (unused_or_error.is_error())
return with_eof_check(stream, ParseError::InvalidInput);
@ -736,45 +742,341 @@ ParseResult<Vector<Instruction>> Instruction::parse(Stream& stream, InstructionP
auto unused = unused_or_error.release_value();
if (unused != 0x00)
return ParseError::InvalidImmediate;
resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector } });
resulting_instructions.append(Instruction { full_opcode });
break;
}
case Instructions::table_init_second: {
case Instructions::table_init.value(): {
auto element_index = GenericIndexParser<ElementIndex>::parse(stream);
if (element_index.is_error())
return element_index.error();
auto table_index = GenericIndexParser<TableIndex>::parse(stream);
if (table_index.is_error())
return table_index.error();
resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector }, TableElementArgs { element_index.release_value(), table_index.release_value() } });
resulting_instructions.append(Instruction { full_opcode, TableElementArgs { element_index.release_value(), table_index.release_value() } });
break;
}
case Instructions::elem_drop_second: {
case Instructions::elem_drop.value(): {
auto element_index = GenericIndexParser<ElementIndex>::parse(stream);
if (element_index.is_error())
return element_index.error();
resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector }, element_index.release_value() });
resulting_instructions.append(Instruction { full_opcode, element_index.release_value() });
break;
}
case Instructions::table_copy_second: {
case Instructions::table_copy.value(): {
auto lhs = GenericIndexParser<TableIndex>::parse(stream);
if (lhs.is_error())
return lhs.error();
auto rhs = GenericIndexParser<TableIndex>::parse(stream);
if (rhs.is_error())
return rhs.error();
resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector }, TableTableArgs { lhs.release_value(), rhs.release_value() } });
resulting_instructions.append(Instruction { full_opcode, TableTableArgs { lhs.release_value(), rhs.release_value() } });
break;
}
case Instructions::table_grow_second:
case Instructions::table_size_second:
case Instructions::table_fill_second: {
case Instructions::table_grow.value():
case Instructions::table_size.value():
case Instructions::table_fill.value(): {
auto index = GenericIndexParser<TableIndex>::parse(stream);
if (index.is_error())
return index.error();
resulting_instructions.append(Instruction { OpCode { 0xfc00 | selector }, index.release_value() });
resulting_instructions.append(Instruction { full_opcode, index.release_value() });
break;
}
case Instructions::v128_load.value():
case Instructions::v128_load8x8_s.value():
case Instructions::v128_load8x8_u.value():
case Instructions::v128_load16x4_s.value():
case Instructions::v128_load16x4_u.value():
case Instructions::v128_load32x2_s.value():
case Instructions::v128_load32x2_u.value():
case Instructions::v128_load8_splat.value():
case Instructions::v128_load16_splat.value():
case Instructions::v128_load32_splat.value():
case Instructions::v128_load64_splat.value():
case Instructions::v128_store.value(): {
// op (align offset)
auto align_or_error = stream.read_value<LEB128<size_t>>();
if (align_or_error.is_error())
return with_eof_check(stream, ParseError::ExpectedIndex);
size_t align = align_or_error.release_value();
auto offset_or_error = stream.read_value<LEB128<size_t>>();
if (offset_or_error.is_error())
return with_eof_check(stream, ParseError::ExpectedIndex);
size_t offset = offset_or_error.release_value();
resulting_instructions.append(Instruction { full_opcode, MemoryArgument { static_cast<u32>(align), static_cast<u32>(offset) } });
break;
}
case Instructions::v128_load8_lane.value():
case Instructions::v128_load16_lane.value():
case Instructions::v128_load32_lane.value():
case Instructions::v128_load64_lane.value():
case Instructions::v128_store8_lane.value():
case Instructions::v128_store16_lane.value():
case Instructions::v128_store32_lane.value():
case Instructions::v128_store64_lane.value(): {
// op (align offset) (index)
auto align_or_error = stream.read_value<LEB128<size_t>>();
if (align_or_error.is_error())
return with_eof_check(stream, ParseError::ExpectedIndex);
size_t align = align_or_error.release_value();
auto offset_or_error = stream.read_value<LEB128<size_t>>();
if (offset_or_error.is_error())
return with_eof_check(stream, ParseError::ExpectedIndex);
size_t offset = offset_or_error.release_value();
auto index_or_error = stream.read_value<u8>();
if (index_or_error.is_error())
return with_eof_check(stream, ParseError::InvalidInput);
auto index = index_or_error.release_value();
resulting_instructions.append(Instruction { full_opcode, MemoryAndLaneArgument { { static_cast<u32>(align), static_cast<u32>(offset) }, index } });
break;
}
case Instructions::v128_const.value(): {
// op (literal:16)
auto value_or_error = stream.read_value<LittleEndian<u128>>();
if (value_or_error.is_error())
return with_eof_check(stream, ParseError::InvalidImmediate);
resulting_instructions.append(Instruction { full_opcode, value_or_error.release_value() });
break;
}
case Instructions::i8x16_shuffle.value(): {
// op 16x(lane)
u8 lanes[16];
for (size_t i = 0; i < 16; ++i) {
auto value_or_error = stream.read_value<u8>();
if (value_or_error.is_error())
return with_eof_check(stream, ParseError::InvalidInput);
lanes[i] = value_or_error.release_value();
}
resulting_instructions.append(Instruction { full_opcode, ShuffleArgument(lanes) });
break;
}
case Instructions::i8x16_extract_lane_s.value():
case Instructions::i8x16_extract_lane_u.value():
case Instructions::i8x16_replace_lane.value():
case Instructions::i16x8_extract_lane_s.value():
case Instructions::i16x8_extract_lane_u.value():
case Instructions::i16x8_replace_lane.value():
case Instructions::i32x4_extract_lane.value():
case Instructions::i32x4_replace_lane.value():
case Instructions::i64x2_extract_lane.value():
case Instructions::i64x2_replace_lane.value():
case Instructions::f32x4_extract_lane.value():
case Instructions::f32x4_replace_lane.value():
case Instructions::f64x2_extract_lane.value():
case Instructions::f64x2_replace_lane.value(): {
// op (lane)
auto lane_or_error = stream.read_value<u8>();
if (lane_or_error.is_error())
return with_eof_check(stream, ParseError::InvalidInput);
auto lane = lane_or_error.release_value();
resulting_instructions.append(Instruction { full_opcode, LaneIndex { lane } });
break;
}
case Instructions::i8x16_swizzle.value():
case Instructions::i8x16_splat.value():
case Instructions::i16x8_splat.value():
case Instructions::i32x4_splat.value():
case Instructions::i64x2_splat.value():
case Instructions::f32x4_splat.value():
case Instructions::f64x2_splat.value():
case Instructions::i8x16_eq.value():
case Instructions::i8x16_ne.value():
case Instructions::i8x16_lt_s.value():
case Instructions::i8x16_lt_u.value():
case Instructions::i8x16_gt_s.value():
case Instructions::i8x16_gt_u.value():
case Instructions::i8x16_le_s.value():
case Instructions::i8x16_le_u.value():
case Instructions::i8x16_ge_s.value():
case Instructions::i8x16_ge_u.value():
case Instructions::i16x8_eq.value():
case Instructions::i16x8_ne.value():
case Instructions::i16x8_lt_s.value():
case Instructions::i16x8_lt_u.value():
case Instructions::i16x8_gt_s.value():
case Instructions::i16x8_gt_u.value():
case Instructions::i16x8_le_s.value():
case Instructions::i16x8_le_u.value():
case Instructions::i16x8_ge_s.value():
case Instructions::i16x8_ge_u.value():
case Instructions::i32x4_eq.value():
case Instructions::i32x4_ne.value():
case Instructions::i32x4_lt_s.value():
case Instructions::i32x4_lt_u.value():
case Instructions::i32x4_gt_s.value():
case Instructions::i32x4_gt_u.value():
case Instructions::i32x4_le_s.value():
case Instructions::i32x4_le_u.value():
case Instructions::i32x4_ge_s.value():
case Instructions::i32x4_ge_u.value():
case Instructions::f32x4_eq.value():
case Instructions::f32x4_ne.value():
case Instructions::f32x4_lt.value():
case Instructions::f32x4_gt.value():
case Instructions::f32x4_le.value():
case Instructions::f32x4_ge.value():
case Instructions::f64x2_eq.value():
case Instructions::f64x2_ne.value():
case Instructions::f64x2_lt.value():
case Instructions::f64x2_gt.value():
case Instructions::f64x2_le.value():
case Instructions::f64x2_ge.value():
case Instructions::v128_not.value():
case Instructions::v128_and.value():
case Instructions::v128_andnot.value():
case Instructions::v128_or.value():
case Instructions::v128_xor.value():
case Instructions::v128_bitselect.value():
case Instructions::v128_any_true.value():
case Instructions::v128_load32_zero.value():
case Instructions::v128_load64_zero.value():
case Instructions::f32x4_demote_f64x2_zero.value():
case Instructions::f64x2_promote_low_f32x4.value():
case Instructions::i8x16_abs.value():
case Instructions::i8x16_neg.value():
case Instructions::i8x16_popcnt.value():
case Instructions::i8x16_all_true.value():
case Instructions::i8x16_bitmask.value():
case Instructions::i8x16_narrow_i16x8_s.value():
case Instructions::i8x16_narrow_i16x8_u.value():
case Instructions::f32x4_ceil.value():
case Instructions::f32x4_floor.value():
case Instructions::f32x4_trunc.value():
case Instructions::f32x4_nearest.value():
case Instructions::i8x16_shl.value():
case Instructions::i8x16_shr_s.value():
case Instructions::i8x16_shr_u.value():
case Instructions::i8x16_add.value():
case Instructions::i8x16_add_sat_s.value():
case Instructions::i8x16_add_sat_u.value():
case Instructions::i8x16_sub.value():
case Instructions::i8x16_sub_sat_s.value():
case Instructions::i8x16_sub_sat_u.value():
case Instructions::f64x2_ceil.value():
case Instructions::f64x2_floor.value():
case Instructions::i8x16_min_s.value():
case Instructions::i8x16_min_u.value():
case Instructions::i8x16_max_s.value():
case Instructions::i8x16_max_u.value():
case Instructions::f64x2_trunc.value():
case Instructions::i8x16_avgr_u.value():
case Instructions::i16x8_extadd_pairwise_i8x16_s.value():
case Instructions::i16x8_extadd_pairwise_i8x16_u.value():
case Instructions::i32x4_extadd_pairwise_i16x8_s.value():
case Instructions::i32x4_extadd_pairwise_i16x8_u.value():
case Instructions::i16x8_abs.value():
case Instructions::i16x8_neg.value():
case Instructions::i16x8_q15mulr_sat_s.value():
case Instructions::i16x8_all_true.value():
case Instructions::i16x8_bitmask.value():
case Instructions::i16x8_narrow_i32x4_s.value():
case Instructions::i16x8_narrow_i32x4_u.value():
case Instructions::i16x8_extend_low_i8x16_s.value():
case Instructions::i16x8_extend_high_i8x16_s.value():
case Instructions::i16x8_extend_low_i8x16_u.value():
case Instructions::i16x8_extend_high_i8x16_u.value():
case Instructions::i16x8_shl.value():
case Instructions::i16x8_shr_s.value():
case Instructions::i16x8_shr_u.value():
case Instructions::i16x8_add.value():
case Instructions::i16x8_add_sat_s.value():
case Instructions::i16x8_add_sat_u.value():
case Instructions::i16x8_sub.value():
case Instructions::i16x8_sub_sat_s.value():
case Instructions::i16x8_sub_sat_u.value():
case Instructions::f64x2_nearest.value():
case Instructions::i16x8_mul.value():
case Instructions::i16x8_min_s.value():
case Instructions::i16x8_min_u.value():
case Instructions::i16x8_max_s.value():
case Instructions::i16x8_max_u.value():
case Instructions::i16x8_avgr_u.value():
case Instructions::i16x8_extmul_low_i8x16_s.value():
case Instructions::i16x8_extmul_high_i8x16_s.value():
case Instructions::i16x8_extmul_low_i8x16_u.value():
case Instructions::i16x8_extmul_high_i8x16_u.value():
case Instructions::i32x4_abs.value():
case Instructions::i32x4_neg.value():
case Instructions::i32x4_all_true.value():
case Instructions::i32x4_bitmask.value():
case Instructions::i32x4_extend_low_i16x8_s.value():
case Instructions::i32x4_extend_high_i16x8_s.value():
case Instructions::i32x4_extend_low_i16x8_u.value():
case Instructions::i32x4_extend_high_i16x8_u.value():
case Instructions::i32x4_shl.value():
case Instructions::i32x4_shr_s.value():
case Instructions::i32x4_shr_u.value():
case Instructions::i32x4_add.value():
case Instructions::i32x4_sub.value():
case Instructions::i32x4_mul.value():
case Instructions::i32x4_min_s.value():
case Instructions::i32x4_min_u.value():
case Instructions::i32x4_max_s.value():
case Instructions::i32x4_max_u.value():
case Instructions::i32x4_dot_i16x8_s.value():
case Instructions::i32x4_extmul_low_i16x8_s.value():
case Instructions::i32x4_extmul_high_i16x8_s.value():
case Instructions::i32x4_extmul_low_i16x8_u.value():
case Instructions::i32x4_extmul_high_i16x8_u.value():
case Instructions::i64x2_abs.value():
case Instructions::i64x2_neg.value():
case Instructions::i64x2_all_true.value():
case Instructions::i64x2_bitmask.value():
case Instructions::i64x2_extend_low_i32x4_s.value():
case Instructions::i64x2_extend_high_i32x4_s.value():
case Instructions::i64x2_extend_low_i32x4_u.value():
case Instructions::i64x2_extend_high_i32x4_u.value():
case Instructions::i64x2_shl.value():
case Instructions::i64x2_shr_s.value():
case Instructions::i64x2_shr_u.value():
case Instructions::i64x2_add.value():
case Instructions::i64x2_sub.value():
case Instructions::i64x2_mul.value():
case Instructions::i64x2_eq.value():
case Instructions::i64x2_ne.value():
case Instructions::i64x2_lt_s.value():
case Instructions::i64x2_gt_s.value():
case Instructions::i64x2_le_s.value():
case Instructions::i64x2_ge_s.value():
case Instructions::i64x2_extmul_low_i32x4_s.value():
case Instructions::i64x2_extmul_high_i32x4_s.value():
case Instructions::i64x2_extmul_low_i32x4_u.value():
case Instructions::i64x2_extmul_high_i32x4_u.value():
case Instructions::f32x4_abs.value():
case Instructions::f32x4_neg.value():
case Instructions::f32x4_sqrt.value():
case Instructions::f32x4_add.value():
case Instructions::f32x4_sub.value():
case Instructions::f32x4_mul.value():
case Instructions::f32x4_div.value():
case Instructions::f32x4_min.value():
case Instructions::f32x4_max.value():
case Instructions::f32x4_pmin.value():
case Instructions::f32x4_pmax.value():
case Instructions::f64x2_abs.value():
case Instructions::f64x2_neg.value():
case Instructions::f64x2_sqrt.value():
case Instructions::f64x2_add.value():
case Instructions::f64x2_sub.value():
case Instructions::f64x2_mul.value():
case Instructions::f64x2_div.value():
case Instructions::f64x2_min.value():
case Instructions::f64x2_max.value():
case Instructions::f64x2_pmin.value():
case Instructions::f64x2_pmax.value():
case Instructions::i32x4_trunc_sat_f32x4_s.value():
case Instructions::i32x4_trunc_sat_f32x4_u.value():
case Instructions::f32x4_convert_i32x4_s.value():
case Instructions::f32x4_convert_i32x4_u.value():
case Instructions::i32x4_trunc_sat_f64x2_s_zero.value():
case Instructions::i32x4_trunc_sat_f64x2_u_zero.value():
case Instructions::f64x2_convert_low_i32x4_s.value():
case Instructions::f64x2_convert_low_i32x4_u.value():
// op
resulting_instructions.append(Instruction { full_opcode });
break;
default:
return ParseError::UnknownInstruction;
}

View file

@ -433,6 +433,15 @@ void Printer::print(Wasm::Instruction const& instruction)
[&](TableIndex const& index) { print("(table index {})", index.value()); },
[&](Instruction::IndirectCallArgs const& args) { print("(indirect (type index {}) (table index {}))", args.type.value(), args.table.value()); },
[&](Instruction::MemoryArgument const& args) { print("(memory (align {}) (offset {}))", args.align, args.offset); },
[&](Instruction::MemoryAndLaneArgument const& args) { print("(memory (align {}) (offset {})) (lane {})", args.memory.align, args.memory.offset, args.lane); },
[&](Instruction::LaneIndex const& args) { print("(lane {})", args.lane); },
[&](Instruction::ShuffleArgument const& args) {
print("{{ {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} }}",
args.lanes[0], args.lanes[1], args.lanes[2], args.lanes[3],
args.lanes[4], args.lanes[5], args.lanes[6], args.lanes[7],
args.lanes[8], args.lanes[9], args.lanes[10], args.lanes[11],
args.lanes[12], args.lanes[13], args.lanes[14], args.lanes[15]);
},
[&](Instruction::StructuredInstructionArgs const& args) {
print("(structured\n");
TemporaryChange change { m_indent, m_indent + 1 };
@ -637,14 +646,17 @@ void Printer::print(Wasm::Value const& value)
{
print_indent();
print("{} ", value.value().visit([&]<typename T>(T const& value) {
if constexpr (IsSame<Wasm::Reference, T>)
if constexpr (IsSame<Wasm::Reference, T>) {
return DeprecatedString::formatted(
"addr({})",
value.ref().visit(
[](Wasm::Reference::Null const&) { return DeprecatedString("null"); },
[](auto const& ref) { return DeprecatedString::number(ref.address.value()); }));
else
} else if constexpr (IsSame<u128, T>) {
return DeprecatedString::formatted("v128({:x})", value);
} else {
return DeprecatedString::formatted("{}", value);
}
}));
TemporaryChange<size_t> change { m_indent, 0 };
print(value.type());
@ -861,6 +873,242 @@ HashMap<Wasm::OpCode, DeprecatedString> Wasm::Names::instruction_names {
{ Instructions::table_grow, "table.grow" },
{ Instructions::table_size, "table.size" },
{ Instructions::table_fill, "table.fill" },
{ Instructions::v128_load, "v128.load" },
{ Instructions::v128_load8x8_s, "v128.load8x8_s" },
{ Instructions::v128_load8x8_u, "v128.load8x8_u" },
{ Instructions::v128_load16x4_s, "v128.load16x4_s" },
{ Instructions::v128_load16x4_u, "v128.load16x4_u" },
{ Instructions::v128_load32x2_s, "v128.load32x2_s" },
{ Instructions::v128_load32x2_u, "v128.load32x2_u" },
{ Instructions::v128_load8_splat, "v128.load8_splat" },
{ Instructions::v128_load16_splat, "v128.load16_splat" },
{ Instructions::v128_load32_splat, "v128.load32_splat" },
{ Instructions::v128_load64_splat, "v128.load64_splat" },
{ Instructions::v128_store, "v128.store" },
{ Instructions::v128_const, "v128.const" },
{ Instructions::i8x16_shuffle, "i8x16.shuffle" },
{ Instructions::i8x16_swizzle, "i8x16.swizzle" },
{ Instructions::i8x16_splat, "i8x16.splat" },
{ Instructions::i16x8_splat, "i16x8.splat" },
{ Instructions::i32x4_splat, "i32x4.splat" },
{ Instructions::i64x2_splat, "i64x2.splat" },
{ Instructions::f32x4_splat, "f32x4.splat" },
{ Instructions::f64x2_splat, "f64x2.splat" },
{ Instructions::i8x16_extract_lane_s, "i8x16.extract_lane_s" },
{ Instructions::i8x16_extract_lane_u, "i8x16.extract_lane_u" },
{ Instructions::i8x16_replace_lane, "i8x16.replace_lane" },
{ Instructions::i16x8_extract_lane_s, "i16x8.extract_lane_s" },
{ Instructions::i16x8_extract_lane_u, "i16x8.extract_lane_u" },
{ Instructions::i16x8_replace_lane, "i16x8.replace_lane" },
{ Instructions::i32x4_extract_lane, "i32x4.extract_lane" },
{ Instructions::i32x4_replace_lane, "i32x4.replace_lane" },
{ Instructions::i64x2_extract_lane, "i64x2.extract_lane" },
{ Instructions::i64x2_replace_lane, "i64x2.replace_lane" },
{ Instructions::f32x4_extract_lane, "f32x4.extract_lane" },
{ Instructions::f32x4_replace_lane, "f32x4.replace_lane" },
{ Instructions::f64x2_extract_lane, "f64x2.extract_lane" },
{ Instructions::f64x2_replace_lane, "f64x2.replace_lane" },
{ Instructions::i8x16_eq, "i8x16.eq" },
{ Instructions::i8x16_ne, "i8x16.ne" },
{ Instructions::i8x16_lt_s, "i8x16.lt_s" },
{ Instructions::i8x16_lt_u, "i8x16.lt_u" },
{ Instructions::i8x16_gt_s, "i8x16.gt_s" },
{ Instructions::i8x16_gt_u, "i8x16.gt_u" },
{ Instructions::i8x16_le_s, "i8x16.le_s" },
{ Instructions::i8x16_le_u, "i8x16.le_u" },
{ Instructions::i8x16_ge_s, "i8x16.ge_s" },
{ Instructions::i8x16_ge_u, "i8x16.ge_u" },
{ Instructions::i16x8_eq, "i16x8.eq" },
{ Instructions::i16x8_ne, "i16x8.ne" },
{ Instructions::i16x8_lt_s, "i16x8.lt_s" },
{ Instructions::i16x8_lt_u, "i16x8.lt_u" },
{ Instructions::i16x8_gt_s, "i16x8.gt_s" },
{ Instructions::i16x8_gt_u, "i16x8.gt_u" },
{ Instructions::i16x8_le_s, "i16x8.le_s" },
{ Instructions::i16x8_le_u, "i16x8.le_u" },
{ Instructions::i16x8_ge_s, "i16x8.ge_s" },
{ Instructions::i16x8_ge_u, "i16x8.ge_u" },
{ Instructions::i32x4_eq, "i32x4.eq" },
{ Instructions::i32x4_ne, "i32x4.ne" },
{ Instructions::i32x4_lt_s, "i32x4.lt_s" },
{ Instructions::i32x4_lt_u, "i32x4.lt_u" },
{ Instructions::i32x4_gt_s, "i32x4.gt_s" },
{ Instructions::i32x4_gt_u, "i32x4.gt_u" },
{ Instructions::i32x4_le_s, "i32x4.le_s" },
{ Instructions::i32x4_le_u, "i32x4.le_u" },
{ Instructions::i32x4_ge_s, "i32x4.ge_s" },
{ Instructions::i32x4_ge_u, "i32x4.ge_u" },
{ Instructions::f32x4_eq, "f32x4.eq" },
{ Instructions::f32x4_ne, "f32x4.ne" },
{ Instructions::f32x4_lt, "f32x4.lt" },
{ Instructions::f32x4_gt, "f32x4.gt" },
{ Instructions::f32x4_le, "f32x4.le" },
{ Instructions::f32x4_ge, "f32x4.ge" },
{ Instructions::f64x2_eq, "f64x2.eq" },
{ Instructions::f64x2_ne, "f64x2.ne" },
{ Instructions::f64x2_lt, "f64x2.lt" },
{ Instructions::f64x2_gt, "f64x2.gt" },
{ Instructions::f64x2_le, "f64x2.le" },
{ Instructions::f64x2_ge, "f64x2.ge" },
{ Instructions::v128_not, "v128.not" },
{ Instructions::v128_and, "v128.and" },
{ Instructions::v128_andnot, "v128.andnot" },
{ Instructions::v128_or, "v128.or" },
{ Instructions::v128_xor, "v128.xor" },
{ Instructions::v128_bitselect, "v128.bitselect" },
{ Instructions::v128_any_true, "v128.any_true" },
{ Instructions::v128_load8_lane, "v128.load8_lane" },
{ Instructions::v128_load16_lane, "v128.load16_lane" },
{ Instructions::v128_load32_lane, "v128.load32_lane" },
{ Instructions::v128_load64_lane, "v128.load64_lane" },
{ Instructions::v128_store8_lane, "v128.store8_lane" },
{ Instructions::v128_store16_lane, "v128.store16_lane" },
{ Instructions::v128_store32_lane, "v128.store32_lane" },
{ Instructions::v128_store64_lane, "v128.store64_lane" },
{ Instructions::v128_load32_zero, "v128.load32_zero" },
{ Instructions::v128_load64_zero, "v128.load64_zero" },
{ Instructions::f32x4_demote_f64x2_zero, "f32x4.demote_f64x2_zero" },
{ Instructions::f64x2_promote_low_f32x4, "f64x2.promote_low_f32x4" },
{ Instructions::i8x16_abs, "i8x16.abs" },
{ Instructions::i8x16_neg, "i8x16.neg" },
{ Instructions::i8x16_popcnt, "i8x16.popcnt" },
{ Instructions::i8x16_all_true, "i8x16.all_true" },
{ Instructions::i8x16_bitmask, "i8x16.bitmask" },
{ Instructions::i8x16_narrow_i16x8_s, "i8x16.narrow_i16x8_s" },
{ Instructions::i8x16_narrow_i16x8_u, "i8x16.narrow_i16x8_u" },
{ Instructions::f32x4_ceil, "f32x4.ceil" },
{ Instructions::f32x4_floor, "f32x4.floor" },
{ Instructions::f32x4_trunc, "f32x4.trunc" },
{ Instructions::f32x4_nearest, "f32x4.nearest" },
{ Instructions::i8x16_shl, "i8x16.shl" },
{ Instructions::i8x16_shr_s, "i8x16.shr_s" },
{ Instructions::i8x16_shr_u, "i8x16.shr_u" },
{ Instructions::i8x16_add, "i8x16.add" },
{ Instructions::i8x16_add_sat_s, "i8x16.add_sat_s" },
{ Instructions::i8x16_add_sat_u, "i8x16.add_sat_u" },
{ Instructions::i8x16_sub, "i8x16.sub" },
{ Instructions::i8x16_sub_sat_s, "i8x16.sub_sat_s" },
{ Instructions::i8x16_sub_sat_u, "i8x16.sub_sat_u" },
{ Instructions::f64x2_ceil, "f64x2.ceil" },
{ Instructions::f64x2_floor, "f64x2.floor" },
{ Instructions::i8x16_min_s, "i8x16.min_s" },
{ Instructions::i8x16_min_u, "i8x16.min_u" },
{ Instructions::i8x16_max_s, "i8x16.max_s" },
{ Instructions::i8x16_max_u, "i8x16.max_u" },
{ Instructions::f64x2_trunc, "f64x2.trunc" },
{ Instructions::i8x16_avgr_u, "i8x16.avgr_u" },
{ Instructions::i16x8_extadd_pairwise_i8x16_s, "i16x8.extadd_pairwise_i8x16_s" },
{ Instructions::i16x8_extadd_pairwise_i8x16_u, "i16x8.extadd_pairwise_i8x16_u" },
{ Instructions::i32x4_extadd_pairwise_i16x8_s, "i32x4.extadd_pairwise_i16x8_s" },
{ Instructions::i32x4_extadd_pairwise_i16x8_u, "i32x4.extadd_pairwise_i16x8_u" },
{ Instructions::i16x8_abs, "i16x8.abs" },
{ Instructions::i16x8_neg, "i16x8.neg" },
{ Instructions::i16x8_q15mulr_sat_s, "i16x8.q15mulr_sat_s" },
{ Instructions::i16x8_all_true, "i16x8.all_true" },
{ Instructions::i16x8_bitmask, "i16x8.bitmask" },
{ Instructions::i16x8_narrow_i32x4_s, "i16x8.narrow_i32x4_s" },
{ Instructions::i16x8_narrow_i32x4_u, "i16x8.narrow_i32x4_u" },
{ Instructions::i16x8_extend_low_i8x16_s, "i16x8.extend_low_i8x16_s" },
{ Instructions::i16x8_extend_high_i8x16_s, "i16x8.extend_high_i8x16_s" },
{ Instructions::i16x8_extend_low_i8x16_u, "i16x8.extend_low_i8x16_u" },
{ Instructions::i16x8_extend_high_i8x16_u, "i16x8.extend_high_i8x16_u" },
{ Instructions::i16x8_shl, "i16x8.shl" },
{ Instructions::i16x8_shr_s, "i16x8.shr_s" },
{ Instructions::i16x8_shr_u, "i16x8.shr_u" },
{ Instructions::i16x8_add, "i16x8.add" },
{ Instructions::i16x8_add_sat_s, "i16x8.add_sat_s" },
{ Instructions::i16x8_add_sat_u, "i16x8.add_sat_u" },
{ Instructions::i16x8_sub, "i16x8.sub" },
{ Instructions::i16x8_sub_sat_s, "i16x8.sub_sat_s" },
{ Instructions::i16x8_sub_sat_u, "i16x8.sub_sat_u" },
{ Instructions::f64x2_nearest, "f64x2.nearest" },
{ Instructions::i16x8_mul, "i16x8.mul" },
{ Instructions::i16x8_min_s, "i16x8.min_s" },
{ Instructions::i16x8_min_u, "i16x8.min_u" },
{ Instructions::i16x8_max_s, "i16x8.max_s" },
{ Instructions::i16x8_max_u, "i16x8.max_u" },
{ Instructions::i16x8_avgr_u, "i16x8.avgr_u" },
{ Instructions::i16x8_extmul_low_i8x16_s, "i16x8.extmul_low_i8x16_s" },
{ Instructions::i16x8_extmul_high_i8x16_s, "i16x8.extmul_high_i8x16_s" },
{ Instructions::i16x8_extmul_low_i8x16_u, "i16x8.extmul_low_i8x16_u" },
{ Instructions::i16x8_extmul_high_i8x16_u, "i16x8.extmul_high_i8x16_u" },
{ Instructions::i32x4_abs, "i32x4.abs" },
{ Instructions::i32x4_neg, "i32x4.neg" },
{ Instructions::i32x4_all_true, "i32x4.all_true" },
{ Instructions::i32x4_bitmask, "i32x4.bitmask" },
{ Instructions::i32x4_extend_low_i16x8_s, "i32x4.extend_low_i16x8_s" },
{ Instructions::i32x4_extend_high_i16x8_s, "i32x4.extend_high_i16x8_s" },
{ Instructions::i32x4_extend_low_i16x8_u, "i32x4.extend_low_i16x8_u" },
{ Instructions::i32x4_extend_high_i16x8_u, "i32x4.extend_high_i16x8_u" },
{ Instructions::i32x4_shl, "i32x4.shl" },
{ Instructions::i32x4_shr_s, "i32x4.shr_s" },
{ Instructions::i32x4_shr_u, "i32x4.shr_u" },
{ Instructions::i32x4_add, "i32x4.add" },
{ Instructions::i32x4_sub, "i32x4.sub" },
{ Instructions::i32x4_mul, "i32x4.mul" },
{ Instructions::i32x4_min_s, "i32x4.min_s" },
{ Instructions::i32x4_min_u, "i32x4.min_u" },
{ Instructions::i32x4_max_s, "i32x4.max_s" },
{ Instructions::i32x4_max_u, "i32x4.max_u" },
{ Instructions::i32x4_dot_i16x8_s, "i32x4.dot_i16x8_s" },
{ Instructions::i32x4_extmul_low_i16x8_s, "i32x4.extmul_low_i16x8_s" },
{ Instructions::i32x4_extmul_high_i16x8_s, "i32x4.extmul_high_i16x8_s" },
{ Instructions::i32x4_extmul_low_i16x8_u, "i32x4.extmul_low_i16x8_u" },
{ Instructions::i32x4_extmul_high_i16x8_u, "i32x4.extmul_high_i16x8_u" },
{ Instructions::i64x2_abs, "i64x2.abs" },
{ Instructions::i64x2_neg, "i64x2.neg" },
{ Instructions::i64x2_all_true, "i64x2.all_true" },
{ Instructions::i64x2_bitmask, "i64x2.bitmask" },
{ Instructions::i64x2_extend_low_i32x4_s, "i64x2.extend_low_i32x4_s" },
{ Instructions::i64x2_extend_high_i32x4_s, "i64x2.extend_high_i32x4_s" },
{ Instructions::i64x2_extend_low_i32x4_u, "i64x2.extend_low_i32x4_u" },
{ Instructions::i64x2_extend_high_i32x4_u, "i64x2.extend_high_i32x4_u" },
{ Instructions::i64x2_shl, "i64x2.shl" },
{ Instructions::i64x2_shr_s, "i64x2.shr_s" },
{ Instructions::i64x2_shr_u, "i64x2.shr_u" },
{ Instructions::i64x2_add, "i64x2.add" },
{ Instructions::i64x2_sub, "i64x2.sub" },
{ Instructions::i64x2_mul, "i64x2.mul" },
{ Instructions::i64x2_eq, "i64x2.eq" },
{ Instructions::i64x2_ne, "i64x2.ne" },
{ Instructions::i64x2_lt_s, "i64x2.lt_s" },
{ Instructions::i64x2_gt_s, "i64x2.gt_s" },
{ Instructions::i64x2_le_s, "i64x2.le_s" },
{ Instructions::i64x2_ge_s, "i64x2.ge_s" },
{ Instructions::i64x2_extmul_low_i32x4_s, "i64x2.extmul_low_i32x4_s" },
{ Instructions::i64x2_extmul_high_i32x4_s, "i64x2.extmul_high_i32x4_s" },
{ Instructions::i64x2_extmul_low_i32x4_u, "i64x2.extmul_low_i32x4_u" },
{ Instructions::i64x2_extmul_high_i32x4_u, "i64x2.extmul_high_i32x4_u" },
{ Instructions::f32x4_abs, "f32x4.abs" },
{ Instructions::f32x4_neg, "f32x4.neg" },
{ Instructions::f32x4_sqrt, "f32x4.sqrt" },
{ Instructions::f32x4_add, "f32x4.add" },
{ Instructions::f32x4_sub, "f32x4.sub" },
{ Instructions::f32x4_mul, "f32x4.mul" },
{ Instructions::f32x4_div, "f32x4.div" },
{ Instructions::f32x4_min, "f32x4.min" },
{ Instructions::f32x4_max, "f32x4.max" },
{ Instructions::f32x4_pmin, "f32x4.pmin" },
{ Instructions::f32x4_pmax, "f32x4.pmax" },
{ Instructions::f64x2_abs, "f64x2.abs" },
{ Instructions::f64x2_neg, "f64x2.neg" },
{ Instructions::f64x2_sqrt, "f64x2.sqrt" },
{ Instructions::f64x2_add, "f64x2.add" },
{ Instructions::f64x2_sub, "f64x2.sub" },
{ Instructions::f64x2_mul, "f64x2.mul" },
{ Instructions::f64x2_div, "f64x2.div" },
{ Instructions::f64x2_min, "f64x2.min" },
{ Instructions::f64x2_max, "f64x2.max" },
{ Instructions::f64x2_pmin, "f64x2.pmin" },
{ Instructions::f64x2_pmax, "f64x2.pmax" },
{ Instructions::i32x4_trunc_sat_f32x4_s, "i32x4.trunc_sat_f32x4_s" },
{ Instructions::i32x4_trunc_sat_f32x4_u, "i32x4.trunc_sat_f32x4_u" },
{ Instructions::f32x4_convert_i32x4_s, "f32x4.convert_i32x4_s" },
{ Instructions::f32x4_convert_i32x4_u, "f32x4.convert_i32x4_u" },
{ Instructions::i32x4_trunc_sat_f64x2_s_zero, "i32x4.trunc_sat_f64x2_s_zero" },
{ Instructions::i32x4_trunc_sat_f64x2_u_zero, "i32x4.trunc_sat_f64x2_u_zero" },
{ Instructions::f64x2_convert_low_i32x4_s, "f64x2.convert_low_i32x4_s" },
{ Instructions::f64x2_convert_low_i32x4_u, "f64x2.convert_low_i32x4_u" },
{ Instructions::structured_else, "synthetic:else" },
{ Instructions::structured_end, "synthetic:end" },
};

View file

@ -11,6 +11,8 @@
#include <AK/DistinctNumeric.h>
#include <AK/LEB128.h>
#include <AK/Result.h>
#include <AK/String.h>
#include <AK/UFixedBigInt.h>
#include <AK/Variant.h>
#include <LibWasm/Constants.h>
#include <LibWasm/Forward.h>
@ -143,6 +145,7 @@ public:
I64,
F32,
F64,
V128,
FunctionReference,
ExternReference,
NullFunctionReference,
@ -157,7 +160,8 @@ public:
bool operator==(ValueType const&) const = default;
auto is_reference() const { return m_kind == ExternReference || m_kind == FunctionReference || m_kind == NullExternReference || m_kind == NullFunctionReference; }
auto is_numeric() const { return !is_reference(); }
auto is_vector() const { return m_kind == V128; }
auto is_numeric() const { return !is_reference() && !is_vector(); }
auto kind() const { return m_kind; }
static ParseResult<ValueType> parse(Stream& stream);
@ -173,6 +177,8 @@ public:
return "f32";
case F64:
return "f64";
case V128:
return "v128";
case FunctionReference:
return "funcref";
case ExternReference:
@ -394,6 +400,27 @@ public:
u32 offset;
};
struct MemoryAndLaneArgument {
MemoryArgument memory;
u8 lane;
};
struct LaneIndex {
u8 lane;
};
struct ShuffleArgument {
explicit ShuffleArgument(u8 (&lanes)[16])
: lanes {
lanes[0], lanes[1], lanes[2], lanes[3], lanes[4], lanes[5], lanes[6], lanes[7],
lanes[8], lanes[9], lanes[10], lanes[11], lanes[12], lanes[13], lanes[14], lanes[15]
}
{
}
u8 lanes[16];
};
template<typename T>
explicit Instruction(OpCode opcode, T argument)
: m_opcode(opcode)
@ -417,9 +444,12 @@ private:
GlobalIndex,
IndirectCallArgs,
LabelIndex,
LaneIndex,
LocalIndex,
MemoryArgument,
MemoryAndLaneArgument,
StructuredInstructionArgs,
ShuffleArgument,
TableBranchArgs,
TableElementArgs,
TableIndex,
@ -430,6 +460,7 @@ private:
float,
i32,
i64,
u128,
u8 // Empty state
> m_arguments;
// clang-format on

View file

@ -416,6 +416,8 @@ JS::ThrowCompletionOr<Wasm::Value> to_webassembly_value(JS::VM& vm, JS::Value va
case Wasm::ValueType::ExternReference:
case Wasm::ValueType::NullExternReference:
TODO();
case Wasm::ValueType::V128:
return vm.throw_completion<JS::TypeError>("Cannot convert a vector value to a javascript value"sv);
}
VERIFY_NOT_REACHED();
@ -438,6 +440,7 @@ JS::Value to_js_value(JS::VM& vm, Wasm::Value& wasm_value)
return create_native_function(vm, wasm_value.to<Wasm::Reference::Func>().value().address, "FIXME_IHaveNoIdeaWhatThisShouldBeCalled");
case Wasm::ValueType::NullFunctionReference:
return JS::js_null();
case Wasm::ValueType::V128:
case Wasm::ValueType::ExternReference:
case Wasm::ValueType::NullExternReference:
TODO();