diff options
| author | Henry Gressmann <mail@henrygressmann.de> | 2024-01-22 01:15:28 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-01-22 01:15:28 +0100 |
| commit | 0b2bd6c33d086b52952206efa03aead00021bb4a (patch) | |
| tree | 513883b826731696643a164a0c1deb14e8141aca | |
| parent | 7b456a58f70c0a1dbaf289d285b14a6b139495f7 (diff) | |
| parent | c0dd4bc48f703b46f6e0f683c10c015c92f46bba (diff) | |
Merge pull request #1 from explodingcamera/imports
feat: host functions, rewrite linker
| -rw-r--r-- | Cargo.lock | 16 | ||||
| -rw-r--r-- | crates/tinywasm/src/export.rs | 17 | ||||
| -rw-r--r-- | crates/tinywasm/src/func.rs | 21 | ||||
| -rw-r--r-- | crates/tinywasm/src/imports.rs | 264 | ||||
| -rw-r--r-- | crates/tinywasm/src/instance.rs | 118 | ||||
| -rw-r--r-- | crates/tinywasm/src/lib.rs | 8 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/executor/macros.rs | 7 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/executor/mod.rs | 43 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/stack/value_stack.rs | 31 | ||||
| -rw-r--r-- | crates/tinywasm/src/store.rs | 306 | ||||
| -rw-r--r-- | crates/tinywasm/tests/generated/mvp.csv | 2 | ||||
| -rw-r--r-- | crates/tinywasm/tests/generated/progress-mvp.svg | 6 | ||||
| -rw-r--r-- | crates/tinywasm/tests/testsuite/run.rs | 9 | ||||
| -rw-r--r-- | crates/types/src/lib.rs | 52 | ||||
| -rw-r--r-- | rustfmt.toml | 1 |
15 files changed, 428 insertions, 473 deletions
@@ -855,9 +855,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.76" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] @@ -919,9 +919,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", @@ -931,9 +931,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "3b7fa1134405e2ec9353fd416b17f8dacd46c473d7d3fd1cf202706a14eb792a" dependencies = [ "aho-corasick", "memchr", @@ -1272,9 +1272,9 @@ checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "uuid" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" [[package]] name = "version_check" diff --git a/crates/tinywasm/src/export.rs b/crates/tinywasm/src/export.rs index 52adc6f..8b13789 100644 --- a/crates/tinywasm/src/export.rs +++ b/crates/tinywasm/src/export.rs @@ -1,18 +1 @@ -use alloc::boxed::Box; -use tinywasm_types::{Export, ExternalKind}; -#[derive(Debug)] -/// Exports of a module instance -// TODO: Maybe use a BTreeMap instead? -pub struct ExportInstance(pub(crate) Box<[Export]>); - -impl ExportInstance { - /// Get an export by name - pub fn get(&self, name: &str, ty: ExternalKind) -> Option<&Export> { - self.0.iter().find(|e| e.name == name.into() && e.kind == ty) - } - - pub(crate) fn get_untyped(&self, name: &str) -> Option<&Export> { - self.0.iter().find(|e| e.name == name.into()) - } -} diff --git a/crates/tinywasm/src/func.rs b/crates/tinywasm/src/func.rs index 74043a9..8546b9f 100644 --- a/crates/tinywasm/src/func.rs +++ b/crates/tinywasm/src/func.rs @@ -52,7 +52,13 @@ impl FuncHandle { } } - let wasm_func = &func_inst.assert_wasm()?; + let wasm_func = match &func_inst.func { + crate::Function::Host(h) => { + let func = h.func.clone(); + return (func)(store, params); + } + crate::Function::Wasm(ref f) => f, + }; // 6. Let f be the dummy frame debug!("locals: {:?}", wasm_func.locals); @@ -76,11 +82,7 @@ impl FuncHandle { let res = stack.values.last_n(result_m)?; // The values are returned as the results of the invocation. - Ok(res - .iter() - .zip(func_ty.results.iter()) - .map(|(v, ty)| v.attach_type(*ty)) - .collect()) + Ok(res.iter().zip(func_ty.results.iter()).map(|(v, ty)| v.attach_type(*ty)).collect()) } } @@ -184,11 +186,8 @@ macro_rules! impl_from_wasm_value_tuple_single { fn from_wasm_value_tuple(values: Vec<WasmValue>) -> Result<Self> { #[allow(unused_variables, unused_mut)] let mut iter = values.into_iter(); - Ok($T::try_from( - iter.next() - .ok_or(Error::Other("Not enough values in WasmValue vector".to_string()))?, - ) - .map_err(|_| Error::Other("Could not convert WasmValue to expected type".to_string()))?) + $T::try_from(iter.next().ok_or(Error::Other("Not enough values in WasmValue vector".to_string()))?) + .map_err(|_| Error::Other("Could not convert WasmValue to expected type".to_string())) } } }; diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index 41dd1a2..ff9d061 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] + use core::fmt::Debug; use crate::{ @@ -10,32 +12,45 @@ use alloc::{ sync::Arc, vec::Vec, }; -use tinywasm_types::{ - ExternVal, ExternalKind, GlobalType, MemoryType, ModuleInstanceAddr, TableType, WasmFunction, WasmValue, -}; +use tinywasm_types::*; -#[derive(Debug)] -pub(crate) enum Function { +/// The internal representation of a function +#[derive(Debug, Clone)] +pub enum Function { + /// A host function Host(HostFunction), + + /// A function defined in WebAssembly Wasm(WasmFunction), } +impl Function { + /// Get the function's type + pub fn ty(&self, module: &crate::ModuleInstance) -> tinywasm_types::FuncType { + match self { + Self::Host(f) => f.ty.clone(), + Self::Wasm(f) => module.func_ty(f.ty_addr).clone(), + } + } +} + /// A host function +#[derive(Clone)] pub struct HostFunction { pub(crate) ty: tinywasm_types::FuncType, - pub(crate) func: Arc<dyn Fn(&mut crate::Store, &[WasmValue]) -> Result<Vec<WasmValue>> + 'static + Send + Sync>, + pub(crate) func: HostFuncInner, } +pub(crate) type HostFuncInner = + Arc<dyn Fn(&mut crate::Store, &[WasmValue]) -> Result<Vec<WasmValue>> + 'static + Send + Sync>; + impl Debug for HostFunction { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - f.debug_struct("HostFunction") - .field("ty", &self.ty) - .field("func", &"...") - .finish() + f.debug_struct("HostFunction").field("ty", &self.ty).field("func", &"...").finish() } } -#[derive(Debug)] +#[derive(Debug, Clone)] #[non_exhaustive] /// An external value pub enum Extern { @@ -49,31 +64,29 @@ pub enum Extern { Memory(ExternMemory), /// A function - Func(HostFunction), + Func(Function), } /// A function -#[derive(Debug)] -pub struct ExternFunc { - pub(crate) inner: HostFunction, -} +#[derive(Debug, Clone)] +pub struct ExternFunc(pub(crate) HostFunction); /// A global value -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ExternGlobal { pub(crate) ty: GlobalType, pub(crate) val: WasmValue, } /// A table -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ExternTable { pub(crate) ty: TableType, pub(crate) val: WasmValue, } /// A memory -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ExternMemory { pub(crate) ty: MemoryType, } @@ -81,13 +94,7 @@ pub struct ExternMemory { impl Extern { /// Create a new global import pub fn global(val: WasmValue, mutable: bool) -> Self { - Self::Global(ExternGlobal { - ty: GlobalType { - ty: val.val_type(), - mutable, - }, - val, - }) + Self::Global(ExternGlobal { ty: GlobalType { ty: val.val_type(), mutable }, val }) } /// Create a new table import @@ -110,10 +117,7 @@ impl Extern { func(store, &args) }; - Self::Func(HostFunction { - func: Arc::new(inner_func), - ty: ty.clone(), - }) + Self::Func(Function::Host(HostFunction { func: Arc::new(inner_func), ty: ty.clone() })) } /// Create a new typed function import @@ -128,15 +132,9 @@ impl Extern { Ok(result.into_wasm_value_tuple()) }; - let ty = tinywasm_types::FuncType { - params: P::val_types(), - results: R::val_types(), - }; + let ty = tinywasm_types::FuncType { params: P::val_types(), results: R::val_types() }; - Self::Func(HostFunction { - func: Arc::new(inner_func), - ty: ty.clone(), - }) + Self::Func(Function::Host(HostFunction { func: Arc::new(inner_func), ty })) } pub(crate) fn kind(&self) -> ExternalKind { @@ -156,6 +154,12 @@ pub struct ExternName { name: String, } +impl From<&Import> for ExternName { + fn from(import: &Import) -> Self { + Self { module: import.module.to_string(), name: import.name.to_string() } + } +} + #[derive(Debug, Default)] /// Imports for a module instance pub struct Imports { @@ -163,30 +167,31 @@ pub struct Imports { modules: BTreeMap<String, ModuleInstanceAddr>, } -pub(crate) struct LinkedImports { - // externs that were defined and need to be instantiated - pub(crate) externs: BTreeMap<ExternName, Extern>, +pub(crate) enum ResolvedExtern<S, V> { + // already in the store + Store(S), - // externs that were linked to other modules and already exist in the store - pub(crate) linked_externs: BTreeMap<ExternName, ExternVal>, + // needs to be added to the store, provided value + Extern(V), } -impl LinkedImports { - pub(crate) fn get(&self, module: &str, name: &str) -> Option<&Extern> { - self.externs.get(&ExternName { - module: module.to_string(), - name: name.to_string(), - }) +pub(crate) struct ResolvedImports { + pub(crate) globals: Vec<GlobalAddr>, + pub(crate) tables: Vec<TableAddr>, + pub(crate) mems: Vec<MemAddr>, + pub(crate) funcs: Vec<FuncAddr>, +} + +impl ResolvedImports { + pub(crate) fn new() -> Self { + Self { globals: Vec::new(), tables: Vec::new(), mems: Vec::new(), funcs: Vec::new() } } } impl Imports { /// Create a new empty import set pub fn new() -> Self { - Imports { - values: BTreeMap::new(), - modules: BTreeMap::new(), - } + Imports { values: BTreeMap::new(), modules: BTreeMap::new() } } /// Link a module @@ -199,87 +204,106 @@ impl Imports { /// Define an import pub fn define(&mut self, module: &str, name: &str, value: Extern) -> Result<&mut Self> { - self.values.insert( - ExternName { - module: module.to_string(), - name: name.to_string(), - }, - value, - ); + self.values.insert(ExternName { module: module.to_string(), name: name.to_string() }, value); Ok(self) } - pub(crate) fn link(self, store: &mut crate::Store, module: &crate::Module) -> Result<LinkedImports> { - let mut links = BTreeMap::new(); - - for import in module.data.imports.iter() { - if let Some(i) = self.values.get(&ExternName { - module: import.module.to_string(), - name: import.name.to_string(), - }) { - if i.kind() != (&import.kind).into() { - return Err(crate::Error::InvalidImportType { - module: import.module.to_string(), - name: import.name.to_string(), - }); - } + pub(crate) fn take( + &mut self, + _store: &mut crate::Store, + import: &Import, + ) -> Option<ResolvedExtern<ExternVal, Extern>> { + let name = ExternName::from(import); + log::error!("provided externs: {:?}", self.values.keys()); + if let Some(v) = self.values.get(&name) { + return Some(ResolvedExtern::Extern(v.clone())); + } + log::error!("failed to resolve import: {:?}", name); + // TODO: + // if let Some(addr) = self.modules.get(&name.module) { + // let instance = store.get_module_instance(*addr)?; + // let exports = instance.exports(); - continue; - } + // let export = exports.get_untyped(&import.name)?; + // let addr = match export.kind { + // ExternalKind::Global(g) => ExternVal::Global(), + // }; - let module_addr = - self.modules - .get(&import.module.to_string()) - .ok_or_else(|| crate::Error::MissingImport { - module: import.module.to_string(), - name: import.name.to_string(), - })?; + // return Some(ResolvedExtern::Store()); + // } - let module = - store - .get_module_instance(*module_addr) - .ok_or_else(|| crate::Error::CouldNotResolveImport { - module: import.module.to_string(), - name: import.name.to_string(), - })?; + None + } - let export = - module - .exports() - .get_untyped(&import.name) - .ok_or_else(|| crate::Error::CouldNotResolveImport { - module: import.module.to_string(), - name: import.name.to_string(), - })?; + pub(crate) fn link( + mut self, + store: &mut crate::Store, + module: &crate::Module, + idx: ModuleInstanceAddr, + ) -> Result<ResolvedImports> { + let mut imports = ResolvedImports::new(); - // validate import - if export.kind != (&import.kind).into() { - return Err(crate::Error::InvalidImportType { + for import in module.data.imports.iter() { + let Some(val) = self.take(store, import) else { + return Err(crate::Error::MissingImport { module: import.module.to_string(), name: import.name.to_string(), }); - } - - let val = match export.kind { - ExternalKind::Func => ExternVal::Func(export.index), - ExternalKind::Global => ExternVal::Global(export.index), - ExternalKind::Table => ExternVal::Table(export.index), - ExternalKind::Memory => ExternVal::Mem(export.index), }; - links.insert( - ExternName { - module: import.module.to_string(), - name: import.name.to_string(), - }, - val, - ); + match val { + // A link to something that needs to be added to the store + ResolvedExtern::Extern(ex) => { + // check if the kind matches + let kind = ex.kind(); + if kind != (&import.kind).into() { + return Err(crate::Error::InvalidImportType { + module: import.module.to_string(), + name: import.name.to_string(), + }); + } + + // TODO: check if the type matches + + // add it to the store and get the address + let addr = match ex { + Extern::Global(g) => store.add_global(g.ty, g.val.into(), idx)?, + Extern::Table(t) => store.add_table(t.ty, idx)?, + Extern::Memory(m) => store.add_mem(m.ty, idx)?, + Extern::Func(f) => store.add_func(f, idx)?, + }; + + // store the link + match &kind { + ExternalKind::Global => imports.globals.push(addr), + ExternalKind::Table => imports.tables.push(addr), + ExternalKind::Memory => imports.mems.push(addr), + ExternalKind::Func => imports.funcs.push(addr), + } + } + + // A link to something already in the store + ResolvedExtern::Store(val) => { + // check if the kind matches + if val.kind() != (&import.kind).into() { + return Err(crate::Error::InvalidImportType { + module: import.module.to_string(), + name: import.name.to_string(), + }); + } + + // TODO: check if the type matches + + match val { + ExternVal::Global(g) => imports.globals.push(g), + ExternVal::Table(t) => imports.tables.push(t), + ExternVal::Mem(m) => imports.mems.push(m), + ExternVal::Func(f) => imports.funcs.push(f), + } + } + } } - // TODO: link to other modules (currently only direct imports are supported) - Ok(LinkedImports { - externs: self.values, - linked_externs: links, - }) + Ok(imports) } } diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index ad1b53c..fb5f5b3 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -1,11 +1,12 @@ use alloc::{boxed::Box, format, string::ToString, sync::Arc, vec::Vec}; use tinywasm_types::{ - DataAddr, ElemAddr, ExternalKind, FuncAddr, FuncType, GlobalAddr, Import, MemAddr, ModuleInstanceAddr, TableAddr, + DataAddr, ElemAddr, Export, ExternVal, ExternalKind, FuncAddr, FuncType, GlobalAddr, Import, MemAddr, + ModuleInstanceAddr, TableAddr, }; use crate::{ func::{FromWasmValueTuple, IntoWasmValueTuple}, - Error, ExportInstance, FuncHandle, Imports, Module, Result, Store, TypedFuncHandle, + Error, FuncHandle, Imports, Module, Result, Store, TypedFuncHandle, }; /// A WebAssembly Module Instance @@ -32,7 +33,7 @@ pub(crate) struct ModuleInstanceInner { pub(crate) func_start: Option<FuncAddr>, pub(crate) imports: Box<[Import]>, - pub(crate) exports: ExportInstance, + pub(crate) exports: Box<[Export]>, } impl ModuleInstance { @@ -52,37 +53,40 @@ impl ModuleInstance { let idx = store.next_module_instance_idx(); let imports = imports.unwrap_or_default(); - // TODO: doesn't link other modules yet - let linked_imports = imports.link(store, &module)?; - let global_addrs = store.add_globals(module.data.globals.into(), &module.data.imports, &linked_imports, idx)?; + let mut addrs = imports.link(store, &module, idx)?; + let data = module.data; - // TODO: imported functions missing - let func_addrs = store.add_funcs(module.data.funcs.into(), idx); + addrs.globals.extend(store.init_globals(data.globals.into(), idx)?); + addrs.funcs.extend(store.init_funcs(data.funcs.into(), idx)?); + addrs.tables.extend(store.init_tables(data.table_types.into(), idx)?); - let table_addrs = store.add_tables(module.data.table_types.into(), idx); - let mem_addrs = store.add_mems(module.data.memory_types.into(), idx)?; + log::info!("init_mems: {:?}", addrs.mems); + addrs.mems.extend(store.init_mems(data.memory_types.into(), idx)?); + log::info!("init_mems2: {:?}", addrs.mems); + log::info!("init_mems g: {:?}", store.data.mems.len()); - // TODO: active/declared elems need to be initialized - let elem_addrs = store.add_elems(module.data.elements.into(), idx)?; + let elem_addrs = store.init_elems(&addrs.tables, data.elements.into(), idx)?; + log::info!("init_elems: {:?}", addrs.mems); - // TODO: active data segments need to be initialized - let data_addrs = store.add_datas(module.data.data.into(), idx)?; + let data_addrs = store.init_datas(&addrs.mems, data.data.into(), idx)?; + log::info!("init_datas: {:?}", addrs.mems); let instance = ModuleInstanceInner { store_id: store.id(), idx, - types: module.data.func_types, - func_addrs, - table_addrs, - mem_addrs, - global_addrs, + types: data.func_types, + + func_addrs: addrs.funcs, + table_addrs: addrs.tables, + mem_addrs: addrs.mems, + global_addrs: addrs.globals, elem_addrs, data_addrs, - func_start: module.data.start_func, - imports: module.data.imports, - exports: crate::ExportInstance(module.data.exports), + func_start: data.start_func, + imports: data.imports, + exports: data.exports, }; let instance = ModuleInstance::new(instance); @@ -92,8 +96,17 @@ impl ModuleInstance { } /// Get the module's exports - pub fn exports(&self) -> &ExportInstance { - &self.0.exports + pub(crate) fn export(&self, name: &str) -> Option<ExternVal> { + let exports = self.0.exports.iter().find(|e| e.name == name.into())?; + let kind = exports.kind.clone(); + let addr = match kind { + ExternalKind::Func => self.0.func_addrs.get(exports.index as usize)?, + ExternalKind::Table => self.0.table_addrs.get(exports.index as usize)?, + ExternalKind::Memory => self.0.mem_addrs.get(exports.index as usize)?, + ExternalKind::Global => self.0.global_addrs.get(exports.index as usize)?, + }; + + Some(ExternVal::new(kind, *addr)) } pub(crate) fn func_addrs(&self) -> &[FuncAddr] { @@ -113,26 +126,22 @@ impl ModuleInstance { } pub(crate) fn func_ty(&self, addr: FuncAddr) -> &FuncType { - &self.0.types[addr as usize] + self.0.types.get(addr as usize).expect("No func type for func, this is a bug") } // resolve a function address to the global store address pub(crate) fn resolve_func_addr(&self, addr: FuncAddr) -> FuncAddr { - self.0.func_addrs[addr as usize] + *self.0.func_addrs.get(addr as usize).expect("No func addr for func, this is a bug") } // resolve a table address to the global store address pub(crate) fn resolve_table_addr(&self, addr: TableAddr) -> TableAddr { - self.0.table_addrs[addr as usize] - } - - pub(crate) fn resolve_elem_addr(&self, addr: ElemAddr) -> ElemAddr { - self.0.elem_addrs[addr as usize] + *self.0.table_addrs.get(addr as usize).expect("No table addr for table, this is a bug") } // resolve a memory address to the global store address pub(crate) fn resolve_mem_addr(&self, addr: MemAddr) -> MemAddr { - self.0.mem_addrs[addr as usize] + *self.0.mem_addrs.get(addr as usize).expect("No mem addr for mem, this is a bug") } // resolve a global address to the global store address @@ -146,23 +155,15 @@ impl ModuleInstance { return Err(Error::InvalidStore); } - let export = self - .0 - .exports - .get(name, ExternalKind::Func) - .ok_or_else(|| Error::Other(format!("Export not found: {}", name)))?; + let export = self.export(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))); + }; - let func_addr = self.0.func_addrs[export.index as usize]; let func_inst = store.get_func(func_addr as usize)?; - let func = func_inst.assert_wasm()?; - let ty = self.0.types[func.ty_addr as usize].clone(); + let ty = func_inst.func.ty(self); - Ok(FuncHandle { - addr: export.index, - module: self.clone(), - name: Some(name.to_string()), - ty, - }) + Ok(FuncHandle { addr: func_addr, module: self.clone(), name: Some(name.to_string()), ty: ty.clone() }) } /// Get a typed exported function by name @@ -172,10 +173,7 @@ impl ModuleInstance { R: FromWasmValueTuple, { let func = self.exported_func_by_name(store, name)?; - Ok(TypedFuncHandle { - func, - marker: core::marker::PhantomData, - }) + Ok(TypedFuncHandle { func, marker: core::marker::PhantomData }) } /// Get the start function of the module @@ -194,30 +192,20 @@ impl ModuleInstance { Some(func_index) => func_index, None => { // alternatively, check for a _start function in the exports - let Some(start) = self.0.exports.get("_start", ExternalKind::Func) else { + let Some(ExternVal::Func(func_addr)) = self.export("_start") else { return Ok(None); }; - start.index + func_addr } }; - let func_addr = self - .0 - .func_addrs - .get(func_index as usize) - .expect("No func addr for start func, this is a bug"); + let func_addr = self.0.func_addrs.get(func_index as usize).expect("No func addr for start func, this is a bug"); let func_inst = store.get_func(*func_addr as usize)?; - let func = func_inst.assert_wasm()?; - let ty = self.0.types[func.ty_addr as usize].clone(); + let ty = func_inst.func.ty(self); - Ok(Some(FuncHandle { - module: self.clone(), - addr: *func_addr, - ty, - name: None, - })) + Ok(Some(FuncHandle { module: self.clone(), addr: *func_addr, ty, name: None })) } /// Invoke the start function of the module diff --git a/crates/tinywasm/src/lib.rs b/crates/tinywasm/src/lib.rs index 0c1863f..64d34df 100644 --- a/crates/tinywasm/src/lib.rs +++ b/crates/tinywasm/src/lib.rs @@ -2,10 +2,7 @@ #![forbid(unsafe_code)] #![doc(test( no_crate_inject, - attr( - deny(warnings, rust_2018_idioms), - allow(dead_code, unused_assignments, unused_variables) - ) + attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_assignments, unused_variables)) ))] #![warn(missing_docs, missing_debug_implementations, rust_2018_idioms, unreachable_pub)] #![cfg_attr(nightly, feature(error_in_core))] @@ -89,9 +86,6 @@ pub use module::Module; mod instance; pub use instance::ModuleInstance; -mod export; -pub use export::ExportInstance; - mod func; pub use func::{FuncHandle, TypedFuncHandle}; diff --git a/crates/tinywasm/src/runtime/executor/macros.rs b/crates/tinywasm/src/runtime/executor/macros.rs index c1bb50f..5b20851 100644 --- a/crates/tinywasm/src/runtime/executor/macros.rs +++ b/crates/tinywasm/src/runtime/executor/macros.rs @@ -63,8 +63,7 @@ macro_rules! mem_store { let val = val as $store_type; let val = val.to_le_bytes(); - mem.borrow_mut() - .store(($arg.offset + addr) as usize, $arg.align as usize, &val)?; + mem.borrow_mut().store(($arg.offset + addr) as usize, $arg.align as usize, &val)?; }}; } @@ -225,9 +224,7 @@ macro_rules! checked_int_arithmetic { return Err(Error::Trap(crate::Trap::DivisionByZero)); } - let result = a_casted - .$op(b_casted) - .ok_or_else(|| Error::Trap(crate::Trap::IntegerOverflow))?; + let result = a_casted.$op(b_casted).ok_or_else(|| Error::Trap(crate::Trap::IntegerOverflow))?; // Cast back to original type if different $stack.values.push((result as $from).into()); diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index 5e191cc..1072577 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -16,7 +16,6 @@ use traits::*; impl DefaultRuntime { pub(crate) fn exec(&self, store: &mut Store, stack: &mut Stack, module: ModuleInstance) -> Result<()> { - log::debug!("exports: {:?}", module.exports()); log::debug!("func_addrs: {:?}", module.func_addrs()); log::debug!("func_ty_addrs: {:?}", module.func_ty_addrs().len()); log::debug!("store funcs: {:?}", store.data.funcs.len()); @@ -26,7 +25,7 @@ impl DefaultRuntime { // The function to execute, gets updated from ExecResult::Call let mut func_inst = store.get_func(cf.func_ptr)?.clone(); - let mut wasm_func = func_inst.assert_wasm()?; + let mut wasm_func = func_inst.assert_wasm().expect("exec expected wasm function"); let mut instrs = &wasm_func.instructions; // TODO: we might be able to index into the instructions directly @@ -37,7 +36,7 @@ impl DefaultRuntime { ExecResult::Call => { cf = stack.call_stack.pop()?; func_inst = store.get_func(cf.func_ptr)?.clone(); - wasm_func = func_inst.assert_wasm()?; + wasm_func = func_inst.assert_wasm().expect("call expected wasm function"); instrs = &wasm_func.instructions; continue; } @@ -129,14 +128,24 @@ fn exec_one( // prepare the call frame let func_idx = module.resolve_func_addr(*v); let func_inst = store.get_func(func_idx as usize)?; - let func = func_inst.assert_wasm()?; + let func = match &func_inst.func { + crate::Function::Wasm(ref f) => f, + crate::Function::Host(host_func) => { + let func = host_func.func.clone(); + let params = stack.values.pop_params(&host_func.ty.params)?; + let res = (func)(store, ¶ms)?; + stack.values.extend_from_typed(&res); + return Ok(ExecResult::Ok); + } + }; + let func_ty = module.func_ty(func.ty_addr); debug!("params: {:?}", func_ty.params); debug!("stack: {:?}", stack.values); let params = stack.values.pop_n(func_ty.params.len())?; - let call_frame = CallFrame::new_raw(*v as usize, ¶ms, func.locals.to_vec()); + let call_frame = CallFrame::new_raw(func_idx as usize, ¶ms, func.locals.to_vec()); // push the call frame cf.instr_ptr += 1; // skip the call instruction @@ -158,15 +167,22 @@ fn exec_one( // prepare the call frame let func_inst = store.get_func(func_addr as usize)?; - let func = func_inst.assert_wasm()?; + let func = match &func_inst.func { + crate::Function::Wasm(ref f) => f, + crate::Function::Host(host_func) => { + let func = host_func.func.clone(); + let params = stack.values.pop_params(&host_func.ty.params)?; + let res = (func)(store, ¶ms)?; + stack.values.extend_from_typed(&res); + return Ok(ExecResult::Ok); + } + }; let func_ty = module.func_ty(func.ty_addr); if func_ty != call_ty { - return Err(Trap::IndirectCallTypeMismatch { - actual: func_ty.clone(), - expected: call_ty.clone(), - } - .into()); + return Err( + Trap::IndirectCallTypeMismatch { actual: func_ty.clone(), expected: call_ty.clone() }.into() + ); } let params = stack.values.pop_n(func_ty.params.len())?; @@ -569,10 +585,7 @@ fn exec_one( i => { log::error!("unimplemented instruction: {:?}", i); - return Err(Error::UnsupportedFeature(alloc::format!( - "unimplemented instruction: {:?}", - i - ))); + return Err(Error::UnsupportedFeature(alloc::format!("unimplemented instruction: {:?}", i))); } }; diff --git a/crates/tinywasm/src/runtime/stack/value_stack.rs b/crates/tinywasm/src/runtime/stack/value_stack.rs index 10054bc..1021289 100644 --- a/crates/tinywasm/src/runtime/stack/value_stack.rs +++ b/crates/tinywasm/src/runtime/stack/value_stack.rs @@ -2,6 +2,7 @@ use core::ops::Range; use crate::{runtime::RawWasmValue, Error, Result}; use alloc::vec::Vec; +use tinywasm_types::{ValType, WasmValue}; // minimum stack size pub(crate) const STACK_SIZE: usize = 1024; @@ -16,10 +17,7 @@ pub(crate) struct ValueStack { impl Default for ValueStack { fn default() -> Self { - Self { - stack: Vec::with_capacity(STACK_SIZE), - top: 0, - } + Self { stack: Vec::with_capacity(STACK_SIZE), top: 0 } } } @@ -31,6 +29,12 @@ impl ValueStack { } #[inline] + pub(crate) fn extend_from_typed(&mut self, values: &[WasmValue]) { + self.top += values.len(); + self.stack.extend(values.iter().map(|v| RawWasmValue::from(*v))); + } + + #[inline] pub(crate) fn len(&self) -> usize { assert!(self.top <= self.stack.len()); self.top @@ -38,10 +42,7 @@ impl ValueStack { pub(crate) fn truncate_keep(&mut self, n: usize, end_keep: usize) { let total_to_keep = n + end_keep; - assert!( - self.top >= total_to_keep, - "Total to keep should be less than or equal to self.top" - ); + assert!(self.top >= total_to_keep, "Total to keep should be less than or equal to self.top"); let current_size = self.stack.len(); if current_size <= total_to_keep { @@ -79,9 +80,19 @@ impl ValueStack { self.stack.pop().ok_or(Error::StackUnderflow) } + #[inline] + pub(crate) fn pop_params(&mut self, types: &[ValType]) -> Result<Vec<WasmValue>> { + let n = types.len(); + if self.top < n { + return Err(Error::StackUnderflow); + } + self.top -= n; + let res = self.stack.drain(self.top..).rev().map(|v| v.attach_type(types[n - 1])).collect(); + Ok(res) + } + pub(crate) fn break_to(&mut self, new_stack_size: usize, result_count: usize) { - self.stack - .copy_within((self.top - result_count)..self.top, new_stack_size); + self.stack.copy_within((self.top - result_count)..self.top, new_stack_size); self.top = new_stack_size + result_count; self.stack.truncate(self.top); } diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 6293cca..e9908d2 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -1,19 +1,14 @@ -#![allow(dead_code)] // TODO: remove this - use core::{ cell::RefCell, sync::atomic::{AtomicUsize, Ordering}, }; use alloc::{format, rc::Rc, string::ToString, vec, vec::Vec}; -use tinywasm_types::{ - Addr, Data, Element, ElementKind, FuncAddr, Global, GlobalType, Import, Instruction, MemAddr, MemoryArch, - MemoryType, ModuleInstanceAddr, TableAddr, TableType, TypeAddr, ValType, WasmFunction, -}; +use tinywasm_types::*; use crate::{ runtime::{self, DefaultRuntime}, - Error, Extern, Function, LinkedImports, ModuleInstance, RawWasmValue, Result, Trap, + Error, Function, ModuleInstance, RawWasmValue, Result, Trap, }; // global store id counter @@ -49,7 +44,7 @@ impl Store { Self::default() } - pub(crate) fn get_module_instance(&self, addr: ModuleInstanceAddr) -> Option<&ModuleInstance> { + pub(crate) fn _get_module_instance(&self, addr: ModuleInstanceAddr) -> Option<&ModuleInstance> { self.module_instances.get(addr as usize) } @@ -106,52 +101,45 @@ impl Store { self.module_instance_count as ModuleInstanceAddr } - /// Initialize the store with global state from the given module pub(crate) fn add_instance(&mut self, instance: ModuleInstance) -> Result<()> { + assert!(instance.id() == self.module_instance_count as ModuleInstanceAddr); self.module_instances.push(instance); self.module_instance_count += 1; Ok(()) } /// Add functions to the store, returning their addresses in the store - pub(crate) fn add_funcs(&mut self, funcs: Vec<WasmFunction>, idx: ModuleInstanceAddr) -> Vec<FuncAddr> { + pub(crate) fn init_funcs(&mut self, funcs: Vec<WasmFunction>, idx: ModuleInstanceAddr) -> Result<Vec<FuncAddr>> { let func_count = self.data.funcs.len(); let mut func_addrs = Vec::with_capacity(func_count); for (i, func) in funcs.into_iter().enumerate() { - self.data.funcs.push(Rc::new(FunctionInstance { - func: Function::Wasm(func), - owner: idx, - })); + self.data.funcs.push(Rc::new(FunctionInstance { func: Function::Wasm(func), _owner: idx })); func_addrs.push((i + func_count) as FuncAddr); } - func_addrs + Ok(func_addrs) } /// Add tables to the store, returning their addresses in the store - pub(crate) fn add_tables(&mut self, tables: Vec<TableType>, idx: ModuleInstanceAddr) -> Vec<TableAddr> { + pub(crate) fn init_tables(&mut self, tables: Vec<TableType>, idx: ModuleInstanceAddr) -> Result<Vec<TableAddr>> { let table_count = self.data.tables.len(); let mut table_addrs = Vec::with_capacity(table_count); for (i, table) in tables.into_iter().enumerate() { - self.data - .tables - .push(Rc::new(RefCell::new(TableInstance::new(table, idx)))); - + self.data.tables.push(Rc::new(RefCell::new(TableInstance::new(table, idx)))); table_addrs.push((i + table_count) as TableAddr); } - table_addrs + Ok(table_addrs) } /// Add memories to the store, returning their addresses in the store - pub(crate) fn add_mems(&mut self, mems: Vec<MemoryType>, idx: ModuleInstanceAddr) -> Result<Vec<MemAddr>> { + pub(crate) fn init_mems(&mut self, mems: Vec<MemoryType>, idx: ModuleInstanceAddr) -> Result<Vec<MemAddr>> { let mem_count = self.data.mems.len(); let mut mem_addrs = Vec::with_capacity(mem_count); for (i, mem) in mems.into_iter().enumerate() { if let MemoryArch::I64 = mem.arch { return Err(Error::UnsupportedFeature("64-bit memories".to_string())); } - self.data - .mems - .push(Rc::new(RefCell::new(MemoryInstance::new(mem, idx)))); + log::info!("adding memory: {:?}", mem); + self.data.mems.push(Rc::new(RefCell::new(MemoryInstance::new(mem, idx)))); mem_addrs.push((i + mem_count) as MemAddr); } @@ -159,53 +147,9 @@ impl Store { } /// Add globals to the store, returning their addresses in the store - pub(crate) fn add_globals( - &mut self, - globals: Vec<Global>, - wasm_imports: &[Import], - user_imports: &LinkedImports, - idx: ModuleInstanceAddr, - ) -> Result<Vec<Addr>> { - // TODO: initialize imported globals - #![allow(clippy::unnecessary_filter_map)] // this is cleaner - let imported_globals = wasm_imports - .iter() - .filter_map(|import| match &import.kind { - tinywasm_types::ImportKind::Global(_) => Some(import), - _ => None, - }) - .map(|import| { - let Some(global) = user_imports.get(&import.module, &import.name) else { - return Err(Error::Other(format!( - "global import not found for {}::{}", - import.module, import.name - ))); - }; - match global { - Extern::Global(global) => Ok(global), - _ => Err(Error::Other(format!( - "expected global import for {}::{}", - import.module, import.name - ))), - } - }) - .collect::<Result<Vec<_>>>()?; - + pub(crate) fn init_globals(&mut self, globals: Vec<Global>, idx: ModuleInstanceAddr) -> Result<Vec<Addr>> { let global_count = self.data.globals.len(); let mut global_addrs = Vec::with_capacity(global_count); - log::debug!("globals: {:?}", globals); - - // first add the imported globals - for (i, global) in imported_globals.iter().enumerate() { - self.data.globals.push(Rc::new(RefCell::new(GlobalInstance::new( - global.ty, - global.val.into(), - idx, - )))); - global_addrs.push((i + global_count) as Addr); - } - - // then add the module globals for (i, global) in globals.iter().enumerate() { self.data.globals.push(Rc::new(RefCell::new(GlobalInstance::new( global.ty, @@ -218,43 +162,14 @@ impl Store { Ok(global_addrs) } - pub(crate) fn eval_i32_const(&self, const_instr: &tinywasm_types::ConstInstruction) -> Result<i32> { - use tinywasm_types::ConstInstruction::*; - let val = match const_instr { - I32Const(i) => *i, - GlobalGet(addr) => { - let addr = *addr as usize; - let global = self.data.globals[addr].clone(); - let val = global.borrow().value; - i32::from(val) - } - _ => return Err(Error::Other("expected i32".to_string())), - }; - Ok(val) - } - - pub(crate) fn eval_const(&self, const_instr: &tinywasm_types::ConstInstruction) -> Result<RawWasmValue> { - use tinywasm_types::ConstInstruction::*; - let val = match const_instr { - F32Const(f) => RawWasmValue::from(*f), - F64Const(f) => RawWasmValue::from(*f), - I32Const(i) => RawWasmValue::from(*i), - I64Const(i) => RawWasmValue::from(*i), - GlobalGet(addr) => { - let addr = *addr as usize; - let global = self.data.globals[addr].clone(); - let val = global.borrow().value; - val - } - RefNull(v) => v.default_value().into(), - RefFunc(idx) => RawWasmValue::from(*idx as i64), - }; - Ok(val) - } - /// Add elements to the store, returning their addresses in the store /// Should be called after the tables have been added - pub(crate) fn add_elems(&mut self, elems: Vec<Element>, idx: ModuleInstanceAddr) -> Result<Vec<Addr>> { + pub(crate) fn init_elems( + &mut self, + table_addrs: &[TableAddr], + elems: Vec<Element>, + idx: ModuleInstanceAddr, + ) -> Result<Vec<Addr>> { let elem_count = self.data.elems.len(); let mut elem_addrs = Vec::with_capacity(elem_count); for (i, elem) in elems.into_iter().enumerate() { @@ -281,13 +196,17 @@ impl Store { // this one is active, so we need to initialize it (essentially a `table.init` instruction) ElementKind::Active { offset, table } => { let offset = self.eval_i32_const(&offset)?; + let table_addr = table_addrs + .get(table as usize) + .copied() + .ok_or_else(|| Error::Other(format!("table {} not found for element {}", table, i)))?; // a. Let n be the length of the vector elem[i].init // b. Execute the instruction sequence einstrs // c. Execute the instruction i32.const 0 // d. Execute the instruction i32.const n // e. Execute the instruction table.init tableidx i - if let Some(table) = self.data.tables.get_mut(table as usize) { + if let Some(table) = self.data.tables.get_mut(table_addr as usize) { table.borrow_mut().init(offset, &init)?; } else { log::error!("table {} not found", table); @@ -306,7 +225,12 @@ impl Store { } /// Add data to the store, returning their addresses in the store - pub(crate) fn add_datas(&mut self, datas: Vec<Data>, idx: ModuleInstanceAddr) -> Result<Vec<Addr>> { + pub(crate) fn init_datas( + &mut self, + mem_addrs: &[MemAddr], + datas: Vec<Data>, + idx: ModuleInstanceAddr, + ) -> Result<Vec<Addr>> { let data_count = self.data.datas.len(); let mut data_addrs = Vec::with_capacity(data_count); for (i, data) in datas.into_iter().enumerate() { @@ -315,11 +239,14 @@ impl Store { Active { mem: mem_addr, offset } => { // a. Assert: memidx == 0 if mem_addr != 0 { - return Err(Error::UnsupportedFeature( - "data segments for non-zero memories".to_string(), - )); + return Err(Error::UnsupportedFeature("data segments for non-zero memories".to_string())); } + let mem_addr = mem_addrs + .get(mem_addr as usize) + .copied() + .ok_or_else(|| Error::Other(format!("memory {} not found for data segment {}", mem_addr, i)))?; + let offset = self.eval_i32_const(&offset)?; let mem = @@ -329,7 +256,7 @@ impl Store { mem.borrow_mut().store(offset as usize, 0, &data.data)?; - // drop the date + // drop the data continue; } Passive => {} @@ -341,35 +268,78 @@ impl Store { Ok(data_addrs) } + pub(crate) fn add_global(&mut self, ty: GlobalType, value: RawWasmValue, idx: ModuleInstanceAddr) -> Result<Addr> { + self.data.globals.push(Rc::new(RefCell::new(GlobalInstance::new(ty, value, idx)))); + Ok(self.data.globals.len() as Addr - 1) + } + + pub(crate) fn add_table(&mut self, table: TableType, idx: ModuleInstanceAddr) -> Result<TableAddr> { + self.data.tables.push(Rc::new(RefCell::new(TableInstance::new(table, idx)))); + Ok(self.data.tables.len() as TableAddr - 1) + } + + pub(crate) fn add_mem(&mut self, mem: MemoryType, idx: ModuleInstanceAddr) -> Result<MemAddr> { + if let MemoryArch::I64 = mem.arch { + return Err(Error::UnsupportedFeature("64-bit memories".to_string())); + } + self.data.mems.push(Rc::new(RefCell::new(MemoryInstance::new(mem, idx)))); + Ok(self.data.mems.len() as MemAddr - 1) + } + + pub(crate) fn add_func(&mut self, func: Function, idx: ModuleInstanceAddr) -> Result<FuncAddr> { + self.data.funcs.push(Rc::new(FunctionInstance { func, _owner: idx })); + Ok(self.data.funcs.len() as FuncAddr - 1) + } + + /// Evaluate a constant expression, only supporting i32 globals and i32.const + pub(crate) fn eval_i32_const(&self, const_instr: &tinywasm_types::ConstInstruction) -> Result<i32> { + use tinywasm_types::ConstInstruction::*; + let val = match const_instr { + I32Const(i) => *i, + GlobalGet(addr) => { + let addr = *addr as usize; + let global = self.data.globals[addr].clone(); + let val = global.borrow().value; + i32::from(val) + } + _ => return Err(Error::Other("expected i32".to_string())), + }; + Ok(val) + } + + /// Evaluate a constant expression + pub(crate) fn eval_const(&self, const_instr: &tinywasm_types::ConstInstruction) -> Result<RawWasmValue> { + use tinywasm_types::ConstInstruction::*; + let val = match const_instr { + F32Const(f) => RawWasmValue::from(*f), + F64Const(f) => RawWasmValue::from(*f), + I32Const(i) => RawWasmValue::from(*i), + I64Const(i) => RawWasmValue::from(*i), + GlobalGet(addr) => { + let addr = *addr as usize; + let global = self.data.globals[addr].clone(); + let val = global.borrow().value; + val + } + RefNull(v) => v.default_value().into(), + RefFunc(idx) => RawWasmValue::from(*idx as i64), + }; + Ok(val) + } + /// Get the function at the actual index in the store pub(crate) fn get_func(&self, addr: usize) -> Result<&Rc<FunctionInstance>> { - self.data - .funcs - .get(addr) - .ok_or_else(|| Error::Other(format!("function {} not found", addr))) + self.data.funcs.get(addr).ok_or_else(|| Error::Other(format!("function {} not found", addr))) } /// Get the memory at the actual index in the store pub(crate) fn get_mem(&self, addr: usize) -> Result<&Rc<RefCell<MemoryInstance>>> { - self.data - .mems - .get(addr) - .ok_or_else(|| Error::Other(format!("memory {} not found", addr))) + self.data.mems.get(addr).ok_or_else(|| Error::Other(format!("memory {} not found", addr))) } /// Get the table at the actual index in the store pub(crate) fn get_table(&self, addr: usize) -> Result<&Rc<RefCell<TableInstance>>> { - self.data - .tables - .get(addr) - .ok_or_else(|| Error::Other(format!("table {} not found", addr))) - } - - pub(crate) fn get_elem(&self, addr: usize) -> Result<&ElemInstance> { - self.data - .elems - .get(addr) - .ok_or_else(|| Error::Other(format!("element {} not found", addr))) + self.data.tables.get(addr).ok_or_else(|| Error::Other(format!("table {} not found", addr))) } /// Get the global at the actual index in the store @@ -396,7 +366,7 @@ impl Store { /// See <https://webassembly.github.io/spec/core/exec/runtime.html#function-instances> pub struct FunctionInstance { pub(crate) func: Function, - pub(crate) owner: ModuleInstanceAddr, // index into store.module_instances, none for host functions + pub(crate) _owner: ModuleInstanceAddr, // index into store.module_instances, none for host functions } // TODO: check if this actually helps @@ -421,25 +391,18 @@ impl FunctionInstance { /// See <https://webassembly.github.io/spec/core/exec/runtime.html#table-instances> #[derive(Debug)] pub(crate) struct TableInstance { - pub(crate) kind: TableType, pub(crate) elements: Vec<Addr>, - pub(crate) owner: ModuleInstanceAddr, // index into store.module_instances + pub(crate) _kind: TableType, + pub(crate) _owner: ModuleInstanceAddr, // index into store.module_instances } impl TableInstance { pub(crate) fn new(kind: TableType, owner: ModuleInstanceAddr) -> Self { - Self { - elements: vec![0; kind.size_initial as usize], - kind, - owner, - } + Self { elements: vec![0; kind.size_initial as usize], _kind: kind, _owner: owner } } pub(crate) fn get(&self, addr: usize) -> Result<Addr> { - self.elements - .get(addr) - .copied() - .ok_or_else(|| Trap::UndefinedElement { index: addr }.into()) + self.elements.get(addr).copied().ok_or_else(|| Trap::UndefinedElement { index: addr }.into()) } pub(crate) fn set(&mut self, addr: usize, value: Addr) -> Result<()> { @@ -457,20 +420,11 @@ impl TableInstance { pub(crate) fn init(&mut self, offset: i32, init: &[Addr]) -> Result<()> { let offset = offset as usize; let end = offset.checked_add(init.len()).ok_or_else(|| { - Error::Trap(crate::Trap::TableOutOfBounds { - offset, - len: init.len(), - max: self.elements.len(), - }) + Error::Trap(crate::Trap::TableOutOfBounds { offset, len: init.len(), max: self.elements.len() }) })?; if end > self.elements.len() || end < offset { - return Err(crate::Trap::TableOutOfBounds { - offset, - len: init.len(), - max: self.elements.len(), - } - .into()); + return Err(crate::Trap::TableOutOfBounds { offset, len: init.len(), max: self.elements.len() }.into()); } self.elements[offset..end].copy_from_slice(init); @@ -490,7 +444,7 @@ pub(crate) struct MemoryInstance { pub(crate) kind: MemoryType, pub(crate) data: Vec<u8>, pub(crate) page_count: usize, - pub(crate) owner: ModuleInstanceAddr, // index into store.module_instances + pub(crate) _owner: ModuleInstanceAddr, // index into store.module_instances } impl MemoryInstance { @@ -502,17 +456,13 @@ impl MemoryInstance { kind, data: vec![0; PAGE_SIZE * kind.page_count_initial as usize], page_count: kind.page_count_initial as usize, - owner, + _owner: owner, } } pub(crate) fn store(&mut self, addr: usize, _align: usize, data: &[u8]) -> Result<()> { let end = addr.checked_add(data.len()).ok_or_else(|| { - Error::Trap(crate::Trap::MemoryOutOfBounds { - offset: addr, - len: data.len(), - max: self.data.len(), - }) + Error::Trap(crate::Trap::MemoryOutOfBounds { offset: addr, len: data.len(), max: self.data.len() }) })?; if end > self.data.len() || end < addr { @@ -533,20 +483,12 @@ impl MemoryInstance { } pub(crate) fn load(&self, addr: usize, _align: usize, len: usize) -> Result<&[u8]> { - let end = addr.checked_add(len).ok_or_else(|| { - Error::Trap(crate::Trap::MemoryOutOfBounds { - offset: addr, - len, - max: self.max_pages(), - }) - })?; + let end = addr + .checked_add(len) + .ok_or_else(|| Error::Trap(crate::Trap::MemoryOutOfBounds { offset: addr, len, max: self.max_pages() }))?; if end > self.data.len() { - return Err(Error::Trap(crate::Trap::MemoryOutOfBounds { - offset: addr, - len, - max: self.data.len(), - })); + return Err(Error::Trap(crate::Trap::MemoryOutOfBounds { offset: addr, len, max: self.data.len() })); } // WebAssembly doesn't require alignment for loads @@ -590,14 +532,14 @@ impl MemoryInstance { /// See <https://webassembly.github.io/spec/core/exec/runtime.html#global-instances> #[derive(Debug)] pub(crate) struct GlobalInstance { - pub(crate) ty: GlobalType, pub(crate) value: RawWasmValue, - owner: ModuleInstanceAddr, // index into store.module_instances + pub(crate) _ty: GlobalType, + pub(crate) _owner: ModuleInstanceAddr, // index into store.module_instances } impl GlobalInstance { pub(crate) fn new(ty: GlobalType, value: RawWasmValue, owner: ModuleInstanceAddr) -> Self { - Self { ty, value, owner } + Self { _ty: ty, value, _owner: owner } } } @@ -606,14 +548,14 @@ impl GlobalInstance { /// See <https://webassembly.github.io/spec/core/exec/runtime.html#element-instances> #[derive(Debug)] pub(crate) struct ElemInstance { - kind: ElementKind, - items: Option<Vec<u32>>, // none is the element was dropped - owner: ModuleInstanceAddr, // index into store.module_instances + _kind: ElementKind, + _items: Option<Vec<u32>>, // none is the element was dropped + _owner: ModuleInstanceAddr, // index into store.module_instances } impl ElemInstance { pub(crate) fn new(kind: ElementKind, owner: ModuleInstanceAddr, items: Option<Vec<u32>>) -> Self { - Self { kind, owner, items } + Self { _kind: kind, _owner: owner, _items: items } } } @@ -622,12 +564,12 @@ impl ElemInstance { /// See <https://webassembly.github.io/spec/core/exec/runtime.html#data-instances> #[derive(Debug)] pub(crate) struct DataInstance { - pub(crate) data: Vec<u8>, - owner: ModuleInstanceAddr, // index into store.module_instances + pub(crate) _data: Vec<u8>, + pub(crate) _owner: ModuleInstanceAddr, // index into store.module_instances } impl DataInstance { pub(crate) fn new(data: Vec<u8>, owner: ModuleInstanceAddr) -> Self { - Self { data, owner } + Self { _data: data, _owner: owner } } } diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 7749a65..824bf55 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,19806,422,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":88,"failed":3},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":76,"failed":15},{"name":"call_indirect.wast","passed":159,"failed":11},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":48,"failed":13},{"name":"elem.wast","passed":76,"failed":23},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":7,"failed":1},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":31,"failed":5},{"name":"global.wast","passed":96,"failed":14},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":232,"failed":9},{"name":"imports.wast","passed":50,"failed":133},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":95,"failed":1},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":143,"failed":5},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":17,"failed":3},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":57,"failed":1},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,19831,397,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":76,"failed":15},{"name":"call_indirect.wast","passed":155,"failed":15},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":69,"failed":30},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":7,"failed":1},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":170,"failed":2},{"name":"func_ptrs.wast","passed":20,"failed":16},{"name":"global.wast","passed":106,"failed":4},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":232,"failed":9},{"name":"imports.wast","passed":70,"failed":113},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":92,"failed":4},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":143,"failed":5},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index 5e3f57b..1f8316a 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -53,12 +53,12 @@ v0.2.0 (19344) </text> <polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="716,345 716,350 "/> <text x="898" y="355" dy="0.76em" text-anchor="middle" font-family="Victor Mono" font-size="12.096774193548388" opacity="1" fill="#000000"> -v0.3.0-alpha.0 (19775) +v0.3.0-alpha.0 (19831) </text> <polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="898,345 898,350 "/> <rect x="266" y="185" width="172" height="159" opacity="0.5" fill="#0000FF" stroke="none"/> -<rect x="630" y="67" width="172" height="277" opacity="0.5" fill="#0000FF" stroke="none"/> +<rect x="812" y="60" width="172" height="284" opacity="0.5" fill="#0000FF" stroke="none"/> <rect x="85" y="212" width="171" height="132" opacity="0.5" fill="#0000FF" stroke="none"/> -<rect x="812" y="61" width="172" height="283" opacity="0.5" fill="#0000FF" stroke="none"/> +<rect x="630" y="67" width="172" height="277" opacity="0.5" fill="#0000FF" stroke="none"/> <rect x="448" y="92" width="172" height="252" opacity="0.5" fill="#0000FF" stroke="none"/> </svg> diff --git a/crates/tinywasm/tests/testsuite/run.rs b/crates/tinywasm/tests/testsuite/run.rs index 5dd42ee..d2eab6c 100644 --- a/crates/tinywasm/tests/testsuite/run.rs +++ b/crates/tinywasm/tests/testsuite/run.rs @@ -57,8 +57,8 @@ impl TestSuite { Ok(()) }); - let print_i64_f64 = Extern::typed_func(|_: &mut tinywasm::Store, args: (i64, f64)| { - log::debug!("print_i64_f64: {}, {}", args.0, args.1); + let print_f64_f64 = Extern::typed_func(|_: &mut tinywasm::Store, args: (f64, f64)| { + log::debug!("print_f64_f64: {}, {}", args.0, args.1); Ok(()) }); @@ -75,9 +75,10 @@ impl TestSuite { .define("spectest", "print_f32", print_f32)? .define("spectest", "print_f64", print_f64)? .define("spectest", "print_i32_f32", print_i32_f32)? - .define("spectest", "print_i64_f64", print_i64_f64)?; + .define("spectest", "print_f64_f64", print_f64_f64)?; for (name, addr) in registered_modules { + log::debug!("registering module: {}", name); imports.link_module(&name, addr)?; } @@ -137,7 +138,7 @@ impl TestSuite { Wat(mut module) => { // TODO: modules are not properly isolated from each other - tests fail because of this otherwise - store = tinywasm::Store::default(); + // store = tinywasm::Store::default(); debug!("got wat module"); let result = catch_unwind_silent(|| { let m = parse_module_bytes(&module.encode().expect("failed to encode module")) diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 069f134..965c97e 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -2,10 +2,7 @@ #![forbid(unsafe_code)] #![doc(test( no_crate_inject, - attr( - deny(warnings, rust_2018_idioms), - allow(dead_code, unused_assignments, unused_variables) - ) + attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_assignments, unused_variables)) ))] #![warn(missing_debug_implementations, rust_2018_idioms, unreachable_pub)] @@ -28,7 +25,7 @@ extern crate alloc; mod instructions; use core::{fmt::Debug, ops::Range}; -use alloc::{boxed::Box, sync::Arc, vec::Vec}; +use alloc::boxed::Box; pub use instructions::*; /// A TinyWasm WebAssembly Module @@ -306,7 +303,7 @@ pub type ModuleInstanceAddr = Addr; /// A WebAssembly External Value. /// /// See <https://webassembly.github.io/spec/core/exec/runtime.html#external-values> -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum ExternVal { Func(FuncAddr), Table(TableAddr), @@ -314,6 +311,26 @@ pub enum ExternVal { Global(GlobalAddr), } +impl ExternVal { + pub fn kind(&self) -> ExternalKind { + match self { + Self::Func(_) => ExternalKind::Func, + Self::Table(_) => ExternalKind::Table, + Self::Mem(_) => ExternalKind::Memory, + Self::Global(_) => ExternalKind::Global, + } + } + + pub fn new(kind: ExternalKind, addr: Addr) -> Self { + match kind { + ExternalKind::Func => Self::Func(addr), + ExternalKind::Table => Self::Table(addr), + ExternalKind::Memory => Self::Mem(addr), + ExternalKind::Global => Self::Global(addr), + } + } +} + /// The type of a WebAssembly Function. /// /// See <https://webassembly.github.io/spec/core/syntax/types.html#function-types> @@ -326,10 +343,7 @@ pub struct FuncType { impl FuncType { /// Get the number of parameters of a function type. pub fn empty() -> Self { - Self { - params: Box::new([]), - results: Box::new([]), - } + Self { params: Box::new([]), results: Box::new([]) } } } @@ -372,19 +386,11 @@ pub struct TableType { impl TableType { pub fn empty() -> Self { - Self { - element_type: ValType::FuncRef, - size_initial: 0, - size_max: None, - } + Self { element_type: ValType::FuncRef, size_initial: 0, size_max: None } } pub fn new(element_type: ValType, size_initial: u32, size_max: Option<u32>) -> Self { - Self { - element_type, - size_initial, - size_max, - } + Self { element_type, size_initial, size_max } } } @@ -400,11 +406,7 @@ pub struct MemoryType { impl MemoryType { pub fn new_32(page_count_initial: u64, page_count_max: Option<u64>) -> Self { - Self { - arch: MemoryArch::I32, - page_count_initial, - page_count_max, - } + Self { arch: MemoryArch::I32, page_count_initial, page_count_max } } // pub fn new_64(page_count_initial: u64, page_count_max: Option<u64>) -> Self { diff --git a/rustfmt.toml b/rustfmt.toml index 94ac875..589b2d2 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1 +1,2 @@ max_width=120 +use_small_heuristics="Max" |
