summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorHenry Gressmann <mail@henrygressmann.de>2023-12-10 00:49:02 +0100
committerHenry Gressmann <mail@henrygressmann.de>2023-12-10 00:49:02 +0100
commitaa2cbdc66cb2df1fb901164f880d2389f74d438c (patch)
tree84b7cce9e5468110be6ea31e2581c6aacab448d2 /crates
parent085c117cc0de0bb9ae90d4cbe65090ed53189b70 (diff)
feat: function calls
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
Diffstat (limited to 'crates')
-rw-r--r--crates/tinywasm/src/runtime/executor/mod.rs47
-rw-r--r--crates/tinywasm/src/runtime/stack/call_stack.rs12
2 files changed, 44 insertions, 15 deletions
diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs
index 1fbcf3f..b71ae11 100644
--- a/crates/tinywasm/src/runtime/executor/mod.rs
+++ b/crates/tinywasm/src/runtime/executor/mod.rs
@@ -12,18 +12,25 @@ use macros::*;
impl DefaultRuntime {
pub(crate) fn exec(&self, store: &mut Store, stack: &mut Stack, module: ModuleInstance) -> Result<()> {
+ // The current call frame, gets updated inside of exec_one
let mut cf = stack.call_stack.pop()?;
- let func = store.get_func(cf.func_ptr)?.clone();
- let instrs = func.instructions();
+
+ // The function to execute, gets updated from ExecResult::Call
+ let mut func = store.get_func(cf.func_ptr)?.clone();
+ let mut instrs = func.instructions();
while let Some(instr) = instrs.get(cf.instr_ptr) {
match exec_one(&mut cf, instr, instrs, stack, store, &module)? {
+ // Continue execution at the new top of the call stack
+ ExecResult::Call => {
+ func = store.get_func(cf.func_ptr)?.clone();
+ instrs = func.instructions();
+ continue;
+ }
+
// return from the function
ExecResult::Return => return Ok(()),
- // continue to the next instruction and don't increment the instruction pointer
- ExecResult::Continue => continue,
-
// continue to the next instruction and increment the instruction pointer
ExecResult::Ok => {
cf.instr_ptr += 1;
@@ -41,8 +48,8 @@ impl DefaultRuntime {
enum ExecResult {
Ok,
- Continue,
Return,
+ Call,
}
#[inline]
@@ -56,23 +63,35 @@ fn exec_one(
) -> Result<ExecResult> {
use tinywasm_types::Instruction::*;
match instr {
+ Nop => {} // do nothing
+ Unreachable => return Err(Error::Trap(crate::Trap::Unreachable)),
+
+ Return => {
+ debug!("return");
+ }
+
Call(v) => {
+ debug!("start call");
// prepare the call frame
let func = store.get_func(*v as usize)?;
let func_ty = module.func_ty(*v);
- debug!("call: {:?}", func_ty);
- let call_frame = CallFrame::new(*v as usize, &[], func.locals().to_vec());
+
+ debug!("params: {:?}", func_ty.params);
+ debug!("stack: {:?}", stack.values);
+ let params = stack.values.pop_n(func_ty.params.len())?;
+ let call_frame = CallFrame::new_raw(*v as usize, &params, func.locals().to_vec());
// push the call frame
+ cf.instr_ptr += 1; // skip the call instruction
stack.call_stack.push(cf.clone());
stack.call_stack.push(call_frame);
- debug!("call: {:?}", func);
// call the function
*cf = stack.call_stack.pop()?;
+ debug!("calling: {:?}", func);
+ return Ok(ExecResult::Call);
}
- Nop => {} // do nothing
- Unreachable => return Err(Error::Trap(crate::Trap::Unreachable)),
+
Loop(args) => {
cf.blocks.push(BlockFrame {
instr_ptr: cf.instr_ptr,
@@ -82,6 +101,7 @@ fn exec_one(
});
stack.values.block_args(*args)?;
}
+
BrTable(_default, len) => {
let instr = instrs[cf.instr_ptr + 1..cf.instr_ptr + 1 + *len]
.iter()
@@ -97,6 +117,7 @@ fn exec_one(
todo!()
}
+
Br(v) => cf.break_to(*v, &mut stack.values)?,
BrIf(v) => {
let val: i32 = stack.values.pop().ok_or(Error::StackUnderflow)?.into();
@@ -113,8 +134,7 @@ fn exec_one(
} else {
debug!("end: no block to end, returning to parent call frame");
*cf = stack.call_stack.pop()?;
- cf.instr_ptr = cf.instr_ptr.saturating_sub(1);
- return Ok(ExecResult::Continue);
+ return Ok(ExecResult::Call);
}
};
debug!("end, blocks: {:?}", blocks);
@@ -140,6 +160,7 @@ fn exec_one(
}
}
}
+
LocalGet(local_index) => {
debug!("local.get: {:?}", local_index);
let val = cf.get_local(*local_index as usize);
diff --git a/crates/tinywasm/src/runtime/stack/call_stack.rs b/crates/tinywasm/src/runtime/stack/call_stack.rs
index 6e96e6c..4493dd8 100644
--- a/crates/tinywasm/src/runtime/stack/call_stack.rs
+++ b/crates/tinywasm/src/runtime/stack/call_stack.rs
@@ -101,9 +101,9 @@ impl CallFrame {
Ok(())
}
- pub(crate) fn new(func_ptr: usize, params: &[WasmValue], local_types: Vec<ValType>) -> Self {
+ pub(crate) fn new_raw(func_ptr: usize, params: &[RawWasmValue], local_types: Vec<ValType>) -> Self {
let mut locals = Vec::with_capacity(local_types.len() + params.len());
- locals.extend(params.iter().map(|v| RawWasmValue::from(*v)));
+ locals.extend(params.iter().cloned());
locals.extend(local_types.iter().map(|_| RawWasmValue::default()));
Self {
@@ -115,6 +115,14 @@ impl CallFrame {
}
}
+ pub(crate) fn new(func_ptr: usize, params: &[WasmValue], local_types: Vec<ValType>) -> Self {
+ CallFrame::new_raw(
+ func_ptr,
+ &params.iter().map(|v| RawWasmValue::from(*v)).collect::<Vec<_>>(),
+ local_types,
+ )
+ }
+
#[inline]
pub(crate) fn set_local(&mut self, local_index: usize, value: RawWasmValue) {
if local_index >= self.local_count {