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

Commit f13e225

Browse files
feat: basic i32 loads/stores
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
1 parent b87eea6 commit f13e225

File tree

8 files changed

+70
-10
lines changed

8 files changed

+70
-10
lines changed

crates/parser/src/conversion.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,8 @@ pub(crate) fn convert_memarg(memarg: wasmparser::MemArg) -> MemArg {
280280
MemArg {
281281
offset: memarg.offset,
282282
align: memarg.align,
283+
align_max: memarg.max_align,
284+
mem_addr: memarg.memory,
283285
}
284286
}
285287

crates/tinywasm/src/runtime/executor/mod.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::{
77
runtime::{BlockType, LabelFrame},
88
CallFrame, Error, ModuleInstance, Result, Store,
99
};
10-
use alloc::{format, vec::Vec};
10+
use alloc::vec::Vec;
1111
use log::info;
1212
use tinywasm_types::Instruction;
1313

@@ -302,6 +302,32 @@ fn exec_one(
302302
}
303303
}
304304

305+
I32Store(arg) => {
306+
let mem_idx = module.resolve_mem_addr(arg.mem_addr);
307+
let mem = store.get_mem(mem_idx as usize)?;
308+
309+
let val = stack.values.pop()?.raw_value();
310+
let addr = stack.values.pop()?.raw_value();
311+
312+
mem.borrow_mut()
313+
.store((arg.offset + addr) as usize, arg.align as usize, &val.to_le_bytes())?;
314+
}
315+
316+
I32Load(arg) => {
317+
let mem_idx = module.resolve_mem_addr(arg.mem_addr);
318+
let mem = store.get_mem(mem_idx as usize)?;
319+
320+
let addr = stack.values.pop()?.raw_value();
321+
322+
let val: [u8; 4] = {
323+
let mem = mem.borrow_mut();
324+
let val = mem.load((arg.offset + addr) as usize, arg.align as usize, 4)?;
325+
val.try_into().expect("slice with incorrect length")
326+
};
327+
328+
stack.values.push(i32::from_le_bytes(val).into());
329+
}
330+
305331
I64Eqz => comp_zero!(==, i64, stack),
306332
I32Eqz => comp_zero!(==, i32, stack),
307333

crates/tinywasm/src/runtime/value.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ impl Debug for RawWasmValue {
1717
}
1818

1919
impl RawWasmValue {
20+
pub fn raw_value(&self) -> u64 {
21+
self.0
22+
}
23+
2024
pub fn attach_type(self, ty: ValType) -> WasmValue {
2125
match ty {
2226
ValType::I32 => WasmValue::I32(self.0 as i32),

crates/tinywasm/src/store.rs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use core::{
55

66
use alloc::{format, rc::Rc, string::ToString, vec, vec::Vec};
77
use tinywasm_types::{
8-
Addr, Data, Element, ElementKind, FuncAddr, Function, Global, GlobalType, Import, Instruction, MemAddr, MemoryArch,
9-
MemoryType, ModuleInstanceAddr, TableAddr, TableType, TypeAddr, ValType,
8+
Addr, Data, Element, ElementKind, FuncAddr, Function, Global, GlobalType, Import, Instruction, MemAddr, MemArg,
9+
MemoryArch, MemoryType, ModuleInstanceAddr, TableAddr, TableType, TypeAddr, ValType,
1010
};
1111

1212
use crate::{
@@ -343,6 +343,35 @@ impl MemoryInstance {
343343
}
344344
}
345345

346+
pub(crate) fn store(&mut self, addr: usize, align: usize, data: &[u8]) -> Result<()> {
347+
if addr + data.len() > self.data.len() {
348+
return Err(Error::Other(format!(
349+
"memory store out of bounds: offset={}, len={}, mem_size={}",
350+
addr,
351+
data.len(),
352+
self.data.len()
353+
)));
354+
}
355+
356+
// WebAssembly doesn't require alignment for stores
357+
self.data[addr..addr + data.len()].copy_from_slice(data);
358+
Ok(())
359+
}
360+
361+
pub(crate) fn load(&self, addr: usize, align: usize, len: usize) -> Result<&[u8]> {
362+
if addr + len > self.data.len() {
363+
return Err(Error::Other(format!(
364+
"memory load out of bounds: offset={}, len={}, mem_size={}",
365+
addr,
366+
len,
367+
self.data.len()
368+
)));
369+
}
370+
371+
// WebAssembly doesn't require alignment for loads
372+
Ok(&self.data[addr..addr + len])
373+
}
374+
346375
pub(crate) fn size(&self) -> i32 {
347376
self.page_count as i32
348377
}

crates/tinywasm/tests/generated/mvp.csv

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

crates/tinywasm/tests/generated/progress-mvp.svg

Lines changed: 3 additions & 3 deletions
Loading

crates/tinywasm/tests/test-mvp.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ fn main() -> Result<()> {
1010
fn test_mvp() -> Result<()> {
1111
let mut test_suite = TestSuite::new();
1212

13-
// currently hangs, so skip it for now
14-
test_suite.skip(&["fac.wast"]);
15-
1613
TestSuite::set_log_level(log::LevelFilter::Off);
1714
test_suite.run_spec_group(wasm_testsuite::MVP_TESTS)?;
1815

crates/types/src/instructions.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ pub enum BlockArgs {
1212
/// Represents a memory immediate in a WebAssembly memory instruction.
1313
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1414
pub struct MemArg {
15+
pub mem_addr: MemAddr,
1516
pub align: u8,
17+
pub align_max: u8,
1618
pub offset: u64,
1719
}
1820

0 commit comments

Comments
 (0)