summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/tinywasm/src/func.rs5
-rw-r--r--crates/tinywasm/src/runtime/interpreter/mod.rs1
-rw-r--r--crates/tinywasm/src/runtime/mod.rs2
-rw-r--r--crates/tinywasm/src/runtime/stack.rs19
-rw-r--r--crates/tinywasm/src/runtime/stack/block_stack.rs4
-rw-r--r--crates/tinywasm/src/runtime/stack/call_stack.rs2
-rw-r--r--crates/tinywasm/src/runtime/stack/large_value_stack.rs12
-rw-r--r--crates/tinywasm/src/runtime/stack/value_stack.rs70
-rw-r--r--crates/tinywasm/src/runtime/value.rs30
-rw-r--r--crates/tinywasm/src/store/global.rs5
-rw-r--r--crates/tinywasm/tests/testsuite/run.rs2
11 files changed, 98 insertions, 54 deletions
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<RawWasmValue>,
+ 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<RawWasmValue>,
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<LargeRawWasmValue>);
+
+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<RawWasmValue>,
-}
+pub(crate) struct ValueStack<T>(Vec<T>);
-impl Default for ValueStack {
+impl<T> Default for ValueStack<T> {
fn default() -> Self {
- Self { stack: Vec::with_capacity(MIN_VALUE_STACK_SIZE) }
+ Self(Vec::with_capacity(MIN_VALUE_STACK_SIZE))
}
}
-impl ValueStack {
+impl<T: From<WasmValue> + Copy + WasmValueRepr> ValueStack<T> {
#[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<RawWasmValue>,
- ) -> Result<()> {
+ pub(crate) fn calculate_trap(&mut self, func: fn(T, T) -> Result<T>) -> 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<RawWasmValue> {
- match self.stack.pop() {
+ pub(crate) fn pop(&mut self) -> Result<T> {
+ 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<alloc::vec::Drain<'_, RawWasmValue>> {
- if unlikely(self.stack.len() < n) {
+ pub(crate) fn pop_n_rev(&mut self, n: usize) -> Result<alloc::vec::Drain<'_, T>> {
+ 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<RawWasmValue> = 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<RawWasmValue> = 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<WasmValue> 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};