summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/cli/Cargo.toml2
-rw-r--r--crates/parser/Cargo.toml4
-rw-r--r--crates/parser/src/conversion.rs4
-rw-r--r--crates/parser/src/lib.rs3
-rw-r--r--crates/parser/src/module.rs21
-rw-r--r--crates/parser/src/visit.rs130
-rw-r--r--crates/tinywasm/Cargo.toml4
-rw-r--r--crates/tinywasm/src/interpreter/executor.rs56
-rw-r--r--crates/tinywasm/src/interpreter/stack/call_stack.rs27
-rw-r--r--crates/tinywasm/src/interpreter/stack/value_stack.rs4
-rw-r--r--crates/tinywasm/src/interpreter/values.rs46
-rw-r--r--crates/tinywasm/tests/generated/wasm-simd.csv1
-rw-r--r--crates/types/src/instructions.rs211
-rw-r--r--crates/types/src/lib.rs38
-rw-r--r--crates/wasm-testsuite/Cargo.toml2
15 files changed, 382 insertions, 171 deletions
diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml
index 51a669d..d5e64a8 100644
--- a/crates/cli/Cargo.toml
+++ b/crates/cli/Cargo.toml
@@ -15,7 +15,7 @@ path="src/bin.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-tinywasm={version="0.8.0-alpha.0", path="../tinywasm", features=["std", "parser"]}
+tinywasm={version="0.9.0-alpha.0", path="../tinywasm", features=["std", "parser"]}
argh="0.1"
eyre={workspace=true}
log={workspace=true}
diff --git a/crates/parser/Cargo.toml b/crates/parser/Cargo.toml
index aa2f589..83bb32b 100644
--- a/crates/parser/Cargo.toml
+++ b/crates/parser/Cargo.toml
@@ -9,9 +9,9 @@ repository.workspace=true
rust-version.workspace=true
[dependencies]
-wasmparser={version="0.218", default-features=false, features=["validate", "features"]}
+wasmparser={version="0.219", default-features=false, features=["validate", "features"]}
log={workspace=true, optional=true}
-tinywasm-types={version="0.8.0-alpha.0", path="../types", default-features=false}
+tinywasm-types={version="0.9.0-alpha.0", path="../types", default-features=false}
[features]
default=["std", "logging"]
diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs
index 76099ca..1ebe392 100644
--- a/crates/parser/src/conversion.rs
+++ b/crates/parser/src/conversion.rs
@@ -203,8 +203,8 @@ pub(crate) fn convert_module_code(
}
}
- let (body, allocations) = process_operators_and_validate(validator, func, local_addr_map)?;
- Ok(((body, local_counts), allocations))
+ let (body, data, allocations) = process_operators_and_validate(validator, func, local_addr_map)?;
+ Ok(((body, data, local_counts), allocations))
}
pub(crate) fn convert_module_type(ty: wasmparser::RecGroup) -> Result<FuncType> {
diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs
index e736576..2222ffa 100644
--- a/crates/parser/src/lib.rs
+++ b/crates/parser/src/lib.rs
@@ -61,10 +61,11 @@ impl Parser {
function_references: true,
tail_call: true,
multi_memory: true,
- memory64: false,
simd: true,
+ memory64: true,
custom_page_sizes: true,
+ wide_arithmetic: false,
gc_types: true,
stack_switching: false,
component_model: false,
diff --git a/crates/parser/src/module.rs b/crates/parser/src/module.rs
index ff7d109..9b31f9e 100644
--- a/crates/parser/src/module.rs
+++ b/crates/parser/src/module.rs
@@ -3,12 +3,12 @@ use crate::{conversion, ParseError, Result};
use alloc::string::ToString;
use alloc::{boxed::Box, format, vec::Vec};
use tinywasm_types::{
- Data, Element, Export, FuncType, Global, Import, Instruction, MemoryType, TableType, TinyWasmModule, ValType,
- ValueCounts, ValueCountsSmall, WasmFunction,
+ Data, Element, Export, FuncType, Global, Import, Instruction, MemoryType, TableType, TinyWasmModule, ValueCounts,
+ ValueCountsSmall, WasmFunction, WasmFunctionData,
};
use wasmparser::{FuncValidatorAllocations, Payload, Validator};
-pub(crate) type Code = (Box<[Instruction]>, ValueCounts);
+pub(crate) type Code = (Box<[Instruction]>, WasmFunctionData, ValueCounts);
#[derive(Default)]
pub(crate) struct ModuleReader {
@@ -179,7 +179,6 @@ impl ModuleReader {
Ok(())
}
- #[inline]
pub(crate) fn into_module(self) -> Result<TinyWasmModule> {
if !self.end_reached {
return Err(ParseError::EndNotReached);
@@ -193,18 +192,10 @@ impl ModuleReader {
.code
.into_iter()
.zip(self.code_type_addrs)
- .map(|((instructions, locals), ty_idx)| {
- let mut params = ValueCountsSmall::default();
+ .map(|((instructions, data, locals), ty_idx)| {
let ty = self.func_types.get(ty_idx as usize).expect("No func type for func, this is a bug").clone();
- for param in &ty.params {
- match param {
- ValType::I32 | ValType::F32 => params.c32 += 1,
- ValType::I64 | ValType::F64 => params.c64 += 1,
- ValType::V128 => params.c128 += 1,
- ValType::RefExtern | ValType::RefFunc => params.cref += 1,
- }
- }
- WasmFunction { instructions, locals, params, ty }
+ let params = ValueCountsSmall::from(&ty.params);
+ WasmFunction { instructions, data, locals, params, ty }
})
.collect::<Vec<_>>()
.into_boxed_slice();
diff --git a/crates/parser/src/visit.rs b/crates/parser/src/visit.rs
index c9e5eac..2e80d20 100644
--- a/crates/parser/src/visit.rs
+++ b/crates/parser/src/visit.rs
@@ -3,7 +3,7 @@ use crate::Result;
use crate::conversion::{convert_heaptype, convert_valtype};
use alloc::string::ToString;
use alloc::{boxed::Box, vec::Vec};
-use tinywasm_types::{Instruction, MemoryArg};
+use tinywasm_types::{Instruction, MemoryArg, SimdInstruction, WasmFunctionData};
use wasmparser::{FuncValidator, FuncValidatorAllocations, FunctionBody, VisitOperator, WasmModuleResources};
struct ValidateThenVisit<'a, R: WasmModuleResources>(usize, &'a mut FunctionBuilder<R>);
@@ -26,7 +26,7 @@ pub(crate) fn process_operators_and_validate<R: WasmModuleResources>(
validator: FuncValidator<R>,
body: FunctionBody<'_>,
local_addr_map: Vec<u32>,
-) -> Result<(Box<[Instruction]>, FuncValidatorAllocations)> {
+) -> Result<(Box<[Instruction]>, WasmFunctionData, FuncValidatorAllocations)> {
let mut reader = body.get_operators_reader()?;
let remaining = reader.get_binary_reader().bytes_remaining();
let mut builder = FunctionBuilder::new(remaining, validator, local_addr_map);
@@ -40,42 +40,65 @@ pub(crate) fn process_operators_and_validate<R: WasmModuleResources>(
return Err(builder.errors.remove(0));
}
- Ok((builder.instructions.into_boxed_slice(), builder.validator.into_allocations()))
+ Ok((
+ builder.instructions.into_boxed_slice(),
+ WasmFunctionData { v128_constants: builder.v128_constants.into_boxed_slice() },
+ builder.validator.into_allocations(),
+ ))
}
macro_rules! define_operand {
- ($name:ident($instr:ident, $ty:ty)) => {
+ ($name:ident($instr:expr, $ty:ty)) => {
fn $name(&mut self, arg: $ty) -> Self::Output {
- self.instructions.push(Instruction::$instr(arg));
+ self.instructions.push($instr(arg).into());
}
};
- ($name:ident($instr:ident, $ty:ty, $ty2:ty)) => {
+ ($name:ident($instr:expr, $ty:ty, $ty2:ty)) => {
fn $name(&mut self, arg: $ty, arg2: $ty2) -> Self::Output {
- self.instructions.push(Instruction::$instr(arg, arg2));
+ self.instructions.push($instr(arg, arg2).into());
}
};
- ($name:ident($instr:ident)) => {
+ ($name:ident($instr:expr)) => {
fn $name(&mut self) -> Self::Output {
- self.instructions.push(Instruction::$instr);
+ self.instructions.push($instr.into());
}
};
}
macro_rules! define_operands {
($($name:ident($instr:ident $(,$ty:ty)*)),*) => {$(
- define_operand!($name($instr $(,$ty)*));
+ define_operand!($name(Instruction::$instr $(,$ty)*));
+ )*};
+}
+
+macro_rules! define_operands_simd {
+ ($($name:ident($instr:ident $(,$ty:ty)*)),*) => {$(
+ define_operand!($name(SimdInstruction::$instr $(,$ty)*));
)*};
}
macro_rules! define_mem_operands {
($($name:ident($instr:ident)),*) => {$(
fn $name(&mut self, memarg: wasmparser::MemArg) -> Self::Output {
- self.instructions.push(Instruction::$instr {
- offset: memarg.offset,
- mem_addr: memarg.memory,
- });
+ self.instructions.push(Instruction::$instr(MemoryArg::new(memarg.offset, memarg.memory)));
+ }
+ )*};
+}
+
+macro_rules! define_mem_operands_simd {
+ ($($name:ident($instr:ident)),*) => {$(
+ fn $name(&mut self, memarg: wasmparser::MemArg) -> Self::Output {
+ self.instructions.push(SimdInstruction::$instr(MemoryArg::new(memarg.offset, memarg.memory)).into());
+ }
+ )*};
+}
+
+macro_rules! define_mem_operands_simd_lane {
+ ($($name:ident($instr:ident)),*) => {$(
+ fn $name(&mut self, memarg: wasmparser::MemArg, lane: u8) -> Self::Output {
+ self.instructions.push(SimdInstruction::$instr(MemoryArg::new(memarg.offset, memarg.memory), lane).into());
}
)*};
}
@@ -83,6 +106,7 @@ macro_rules! define_mem_operands {
pub(crate) struct FunctionBuilder<R: WasmModuleResources> {
validator: FuncValidator<R>,
instructions: Vec<Instruction>,
+ v128_constants: Vec<u128>,
label_ptrs: Vec<usize>,
local_addr_map: Vec<u32>,
errors: Vec<crate::ParseError>,
@@ -107,6 +131,7 @@ impl<R: WasmModuleResources> FunctionBuilder<R> {
validator,
local_addr_map,
instructions: Vec::with_capacity(instr_capacity),
+ v128_constants: Vec::new(),
label_ptrs: Vec::with_capacity(256),
errors: Vec::new(),
}
@@ -127,8 +152,8 @@ macro_rules! impl_visit_operator {
(@@sign_extension $($rest:tt)* ) => {};
(@@saturating_float_to_int $($rest:tt)* ) => {};
(@@bulk_memory $($rest:tt)* ) => {};
- (@@tail_call $($rest:tt)* ) => {};
- // (@@simd $($rest:tt)* ) => {};
+ // (@@tail_call $($rest:tt)* ) => {};
+ (@@simd $($rest:tt)* ) => {};
(@@$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*)) => {
#[cold]
fn $visit(&mut self $($(,$arg: $argty)*)?) {
@@ -142,7 +167,7 @@ impl<R: WasmModuleResources> wasmparser::VisitOperator<'_> for FunctionBuilder<R
wasmparser::for_each_operator!(impl_visit_operator);
define_mem_operands! {
- visit_i32_load(I32Load), visit_i64_load(I64Load), visit_f32_load(F32Load), visit_f64_load(F64Load), visit_i32_load8_s(I32Load8S), visit_i32_load8_u(I32Load8U), visit_i32_load16_s(I32Load16S), visit_i32_load16_u(I32Load16U), visit_i64_load8_s(I64Load8S), visit_i64_load8_u(I64Load8U), visit_i64_load16_s(I64Load16S), visit_i64_load16_u(I64Load16U), visit_i64_load32_s(I64Load32S), visit_i64_load32_u(I64Load32U), /* visit_i32_store( I32Store), custom implementation */ visit_i64_store(I64Store), visit_f32_store(F32Store), visit_f64_store(F64Store), visit_i32_store8(I32Store8), visit_i32_store16(I32Store16), visit_i64_store8(I64Store8), visit_i64_store16(I64Store16), visit_i64_store32(I64Store32)
+ visit_i32_load(I32Load), visit_i64_load(I64Load), visit_f32_load(F32Load), visit_f64_load(F64Load), visit_i32_load8_s(I32Load8S), visit_i32_load8_u(I32Load8U), visit_i32_load16_s(I32Load16S), visit_i32_load16_u(I32Load16U), visit_i64_load8_s(I64Load8S), visit_i64_load8_u(I64Load8U), visit_i64_load16_s(I64Load16S), visit_i64_load16_u(I64Load16U), visit_i64_load32_s(I64Load32S), visit_i64_load32_u(I64Load32U), visit_i32_store( I32Store), visit_i64_store(I64Store), visit_f32_store(F32Store), visit_f64_store(F64Store), visit_i32_store8(I32Store8), visit_i32_store16(I32Store16), visit_i64_store8(I64Store8), visit_i64_store16(I64Store16), visit_i64_store32(I64Store32)
}
define_operands! {
@@ -160,19 +185,73 @@ impl<R: WasmModuleResources> wasmparser::VisitOperator<'_> for FunctionBuilder<R
// Bulk Memory
visit_memory_init(MemoryInit, u32, u32), visit_memory_copy(MemoryCopy, u32, u32), visit_table_init(TableInit, u32, u32), visit_memory_fill(MemoryFill, u32), visit_data_drop(DataDrop, u32), visit_elem_drop(ElemDrop, u32)
+ }
- // simd
- // visit_v128_load(V128Load), visit_v128_store(V128Store), visit_v128_const(V128Const), visit_v128_not(V128Not), visit_v128_and(V128And), visit_v128_or(V128Or), visit_v128_xor(V128Xor), visit_v128_bitselect(V128Bitselect), visit_v128_any_true(V128AnyTrue), visit_v128_all_true(V128AllTrue), visit_v128_shl(V128Shl), visit_v128_shr_s(V128ShrS), visit_v128_shr_u(V128ShrU), visit_v128_add(V128Add), visit_v128_sub(V128Sub), visit_v128_mul(V128Mul), visit_v128_div_s(V128DivS), visit_v128_div_u(V128DivU), visit_v128_min_s(V128MinS), visit_v128_min_u(V128MinU), visit_v128_max_s(V128MaxS), visit_v128_max_u(V128MaxU), visit_v128_eq(V128Eq), visit_v128_ne(V128Ne), visit_v128_lt_s(V128LtS), visit_v128_lt_u(V128LtU), visit_v128_le_s(V128LeS), visit_v128_le_u(V128LeU), visit_v128_gt_s(V128GtS), visit_v128_gt_u(V128GtU), visit_v128_ge_s(V128GeS), visit_v128_ge_u(V128GeU), visit_v128_narrow_i32x4_s(V128NarrowI32x4S), visit_v128_narrow_i32x4_u(V128NarrowI32x4U), visit_v128_widen_low_i8x16_s(V128WidenLowI8x16S), visit_v128_widen_high_i8x16_s(V128WidenHighI8x16S), visit_v128_widen_low_i8x16_u(V128WidenLowI8x16U), visit_v128_widen_high_i8x16_u(V128WidenHighI8x16U), visit_v128_widen_low_i16x8_s(V128WidenLowI16x8S), visit_v128_widen_high_i16x8_s(V128WidenHighI16x8S), visit_v128_widen_low_i16x8_u(V128WidenLowI16x8U)
+ // simd
+ define_mem_operands_simd! {
+ visit_v128_load(V128Load), visit_v128_load8x8_s(V128Load8x8S), visit_v128_load8x8_u(V128Load8x8U), visit_v128_load16x4_s(V128Load16x4S), visit_v128_load16x4_u(V128Load16x4U), visit_v128_load32x2_s(V128Load32x2S), visit_v128_load32x2_u(V128Load32x2U), visit_v128_load8_splat(V128Load8Splat), visit_v128_load16_splat(V128Load16Splat), visit_v128_load32_splat(V128Load32Splat), visit_v128_load64_splat(V128Load64Splat), visit_v128_load32_zero(V128Load32Zero), visit_v128_load64_zero(V128Load64Zero), visit_v128_store(V128Store)
+ }
+ define_mem_operands_simd_lane! {
+ visit_v128_load8_lane(V128Load8Lane), visit_v128_load16_lane(V128Load16Lane), visit_v128_load32_lane(V128Load32Lane), visit_v128_load64_lane(V128Load64Lane),
+ visit_v128_store8_lane(V128Store8Lane), visit_v128_store16_lane(V128Store16Lane), visit_v128_store32_lane(V128Store32Lane), visit_v128_store64_lane(V128Store64Lane)
}
+ define_operands_simd! {
+ visit_v128_not(V128Not), visit_v128_and(V128And), visit_v128_andnot(V128AndNot), visit_v128_or(V128Or), visit_v128_xor(V128Xor), visit_v128_bitselect(V128Bitselect), visit_v128_any_true(V128AnyTrue),
+ visit_i8x16_splat(I8x16Splat), visit_i8x16_swizzle(I8x16Swizzle), visit_i8x16_eq(I8x16Eq), visit_i8x16_ne(I8x16Ne), visit_i8x16_lt_s(I8x16LtS), visit_i8x16_lt_u(I8x16LtU), visit_i8x16_gt_s(I8x16GtS), visit_i8x16_gt_u(I8x16GtU), visit_i8x16_le_s(I8x16LeS), visit_i8x16_le_u(I8x16LeU), visit_i8x16_ge_s(I8x16GeS), visit_i8x16_ge_u(I8x16GeU),
+ visit_i16x8_splat(I16x8Splat), visit_i16x8_eq(I16x8Eq), visit_i16x8_ne(I16x8Ne), visit_i16x8_lt_s(I16x8LtS), visit_i16x8_lt_u(I16x8LtU), visit_i16x8_gt_s(I16x8GtS), visit_i16x8_gt_u(I16x8GtU), visit_i16x8_le_s(I16x8LeS), visit_i16x8_le_u(I16x8LeU), visit_i16x8_ge_s(I16x8GeS), visit_i16x8_ge_u(I16x8GeU),
+ visit_i32x4_splat(I32x4Splat), visit_i32x4_eq(I32x4Eq), visit_i32x4_ne(I32x4Ne), visit_i32x4_lt_s(I32x4LtS), visit_i32x4_lt_u(I32x4LtU), visit_i32x4_gt_s(I32x4GtS), visit_i32x4_gt_u(I32x4GtU), visit_i32x4_le_s(I32x4LeS), visit_i32x4_le_u(I32x4LeU), visit_i32x4_ge_s(I32x4GeS), visit_i32x4_ge_u(I32x4GeU),
+ visit_i64x2_splat(I64x2Splat), visit_i64x2_eq(I64x2Eq), visit_i64x2_ne(I64x2Ne), visit_i64x2_lt_s(I64x2LtS), visit_i64x2_gt_s(I64x2GtS), visit_i64x2_le_s(I64x2LeS), visit_i64x2_ge_s(I64x2GeS),
+ visit_f32x4_splat(F32x4Splat), visit_f32x4_eq(F32x4Eq), visit_f32x4_ne(F32x4Ne), visit_f32x4_lt(F32x4Lt), visit_f32x4_gt(F32x4Gt), visit_f32x4_le(F32x4Le), visit_f32x4_ge(F32x4Ge),
+ visit_f64x2_splat(F64x2Splat), visit_f64x2_eq(F64x2Eq), visit_f64x2_ne(F64x2Ne), visit_f64x2_lt(F64x2Lt), visit_f64x2_gt(F64x2Gt), visit_f64x2_le(F64x2Le), visit_f64x2_ge(F64x2Ge),
+ visit_i8x16_abs(I8x16Abs), visit_i8x16_neg(I8x16Neg), visit_i8x16_all_true(I8x16AllTrue), visit_i8x16_bitmask(I8x16Bitmask), visit_i8x16_shl(I8x16Shl), visit_i8x16_shr_s(I8x16ShrS), visit_i8x16_shr_u(I8x16ShrU), visit_i8x16_add(I8x16Add), visit_i8x16_sub(I8x16Sub), visit_i8x16_min_s(I8x16MinS), visit_i8x16_min_u(I8x16MinU), visit_i8x16_max_s(I8x16MaxS), visit_i8x16_max_u(I8x16MaxU),
+ visit_i16x8_abs(I16x8Abs), visit_i16x8_neg(I16x8Neg), visit_i16x8_all_true(I16x8AllTrue), visit_i16x8_bitmask(I16x8Bitmask), visit_i16x8_shl(I16x8Shl), visit_i16x8_shr_s(I16x8ShrS), visit_i16x8_shr_u(I16x8ShrU), visit_i16x8_add(I16x8Add), visit_i16x8_sub(I16x8Sub), visit_i16x8_min_s(I16x8MinS), visit_i16x8_min_u(I16x8MinU), visit_i16x8_max_s(I16x8MaxS), visit_i16x8_max_u(I16x8MaxU),
+ visit_i32x4_abs(I32x4Abs), visit_i32x4_neg(I32x4Neg), visit_i32x4_all_true(I32x4AllTrue), visit_i32x4_bitmask(I32x4Bitmask), visit_i32x4_shl(I32x4Shl), visit_i32x4_shr_s(I32x4ShrS), visit_i32x4_shr_u(I32x4ShrU), visit_i32x4_add(I32x4Add), visit_i32x4_sub(I32x4Sub), visit_i32x4_min_s(I32x4MinS), visit_i32x4_min_u(I32x4MinU), visit_i32x4_max_s(I32x4MaxS), visit_i32x4_max_u(I32x4MaxU),
+ visit_i64x2_abs(I64x2Abs), visit_i64x2_neg(I64x2Neg), visit_i64x2_all_true(I64x2AllTrue), visit_i64x2_bitmask(I64x2Bitmask), visit_i64x2_shl(I64x2Shl), visit_i64x2_shr_s(I64x2ShrS), visit_i64x2_shr_u(I64x2ShrU), visit_i64x2_add(I64x2Add), visit_i64x2_sub(I64x2Sub), visit_i64x2_mul(I64x2Mul),
+ visit_i8x16_narrow_i16x8_s(I8x16NarrowI16x8S), visit_i8x16_narrow_i16x8_u(I8x16NarrowI16x8U), visit_i8x16_add_sat_s(I8x16AddSatS), visit_i8x16_add_sat_u(I8x16AddSatU), visit_i8x16_sub_sat_s(I8x16SubSatS), visit_i8x16_sub_sat_u(I8x16SubSatU), visit_i8x16_avgr_u(I8x16AvgrU),
+ visit_i16x8_narrow_i32x4_s(I16x8NarrowI32x4S), visit_i16x8_narrow_i32x4_u(I16x8NarrowI32x4U), visit_i16x8_add_sat_s(I16x8AddSatS), visit_i16x8_add_sat_u(I16x8AddSatU), visit_i16x8_sub_sat_s(I16x8SubSatS), visit_i16x8_sub_sat_u(I16x8SubSatU), visit_i16x8_avgr_u(I16x8AvgrU),
+ visit_i16x8_extadd_pairwise_i8x16_s(I16x8ExtAddPairwiseI8x16S), visit_i16x8_extadd_pairwise_i8x16_u(I16x8ExtAddPairwiseI8x16U), visit_i16x8_mul(I16x8Mul),
+ visit_i32x4_extadd_pairwise_i16x8_s(I32x4ExtAddPairwiseI16x8S), visit_i32x4_extadd_pairwise_i16x8_u(I32x4ExtAddPairwiseI16x8U), visit_i32x4_mul(I32x4Mul),
+ visit_i16x8_extmul_low_i8x16_s(I16x8ExtMulLowI8x16S), visit_i16x8_extmul_low_i8x16_u(I16x8ExtMulLowI8x16U), visit_i16x8_extmul_high_i8x16_s(I16x8ExtMulHighI8x16S), visit_i16x8_extmul_high_i8x16_u(I16x8ExtMulHighI8x16U),
+ visit_i32x4_extmul_low_i16x8_s(I32x4ExtMulLowI16x8S), visit_i32x4_extmul_low_i16x8_u(I32x4ExtMulLowI16x8U), visit_i32x4_extmul_high_i16x8_s(I32x4ExtMulHighI16x8S), visit_i32x4_extmul_high_i16x8_u(I32x4ExtMulHighI16x8U),
+ visit_i64x2_extmul_low_i32x4_s(I64x2ExtMulLowI32x4S), visit_i64x2_extmul_low_i32x4_u(I64x2ExtMulLowI32x4U), visit_i64x2_extmul_high_i32x4_s(I64x2ExtMulHighI32x4S), visit_i64x2_extmul_high_i32x4_u(I64x2ExtMulHighI32x4U),
+ visit_i16x8_extend_low_i8x16_s(I16x8ExtendLowI8x16S), visit_i16x8_extend_low_i8x16_u(I16x8ExtendLowI8x16U), visit_i16x8_extend_high_i8x16_s(I16x8ExtendHighI8x16S), visit_i16x8_extend_high_i8x16_u(I16x8ExtendHighI8x16U),
+ visit_i32x4_extend_low_i16x8_s(I32x4ExtendLowI16x8S), visit_i32x4_extend_low_i16x8_u(I32x4ExtendLowI16x8U), visit_i32x4_extend_high_i16x8_s(I32x4ExtendHighI16x8S), visit_i32x4_extend_high_i16x8_u(I32x4ExtendHighI16x8U),
+ visit_i64x2_extend_low_i32x4_s(I64x2ExtendLowI32x4S), visit_i64x2_extend_low_i32x4_u(I64x2ExtendLowI32x4U), visit_i64x2_extend_high_i32x4_s(I64x2ExtendHighI32x4S), visit_i64x2_extend_high_i32x4_u(I64x2ExtendHighI32x4U),
+ visit_i8x16_popcnt(I8x16Popcnt), visit_i16x8_q15mulr_sat_s(I16x8Q15MulrSatS), visit_i32x4_dot_i16x8_s(I32x4DotI16x8S),
+ visit_f32x4_ceil(F32x4Ceil), visit_f32x4_floor(F32x4Floor), visit_f32x4_trunc(F32x4Trunc), visit_f32x4_nearest(F32x4Nearest), visit_f32x4_abs(F32x4Abs), visit_f32x4_neg(F32x4Neg), visit_f32x4_sqrt(F32x4Sqrt), visit_f32x4_add(F32x4Add), visit_f32x4_sub(F32x4Sub), visit_f32x4_mul(F32x4Mul), visit_f32x4_div(F32x4Div), visit_f32x4_min(F32x4Min), visit_f32x4_max(F32x4Max), visit_f32x4_pmin(F32x4PMin), visit_f32x4_pmax(F32x4PMax),
+ visit_f64x2_ceil(F64x2Ceil), visit_f64x2_floor(F64x2Floor), visit_f64x2_trunc(F64x2Trunc), visit_f64x2_nearest(F64x2Nearest), visit_f64x2_abs(F64x2Abs), visit_f64x2_neg(F64x2Neg), visit_f64x2_sqrt(F64x2Sqrt), visit_f64x2_add(F64x2Add), visit_f64x2_sub(F64x2Sub), visit_f64x2_mul(F64x2Mul), visit_f64x2_div(F64x2Div), visit_f64x2_min(F64x2Min), visit_f64x2_max(F64x2Max), visit_f64x2_pmin(F64x2PMin), visit_f64x2_pmax(F64x2PMax),
+ visit_i32x4_trunc_sat_f32x4_s(I32x4TruncSatF32x4S), visit_i32x4_trunc_sat_f32x4_u(I32x4TruncSatF32x4U),
+ visit_f32x4_convert_i32x4_s(F32x4ConvertI32x4S), visit_f32x4_convert_i32x4_u(F32x4ConvertI32x4U),
+ visit_i32x4_trunc_sat_f64x2_s_zero(I32x4TruncSatF64x2SZero), visit_i32x4_trunc_sat_f64x2_u_zero(I32x4TruncSatF64x2UZero),
+ visit_f64x2_convert_low_i32x4_s(F64x2ConvertLowI32x4S), visit_f64x2_convert_low_i32x4_u(F64x2ConvertLowI32x4U),
+ visit_f32x4_demote_f64x2_zero(F32x4DemoteF64x2Zero), visit_f64x2_promote_low_f32x4(F64x2PromoteLowF32x4),
- fn visit_return_call(&mut self, function_index: u32) -> Self::Output {
- self.instructions.push(Instruction::ReturnCall(function_index));
+ visit_i8x16_extract_lane_s(I8x16ExtractLaneS, u8), visit_i8x16_extract_lane_u(I8x16ExtractLaneU, u8), visit_i8x16_replace_lane(I8x16ReplaceLane, u8),
+ visit_i16x8_extract_lane_s(I16x8ExtractLaneS, u8), visit_i16x8_extract_lane_u(I16x8ExtractLaneU, u8), visit_i16x8_replace_lane(I16x8ReplaceLane, u8),
+ visit_i32x4_extract_lane(I32x4ExtractLane, u8), visit_i32x4_replace_lane(I32x4ReplaceLane, u8),
+ visit_i64x2_extract_lane(I64x2ExtractLane, u8), visit_i64x2_replace_lane(I64x2ReplaceLane, u8),
+ visit_f32x4_extract_lane(F32x4ExtractLane, u8), visit_f32x4_replace_lane(F32x4ReplaceLane, u8),
+ visit_f64x2_extract_lane(F64x2ExtractLane, u8), visit_f64x2_replace_lane(F64x2ReplaceLane, u8)
}
- fn visit_return_call_indirect(&mut self, type_index: u32, table_index: u32) -> Self::Output {
- self.instructions.push(Instruction::ReturnCallIndirect(type_index, table_index));
+ fn visit_i8x16_shuffle(&mut self, lanes: [u8; 16]) -> Self::Output {
+ self.v128_constants.push(u128::from_le_bytes(lanes));
+ self.instructions.push(SimdInstruction::I8x16Shuffle(self.v128_constants.len() as u32 - 1).into());
}
+ fn visit_v128_const(&mut self, value: wasmparser::V128) -> Self::Output {
+ self.v128_constants.push(value.i128() as u128);
+ self.instructions.push(SimdInstruction::V128Const(self.v128_constants.len() as u32 - 1).into());
+ }
+
+ // fn visit_return_call(&mut self, function_index: u32) -> Self::Output {
+ // self.instructions.push(Instruction::ReturnCall(function_index));
+ // }
+
+ // fn visit_return_call_indirect(&mut self, type_index: u32, table_index: u32) -> Self::Output {
+ // self.instructions.push(Instruction::ReturnCallIndirect(type_index, table_index));
+ // }
+
fn visit_global_set(&mut self, global_index: u32) -> Self::Output {
match self.validator.get_operand_type(0) {
Some(Some(t)) => self.instructions.push(match t {
@@ -206,11 +285,6 @@ impl<R: WasmModuleResources> wasmparser::VisitOperator<'_> for FunctionBuilder<R
_ => self.visit_unreachable(),
}
}
- fn visit_i32_store(&mut self, memarg: wasmparser::MemArg) -> Self::Output {
- let arg = MemoryArg { offset: memarg.offset, mem_addr: memarg.memory };
- let i32store = Instruction::I32Store { offset: arg.offset, mem_addr: arg.mem_addr };
- self.instructions.push(i32store);
- }
fn visit_local_get(&mut self, idx: u32) -> Self::Output {
let Ok(resolved_idx) = self.local_addr_map[idx as usize].try_into() else {
diff --git a/crates/tinywasm/Cargo.toml b/crates/tinywasm/Cargo.toml
index 4dc82bb..401e3de 100644
--- a/crates/tinywasm/Cargo.toml
+++ b/crates/tinywasm/Cargo.toml
@@ -15,8 +15,8 @@ path="src/lib.rs"
[dependencies]
log={workspace=true, optional=true}
-tinywasm-parser={version="0.8.0-alpha.0", path="../parser", default-features=false, optional=true}
-tinywasm-types={version="0.8.0-alpha.0", path="../types", default-features=false}
+tinywasm-parser={version="0.9.0-alpha.0", path="../parser", default-features=false, optional=true}
+tinywasm-types={version="0.9.0-alpha.0", path="../types", default-features=false}
libm={version="0.2", default-features=false}
[dev-dependencies]
diff --git a/crates/tinywasm/src/interpreter/executor.rs b/crates/tinywasm/src/interpreter/executor.rs
index c2df82c..2326227 100644
--- a/crates/tinywasm/src/interpreter/executor.rs
+++ b/crates/tinywasm/src/interpreter/executor.rs
@@ -26,7 +26,7 @@ impl<'store, 'stack> Executor<'store, 'stack> {
Ok(Self { cf: current_frame, module: current_module, stack, store })
}
- #[inline]
+ #[inline(always)]
pub(crate) fn run_to_completion(&mut self) -> Result<()> {
loop {
if let ControlFlow::Break(res) = self.exec_next() {
@@ -114,30 +114,30 @@ impl<'store, 'stack> Executor<'store, 'stack> {
ElemDrop(elem_index) => self.exec_elem_drop(*elem_index),
TableCopy { from, to } => self.exec_table_copy(*from, *to).to_cf()?,
- I32Store { mem_addr, offset } => self.exec_mem_store::<i32, i32, 4>(*mem_addr, *offset, |v| v)?,
- I64Store { mem_addr, offset } => self.exec_mem_store::<i64, i64, 8>(*mem_addr, *offset, |v| v)?,
- F32Store { mem_addr, offset } => self.exec_mem_store::<f32, f32, 4>(*mem_addr, *offset, |v| v)?,
- F64Store { mem_addr, offset } => self.exec_mem_store::<f64, f64, 8>(*mem_addr, *offset, |v| v)?,
- I32Store8 { mem_addr, offset } => self.exec_mem_store::<i32, i8, 1>(*mem_addr, *offset, |v| v as i8)?,
- I32Store16 { mem_addr, offset } => self.exec_mem_store::<i32, i16, 2>(*mem_addr, *offset, |v| v as i16)?,
- I64Store8 { mem_addr, offset } => self.exec_mem_store::<i64, i8, 1>(*mem_addr, *offset, |v| v as i8)?,
- I64Store16 { mem_addr, offset } => self.exec_mem_store::<i64, i16, 2>(*mem_addr, *offset, |v| v as i16)?,
- I64Store32 { mem_addr, offset } => self.exec_mem_store::<i64, i32, 4>(*mem_addr, *offset, |v| v as i32)?,
+ I32Store(m) => self.exec_mem_store::<i32, i32, 4>(m.mem_addr(), m.offset(), |v| v)?,
+ I64Store(m) => self.exec_mem_store::<i64, i64, 8>(m.mem_addr(), m.offset(), |v| v)?,
+ F32Store(m) => self.exec_mem_store::<f32, f32, 4>(m.mem_addr(), m.offset(), |v| v)?,
+ F64Store(m) => self.exec_mem_store::<f64, f64, 8>(m.mem_addr(), m.offset(), |v| v)?,
+ I32Store8(m) => self.exec_mem_store::<i32, i8, 1>(m.mem_addr(), m.offset(), |v| v as i8)?,
+ I32Store16(m) => self.exec_mem_store::<i32, i16, 2>(m.mem_addr(), m.offset(), |v| v as i16)?,
+ I64Store8(m) => self.exec_mem_store::<i64, i8, 1>(m.mem_addr(), m.offset(), |v| v as i8)?,
+ I64Store16(m) => self.exec_mem_store::<i64, i16, 2>(m.mem_addr(), m.offset(), |v| v as i16)?,
+ I64Store32(m) => self.exec_mem_store::<i64, i32, 4>(m.mem_addr(), m.offset(), |v| v as i32)?,
- I32Load { mem_addr, offset } => self.exec_mem_load::<i32, 4, _>(*mem_addr, *offset, |v| v)?,
- I64Load { mem_addr, offset } => self.exec_mem_load::<i64, 8, _>(*mem_addr, *offset, |v| v)?,
- F32Load { mem_addr, offset } => self.exec_mem_load::<f32, 4, _>(*mem_addr, *offset, |v| v)?,
- F64Load { mem_addr, offset } => self.exec_mem_load::<f64, 8, _>(*mem_addr, *offset, |v| v)?,
- I32Load8S { mem_addr, offset } => self.exec_mem_load::<i8, 1, _>(*mem_addr, *offset, |v| v as i32)?,
- I32Load8U { mem_addr, offset } => self.exec_mem_load::<u8, 1, _>(*mem_addr, *offset, |v| v as i32)?,
- I32Load16S { mem_addr, offset } => self.exec_mem_load::<i16, 2, _>(*mem_addr, *offset, |v| v as i32)?,
- I32Load16U { mem_addr, offset } => self.exec_mem_load::<u16, 2, _>(*mem_addr, *offset, |v| v as i32)?,
- I64Load8S { mem_addr, offset } => self.exec_mem_load::<i8, 1, _>(*mem_addr, *offset, |v| v as i64)?,
- I64Load8U { mem_addr, offset } => self.exec_mem_load::<u8, 1, _>(*mem_addr, *offset, |v| v as i64)?,
- I64Load16S { mem_addr, offset } => self.exec_mem_load::<i16, 2, _>(*mem_addr, *offset, |v| v as i64)?,
- I64Load16U { mem_addr, offset } => self.exec_mem_load::<u16, 2, _>(*mem_addr, *offset, |v| v as i64)?,
- I64Load32S { mem_addr, offset } => self.exec_mem_load::<i32, 4, _>(*mem_addr, *offset, |v| v as i64)?,
- I64Load32U { mem_addr, offset } => self.exec_mem_load::<u32, 4, _>(*mem_addr, *offset, |v| v as i64)?,
+ I32Load(m) => self.exec_mem_load::<i32, 4, _>(m.mem_addr(), m.offset(), |v| v)?,
+ I64Load(m) => self.exec_mem_load::<i64, 8, _>(m.mem_addr(), m.offset(), |v| v)?,
+ F32Load(m) => self.exec_mem_load::<f32, 4, _>(m.mem_addr(), m.offset(), |v| v)?,
+ F64Load(m) => self.exec_mem_load::<f64, 8, _>(m.mem_addr(), m.offset(), |v| v)?,
+ I32Load8S(m) => self.exec_mem_load::<i8, 1, _>(m.mem_addr(), m.offset(), |v| v as i32)?,
+ I32Load8U(m) => self.exec_mem_load::<u8, 1, _>(m.mem_addr(), m.offset(), |v| v as i32)?,
+ I32Load16S(m) => self.exec_mem_load::<i16, 2, _>(m.mem_addr(), m.offset(), |v| v as i32)?,
+ I32Load16U(m) => self.exec_mem_load::<u16, 2, _>(m.mem_addr(), m.offset(), |v| v as i32)?,
+ I64Load8S(m) => self.exec_mem_load::<i8, 1, _>(m.mem_addr(), m.offset(), |v| v as i64)?,
+ I64Load8U(m) => self.exec_mem_load::<u8, 1, _>(m.mem_addr(), m.offset(), |v| v as i64)?,
+ I64Load16S(m) => self.exec_mem_load::<i16, 2, _>(m.mem_addr(), m.offset(), |v| v as i64)?,
+ I64Load16U(m) => self.exec_mem_load::<u16, 2, _>(m.mem_addr(), m.offset(), |v| v as i64)?,
+ I64Load32S(m) => self.exec_mem_load::<i32, 4, _>(m.mem_addr(), m.offset(), |v| v as i64)?,
+ I64Load32U(m) => self.exec_mem_load::<u32, 4, _>(m.mem_addr(), m.offset(), |v| v as i64)?,
I64Eqz => self.stack.values.replace_top::<i64, _>(|v| Ok(i32::from(v == 0))).to_cf()?,
I32Eqz => self.stack.values.replace_top_same::<i32>(|v| Ok(i32::from(v == 0))).to_cf()?,
@@ -302,6 +302,10 @@ impl<'store, 'stack> Executor<'store, 'stack> {
LocalCopy128(from, to) => self.exec_local_copy::<Value128>(*from, *to),
LocalCopyRef(from, to) => self.exec_local_copy::<ValueRef>(*from, *to),
+ Simd(_) => {
+ unreachable!("unimplemented sidm instruction");
+ }
+
instr => {
unreachable!("unimplemented instruction: {:?}", instr);
}
@@ -585,10 +589,10 @@ impl<'store, 'stack> Executor<'store, 'stack> {
mem.store(dst as usize, size as usize, &data[offset as usize..((offset + size) as usize)])
}
fn exec_data_drop(&mut self, data_index: u32) {
- self.store.get_data_mut(self.module.resolve_data_addr(data_index)).drop()
+ self.store.get_data_mut(self.module.resolve_data_addr(data_index)).drop();
}
fn exec_elem_drop(&mut self, elem_index: u32) {
- self.store.get_elem_mut(self.module.resolve_elem_addr(elem_index)).drop()
+ self.store.get_elem_mut(self.module.resolve_elem_addr(elem_index)).drop();
}
fn exec_table_copy(&mut self, from: u32, to: u32) -> Result<()> {
let size: i32 = self.stack.values.pop();
diff --git a/crates/tinywasm/src/interpreter/stack/call_stack.rs b/crates/tinywasm/src/interpreter/stack/call_stack.rs
index 7c2be9c..f0e8d18 100644
--- a/crates/tinywasm/src/interpreter/stack/call_stack.rs
+++ b/crates/tinywasm/src/interpreter/stack/call_stack.rs
@@ -22,12 +22,12 @@ impl CallStack {
Self { stack: vec![initial_frame] }
}
- #[inline(always)]
+ #[inline]
pub(crate) fn pop(&mut self) -> Option<CallFrame> {
self.stack.pop()
}
- #[inline(always)]
+ #[inline]
pub(crate) fn push(&mut self, call_frame: CallFrame) -> ControlFlow<Option<Error>> {
if unlikely((self.stack.len() + 1) >= MAX_CALL_STACK_SIZE) {
return ControlFlow::Break(Some(Trap::CallStackOverflow.into()));
@@ -60,44 +60,47 @@ impl Locals {
}
pub(crate) fn set<T: InternalValue>(&mut self, local_index: LocalAddr, value: T) {
- T::local_set(self, local_index, value)
+ T::local_set(self, local_index, value);
}
}
impl CallFrame {
- #[inline(always)]
+ #[inline]
pub(crate) fn instr_ptr(&self) -> usize {
self.instr_ptr
}
- #[inline(always)]
+ #[inline]
pub(crate) fn incr_instr_ptr(&mut self) {
self.instr_ptr += 1;
}
- #[inline(always)]
+ #[inline]
pub(crate) fn jump(&mut self, offset: usize) {
self.instr_ptr += offset;
}
- #[inline(always)]
+ #[inline]
pub(crate) fn module_addr(&self) -> ModuleInstanceAddr {
self.module_addr
}
- #[inline(always)]
+ #[inline]
pub(crate) fn block_ptr(&self) -> u32 {
self.block_ptr
}
#[inline(always)]
pub(crate) fn fetch_instr(&self) -> &Instruction {
- &self.func_instance.instructions[self.instr_ptr]
+ match self.func_instance.instructions.get(self.instr_ptr) {
+ Some(instr) => instr,
+ None => unreachable!("Instruction out of bounds, this is a bug"),
+ }
}
/// Break to a block at the given index (relative to the current frame)
/// Returns `None` if there is no block at the given index (e.g. if we need to return, this is handled by the caller)
- #[inline(always)]
+ #[inline]
pub(crate) fn break_to(
&mut self,
break_to_relative: u32,
@@ -140,7 +143,7 @@ impl CallFrame {
Some(())
}
- #[inline(always)]
+ #[inline]
pub(crate) fn new(
wasm_func_inst: Rc<WasmFunction>,
owner: ModuleInstanceAddr,
@@ -192,7 +195,7 @@ impl CallFrame {
Self { instr_ptr: 0, func_instance: wasm_func_inst, module_addr: owner, block_ptr, locals }
}
- #[inline(always)]
+ #[inline]
pub(crate) fn instructions(&self) -> &[Instruction] {
&self.func_instance.instructions
}
diff --git a/crates/tinywasm/src/interpreter/stack/value_stack.rs b/crates/tinywasm/src/interpreter/stack/value_stack.rs
index 03c676e..7cbf612 100644
--- a/crates/tinywasm/src/interpreter/stack/value_stack.rs
+++ b/crates/tinywasm/src/interpreter/stack/value_stack.rs
@@ -48,7 +48,7 @@ impl ValueStack {
#[inline]
pub(crate) fn push<T: InternalValue>(&mut self, value: T) {
- T::stack_push(self, value)
+ T::stack_push(self, value);
}
#[inline]
@@ -180,7 +180,7 @@ impl ValueStack {
pub(crate) fn extend_from_wasmvalues(&mut self, values: &[WasmValue]) {
for value in values {
- self.push_dyn(value.into())
+ self.push_dyn(value.into());
}
}
}
diff --git a/crates/tinywasm/src/interpreter/values.rs b/crates/tinywasm/src/interpreter/values.rs
index 7b363a8..99cf443 100644
--- a/crates/tinywasm/src/interpreter/values.rs
+++ b/crates/tinywasm/src/interpreter/values.rs
@@ -169,7 +169,6 @@ macro_rules! impl_internalvalue {
impl sealed::Sealed for $outer {}
impl From<$outer> for TinyWasmValue {
- #[inline(always)]
fn from(value: $outer) -> Self {
TinyWasmValue::$variant($to_internal(value))
}
@@ -180,44 +179,59 @@ macro_rules! impl_internalvalue {
fn stack_push(stack: &mut ValueStack, value: Self) {
stack.$stack.push($to_internal(value));
}
+
#[inline(always)]
fn stack_pop(stack: &mut ValueStack) -> Self {
- ($to_outer)(stack.$stack.pop().expect("ValueStack underflow, this is a bug"))
+ match stack.$stack.pop() {
+ Some(v) => $to_outer(v),
+ None => unreachable!("ValueStack underflow, this is a bug"),
+ }
}
+
#[inline(always)]
fn stack_peek(stack: &ValueStack) -> Self {
- ($to_outer)(*stack.$stack.last().expect("ValueStack underflow, this is a bug"))
+ match stack.$stack.last() {
+ Some(v) => $to_outer(*v),
+ None => unreachable!("ValueStack underflow, this is a bug"),
+ }
}
#[inline(always)]
fn stack_calculate(stack: &mut ValueStack, func: fn(Self, Self) -> Result<Self>) -> Result<()> {
let v2 = stack.$stack.pop();
let v1 = stack.$stack.last_mut();
- if let (Some(v1), Some(v2)) = (v1, v2) {
- *v1 = $to_internal(func($to_outer(*v1), $to_outer(v2))?);
- } else {
- unreachable!("ValueStack underflow, this is a bug");
- }
- Ok(())
+ let (Some(v1), Some(v2)) = (v1, v2) else {
+ unreachable!("ValueStack underflow, this is a bug");
+ };
+
+ *v1 = $to_internal(func($to_outer(*v1), $to_outer(v2))?);
+ return Ok(())
}
#[inline(always)]
fn replace_top(stack: &mut ValueStack, func: fn(Self) -> Result<Self>) -> Result<()> {
- if let Some(v) = stack.$stack.last_mut() {
- *v = $to_internal(func($to_outer(*v))?);
- Ok(())
- } else {
+ let Some(v) = stack.$stack.last_mut() else {
unreachable!("ValueStack underflow, this is a bug");
- }
+ };
+
+ *v = $to_internal(func($to_outer(*v))?);
+ Ok(())
}
#[inline(always)]
fn local_get(locals: &Locals, index: LocalAddr) -> Self {
- $to_outer(locals.$locals[index as usize])
+ match locals.$locals.get(index as usize) {
+ Some(v) => $to_outer(*v),
+ None => unreachable!("Local variable out of bounds, this is a bug"),
+ }
}
+
#[inline(always)]
fn local_set(locals: &mut Locals, index: LocalAddr, value: Self) {
- locals.$locals[index as usize] = $to_internal(value);
+ match locals.$locals.get_mut(index as usize) {
+ Some(v) => *v = $to_internal(value),
+ None => unreachable!("Local variable out of bounds, this is a bug"),
+ }
}
}
)*
diff --git a/crates/tinywasm/tests/generated/wasm-simd.csv b/crates/tinywasm/tests/generated/wasm-simd.csv
index e9bc8ae..a7fc7ef 100644
--- a/crates/tinywasm/tests/generated/wasm-simd.csv
+++ b/crates/tinywasm/tests/generated/wasm-simd.csv
@@ -1 +1,2 @@
0.8.0,1300,24679,[{"name":"simd_address.wast","passed":4,"failed":45},{"name":"simd_align.wast","passed":46,"failed":54},{"name":"simd_bit_shift.wast","passed":39,"failed":213},{"name":"simd_bitwise.wast","passed":28,"failed":141},{"name":"simd_boolean.wast","passed":16,"failed":261},{"name":"simd_const.wast","passed":301,"failed":456},{"name":"simd_conversions.wast","passed":48,"failed":234},{"name":"simd_f32x4.wast","passed":16,"failed":774},{"name":"simd_f32x4_arith.wast","passed":16,"failed":1806},{"name":"simd_f32x4_cmp.wast","passed":24,"failed":2583},{"name":"simd_f32x4_pmin_pmax.wast","passed":14,"failed":3873},{"name":"simd_f32x4_rounding.wast","passed":24,"failed":177},{"name":"simd_f64x2.wast","passed":8,"failed":795},{"name":"simd_f64x2_arith.wast","passed":16,"failed":1809},{"name":"simd_f64x2_cmp.wast","passed":24,"failed":2661},{"name":"simd_f64x2_pmin_pmax.wast","passed":14,"failed":3873},{"name":"simd_f64x2_rounding.wast","passed":24,"failed":177},{"name":"simd_i16x8_arith.wast","passed":11,"failed":183},{"name":"simd_i16x8_arith2.wast","passed":19,"failed":153},{"name":"simd_i16x8_cmp.wast","passed":30,"failed":435},{"name":"simd_i16x8_extadd_pairwise_i8x16.wast","passed":4,"failed":17},{"name":"simd_i16x8_extmul_i8x16.wast","passed":12,"failed":105},{"name":"simd_i16x8_q15mulr_sat_s.wast","passed":3,"failed":27},{"name":"simd_i16x8_sat_arith.wast","passed":16,"failed":206},{"name":"simd_i32x4_arith.wast","passed":11,"failed":183},{"name":"simd_i32x4_arith2.wast","passed":26,"failed":123},{"name":"simd_i32x4_cmp.wast","passed":40,"failed":435},{"name":"simd_i32x4_dot_i16x8.wast","passed":3,"failed":27},{"name":"simd_i32x4_extadd_pairwise_i16x8.wast","passed":4,"failed":17},{"name":"simd_i32x4_extmul_i16x8.wast","passed":12,"failed":105},{"name":"simd_i32x4_trunc_sat_f32x4.wast","passed":4,"failed":103},{"name":"simd_i32x4_trunc_sat_f64x2.wast","passed":4,"failed":103},{"name":"simd_i64x2_arith.wast","passed":11,"failed":189},{"name":"simd_i64x2_arith2.wast","passed":2,"failed":23},{"name":"simd_i64x2_cmp.wast","passed":10,"failed":103},{"name":"simd_i64x2_extmul_i32x4.wast","passed":12,"failed":105},{"name":"simd_i8x16_arith.wast","passed":8,"failed":123},{"name":"simd_i8x16_arith2.wast","passed":25,"failed":186},{"name":"simd_i8x16_cmp.wast","passed":30,"failed":415},{"name":"simd_i8x16_sat_arith.wast","passed":24,"failed":190},{"name":"simd_int_to_int_extend.wast","passed":24,"failed":229},{"name":"simd_lane.wast","passed":189,"failed":286},{"name":"simd_linking.wast","passed":0,"failed":3},{"name":"simd_load.wast","passed":8,"failed":31},{"name":"simd_load16_lane.wast","passed":3,"failed":33},{"name":"simd_load32_lane.wast","passed":3,"failed":21},{"name":"simd_load64_lane.wast","passed":3,"failed":13},{"name":"simd_load8_lane.wast","passed":3,"failed":49},{"name":"simd_load_extend.wast","passed":18,"failed":86},{"name":"simd_load_splat.wast","passed":12,"failed":114},{"name":"simd_load_zero.wast","passed":10,"failed":29},{"name":"simd_splat.wast","passed":23,"failed":162},{"name":"simd_store.wast","passed":9,"failed":19},{"name":"simd_store16_lane.wast","passed":3,"failed":33},{"name":"simd_store32_lane.wast","passed":3,"failed":21},{"name":"simd_store64_lane.wast","passed":3,"failed":13},{"name":"simd_store8_lane.wast","passed":3,"failed":49}]
+0.9.0-alpha.0,1702,24277,[{"name":"simd_address.wast","passed":7,"failed":42},{"name":"simd_align.wast","passed":92,"failed":8},{"name":"simd_bit_shift.wast","passed":41,"failed":211},{"name":"simd_bitwise.wast","passed":30,"failed":139},{"name":"simd_boolean.wast","passed":18,"failed":259},{"name":"simd_const.wast","passed":551,"failed":206},{"name":"simd_conversions.wast","passed":50,"failed":232},{"name":"simd_f32x4.wast","passed":18,"failed":772},{"name":"simd_f32x4_arith.wast","passed":19,"failed":1803},{"name":"simd_f32x4_cmp.wast","passed":26,"failed":2581},{"name":"simd_f32x4_pmin_pmax.wast","passed":15,"failed":3872},{"name":"simd_f32x4_rounding.wast","passed":25,"failed":176},{"name":"simd_f64x2.wast","passed":10,"failed":793},{"name":"simd_f64x2_arith.wast","passed":19,"failed":1806},{"name":"simd_f64x2_cmp.wast","passed":26,"failed":2659},{"name":"simd_f64x2_pmin_pmax.wast","passed":15,"failed":3872},{"name":"simd_f64x2_rounding.wast","passed":25,"failed":176},{"name":"simd_i16x8_arith.wast","passed":13,"failed":181},{"name":"simd_i16x8_arith2.wast","passed":21,"failed":151},{"name":"simd_i16x8_cmp.wast","passed":32,"failed":433},{"name":"simd_i16x8_extadd_pairwise_i8x16.wast","passed":5,"failed":16},{"name":"simd_i16x8_extmul_i8x16.wast","passed":13,"failed":104},{"name":"simd_i16x8_q15mulr_sat_s.wast","passed":4,"failed":26},{"name":"simd_i16x8_sat_arith.wast","passed":18,"failed":204},{"name":"simd_i32x4_arith.wast","passed":13,"failed":181},{"name":"simd_i32x4_arith2.wast","passed":28,"failed":121},{"name":"simd_i32x4_cmp.wast","passed":42,"failed":433},{"name":"simd_i32x4_dot_i16x8.wast","passed":4,"failed":26},{"name":"simd_i32x4_extadd_pairwise_i16x8.wast","passed":5,"failed":16},{"name":"simd_i32x4_extmul_i16x8.wast","passed":13,"failed":104},{"name":"simd_i32x4_trunc_sat_f32x4.wast","passed":5,"failed":102},{"name":"simd_i32x4_trunc_sat_f64x2.wast","passed":5,"failed":102},{"name":"simd_i64x2_arith.wast","passed":13,"failed":187},{"name":"simd_i64x2_arith2.wast","passed":4,"failed":21},{"name":"simd_i64x2_cmp.wast","passed":11,"failed":102},{"name":"simd_i64x2_extmul_i32x4.wast","passed":13,"failed":104},{"name":"simd_i8x16_arith.wast","passed":10,"failed":121},{"name":"simd_i8x16_arith2.wast","passed":27,"failed":184},{"name":"simd_i8x16_cmp.wast","passed":32,"failed":413},{"name":"simd_i8x16_sat_arith.wast","passed":26,"failed":188},{"name":"simd_int_to_int_extend.wast","passed":25,"failed":228},{"name":"simd_lane.wast","passed":200,"failed":275},{"name":"simd_linking.wast","passed":0,"failed":3},{"name":"simd_load.wast","passed":22,"failed":17},{"name":"simd_load16_lane.wast","passed":4,"failed":32},{"name":"simd_load32_lane.wast","passed":4,"failed":20},{"name":"simd_load64_lane.wast","passed":4,"failed":12},{"name":"simd_load8_lane.wast","passed":4,"failed":48},{"name":"simd_load_extend.wast","passed":20,"failed":84},{"name":"simd_load_splat.wast","passed":14,"failed":112},{"name":"simd_load_zero.wast","passed":12,"failed":27},{"name":"simd_splat.wast","passed":26,"failed":159},{"name":"simd_store.wast","passed":11,"failed":17},{"name":"simd_store16_lane.wast","passed":3,"failed":33},{"name":"simd_store32_lane.wast","passed":3,"failed":21},{"name":"simd_store64_lane.wast","passed":3,"failed":13},{"name":"simd_store8_lane.wast","passed":3,"failed":49}]
diff --git a/crates/types/src/instructions.rs b/crates/types/src/instructions.rs
index a3c2fee..1edfef7 100644
--- a/crates/types/src/instructions.rs
+++ b/crates/types/src/instructions.rs
@@ -1,12 +1,27 @@
use super::{FuncAddr, GlobalAddr, LabelAddr, LocalAddr, TableAddr, TypeAddr, ValType};
-use crate::{DataAddr, ElemAddr, MemAddr};
+use crate::{ConstIdx, DataAddr, ElemAddr, MemAddr};
/// Represents a memory immediate in a WebAssembly memory instruction.
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize))]
-pub struct MemoryArg {
- pub offset: u64,
- pub mem_addr: MemAddr,
+
+pub struct MemoryArg([u8; 12]);
+
+impl MemoryArg {
+ pub fn new(offset: u64, mem_addr: MemAddr) -> Self {
+ let mut bytes = [0; 12];
+ bytes[0..8].copy_from_slice(&offset.to_le_bytes());
+ bytes[8..12].copy_from_slice(&mem_addr.to_le_bytes());
+ Self(bytes)
+ }
+
+ pub fn offset(&self) -> u64 {
+ u64::from_le_bytes(self.0[0..8].try_into().expect("invalid offset"))
+ }
+
+ pub fn mem_addr(&self) -> MemAddr {
+ MemAddr::from_le_bytes(self.0[8..12].try_into().expect("invalid mem_addr"))
+ }
}
type BrTableDefault = u32;
@@ -42,8 +57,8 @@ pub enum ConstInstruction {
// should be kept as small as possible (16 bytes max)
#[rustfmt::skip]
pub enum Instruction {
- LocalCopy32(LocalAddr, LocalAddr), LocalCopy64(LocalAddr, LocalAddr), LocalCopy128(LocalAddr, LocalAddr), LocalCopy128Ref(LocalAddr, LocalAddr), LocalCopyRef(LocalAddr, LocalAddr),
- LocalsStore32(LocalAddr, LocalAddr, u32, MemAddr), LocalsStore64(LocalAddr, LocalAddr, u32, MemAddr), LocalsStore128(LocalAddr, LocalAddr, u32, MemAddr), LocalsStoreRef(LocalAddr, LocalAddr, u32, MemAddr),
+ LocalCopy32(LocalAddr, LocalAddr), LocalCopy64(LocalAddr, LocalAddr), LocalCopy128(LocalAddr, LocalAddr), LocalCopyRef(LocalAddr, LocalAddr),
+ // LocalsStore32(LocalAddr, LocalAddr, u32, MemAddr), LocalsStore64(LocalAddr, LocalAddr, u32, MemAddr), LocalsStore128(LocalAddr, LocalAddr, u32, MemAddr), LocalsStoreRef(LocalAddr, LocalAddr, u32, MemAddr),
// > Control Instructions
// See <https://webassembly.github.io/spec/core/binary/instructions.html#control-instructions>
@@ -71,68 +86,48 @@ pub enum Instruction {
Return,
Call(FuncAddr),
CallIndirect(TypeAddr, TableAddr),
- ReturnCall(FuncAddr),
- ReturnCallIndirect(TypeAddr, TableAddr),
+ // ReturnCall(FuncAddr),
+ // ReturnCallIndirect(TypeAddr, TableAddr),
// > Parametric Instructions
// See <https://webassembly.github.io/spec/core/binary/instructions.html#parametric-instructions>
- Drop32,
- Drop64,
- Drop128,
- DropRef,
-
- Select32,
- Select64,
- Select128,
- SelectRef,
+ Drop32, Select32,
+ Drop64, Select64,
+ Drop128, Select128,
+ DropRef, SelectRef,
// > Variable Instructions
// See <https://webassembly.github.io/spec/core/binary/instructions.html#variable-instructions>
- LocalGet32(LocalAddr),
- LocalGet64(LocalAddr),
- LocalGet128(LocalAddr),
- LocalGetRef(LocalAddr),
-
- LocalSet32(LocalAddr),
- LocalSet64(LocalAddr),
- LocalSet128(LocalAddr),
- LocalSetRef(LocalAddr),
-
- LocalTee32(LocalAddr),
- LocalTee64(LocalAddr),
- LocalTee128(LocalAddr),
- LocalTeeRef(LocalAddr),
-
GlobalGet(GlobalAddr),
- GlobalSet32(GlobalAddr),
- GlobalSet64(GlobalAddr),
- GlobalSet128(GlobalAddr),
- GlobalSetRef(GlobalAddr),
+ LocalGet32(LocalAddr), LocalSet32(LocalAddr), LocalTee32(LocalAddr), GlobalSet32(GlobalAddr),
+ LocalGet64(LocalAddr), LocalSet64(LocalAddr), LocalTee64(LocalAddr), GlobalSet64(GlobalAddr),
+ LocalGet128(LocalAddr), LocalSet128(LocalAddr), LocalTee128(LocalAddr), GlobalSet128(GlobalAddr),
+ LocalGetRef(LocalAddr), LocalSetRef(LocalAddr), LocalTeeRef(LocalAddr), GlobalSetRef(GlobalAddr),
// > Memory Instructions
- I32Load { offset: u64, mem_addr: MemAddr },
- I64Load { offset: u64, mem_addr: MemAddr },
- F32Load { offset: u64, mem_addr: MemAddr },
- F64Load { offset: u64, mem_addr: MemAddr },
- I32Load8S { offset: u64, mem_addr: MemAddr },
- I32Load8U { offset: u64, mem_addr: MemAddr },
- I32Load16S { offset: u64, mem_addr: MemAddr },
- I32Load16U { offset: u64, mem_addr: MemAddr },
- I64Load8S { offset: u64, mem_addr: MemAddr },
- I64Load8U { offset: u64, mem_addr: MemAddr },
- I64Load16S { offset: u64, mem_addr: MemAddr },
- I64Load16U { offset: u64, mem_addr: MemAddr },
- I64Load32S { offset: u64, mem_addr: MemAddr },
- I64Load32U { offset: u64, mem_addr: MemAddr },
- I32Store { offset: u64, mem_addr: MemAddr },
- I64Store { offset: u64, mem_addr: MemAddr },
- F32Store { offset: u64, mem_addr: MemAddr },
- F64Store { offset: u64, mem_addr: MemAddr },
- I32Store8 { offset: u64, mem_addr: MemAddr },
- I32Store16 { offset: u64, mem_addr: MemAddr },
- I64Store8 { offset: u64, mem_addr: MemAddr },
- I64Store16 { offset: u64, mem_addr: MemAddr },
- I64Store32 { offset: u64, mem_addr: MemAddr },
+ I32Load(MemoryArg),
+ I64Load(MemoryArg),
+ F32Load(MemoryArg),
+ F64Load(MemoryArg),
+ I32Load8S(MemoryArg),
+ I32Load8U(MemoryArg),
+ I32Load16S(MemoryArg),
+ I32Load16U(MemoryArg),
+ I64Load8S(MemoryArg),
+ I64Load8U(MemoryArg),
+ I64Load16S(MemoryArg),
+ I64Load16U(MemoryArg),
+ I64Load32S(MemoryArg),
+ I64Load32U(MemoryArg),
+ I32Store(MemoryArg),
+ I64Store(MemoryArg),
+ F32Store(MemoryArg),
+ F64Store(MemoryArg),
+ I32Store8(MemoryArg),
+ I32Store16(MemoryArg),
+ I64Store8(MemoryArg),
+ I64Store16(MemoryArg),
+ I64Store32(MemoryArg),
MemorySize(MemAddr),
MemoryGrow(MemAddr),
@@ -146,7 +141,7 @@ pub enum Instruction {
RefNull(ValType),
RefFunc(FuncAddr),
RefIsNull,
-
+
// > Numeric Instructions
// See <https://webassembly.github.io/spec/core/binary/instructions.html#numeric-instructions>
I32Eqz, I32Eq, I32Ne, I32LtS, I32LtU, I32GtS, I32GtU, I32LeS, I32LeU, I32GeS, I32GeU,
@@ -188,7 +183,97 @@ pub enum Instruction {
DataDrop(DataAddr),
ElemDrop(ElemAddr),
- // // > SIMD Instructions
- // V128Load(MemoryArg), V128Load8x8S { offset: u64, mem_addr: MemAddr }, V128Load8x8U { offset: u64, mem_addr: MemAddr }, V128Load16x4S { offset: u64, mem_addr: MemAddr }, V128Load16x4U { offset: u64, mem_addr: MemAddr }, V128Load32x2S { offset: u64, mem_addr: MemAddr }, V128Load32x2U { offset: u64, mem_addr: MemAddr }, V128Load8Splat { offset: u64, mem_addr: MemAddr }, V128Load16Splat { offset: u64, mem_addr: MemAddr }, V128Load32Splat { offset: u64, mem_addr: MemAddr }, V128Load64Splat { offset: u64, mem_addr: MemAddr }, V128Load32Zero { offset: u64, mem_addr: MemAddr }, V128Load64Zero { offset: u64, mem_addr: MemAddr },
- // V128Store { offset: u64, mem_addr: MemAddr }, V128Store8x8 { offset: u64, mem_addr: MemAddr }, V128Store16x4 { offset: u64, mem_addr: MemAddr }, V128Store32x2 { offset: u64, mem_addr: MemAddr },
+ // > SIMD Instructions
+ Simd(SimdInstruction),
+}
+
+impl From<SimdInstruction> for Instruction {
+ fn from(instr: SimdInstruction) -> Self {
+ Instruction::Simd(instr)
+ }
+}
+
+#[derive(Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize))]
+#[rustfmt::skip]
+pub enum SimdInstruction {
+ V128Load(MemoryArg),
+ V128Load8x8S(MemoryArg), V128Load8x8U(MemoryArg),
+ V128Load16x4S(MemoryArg), V128Load16x4U(MemoryArg),
+ V128Load32x2S(MemoryArg), V128Load32x2U(MemoryArg),
+
+ V128Load8Splat(MemoryArg), V128Load16Splat(MemoryArg), V128Load32Splat(MemoryArg), V128Load64Splat(MemoryArg),
+ V128Load8Lane(MemoryArg, u8), V128Load16Lane(MemoryArg, u8), V128Load32Lane(MemoryArg, u8), V128Load64Lane(MemoryArg, u8),
+
+ V128Load32Zero(MemoryArg), V128Load64Zero(MemoryArg),
+
+ V128Store(MemoryArg), V128Store8Lane(MemoryArg, u8), V128Store16Lane(MemoryArg, u8), V128Store32Lane(MemoryArg, u8), V128Store64Lane(MemoryArg, u8),
+
+ I8x16Shuffle(ConstIdx),
+ V128Const(ConstIdx),
+
+ I8x16ExtractLaneS(u8), I8x16ExtractLaneU(u8), I8x16ReplaceLane(u8),
+ I16x8ExtractLaneS(u8), I16x8ExtractLaneU(u8), I16x8ReplaceLane(u8),
+ I32x4ExtractLane(u8), I32x4ReplaceLane(u8),
+ I64x2ExtractLane(u8), I64x2ReplaceLane(u8),
+ F32x4ExtractLane(u8), F32x4ReplaceLane(u8),
+ F64x2ExtractLane(u8), F64x2ReplaceLane(u8),
+
+ V128Not, V128And, V128AndNot, V128Or, V128Xor, V128Bitselect, V128AnyTrue,
+
+ I8x16Splat, I8x16Swizzle, I8x16Eq, I8x16Ne, I8x16LtS, I8x16LtU, I8x16GtS, I8x16GtU, I8x16LeS, I8x16LeU, I8x16GeS, I8x16GeU,
+ I16x8Splat, I16x8Eq, I16x8Ne, I16x8LtS, I16x8LtU, I16x8GtS, I16x8GtU, I16x8LeS, I16x8LeU, I16x8GeS, I16x8GeU,
+ I32x4Splat, I32x4Eq, I32x4Ne, I32x4LtS, I32x4LtU, I32x4GtS, I32x4GtU, I32x4LeS, I32x4LeU, I32x4GeS, I32x4GeU,
+ I64x2Splat, I64x2Eq, I64x2Ne, I64x2LtS, I64x2GtS, I64x2LeS, I64x2GeS,
+ F32x4Splat, F32x4Eq, F32x4Ne, F32x4Lt, F32x4Gt, F32x4Le, F32x4Ge,
+ F64x2Splat, F64x2Eq, F64x2Ne, F64x2Lt, F64x2Gt, F64x2Le, F64x2Ge,
+
+ I8x16Abs, I8x16Neg, I8x16AllTrue, I8x16Bitmask, I8x16Shl, I8x16ShrS, I8x16ShrU, I8x16Add, I8x16Sub, I8x16MinS, I8x16MinU, I8x16MaxS, I8x16MaxU,
+ I16x8Abs, I16x8Neg, I16x8AllTrue, I16x8Bitmask, I16x8Shl, I16x8ShrS, I16x8ShrU, I16x8Add, I16x8Sub, I16x8MinS, I16x8MinU, I16x8MaxS, I16x8MaxU,
+ I32x4Abs, I32x4Neg, I32x4AllTrue, I32x4Bitmask, I32x4Shl, I32x4ShrS, I32x4ShrU, I32x4Add, I32x4Sub, I32x4MinS, I32x4MinU, I32x4MaxS, I32x4MaxU,
+ I64x2Abs, I64x2Neg, I64x2AllTrue, I64x2Bitmask, I64x2Shl, I64x2ShrS, I64x2ShrU, I64x2Add, I64x2Sub, I64x2Mul,
+
+ I8x16NarrowI16x8S, I8x16NarrowI16x8U, I8x16AddSatS, I8x16AddSatU, I8x16SubSatS, I8x16SubSatU, I8x16AvgrU,
+ I16x8NarrowI32x4S, I16x8NarrowI32x4U, I16x8AddSatS, I16x8AddSatU, I16x8SubSatS, I16x8SubSatU, I16x8AvgrU,
+
+ I16x8ExtAddPairwiseI8x16S, I16x8ExtAddPairwiseI8x16U, I16x8Mul,
+ I32x4ExtAddPairwiseI16x8S, I32x4ExtAddPairwiseI16x8U, I32x4Mul,
+
+ I16x8ExtMulLowI8x16S, I16x8ExtMulLowI8x16U, I16x8ExtMulHighI8x16S, I16x8ExtMulHighI8x16U,
+ I32x4ExtMulLowI16x8S, I32x4ExtMulLowI16x8U, I32x4ExtMulHighI16x8S, I32x4ExtMulHighI16x8U,
+ I64x2ExtMulLowI32x4S, I64x2ExtMulLowI32x4U, I64x2ExtMulHighI32x4S, I64x2ExtMulHighI32x4U,
+
+ I16x8ExtendLowI8x16S, I16x8ExtendLowI8x16U, I16x8ExtendHighI8x16S, I16x8ExtendHighI8x16U,
+ I32x4ExtendLowI16x8S, I32x4ExtendLowI16x8U, I32x4ExtendHighI16x8S, I32x4ExtendHighI16x8U,
+ I64x2ExtendLowI32x4S, I64x2ExtendLowI32x4U, I64x2ExtendHighI32x4S, I64x2ExtendHighI32x4U,
+
+ I8x16Popcnt, I16x8Q15MulrSatS, I32x4DotI16x8S,
+
+ F32x4Ceil, F32x4Floor, F32x4Trunc, F32x4Nearest, F32x4Abs, F32x4Neg, F32x4Sqrt, F32x4Add, F32x4Sub, F32x4Mul, F32x4Div, F32x4Min, F32x4Max, F32x4PMin, F32x4PMax,
+ F64x2Ceil, F64x2Floor, F64x2Trunc, F64x2Nearest, F64x2Abs, F64x2Neg, F64x2Sqrt, F64x2Add, F64x2Sub, F64x2Mul, F64x2Div, F64x2Min, F64x2Max, F64x2PMin, F64x2PMax,
+ I32x4TruncSatF32x4S, I32x4TruncSatF32x4U,
+ F32x4ConvertI32x4S, F32x4ConvertI32x4U,
+ I32x4TruncSatF64x2SZero, I32x4TruncSatF64x2UZero,
+ F64x2ConvertLowI32x4S, F64x2ConvertLowI32x4U,
+ F32x4DemoteF64x2Zero, F64x2PromoteLowF32x4,
+}
+
+#[derive(Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize))]
+#[rustfmt::skip]
+pub enum RelaxedSimd {
+ I8x16RelaxedSwizzle,
+ I32x4RelaxedTruncF32x4S, I32x4RelaxedTruncF32x4U,
+ I32x4RelaxedTruncF64x2SZero, I32x4RelaxedTruncF64x2UZero,
+ F32x4RelaxedMadd, F32x4RelaxedNmadd,
+ F64x2RelaxedMadd, F64x2RelaxedNmadd,
+ I8x16RelaxedLaneselect,
+ I16x8RelaxedLaneselect,
+ I32x4RelaxedLaneselect,
+ I64x2RelaxedLaneselect,
+ F32x4RelaxedMin, F32x4RelaxedMax,
+ F64x2RelaxedMin, F64x2RelaxedMax,
+ I16x8RelaxedQ15mulrS,
+ I16x8RelaxedDotI8x16I7x16S,
+ I32x4RelaxedDotI8x16I7x16AddS
}
diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs
index 8ee044f..58120fe 100644
--- a/crates/types/src/lib.rs
+++ b/crates/types/src/lib.rs
@@ -135,6 +135,7 @@ pub type GlobalAddr = Addr;
pub type ElemAddr = Addr;
pub type DataAddr = Addr;
pub type ExternAddr = Addr;
+pub type ConstIdx = Addr;
// additional internal addresses
pub type TypeAddr = Addr;
@@ -203,15 +204,52 @@ pub struct ValueCountsSmall {
pub cref: u16,
}
+impl<'a, T: IntoIterator<Item = &'a ValType>> From<T> for ValueCounts {
+ fn from(types: T) -> Self {
+ let mut counts = ValueCounts::default();
+ for ty in types {
+ match ty {
+ ValType::I32 | ValType::F32 => counts.c32 += 1,
+ ValType::I64 | ValType::F64 => counts.c64 += 1,
+ ValType::V128 => counts.c128 += 1,
+ ValType::RefExtern | ValType::RefFunc => counts.cref += 1,
+ }
+ }
+ counts
+ }
+}
+
+impl<'a, T: IntoIterator<Item = &'a ValType>> From<T> for ValueCountsSmall {
+ fn from(types: T) -> Self {
+ let mut counts = ValueCountsSmall::default();
+ for ty in types {
+ match ty {
+ ValType::I32 | ValType::F32 => counts.c32 += 1,
+ ValType::I64 | ValType::F64 => counts.c64 += 1,
+ ValType::V128 => counts.c128 += 1,
+ ValType::RefExtern | ValType::RefFunc => counts.cref += 1,
+ }
+ }
+ counts
+ }
+}
+
#[derive(Debug, Clone, PartialEq, Default)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize))]
pub struct WasmFunction {
pub instructions: Box<[Instruction]>,
+ pub data: WasmFunctionData,
pub locals: ValueCounts,
pub params: ValueCountsSmall,
pub ty: FuncType,
}
+#[derive(Debug, Clone, PartialEq, Default)]
+#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize))]
+pub struct WasmFunctionData {
+ pub v128_constants: Box<[u128]>,
+}
+
/// A WebAssembly Module Export
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize))]
diff --git a/crates/wasm-testsuite/Cargo.toml b/crates/wasm-testsuite/Cargo.toml
index 8edcb8a..46df77f 100644
--- a/crates/wasm-testsuite/Cargo.toml
+++ b/crates/wasm-testsuite/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name="wasm-testsuite"
-version="0.5.0"
+version="0.6.0-alpha.0"
description="Mirror of the WebAssembly core testsuite for use in testing WebAssembly implementations"
license="Apache-2.0"
readme="README.md"