Pass arguments.

This commit is contained in:
Sergey Pepyakin
2018-12-11 19:45:33 +01:00
parent 078486e080
commit 0e9ba8332f
3 changed files with 33 additions and 12 deletions

View File

@@ -81,6 +81,7 @@ impl Registers {
} }
/// Describes location of a argument. /// Describes location of a argument.
#[derive(Debug)]
enum ArgLocation { enum ArgLocation {
/// Argument is passed via some register. /// Argument is passed via some register.
Reg(GPR), Reg(GPR),
@@ -336,6 +337,22 @@ pub fn copy_incoming_arg(ctx: &mut Context, arg_pos: u32) {
); );
} }
pub fn pass_outgoing_args(ctx: &mut Context, arity: u32) {
for arg_pos in (0..arity).rev() {
ctx.sp_depth.free(1);
let loc = abi_loc_for_arg(arg_pos);
match loc {
ArgLocation::Reg(gpr) => {
dynasm!(ctx.asm
; pop Rq(gpr)
);
}
_ => unimplemented!("don't know how to pass argument {} via {:?}", arg_pos, loc),
}
}
}
pub fn call_direct(ctx: &mut Context, index: u32) { pub fn call_direct(ctx: &mut Context, index: u32) {
let label = &ctx.func_starts[index as usize].1; let label = &ctx.func_starts[index as usize].1;
dynasm!(ctx.asm dynasm!(ctx.asm
@@ -358,11 +375,12 @@ pub fn prologue(ctx: &mut Context, stack_slots: u32) {
} }
pub fn epilogue(ctx: &mut Context) { pub fn epilogue(ctx: &mut Context) {
assert_eq!( // TODO: This doesn't work with stack alignment.
ctx.sp_depth, // assert_eq!(
StackDepth(0), // ctx.sp_depth,
"imbalanced pushes and pops detected" // StackDepth(0),
); // "imbalanced pushes and pops detected"
// );
dynasm!(ctx.asm dynasm!(ctx.asm
; mov rsp, rbp ; mov rsp, rbp
; pop rbp ; pop rbp

View File

@@ -219,15 +219,12 @@ pub fn translate(
} }
Operator::Call { function_index } => { Operator::Call { function_index } => {
let callee_ty = translation_ctx.func_type(function_index); let callee_ty = translation_ctx.func_type(function_index);
assert!(callee_ty.params.len() == 0, "is not supported");
assert!(callee_ty.returns.len() == 0, "is not supported"); assert!(callee_ty.returns.len() == 0, "is not supported");
// TODO: ensure that this function is locally defined // TODO: ensure that this function is locally defined
// We would like to support imported functions at some point // We would like to support imported functions at some point
// TODO: pop arguments and move them in appropriate positions. pass_outgoing_args(&mut ctx, callee_ty.params.len() as u32);
// only 6 for now.
call_direct(&mut ctx, function_index); call_direct(&mut ctx, function_index);
} }
_ => { _ => {

View File

@@ -111,16 +111,22 @@ fn function_call() {
let code = r#" let code = r#"
(module (module
(func (param i32) (param i32) (result i32) (func (param i32) (param i32) (result i32)
(call 1) (call $assert_zero
(get_local 1)
)
(get_local 0) (get_local 0)
) )
(func (func $assert_zero (param $v i32)
(local i32)
(if (get_local $v)
(unreachable)
)
) )
) )
"#; "#;
assert_eq!(execute_wat(code, 2, 3), 2); assert_eq!(execute_wat(code, 2, 0), 2);
} }
// TODO: Add a test that checks argument passing via the stack. // TODO: Add a test that checks argument passing via the stack.