Stop leaking stack space on function call

This commit is contained in:
Jef
2018-12-13 10:25:17 +01:00
parent 189996accd
commit 5b448ce3c7
2 changed files with 29 additions and 7 deletions

View File

@@ -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

View File

@@ -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);