diff --git a/cranelift/codegen/src/isa/aarch64/abi.rs b/cranelift/codegen/src/isa/aarch64/abi.rs index 380d2dfe0bc1..72ff0e6d643a 100644 --- a/cranelift/codegen/src/isa/aarch64/abi.rs +++ b/cranelift/codegen/src/isa/aarch64/abi.rs @@ -587,6 +587,7 @@ impl ABIMachineSpec for AArch64MachineDeps { flags: &settings::Flags, clobbers: &Set>, fixed_frame_storage_size: u32, + _outgoing_args_size: u32, ) -> (u64, SmallVec<[Inst; 16]>) { let mut insts = SmallVec::new(); let (clobbered_int, clobbered_vec) = get_regs_saved_in_prologue(call_conv, clobbers); @@ -691,6 +692,7 @@ impl ABIMachineSpec for AArch64MachineDeps { flags: &settings::Flags, clobbers: &Set>, fixed_frame_storage_size: u32, + _outgoing_args_size: u32, ) -> SmallVec<[Inst; 16]> { let mut insts = SmallVec::new(); let (clobbered_int, clobbered_vec) = get_regs_saved_in_prologue(call_conv, clobbers); diff --git a/cranelift/codegen/src/isa/arm32/abi.rs b/cranelift/codegen/src/isa/arm32/abi.rs index 94627a227c7c..5a4145d8b7d5 100644 --- a/cranelift/codegen/src/isa/arm32/abi.rs +++ b/cranelift/codegen/src/isa/arm32/abi.rs @@ -319,6 +319,7 @@ impl ABIMachineSpec for Arm32MachineDeps { _flags: &settings::Flags, clobbers: &Set>, fixed_frame_storage_size: u32, + _outgoing_args_size: u32, ) -> (u64, SmallVec<[Inst; 16]>) { let mut insts = SmallVec::new(); if fixed_frame_storage_size > 0 { @@ -348,6 +349,7 @@ impl ABIMachineSpec for Arm32MachineDeps { _flags: &settings::Flags, clobbers: &Set>, _fixed_frame_storage_size: u32, + _outgoing_args_size: u32, ) -> SmallVec<[Inst; 16]> { let mut insts = SmallVec::new(); let clobbered_vec = get_callee_saves(clobbers); diff --git a/cranelift/codegen/src/isa/x64/abi.rs b/cranelift/codegen/src/isa/x64/abi.rs index 29a0dbd98250..63a8af7c9b91 100644 --- a/cranelift/codegen/src/isa/x64/abi.rs +++ b/cranelift/codegen/src/isa/x64/abi.rs @@ -500,6 +500,7 @@ impl ABIMachineSpec for X64ABIMachineSpec { flags: &settings::Flags, clobbers: &Set>, fixed_frame_storage_size: u32, + _outgoing_args_size: u32, ) -> (u64, SmallVec<[Self::I; 16]>) { let mut insts = SmallVec::new(); // Find all clobbered registers that are callee-save. @@ -574,6 +575,7 @@ impl ABIMachineSpec for X64ABIMachineSpec { flags: &settings::Flags, clobbers: &Set>, fixed_frame_storage_size: u32, + _outgoing_args_size: u32, ) -> SmallVec<[Self::I; 16]> { let mut insts = SmallVec::new(); diff --git a/cranelift/codegen/src/machinst/abi.rs b/cranelift/codegen/src/machinst/abi.rs index ac4cb7fad2e0..7af9b087c83c 100644 --- a/cranelift/codegen/src/machinst/abi.rs +++ b/cranelift/codegen/src/machinst/abi.rs @@ -30,6 +30,12 @@ pub trait ABICallee { /// Access the (possibly legalized) signature. fn signature(&self) -> &Signature; + /// Accumulate outgoing arguments. This ensures that at least SIZE bytes + /// are allocated in the prologue to be available for use in function calls + /// to hold arguments and/or return values. If this function is called + /// multiple times, the maximum of all SIZE values will be available. + fn accumulate_outgoing_args_size(&mut self, size: u32); + /// Get the settings controlling this function's compilation. fn flags(&self) -> &settings::Flags; @@ -242,6 +248,13 @@ pub trait ABICaller { /// Emit code to post-adjust the satck, after call return and return-value copies. fn emit_stack_post_adjust>(&self, ctx: &mut C); + /// Accumulate outgoing arguments. This ensures that the caller (as + /// identified via the CTX argument) allocates enough space in the + /// prologue to hold all arguments and return values for this call. + /// There is no code emitted at the call site, everything is done + /// in the caller's function prologue. + fn accumulate_outgoing_args_size>(&self, ctx: &mut C); + /// Emit the call itself. /// /// The returned instruction should have proper use- and def-sets according diff --git a/cranelift/codegen/src/machinst/abi_impl.rs b/cranelift/codegen/src/machinst/abi_impl.rs index 85a6d6831b20..2b1b0cae0551 100644 --- a/cranelift/codegen/src/machinst/abi_impl.rs +++ b/cranelift/codegen/src/machinst/abi_impl.rs @@ -444,6 +444,7 @@ pub trait ABIMachineSpec { flags: &settings::Flags, clobbers: &Set>, fixed_frame_storage_size: u32, + outgoing_args_size: u32, ) -> (u64, SmallVec<[Self::I; 16]>); /// Generate a clobber-restore sequence. This sequence should perform the @@ -455,6 +456,7 @@ pub trait ABIMachineSpec { flags: &settings::Flags, clobbers: &Set>, fixed_frame_storage_size: u32, + outgoing_args_size: u32, ) -> SmallVec<[Self::I; 16]>; /// Generate a call instruction/sequence. This method is provided one @@ -576,6 +578,8 @@ pub struct ABICalleeImpl { stackslots: PrimaryMap, /// 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>, /// Total number of spillslots, from regalloc. @@ -691,6 +695,7 @@ impl ABICalleeImpl { sig, stackslots, stackslots_size: stack_offset, + outgoing_args_size: 0, clobbered: Set::empty(), spillslots: None, fixed_frame_storage_size: 0, @@ -917,6 +922,12 @@ impl ABICallee for ABICalleeImpl { } } + 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 } @@ -1290,6 +1301,7 @@ impl ABICallee for ABICalleeImpl { &self.flags, &self.clobbered, self.fixed_frame_storage_size, + self.outgoing_args_size, ); insts.extend(clobber_insts); @@ -1317,6 +1329,7 @@ impl ABICallee for ABICalleeImpl { &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 @@ -1519,6 +1532,11 @@ impl ABICaller for ABICallerImpl { } } + fn accumulate_outgoing_args_size>(&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>(&self, ctx: &mut C) { let off = self.sig.stack_arg_space + self.sig.stack_ret_space; adjust_stack_and_nominal_sp::(ctx, off as i32, /* is_sub = */ true)