From bcb8ebf79470d118c602f5e5c2fd41d4325827b5 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Thu, 23 May 2024 23:44:09 +0200 Subject: wip: another v128 attempt Signed-off-by: Henry Gressmann --- crates/tinywasm/src/func.rs | 5 +- crates/tinywasm/src/runtime/interpreter/mod.rs | 1 + crates/tinywasm/src/runtime/mod.rs | 2 +- crates/tinywasm/src/runtime/stack.rs | 19 ++++-- crates/tinywasm/src/runtime/stack/block_stack.rs | 4 +- crates/tinywasm/src/runtime/stack/call_stack.rs | 2 +- .../src/runtime/stack/large_value_stack.rs | 12 ++++ crates/tinywasm/src/runtime/stack/value_stack.rs | 70 ++++++++++------------ crates/tinywasm/src/runtime/value.rs | 30 ++++++++-- crates/tinywasm/src/store/global.rs | 5 +- crates/tinywasm/tests/testsuite/run.rs | 2 +- 11 files changed, 98 insertions(+), 54 deletions(-) create mode 100644 crates/tinywasm/src/runtime/stack/large_value_stack.rs diff --git a/crates/tinywasm/src/func.rs b/crates/tinywasm/src/func.rs index 95b7cc0..0f19651 100644 --- a/crates/tinywasm/src/func.rs +++ b/crates/tinywasm/src/func.rs @@ -1,10 +1,9 @@ +use crate::runtime::{CallFrame, Stack, WasmValueRepr}; use crate::{log, runtime::RawWasmValue, unlikely, Function}; +use crate::{Error, FuncContext, Result, Store}; use alloc::{boxed::Box, format, string::String, string::ToString, vec, vec::Vec}; use tinywasm_types::{FuncType, ModuleInstanceAddr, ValType, WasmValue}; -use crate::runtime::{CallFrame, Stack}; -use crate::{Error, FuncContext, Result, Store}; - #[derive(Debug)] /// A function handle pub struct FuncHandle { diff --git a/crates/tinywasm/src/runtime/interpreter/mod.rs b/crates/tinywasm/src/runtime/interpreter/mod.rs index d7da19f..f9dc95c 100644 --- a/crates/tinywasm/src/runtime/interpreter/mod.rs +++ b/crates/tinywasm/src/runtime/interpreter/mod.rs @@ -724,6 +724,7 @@ impl<'store, 'stack> Executor<'store, 'stack> { instr_ptr, end_instr_offset, stack_ptr: self.stack.values.len() as u32 - params as u32, + large_stack_ptr: 0, results, params, ty, diff --git a/crates/tinywasm/src/runtime/mod.rs b/crates/tinywasm/src/runtime/mod.rs index 8c22ce0..72fa6d4 100644 --- a/crates/tinywasm/src/runtime/mod.rs +++ b/crates/tinywasm/src/runtime/mod.rs @@ -4,7 +4,7 @@ mod value; use crate::Result; pub use stack::*; -pub(crate) use value::RawWasmValue; +pub use value::{LargeRawWasmValue, RawWasmValue, WasmValueRepr}; #[allow(rustdoc::private_intra_doc_links)] /// A WebAssembly runtime. diff --git a/crates/tinywasm/src/runtime/stack.rs b/crates/tinywasm/src/runtime/stack.rs index a64b234..ebcc41f 100644 --- a/crates/tinywasm/src/runtime/stack.rs +++ b/crates/tinywasm/src/runtime/stack.rs @@ -1,21 +1,32 @@ mod block_stack; mod call_stack; +mod large_value_stack; mod value_stack; -pub(crate) use self::{call_stack::CallStack, value_stack::ValueStack}; pub(crate) use block_stack::{BlockFrame, BlockStack, BlockType}; -pub(crate) use call_stack::CallFrame; +pub(crate) use call_stack::{CallFrame, CallStack}; +pub(crate) use large_value_stack::LargeValueStack; +pub(crate) use value_stack::ValueStack; + +use super::RawWasmValue; /// A WebAssembly Stack #[derive(Debug)] pub struct Stack { - pub(crate) values: ValueStack, + pub(crate) values: ValueStack, + pub(crate) large_values: LargeValueStack, + pub(crate) blocks: BlockStack, pub(crate) call_stack: CallStack, } impl Stack { pub(crate) fn new(call_frame: CallFrame) -> Self { - Self { values: ValueStack::default(), blocks: BlockStack::new(), call_stack: CallStack::new(call_frame) } + Self { + values: ValueStack::default(), + blocks: BlockStack::new(), + call_stack: CallStack::new(call_frame), + large_values: LargeValueStack::default(), + } } } diff --git a/crates/tinywasm/src/runtime/stack/block_stack.rs b/crates/tinywasm/src/runtime/stack/block_stack.rs index 9a823fd..425f584 100644 --- a/crates/tinywasm/src/runtime/stack/block_stack.rs +++ b/crates/tinywasm/src/runtime/stack/block_stack.rs @@ -54,7 +54,9 @@ impl BlockStack { pub(crate) struct BlockFrame { pub(crate) instr_ptr: usize, // position of the instruction pointer when the block was entered pub(crate) end_instr_offset: u32, // position of the end instruction of the block - pub(crate) stack_ptr: u32, // position of the stack pointer when the block was entered + + pub(crate) stack_ptr: u32, // position of the stack pointer when the block was entered + pub(crate) large_stack_ptr: u32, // position of the large stack pointer when the block was entered pub(crate) results: u8, pub(crate) params: u8, diff --git a/crates/tinywasm/src/runtime/stack/call_stack.rs b/crates/tinywasm/src/runtime/stack/call_stack.rs index 5dc754f..430e1c4 100644 --- a/crates/tinywasm/src/runtime/stack/call_stack.rs +++ b/crates/tinywasm/src/runtime/stack/call_stack.rs @@ -72,7 +72,7 @@ impl CallFrame { pub(crate) fn break_to( &mut self, break_to_relative: u32, - values: &mut super::ValueStack, + values: &mut super::ValueStack, blocks: &mut super::BlockStack, ) -> Option<()> { let break_to = blocks.get_relative_to(break_to_relative, self.block_ptr)?; diff --git a/crates/tinywasm/src/runtime/stack/large_value_stack.rs b/crates/tinywasm/src/runtime/stack/large_value_stack.rs new file mode 100644 index 0000000..97b7ce5 --- /dev/null +++ b/crates/tinywasm/src/runtime/stack/large_value_stack.rs @@ -0,0 +1,12 @@ +use alloc::vec::Vec; + +use crate::runtime::LargeRawWasmValue; + +#[derive(Debug)] +pub(crate) struct LargeValueStack(Vec); + +impl Default for LargeValueStack { + fn default() -> Self { + Self(Vec::new()) + } +} diff --git a/crates/tinywasm/src/runtime/stack/value_stack.rs b/crates/tinywasm/src/runtime/stack/value_stack.rs index 87522df..993715c 100644 --- a/crates/tinywasm/src/runtime/stack/value_stack.rs +++ b/crates/tinywasm/src/runtime/stack/value_stack.rs @@ -1,35 +1,33 @@ -use crate::{cold, runtime::RawWasmValue, unlikely, Error, Result}; +use crate::{cold, runtime::WasmValueRepr, unlikely, Error, Result}; use alloc::vec::Vec; use tinywasm_types::{ValType, WasmValue}; pub(crate) const MIN_VALUE_STACK_SIZE: usize = 1024 * 128; #[derive(Debug)] -pub(crate) struct ValueStack { - stack: Vec, -} +pub(crate) struct ValueStack(Vec); -impl Default for ValueStack { +impl Default for ValueStack { fn default() -> Self { - Self { stack: Vec::with_capacity(MIN_VALUE_STACK_SIZE) } + Self(Vec::with_capacity(MIN_VALUE_STACK_SIZE)) } } -impl ValueStack { +impl + Copy + WasmValueRepr> ValueStack { #[inline] pub(crate) fn extend_from_typed(&mut self, values: &[WasmValue]) { - self.stack.extend(values.iter().map(|v| RawWasmValue::from(*v))); + self.0.extend(values.iter().map(|v| T::from(*v))); } #[inline(always)] - pub(crate) fn replace_top(&mut self, func: fn(RawWasmValue) -> RawWasmValue) -> Result<()> { + pub(crate) fn replace_top(&mut self, func: fn(T) -> T) -> Result<()> { let v = self.last_mut()?; *v = func(*v); Ok(()) } #[inline(always)] - pub(crate) fn calculate(&mut self, func: fn(RawWasmValue, RawWasmValue) -> RawWasmValue) -> Result<()> { + pub(crate) fn calculate(&mut self, func: fn(T, T) -> T) -> Result<()> { let v2 = self.pop()?; let v1 = self.last_mut()?; *v1 = func(*v1, v2); @@ -37,10 +35,7 @@ impl ValueStack { } #[inline(always)] - pub(crate) fn calculate_trap( - &mut self, - func: fn(RawWasmValue, RawWasmValue) -> Result, - ) -> Result<()> { + pub(crate) fn calculate_trap(&mut self, func: fn(T, T) -> Result) -> Result<()> { let v2 = self.pop()?; let v1 = self.last_mut()?; *v1 = func(*v1, v2)?; @@ -49,13 +44,13 @@ impl ValueStack { #[inline(always)] pub(crate) fn len(&self) -> usize { - self.stack.len() + self.0.len() } #[inline] pub(crate) fn truncate_keep(&mut self, n: u32, end_keep: u32) { let total_to_keep = n + end_keep; - let len = self.stack.len() as u32; + let len = self.0.len() as u32; assert!(len >= total_to_keep, "Total to keep should be less than or equal to self.top"); if len <= total_to_keep { @@ -65,22 +60,22 @@ impl ValueStack { let items_to_remove = len - total_to_keep; let remove_start_index = (len - items_to_remove - end_keep) as usize; let remove_end_index = (len - end_keep) as usize; - self.stack.drain(remove_start_index..remove_end_index); + self.0.drain(remove_start_index..remove_end_index); } #[inline(always)] - pub(crate) fn push(&mut self, value: RawWasmValue) { - self.stack.push(value); + pub(crate) fn push(&mut self, value: T) { + self.0.push(value); } #[inline(always)] - pub(crate) fn extend_from_slice(&mut self, values: &[RawWasmValue]) { - self.stack.extend_from_slice(values); + pub(crate) fn extend_from_slice(&mut self, values: &[T]) { + self.0.extend_from_slice(values); } #[inline] - pub(crate) fn last_mut(&mut self) -> Result<&mut RawWasmValue> { - match self.stack.last_mut() { + pub(crate) fn last_mut(&mut self) -> Result<&mut T> { + match self.0.last_mut() { Some(v) => Ok(v), None => { cold(); @@ -90,8 +85,8 @@ impl ValueStack { } #[inline] - pub(crate) fn last(&self) -> Result<&RawWasmValue> { - match self.stack.last() { + pub(crate) fn last(&self) -> Result<&T> { + match self.0.last() { Some(v) => Ok(v), None => { cold(); @@ -101,8 +96,8 @@ impl ValueStack { } #[inline(always)] - pub(crate) fn pop(&mut self) -> Result { - match self.stack.pop() { + pub(crate) fn pop(&mut self) -> Result { + match self.0.pop() { Some(v) => Ok(v), None => { cold(); @@ -119,35 +114,36 @@ impl ValueStack { #[inline] pub(crate) fn break_to(&mut self, new_stack_size: u32, result_count: u8) { let start = new_stack_size as usize; - let end = self.stack.len() - result_count as usize; - self.stack.drain(start..end); + let end = self.0.len() - result_count as usize; + self.0.drain(start..end); } #[inline] - pub(crate) fn last_n(&self, n: usize) -> Result<&[RawWasmValue]> { - let len = self.stack.len(); + pub(crate) fn last_n(&self, n: usize) -> Result<&[T]> { + let len = self.0.len(); if unlikely(len < n) { return Err(Error::ValueStackUnderflow); } - Ok(&self.stack[len - n..len]) + Ok(&self.0[len - n..len]) } #[inline] - pub(crate) fn pop_n_rev(&mut self, n: usize) -> Result> { - if unlikely(self.stack.len() < n) { + pub(crate) fn pop_n_rev(&mut self, n: usize) -> Result> { + if unlikely(self.0.len() < n) { return Err(Error::ValueStackUnderflow); } - Ok(self.stack.drain((self.stack.len() - n)..)) + Ok(self.0.drain((self.0.len() - n)..)) } } #[cfg(test)] mod tests { use super::*; + use crate::runtime::RawWasmValue; #[test] fn test_value_stack() { - let mut stack = ValueStack::default(); + let mut stack: ValueStack = ValueStack::default(); stack.push(1.into()); stack.push(2.into()); stack.push(3.into()); @@ -165,7 +161,7 @@ mod tests { macro_rules! test_macro { ($( $n:expr, $end_keep:expr, $expected:expr ),*) => { $( - let mut stack = ValueStack::default(); + let mut stack: ValueStack = ValueStack::default(); stack.push(1.into()); stack.push(2.into()); stack.push(3.into()); diff --git a/crates/tinywasm/src/runtime/value.rs b/crates/tinywasm/src/runtime/value.rs index e5769bf..832371e 100644 --- a/crates/tinywasm/src/runtime/value.rs +++ b/crates/tinywasm/src/runtime/value.rs @@ -9,20 +9,33 @@ use tinywasm_types::{ValType, WasmValue}; #[derive(Clone, Copy, Default, PartialEq, Eq)] pub struct RawWasmValue([u8; 8]); +/// A large raw wasm value, used for 128-bit values. +/// +/// This is the internal representation of vector values. +/// +/// See [`WasmValue`] for the public representation. +#[derive(Clone, Copy, Default, PartialEq, Eq)] +pub struct LargeRawWasmValue([u8; 16]); + impl Debug for RawWasmValue { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "RawWasmValue({})", 0) } } -impl RawWasmValue { - #[inline(always)] - pub fn raw_value(&self) -> [u8; 8] { - self.0 +impl Debug for LargeRawWasmValue { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "LargeRawWasmValue({})", 0) } +} + +pub trait WasmValueRepr { + fn attach_type(self, ty: ValType) -> WasmValue; +} +impl WasmValueRepr for RawWasmValue { #[inline] - pub fn attach_type(self, ty: ValType) -> WasmValue { + fn attach_type(self, ty: ValType) -> WasmValue { match ty { ValType::I32 => WasmValue::I32(self.into()), ValType::I64 => WasmValue::I64(self.into()), @@ -40,6 +53,13 @@ impl RawWasmValue { } } +impl RawWasmValue { + #[inline(always)] + pub fn raw_value(&self) -> [u8; 8] { + self.0 + } +} + impl From for RawWasmValue { #[inline] fn from(v: WasmValue) -> Self { diff --git a/crates/tinywasm/src/store/global.rs b/crates/tinywasm/src/store/global.rs index 6cc778c..e4a1817 100644 --- a/crates/tinywasm/src/store/global.rs +++ b/crates/tinywasm/src/store/global.rs @@ -3,7 +3,10 @@ use core::cell::Cell; use alloc::{format, string::ToString}; use tinywasm_types::*; -use crate::{runtime::RawWasmValue, unlikely, Error, Result}; +use crate::{ + runtime::{RawWasmValue, WasmValueRepr}, + unlikely, Error, Result, +}; /// A WebAssembly Global Instance /// diff --git a/crates/tinywasm/tests/testsuite/run.rs b/crates/tinywasm/tests/testsuite/run.rs index 1de633f..beb20a8 100644 --- a/crates/tinywasm/tests/testsuite/run.rs +++ b/crates/tinywasm/tests/testsuite/run.rs @@ -6,7 +6,7 @@ use super::TestSuite; use _log as log; use eyre::{eyre, Result}; use log::{debug, error, info}; -use tinywasm::{Extern, Imports, ModuleInstance}; +use tinywasm::{runtime::WasmValueRepr, Extern, Imports, ModuleInstance}; use tinywasm_types::{ExternVal, MemoryType, ModuleInstanceAddr, TableType, ValType, WasmValue}; use wast::{lexer::Lexer, parser::ParseBuffer, Wast}; -- cgit v1.3.1