summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorHenry <mail@henrygressmann.de>2026-05-02 15:40:47 +0200
committerHenry <mail@henrygressmann.de>2026-05-02 15:45:44 +0200
commit5ed8982ad2cb4b348046aa11c527ce6a51f02e0e (patch)
treec5427ac3ffdeedfa37b698eeb4f2dac09859b4a6 /crates
parent361b715de9ea6a859aaafe84d4bcd3d46ed70797 (diff)
feat: add doom example, fix import argument order
Signed-off-by: Henry <mail@henrygressmann.de>
Diffstat (limited to 'crates')
-rw-r--r--crates/tinywasm/src/interpreter/executor.rs4
-rw-r--r--crates/tinywasm/src/reference.rs13
-rw-r--r--crates/tinywasm/tests/host_import_arg_order.rs31
3 files changed, 47 insertions, 1 deletions
diff --git a/crates/tinywasm/src/interpreter/executor.rs b/crates/tinywasm/src/interpreter/executor.rs
index b1178d8..4d862d6 100644
--- a/crates/tinywasm/src/interpreter/executor.rs
+++ b/crates/tinywasm/src/interpreter/executor.rs
@@ -6,6 +6,7 @@ use super::no_std_floats::NoStdFloatExt;
use alloc::boxed::Box;
use alloc::rc::Rc;
+use alloc::vec::Vec;
use alloc::sync::Arc;
use interpreter::stack::CallFrame;
@@ -969,7 +970,8 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
}
fn exec_call_host(&mut self, host_func: Rc<HostFunction>) -> Result<(), Trap> {
- let params = self.store.value_stack.pop_types(host_func.ty.params()).collect::<Box<_>>();
+ let mut params = self.store.value_stack.pop_types(host_func.ty.params().iter().rev()).collect::<Vec<_>>();
+ params.reverse();
let res = match host_func.call(FuncContext { store: self.store, module_addr: self.module.idx() }, &params) {
Ok(res) => res,
Err(err) => {
diff --git a/crates/tinywasm/src/reference.rs b/crates/tinywasm/src/reference.rs
index 44916b4..5f8d46f 100644
--- a/crates/tinywasm/src/reference.rs
+++ b/crates/tinywasm/src/reference.rs
@@ -261,6 +261,19 @@ impl Memory {
})
}
+ /// Copies a nul-terminated C string into memory.
+ pub fn write_cstring(&self, store: &mut Store, offset: usize, string: &CString) -> Result<()> {
+ self.copy_from_slice(store, offset, string.as_bytes_with_nul())
+ }
+
+ /// Copies a UTF-8 string into memory and appends a trailing nul byte.
+ pub fn write_cstring_bytes(&self, store: &mut Store, offset: usize, string: &str) -> Result<()> {
+ let mut bytes = Vec::with_capacity(string.len() + 1);
+ bytes.extend_from_slice(string.as_bytes());
+ bytes.push(0);
+ self.copy_from_slice(store, offset, &bytes)
+ }
+
/// Reads a C-style string from memory.
pub fn read_cstring(&self, store: &Store, offset: usize, len: usize) -> Result<CString> {
CString::from_vec_with_nul(self.read_vec(store, offset, len)?)
diff --git a/crates/tinywasm/tests/host_import_arg_order.rs b/crates/tinywasm/tests/host_import_arg_order.rs
new file mode 100644
index 0000000..2004641
--- /dev/null
+++ b/crates/tinywasm/tests/host_import_arg_order.rs
@@ -0,0 +1,31 @@
+use tinywasm::{HostFunction, Imports, ModuleInstance, Store};
+
+#[test]
+fn multi_arg_host_imports_preserve_source_order() {
+ let wasm = wat::parse_str(
+ r#"
+ (module
+ (import "env" "pair" (func $pair (param i32 i32) (result i32)))
+ (func (export "call_pair") (param i32 i32) (result i32)
+ local.get 0
+ local.get 1
+ call $pair))
+ "#,
+ )
+ .unwrap();
+
+ let module = tinywasm::parse_bytes(&wasm).unwrap();
+ let mut store = Store::default();
+
+ let pair = HostFunction::from(&mut store, |_ctx, (left, right): (i32, i32)| -> tinywasm::Result<i32> {
+ Ok(left * 1000 + right)
+ });
+
+ let mut imports = Imports::new();
+ imports.define("env", "pair", pair);
+
+ let instance = ModuleInstance::instantiate(&mut store, &module, Some(imports)).unwrap();
+ let func = instance.func::<(i32, i32), i32>(&store, "call_pair").unwrap();
+
+ assert_eq!(func.call(&mut store, (12, 34)).unwrap(), 12034);
+}