Cranelift: Remove the ABICaller trait (#4711)

* Cranelift: Remove the `ABICaller` trait

It has only one implementation: the `ABICallerImpl` struct. We can just use that
directly rather than having extra, unnecessary layers of generics and abstractions.

* Cranelift: Rename `ABICallerImpl` to `Caller`
This commit is contained in:
Nick Fitzgerald
2022-08-15 13:41:08 -07:00
committed by GitHub
parent 1d0f6fa4fb
commit e0d4934ef4
7 changed files with 53 additions and 112 deletions

View File

@@ -1,83 +1,7 @@
//! ABI definitions.
use crate::machinst::*;
use smallvec::SmallVec;
/// A small vector of instructions (with some reasonable size); appropriate for
/// a small fixed sequence implementing one operation.
pub type SmallInstVec<I> = SmallVec<[I; 4]>;
/// Trait implemented by an object that tracks ABI-related state and can
/// generate code while emitting a *call* to a function.
///
/// An instance of this trait returns information for a *particular*
/// callsite. It will usually be computed from the called function's
/// signature.
///
/// Unlike `Callee`, methods on this trait are not invoked directly by the
/// machine-independent code. Rather, the machine-specific lowering code will
/// typically create an `ABICaller` when creating machine instructions for an IR
/// call instruction inside `lower()`, directly emit the arg and and retval
/// copies, and attach the register use/def info to the call.
///
/// This trait is thus provided for convenience to the backends.
pub trait ABICaller {
/// The instruction type for the ISA associated with this ABI.
type I: VCodeInst;
/// Get the number of arguments expected.
fn num_args(&self) -> usize;
/// Emit a copy of an argument value from a source register, prior to the call.
/// For large arguments with associated stack buffer, this may load the address
/// of the buffer into the argument register, if required by the ABI.
fn emit_copy_regs_to_arg(&self, ctx: &mut Lower<Self::I>, idx: usize, from_reg: ValueRegs<Reg>);
/// Emit a copy of a large argument into its associated stack buffer, if any.
/// We must be careful to perform all these copies (as necessary) before setting
/// up the argument registers, since we may have to invoke memcpy(), which could
/// clobber any registers already set up. The back-end should call this routine
/// for all arguments before calling emit_copy_regs_to_arg for all arguments.
fn emit_copy_regs_to_buffer(
&self,
ctx: &mut Lower<Self::I>,
idx: usize,
from_reg: ValueRegs<Reg>,
);
/// Emit a copy a return value into a destination register, after the call returns.
fn emit_copy_retval_to_regs(
&self,
ctx: &mut Lower<Self::I>,
idx: usize,
into_reg: ValueRegs<Writable<Reg>>,
);
/// Emit code to pre-adjust the stack, prior to argument copies and call.
fn emit_stack_pre_adjust(&self, ctx: &mut Lower<Self::I>);
/// Emit code to post-adjust the satck, after call return and return-value copies.
fn emit_stack_post_adjust(&self, ctx: &mut Lower<Self::I>);
/// 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 Lower<Self::I>);
/// Emit the call itself.
///
/// The returned instruction should have proper use- and def-sets according
/// to the argument registers, return-value registers, and clobbered
/// registers for this function signature in this ABI.
///
/// (Arg registers are uses, and retval registers are defs. Clobbered
/// registers are also logically defs, but should never be read; their
/// values are "defined" (to the regalloc) but "undefined" in every other
/// sense.)
///
/// This function should only be called once, as it is allowed to re-use
/// parts of the ABICaller object in emitting instructions.
fn emit_call(&mut self, ctx: &mut Lower<Self::I>);
}

View File

@@ -1638,7 +1638,7 @@ impl<M: ABIMachineSpec> Callee<M> {
}
/// ABI object for a callsite.
pub struct ABICallerImpl<M: ABIMachineSpec> {
pub struct Caller<M: ABIMachineSpec> {
/// The called function's signature.
sig: ABISig,
/// All uses for the callsite, i.e., function args.
@@ -1668,7 +1668,7 @@ pub enum CallDest {
Reg(Reg),
}
impl<M: ABIMachineSpec> ABICallerImpl<M> {
impl<M: ABIMachineSpec> Caller<M> {
/// Create a callsite ABI object for a call directly to the specified function.
pub fn from_func(
sig: &ir::Signature,
@@ -1676,11 +1676,11 @@ impl<M: ABIMachineSpec> ABICallerImpl<M> {
dist: RelocDistance,
caller_conv: isa::CallConv,
flags: &settings::Flags,
) -> CodegenResult<ABICallerImpl<M>> {
) -> CodegenResult<Caller<M>> {
let ir_sig = ensure_struct_return_ptr_is_returned(sig);
let sig = ABISig::from_func_sig::<M>(&ir_sig, flags)?;
let (uses, defs, clobbers) = sig.call_uses_defs_clobbers::<M>();
Ok(ABICallerImpl {
Ok(Caller {
sig,
uses,
defs,
@@ -1701,11 +1701,11 @@ impl<M: ABIMachineSpec> ABICallerImpl<M> {
opcode: ir::Opcode,
caller_conv: isa::CallConv,
flags: &settings::Flags,
) -> CodegenResult<ABICallerImpl<M>> {
) -> CodegenResult<Caller<M>> {
let ir_sig = ensure_struct_return_ptr_is_returned(sig);
let sig = ABISig::from_func_sig::<M>(&ir_sig, flags)?;
let (uses, defs, clobbers) = sig.call_uses_defs_clobbers::<M>();
Ok(ABICallerImpl {
Ok(Caller {
sig,
uses,
defs,
@@ -1730,10 +1730,9 @@ fn adjust_stack_and_nominal_sp<M: ABIMachineSpec>(ctx: &mut Lower<M::I>, off: i3
ctx.emit(M::gen_nominal_sp_adj(-amt));
}
impl<M: ABIMachineSpec> ABICaller for ABICallerImpl<M> {
type I = M::I;
fn num_args(&self) -> usize {
impl<M: ABIMachineSpec> Caller<M> {
/// Get the number of arguments expected.
pub fn num_args(&self) -> usize {
if self.sig.stack_ret_arg.is_some() {
self.sig.args.len() - 1
} else {
@@ -1741,24 +1740,26 @@ impl<M: ABIMachineSpec> ABICaller for ABICallerImpl<M> {
}
}
fn accumulate_outgoing_args_size(&self, ctx: &mut Lower<Self::I>) {
let off = self.sig.sized_stack_arg_space + self.sig.sized_stack_ret_space;
ctx.abi().accumulate_outgoing_args_size(off as u32);
}
fn emit_stack_pre_adjust(&self, ctx: &mut Lower<Self::I>) {
/// Emit code to pre-adjust the stack, prior to argument copies and call.
pub fn emit_stack_pre_adjust(&self, ctx: &mut Lower<M::I>) {
let off = self.sig.sized_stack_arg_space + self.sig.sized_stack_ret_space;
adjust_stack_and_nominal_sp::<M>(ctx, off as i32, /* is_sub = */ true)
}
fn emit_stack_post_adjust(&self, ctx: &mut Lower<Self::I>) {
/// Emit code to post-adjust the satck, after call return and return-value copies.
pub fn emit_stack_post_adjust(&self, ctx: &mut Lower<M::I>) {
let off = self.sig.sized_stack_arg_space + self.sig.sized_stack_ret_space;
adjust_stack_and_nominal_sp::<M>(ctx, off as i32, /* is_sub = */ false)
}
fn emit_copy_regs_to_buffer(
/// Emit a copy of a large argument into its associated stack buffer, if any.
/// We must be careful to perform all these copies (as necessary) before setting
/// up the argument registers, since we may have to invoke memcpy(), which could
/// clobber any registers already set up. The back-end should call this routine
/// for all arguments before calling emit_copy_regs_to_arg for all arguments.
pub fn emit_copy_regs_to_buffer(
&self,
ctx: &mut Lower<Self::I>,
ctx: &mut Lower<M::I>,
idx: usize,
from_regs: ValueRegs<Reg>,
) {
@@ -1788,9 +1789,12 @@ impl<M: ABIMachineSpec> ABICaller for ABICallerImpl<M> {
}
}
fn emit_copy_regs_to_arg(
/// Emit a copy of an argument value from a source register, prior to the call.
/// For large arguments with associated stack buffer, this may load the address
/// of the buffer into the argument register, if required by the ABI.
pub fn emit_copy_regs_to_arg(
&self,
ctx: &mut Lower<Self::I>,
ctx: &mut Lower<M::I>,
idx: usize,
from_regs: ValueRegs<Reg>,
) {
@@ -1871,9 +1875,10 @@ impl<M: ABIMachineSpec> ABICaller for ABICallerImpl<M> {
}
}
fn emit_copy_retval_to_regs(
/// Emit a copy a return value into a destination register, after the call returns.
pub fn emit_copy_retval_to_regs(
&self,
ctx: &mut Lower<Self::I>,
ctx: &mut Lower<M::I>,
idx: usize,
into_regs: ValueRegs<Writable<Reg>>,
) {
@@ -1907,7 +1912,20 @@ impl<M: ABIMachineSpec> ABICaller for ABICallerImpl<M> {
}
}
fn emit_call(&mut self, ctx: &mut Lower<Self::I>) {
/// Emit the call itself.
///
/// The returned instruction should have proper use- and def-sets according
/// to the argument registers, return-value registers, and clobbered
/// registers for this function signature in this ABI.
///
/// (Arg registers are uses, and retval registers are defs. Clobbered
/// registers are also logically defs, but should never be read; their
/// values are "defined" (to the regalloc) but "undefined" in every other
/// sense.)
///
/// This function should only be called once, as it is allowed to re-use
/// parts of the `Caller` object in emitting instructions.
pub fn emit_call(&mut self, ctx: &mut Lower<M::I>) {
let (uses, defs) = (
mem::replace(&mut self.uses, Default::default()),
mem::replace(&mut self.defs, Default::default()),