summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenry Gressmann <mail@henrygressmann.de>2023-11-30 15:04:40 +0100
committerHenry Gressmann <mail@henrygressmann.de>2023-11-30 15:04:40 +0100
commit82e01c1797875bb07887283d5673e0dda238033e (patch)
treecd0658c62689758df6decca3c0457c7a51af5d1f
parent4f13c2518133c35db8533bd736ce5497105e2e10 (diff)
chore: improve api
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
-rw-r--r--crates/cli/bin.rs49
-rw-r--r--crates/tinywasm/src/engine/executer.rs1
-rw-r--r--crates/tinywasm/src/engine/mod.rs20
-rw-r--r--crates/tinywasm/src/engine/stack/call.rs (renamed from crates/tinywasm/src/runtime/stack/call.rs)1
-rw-r--r--crates/tinywasm/src/engine/stack/mod.rs (renamed from crates/tinywasm/src/runtime/stack/mod.rs)16
-rw-r--r--crates/tinywasm/src/engine/types.rs (renamed from crates/tinywasm/src/runtime/types.rs)36
-rw-r--r--crates/tinywasm/src/instance.rs0
-rw-r--r--crates/tinywasm/src/instructions.rs106
-rw-r--r--crates/tinywasm/src/lib.rs32
-rw-r--r--crates/tinywasm/src/module/mod.rs111
-rw-r--r--crates/tinywasm/src/module/reader.rs2
-rw-r--r--crates/tinywasm/src/naive/mod.rs (renamed from crates/tinywasm/src/naive_runtime.rs)5
-rw-r--r--crates/tinywasm/src/naive/module.rs92
-rw-r--r--crates/tinywasm/src/runtime/mod.rs6
-rw-r--r--crates/tinywasm/src/runtime/store.rs14
-rw-r--r--crates/tinywasm/src/store.rs51
16 files changed, 318 insertions, 224 deletions
diff --git a/crates/cli/bin.rs b/crates/cli/bin.rs
index 6875eac..18b61cc 100644
--- a/crates/cli/bin.rs
+++ b/crates/cli/bin.rs
@@ -1,6 +1,8 @@
+use std::str::FromStr;
+
use argh::FromArgs;
use color_eyre::eyre::Result;
-use tinywasm::{self, Module, WasmValue};
+use tinywasm::{self, WasmValue};
use util::install_tracing;
mod util;
@@ -18,6 +20,23 @@ enum TinyWasmSubcommand {
Run(Run),
}
+enum Engine {
+ Main,
+ Naive,
+}
+
+impl FromStr for Engine {
+ type Err = String;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ match s {
+ "naive" => Ok(Self::Naive),
+ "main" => Ok(Self::Main),
+ _ => Err(format!("unknown engine: {}", s)),
+ }
+ }
+}
+
#[derive(FromArgs)]
/// run a wasm file
#[argh(subcommand, name = "run")]
@@ -25,6 +44,10 @@ struct Run {
/// wasm file to run
#[argh(positional)]
wasm_file: String,
+
+ /// engine to use
+ #[argh(option, short = 'e', default = "Engine::Main")]
+ engine: Engine,
}
fn main() -> Result<()> {
@@ -34,22 +57,32 @@ fn main() -> Result<()> {
let args: TinyWasmCli = argh::from_env();
match args.nested {
- TinyWasmSubcommand::Run(Run { wasm_file }) => {
- let wasm = std::fs::read(wasm_file).unwrap();
- run(&wasm)?;
- Ok(())
+ TinyWasmSubcommand::Run(Run { wasm_file, engine }) => {
+ let wasm = std::fs::read(wasm_file)?;
+ match engine {
+ Engine::Main => run(&wasm),
+ Engine::Naive => run_naive(&wasm),
+ }
}
}
}
fn run(wasm: &[u8]) -> Result<()> {
- let mut module = Module::new(wasm)?;
+ let mut store = tinywasm::Store::default();
+ let mut module = tinywasm::Module::try_new(&mut store, wasm)?;
+ let instance = tinywasm::ModuleInstance::new(&mut module)?;
+
+ Ok(())
+}
+
+fn run_naive(wasm: &[u8]) -> Result<()> {
+ let mut module = tinywasm::naive::Module::new(wasm)?;
let args = [WasmValue::I32(1), WasmValue::I32(2)];
- let res = tinywasm::naive_runtime::run(&mut module, "add", &args)?;
+ let res = tinywasm::naive::run(&mut module, "add", &args)?;
println!("res: {:?}", res);
let args = [WasmValue::I64(1), WasmValue::I64(2)];
- let res = tinywasm::naive_runtime::run(&mut module, "add_64", &args)?;
+ let res = tinywasm::naive::run(&mut module, "add_64", &args)?;
println!("res: {:?}", res);
Ok(())
diff --git a/crates/tinywasm/src/engine/executer.rs b/crates/tinywasm/src/engine/executer.rs
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/crates/tinywasm/src/engine/executer.rs
@@ -0,0 +1 @@
+
diff --git a/crates/tinywasm/src/engine/mod.rs b/crates/tinywasm/src/engine/mod.rs
new file mode 100644
index 0000000..a134659
--- /dev/null
+++ b/crates/tinywasm/src/engine/mod.rs
@@ -0,0 +1,20 @@
+mod executer;
+mod stack;
+mod types;
+
+pub use executer::*;
+pub use stack::*;
+pub use types::*;
+
+#[derive(Debug)]
+pub struct Engine {
+ pub stack: Stack,
+}
+
+impl Default for Engine {
+ fn default() -> Self {
+ Self {
+ stack: Stack::default(),
+ }
+ }
+}
diff --git a/crates/tinywasm/src/runtime/stack/call.rs b/crates/tinywasm/src/engine/stack/call.rs
index a58e2ef..0d0ffae 100644
--- a/crates/tinywasm/src/runtime/stack/call.rs
+++ b/crates/tinywasm/src/engine/stack/call.rs
@@ -1,5 +1,6 @@
use alloc::vec::Vec;
+#[derive(Debug)]
pub struct CallFrame {
pub instr_ptr: usize,
pub func_ptr: usize,
diff --git a/crates/tinywasm/src/runtime/stack/mod.rs b/crates/tinywasm/src/engine/stack/mod.rs
index 68f02ff..f7ffdf3 100644
--- a/crates/tinywasm/src/runtime/stack/mod.rs
+++ b/crates/tinywasm/src/engine/stack/mod.rs
@@ -4,9 +4,13 @@ use alloc::vec::Vec;
mod call;
pub use call::CallFrame;
+// minimum stack size
pub const STACK_SIZE: usize = 1024;
+// minimum call stack size
+pub const CALL_STACK_SIZE: usize = 1024;
/// A WebAssembly Stack
+#[derive(Debug)]
pub struct Stack {
/// Locals
// TODO: maybe store the locals on the stack instead?
@@ -21,3 +25,15 @@ pub struct Stack {
pub call_stack: Vec<CallFrame>,
pub call_stack_top: usize,
}
+
+impl Default for Stack {
+ fn default() -> Self {
+ Self {
+ locals: Vec::new(),
+ value_stack: Vec::with_capacity(STACK_SIZE),
+ value_stack_top: 0,
+ call_stack: Vec::with_capacity(CALL_STACK_SIZE),
+ call_stack_top: 0,
+ }
+ }
+}
diff --git a/crates/tinywasm/src/runtime/types.rs b/crates/tinywasm/src/engine/types.rs
index a9be605..ab81b9d 100644
--- a/crates/tinywasm/src/runtime/types.rs
+++ b/crates/tinywasm/src/engine/types.rs
@@ -1,6 +1,8 @@
use alloc::{string::String, vec::Vec};
use wasmparser::{FuncType, OperatorsIterator, ValType};
+use crate::module::ModuleInstance;
+
/// A WebAssembly Label
pub struct Label(Addr);
@@ -8,40 +10,30 @@ pub struct Label(Addr);
/// These are indexes into the respective stores.
/// See https://webassembly.github.io/spec/core/exec/runtime.html#addresses
pub type Addr = u32;
-pub struct FuncAddr(pub Addr);
-pub struct TableAddr(pub Addr);
-pub struct MemAddr(pub Addr);
-pub struct GlobalAddr(pub Addr);
-pub struct ElmAddr(pub Addr);
-pub struct DataAddr(pub Addr);
-pub struct ExternAddr(pub Addr);
-
-/// A WebAssembly Module Instance.
-/// See https://webassembly.github.io/spec/core/exec/runtime.html#module-instances
-pub struct ModuleInstance {
- pub types: Vec<FuncType>,
- pub 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 exports: Vec<ExportInst>,
-}
+pub type FuncAddr = Addr;
+pub type TableAddr = Addr;
+pub type MemAddr = Addr;
+pub type GlobalAddr = Addr;
+pub type ElmAddr = Addr;
+pub type DataAddr = Addr;
+pub type ExternAddr = Addr;
/// A WebAssembly Function Instance.
/// See https://webassembly.github.io/spec/core/exec/runtime.html#function-instances
+#[derive(Debug)]
pub enum FuncInst {
Host(HostFunc),
Module(ModuleFunc),
}
+#[derive(Debug)]
pub struct HostFunc {
pub ty: FuncType,
pub hostcode: fn() -> (),
}
+#[derive(Debug)]
pub struct ModuleFunc {
pub ty: FuncType,
- pub module: ModuleInstance,
+ pub module: Addr,
pub code: FuncAddr,
}
pub struct Func<'a> {
@@ -52,6 +44,7 @@ pub struct Func<'a> {
/// A WebAssembly Export Instance.
/// https://webassembly.github.io/spec/core/exec/runtime.html#export-instances
+#[derive(Debug)]
pub struct ExportInst {
pub name: String,
pub value: ExternVal,
@@ -59,6 +52,7 @@ pub struct ExportInst {
/// A WebAssembly External Value.
/// https://webassembly.github.io/spec/core/exec/runtime.html#external-values
+#[derive(Debug)]
pub enum ExternVal {
Func(FuncAddr),
Table(TableAddr),
diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs
deleted file mode 100644
index e69de29..0000000
--- a/crates/tinywasm/src/instance.rs
+++ /dev/null
diff --git a/crates/tinywasm/src/instructions.rs b/crates/tinywasm/src/instructions.rs
deleted file mode 100644
index e3e6a08..0000000
--- a/crates/tinywasm/src/instructions.rs
+++ /dev/null
@@ -1,106 +0,0 @@
-// https://webassembly.github.io/spec/core/binary/instructions.html
-
-// Controll Instructions
-pub mod control {
- pub const WASM_UNREACHABLE: u8 = 0x00;
- pub const WASM_NOP: u8 = 0x01; // do nothing
-
- // stuctured instructions
- pub const WASM_BLOCK: u8 = 0x02;
- pub const WASM_LOOP: u8 = 0x03;
- pub const WASM_IF: u8 = 0x04;
-
- pub const WASM_ELSE: u8 = 0x05;
- pub const WASM_END: u8 = 0x0B;
- pub const WASM_BR: u8 = 0x0C;
- pub const WASM_BR_IF: u8 = 0x0D;
- pub const WASM_BR_TABLE: u8 = 0x0E;
- pub const WASM_RETURN: u8 = 0x0F;
- pub const WASM_CALL: u8 = 0x10;
- pub const WASM_CALL_INDIRECT: u8 = 0x11;
- pub const WASM_DROP: u8 = 0x1A;
-}
-
-// Reference Instructions
-pub mod reference {
- pub const WASM_REF_NULL: u8 = 0xD0;
- pub const WASM_REF_IS_NULL: u8 = 0xD1;
- pub const WASM_REF_FUNC: u8 = 0xD2;
-}
-
-// Parametric Instructions
-pub mod parametric {
- pub const WASM_DROP: u8 = 0x1A;
- pub const WASM_SELECT: u8 = 0x1B;
- pub const WASM_SELECT_T: u8 = 0x1C;
-}
-
-// Variable Instructions
-pub mod variable {
- pub const WASM_LOCAL_GET: u8 = 0x20;
- pub const WASM_LOCAL_SET: u8 = 0x21;
- pub const WASM_LOCAL_TEE: u8 = 0x22;
- pub const WASM_GLOBAL_GET: u8 = 0x23;
- pub const WASM_GLOBAL_SET: u8 = 0x24;
-}
-
-// Table Instructions
-pub mod table {
- pub const WASM_TABLE_GET: u8 = 0x25;
- pub const WASM_TABLE_SET: u8 = 0x26;
- pub const WASM_TABLE_INIT: u8 = 0xFC;
- pub const WASM_ELEM_DROP: u8 = 0xFC;
- pub const WASM_TABLE_COPY: u8 = 0xFC;
- pub const WASM_TABLE_GROW: u8 = 0xFC;
- pub const WASM_TABLE_SIZE: u8 = 0xFC;
- pub const WASM_TABLE_FILL: u8 = 0xFC;
-}
-
-// Memory Instructions
-pub mod memory {
- pub const WASM_I32_LOAD: u8 = 0x28;
- pub const WASM_I64_LOAD: u8 = 0x29;
- pub const WASM_F32_LOAD: u8 = 0x2A;
- pub const WASM_F64_LOAD: u8 = 0x2B;
- pub const WASM_I32_LOAD8_S: u8 = 0x2C;
- pub const WASM_I32_LOAD8_U: u8 = 0x2D;
- pub const WASM_I32_LOAD16_S: u8 = 0x2E;
- pub const WASM_I32_LOAD16_U: u8 = 0x2F;
- pub const WASM_I64_LOAD8_S: u8 = 0x30;
- pub const WASM_I64_LOAD8_U: u8 = 0x31;
- pub const WASM_I64_LOAD16_S: u8 = 0x32;
- pub const WASM_I64_LOAD16_U: u8 = 0x33;
- pub const WASM_I64_LOAD32_S: u8 = 0x34;
- pub const WASM_I64_LOAD32_U: u8 = 0x35;
- pub const WASM_I32_STORE: u8 = 0x36;
- pub const WASM_I64_STORE: u8 = 0x37;
- pub const WASM_F32_STORE: u8 = 0x38;
- pub const WASM_F64_STORE: u8 = 0x39;
- pub const WASM_I32_STORE8: u8 = 0x3A;
- pub const WASM_I32_STORE16: u8 = 0x3B;
- pub const WASM_I64_STORE8: u8 = 0x3C;
- pub const WASM_I64_STORE16: u8 = 0x3D;
- pub const WASM_I64_STORE32: u8 = 0x3E;
- pub const WASM_MEMORY_SIZE: u8 = 0x3F;
- pub const WASM_MEMORY_GROW: u8 = 0x40;
- pub const WASM_MEMORY_INIT: u8 = 0xFC;
- pub const WASM_DATA_DROP: u8 = 0xFC;
- pub const WASM_MEMORY_COPY: u8 = 0xFC;
- pub const WASM_MEMORY_FILL: u8 = 0xFC;
-}
-
-// Numeric Instructions
-pub mod numeric {
- // Constants
- pub const WASM_I32_CONST: u8 = 0x41;
- pub const WASM_I64_CONST: u8 = 0x42;
- pub const WASM_F32_CONST: u8 = 0x43;
- pub const WASM_F64_CONST: u8 = 0x44;
-
- // Operations
- pub const START_NUMERIC: u8 = 0x45;
- pub const END_NUMERIC: u8 = 0xC4;
- pub const WASM_SATURATING_TRUNC: u8 = 0xFC;
-}
-
-pub const WASM_VEC: u8 = 0xFD;
diff --git a/crates/tinywasm/src/lib.rs b/crates/tinywasm/src/lib.rs
index 6b2cd3f..f4bdd65 100644
--- a/crates/tinywasm/src/lib.rs
+++ b/crates/tinywasm/src/lib.rs
@@ -6,28 +6,38 @@ mod std;
extern crate alloc;
mod error;
-pub mod instructions;
-pub mod module;
pub use error::*;
+
+pub mod store;
+pub use store::Store;
+
+pub mod module;
pub use module::Module;
+pub use module::ModuleInstance;
+
pub mod types;
pub use types::*;
-pub mod runtime;
-pub mod naive_runtime;
-
-pub struct Store {}
-
-pub struct Instance {}
+pub mod engine;
+pub mod naive;
#[cfg(test)]
mod tests {
- use crate::{error::Result, Module};
+ use crate::std::println;
+ use crate::{error::Result, naive, WasmValue};
#[test]
- fn it_works() -> Result<()> {
+ fn naive_add() -> Result<()> {
let wasm = include_bytes!("../../../examples/wasm/add.wasm");
- let module = Module::new(wasm)?;
+ let mut module = naive::Module::new(wasm)?;
+
+ let args = [WasmValue::I32(1), WasmValue::I32(2)];
+ let res = naive::run(&mut module, "add", &args)?;
+ println!("res: {:?}", res);
+
+ let args = [WasmValue::I64(1), WasmValue::I64(2)];
+ let res = naive::run(&mut module, "add_64", &args)?;
+ println!("res: {:?}", res);
Ok(())
}
diff --git a/crates/tinywasm/src/module/mod.rs b/crates/tinywasm/src/module/mod.rs
index 23c2a93..51731e9 100644
--- a/crates/tinywasm/src/module/mod.rs
+++ b/crates/tinywasm/src/module/mod.rs
@@ -1,63 +1,44 @@
-use core::fmt::Debug;
-
-use crate::error::{Error, Result};
use alloc::vec::Vec;
-use wasmparser::*;
+use wasmparser::{Export, FuncType, Validator};
+
+use crate::{engine::FuncAddr, Error, Result, Store};
-mod reader;
use self::reader::ModuleReader;
+pub mod reader;
+
#[derive(Debug)]
-pub struct ModuleMetadata {
- pub version: u16,
+pub struct Module<'a> {
+ store: &'a mut Store<'a>,
+ reader: ModuleReader<'a>,
}
-pub struct Module<'data> {
- pub meta: ModuleMetadata,
+/// A WebAssembly Module Instance.
+/// See https://webassembly.github.io/spec/core/exec/runtime.html#module-instances
+#[derive(Debug)]
+pub struct ModuleInstance<'m, 'data> {
+ pub module: &'m Module<'data>,
pub types: Vec<FuncType>,
- pub functions: Vec<u32>,
+ pub 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 exports: Vec<Export<'data>>,
- pub code: Vec<FunctionBody<'data>>,
-
- marker: core::marker::PhantomData<&'data ()>,
}
-impl Debug for Module<'_> {
- fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
- f.debug_struct("Module")
- .field("meta", &self.meta)
- .field("types", &self.types)
- .field("functions", &self.functions)
- .field("exports", &self.exports)
- .field("code", &self.code)
- .finish()
- }
-}
-
-impl<'data> Module<'data> {
- pub fn new(wasm: &'data [u8]) -> Result<Self> {
- let mut validator = Validator::new();
- let mut reader = ModuleReader::new();
-
- for payload in wasmparser::Parser::new(0).parse_all(wasm) {
- reader.process_payload(payload?, &mut validator)?;
- }
-
- if !reader.end_reached {
- return Error::other("End not reached");
- }
-
- Self::from_reader(reader)
- }
-
- fn from_reader(reader: ModuleReader<'data>) -> Result<Self> {
- let types = reader
+impl<'m, 'data> ModuleInstance<'m, 'data> {
+ pub fn new(module: &'m mut Module<'data>) -> Result<Self> {
+ let types = module
+ .reader
.type_section
+ .take()
.map(|s| {
s.into_iter()
.map(|ty| {
- let Type::Func(func) = ty?;
+ let wasmparser::Type::Func(func) = ty?;
Ok(func)
})
.collect::<Result<Vec<_>>>()
@@ -65,31 +46,49 @@ impl<'data> Module<'data> {
.transpose()?
.unwrap_or_default();
- let functions = reader
+ let func_addrs = module
+ .reader
.function_section
+ .take()
.map(|s| s.into_iter().map(|f| Ok(f?)).collect::<Result<Vec<_>>>())
.transpose()?
.unwrap_or_default();
- let exports = reader
+ let exports = module
+ .reader
.export_section
+ .take()
.map(|s| s.into_iter().map(|e| Ok(e?)).collect::<Result<Vec<_>>>())
.transpose()?
.unwrap_or_default();
- let code = reader.code_section.map(|s| s.functions).unwrap_or_default();
-
- let meta = ModuleMetadata {
- version: reader.version.unwrap_or(1),
- };
-
Ok(Self {
- marker: core::marker::PhantomData,
- meta,
+ module,
+
types,
+ func_addrs,
+ // table_addrs,
+ // mem_addrs,
+ // global_addrs,
+ // elem_addrs,
+ // data_addrs,
exports,
- functions,
- code,
})
}
}
+
+impl<'a> Module<'a> {
+ pub fn try_new(store: &'a mut Store<'a>, wasm: &'a [u8]) -> Result<Module<'a>> {
+ let mut validator = Validator::new();
+ let mut reader = ModuleReader::new();
+
+ for payload in wasmparser::Parser::new(0).parse_all(&wasm) {
+ reader.process_payload(payload?, &mut validator)?;
+ }
+ if !reader.end_reached {
+ return Error::other("End not reached");
+ }
+
+ Ok(Self { store, reader })
+ }
+}
diff --git a/crates/tinywasm/src/module/reader.rs b/crates/tinywasm/src/module/reader.rs
index 5ccadea..50d1012 100644
--- a/crates/tinywasm/src/module/reader.rs
+++ b/crates/tinywasm/src/module/reader.rs
@@ -46,7 +46,7 @@ impl Debug for ModuleReader<'_> {
}
impl<'a> ModuleReader<'a> {
- pub fn new() -> Self {
+ pub fn new() -> ModuleReader<'a> {
Self::default()
}
diff --git a/crates/tinywasm/src/naive_runtime.rs b/crates/tinywasm/src/naive/mod.rs
index 6e6c709..44b40af 100644
--- a/crates/tinywasm/src/naive_runtime.rs
+++ b/crates/tinywasm/src/naive/mod.rs
@@ -2,7 +2,10 @@ use alloc::{format, string::ToString, vec, vec::Vec};
use tracing::info;
use wasmparser::Operator;
-use crate::{Error, Module, Result, WasmValue};
+mod module;
+pub use self::module::Module;
+
+use crate::{Error, Result, WasmValue};
pub fn run(module: &mut Module, func_name: &str, args: &[WasmValue]) -> Result<Vec<WasmValue>> {
let func = module
diff --git a/crates/tinywasm/src/naive/module.rs b/crates/tinywasm/src/naive/module.rs
new file mode 100644
index 0000000..24f2d55
--- /dev/null
+++ b/crates/tinywasm/src/naive/module.rs
@@ -0,0 +1,92 @@
+use core::fmt::Debug;
+
+use crate::{
+ error::{Error, Result},
+ module::reader::ModuleReader,
+};
+use alloc::vec::Vec;
+use wasmparser::*;
+
+#[derive(Debug)]
+pub struct ModuleMetadata {
+ pub version: u16,
+}
+
+pub struct Module<'data> {
+ pub meta: ModuleMetadata,
+
+ pub types: Vec<FuncType>,
+ pub functions: Vec<u32>,
+ pub exports: Vec<Export<'data>>,
+ pub code: Vec<FunctionBody<'data>>,
+}
+
+impl Debug for Module<'_> {
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ f.debug_struct("Module")
+ .field("meta", &self.meta)
+ .field("types", &self.types)
+ .field("functions", &self.functions)
+ .field("exports", &self.exports)
+ .field("code", &self.code)
+ .finish()
+ }
+}
+
+impl<'data> Module<'data> {
+ pub fn new(wasm: &'data [u8]) -> Result<Self> {
+ let mut validator = Validator::new();
+ let mut reader = ModuleReader::new();
+
+ for payload in wasmparser::Parser::new(0).parse_all(wasm) {
+ reader.process_payload(payload?, &mut validator)?;
+ }
+
+ if !reader.end_reached {
+ return Error::other("End not reached");
+ }
+
+ Self::from_reader(reader)
+ }
+
+ fn from_reader(reader: ModuleReader<'data>) -> Result<Self> {
+ let types = reader
+ .type_section
+ .map(|s| {
+ s.into_iter()
+ .map(|ty| {
+ let Type::Func(func) = ty?;
+ Ok(func)
+ })
+ .collect::<Result<Vec<_>>>()
+ })
+ .transpose()?
+ .unwrap_or_default();
+
+ let functions = reader
+ .function_section
+ .map(|s| s.into_iter().map(|f| Ok(f?)).collect::<Result<Vec<_>>>())
+ .transpose()?
+ .unwrap_or_default();
+
+ let exports = reader
+ .export_section
+ .map(|s| s.into_iter().map(|e| Ok(e?)).collect::<Result<Vec<_>>>())
+ .transpose()?
+ .unwrap_or_default();
+
+ let code = reader.code_section.map(|s| s.functions).unwrap_or_default();
+
+ let meta = ModuleMetadata {
+ version: reader.version.unwrap_or(1),
+ };
+
+ Ok(Self {
+ meta,
+ types,
+ exports,
+ functions,
+ code,
+ })
+ }
+}
diff --git a/crates/tinywasm/src/runtime/mod.rs b/crates/tinywasm/src/runtime/mod.rs
deleted file mode 100644
index 0504365..0000000
--- a/crates/tinywasm/src/runtime/mod.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-mod stack;
-mod store;
-mod types;
-pub use stack::*;
-pub use store::*;
-pub use types::*;
diff --git a/crates/tinywasm/src/runtime/store.rs b/crates/tinywasm/src/runtime/store.rs
deleted file mode 100644
index cf0163b..0000000
--- a/crates/tinywasm/src/runtime/store.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-use alloc::vec::Vec;
-
-use super::FuncInst;
-
-/// global state that can be manipulated by WebAssembly programs
-/// https://webassembly.github.io/spec/core/exec/runtime.html#store
-pub struct Store {
- pub funcs: Vec<FuncInst>,
- // tables: Vec<TableType>,
- // mems: Vec<MemoryType>,
- // globals: Vec<GlobalType>,
- // elems: Vec<Element>,
- // data: Vec<Data>,
-}
diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs
new file mode 100644
index 0000000..3c70c2f
--- /dev/null
+++ b/crates/tinywasm/src/store.rs
@@ -0,0 +1,51 @@
+use alloc::vec::Vec;
+use wasmparser::FunctionBody;
+
+use crate::{engine::Engine, module::reader::ModuleReader, Result};
+
+/// global state that can be manipulated by WebAssembly programs
+/// https://webassembly.github.io/spec/core/exec/runtime.html#store
+#[derive(Debug)]
+pub struct Store<'data> {
+ pub data: StoreData<'data>,
+ pub engine: Engine,
+}
+
+#[derive(Debug)]
+pub struct StoreData<'data> {
+ pub funcs: Vec<FunctionBody<'data>>,
+ // pub tables: Vec<TableAddr>,
+ // pub mems: Vec<MemAddr>,
+ // pub globals: Vec<GlobalAddr>,
+}
+
+impl<'data> Default for StoreData<'data> {
+ fn default() -> Self {
+ Self {
+ funcs: Vec::new(),
+ // tables: Vec::new(),
+ // mems: Vec::new(),
+ // globals: Vec::new(),
+ }
+ }
+}
+
+impl<'data> Store<'data> {
+ pub(crate) fn initialize(&'data mut self, reader: &'data mut ModuleReader) -> Result<()> {
+ let code = reader.code_section.take().ok_or_else(|| {
+ crate::Error::Other("Module must have a code section to initialize the store".into())
+ })?;
+
+ self.data.funcs = code.functions;
+ Ok(())
+ }
+}
+
+impl Default for Store<'_> {
+ fn default() -> Self {
+ Self {
+ data: StoreData::default(),
+ engine: Engine::default(),
+ }
+ }
+}