From d8d439e6401607fab18feb5025f3b91f135e3a50 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Fri, 26 Jan 2024 15:16:05 +0100 Subject: feat: add more examples, work on new public api Signed-off-by: Henry Gressmann --- crates/cli/src/bin.rs | 2 +- crates/tinywasm/src/export.rs | 1 - crates/tinywasm/src/imports.rs | 9 +++++++-- crates/tinywasm/src/instance.rs | 36 +++++++++++++++++++++++---------- crates/tinywasm/src/lib.rs | 5 ++++- crates/tinywasm/src/reference.rs | 17 ++++++++++++++++ crates/tinywasm/tests/testsuite/run.rs | 2 +- crates/tinywasm/tests/testsuite/util.rs | 4 ++-- crates/types/src/lib.rs | 6 +++--- 9 files changed, 60 insertions(+), 22 deletions(-) delete mode 100644 crates/tinywasm/src/export.rs create mode 100644 crates/tinywasm/src/reference.rs (limited to 'crates') diff --git a/crates/cli/src/bin.rs b/crates/cli/src/bin.rs index 1c166cf..34d4bcd 100644 --- a/crates/cli/src/bin.rs +++ b/crates/cli/src/bin.rs @@ -112,7 +112,7 @@ fn run(module: Module, func: Option, args: Vec) -> Result<()> let instance = module.instantiate(&mut store, None)?; if let Some(func) = func { - let func = instance.exported_func_by_name(&store, &func)?; + let func = instance.exported_func_untyped(&store, &func)?; let res = func.call(&mut store, &args)?; info!("{res:?}"); } diff --git a/crates/tinywasm/src/export.rs b/crates/tinywasm/src/export.rs deleted file mode 100644 index 8b13789..0000000 --- a/crates/tinywasm/src/export.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index a640081..9c5086a 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -77,6 +77,11 @@ impl FuncContext<'_> { pub fn module(&self) -> &crate::ModuleInstance { self.module } + + /// Get a reference to an exported memory + pub fn memory(&mut self, name: &str) -> Result { + self.module.exported_memory(self.store, name) + } } impl Debug for HostFunction { @@ -276,7 +281,7 @@ impl Imports { if let Some(addr) = self.modules.get(&name.module) { let instance = store.get_module_instance(*addr)?; - return Some(ResolvedExtern::Store(instance.export(&import.name)?)); + return Some(ResolvedExtern::Store(instance.export_addr(&import.name)?)); } None @@ -398,7 +403,7 @@ impl Imports { Self::compare_table_types(import, &table.borrow().kind, ty)?; imports.tables.push(table_addr); } - (ExternVal::Mem(memory_addr), ImportKind::Memory(ty)) => { + (ExternVal::Memory(memory_addr), ImportKind::Memory(ty)) => { let mem = store.get_mem(memory_addr as usize)?; let (size, kind) = { let mem = mem.borrow(); diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index d750cd5..dfee2ca 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -1,12 +1,9 @@ use alloc::{boxed::Box, format, string::ToString, sync::Arc}; -use tinywasm_types::{ - DataAddr, ElemAddr, Export, ExternVal, ExternalKind, FuncAddr, FuncType, GlobalAddr, Import, MemAddr, - ModuleInstanceAddr, TableAddr, -}; +use tinywasm_types::*; use crate::{ func::{FromWasmValueTuple, IntoWasmValueTuple}, - log, Error, FuncHandle, FuncHandleTyped, Imports, Module, Result, Store, + log, Error, FuncHandle, FuncHandleTyped, Imports, MemoryRef, Module, Result, Store, }; /// An instanciated WebAssembly module @@ -106,7 +103,7 @@ impl ModuleInstance { } /// Get a export by name - pub fn export(&self, name: &str) -> Option { + pub fn export_addr(&self, name: &str) -> Option { let exports = self.0.exports.iter().find(|e| e.name == name.into())?; let kind = exports.kind.clone(); let addr = match kind { @@ -162,12 +159,12 @@ impl ModuleInstance { } /// Get an exported function by name - pub fn exported_func_by_name(&self, store: &Store, name: &str) -> Result { + pub fn exported_func_untyped(&self, store: &Store, name: &str) -> Result { if self.0.store_id != store.id() { return Err(Error::InvalidStore); } - let export = self.export(name).ok_or_else(|| Error::Other(format!("Export not found: {}", name)))?; + let export = self.export_addr(name).ok_or_else(|| Error::Other(format!("Export not found: {}", name)))?; let ExternVal::Func(func_addr) = export else { return Err(Error::Other(format!("Export is not a function: {}", name))); }; @@ -179,15 +176,32 @@ impl ModuleInstance { } /// Get a typed exported function by name - pub fn typed_func(&self, store: &Store, name: &str) -> Result> + pub fn exported_func(&self, store: &Store, name: &str) -> Result> where P: IntoWasmValueTuple, R: FromWasmValueTuple, { - let func = self.exported_func_by_name(store, name)?; + let func = self.exported_func_untyped(store, name)?; Ok(FuncHandleTyped { func, marker: core::marker::PhantomData }) } + /// Get an exported memory by name + pub fn exported_memory(&self, store: &mut Store, name: &str) -> Result { + let export = self.export_addr(name).ok_or_else(|| Error::Other(format!("Export not found: {}", name)))?; + let ExternVal::Memory(mem_addr) = export else { + return Err(Error::Other(format!("Export is not a memory: {}", name))); + }; + let mem = self.memory(store, mem_addr)?; + Ok(mem) + } + + /// Get a memory by address + pub fn memory(&self, store: &Store, addr: MemAddr) -> Result { + let addr = self.resolve_mem_addr(addr); + let mem = store.get_mem(addr as usize)?; + Ok(MemoryRef { instance: mem.clone() }) + } + /// Get the start function of the module /// /// Returns None if the module has no start function @@ -204,7 +218,7 @@ impl ModuleInstance { Some(func_index) => func_index, None => { // alternatively, check for a _start function in the exports - let Some(ExternVal::Func(func_addr)) = self.export("_start") else { + let Some(ExternVal::Func(func_addr)) = self.export_addr("_start") else { return Ok(None); }; diff --git a/crates/tinywasm/src/lib.rs b/crates/tinywasm/src/lib.rs index 36270a7..f2951b6 100644 --- a/crates/tinywasm/src/lib.rs +++ b/crates/tinywasm/src/lib.rs @@ -51,7 +51,7 @@ //! // Get a typed handle to the exported "add" function //! // Alternatively, you can use `instance.get_func` to get an untyped handle //! // that takes and returns [`WasmValue`]s -//! let func = instance.typed_func::<(i32, i32), i32>(&mut store, "add")?; +//! let func = instance.exported_func::<(i32, i32), i32>(&mut store, "add")?; //! let res = func.call(&mut store, (1, 2))?; //! //! assert_eq!(res, 3); @@ -99,6 +99,9 @@ pub use module::Module; mod instance; pub use instance::ModuleInstance; +mod reference; +pub use reference::*; + mod func; pub use func::{FuncHandle, FuncHandleTyped}; diff --git a/crates/tinywasm/src/reference.rs b/crates/tinywasm/src/reference.rs new file mode 100644 index 0000000..21471f6 --- /dev/null +++ b/crates/tinywasm/src/reference.rs @@ -0,0 +1,17 @@ +use core::cell::RefCell; + +use alloc::rc::Rc; + +use crate::{GlobalInstance, MemoryInstance}; + +/// A reference to a memory instance +#[derive(Debug, Clone)] +pub struct MemoryRef { + pub(crate) instance: Rc>, +} + +/// A reference to a global instance +#[derive(Debug, Clone)] +pub struct GlobalRef { + pub(crate) instance: Rc>, +} diff --git a/crates/tinywasm/tests/testsuite/run.rs b/crates/tinywasm/tests/testsuite/run.rs index 79d9acc..c44c3fb 100644 --- a/crates/tinywasm/tests/testsuite/run.rs +++ b/crates/tinywasm/tests/testsuite/run.rs @@ -428,7 +428,7 @@ impl TestSuite { continue; }; - let module_global = match match module.export(global) { + let module_global = match match module.export_addr(global) { Some(ExternVal::Global(addr)) => { store.get_global_val(addr as usize).map_err(|_| eyre!("failed to get global")) } diff --git a/crates/tinywasm/tests/testsuite/util.rs b/crates/tinywasm/tests/testsuite/util.rs index b74eec5..09a4769 100644 --- a/crates/tinywasm/tests/testsuite/util.rs +++ b/crates/tinywasm/tests/testsuite/util.rs @@ -25,7 +25,7 @@ pub fn exec_fn_instance( return Err(tinywasm::Error::Other("no instance found".to_string())); }; - let func = instance.exported_func_by_name(store, name)?; + let func = instance.exported_func_untyped(store, name)?; func.call(store, args) } @@ -42,7 +42,7 @@ pub fn exec_fn( let mut store = tinywasm::Store::new(); let module = tinywasm::Module::from(module); let instance = module.instantiate(&mut store, imports)?; - instance.exported_func_by_name(&store, name)?.call(&mut store, args) + instance.exported_func_untyped(&store, name)?.call(&mut store, args) } pub fn catch_unwind_silent R, R>(f: F) -> std::thread::Result { diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index d0d854c..365ead7 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -316,7 +316,7 @@ pub type ModuleInstanceAddr = Addr; pub enum ExternVal { Func(FuncAddr), Table(TableAddr), - Mem(MemAddr), + Memory(MemAddr), Global(GlobalAddr), } @@ -325,7 +325,7 @@ impl ExternVal { match self { Self::Func(_) => ExternalKind::Func, Self::Table(_) => ExternalKind::Table, - Self::Mem(_) => ExternalKind::Memory, + Self::Memory(_) => ExternalKind::Memory, Self::Global(_) => ExternalKind::Global, } } @@ -334,7 +334,7 @@ impl ExternVal { match kind { ExternalKind::Func => Self::Func(addr), ExternalKind::Table => Self::Table(addr), - ExternalKind::Memory => Self::Mem(addr), + ExternalKind::Memory => Self::Memory(addr), ExternalKind::Global => Self::Global(addr), } } -- cgit v1.3.1