Stop leaking stack space on function call
This commit is contained in:
@@ -346,8 +346,9 @@ pub fn copy_incoming_arg(ctx: &mut Context, frame_size: u32, arg_pos: u32) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pass_outgoing_args(ctx: &mut Context, arity: u32) {
|
#[must_use]
|
||||||
let mut stack_args = vec![];
|
fn pass_outgoing_args(ctx: &mut Context, arity: u32) -> i32 {
|
||||||
|
let mut stack_args = Vec::with_capacity((arity as usize).saturating_sub(ARGS_IN_GPRS.len()));
|
||||||
for arg_pos in (0..arity).rev() {
|
for arg_pos in (0..arity).rev() {
|
||||||
ctx.sp_depth.free(1);
|
ctx.sp_depth.free(1);
|
||||||
|
|
||||||
@@ -368,22 +369,39 @@ pub fn pass_outgoing_args(ctx: &mut Context, arity: u32) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for gpr in stack_args {
|
let num_stack_args = stack_args.len() as i32;
|
||||||
|
dynasm!(ctx.asm
|
||||||
|
; sub rsp, num_stack_args
|
||||||
|
);
|
||||||
|
for (stack_slot, gpr) in stack_args.into_iter().rev().enumerate() {
|
||||||
|
let offset = (stack_slot * WORD_SIZE as usize) as i32;
|
||||||
dynasm!(ctx.asm
|
dynasm!(ctx.asm
|
||||||
; push Rq(gpr)
|
; mov [rsp + offset], Rq(gpr)
|
||||||
);
|
);
|
||||||
ctx.regs.release_scratch_gpr(gpr);
|
ctx.regs.release_scratch_gpr(gpr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
num_stack_args
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call_direct(ctx: &mut Context, index: u32, return_arity: u32) {
|
fn post_call_cleanup(ctx: &mut Context, num_stack_args: i32) {
|
||||||
|
dynasm!(ctx.asm
|
||||||
|
; add rsp, num_stack_args
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn call_direct(ctx: &mut Context, index: u32, arg_arity: u32, return_arity: u32) {
|
||||||
assert!(return_arity == 0 || return_arity == 1);
|
assert!(return_arity == 0 || return_arity == 1);
|
||||||
|
|
||||||
|
let num_stack_args = pass_outgoing_args(ctx, arg_arity);
|
||||||
|
|
||||||
let label = &ctx.func_starts[index as usize].1;
|
let label = &ctx.func_starts[index as usize].1;
|
||||||
dynasm!(ctx.asm
|
dynasm!(ctx.asm
|
||||||
; call =>*label
|
; call =>*label
|
||||||
);
|
);
|
||||||
|
|
||||||
|
post_call_cleanup(ctx, num_stack_args);
|
||||||
|
|
||||||
if return_arity == 1 {
|
if return_arity == 1 {
|
||||||
dynasm!(ctx.asm
|
dynasm!(ctx.asm
|
||||||
; push rax
|
; push rax
|
||||||
|
|||||||
@@ -225,8 +225,12 @@ pub fn translate(
|
|||||||
|
|
||||||
// TODO: this implementation assumes that this function is locally defined.
|
// TODO: this implementation assumes that this function is locally defined.
|
||||||
|
|
||||||
pass_outgoing_args(&mut ctx, callee_ty.params.len() as u32);
|
call_direct(
|
||||||
call_direct(&mut ctx, function_index, callee_ty.returns.len() as u32);
|
&mut ctx,
|
||||||
|
function_index,
|
||||||
|
callee_ty.params.len() as u32,
|
||||||
|
callee_ty.returns.len() as u32,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
trap(&mut ctx);
|
trap(&mut ctx);
|
||||||
|
|||||||
Reference in New Issue
Block a user