summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/tinywasm/src/instance.rs45
-rw-r--r--crates/tinywasm/src/module.rs38
-rw-r--r--crates/tinywasm/src/store.rs221
-rw-r--r--crates/tinywasm/tests/generated/progress-mvp.svg6
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>