Skip to content
This repository was archived by the owner on Oct 3, 2025. It is now read-only.

Commit 54c1b75

Browse files
feat: imports
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
1 parent 64606e0 commit 54c1b75

File tree

11 files changed

+141
-44
lines changed

11 files changed

+141
-44
lines changed

crates/cli/src/bin.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ fn main() -> Result<()> {
114114

115115
fn run(module: Module, func: Option<String>, args: Vec<WasmValue>) -> Result<()> {
116116
let mut store = tinywasm::Store::default();
117-
let instance = module.instantiate(&mut store)?;
117+
let instance = module.instantiate(&mut store, None)?;
118118

119119
if let Some(func) = func {
120120
let func = instance.exported_func_by_name(&store, &func)?;

crates/tinywasm/src/imports.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
use crate::Result;
2+
use alloc::{
3+
collections::BTreeMap,
4+
string::{String, ToString},
5+
};
6+
use tinywasm_types::{Global, GlobalType, WasmValue};
7+
8+
#[derive(Debug)]
9+
#[non_exhaustive]
10+
/// An external value
11+
pub enum Extern {
12+
/// A global value
13+
Global(Global),
14+
// Func(HostFunc),
15+
// Table(Table),
16+
}
17+
18+
impl Extern {
19+
/// Create a new global import
20+
pub fn global(val: WasmValue, mutable: bool) -> Self {
21+
Self::Global(Global {
22+
ty: GlobalType {
23+
ty: val.val_type(),
24+
mutable,
25+
},
26+
init: val.const_instr(),
27+
})
28+
}
29+
}
30+
31+
#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
32+
/// Name of an import
33+
pub struct ExternName {
34+
module: String,
35+
name: String,
36+
}
37+
38+
#[derive(Debug, Default)]
39+
/// Imports for a module instance
40+
pub struct Imports {
41+
values: BTreeMap<ExternName, Extern>,
42+
}
43+
44+
impl Imports {
45+
/// Create a new empty import set
46+
pub fn new() -> Self {
47+
Imports {
48+
values: BTreeMap::new(),
49+
}
50+
}
51+
52+
/// Define an import
53+
pub fn define(&mut self, module: &str, name: &str, value: Extern) -> Result<&mut Self> {
54+
self.values.insert(
55+
ExternName {
56+
module: module.to_string(),
57+
name: name.to_string(),
58+
},
59+
value,
60+
);
61+
Ok(self)
62+
}
63+
64+
pub(crate) fn get(&self, module: &str, name: &str) -> Option<&Extern> {
65+
self.values.get(&ExternName {
66+
module: module.to_string(),
67+
name: name.to_string(),
68+
})
69+
}
70+
}

crates/tinywasm/src/instance.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use tinywasm_types::{
55

66
use crate::{
77
func::{FromWasmValueTuple, IntoWasmValueTuple},
8-
Error, ExportInstance, FuncHandle, Module, Result, Store, TypedFuncHandle,
8+
Error, ExportInstance, FuncHandle, Imports, Module, Result, Store, TypedFuncHandle,
99
};
1010

1111
/// A WebAssembly Module Instance
@@ -36,14 +36,15 @@ pub(crate) struct ModuleInstanceInner {
3636

3737
impl ModuleInstance {
3838
/// Instantiate the module in the given store
39-
pub fn instantiate(store: &mut Store, module: Module) -> Result<Self> {
39+
pub fn instantiate(store: &mut Store, module: Module, imports: Option<Imports>) -> Result<Self> {
4040
let idx = store.next_module_instance_idx();
41+
let imports = imports.unwrap_or_default();
4142

4243
let func_addrs = store.add_funcs(module.data.funcs.into(), idx);
4344
let table_addrs = store.add_tables(module.data.table_types.into(), idx);
4445
let mem_addrs = store.add_mems(module.data.memory_types.into(), idx);
4546

46-
let global_addrs = store.add_globals(module.data.globals.into(), &module.data.imports, idx);
47+
let global_addrs = store.add_globals(module.data.globals.into(), &module.data.imports, &imports, idx)?;
4748
let elem_addrs = store.add_elems(module.data.elements.into(), idx);
4849
let data_addrs = store.add_datas(module.data.data.into(), idx);
4950

crates/tinywasm/src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
//! // This will allocate the module and its globals into the store
3939
//! // and execute the module's start function.
4040
//! // Every ModuleInstance has its own ID space for functions, globals, etc.
41-
//! let instance = module.instantiate(&mut store)?;
41+
//! let instance = module.instantiate(&mut store, None)?;
4242
//!
4343
//! // Get a typed handle to the exported "add" function
4444
//! // Alternatively, you can use `instance.get_func` to get an untyped handle
@@ -94,6 +94,9 @@ pub use export::ExportInstance;
9494
mod func;
9595
pub use func::{FuncHandle, TypedFuncHandle};
9696

97+
mod imports;
98+
pub use imports::*;
99+
97100
mod runtime;
98101
pub use runtime::*;
99102

crates/tinywasm/src/module.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use tinywasm_types::TinyWasmModule;
22

3-
use crate::{ModuleInstance, Result, Store};
3+
use crate::{Imports, ModuleInstance, Result, Store};
44

55
#[derive(Debug)]
66
/// A WebAssembly Module
@@ -53,12 +53,8 @@ impl Module {
5353
/// If you want to run the start function yourself, use `ModuleInstance::instantiate`
5454
///
5555
/// See <https://webassembly.github.io/spec/core/exec/modules.html#exec-instantiation>
56-
pub fn instantiate(
57-
self,
58-
store: &mut Store,
59-
// imports: Option<()>,
60-
) -> Result<ModuleInstance> {
61-
let instance = ModuleInstance::instantiate(store, self)?;
56+
pub fn instantiate(self, store: &mut Store, imports: Option<Imports>) -> Result<ModuleInstance> {
57+
let instance = ModuleInstance::instantiate(store, self, imports)?;
6258

6359
// TODO: this currently panics if theres no start fn
6460
// let _ = instance.start(store)?;

crates/tinywasm/src/store.rs

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use tinywasm_types::{
1111

1212
use crate::{
1313
runtime::{self, DefaultRuntime},
14-
Error, ModuleInstance, RawWasmValue, Result,
14+
Error, Extern, Imports, ModuleInstance, RawWasmValue, Result,
1515
};
1616

1717
// global store id counter
@@ -144,36 +144,42 @@ impl Store {
144144
pub(crate) fn add_globals(
145145
&mut self,
146146
globals: Vec<Global>,
147-
imports: &[Import],
147+
wasm_imports: &[Import],
148+
user_imports: &Imports,
148149
idx: ModuleInstanceAddr,
149-
) -> Vec<Addr> {
150-
let global_count = self.data.globals.len();
151-
let mut global_addrs = Vec::with_capacity(global_count);
152-
150+
) -> Result<Vec<Addr>> {
153151
// TODO: initialize imported globals
154-
let imported_globals = imports
152+
let imported_globals = wasm_imports
155153
.iter()
156154
.filter_map(|import| match &import.kind {
157-
tinywasm_types::ImportKind::Global(t) => Some(t),
155+
tinywasm_types::ImportKind::Global(_) => Some(import),
158156
_ => None,
159157
})
160-
.collect::<Vec<_>>();
161-
162-
for (i, global) in imported_globals.into_iter().enumerate() {
163-
log::debug!("imported global: {:?}", global);
164-
self.data.globals.push(Rc::new(RefCell::new(GlobalInstance::new(
165-
global.clone(),
166-
global.ty.default_value().into(),
167-
idx,
168-
))));
169-
global_addrs.push((i + global_count) as Addr);
170-
}
158+
.map(|import| {
159+
let Some(global) = user_imports.get(&import.module, &import.name) else {
160+
return Err(Error::Other(format!(
161+
"global import not found for {}::{}",
162+
import.module, import.name
163+
)));
164+
};
165+
match global {
166+
Extern::Global(global) => Ok(global),
167+
_ => Err(Error::Other(format!(
168+
"expected global import for {}::{}",
169+
import.module, import.name
170+
))),
171+
}
172+
})
173+
.collect::<Result<Vec<_>>>()?;
171174

172175
let global_count = self.data.globals.len();
176+
let mut global_addrs = Vec::with_capacity(global_count);
177+
173178
log::debug!("globals: {:?}", globals);
174-
for (i, global) in globals.into_iter().enumerate() {
175-
// TODO: initialize globals
179+
let globals = globals.into_iter();
180+
let iterator = imported_globals.into_iter().chain(globals.as_ref());
176181

182+
for (i, global) in iterator.enumerate() {
177183
use tinywasm_types::ConstInstruction::*;
178184
let val = match global.init {
179185
F32Const(f) => RawWasmValue::from(f),
@@ -197,7 +203,7 @@ impl Store {
197203
global_addrs.push((i + global_count) as Addr);
198204
}
199205
log::debug!("global_addrs: {:?}", global_addrs);
200-
global_addrs
206+
Ok(global_addrs)
201207
}
202208

203209
/// Add elements to the store, returning their addresses in the store

0 commit comments

Comments
 (0)