diff options
| -rw-r--r-- | Cargo.lock | 11 | ||||
| -rw-r--r-- | crates/cli/src/bin.rs | 2 | ||||
| -rw-r--r-- | crates/parser/src/lib.rs | 2 | ||||
| -rw-r--r-- | crates/tinywasm/Cargo.toml | 4 | ||||
| -rw-r--r-- | crates/tinywasm/src/func.rs | 3 | ||||
| -rw-r--r-- | crates/tinywasm/src/interpreter/executor.rs | 249 | ||||
| -rw-r--r-- | crates/tinywasm/src/interpreter/stack/call_stack.rs | 12 | ||||
| -rw-r--r-- | crates/tinywasm/src/interpreter/stack/mod.rs | 2 | ||||
| -rw-r--r-- | crates/tinywasm/src/interpreter/stack/value_stack.rs | 26 | ||||
| -rw-r--r-- | crates/tinywasm/src/interpreter/values.rs | 8 |
10 files changed, 96 insertions, 223 deletions
@@ -21,12 +21,6 @@ dependencies = [ ] [[package]] -name = "allocator-api2" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c880a97d28a3681c0267bd29cff89621202715b065127cd445fa0f0fe0aa2880" - -[[package]] name = "anes" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -374,9 +368,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "leb128fmt" @@ -652,7 +646,6 @@ dependencies = [ name = "tinywasm" version = "0.9.0-alpha.0" dependencies = [ - "allocator-api2", "criterion", "eyre", "indexmap", diff --git a/crates/cli/src/bin.rs b/crates/cli/src/bin.rs index d00848e..235498c 100644 --- a/crates/cli/src/bin.rs +++ b/crates/cli/src/bin.rs @@ -84,7 +84,7 @@ fn main() -> Result<()> { TinyWasmSubcommand::Run(Run { wasm_file, engine, args, func }) => { debug!("args: {args:?}"); - let path = cwd.join(wasm_file.clone()); + let path = cwd.join(&wasm_file); let module = match wasm_file.ends_with(".wat") { #[cfg(feature = "wat")] true => { diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index b65c47b..73bded0 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -116,7 +116,7 @@ impl Parser { /// Parse a [`TinyWasmModule`] from a file. Requires `std` feature. pub fn parse_module_file(&self, path: impl AsRef<crate::std::path::Path> + Clone) -> Result<TinyWasmModule> { use alloc::format; - let f = crate::std::fs::File::open(path.clone()) + let f = crate::std::fs::File::open(&path) .map_err(|e| ParseError::Other(format!("Error opening file {:?}: {}", path.as_ref(), e)))?; let mut reader = crate::std::io::BufReader::new(f); diff --git a/crates/tinywasm/Cargo.toml b/crates/tinywasm/Cargo.toml index 1ff4032..d1a0839 100644 --- a/crates/tinywasm/Cargo.toml +++ b/crates/tinywasm/Cargo.toml @@ -20,7 +20,6 @@ log={workspace=true, optional=true} 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} -allocator-api2={version="0.4", optional=true} [dev-dependencies] wasm-testsuite.workspace=true @@ -49,9 +48,6 @@ archive=["tinywasm-types/archive"] # canonicalize all NaN values to a single representation canonicalize_nans=[] -# support for the allocator-api2 crate -allocator-api2=["dep:allocator-api2"] - [[test]] name="test-wasm-1" harness=false diff --git a/crates/tinywasm/src/func.rs b/crates/tinywasm/src/func.rs index 87713bb..5d5b56b 100644 --- a/crates/tinywasm/src/func.rs +++ b/crates/tinywasm/src/func.rs @@ -70,7 +70,8 @@ impl FuncHandle { debug_assert!(store.stack.values.len() >= func_ty.results.len()); // 2. Pop m values from the stack - let res = store.stack.values.pop_results(&func_ty.results); + let mut res: Vec<_> = store.stack.values.pop_types(func_ty.results.iter().rev()).collect(); // pop in reverse order since the stack is LIFO + res.reverse(); // reverse to get the original order // The values are returned as the results of the invocation. Ok(res) diff --git a/crates/tinywasm/src/interpreter/executor.rs b/crates/tinywasm/src/interpreter/executor.rs index fd24896..dbeceb9 100644 --- a/crates/tinywasm/src/interpreter/executor.rs +++ b/crates/tinywasm/src/interpreter/executor.rs @@ -2,6 +2,7 @@ #[allow(unused_imports)] use super::no_std_floats::NoStdFloatExt; +use alloc::boxed::Box; use alloc::{format, rc::Rc, string::ToString}; use core::ops::ControlFlow; @@ -75,24 +76,19 @@ impl<'store> Executor<'store> { #[rustfmt::skip] match self.cf.fetch_instr() { Nop | BrLabel(_) | I32ReinterpretF32 | I64ReinterpretF64 | F32ReinterpretI32 | F64ReinterpretI64 => {} - Unreachable => self.exec_unreachable()?, - + Unreachable => return ControlFlow::Break(Some(Trap::Unreachable.into())), Drop32 => self.store.stack.values.drop::<Value32>(), Drop64 => self.store.stack.values.drop::<Value64>(), Drop128 => self.store.stack.values.drop::<Value128>(), DropRef => self.store.stack.values.drop::<ValueRef>(), - Select32 => self.store.stack.values.select::<Value32>(), Select64 => self.store.stack.values.select::<Value64>(), Select128 => self.store.stack.values.select::<Value128>(), SelectRef => self.store.stack.values.select::<ValueRef>(), - Call(v) => return self.exec_call_direct::<false>(*v), CallIndirect(ty, table) => return self.exec_call_indirect::<false>(*ty, *table), - ReturnCall(v) => return self.exec_call_direct::<true>(*v), ReturnCallIndirect(ty, table) => return self.exec_call_indirect::<true>(*ty, *table), - If(end, el) => self.exec_if(*end, *el, (StackHeight::default(), StackHeight::default())), IfWithType(ty, end, el) => self.exec_if(*end, *el, (StackHeight::default(), (*ty).into())), IfWithFuncType(ty, end, el) => self.exec_if(*end, *el, self.resolve_functype(*ty)), @@ -108,141 +104,79 @@ impl<'store> Executor<'store> { BrTable(default, len) => return self.exec_brtable(*default, *len), Return => return self.exec_return(), EndBlockFrame => self.exec_end_block(), - LocalGet32(local_index) => self.exec_local_get::<Value32>(*local_index), LocalGet64(local_index) => self.exec_local_get::<Value64>(*local_index), LocalGet128(local_index) => self.exec_local_get::<Value128>(*local_index), LocalGetRef(local_index) => self.exec_local_get::<ValueRef>(*local_index), - LocalSet32(local_index) => self.exec_local_set::<Value32>(*local_index), LocalSet64(local_index) => self.exec_local_set::<Value64>(*local_index), LocalSet128(local_index) => self.exec_local_set::<Value128>(*local_index), LocalSetRef(local_index) => self.exec_local_set::<ValueRef>(*local_index), - + LocalCopy32(from, to) => self.exec_local_copy::<Value32>(*from, *to), + LocalCopy64(from, to) => self.exec_local_copy::<Value64>(*from, *to), + LocalCopy128(from, to) => self.exec_local_copy::<Value128>(*from, *to), + LocalCopyRef(from, to) => self.exec_local_copy::<ValueRef>(*from, *to), LocalTee32(local_index) => self.exec_local_tee::<Value32>(*local_index), LocalTee64(local_index) => self.exec_local_tee::<Value64>(*local_index), LocalTee128(local_index) => self.exec_local_tee::<Value128>(*local_index), LocalTeeRef(local_index) => self.exec_local_tee::<ValueRef>(*local_index), - GlobalGet(global_index) => self.exec_global_get(*global_index), GlobalSet32(global_index) => self.exec_global_set::<Value32>(*global_index), GlobalSet64(global_index) => self.exec_global_set::<Value64>(*global_index), GlobalSet128(global_index) => self.exec_global_set::<Value128>(*global_index), GlobalSetRef(global_index) => self.exec_global_set::<ValueRef>(*global_index), - I32Const(val) => self.exec_const(*val), I64Const(val) => self.exec_const(*val), F32Const(val) => self.exec_const(*val), F64Const(val) => self.exec_const(*val), - - // Reference types - RefFunc(func_idx) => self.exec_const::<ValueRef>(Some(*func_idx)), - RefNull(_) => self.exec_const::<ValueRef>(None), - RefIsNull => self.exec_ref_is_null(), - - MemorySize(addr) => self.exec_memory_size(*addr), - MemoryGrow(addr) => self.exec_memory_grow(*addr), - - // Bulk memory operations - MemoryCopy(from, to) => self.exec_memory_copy(*from, *to).to_cf()?, - MemoryFill(addr) => self.exec_memory_fill(*addr).to_cf()?, - MemoryInit(data_idx, mem_idx) => self.exec_memory_init(*data_idx, *mem_idx).to_cf()?, - DataDrop(data_index) => self.exec_data_drop(*data_index), - ElemDrop(elem_index) => self.exec_elem_drop(*elem_index), - - // Table instructions - TableGet(table_idx) => self.exec_table_get(*table_idx).to_cf()?, - TableSet(table_idx) => self.exec_table_set(*table_idx).to_cf()?, - TableSize(table_idx) => self.exec_table_size(*table_idx).to_cf()?, - TableInit(elem_idx, table_idx) => self.exec_table_init(*elem_idx, *table_idx).to_cf()?, - TableGrow(table_idx) => self.exec_table_grow(*table_idx).to_cf()?, - TableFill(table_idx) => self.exec_table_fill(*table_idx).to_cf()?, - TableCopy { from, to } => self.exec_table_copy(*from, *to).to_cf()?, - - // Core memory load/store operations - 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(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(), i32::from)?, - I32Load8U(m) => self.exec_mem_load::<u8, 1, _>(m.mem_addr(), m.offset(), i32::from)?, - I32Load16S(m) => self.exec_mem_load::<i16, 2, _>(m.mem_addr(), m.offset(), i32::from)?, - I32Load16U(m) => self.exec_mem_load::<u16, 2, _>(m.mem_addr(), m.offset(), i32::from)?, - I64Load8S(m) => self.exec_mem_load::<i8, 1, _>(m.mem_addr(), m.offset(), i64::from)?, - I64Load8U(m) => self.exec_mem_load::<u8, 1, _>(m.mem_addr(), m.offset(), i64::from)?, - I64Load16S(m) => self.exec_mem_load::<i16, 2, _>(m.mem_addr(), m.offset(), i64::from)?, - I64Load16U(m) => self.exec_mem_load::<u16, 2, _>(m.mem_addr(), m.offset(), i64::from)?, - I64Load32S(m) => self.exec_mem_load::<i32, 4, _>(m.mem_addr(), m.offset(), i64::from)?, - I64Load32U(m) => self.exec_mem_load::<u32, 4, _>(m.mem_addr(), m.offset(), i64::from)?, - I64Eqz => stack_op!(unary i64 => i32, |v| i32::from(v == 0)), I32Eqz => stack_op!(unary i32, |v| i32::from(v == 0)), I32Eq => stack_op!(binary i32, |a, b| i32::from(a == b)), I64Eq => stack_op!(binary i64 => i32, |a, b| i32::from(a == b)), F32Eq => stack_op!(binary f32 => i32, |a, b| i32::from(a == b)), F64Eq => stack_op!(binary f64 => i32, |a, b| i32::from(a == b)), - I32Ne => stack_op!(binary i32, |a, b| i32::from(a != b)), I64Ne => stack_op!(binary i64 => i32, |a, b| i32::from(a != b)), F32Ne => stack_op!(binary f32 => i32, |a, b| i32::from(a != b)), F64Ne => stack_op!(binary f64 => i32, |a, b| i32::from(a != b)), - I32LtS => stack_op!(binary i32, |a, b| i32::from(a < b)), I64LtS => stack_op!(binary i64 => i32, |a, b| i32::from(a < b)), I32LtU => stack_op!(binary u32 => i32, |a, b| i32::from(a < b)), I64LtU => stack_op!(binary u64 => i32, |a, b| i32::from(a < b)), F32Lt => stack_op!(binary f32 => i32, |a, b| i32::from(a < b)), F64Lt => stack_op!(binary f64 => i32, |a, b| i32::from(a < b)), - I32LeS => stack_op!(binary i32, |a, b| i32::from(a <= b)), I64LeS => stack_op!(binary i64 => i32, |a, b| i32::from(a <= b)), I32LeU => stack_op!(binary u32 => i32, |a, b| i32::from(a <= b)), I64LeU => stack_op!(binary u64 => i32, |a, b| i32::from(a <= b)), F32Le => stack_op!(binary f32 => i32, |a, b| i32::from(a <= b)), F64Le => stack_op!(binary f64 => i32, |a, b| i32::from(a <= b)), - I32GeS => stack_op!(binary i32, |a, b| i32::from(a >= b)), I64GeS => stack_op!(binary i64 => i32, |a, b| i32::from(a >= b)), I32GeU => stack_op!(binary u32 => i32, |a, b| i32::from(a >= b)), I64GeU => stack_op!(binary u64 => i32, |a, b| i32::from(a >= b)), F32Ge => stack_op!(binary f32 => i32, |a, b| i32::from(a >= b)), F64Ge => stack_op!(binary f64 => i32, |a, b| i32::from(a >= b)), - I32GtS => stack_op!(binary i32, |a, b| i32::from(a > b)), I64GtS => stack_op!(binary i64 => i32, |a, b| i32::from(a > b)), I32GtU => stack_op!(binary u32 => i32, |a, b| i32::from(a > b)), I64GtU => stack_op!(binary u64 => i32, |a, b| i32::from(a > b)), F32Gt => stack_op!(binary f32 => i32, |a, b| i32::from(a > b)), F64Gt => stack_op!(binary f64 => i32, |a, b| i32::from(a > b)), - I32Add => stack_op!(binary i32, |a, b| a.wrapping_add(b)), I64Add => stack_op!(binary i64, |a, b| a.wrapping_add(b)), F32Add => stack_op!(binary f32, |a, b| a + b), F64Add => stack_op!(binary f64, |a, b| a + b), - I32Sub => stack_op!(binary i32, |a, b| a.wrapping_sub(b)), I64Sub => stack_op!(binary i64, |a, b| a.wrapping_sub(b)), F32Sub => stack_op!(binary f32, |a, b| a - b), F64Sub => stack_op!(binary f64, |a, b| a - b), - F32Div => stack_op!(binary f32, |a, b| a / b), F64Div => stack_op!(binary f64, |a, b| a / b), - I32Mul => stack_op!(binary i32, |a, b| a.wrapping_mul(b)), I64Mul => stack_op!(binary i64, |a, b| a.wrapping_mul(b)), F32Mul => stack_op!(binary f32, |a, b| a * b), F64Mul => stack_op!(binary f64, |a, b| a * b), - I32DivS => stack_op!(binary_try i32, |a, b| a.wasm_checked_div(b)), I64DivS => stack_op!(binary_try i64, |a, b| a.wasm_checked_div(b)), I32DivU => stack_op!(binary_try u32, |a, b| a.checked_div(b).ok_or_else(trap_0)), @@ -251,7 +185,6 @@ impl<'store> Executor<'store> { I64RemS => stack_op!(binary_try i64, |a, b| a.checked_wrapping_rem(b)), I32RemU => stack_op!(binary_try u32, |a, b| a.checked_wrapping_rem(b)), I64RemU => stack_op!(binary_try u64, |a, b| a.checked_wrapping_rem(b)), - I32And => stack_op!(binary i32, |a, b| a & b), I64And => stack_op!(binary i64, |a, b| a & b), I32Or => stack_op!(binary i32, |a, b| a | b), @@ -268,7 +201,6 @@ impl<'store> Executor<'store> { I64Rotl => stack_op!(binary i64, |a, b| a.wasm_rotl(b)), I32Rotr => stack_op!(binary i32, |a, b| a.wasm_rotr(b)), I64Rotr => stack_op!(binary i64, |a, b| a.wasm_rotr(b)), - I32Clz => stack_op!(unary i32, |v| v.leading_zeros() as i32), I64Clz => stack_op!(unary i64, |v| i64::from(v.leading_zeros())), I32Ctz => stack_op!(unary i32, |v| v.trailing_zeros() as i32), @@ -276,6 +208,54 @@ impl<'store> Executor<'store> { I32Popcnt => stack_op!(unary i32, |v| v.count_ones() as i32), I64Popcnt => stack_op!(unary i64, |v| i64::from(v.count_ones())), + // Reference types + RefFunc(func_idx) => self.exec_const::<ValueRef>(Some(*func_idx)), + RefNull(_) => self.exec_const::<ValueRef>(None), + RefIsNull => self.exec_ref_is_null(), + MemorySize(addr) => self.exec_memory_size(*addr), + MemoryGrow(addr) => self.exec_memory_grow(*addr), + + // Bulk memory operations + MemoryCopy(from, to) => self.exec_memory_copy(*from, *to).to_cf()?, + MemoryFill(addr) => self.exec_memory_fill(*addr).to_cf()?, + MemoryInit(data_idx, mem_idx) => self.exec_memory_init(*data_idx, *mem_idx).to_cf()?, + DataDrop(data_index) => self.store.state.get_data_mut(self.module.resolve_data_addr(*data_index)).drop(), + ElemDrop(elem_index) => self.store.state.get_elem_mut(self.module.resolve_elem_addr(*elem_index)).drop(), + + // Table instructions + TableGet(table_idx) => self.exec_table_get(*table_idx).to_cf()?, + TableSet(table_idx) => self.exec_table_set(*table_idx).to_cf()?, + TableSize(table_idx) => self.exec_table_size(*table_idx).to_cf()?, + TableInit(elem_idx, table_idx) => self.exec_table_init(*elem_idx, *table_idx).to_cf()?, + TableGrow(table_idx) => self.exec_table_grow(*table_idx).to_cf()?, + TableFill(table_idx) => self.exec_table_fill(*table_idx).to_cf()?, + TableCopy { from, to } => self.exec_table_copy(*from, *to).to_cf()?, + + // Core memory load/store operations + 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(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(), i32::from)?, + I32Load8U(m) => self.exec_mem_load::<u8, 1, _>(m.mem_addr(), m.offset(), i32::from)?, + I32Load16S(m) => self.exec_mem_load::<i16, 2, _>(m.mem_addr(), m.offset(), i32::from)?, + I32Load16U(m) => self.exec_mem_load::<u16, 2, _>(m.mem_addr(), m.offset(), i32::from)?, + I64Load8S(m) => self.exec_mem_load::<i8, 1, _>(m.mem_addr(), m.offset(), i64::from)?, + I64Load8U(m) => self.exec_mem_load::<u8, 1, _>(m.mem_addr(), m.offset(), i64::from)?, + I64Load16S(m) => self.exec_mem_load::<i16, 2, _>(m.mem_addr(), m.offset(), i64::from)?, + I64Load16U(m) => self.exec_mem_load::<u16, 2, _>(m.mem_addr(), m.offset(), i64::from)?, + I64Load32S(m) => self.exec_mem_load::<i32, 4, _>(m.mem_addr(), m.offset(), i64::from)?, + I64Load32U(m) => self.exec_mem_load::<u32, 4, _>(m.mem_addr(), m.offset(), i64::from)?, + // Numeric conversion operations F32ConvertI32S => stack_op!(unary i32 => f32, |v| v as f32), F32ConvertI64S => stack_op!(unary i64 => f32, |v| v as f32), @@ -295,10 +275,8 @@ impl<'store> Executor<'store> { I64ExtendI32U => stack_op!(unary u32 => i64, |v| i64::from(v)), I64ExtendI32S => stack_op!(unary i32 => i64, |v| i64::from(v)), I32WrapI64 => stack_op!(unary i64 => i32, |v| v as i32), - F32DemoteF64 => stack_op!(unary f64 => f32, |v| v as f32), F64PromoteF32 => stack_op!(unary f32 => f64, |v| f64::from(v)), - F32Abs => stack_op!(unary f32, |v| v.abs()), F64Abs => stack_op!(unary f64, |v| v.abs()), F32Neg => stack_op!(unary f32, |v| -v), @@ -319,7 +297,6 @@ impl<'store> Executor<'store> { F64Max => stack_op!(binary f64, |a, b| a.tw_maximum(b)), F32Copysign => stack_op!(binary f32, |a, b| a.copysign(b)), F64Copysign => stack_op!(binary f64, |a, b| a.copysign(b)), - I32TruncF32S => checked_conv_float!(f32, i32, self), I32TruncF64S => checked_conv_float!(f64, i32, self), I32TruncF32U => checked_conv_float!(f32, u32, i32, self), @@ -339,11 +316,6 @@ impl<'store> Executor<'store> { I64TruncSatF64S => stack_op!(unary f64 => i64, |v| v.trunc() as i64), I64TruncSatF64U => stack_op!(unary f64 => u64, |v| v.trunc() as u64), - LocalCopy32(from, to) => self.exec_local_copy::<Value32>(*from, *to), - LocalCopy64(from, to) => self.exec_local_copy::<Value64>(*from, *to), - LocalCopy128(from, to) => self.exec_local_copy::<Value128>(*from, *to), - LocalCopyRef(from, to) => self.exec_local_copy::<ValueRef>(*from, *to), - // SIMD extension V128Not => stack_op!(unary Value128, |v| v.v128_not()), V128And => stack_op!(binary Value128, |a, b| a.v128_and(b)), @@ -353,7 +325,6 @@ impl<'store> Executor<'store> { V128Bitselect => self.store.stack.values.ternary_same::<Value128>(|v1, v2, c| Ok(Value128::v128_bitselect(v1, v2, c))).to_cf()?, V128AnyTrue => stack_op!(unary Value128 => i32, |v| v.v128_any_true() as i32), I8x16Swizzle => stack_op!(binary Value128, |a, s| a.i8x16_swizzle(s)), - V128Load(arg) => self.exec_mem_load::<Value128, 16, _>(arg.mem_addr(), arg.offset(), |v| v)?, V128Load8x8S(arg) => self.exec_mem_load::<u64, 8, Value128>(arg.mem_addr(), arg.offset(), |v| Value128::v128_load8x8_s(v.to_le_bytes()))?, V128Load8x8U(arg) => self.exec_mem_load::<u64, 8, Value128>(arg.mem_addr(), arg.offset(), |v| Value128::v128_load8x8_u(v.to_le_bytes()))?, @@ -365,20 +336,14 @@ impl<'store> Executor<'store> { V128Load16Splat(_arg) => self.exec_mem_load::<i16, 2, Value128>(_arg.mem_addr(), _arg.offset(), Value128::splat_i16)?, V128Load32Splat(_arg) => self.exec_mem_load::<i32, 4, Value128>(_arg.mem_addr(), _arg.offset(), Value128::splat_i32)?, V128Load64Splat(_arg) => self.exec_mem_load::<i64, 8, Value128>(_arg.mem_addr(), _arg.offset(), Value128::splat_i64)?, - V128Store(arg) => self.exec_mem_store::<Value128, Value128, 16>(arg.mem_addr(), arg.offset(), |v| v)?, - V128Store8Lane(arg, lane) => self.exec_mem_store_lane::<i8, 1>(arg.mem_addr(), arg.offset(), *lane)?, V128Store16Lane(arg, lane) => self.exec_mem_store_lane::<i16, 2>(arg.mem_addr(), arg.offset(), *lane)?, V128Store32Lane(arg, lane) => self.exec_mem_store_lane::<i32, 4>(arg.mem_addr(), arg.offset(), *lane)?, V128Store64Lane(arg, lane) => self.exec_mem_store_lane::<i64, 8>(arg.mem_addr(), arg.offset(), *lane)?, - - // Load a single 32-bit or 64-bit element into the lowest bits of a v128 vector, and initialize all other bits of the v128 vector to zero. V128Load32Zero(arg) => self.exec_mem_load::<i32, 4, Value128>(arg.mem_addr(), arg.offset(), |v| Value128::from_i32x4([v, 0, 0, 0]))?, V128Load64Zero(arg) => self.exec_mem_load::<i64, 8, Value128>(arg.mem_addr(), arg.offset(), |v| Value128::from_i64x2([v, 0]))?, - V128Const(arg) => self.exec_const::<Value128>(self.cf.data().v128_constants[*arg as usize].into()), - I8x16ExtractLaneS(lane) => stack_op!(unary Value128 => i32, |v| v.extract_lane_i8(*lane) as i32), I8x16ExtractLaneU(lane) => stack_op!(unary Value128 => i32, |v| v.extract_lane_u8(*lane) as i32), I16x8ExtractLaneS(lane) => stack_op!(unary Value128 => i32, |v| v.extract_lane_i16(*lane) as i32), @@ -387,40 +352,34 @@ impl<'store> Executor<'store> { I64x2ExtractLane(lane) => stack_op!(unary Value128 => i64, |v| v.extract_lane_i64(*lane)), F32x4ExtractLane(lane) => stack_op!(unary Value128 => f32, |v| v.extract_lane_f32(*lane)), F64x2ExtractLane(lane) => stack_op!(unary Value128 => f64, |v| v.extract_lane_f64(*lane)), - V128Load8Lane(arg, lane) => self.exec_mem_load_lane::<i8, 1>(arg.mem_addr(), arg.offset(), *lane)?, V128Load16Lane(arg, lane) => self.exec_mem_load_lane::<i16, 2>(arg.mem_addr(), arg.offset(), *lane)?, V128Load32Lane(arg, lane) => self.exec_mem_load_lane::<i32, 4>(arg.mem_addr(), arg.offset(), *lane)?, V128Load64Lane(arg, lane) => self.exec_mem_load_lane::<i64, 8>(arg.mem_addr(), arg.offset(), *lane)?, - I8x16ReplaceLane(lane) => stack_op!(binary i32, Value128, |value, vec| vec.i8x16_replace_lane(*lane, value as i8)), I16x8ReplaceLane(lane) => stack_op!(binary i32, Value128, |value, vec| vec.i16x8_replace_lane(*lane, value as i16)), I32x4ReplaceLane(lane) => stack_op!(binary i32, Value128, |value, vec| vec.i32x4_replace_lane(*lane, value)), I64x2ReplaceLane(lane) => stack_op!(binary i64, Value128, |value, vec| vec.i64x2_replace_lane(*lane, value)), F32x4ReplaceLane(lane) => stack_op!(binary f32, Value128, |value, vec| vec.f32x4_replace_lane(*lane, value)), F64x2ReplaceLane(lane) => stack_op!(binary f64, Value128, |value, vec| vec.f64x2_replace_lane(*lane, value)), - I8x16Splat => stack_op!(unary i32 => Value128, |v| Value128::splat_i8(v as i8)), I16x8Splat => stack_op!(unary i32 => Value128, |v| Value128::splat_i16(v as i16)), I32x4Splat => stack_op!(unary i32 => Value128, |v| Value128::splat_i32(v)), I64x2Splat => stack_op!(unary i64 => Value128, |v| Value128::splat_i64(v)), F32x4Splat => stack_op!(unary f32 => Value128, |v| Value128::splat_f32(v)), F64x2Splat => stack_op!(unary f64 => Value128, |v| Value128::splat_f64(v)), - I8x16Eq => stack_op!(binary Value128, |a, b| a.i8x16_eq(b)), I16x8Eq => stack_op!(binary Value128, |a, b| a.i16x8_eq(b)), I32x4Eq => stack_op!(binary Value128, |a, b| a.i32x4_eq(b)), I64x2Eq => stack_op!(binary Value128, |a, b| a.i64x2_eq(b)), F32x4Eq => stack_op!(binary Value128, |a, b| a.f32x4_eq(b)), F64x2Eq => stack_op!(binary Value128, |a, b| a.f64x2_eq(b)), - I8x16Ne => stack_op!(binary Value128, |a, b| a.i8x16_ne(b)), I16x8Ne => stack_op!(binary Value128, |a, b| a.i16x8_ne(b)), I32x4Ne => stack_op!(binary Value128, |a, b| a.i32x4_ne(b)), I64x2Ne => stack_op!(binary Value128, |a, b| a.i64x2_ne(b)), F32x4Ne => stack_op!(binary Value128, |a, b| a.f32x4_ne(b)), F64x2Ne => stack_op!(binary Value128, |a, b| a.f64x2_ne(b)), - I8x16LtS => stack_op!(binary Value128, |a, b| a.i8x16_lt_s(b)), I16x8LtS => stack_op!(binary Value128, |a, b| a.i16x8_lt_s(b)), I32x4LtS => stack_op!(binary Value128, |a, b| a.i32x4_lt_s(b)), @@ -430,10 +389,8 @@ impl<'store> Executor<'store> { I32x4LtU => stack_op!(binary Value128, |a, b| a.i32x4_lt_u(b)), F32x4Lt => stack_op!(binary Value128, |a, b| a.f32x4_lt(b)), F64x2Lt => stack_op!(binary Value128, |a, b| a.f64x2_lt(b)), - F32x4Gt => stack_op!(binary Value128, |a, b| a.f32x4_gt(b)), F64x2Gt => stack_op!(binary Value128, |a, b| a.f64x2_gt(b)), - I8x16GtS => stack_op!(binary Value128, |a, b| a.i8x16_gt_s(b)), I16x8GtS => stack_op!(binary Value128, |a, b| a.i16x8_gt_s(b)), I32x4GtS => stack_op!(binary Value128, |a, b| a.i32x4_gt_s(b)), @@ -441,100 +398,79 @@ impl<'store> Executor<'store> { I64x2LeS => stack_op!(binary Value128, |a, b| a.i64x2_le_s(b)), F32x4Le => stack_op!(binary Value128, |a, b| a.f32x4_le(b)), F64x2Le => stack_op!(binary Value128, |a, b| a.f64x2_le(b)), - I8x16GtU => stack_op!(binary Value128, |a, b| a.i8x16_gt_u(b)), I16x8GtU => stack_op!(binary Value128, |a, b| a.i16x8_gt_u(b)), I32x4GtU => stack_op!(binary Value128, |a, b| a.i32x4_gt_u(b)), F32x4Ge => stack_op!(binary Value128, |a, b| a.f32x4_ge(b)), F64x2Ge => stack_op!(binary Value128, |a, b| a.f64x2_ge(b)), - I8x16LeS => stack_op!(binary Value128, |a, b| a.i8x16_le_s(b)), I16x8LeS => stack_op!(binary Value128, |a, b| a.i16x8_le_s(b)), I32x4LeS => stack_op!(binary Value128, |a, b| a.i32x4_le_s(b)), - I8x16LeU => stack_op!(binary Value128, |a, b| a.i8x16_le_u(b)), I16x8LeU => stack_op!(binary Value128, |a, b| a.i16x8_le_u(b)), I32x4LeU => stack_op!(binary Value128, |a, b| a.i32x4_le_u(b)), - I8x16GeS => stack_op!(binary Value128, |a, b| a.i8x16_ge_s(b)), I16x8GeS => stack_op!(binary Value128, |a, b| a.i16x8_ge_s(b)), I32x4GeS => stack_op!(binary Value128, |a, b| a.i32x4_ge_s(b)), I64x2GeS => stack_op!(binary Value128, |a, b| a.i64x2_ge_s(b)), - I8x16GeU => stack_op!(binary Value128, |a, b| a.i8x16_ge_u(b)), I16x8GeU => stack_op!(binary Value128, |a, b| a.i16x8_ge_u(b)), I32x4GeU => stack_op!(binary Value128, |a, b| a.i32x4_ge_u(b)), - I8x16Abs => stack_op!(unary Value128, |a| a.i8x16_abs()), I16x8Abs => stack_op!(unary Value128, |a| a.i16x8_abs()), I32x4Abs => stack_op!(unary Value128, |a| a.i32x4_abs()), I64x2Abs => stack_op!(unary Value128, |a| a.i64x2_abs()), - I8x16Neg => stack_op!(unary Value128, |a| a.i8x16_neg()), I16x8Neg => stack_op!(unary Value128, |a| a.i16x8_neg()), I32x4Neg => stack_op!(unary Value128, |a| a.i32x4_neg()), I64x2Neg => stack_op!(unary Value128, |a| a.i64x2_neg()), - I8x16AllTrue => stack_op!(unary Value128 => i32, |v| v.i8x16_all_true() as i32), I16x8AllTrue => stack_op!(unary Value128 => i32, |v| v.i16x8_all_true() as i32), I32x4AllTrue => stack_op!(unary Value128 => i32, |v| v.i32x4_all_true() as i32), I64x2AllTrue => stack_op!(unary Value128 => i32, |v| v.i64x2_all_true() as i32), - I8x16Bitmask => stack_op!(unary Value128 => i32, |v| v.i8x16_bitmask() as i32), I16x8Bitmask => stack_op!(unary Value128 => i32, |v| v.i16x8_bitmask() as i32), I32x4Bitmask => stack_op!(unary Value128 => i32, |v| v.i32x4_bitmask() as i32), I64x2Bitmask => stack_op!(unary Value128 => i32, |v| v.i64x2_bitmask() as i32), - I8x16Shl => stack_op!(binary i32, Value128, |a, b| b.i8x16_shl(a as u32)), I16x8Shl => stack_op!(binary i32, Value128, |a, b| b.i16x8_shl(a as u32)), I32x4Shl => stack_op!(binary i32, Value128, |a, b| b.i32x4_shl(a as u32)), I64x2Shl => stack_op!(binary i32, Value128, |a, b| b.i64x2_shl(a as u32)), - I8x16ShrS => stack_op!(binary i32, Value128, |a, b| b.i8x16_shr_s(a as u32)), I16x8ShrS => stack_op!(binary i32, Value128, |a, b| b.i16x8_shr_s(a as u32)), I32x4ShrS => stack_op!(binary i32, Value128, |a, b| b.i32x4_shr_s(a as u32)), I64x2ShrS => stack_op!(binary i32, Value128, |a, b| b.i64x2_shr_s(a as u32)), - I8x16ShrU => stack_op!(binary i32, Value128, |a, b| b.i8x16_shr_u(a as u32)), I16x8ShrU => stack_op!(binary i32, Value128, |a, b| b.i16x8_shr_u(a as u32)), I32x4ShrU => stack_op!(binary i32, Value128, |a, b| b.i32x4_shr_u(a as u32)), I64x2ShrU => stack_op!(binary i32, Value128, |a, b| b.i64x2_shr_u(a as u32)), - I8x16Add => stack_op!(binary Value128, |a, b| a.i8x16_add(b)), I16x8Add => stack_op!(binary Value128, |a, b| a.i16x8_add(b)), I32x4Add => stack_op!(binary Value128, |a, b| a.i32x4_add(b)), I64x2Add => stack_op!(binary Value128, |a, b| a.i64x2_add(b)), - I8x16Sub => stack_op!(binary Value128, |a, b| a.i8x16_sub(b)), I16x8Sub => stack_op!(binary Value128, |a, b| a.i16x8_sub(b)), I32x4Sub => stack_op!(binary Value128, |a, b| a.i32x4_sub(b)), I64x2Sub => stack_op!(binary Value128, |a, b| a.i64x2_sub(b)), - I8x16MinS => stack_op!(binary Value128, |a, b| a.i8x16_min_s(b)), I16x8MinS => stack_op!(binary Value128, |a, b| a.i16x8_min_s(b)), I32x4MinS => stack_op!(binary Value128, |a, b| a.i32x4_min_s(b)), - I8x16MinU => stack_op!(binary Value128, |a, b| a.i8x16_min_u(b)), I16x8MinU => stack_op!(binary Value128, |a, b| a.i16x8_min_u(b)), I32x4MinU => stack_op!(binary Value128, |a, b| a.i32x4_min_u(b)), - I8x16MaxS => stack_op!(binary Value128, |a, b| a.i8x16_max_s(b)), I16x8MaxS => stack_op!(binary Value128, |a, b| a.i16x8_max_s(b)), I32x4MaxS => stack_op!(binary Value128, |a, b| a.i32x4_max_s(b)), - I8x16MaxU => stack_op!(binary Value128, |a, b| a.i8x16_max_u(b)), I16x8MaxU => stack_op!(binary Value128, |a, b| a.i16x8_max_u(b)), I32x4MaxU => stack_op!(binary Value128, |a, b| a.i32x4_max_u(b)), - I64x2Mul => stack_op!(binary Value128, |a, b| a.i64x2_mul(b)), I16x8Mul => stack_op!(binary Value128, |a, b| a.i16x8_mul(b)), I32x4Mul => stack_op!(binary Value128, |a, b| a.i32x4_mul(b)), - I8x16NarrowI16x8S => stack_op!(binary Value128, |a, b| Value128::i8x16_narrow_i16x8_s(a, b)), I8x16NarrowI16x8U => stack_op!(binary Value128, |a, b| Value128::i8x16_narrow_i16x8_u(a, b)), I16x8NarrowI32x4S => stack_op!(binary Value128, |a, b| Value128::i16x8_narrow_i32x4_s(a, b)), I16x8NarrowI32x4U => stack_op!(binary Value128, |a, b| Value128::i16x8_narrow_i32x4_u(a, b)), - I8x16AddSatS => stack_op!(binary Value128, |a, b| a.i8x16_add_sat_s(b)), I16x8AddSatS => stack_op!(binary Value128, |a, b| a.i16x8_add_sat_s(b)), I8x16AddSatU => stack_op!(binary Value128, |a, b| a.i8x16_add_sat_u(b)), @@ -543,15 +479,12 @@ impl<'store> Executor<'store> { I16x8SubSatS => stack_op!(binary Value128, |a, b| a.i16x8_sub_sat_s(b)), I8x16SubSatU => stack_op!(binary Value128, |a, b| a.i8x16_sub_sat_u(b)), I16x8SubSatU => stack_op!(binary Value128, |a, b| a.i16x8_sub_sat_u(b)), - I8x16AvgrU => stack_op!(binary Value128, |a, b| a.i8x16_avgr_u(b)), I16x8AvgrU => stack_op!(binary Value128, |a, b| a.i16x8_avgr_u(b)), - I16x8ExtAddPairwiseI8x16S => stack_op!(unary Value128, |a| a.i16x8_extadd_pairwise_i8x16_s()), I16x8ExtAddPairwiseI8x16U => stack_op!(unary Value128, |a| a.i16x8_extadd_pairwise_i8x16_u()), I32x4ExtAddPairwiseI16x8S => stack_op!(unary Value128, |a| a.i32x4_extadd_pairwise_i16x8_s()), I32x4ExtAddPairwiseI16x8U => stack_op!(unary Value128, |a| a.i32x4_extadd_pairwise_i16x8_u()), - I16x8ExtMulLowI8x16S => stack_op!(binary Value128, |a, b| a.i16x8_extmul_low_i8x16_s(b)), I16x8ExtMulLowI8x16U => stack_op!(binary Value128, |a, b| a.i16x8_extmul_low_i8x16_u(b)), I16x8ExtMulHighI8x16S => stack_op!(binary Value128, |a, b| a.i16x8_extmul_high_i8x16_s(b)), @@ -564,7 +497,6 @@ impl<'store> Executor<'store> { I64x2ExtMulLowI32x4U => stack_op!(binary Value128, |a, b| a.i64x2_extmul_low_i32x4_u(b)), I64x2ExtMulHighI32x4S => stack_op!(binary Value128, |a, b| a.i64x2_extmul_high_i32x4_s(b)), I64x2ExtMulHighI32x4U => stack_op!(binary Value128, |a, b| a.i64x2_extmul_high_i32x4_u(b)), - I16x8ExtendLowI8x16S => stack_op!(unary Value128, |a| a.i16x8_extend_low_i8x16_s()), I16x8ExtendLowI8x16U => stack_op!(unary Value128, |a| a.i16x8_extend_low_i8x16_u()), I16x8ExtendHighI8x16S => stack_op!(unary Value128, |a| a.i16x8_extend_high_i8x16_s()), @@ -577,14 +509,10 @@ impl<'store> Executor<'store> { I64x2ExtendLowI32x4U => stack_op!(unary Value128, |a| a.i64x2_extend_low_i32x4_u()), I64x2ExtendHighI32x4S => stack_op!(unary Value128, |a| a.i64x2_extend_high_i32x4_s()), I64x2ExtendHighI32x4U => stack_op!(unary Value128, |a| a.i64x2_extend_high_i32x4_u()), - I8x16Popcnt => stack_op!(unary Value128, |v| v.i8x16_popcnt()), I8x16Shuffle(idx) => { let idx = self.cf.data().v128_constants[*idx as usize].to_le_bytes(); stack_op!(binary Value128, |a, b| Value128::i8x16_shuffle(a, b, idx)) } - I16x8Q15MulrSatS => stack_op!(binary Value128, |a, b| a.i16x8_q15mulr_sat_s(b)), - I32x4DotI16x8S => stack_op!(binary Value128, |a, b| a.i32x4_dot_i16x8_s(b)), - F32x4Ceil => stack_op!(simd_unary f32x4_ceil), F64x2Ceil => stack_op!(simd_unary f64x2_ceil), F32x4Floor => stack_op!(simd_unary f32x4_floor), @@ -607,7 +535,6 @@ impl<'store> Executor<'store> { F64x2Mul => stack_op!(simd_binary f64x2_mul), F32x4Div => stack_op!(simd_binary f32x4_div), F64x2Div => stack_op!(simd_binary f64x2_div), - F32x4Min => stack_op!(simd_binary f32x4_min), F64x2Min => stack_op!(simd_binary f64x2_min), F32x4Max => stack_op!(simd_binary f32x4_max), @@ -616,7 +543,6 @@ impl<'store> Executor<'store> { F32x4PMax => stack_op!(simd_binary f32x4_pmax), F64x2PMin => stack_op!(simd_binary f64x2_pmin), F64x2PMax => stack_op!(simd_binary f64x2_pmax), - I32x4TruncSatF32x4S => stack_op!(unary Value128, |v| v.i32x4_trunc_sat_f32x4_s()), I32x4TruncSatF32x4U => stack_op!(unary Value128, |v| v.i32x4_trunc_sat_f32x4_u()), F32x4ConvertI32x4S => stack_op!(unary Value128, |v| v.f32x4_convert_i32x4_s()), @@ -628,28 +554,6 @@ impl<'store> Executor<'store> { I32x4TruncSatF64x2SZero => stack_op!(unary Value128, |v| v.i32x4_trunc_sat_f64x2_s_zero()), I32x4TruncSatF64x2UZero => stack_op!(unary Value128, |v| v.i32x4_trunc_sat_f64x2_u_zero()), - // Relaxed SIMD (not yet implemented) - // I8x16RelaxedSwizzle => unimplemented!(), - // I32x4RelaxedTruncF32x4S => unimplemented!(), - // I32x4RelaxedTruncF32x4U => unimplemented!(), - // I32x4RelaxedTruncF64x2SZero => unimplemented!(), - // I32x4RelaxedTruncF64x2UZero => unimplemented!(), - // F32x4RelaxedMadd => unimplemented!(), - // F32x4RelaxedNmadd => unimplemented!(), - // F64x2RelaxedMadd => unimplemented!(), - // F64x2RelaxedNmadd => unimplemented!(), - // I8x16RelaxedLaneselect => unimplemented!(), - // I16x8RelaxedLaneselect => unimplemented!(), - // I32x4RelaxedLaneselect => unimplemented!(), - // I64x2RelaxedLaneselect => unimplemented!(), - // F32x4RelaxedMin => unimplemented!(), - // F32x4RelaxedMax => unimplemented!(), - // F64x2RelaxedMin => unimplemented!(), - // F64x2RelaxedMax => unimplemented!(), - // I16x8RelaxedQ15mulrS => unimplemented!(), - // I16x8RelaxedDotI8x16I7x16S => unimplemented!(), - // I32x4RelaxedDotI8x16I7x16AddS => unimplemented!(), - #[allow(unreachable_patterns)] i => return ControlFlow::Break(Some(Error::UnsupportedFeature(format!("unimplemented opcode: {i:?}")))), }; @@ -658,11 +562,6 @@ impl<'store> Executor<'store> { ControlFlow::Continue(()) } - #[cold] - fn exec_unreachable(&self) -> ControlFlow<Option<Error>> { - ControlFlow::Break(Some(Trap::Unreachable.into())) - } - fn exec_call<const IS_RETURN_CALL: bool>( &mut self, wasm_func: Rc<WasmFunction>, @@ -681,12 +580,9 @@ impl<'store> Executor<'store> { self.module.swap_with(self.cf.module_addr(), self.store); ControlFlow::Continue(()) } - fn exec_call_host(&mut self, host_func: Rc<imports::HostFunction>) -> ControlFlow<Option<Error>> { - let params = self.store.stack.values.pop_params(&host_func.ty.params); - let res = host_func - .clone() - .call(FuncContext { store: self.store, module_addr: self.module.id() }, ¶ms) - .to_cf()?; + fn exec_call_host(&mut self, host_func: &Rc<imports::HostFunction>) -> ControlFlow<Option<Error>> { + let params = self.store.stack.values.pop_types(&host_func.ty.params).collect::<Box<_>>(); + let res = host_func.call(FuncContext { store: self.store, module_addr: self.module.id() }, ¶ms).to_cf()?; self.store.stack.values.extend_from_wasmvalues(&res); self.cf.incr_instr_ptr(); ControlFlow::Continue(()) @@ -695,7 +591,7 @@ impl<'store> Executor<'store> { let func_inst = self.store.state.get_func(self.module.resolve_func_addr(v)); match func_inst.func.clone() { crate::Function::Wasm(wasm_func) => self.exec_call::<IS_RETURN_CALL>(wasm_func, func_inst.owner), - crate::Function::Host(host_func) => self.exec_call_host(host_func), + crate::Function::Host(host_func) => self.exec_call_host(&host_func), } } fn exec_call_indirect<const IS_RETURN_CALL: bool>( @@ -735,7 +631,7 @@ impl<'store> Executor<'store> { )); } - self.exec_call_host(host_func) + self.exec_call_host(&host_func) } } } @@ -925,19 +821,12 @@ impl<'store> Executor<'store> { let offset: i32 = self.store.stack.values.pop(); let dst: i32 = self.store.stack.values.pop(); - let data = self - .store - .state - .data - .get(self.module.resolve_data_addr(data_index) as usize) - .ok_or_else(|| Error::Other("data not found".to_string()))?; + let data_addr = self.module.resolve_data_addr(data_index) as usize; + let data = self.store.state.data.get(data_addr).ok_or_else(|| Error::Other("data not found".to_string()))?; - let mem = self - .store - .state - .memories - .get_mut(self.module.resolve_mem_addr(mem_index) as usize) - .ok_or_else(|| Error::Other("memory not found".to_string()))?; + let mem_addr = self.module.resolve_mem_addr(mem_index) as usize; + let mem = + self.store.state.memories.get_mut(mem_addr).ok_or_else(|| Error::Other("memory not found".to_string()))?; let data_len = data.data.as_ref().map_or(0, |d| d.len()); @@ -952,12 +841,6 @@ impl<'store> Executor<'store> { let Some(data) = &data.data else { return Err(Trap::MemoryOutOfBounds { offset: 0, len: 0, max: 0 }.into()) }; 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.state.get_data_mut(self.module.resolve_data_addr(data_index)).drop(); - } - fn exec_elem_drop(&mut self, elem_index: u32) { - self.store.state.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.store.stack.values.pop(); let src: i32 = self.store.stack.values.pop(); @@ -990,7 +873,6 @@ impl<'store> Executor<'store> { let val = self.store.stack.values.pop::<i32>() as u64; let mem = self.store.state.get_mem(self.module.resolve_mem_addr(mem_addr)); let Some(Ok(addr)) = offset.checked_add(val).map(TryInto::try_into) else { - cold(); return ControlFlow::Break(Some(Error::Trap(Trap::MemoryOutOfBounds { offset: val as usize, len: LOAD_SIZE, @@ -1020,7 +902,6 @@ impl<'store> Executor<'store> { }; let Some(Ok(addr)) = offset.checked_add(addr).map(|a| a.try_into()) else { - cold(); return ControlFlow::Break(Some(Error::Trap(Trap::MemoryOutOfBounds { offset: addr as usize, len: LOAD_SIZE, @@ -1093,7 +974,7 @@ impl<'store> Executor<'store> { } fn exec_table_size(&mut self, table_index: u32) -> Result<()> { let table = self.store.state.get_table(self.module.resolve_table_addr(table_index)); - self.store.stack.values.push_dyn(table.size().into()); + self.store.stack.values.push(table.size()); Ok(()) } fn exec_table_init(&mut self, elem_index: u32, table_index: u32) -> Result<()> { diff --git a/crates/tinywasm/src/interpreter/stack/call_stack.rs b/crates/tinywasm/src/interpreter/stack/call_stack.rs index 9954beb..ba74d3a 100644 --- a/crates/tinywasm/src/interpreter/stack/call_stack.rs +++ b/crates/tinywasm/src/interpreter/stack/call_stack.rs @@ -176,14 +176,10 @@ impl CallFrame { block_ptr: u32, ) -> Self { let locals = { - let mut locals_32 = Vec::new(); - locals_32.reserve_exact(wasm_func_inst.locals.c32 as usize); - let mut locals_64 = Vec::new(); - locals_64.reserve_exact(wasm_func_inst.locals.c64 as usize); - let mut locals_128 = Vec::new(); - locals_128.reserve_exact(wasm_func_inst.locals.c128 as usize); - let mut locals_ref = Vec::new(); - locals_ref.reserve_exact(wasm_func_inst.locals.cref as usize); + let mut locals_32 = Vec::with_capacity(wasm_func_inst.locals.c32 as usize); + let mut locals_64 = Vec::with_capacity(wasm_func_inst.locals.c64 as usize); + let mut locals_128 = Vec::with_capacity(wasm_func_inst.locals.c128 as usize); + let mut locals_ref = Vec::with_capacity(wasm_func_inst.locals.cref as usize); for p in params { match p.into() { diff --git a/crates/tinywasm/src/interpreter/stack/mod.rs b/crates/tinywasm/src/interpreter/stack/mod.rs index 3da262c..0635bae 100644 --- a/crates/tinywasm/src/interpreter/stack/mod.rs +++ b/crates/tinywasm/src/interpreter/stack/mod.rs @@ -23,8 +23,8 @@ impl Stack { /// Initialize the stack with the given call frame (used for starting execution) pub(crate) fn initialize(&mut self, callframe: CallFrame) { - self.blocks.clear(); self.values.clear(); + self.blocks.clear(); self.call_stack.reset(callframe); } } diff --git a/crates/tinywasm/src/interpreter/stack/value_stack.rs b/crates/tinywasm/src/interpreter/stack/value_stack.rs index 32dd3a8..cec08a3 100644 --- a/crates/tinywasm/src/interpreter/stack/value_stack.rs +++ b/crates/tinywasm/src/interpreter/stack/value_stack.rs @@ -122,14 +122,12 @@ impl ValueStack { T::replace_top(self, func) } - pub(crate) fn pop_params(&mut self, val_types: &[ValType]) -> Vec<WasmValue> { - val_types.iter().map(|val_type| self.pop_wasmvalue(*val_type)).collect::<Vec<_>>() - } - - pub(crate) fn pop_results(&mut self, val_types: &[ValType]) -> Vec<WasmValue> { - let mut results = val_types.iter().rev().map(|val_type| self.pop_wasmvalue(*val_type)).collect::<Vec<_>>(); - results.reverse(); - results + #[inline] + pub(crate) fn pop_types<'a>( + &'a mut self, + val_types: impl IntoIterator<Item = &'a ValType>, + ) -> impl core::iter::Iterator<Item = WasmValue> { + val_types.into_iter().map(|val_type| self.pop_wasmvalue(*val_type)) } #[inline] @@ -168,7 +166,7 @@ impl ValueStack { pub(crate) fn truncate_keep(&mut self, to: StackLocation, keep: StackHeight) { #[inline(always)] - fn truncate_keep<T: Copy + Default>(data: &mut Vec<T>, n: u32, end_keep: u32) { + fn truncate_keep<T>(data: &mut Vec<T>, n: u32, end_keep: u32) { let len = data.len() as u32; if len <= n { return; // No need to truncate if the current size is already less than or equal to total_to_keep @@ -205,7 +203,15 @@ impl ValueStack { pub(crate) fn extend_from_wasmvalues(&mut self, values: &[WasmValue]) { for value in values { - self.push_dyn(value.into()); + match value { + WasmValue::I32(v) => self.stack_32.push(*v as u32), + WasmValue::I64(v) => self.stack_64.push(*v as u64), + WasmValue::F32(v) => self.stack_32.push(v.to_bits()), + WasmValue::F64(v) => self.stack_64.push(v.to_bits()), + WasmValue::RefExtern(v) => self.stack_ref.push(v.addr()), + WasmValue::RefFunc(v) => self.stack_ref.push(v.addr()), + WasmValue::V128(v) => self.stack_128.push((*v).into()), + } } } } diff --git a/crates/tinywasm/src/interpreter/values.rs b/crates/tinywasm/src/interpreter/values.rs index 0940c97..456fb93 100644 --- a/crates/tinywasm/src/interpreter/values.rs +++ b/crates/tinywasm/src/interpreter/values.rs @@ -70,7 +70,7 @@ impl TinyWasmValue { pub fn unwrap_32(&self) -> Value32 { match self { Self::Value32(v) => *v, - _ => unreachable!("Expected Value32"), + _ => panic!("Expected Value32"), } } @@ -78,7 +78,7 @@ impl TinyWasmValue { pub fn unwrap_64(&self) -> Value64 { match self { Self::Value64(v) => *v, - _ => unreachable!("Expected Value64"), + _ => panic!("Expected Value64"), } } @@ -86,7 +86,7 @@ impl TinyWasmValue { pub fn unwrap_128(&self) -> Value128 { match self { Self::Value128(v) => *v, - _ => unreachable!("Expected Value128"), + _ => panic!("Expected Value128"), } } @@ -94,7 +94,7 @@ impl TinyWasmValue { pub fn unwrap_ref(&self) -> ValueRef { match self { Self::ValueRef(v) => *v, - _ => unreachable!("Expected ValueRef"), + _ => panic!("Expected ValueRef"), } } |
