diff options
| author | Henry Gressmann <mail@henrygressmann.de> | 2024-01-04 22:21:38 +0100 |
|---|---|---|
| committer | Henry Gressmann <mail@henrygressmann.de> | 2024-01-04 22:21:38 +0100 |
| commit | 489abcda7b1e5aedcb12b6c6a768c9046542836c (patch) | |
| tree | 60a3d33f0b055efba029ac43c01a8213cac43df4 /crates | |
| parent | af3caca15123e06879c789a25b6254454cb1a756 (diff) | |
chore: add all instances
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
Diffstat (limited to 'crates')
| -rw-r--r-- | crates/tinywasm/src/instance.rs | 45 | ||||
| -rw-r--r-- | crates/tinywasm/src/module.rs | 38 | ||||
| -rw-r--r-- | crates/tinywasm/src/store.rs | 221 | ||||
| -rw-r--r-- | crates/tinywasm/tests/generated/progress-mvp.svg | 6 |
4 files changed, 233 insertions, 77 deletions
diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index fb09249..86a9296 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -1,5 +1,8 @@ use alloc::{boxed::Box, string::ToString, sync::Arc, vec::Vec}; -use tinywasm_types::{Export, ExternalKind, FuncAddr, FuncType, ModuleInstanceAddr}; +use tinywasm_types::{ + DataAddr, ElmAddr, Export, ExternalKind, FuncAddr, FuncType, GlobalAddr, Import, MemAddr, ModuleInstanceAddr, + TableAddr, +}; use crate::{ func::{FromWasmValueTuple, IntoWasmValueTuple}, @@ -15,19 +18,21 @@ use crate::{ pub struct ModuleInstance(Arc<ModuleInstanceInner>); #[derive(Debug)] -struct ModuleInstanceInner { +pub(crate) struct ModuleInstanceInner { pub(crate) store_id: usize, - pub(crate) _idx: ModuleInstanceAddr, - pub(crate) func_start: Option<FuncAddr>, - pub(crate) types: Box<[FuncType]>, - pub(crate) exports: ExportInstance, + pub(crate) idx: ModuleInstanceAddr, + pub(crate) types: Box<[FuncType]>, pub(crate) func_addrs: Vec<FuncAddr>, - // pub table_addrs: Vec<TableAddr>, - // pub mem_addrs: Vec<MemAddr>, - // pub global_addrs: Vec<GlobalAddr>, - // pub elem_addrs: Vec<ElmAddr>, - // pub data_addrs: Vec<DataAddr>, + pub(crate) table_addrs: Vec<TableAddr>, + pub(crate) mem_addrs: Vec<MemAddr>, + pub(crate) global_addrs: Vec<GlobalAddr>, + pub(crate) elem_addrs: Vec<ElmAddr>, + pub(crate) data_addrs: Vec<DataAddr>, + + pub(crate) func_start: Option<FuncAddr>, + pub(crate) imports: Box<[Import]>, + pub(crate) exports: ExportInstance, } impl ModuleInstance { @@ -44,22 +49,8 @@ impl ModuleInstance { &self.0.types } - pub(crate) fn new( - types: Box<[FuncType]>, - func_start: Option<FuncAddr>, - exports: Box<[Export]>, - func_addrs: Vec<FuncAddr>, - idx: ModuleInstanceAddr, - store_id: usize, - ) -> Self { - Self(Arc::new(ModuleInstanceInner { - store_id, - _idx: idx, - types, - func_start, - func_addrs, - exports: ExportInstance(exports), - })) + pub(crate) fn new(inner: ModuleInstanceInner) -> Self { + Self(Arc::new(inner)) } pub(crate) fn func_ty(&self, addr: FuncAddr) -> &FuncType { diff --git a/crates/tinywasm/src/module.rs b/crates/tinywasm/src/module.rs index 4f3575d..e26db90 100644 --- a/crates/tinywasm/src/module.rs +++ b/crates/tinywasm/src/module.rs @@ -1,6 +1,7 @@ +use alloc::vec::Vec; use tinywasm_types::TinyWasmModule; -use crate::{ModuleInstance, Result, Store}; +use crate::{instance::ModuleInstanceInner, ModuleInstance, Result, Store}; #[derive(Debug)] /// A WebAssembly Module @@ -49,8 +50,8 @@ impl Module { /// Instantiate the module in the given store /// - /// Runs the start function if it exists - /// If you want to run the start function yourself, use `ModuleInstance::new` + // TODO: /// Runs the start function if it exists + // /// If you want to run the start function yourself, use `ModuleInstance::new` /// /// See <https://webassembly.github.io/spec/core/exec/modules.html#exec-instantiation> pub fn instantiate( @@ -59,18 +60,35 @@ impl Module { // imports: Option<()>, ) -> Result<ModuleInstance> { let idx = store.next_module_instance_idx(); + let func_addrs = store.add_funcs(self.data.funcs.into(), idx); + let table_addrs = store.add_tables(self.data.table_types.into(), idx); + let mem_addrs = store.add_mems(self.data.memory_types.into(), idx); + let global_addrs = store.add_globals(self.data.globals.into(), idx); + let elem_addrs = store.add_elems(self.data.elements.into(), idx); + let data_addrs = store.add_datas(self.data.data.into(), idx); - let instance = ModuleInstance::new( - self.data.func_types, - self.data.start_func, - self.data.exports, - func_addrs, + let instance = ModuleInstanceInner { + store_id: store.id(), idx, - store.id(), - ); + types: self.data.func_types, + func_addrs, + table_addrs, + mem_addrs, + global_addrs, + elem_addrs, + data_addrs, + + func_start: self.data.start_func, + imports: self.data.imports, + exports: crate::ExportInstance(self.data.exports), + }; + + let instance = ModuleInstance::new(instance); store.add_instance(instance.clone())?; + + // TODO: Auto-run start function? // let _ = instance.start(store)?; Ok(instance) } diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index f28a6cb..d0e7b4f 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -1,7 +1,10 @@ use core::sync::atomic::{AtomicUsize, Ordering}; use alloc::{format, rc::Rc, vec::Vec}; -use tinywasm_types::{FuncAddr, Function, Instruction, ModuleInstanceAddr, TypeAddr, ValType}; +use tinywasm_types::{ + Addr, Data, Element, ElementKind, FuncAddr, Function, Global, GlobalType, Instruction, MemAddr, MemoryType, + ModuleInstanceAddr, TableAddr, TableType, TypeAddr, ValType, +}; use crate::{ runtime::{self, DefaultRuntime}, @@ -69,42 +72,19 @@ impl Default for Store { } } -#[derive(Debug)] -/// A WebAssembly Function Instance -/// -/// See <https://webassembly.github.io/spec/core/exec/runtime.html#function-instances> -pub struct FunctionInstance { - pub(crate) func: Function, - pub(crate) _module_instance: ModuleInstanceAddr, // index into store.module_instances -} - -impl FunctionInstance { - pub(crate) fn _module_instance_addr(&self) -> ModuleInstanceAddr { - self._module_instance - } - - pub(crate) fn locals(&self) -> &[ValType] { - &self.func.locals - } - - pub(crate) fn instructions(&self) -> &[Instruction] { - &self.func.instructions - } - - pub(crate) fn ty_addr(&self) -> TypeAddr { - self.func.ty - } -} - #[derive(Debug, Default)] /// Global state that can be manipulated by WebAssembly programs +/// +/// Data should only be addressable by the module that owns it +/// See <https://webassembly.github.io/spec/core/exec/runtime.html#store> +// TODO: Arena allocate these? pub(crate) struct StoreData { pub(crate) funcs: Vec<Rc<FunctionInstance>>, - // pub tables: Vec<TableAddr>, - // pub mems: Vec<MemAddr>, - // pub globals: Vec<GlobalAddr>, - // pub elems: Vec<ElmAddr>, - // pub datas: Vec<DataAddr>, + pub(crate) tables: Vec<TableInstance>, + pub(crate) mems: Vec<Rc<MemoryInstance>>, + pub(crate) globals: Vec<Rc<GlobalInstance>>, + pub(crate) elems: Vec<ElemInstance>, + pub(crate) datas: Vec<DataInstance>, } impl Store { @@ -129,15 +109,69 @@ impl Store { 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, - _module_instance: idx, - })); + self.data.funcs.push(Rc::new(FunctionInstance { func, owner: idx })); func_addrs.push((i + func_count) as FuncAddr); } 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> { + 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(TableInstance::new(table, idx)); + table_addrs.push((i + table_count) as TableAddr); + } + 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) -> 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() { + self.data.mems.push(Rc::new(MemoryInstance::new(mem, idx))); + mem_addrs.push((i + mem_count) as MemAddr); + } + mem_addrs + } + + /// Add globals to the store, returning their addresses in the store + pub(crate) fn add_globals(&mut self, globals: Vec<Global>, idx: ModuleInstanceAddr) -> Vec<Addr> { + let global_count = self.data.globals.len(); + let mut global_addrs = Vec::with_capacity(global_count); + for (i, global) in globals.into_iter().enumerate() { + // TODO: initialize globals + // Don't fail here yet - we'll fail when we try to use the global + self.data.globals.push(Rc::new(GlobalInstance::new(global.ty, 0, idx))); + global_addrs.push((i + global_count) as Addr); + } + global_addrs + } + + /// Add elements to the store, returning their addresses in the store + pub(crate) fn add_elems(&mut self, elems: Vec<Element>, idx: ModuleInstanceAddr) -> 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() { + self.data.elems.push(ElemInstance::new(elem.kind, idx)); + elem_addrs.push((i + elem_count) as Addr); + } + elem_addrs + } + + /// Add data to the store, returning their addresses in the store + pub(crate) fn add_datas(&mut self, datas: Vec<Data>, idx: ModuleInstanceAddr) -> 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() { + self.data.datas.push(DataInstance::new(data.data.to_vec(), idx)); + data_addrs.push((i + data_count) as Addr); + } + data_addrs + } + /// Get the function at the actual index in the store pub(crate) fn get_func(&self, addr: usize) -> Result<&Rc<FunctionInstance>> { self.data @@ -146,3 +180,116 @@ impl Store { .ok_or_else(|| Error::Other(format!("function {} not found", addr))) } } + +#[derive(Debug)] +/// A WebAssembly Function Instance +/// +/// 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 +} + +impl FunctionInstance { + pub(crate) fn _module_instance_addr(&self) -> ModuleInstanceAddr { + self.owner + } + + pub(crate) fn locals(&self) -> &[ValType] { + &self.func.locals + } + + pub(crate) fn instructions(&self) -> &[Instruction] { + &self.func.instructions + } + + pub(crate) fn ty_addr(&self) -> TypeAddr { + self.func.ty + } +} + +/// A WebAssembly Table Instance +/// +/// 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 +} + +impl TableInstance { + pub(crate) fn new(kind: TableType, owner: ModuleInstanceAddr) -> Self { + Self { + kind, + elements: Vec::new(), + owner, + } + } +} + +/// A WebAssembly Memory Instance +/// +/// See <https://webassembly.github.io/spec/core/exec/runtime.html#memory-instances> +#[derive(Debug)] +pub(crate) struct MemoryInstance { + pub(crate) kind: MemoryType, + pub(crate) data: Vec<u8>, + pub(crate) owner: ModuleInstanceAddr, // index into store.module_instances +} + +impl MemoryInstance { + pub(crate) fn new(kind: MemoryType, owner: ModuleInstanceAddr) -> Self { + Self { + kind, + data: Vec::new(), + owner, + } + } +} + +/// A WebAssembly Global Instance +/// +/// 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: Addr, + owner: ModuleInstanceAddr, // index into store.module_instances +} + +impl GlobalInstance { + pub(crate) fn new(ty: GlobalType, value: Addr, owner: ModuleInstanceAddr) -> Self { + Self { ty, value, owner } + } +} + +/// A WebAssembly Element Instance +/// +/// See <https://webassembly.github.io/spec/core/exec/runtime.html#element-instances> +#[derive(Debug)] +pub(crate) struct ElemInstance { + kind: ElementKind, + owner: ModuleInstanceAddr, // index into store.module_instances +} + +impl ElemInstance { + pub(crate) fn new(kind: ElementKind, owner: ModuleInstanceAddr) -> Self { + Self { kind, owner } + } +} + +/// A WebAssembly Data Instance +/// +/// 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 +} + +impl DataInstance { + pub(crate) fn new(data: Vec<u8>, owner: ModuleInstanceAddr) -> Self { + Self { data, owner } + } +} diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index 042b0c0..ec72fb3 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -53,12 +53,12 @@ v0.1.0 (17630) </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.2.0-alpha.0 (17639) +v0.2.0-alpha.0 (17747) </text> <polyline fill="none" opacity="1" stroke="#000000" stroke-width="1" points="898,345 898,350 "/> -<rect x="630" y="92" width="172" height="252" opacity="0.5" fill="#0000FF" stroke="none"/> -<rect x="812" y="92" width="172" height="252" opacity="0.5" fill="#0000FF" stroke="none"/> <rect x="448" y="185" width="172" height="159" opacity="0.5" fill="#0000FF" stroke="none"/> <rect x="266" y="212" width="172" height="132" 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="630" y="92" width="172" height="252" opacity="0.5" fill="#0000FF" stroke="none"/> +<rect x="812" y="90" width="172" height="254" opacity="0.5" fill="#0000FF" stroke="none"/> </svg> |
