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

Commit 7e8770c

Browse files
chore: restructure runtime
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
1 parent abec4b6 commit 7e8770c

28 files changed

+396
-793
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
- Improved support for WebAssembly 2.0 features
1313
- Simplify and optimize the interpreter loop
1414
- Use a seperate stack and locals for 32, 64 and 128 bit values and references (#21)
15-
- Updated to latest wasmparser version
15+
- Updated to latest `wasmparser` version
1616

1717
## [0.7.0] - 2024-05-15
1818

crates/parser/src/conversion.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -225,14 +225,6 @@ pub(crate) fn convert_module_type(ty: wasmparser::RecGroup) -> Result<FuncType>
225225
Ok(FuncType { params, results })
226226
}
227227

228-
pub(crate) fn convert_blocktype(blocktype: wasmparser::BlockType) -> BlockArgs {
229-
match blocktype {
230-
wasmparser::BlockType::Empty => BlockArgs::Empty,
231-
wasmparser::BlockType::Type(ty) => BlockArgs::Type(convert_valtype(&ty)),
232-
wasmparser::BlockType::FuncType(ty) => BlockArgs::FuncType(ty),
233-
}
234-
}
235-
236228
pub(crate) fn convert_reftype(reftype: &wasmparser::RefType) -> ValType {
237229
match reftype {
238230
_ if reftype.is_func_ref() => ValType::RefFunc,

crates/parser/src/visit.rs

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
use crate::{conversion::convert_blocktype, Result};
1+
use crate::Result;
22

3-
use crate::conversion::convert_heaptype;
3+
use crate::conversion::{convert_heaptype, convert_valtype};
44
use alloc::string::ToString;
55
use alloc::{boxed::Box, vec::Vec};
66
use tinywasm_types::{Instruction, MemoryArg};
@@ -357,7 +357,13 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild
357357
}
358358

359359
fn visit_local_get(&mut self, idx: u32) -> Self::Output {
360-
let resolved_idx = self.local_addr_map[idx as usize];
360+
let Ok(resolved_idx) = self.local_addr_map[idx as usize].try_into() else {
361+
self.errors.push(crate::ParseError::UnsupportedOperator(
362+
"Local index is too large, tinywasm does not support local indexes that large".to_string(),
363+
));
364+
return;
365+
};
366+
361367
match self.validator.get_local_type(idx) {
362368
Some(t) => self.instructions.push(match t {
363369
wasmparser::ValType::I32 => Instruction::LocalGet32(resolved_idx),
@@ -372,7 +378,13 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild
372378
}
373379

374380
fn visit_local_set(&mut self, idx: u32) -> Self::Output {
375-
let resolved_idx = self.local_addr_map[idx as usize];
381+
let Ok(resolved_idx) = self.local_addr_map[idx as usize].try_into() else {
382+
self.errors.push(crate::ParseError::UnsupportedOperator(
383+
"Local index is too large, tinywasm does not support local indexes that large".to_string(),
384+
));
385+
return;
386+
};
387+
376388
match self.validator.get_operand_type(0) {
377389
Some(Some(t)) => self.instructions.push(match t {
378390
wasmparser::ValType::I32 => Instruction::LocalSet32(resolved_idx),
@@ -387,7 +399,13 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild
387399
}
388400

389401
fn visit_local_tee(&mut self, idx: u32) -> Self::Output {
390-
let resolved_idx = self.local_addr_map[idx as usize];
402+
let Ok(resolved_idx) = self.local_addr_map[idx as usize].try_into() else {
403+
self.errors.push(crate::ParseError::UnsupportedOperator(
404+
"Local index is too large, tinywasm does not support local indexes that large".to_string(),
405+
));
406+
return;
407+
};
408+
391409
match self.validator.get_operand_type(0) {
392410
Some(Some(t)) => self.instructions.push(match t {
393411
wasmparser::ValType::I32 => Instruction::LocalTee32(resolved_idx),
@@ -411,17 +429,29 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild
411429

412430
fn visit_block(&mut self, blockty: wasmparser::BlockType) -> Self::Output {
413431
self.label_ptrs.push(self.instructions.len());
414-
self.instructions.push(Instruction::Block(convert_blocktype(blockty), 0))
432+
self.instructions.push(match blockty {
433+
wasmparser::BlockType::Empty => Instruction::Block(0),
434+
wasmparser::BlockType::FuncType(idx) => Instruction::BlockWithFuncType(idx, 0),
435+
wasmparser::BlockType::Type(ty) => Instruction::BlockWithType(convert_valtype(&ty), 0),
436+
})
415437
}
416438

417439
fn visit_loop(&mut self, ty: wasmparser::BlockType) -> Self::Output {
418440
self.label_ptrs.push(self.instructions.len());
419-
self.instructions.push(Instruction::Loop(convert_blocktype(ty), 0))
441+
self.instructions.push(match ty {
442+
wasmparser::BlockType::Empty => Instruction::Loop(0),
443+
wasmparser::BlockType::FuncType(idx) => Instruction::LoopWithFuncType(idx, 0),
444+
wasmparser::BlockType::Type(ty) => Instruction::LoopWithType(convert_valtype(&ty), 0),
445+
})
420446
}
421447

422448
fn visit_if(&mut self, ty: wasmparser::BlockType) -> Self::Output {
423449
self.label_ptrs.push(self.instructions.len());
424-
self.instructions.push(Instruction::If(convert_blocktype(ty).into(), 0, 0))
450+
self.instructions.push(match ty {
451+
wasmparser::BlockType::Empty => Instruction::If(0, 0),
452+
wasmparser::BlockType::FuncType(idx) => Instruction::IfWithFuncType(idx, 0, 0),
453+
wasmparser::BlockType::Type(ty) => Instruction::IfWithType(convert_valtype(&ty), 0, 0),
454+
})
425455
}
426456

427457
fn visit_else(&mut self) -> Self::Output {
@@ -451,12 +481,18 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild
451481
};
452482

453483
let if_instruction = &mut self.instructions[if_label_pointer];
454-
let Instruction::If(_, else_offset, end_offset) = if_instruction else {
455-
self.errors.push(crate::ParseError::UnsupportedOperator(
456-
"Expected to end an if block, but the last label was not an if".to_string(),
457-
));
458484

459-
return;
485+
let (else_offset, end_offset) = match if_instruction {
486+
Instruction::If(else_offset, end_offset)
487+
| Instruction::IfWithFuncType(_, else_offset, end_offset)
488+
| Instruction::IfWithType(_, else_offset, end_offset) => (else_offset, end_offset),
489+
_ => {
490+
self.errors.push(crate::ParseError::UnsupportedOperator(
491+
"Expected to end an if block, but the last label was not an if".to_string(),
492+
));
493+
494+
return;
495+
}
460496
};
461497

462498
*else_offset = (label_pointer - if_label_pointer)
@@ -467,9 +503,15 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild
467503
.try_into()
468504
.expect("else_instr_end_offset is too large, tinywasm does not support blocks that large");
469505
}
470-
Some(Instruction::Block(_, end_offset))
471-
| Some(Instruction::Loop(_, end_offset))
472-
| Some(Instruction::If(_, _, end_offset)) => {
506+
Some(Instruction::Block(end_offset))
507+
| Some(Instruction::BlockWithType(_, end_offset))
508+
| Some(Instruction::BlockWithFuncType(_, end_offset))
509+
| Some(Instruction::Loop(end_offset))
510+
| Some(Instruction::LoopWithFuncType(_, end_offset))
511+
| Some(Instruction::LoopWithType(_, end_offset))
512+
| Some(Instruction::If(_, end_offset))
513+
| Some(Instruction::IfWithFuncType(_, _, end_offset))
514+
| Some(Instruction::IfWithType(_, _, end_offset)) => {
473515
*end_offset = (current_instr_ptr - label_pointer)
474516
.try_into()
475517
.expect("else_instr_end_offset is too large, tinywasm does not support blocks that large");

crates/tinywasm/Cargo.toml

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,6 @@ tinywasm-parser={version="0.7.0", path="../parser", default-features=false, opti
1919
tinywasm-types={version="0.7.0", path="../types", default-features=false}
2020
libm={version="0.2", default-features=false}
2121

22-
# maybe?
23-
# arrayvec={version="0.7"} instead of the custom implementation
24-
# bumpalo={version="3.16"}
25-
# wide= for simd
26-
# vec1= might be useful? fast .last() and .first() access
27-
# https://github.com/lumol-org/soa-derive could be useful for the memory layout of Stacks
28-
29-
#https://alic.dev/blog/dense-enums
30-
# https://docs.rs/tagged-pointer/latest/tagged_pointer/
31-
3222
[dev-dependencies]
3323
wasm-testsuite={path="../wasm-testsuite"}
3424
wast={version="212.0"}

crates/tinywasm/src/func.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::runtime::{CallFrame, Stack};
1+
use crate::interpreter::{CallFrame, Stack};
22
use crate::{log, unlikely, Function};
33
use crate::{Error, FuncContext, Result, Store};
44
use alloc::{boxed::Box, format, string::String, string::ToString, vec, vec::Vec};
@@ -59,7 +59,7 @@ impl FuncHandle {
5959
};
6060

6161
// 6. Let f be the dummy frame
62-
let call_frame = CallFrame::new(wasm_func.clone(), func_inst.owner, params, 0);
62+
let call_frame = CallFrame::new(wasm_func.clone(), func_inst._owner, params, 0);
6363

6464
// 7. Push the frame f to the call stack
6565
// & 8. Push the values to the stack (Not needed since the call frame owns the values)

crates/tinywasm/src/imports.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ impl Imports {
348348
) -> Result<ResolvedImports> {
349349
let mut imports = ResolvedImports::new();
350350

351-
for import in module.data.imports.iter() {
351+
for import in module.0.imports.iter() {
352352
let val = self.take(store, import).ok_or_else(|| LinkingError::unknown_import(import))?;
353353

354354
match val {
@@ -368,7 +368,7 @@ impl Imports {
368368
}
369369
(Extern::Function(extern_func), ImportKind::Function(ty)) => {
370370
let import_func_type = module
371-
.data
371+
.0
372372
.func_types
373373
.get(*ty as usize)
374374
.ok_or_else(|| LinkingError::incompatible_import_type(import))?;
@@ -409,7 +409,7 @@ impl Imports {
409409
(ExternVal::Func(func_addr), ImportKind::Function(ty)) => {
410410
let func = store.get_func(func_addr)?;
411411
let import_func_type = module
412-
.data
412+
.0
413413
.func_types
414414
.get(*ty as usize)
415415
.ok_or_else(|| LinkingError::incompatible_import_type(import))?;

crates/tinywasm/src/instance.rs

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -64,45 +64,39 @@ impl ModuleInstance {
6464

6565
let idx = store.next_module_instance_idx();
6666
let mut addrs = imports.unwrap_or_default().link(store, &module, idx)?;
67-
let data = module.data;
6867

69-
addrs.funcs.extend(store.init_funcs(data.funcs.into(), idx)?);
70-
addrs.tables.extend(store.init_tables(data.table_types.into(), idx)?);
71-
addrs.memories.extend(store.init_memories(data.memory_types.into(), idx)?);
68+
addrs.funcs.extend(store.init_funcs(module.0.funcs.into(), idx)?);
69+
addrs.tables.extend(store.init_tables(module.0.table_types.into(), idx)?);
70+
addrs.memories.extend(store.init_memories(module.0.memory_types.into(), idx)?);
7271

73-
let global_addrs = store.init_globals(addrs.globals, data.globals.into(), &addrs.funcs, idx)?;
72+
let global_addrs = store.init_globals(addrs.globals, module.0.globals.into(), &addrs.funcs, idx)?;
7473
let (elem_addrs, elem_trapped) =
75-
store.init_elements(&addrs.tables, &addrs.funcs, &global_addrs, &data.elements, idx)?;
76-
let (data_addrs, data_trapped) = store.init_datas(&addrs.memories, data.data.into(), idx)?;
74+
store.init_elements(&addrs.tables, &addrs.funcs, &global_addrs, &module.0.elements, idx)?;
75+
let (data_addrs, data_trapped) = store.init_datas(&addrs.memories, module.0.data.into(), idx)?;
7776

7877
let instance = ModuleInstanceInner {
7978
failed_to_instantiate: elem_trapped.is_some() || data_trapped.is_some(),
8079
store_id: store.id(),
8180
idx,
82-
types: data.func_types,
81+
types: module.0.func_types,
8382
func_addrs: addrs.funcs.into_boxed_slice(),
8483
table_addrs: addrs.tables.into_boxed_slice(),
8584
mem_addrs: addrs.memories.into_boxed_slice(),
8685
global_addrs: global_addrs.into_boxed_slice(),
8786
elem_addrs,
8887
data_addrs,
89-
func_start: data.start_func,
90-
imports: data.imports,
91-
exports: data.exports,
88+
func_start: module.0.start_func,
89+
imports: module.0.imports,
90+
exports: module.0.exports,
9291
};
9392

9493
let instance = ModuleInstance::new(instance);
9594
store.add_instance(instance.clone());
9695

97-
if let Some(trap) = elem_trapped {
98-
return Err(trap.into());
99-
};
100-
101-
if let Some(trap) = data_trapped {
102-
return Err(trap.into());
103-
};
104-
105-
Ok(instance)
96+
match (elem_trapped, data_trapped) {
97+
(Some(trap), _) | (_, Some(trap)) => Err(trap.into()),
98+
_ => Ok(instance),
99+
}
106100
}
107101

108102
/// Get a export by name
@@ -224,13 +218,13 @@ impl ModuleInstance {
224218
/// Get a memory by address
225219
pub fn memory<'a>(&self, store: &'a mut Store, addr: MemAddr) -> Result<MemoryRef<'a>> {
226220
let mem = store.get_mem(self.resolve_mem_addr(addr)?)?;
227-
Ok(MemoryRef { instance: mem.borrow() })
221+
Ok(MemoryRef(mem.borrow()))
228222
}
229223

230224
/// Get a memory by address (mutable)
231225
pub fn memory_mut<'a>(&self, store: &'a mut Store, addr: MemAddr) -> Result<MemoryRefMut<'a>> {
232226
let mem = store.get_mem(self.resolve_mem_addr(addr)?)?;
233-
Ok(MemoryRefMut { instance: mem.borrow_mut() })
227+
Ok(MemoryRefMut(mem.borrow_mut()))
234228
}
235229

236230
/// Get the start function of the module

0 commit comments

Comments
 (0)