machinst ABI: Support for accumulating outgoing args
When performing a function call, the platform ABI may require space on the stack to hold outgoing arguments and/or return values. Currently, this is supported via decrementing the stack pointer before the call and incrementing it afterwards, using the emit_stack_pre_adjust and emit_stack_post_adjust methods of ABICaller. However, on some platforms it would be preferable to just allocate enough space for any call done in the function in the caller's prologue instead. This patch adds support to allow back-ends to choose that method. Instead of calling emit_stack_pre/post_adjust around a call, they simply call a new accumulate_outgoing_args_size method of ABICaller instead. This will pass on the required size to the ABICallee structure of the calling function, which will accumulate the maximum size required for all function calls. That accumulated size is then passed to the gen_clobber_save and gen_clobber_restore functions so they can include the size in the stack allocation / deallocation that already happens in the prologue / epilogue code.
This commit is contained in:
@@ -329,6 +329,7 @@ pub trait ABIMachineSpec {
|
||||
flags: &settings::Flags,
|
||||
clobbers: &Set<Writable<RealReg>>,
|
||||
fixed_frame_storage_size: u32,
|
||||
outgoing_args_size: u32,
|
||||
) -> (u64, SmallVec<[Self::I; 16]>);
|
||||
|
||||
/// Generate a clobber-restore sequence. This sequence should perform the
|
||||
@@ -340,6 +341,7 @@ pub trait ABIMachineSpec {
|
||||
flags: &settings::Flags,
|
||||
clobbers: &Set<Writable<RealReg>>,
|
||||
fixed_frame_storage_size: u32,
|
||||
outgoing_args_size: u32,
|
||||
) -> SmallVec<[Self::I; 16]>;
|
||||
|
||||
/// Generate a call instruction/sequence. This method is provided one
|
||||
@@ -435,6 +437,8 @@ pub struct ABICalleeImpl<M: ABIMachineSpec> {
|
||||
stackslots: Vec<u32>,
|
||||
/// Total stack size of all stackslots.
|
||||
stackslots_size: u32,
|
||||
/// Stack size to be reserved for outgoing arguments.
|
||||
outgoing_args_size: u32,
|
||||
/// Clobbered registers, from regalloc.
|
||||
clobbered: Set<Writable<RealReg>>,
|
||||
/// Total number of spillslots, from regalloc.
|
||||
@@ -527,6 +531,7 @@ impl<M: ABIMachineSpec> ABICalleeImpl<M> {
|
||||
sig,
|
||||
stackslots,
|
||||
stackslots_size: stack_offset,
|
||||
outgoing_args_size: 0,
|
||||
clobbered: Set::empty(),
|
||||
spillslots: None,
|
||||
fixed_frame_storage_size: 0,
|
||||
@@ -690,6 +695,12 @@ impl<M: ABIMachineSpec> ABICallee for ABICalleeImpl<M> {
|
||||
}
|
||||
}
|
||||
|
||||
fn accumulate_outgoing_args_size(&mut self, size: u32) {
|
||||
if size > self.outgoing_args_size {
|
||||
self.outgoing_args_size = size;
|
||||
}
|
||||
}
|
||||
|
||||
fn flags(&self) -> &settings::Flags {
|
||||
&self.flags
|
||||
}
|
||||
@@ -978,11 +989,13 @@ impl<M: ABIMachineSpec> ABICallee for ABICalleeImpl<M> {
|
||||
&self.flags,
|
||||
&self.clobbered,
|
||||
self.fixed_frame_storage_size,
|
||||
self.outgoing_args_size,
|
||||
);
|
||||
insts.extend(clobber_insts);
|
||||
|
||||
if clobber_size > 0 {
|
||||
insts.push(M::gen_nominal_sp_adj(clobber_size as i32));
|
||||
let sp_adj = self.outgoing_args_size as i32 + clobber_size as i32;
|
||||
if sp_adj > 0 {
|
||||
insts.push(M::gen_nominal_sp_adj(sp_adj));
|
||||
}
|
||||
|
||||
self.total_frame_size = Some(total_stacksize);
|
||||
@@ -998,6 +1011,7 @@ impl<M: ABIMachineSpec> ABICallee for ABICalleeImpl<M> {
|
||||
&self.flags,
|
||||
&self.clobbered,
|
||||
self.fixed_frame_storage_size,
|
||||
self.outgoing_args_size,
|
||||
));
|
||||
|
||||
// N.B.: we do *not* emit a nominal SP adjustment here, because (i) there will be no
|
||||
@@ -1180,6 +1194,11 @@ impl<M: ABIMachineSpec> ABICaller for ABICallerImpl<M> {
|
||||
}
|
||||
}
|
||||
|
||||
fn accumulate_outgoing_args_size<C: LowerCtx<I = Self::I>>(&self, ctx: &mut C) {
|
||||
let off = self.sig.stack_arg_space + self.sig.stack_ret_space;
|
||||
ctx.abi().accumulate_outgoing_args_size(off as u32);
|
||||
}
|
||||
|
||||
fn emit_stack_pre_adjust<C: LowerCtx<I = Self::I>>(&self, ctx: &mut C) {
|
||||
let off = self.sig.stack_arg_space + self.sig.stack_ret_space;
|
||||
adjust_stack_and_nominal_sp::<M, C>(ctx, off as i32, /* is_sub = */ true)
|
||||
|
||||
Reference in New Issue
Block a user