From becbc9a22776f543102c953622493693b0572488 Mon Sep 17 00:00:00 2001 From: Filippo Costa Date: Sun, 22 Dec 2024 16:20:17 +0100 Subject: [PATCH] Add support for variadic functions Signed-off-by: Filippo Costa --- examples/hello_world.rs | 3 ++- src/lib.rs | 22 +++++++++++----------- src/tests.rs | 14 ++++++++++++++ 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/examples/hello_world.rs b/examples/hello_world.rs index 02a9cd6..ec35310 100644 --- a/examples/hello_world.rs +++ b/examples/hello_world.rs @@ -34,15 +34,16 @@ fn generate_main_func(module: &mut Module) { Instr::Call( "add".into(), vec![(Type::Word, Value::Const(1)), (Type::Word, Value::Const(1))], + None, ), ); - // TODO: The example shows a variadic call. We don't have those yet func.add_instr(Instr::Call( "printf".into(), vec![ (Type::Long, Value::Global("fmt".into())), (Type::Word, Value::Temporary("r".into())), ], + Some(1), )); func.add_instr(Instr::Ret(Some(Value::Const(0)))); diff --git a/src/lib.rs b/src/lib.rs index 277a3b9..f1d500c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -57,7 +57,7 @@ pub enum Instr<'a> { /// Unconditionally jumps to a label Jmp(String), /// Calls a function - Call(String, Vec<(Type<'a>, Value)>), + Call(String, Vec<(Type<'a>, Value)>, Option), /// Allocates a 4-byte aligned area on the stack Alloc4(u32), /// Allocates a 8-byte aligned area on the stack @@ -122,16 +122,16 @@ impl<'a> fmt::Display for Instr<'a> { write!(f, "jnz {}, @{}, @{}", val, if_nonzero, if_zero) } Self::Jmp(label) => write!(f, "jmp @{}", label), - Self::Call(name, args) => { - write!( - f, - "call ${}({})", - name, - args.iter() - .map(|(ty, temp)| format!("{} {}", ty, temp)) - .collect::>() - .join(", "), - ) + Self::Call(name, args, opt_variadic_i) => { + let mut args_fmt = args + .iter() + .map(|(ty, temp)| format!("{} {}", ty, temp)) + .collect::>(); + if let Some(i) = *opt_variadic_i { + args_fmt.insert(i as usize, "...".to_string()); + } + + write!(f, "call ${}({})", name, args_fmt.join(", "),) } Self::Alloc4(size) => write!(f, "alloc4 {}", size), Self::Alloc8(size) => write!(f, "alloc8 {}", size), diff --git a/src/tests.rs b/src/tests.rs index 91410e7..9658192 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -266,3 +266,17 @@ fn add_function_to_module() { assert_eq!(module.functions.into_iter().next().unwrap(), function); } + +#[test] +fn variadic_call() { + let instr = Instr::Call( + "printf".into(), + vec![ + (Type::Long, Value::Global("fmt".into())), + (Type::Word, Value::Const(0)), + ], + Some(1), + ); + + assert_eq!(instr.to_string(), "call $printf(l $fmt, ..., w 0)"); +}