From a3ca2af26f066900e2db550bbd608aceadf1ac7c Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Thu, 12 Sep 2024 21:03:44 +0200 Subject: chore: refactor compiler macros Signed-off-by: Henry Gressmann --- crates/parser/src/visit.rs | 253 +++++--------------------------- crates/tinywasm/src/interpreter/simd.rs | 130 ++++++++++++++++ crates/tinywasm/tests/test-wasm-2.rs | 2 +- crates/types/Cargo.toml | 2 +- crates/types/src/instructions.rs | 22 +-- crates/wasm-testsuite/lib.rs | 2 +- 6 files changed, 172 insertions(+), 239 deletions(-) create mode 100644 crates/tinywasm/src/interpreter/simd.rs (limited to 'crates') diff --git a/crates/parser/src/visit.rs b/crates/parser/src/visit.rs index 73cf9b4..4e39a5a 100644 --- a/crates/parser/src/visit.rs +++ b/crates/parser/src/visit.rs @@ -43,29 +43,34 @@ pub(crate) fn process_operators_and_validate( Ok((builder.instructions.into_boxed_slice(), builder.validator.into_allocations())) } -macro_rules! define_operands { - ($($name:ident, $instr:expr),*) => {$( - fn $name(&mut self) -> Self::Output { - self.instructions.push($instr); - } - )*}; -} - -macro_rules! define_primitive_operands { - ($($name:ident, $instr:expr, $ty:ty),*) => {$( +macro_rules! define_operand { + ($name:ident($instr:ident, $ty:ty)) => { fn $name(&mut self, arg: $ty) -> Self::Output { - self.instructions.push($instr(arg)); + self.instructions.push(Instruction::$instr(arg)); } - )*}; - ($($name:ident, $instr:expr, $ty:ty, $ty2:ty),*) => {$( + }; + + ($name:ident($instr:ident, $ty:ty, $ty2:ty)) => { fn $name(&mut self, arg: $ty, arg2: $ty2) -> Self::Output { - self.instructions.push($instr(arg, arg2)); + self.instructions.push(Instruction::$instr(arg, arg2)); + } + }; + + ($name:ident($instr:ident)) => { + fn $name(&mut self) -> Self::Output { + self.instructions.push(Instruction::$instr); } + }; +} + +macro_rules! define_operands { + ($($name:ident($instr:ident $(,$ty:ty)*)),*) => {$( + define_operand!($name($instr $(,$ty)*)); )*}; } macro_rules! define_mem_operands { - ($($name:ident, $instr:ident),*) => {$( + ($($name:ident($instr:ident)),*) => {$( fn $name(&mut self, memarg: wasmparser::MemArg) -> Self::Output { self.instructions.push(Instruction::$instr { offset: memarg.offset, @@ -123,6 +128,7 @@ macro_rules! impl_visit_operator { (@@saturating_float_to_int $($rest:tt)* ) => {}; (@@bulk_memory $($rest:tt)* ) => {}; (@@tail_call $($rest:tt)* ) => {}; + // (@@simd $($rest:tt)* ) => {}; (@@$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident) => { #[cold] fn $visit(&mut self $($(,$arg: $argty)*)?) { @@ -135,187 +141,28 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild type Output = (); wasmparser::for_each_operator!(impl_visit_operator); - define_primitive_operands! { - visit_br, Instruction::Br, u32, - visit_br_if, Instruction::BrIf, u32, - visit_global_get, Instruction::GlobalGet, u32, - visit_i32_const, Instruction::I32Const, i32, - visit_i64_const, Instruction::I64Const, i64, - visit_call, Instruction::Call, u32, - visit_memory_size, Instruction::MemorySize, u32, - visit_memory_grow, Instruction::MemoryGrow, u32 - } - 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), 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) } define_operands! { - visit_unreachable, Instruction::Unreachable, - visit_nop, Instruction::Nop, - visit_return, Instruction::Return, - visit_i32_eqz, Instruction::I32Eqz, - visit_i32_eq, Instruction::I32Eq, - visit_i32_ne, Instruction::I32Ne, - visit_i32_lt_s, Instruction::I32LtS, - visit_i32_lt_u, Instruction::I32LtU, - visit_i32_gt_s, Instruction::I32GtS, - visit_i32_gt_u, Instruction::I32GtU, - visit_i32_le_s, Instruction::I32LeS, - visit_i32_le_u, Instruction::I32LeU, - visit_i32_ge_s, Instruction::I32GeS, - visit_i32_ge_u, Instruction::I32GeU, - visit_i64_eqz, Instruction::I64Eqz, - visit_i64_eq, Instruction::I64Eq, - visit_i64_ne, Instruction::I64Ne, - visit_i64_lt_s, Instruction::I64LtS, - visit_i64_lt_u, Instruction::I64LtU, - visit_i64_gt_s, Instruction::I64GtS, - visit_i64_gt_u, Instruction::I64GtU, - visit_i64_le_s, Instruction::I64LeS, - visit_i64_le_u, Instruction::I64LeU, - visit_i64_ge_s, Instruction::I64GeS, - visit_i64_ge_u, Instruction::I64GeU, - visit_f32_eq, Instruction::F32Eq, - visit_f32_ne, Instruction::F32Ne, - visit_f32_lt, Instruction::F32Lt, - visit_f32_gt, Instruction::F32Gt, - visit_f32_le, Instruction::F32Le, - visit_f32_ge, Instruction::F32Ge, - visit_f64_eq, Instruction::F64Eq, - visit_f64_ne, Instruction::F64Ne, - visit_f64_lt, Instruction::F64Lt, - visit_f64_gt, Instruction::F64Gt, - visit_f64_le, Instruction::F64Le, - visit_f64_ge, Instruction::F64Ge, - visit_i32_clz, Instruction::I32Clz, - visit_i32_ctz, Instruction::I32Ctz, - visit_i32_popcnt, Instruction::I32Popcnt, - // visit_i32_add, Instruction::I32Add, custom implementation - visit_i32_sub, Instruction::I32Sub, - visit_i32_mul, Instruction::I32Mul, - visit_i32_div_s, Instruction::I32DivS, - visit_i32_div_u, Instruction::I32DivU, - visit_i32_rem_s, Instruction::I32RemS, - visit_i32_rem_u, Instruction::I32RemU, - visit_i32_and, Instruction::I32And, - visit_i32_or, Instruction::I32Or, - visit_i32_xor, Instruction::I32Xor, - visit_i32_shl, Instruction::I32Shl, - visit_i32_shr_s, Instruction::I32ShrS, - visit_i32_shr_u, Instruction::I32ShrU, - visit_i32_rotl, Instruction::I32Rotl, - visit_i32_rotr, Instruction::I32Rotr, - visit_i64_clz, Instruction::I64Clz, - visit_i64_ctz, Instruction::I64Ctz, - visit_i64_popcnt, Instruction::I64Popcnt, - visit_i64_add, Instruction::I64Add, - visit_i64_sub, Instruction::I64Sub, - visit_i64_mul, Instruction::I64Mul, - visit_i64_div_s, Instruction::I64DivS, - visit_i64_div_u, Instruction::I64DivU, - visit_i64_rem_s, Instruction::I64RemS, - visit_i64_rem_u, Instruction::I64RemU, - visit_i64_and, Instruction::I64And, - visit_i64_or, Instruction::I64Or, - visit_i64_xor, Instruction::I64Xor, - visit_i64_shl, Instruction::I64Shl, - visit_i64_shr_s, Instruction::I64ShrS, - visit_i64_shr_u, Instruction::I64ShrU, - // visit_i64_rotl, Instruction::I64Rotl, custom implementation - visit_i64_rotr, Instruction::I64Rotr, - visit_f32_abs, Instruction::F32Abs, - visit_f32_neg, Instruction::F32Neg, - visit_f32_ceil, Instruction::F32Ceil, - visit_f32_floor, Instruction::F32Floor, - visit_f32_trunc, Instruction::F32Trunc, - visit_f32_nearest, Instruction::F32Nearest, - visit_f32_sqrt, Instruction::F32Sqrt, - visit_f32_add, Instruction::F32Add, - visit_f32_sub, Instruction::F32Sub, - visit_f32_mul, Instruction::F32Mul, - visit_f32_div, Instruction::F32Div, - visit_f32_min, Instruction::F32Min, - visit_f32_max, Instruction::F32Max, - visit_f32_copysign, Instruction::F32Copysign, - visit_f64_abs, Instruction::F64Abs, - visit_f64_neg, Instruction::F64Neg, - visit_f64_ceil, Instruction::F64Ceil, - visit_f64_floor, Instruction::F64Floor, - visit_f64_trunc, Instruction::F64Trunc, - visit_f64_nearest, Instruction::F64Nearest, - visit_f64_sqrt, Instruction::F64Sqrt, - visit_f64_add, Instruction::F64Add, - visit_f64_sub, Instruction::F64Sub, - visit_f64_mul, Instruction::F64Mul, - visit_f64_div, Instruction::F64Div, - visit_f64_min, Instruction::F64Min, - visit_f64_max, Instruction::F64Max, - visit_f64_copysign, Instruction::F64Copysign, - visit_i32_wrap_i64, Instruction::I32WrapI64, - visit_i32_trunc_f32_s, Instruction::I32TruncF32S, - visit_i32_trunc_f32_u, Instruction::I32TruncF32U, - visit_i32_trunc_f64_s, Instruction::I32TruncF64S, - visit_i32_trunc_f64_u, Instruction::I32TruncF64U, - visit_i64_extend_i32_s, Instruction::I64ExtendI32S, - visit_i64_extend_i32_u, Instruction::I64ExtendI32U, - visit_i64_trunc_f32_s, Instruction::I64TruncF32S, - visit_i64_trunc_f32_u, Instruction::I64TruncF32U, - visit_i64_trunc_f64_s, Instruction::I64TruncF64S, - visit_i64_trunc_f64_u, Instruction::I64TruncF64U, - visit_f32_convert_i32_s, Instruction::F32ConvertI32S, - visit_f32_convert_i32_u, Instruction::F32ConvertI32U, - visit_f32_convert_i64_s, Instruction::F32ConvertI64S, - visit_f32_convert_i64_u, Instruction::F32ConvertI64U, - visit_f32_demote_f64, Instruction::F32DemoteF64, - visit_f64_convert_i32_s, Instruction::F64ConvertI32S, - visit_f64_convert_i32_u, Instruction::F64ConvertI32U, - visit_f64_convert_i64_s, Instruction::F64ConvertI64S, - visit_f64_convert_i64_u, Instruction::F64ConvertI64U, - visit_f64_promote_f32, Instruction::F64PromoteF32, - visit_i32_reinterpret_f32, Instruction::I32ReinterpretF32, - visit_i64_reinterpret_f64, Instruction::I64ReinterpretF64, - visit_f32_reinterpret_i32, Instruction::F32ReinterpretI32, - visit_f64_reinterpret_i64, Instruction::F64ReinterpretI64, + // basic instructions + visit_br(Br, u32), visit_br_if(BrIf, u32), visit_global_get(GlobalGet, u32), visit_i32_const(I32Const, i32), visit_i64_const(I64Const, i64), visit_call(Call, u32), visit_memory_size(MemorySize, u32), visit_memory_grow(MemoryGrow, u32), visit_unreachable(Unreachable), visit_nop(Nop), visit_return(Return), visit_i32_eqz(I32Eqz), visit_i32_eq(I32Eq), visit_i32_ne(I32Ne), visit_i32_lt_s(I32LtS), visit_i32_lt_u(I32LtU), visit_i32_gt_s(I32GtS), visit_i32_gt_u(I32GtU), visit_i32_le_s(I32LeS), visit_i32_le_u(I32LeU), visit_i32_ge_s(I32GeS), visit_i32_ge_u(I32GeU), visit_i64_eqz(I64Eqz), visit_i64_eq(I64Eq), visit_i64_ne(I64Ne), visit_i64_lt_s(I64LtS), visit_i64_lt_u(I64LtU), visit_i64_gt_s(I64GtS), visit_i64_gt_u(I64GtU), visit_i64_le_s(I64LeS), visit_i64_le_u(I64LeU), visit_i64_ge_s(I64GeS), visit_i64_ge_u(I64GeU), visit_f32_eq(F32Eq), visit_f32_ne(F32Ne), visit_f32_lt(F32Lt), visit_f32_gt(F32Gt), visit_f32_le(F32Le), visit_f32_ge(F32Ge), visit_f64_eq(F64Eq), visit_f64_ne(F64Ne), visit_f64_lt(F64Lt), visit_f64_gt(F64Gt), visit_f64_le(F64Le), visit_f64_ge(F64Ge), visit_i32_clz(I32Clz), visit_i32_ctz(I32Ctz), visit_i32_popcnt(I32Popcnt), visit_i32_add(I32Add), visit_i32_sub(I32Sub), visit_i32_mul(I32Mul), visit_i32_div_s(I32DivS), visit_i32_div_u(I32DivU), visit_i32_rem_s(I32RemS), visit_i32_rem_u(I32RemU), visit_i32_and(I32And), visit_i32_or(I32Or), visit_i32_xor(I32Xor), visit_i32_shl(I32Shl), visit_i32_shr_s(I32ShrS), visit_i32_shr_u(I32ShrU), visit_i32_rotl(I32Rotl), visit_i32_rotr(I32Rotr), visit_i64_clz(I64Clz), visit_i64_ctz(I64Ctz), visit_i64_popcnt(I64Popcnt), visit_i64_add(I64Add), visit_i64_sub(I64Sub), visit_i64_mul(I64Mul), visit_i64_div_s(I64DivS), visit_i64_div_u(I64DivU), visit_i64_rem_s(I64RemS), visit_i64_rem_u(I64RemU), visit_i64_and(I64And), visit_i64_or(I64Or), visit_i64_xor(I64Xor), visit_i64_shl(I64Shl), visit_i64_shr_s(I64ShrS), visit_i64_shr_u(I64ShrU), visit_i64_rotl(I64Rotl), visit_i64_rotr(I64Rotr), visit_f32_abs(F32Abs), visit_f32_neg(F32Neg), visit_f32_ceil(F32Ceil), visit_f32_floor(F32Floor), visit_f32_trunc(F32Trunc), visit_f32_nearest(F32Nearest), visit_f32_sqrt(F32Sqrt), visit_f32_add(F32Add), visit_f32_sub(F32Sub), visit_f32_mul(F32Mul), visit_f32_div(F32Div), visit_f32_min(F32Min), visit_f32_max(F32Max), visit_f32_copysign(F32Copysign), visit_f64_abs(F64Abs), visit_f64_neg(F64Neg), visit_f64_ceil(F64Ceil), visit_f64_floor(F64Floor), visit_f64_trunc(F64Trunc), visit_f64_nearest(F64Nearest), visit_f64_sqrt(F64Sqrt), visit_f64_add(F64Add), visit_f64_sub(F64Sub), visit_f64_mul(F64Mul), visit_f64_div(F64Div), visit_f64_min(F64Min), visit_f64_max(F64Max), visit_f64_copysign(F64Copysign), visit_i32_wrap_i64(I32WrapI64), visit_i32_trunc_f32_s(I32TruncF32S), visit_i32_trunc_f32_u(I32TruncF32U), visit_i32_trunc_f64_s(I32TruncF64S), visit_i32_trunc_f64_u(I32TruncF64U), visit_i64_extend_i32_s(I64ExtendI32S), visit_i64_extend_i32_u(I64ExtendI32U), visit_i64_trunc_f32_s(I64TruncF32S), visit_i64_trunc_f32_u(I64TruncF32U), visit_i64_trunc_f64_s(I64TruncF64S), visit_i64_trunc_f64_u(I64TruncF64U), visit_f32_convert_i32_s(F32ConvertI32S), visit_f32_convert_i32_u(F32ConvertI32U), visit_f32_convert_i64_s(F32ConvertI64S), visit_f32_convert_i64_u(F32ConvertI64U), visit_f32_demote_f64(F32DemoteF64), visit_f64_convert_i32_s(F64ConvertI32S), visit_f64_convert_i32_u(F64ConvertI32U), visit_f64_convert_i64_s(F64ConvertI64S), visit_f64_convert_i64_u(F64ConvertI64U), visit_f64_promote_f32(F64PromoteF32), visit_i32_reinterpret_f32(I32ReinterpretF32), visit_i64_reinterpret_f64(I64ReinterpretF64), visit_f32_reinterpret_i32(F32ReinterpretI32), visit_f64_reinterpret_i64(F64ReinterpretI64), // sign_extension - visit_i32_extend8_s, Instruction::I32Extend8S, - visit_i32_extend16_s, Instruction::I32Extend16S, - visit_i64_extend8_s, Instruction::I64Extend8S, - visit_i64_extend16_s, Instruction::I64Extend16S, - visit_i64_extend32_s, Instruction::I64Extend32S, + visit_i32_extend8_s(I32Extend8S), visit_i32_extend16_s(I32Extend16S), visit_i64_extend8_s(I64Extend8S), visit_i64_extend16_s(I64Extend16S), visit_i64_extend32_s(I64Extend32S), // Non-trapping Float-to-int Conversions - visit_i32_trunc_sat_f32_s, Instruction::I32TruncSatF32S, - visit_i32_trunc_sat_f32_u, Instruction::I32TruncSatF32U, - visit_i32_trunc_sat_f64_s, Instruction::I32TruncSatF64S, - visit_i32_trunc_sat_f64_u, Instruction::I32TruncSatF64U, - visit_i64_trunc_sat_f32_s, Instruction::I64TruncSatF32S, - visit_i64_trunc_sat_f32_u, Instruction::I64TruncSatF32U, - visit_i64_trunc_sat_f64_s, Instruction::I64TruncSatF64S, - visit_i64_trunc_sat_f64_u, Instruction::I64TruncSatF64U + visit_i32_trunc_sat_f32_s(I32TruncSatF32S), visit_i32_trunc_sat_f32_u(I32TruncSatF32U), visit_i32_trunc_sat_f64_s(I32TruncSatF64S), visit_i32_trunc_sat_f64_u(I32TruncSatF64U), visit_i64_trunc_sat_f32_s(I64TruncSatF32S), visit_i64_trunc_sat_f32_u(I64TruncSatF32U), visit_i64_trunc_sat_f64_s(I64TruncSatF64S), visit_i64_trunc_sat_f64_u(I64TruncSatF64U), + + // Reference Types + visit_ref_func(RefFunc, u32), visit_table_fill(TableFill, u32), visit_table_get(TableGet, u32), visit_table_set(TableSet, u32), visit_table_grow(TableGrow, u32), visit_table_size(TableSize, u32), + + // 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) } fn visit_return_call(&mut self, function_index: u32) -> Self::Output { @@ -452,14 +299,6 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild } } - fn visit_i64_rotl(&mut self) -> Self::Output { - self.instructions.push(Instruction::I64Rotl); - } - - fn visit_i32_add(&mut self) -> Self::Output { - self.instructions.push(Instruction::I32Add); - } - fn visit_block(&mut self, blockty: wasmparser::BlockType) -> Self::Output { self.label_ptrs.push(self.instructions.len()); self.instructions.push(match blockty { @@ -582,19 +421,6 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild self.instructions.push(Instruction::F64Const(f64::from_bits(val.bits()))); } - // Bulk Memory Operations - - define_primitive_operands! { - visit_memory_init, Instruction::MemoryInit, u32, u32, - visit_memory_copy, Instruction::MemoryCopy, u32, u32, - visit_table_init, Instruction::TableInit, u32, u32 - } - define_primitive_operands! { - visit_memory_fill, Instruction::MemoryFill, u32, - visit_data_drop, Instruction::DataDrop, u32, - visit_elem_drop, Instruction::ElemDrop, u32 - } - fn visit_table_copy(&mut self, dst_table: u32, src_table: u32) -> Self::Output { self.instructions.push(Instruction::TableCopy { from: src_table, to: dst_table }); } @@ -618,13 +444,4 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild wasmparser::ValType::Ref(_) => Instruction::SelectRef, }); } - - define_primitive_operands! { - visit_ref_func, Instruction::RefFunc, u32, - visit_table_fill, Instruction::TableFill, u32, - visit_table_get, Instruction::TableGet, u32, - visit_table_set, Instruction::TableSet, u32, - visit_table_grow, Instruction::TableGrow, u32, - visit_table_size, Instruction::TableSize, u32 - } } diff --git a/crates/tinywasm/src/interpreter/simd.rs b/crates/tinywasm/src/interpreter/simd.rs new file mode 100644 index 0000000..bc2f402 --- /dev/null +++ b/crates/tinywasm/src/interpreter/simd.rs @@ -0,0 +1,130 @@ +// WIP + +struct V128([u8; 16]); + +impl V128 { + fn f32x4(&self) -> [f32; 4] { + let mut res = [0.0; 4]; + for i in 0..4 { + let mut f = [0; 4]; + for j in 0..4 { + f[j] = self.0[i * 4 + j]; + } + res[i] = f32::from_le_bytes(f); + } + res + } + + fn i32x4(&self) -> [i32; 4] { + let mut res = [0; 4]; + for i in 0..4 { + let mut f = [0; 4]; + for j in 0..4 { + f[j] = self.0[i * 4 + j]; + } + res[i] = i32::from_le_bytes(f); + } + res + } + + fn i64x2(&self) -> [i64; 2] { + let mut res = [0; 2]; + for i in 0..2 { + let mut f = [0; 8]; + for j in 0..8 { + f[j] = self.0[i * 8 + j]; + } + res[i] = i64::from_le_bytes(f); + } + res + } + + fn f64x2(&self) -> [f64; 2] { + let mut res = [0.0; 2]; + for i in 0..2 { + let mut f = [0; 8]; + for j in 0..8 { + f[j] = self.0[i * 8 + j]; + } + res[i] = f64::from_le_bytes(f); + } + res + } + + fn i16x8(&self) -> [i16; 8] { + let mut res = [0; 8]; + for i in 0..8 { + let mut f = [0; 2]; + for j in 0..2 { + f[j] = self.0[i * 2 + j]; + } + res[i] = i16::from_le_bytes(f); + } + res + } + + fn i8x16(&self) -> [i8; 16] { + let mut res = [0; 16]; + for i in 0..16 { + res[i] = i8::from_le_bytes([self.0[i]]); + } + res + } +} + +fn vvunop(c1: V128) -> V128 { + let mut res = [0; 16]; + for i in 0..16 { + res[i] = !c1.0[i]; + } + V128(res) +} + +fn vvbinop(c1: V128, c2: V128) -> V128 { + let mut res = [0; 16]; + for i in 0..16 { + res[i] = c1.0[i] & c2.0[i]; + } + V128(res) +} + +fn vvternop(c1: V128, c2: V128, c3: V128) -> V128 { + let mut res = [0; 16]; + for i in 0..16 { + res[i] = c1.0[i] & c2.0[i] | !c1.0[i] & c3.0[i]; + } + V128(res) +} + +fn any_true(val: V128) -> bool { + val.0.iter().any(|&x| x != 0) +} + +fn i8x16_swizzle(c1: V128, c2: V128) -> V128 { + let mut res = [0; 16]; + for i in 0..16 { + res[i] = c1.0[c2.0[i] as usize]; + } + V128(res) +} + +fn i18x16_shuffle(c1: V128, c2: V128) -> V128 { + let mut res = [0; 16]; + for i in 0..16 { + res[i] = c1.0[(c2.0[i] & 0xf) as usize]; + } + V128(res) +} + +fn f32x4_abs(val: V128) -> V128 { + let mut res = [0; 16]; + for i in 0..4 { + let f = val.f32x4(); + let f = f32::abs(f[i]); + let f = f.to_le_bytes(); + for j in 0..4 { + res[i * 4 + j] = f[j]; + } + } + V128(res) +} diff --git a/crates/tinywasm/tests/test-wasm-2.rs b/crates/tinywasm/tests/test-wasm-2.rs index bd1afe6..336632f 100644 --- a/crates/tinywasm/tests/test-wasm-2.rs +++ b/crates/tinywasm/tests/test-wasm-2.rs @@ -7,7 +7,7 @@ fn main() -> Result<()> { let mut test_suite = TestSuite::new(); TestSuite::set_log_level(log::LevelFilter::Off); - test_suite.run_spec_group(wasm_testsuite::V2_DRAFT_1_TESTS)?; + test_suite.run_spec_group(wasm_testsuite::V2_TESTS)?; test_suite.save_csv("./tests/generated/wasm-2.csv", env!("CARGO_PKG_VERSION"))?; if test_suite.failed() { diff --git a/crates/types/Cargo.toml b/crates/types/Cargo.toml index 7531ab4..9d9f9af 100644 --- a/crates/types/Cargo.toml +++ b/crates/types/Cargo.toml @@ -10,7 +10,7 @@ rust-version.workspace=true [dependencies] log={workspace=true, optional=true} -rkyv={version="0.8.0-rc.2", optional=true, default-features=false, features=["alloc", "bytecheck"]} +rkyv={version="0.8.1", optional=true, default-features=false, features=["alloc", "bytecheck"]} [features] default=["std", "logging", "archive"] diff --git a/crates/types/src/instructions.rs b/crates/types/src/instructions.rs index 2030942..a3c2fee 100644 --- a/crates/types/src/instructions.rs +++ b/crates/types/src/instructions.rs @@ -42,24 +42,6 @@ pub enum ConstInstruction { // should be kept as small as possible (16 bytes max) #[rustfmt::skip] pub enum Instruction { - // > Custom Instructions - // // LocalGet + I32Const + I32Add - // I32LocalGetConstAdd(LocalAddr, i32), - // // LocalGet + I32Const + I32Store - // I32ConstStoreLocal { local: LocalAddr, const_i32: i32, offset: u32, mem_addr: u8 }, - // // LocalGet + LocalGet + I32Store - // I32StoreLocal { local_a: LocalAddr, local_b: LocalAddr, offset: u32, mem_addr: u8 }, - // // I64Xor + I64Const + I64RotL - // // Commonly used by a few crypto libraries - // I64XorConstRotl(i64), - // // LocalTee + LocalGet - // LocalTeeGet(LocalAddr, LocalAddr), - // LocalGet2(LocalAddr, LocalAddr), - // LocalGet3(LocalAddr, LocalAddr, LocalAddr), - // LocalGetSet(LocalAddr, LocalAddr), - - // LocalGetGet32(LocalAddr, LocalAddr), LocalGetGet64(LocalAddr, LocalAddr), LocalGetGet128(LocalAddr, LocalAddr), - // LocalTeeGet32(LocalAddr, LocalAddr), LocalTeeGet64(LocalAddr, LocalAddr), LocalTeeGet128(LocalAddr, LocalAddr), 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), @@ -205,4 +187,8 @@ pub enum Instruction { MemoryFill(MemAddr), 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 }, } diff --git a/crates/wasm-testsuite/lib.rs b/crates/wasm-testsuite/lib.rs index 12bf459..2a2892c 100644 --- a/crates/wasm-testsuite/lib.rs +++ b/crates/wasm-testsuite/lib.rs @@ -32,7 +32,7 @@ pub const MVP_TESTS: &[&str] = &["address.wast", "align.wast", "binary-leb128.wa /// List of all tests that apply to the V2 draft 1 spec. #[rustfmt::skip] -pub const V2_DRAFT_1_TESTS: &[&str] = &["address.wast", "align.wast", "binary-leb128.wast", "binary.wast", "block.wast", "br.wast", "br_if.wast", "br_table.wast", "bulk.wast", "call.wast", "call_indirect.wast", "comments.wast", "const.wast", "conversions.wast", "custom.wast", "data.wast", "elem.wast", "endianness.wast", "exports.wast", "f32.wast", "f32_bitwise.wast", "f32_cmp.wast", "f64.wast", "f64_bitwise.wast", "f64_cmp.wast", "fac.wast", "float_exprs.wast", "float_literals.wast", "float_memory.wast", "float_misc.wast", "forward.wast", "func.wast", "func_ptrs.wast", "global.wast", "i32.wast", "i64.wast", "if.wast", "imports.wast", "inline-module.wast", "int_exprs.wast", "int_literals.wast", "labels.wast", "left-to-right.wast", "linking.wast", "load.wast", "local_get.wast", "local_set.wast", "local_tee.wast", "loop.wast", "memory.wast", "memory_copy.wast", "memory_fill.wast", "memory_grow.wast", "memory_init.wast", "memory_redundancy.wast", "memory_size.wast", "memory_trap.wast", "names.wast", "nop.wast", "obsolete-keywords.wast", "ref_func.wast", "ref_is_null.wast", "ref_null.wast", "return.wast", "select.wast", "skip-stack-guard-page.wast", "stack.wast", "start.wast", "store.wast", "switch.wast", "table-sub.wast", "table.wast", "table_copy.wast", "table_fill.wast", "table_get.wast", "table_grow.wast", "table_init.wast", "table_set.wast", "table_size.wast", "token.wast", "traps.wast", "type.wast", "unreachable.wast", "unreached-invalid.wast", "unreached-valid.wast", "unwind.wast", "utf8-custom-section-id.wast", "utf8-import-field.wast", "utf8-import-module.wast", "utf8-invalid-encoding.wast"]; +pub const V2_TESTS: &[&str] = &["address.wast", "align.wast", "binary-leb128.wast", "binary.wast", "block.wast", "br.wast", "br_if.wast", "br_table.wast", "bulk.wast", "call.wast", "call_indirect.wast", "comments.wast", "const.wast", "conversions.wast", "custom.wast", "data.wast", "elem.wast", "endianness.wast", "exports.wast", "f32.wast", "f32_bitwise.wast", "f32_cmp.wast", "f64.wast", "f64_bitwise.wast", "f64_cmp.wast", "fac.wast", "float_exprs.wast", "float_literals.wast", "float_memory.wast", "float_misc.wast", "forward.wast", "func.wast", "func_ptrs.wast", "global.wast", "i32.wast", "i64.wast", "if.wast", "imports.wast", "inline-module.wast", "int_exprs.wast", "int_literals.wast", "labels.wast", "left-to-right.wast", "linking.wast", "load.wast", "local_get.wast", "local_set.wast", "local_tee.wast", "loop.wast", "memory.wast", "memory_copy.wast", "memory_fill.wast", "memory_grow.wast", "memory_init.wast", "memory_redundancy.wast", "memory_size.wast", "memory_trap.wast", "names.wast", "nop.wast", "obsolete-keywords.wast", "ref_func.wast", "ref_is_null.wast", "ref_null.wast", "return.wast", "select.wast", "skip-stack-guard-page.wast", "stack.wast", "start.wast", "store.wast", "switch.wast", "table-sub.wast", "table.wast", "table_copy.wast", "table_fill.wast", "table_get.wast", "table_grow.wast", "table_init.wast", "table_set.wast", "table_size.wast", "token.wast", "traps.wast", "type.wast", "unreachable.wast", "unreached-invalid.wast", "unreached-valid.wast", "unwind.wast", "utf8-custom-section-id.wast", "utf8-import-field.wast", "utf8-import-module.wast", "utf8-invalid-encoding.wast"]; /// List of all tests that apply to the simd proposal #[rustfmt::skip] -- cgit v1.3.1