From aef97d440c4db5f87d0b7b8e043c6f218e0942a6 Mon Sep 17 00:00:00 2001 From: Maxime Chevalier-Boisvert Date: Sun, 26 Nov 2023 23:40:15 -0500 Subject: [PATCH] Add call_fp (call function pointer). Requested in #39. --- vm/src/asm.rs | 8 ++++++++ vm/src/vm.rs | 32 +++++++++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/vm/src/asm.rs b/vm/src/asm.rs index a6eb349..d634de9 100644 --- a/vm/src/asm.rs +++ b/vm/src/asm.rs @@ -1154,6 +1154,7 @@ impl Assembler self.code.push_u16(syscall_idx); } + // Call label "call" => { let label_name = input.parse_ident()?; input.expect_token(",")?; @@ -1164,6 +1165,13 @@ impl Assembler self.code.push_u8(argc); } + // Call function pointer + "call_fp" => { + let argc: u8 = self.parse_int_arg(input)?; + self.code.push_op(Op::call_fp); + self.code.push_u8(argc); + } + "ret" => self.code.push_op(Op::ret), "exit" => self.code.push_op(Op::exit), diff --git a/vm/src/vm.rs b/vm/src/vm.rs index cbf3468..ba0c133 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -244,8 +244,8 @@ pub enum Op call, // Call a function pointer passed as argument - // call (f_ptr, arg0, arg1, ..., argN) - //call_fp, + // call (arg0, arg1, ..., argN, f_ptr) + call_fp, // Call into a host function // For example, to set up a device or to allocate more memory @@ -1440,6 +1440,26 @@ impl VM pc = ((pc as isize) + offset) as usize; } + // call (arg0, arg1, ..., argN, f_ptr) + Op::call_fp => { + // Absolute address of the function to call + let fp = self.pop(); + + // Argument count + let num_args = self.code.read_pc::(&mut pc) as usize; + assert!(num_args <= self.stack.len() - bp); + + self.frames.push(StackFrame { + prev_bp: bp, + ret_addr: pc, + argc: num_args, + }); + + // The base pointer will point at the first local + bp = self.stack.len(); + pc = fp.as_usize(); + } + Op::syscall => { let syscall_idx = self.code.read_pc::(&mut pc); let syscall_fn = self.sys_state.get_syscall(syscall_idx); @@ -1593,7 +1613,7 @@ mod tests // Keep track of how many short opcodes we have so far dbg!(Op::exit as usize); - assert!(Op::exit as usize <= 112); + assert!(Op::exit as usize <= 113); } #[test] @@ -1681,6 +1701,12 @@ mod tests eval_i64("push 5; call foo, 0; pop; exit; foo: push 2; push 0; ret;", 5); } + #[test] + fn test_call_fp() + { + eval_i64(" push FN; call_fp 0; exit; FN: push_i8 33; ret;", 33); + } + #[test] fn test_syscalls() {