diff options
| -rw-r--r-- | crates/cli/bin.rs | 4 | ||||
| -rw-r--r-- | crates/parser/src/lib.rs | 2 | ||||
| -rw-r--r-- | crates/tinywasm/src/lib.rs | 5 | ||||
| -rw-r--r-- | crates/tinywasm/src/module/mod.rs | 69 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/stack/mod.rs | 13 | ||||
| -rw-r--r-- | crates/tinywasm/src/store.rs | 9 | ||||
| -rw-r--r-- | crates/tinywasm/src/types.rs | 47 | ||||
| -rw-r--r-- | crates/types/src/lib.rs | 30 |
8 files changed, 91 insertions, 88 deletions
diff --git a/crates/cli/bin.rs b/crates/cli/bin.rs index 015f34a..ce33544 100644 --- a/crates/cli/bin.rs +++ b/crates/cli/bin.rs @@ -82,9 +82,9 @@ fn run(wasm: &[u8]) -> Result<()> { let mut store = tinywasm::Store::default(); let module = tinywasm::Module::parse_bytes(wasm)?; - let instance = module.instantiate(&mut store)?; + let mut instance = module.instantiate(&mut store)?; - let func = instance.get_func(&mut store, "add")?; + let mut func = instance.get_func(&mut store, "add")?; let params = vec![WasmValue::I32(2), WasmValue::I32(2)]; let res = func.call(&mut store, params)?; info!("{res:?}"); diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index 6c49af0..0d12990 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -98,7 +98,7 @@ impl TryFrom<ModuleReader> for TinyWasmModule { .into_iter() .zip(func_types) .map(|(f, ty)| Function { - body: f.body, + instructions: f.body, locals: f.locals, ty, }) diff --git a/crates/tinywasm/src/lib.rs b/crates/tinywasm/src/lib.rs index da24d19..eecf325 100644 --- a/crates/tinywasm/src/lib.rs +++ b/crates/tinywasm/src/lib.rs @@ -15,9 +15,8 @@ pub mod module; pub use module::Module; pub use module::ModuleInstance; -pub mod types; -pub use types::*; - +pub use tinywasm_parser as parser; +pub use tinywasm_types::*; pub mod runtime; #[cfg(test)] diff --git a/crates/tinywasm/src/module/mod.rs b/crates/tinywasm/src/module/mod.rs index a692175..2a5141c 100644 --- a/crates/tinywasm/src/module/mod.rs +++ b/crates/tinywasm/src/module/mod.rs @@ -6,12 +6,13 @@ use alloc::{ vec::Vec, }; use log::info; -use tinywasm_types::{Export, ExternalKind, FuncAddr, FuncType, TinyWasmModule}; +use tinywasm_types::{ + Export, ExternalKind, FuncAddr, FuncType, TinyWasmModule, ValType, WasmValue, +}; use crate::{ - runtime::Runtime, store::{self, StoreData}, - Error, Result, Store, WasmValue, + Error, Result, Store, }; #[derive(Debug)] @@ -55,7 +56,7 @@ impl Module { store: &mut Store, // imports: Option<()>, ) -> Result<ModuleInstance> { - let i = ModuleInstance::new(store, self)?; + let mut i = ModuleInstance::new(store, self)?; let _ = i.start(store)?; Ok(i) } @@ -79,7 +80,7 @@ pub struct ModuleInstance { impl ModuleInstance { /// Get an exported function by name - pub fn get_func(&self, store: &store::Store, name: &str) -> Result<FuncHandle> { + pub fn get_func(&mut self, store: &store::Store, name: &str) -> Result<FuncHandle> { let export = self .exports .iter() @@ -87,39 +88,39 @@ impl ModuleInstance { .ok_or(Error::Other(format!("export {} not found", name)))?; let func = store.get_func(export.index as usize)?; - let ty = &self.types[func.ty as usize]; + let ty = self.types[func.ty as usize].clone(); Ok(FuncHandle { addr: export.index, - module: &self, + module: self, name: Some(name.to_string()), - ty: ty.clone(), + ty, }) } /// Get the start function of the module - pub fn get_start_func(&self, store: &store::Store) -> Result<Option<FuncHandle>> { - let Some(func_addr) = self.func_start else { + pub fn get_start_func(&mut self, store: &store::Store) -> Result<Option<FuncHandle>> { + let Some(addr) = self.func_start else { return Ok(None); }; - let func = store.get_func(func_addr as usize)?; - let ty = &self.types[func.ty as usize]; + let func = store.get_func(addr as usize)?; + let ty = self.types[func.ty as usize].clone(); + Ok(Some(FuncHandle { - module: &self, - addr: func_addr, - ty: ty.clone(), + module: self, + addr, + ty, name: None, })) } - pub fn new(store: &mut Store, module: Module) -> Result<Self> { + pub fn new(store: &mut Store, mut module: Module) -> Result<Self> { let store_data = StoreData { funcs: module.data.funcs, }; store.initialize(store_data)?; - Ok(Self { types: module.data.types, func_start: module.data.start_func, @@ -135,8 +136,8 @@ impl ModuleInstance { /// Invoke the start function of the module /// Returns None if the module has no start function /// https://webassembly.github.io/spec/core/syntax/modules.html#syntax-start - pub fn start(&self, store: &mut store::Store) -> Result<Option<()>> { - let Some(func) = self.get_start_func(store)? else { + pub fn start(&mut self, store: &mut store::Store) -> Result<Option<()>> { + let Some(mut func) = self.get_start_func(store)? else { return Ok(None); }; @@ -147,7 +148,7 @@ impl ModuleInstance { #[derive(Debug)] pub struct FuncHandle<'a> { - module: &'a ModuleInstance, + module: &'a mut ModuleInstance, addr: FuncAddr, ty: FuncType, pub name: Option<String>, @@ -155,17 +156,35 @@ pub struct FuncHandle<'a> { impl<'a> FuncHandle<'a> { /// Call a function - pub fn call(&self, store: &mut Store, params: Vec<WasmValue>) -> Result<Vec<WasmValue>> { - let func = store.get_func(self.addr as usize)?; + pub fn call(&mut self, store: &mut Store, params: Vec<WasmValue>) -> Result<Vec<WasmValue>> { + let func = store + .data + .funcs + .get(self.addr as usize) + .ok_or(Error::Other(format!("function {} not found", self.addr)))?; + let func_ty = &self.ty; - let mut runtime = Runtime::default(); + // check that params match func_ty params + for (ty, param) in func_ty.params.iter().zip(params.clone()) { + if ty != ¶m.val_type() { + return Err(Error::Other(format!( + "param type mismatch: expected {:?}, got {:?}", + ty, param + ))); + } + } + + let mut local_types: Vec<ValType> = Vec::new(); + local_types.extend(func_ty.params.iter()); + local_types.extend(func.locals.iter()); + + let runtime = &mut store.runtime; let stack = &mut runtime.stack; let locals = &mut stack.locals; locals.extend(params); - let mut instrs = func.body.iter(); - + let mut instrs = func.instructions.iter(); while let Some(instr) = instrs.next() { use tinywasm_types::Instruction::*; match instr { diff --git a/crates/tinywasm/src/runtime/stack/mod.rs b/crates/tinywasm/src/runtime/stack/mod.rs index f7ffdf3..1149429 100644 --- a/crates/tinywasm/src/runtime/stack/mod.rs +++ b/crates/tinywasm/src/runtime/stack/mod.rs @@ -1,8 +1,8 @@ -use crate::WasmValue; use alloc::vec::Vec; mod call; pub use call::CallFrame; +use tinywasm_types::WasmValue; // minimum stack size pub const STACK_SIZE: usize = 1024; @@ -20,10 +20,9 @@ pub struct Stack { // TODO: Split into Vec<u8> and Vec<ValType> for better memory usage? pub value_stack: Vec<WasmValue>, // keeping this typed for now to make it easier to debug pub value_stack_top: usize, - - /// The call stack - pub call_stack: Vec<CallFrame>, - pub call_stack_top: usize, + // /// The call stack + // pub call_stack: Vec<CallFrame>, + // pub call_stack_top: usize, } impl Default for Stack { @@ -32,8 +31,8 @@ impl Default for Stack { locals: Vec::new(), value_stack: Vec::with_capacity(STACK_SIZE), value_stack_top: 0, - call_stack: Vec::with_capacity(CALL_STACK_SIZE), - call_stack_top: 0, + // call_stack: Vec::with_capacity(CALL_STACK_SIZE), + // call_stack_top: 0, } } } diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 6fc5860..fc64bc4 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -1,15 +1,22 @@ use alloc::{boxed::Box, format}; use tinywasm_types::Function; -use crate::{Error, Result}; +use crate::{runtime::Runtime, Error, Result}; /// global state that can be manipulated by WebAssembly programs /// https://webassembly.github.io/spec/core/exec/runtime.html#store #[derive(Debug, Default)] pub struct Store { pub(crate) data: StoreData, + pub(crate) runtime: Runtime, } +// #[derive(Debug)] +// pub struct FunctionInstance { +// pub(crate) func: Function, +// pub(crate) module: usize, +// } + #[derive(Debug, Default)] pub struct StoreData { pub funcs: Box<[Function]>, diff --git a/crates/tinywasm/src/types.rs b/crates/tinywasm/src/types.rs deleted file mode 100644 index 0ce721f..0000000 --- a/crates/tinywasm/src/types.rs +++ /dev/null @@ -1,47 +0,0 @@ -/// A WebAssembly value. -/// See https://webassembly.github.io/spec/core/syntax/types.html#value-types -#[derive(Debug, Clone, PartialEq)] -pub enum WasmValue { - // Num types - I32(i32), - I64(i64), - F32(f32), - F64(f64), - - // Vec types - V128(i128), -} - -/// Type of a WebAssembly value. -#[derive(Debug, Clone, PartialEq)] -pub enum ValType { - I32, - I64, - F32, - F64, - V128, - FuncRef, - ExternRef, -} - -impl From<WasmValue> for ValType { - fn from(wasm_value: WasmValue) -> Self { - match wasm_value { - WasmValue::I32(_) => ValType::I32, - WasmValue::I64(_) => ValType::I64, - WasmValue::F32(_) => ValType::F32, - WasmValue::F64(_) => ValType::F64, - WasmValue::V128(_) => ValType::V128, - } - } -} - -impl WasmValue { - pub fn type_of(&self) -> ValType { - self.clone().into() - } - - pub fn is(&self, ty: ValType) -> bool { - self.type_of() == ty - } -} diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 39ced78..9477dc7 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -1,6 +1,8 @@ extern crate alloc; mod instructions; +use core::fmt::Debug; + pub use instructions::*; #[derive(Debug)] @@ -21,7 +23,7 @@ pub struct TinyWasmModule { /// A WebAssembly value. /// See https://webassembly.github.io/spec/core/syntax/types.html#value-types -#[derive(Debug, Clone, PartialEq)] +#[derive(Clone, PartialEq)] pub enum WasmValue { // Num types I32(i32), @@ -33,6 +35,30 @@ pub enum WasmValue { V128(i128), } +impl Debug for WasmValue { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + WasmValue::I32(i) => write!(f, "i32({})", i), + WasmValue::I64(i) => write!(f, "i64({})", i), + WasmValue::F32(i) => write!(f, "f32({})", i), + WasmValue::F64(i) => write!(f, "f64({})", i), + WasmValue::V128(i) => write!(f, "v128({})", i), + } + } +} + +impl WasmValue { + pub fn val_type(&self) -> ValType { + match self { + Self::I32(_) => ValType::I32, + Self::I64(_) => ValType::I64, + Self::F32(_) => ValType::F32, + Self::F64(_) => ValType::F64, + Self::V128(_) => ValType::V128, + } + } +} + /// Type of a WebAssembly value. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ValType { @@ -102,7 +128,7 @@ pub struct FuncType { pub struct Function { pub ty: TypeAddr, pub locals: Box<[ValType]>, - pub body: Box<[Instruction]>, + pub instructions: Box<[Instruction]>, } /// A WebAssembly Module Export |
