Cranelift: Remove ABICallee trait (#4701)
* Cranelift: Remove `ABICallee` trait It has only one implementation: the `ABICalleeImpl` struct. By using that directly we can avoid unnecessary layers of generics and abstractions as well as a couple `Box`es that were previously putting the single implementation into a `Box<dyn>`. * Cranelift: Rename `ABICalleeImpl` to `AbiCallee` * Fix comments as per review * Rename `AbiCallee` to `Callee`
This commit is contained in:
@@ -1,175 +1,12 @@
|
||||
//! ABI definitions.
|
||||
|
||||
use crate::binemit::StackMap;
|
||||
use crate::ir::{DynamicStackSlot, Signature, StackSlot};
|
||||
use crate::isa::CallConv;
|
||||
use crate::machinst::*;
|
||||
use crate::settings;
|
||||
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 (e.g., stack
|
||||
/// layout) and can generate code while emitting the *body* of a function.
|
||||
pub trait ABICallee {
|
||||
/// The instruction type for the ISA associated with this ABI.
|
||||
type I: VCodeInst;
|
||||
|
||||
/// Does the ABI-body code need temp registers (and if so, of what type)?
|
||||
/// They will be provided to `init()` as the `temps` arg if so.
|
||||
fn temps_needed(&self) -> Vec<Type>;
|
||||
|
||||
/// Initialize. This is called after the ABICallee is constructed because it
|
||||
/// may be provided with a vector of temp vregs, which can only be allocated
|
||||
/// once the lowering context exists.
|
||||
fn init(&mut self, temps: Vec<Writable<Reg>>);
|
||||
|
||||
/// 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;
|
||||
|
||||
/// Get the calling convention implemented by this ABI object.
|
||||
fn call_conv(&self) -> CallConv;
|
||||
|
||||
/// Number of arguments.
|
||||
fn num_args(&self) -> usize;
|
||||
|
||||
/// Number of return values.
|
||||
fn num_retvals(&self) -> usize;
|
||||
|
||||
/// Number of sized stack slots (not spill slots).
|
||||
fn num_sized_stackslots(&self) -> usize;
|
||||
|
||||
/// The offsets of all sized stack slots (not spill slots) for debuginfo purposes.
|
||||
fn sized_stackslot_offsets(&self) -> &PrimaryMap<StackSlot, u32>;
|
||||
|
||||
/// The offsets of all dynamic stack slots (not spill slots) for debuginfo purposes.
|
||||
fn dynamic_stackslot_offsets(&self) -> &PrimaryMap<DynamicStackSlot, u32>;
|
||||
|
||||
/// All the defined dynamic types.
|
||||
fn dynamic_type_size(&self, ty: Type) -> u32;
|
||||
|
||||
/// Generate an instruction which copies an argument to a destination
|
||||
/// register.
|
||||
fn gen_copy_arg_to_regs(
|
||||
&self,
|
||||
idx: usize,
|
||||
into_reg: ValueRegs<Writable<Reg>>,
|
||||
) -> SmallInstVec<Self::I>;
|
||||
|
||||
/// Is the given argument needed in the body (as opposed to, e.g., serving
|
||||
/// only as a special ABI-specific placeholder)? This controls whether
|
||||
/// lowering will copy it to a virtual reg use by CLIF instructions.
|
||||
fn arg_is_needed_in_body(&self, idx: usize) -> bool;
|
||||
|
||||
/// Generate any setup instruction needed to save values to the
|
||||
/// return-value area. This is usually used when were are multiple return
|
||||
/// values or an otherwise large return value that must be passed on the
|
||||
/// stack; typically the ABI specifies an extra hidden argument that is a
|
||||
/// pointer to that memory.
|
||||
fn gen_retval_area_setup(&self) -> Option<Self::I>;
|
||||
|
||||
/// Generate an instruction which copies a source register to a return value slot.
|
||||
fn gen_copy_regs_to_retval(
|
||||
&self,
|
||||
idx: usize,
|
||||
from_reg: ValueRegs<Writable<Reg>>,
|
||||
) -> SmallInstVec<Self::I>;
|
||||
|
||||
/// Generate a return instruction.
|
||||
fn gen_ret(&self) -> Self::I;
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Every function above this line may only be called pre-regalloc.
|
||||
// Every function below this line may only be called post-regalloc.
|
||||
// `spillslots()` must be called before any other post-regalloc
|
||||
// function.
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
/// Update with the number of spillslots, post-regalloc.
|
||||
fn set_num_spillslots(&mut self, slots: usize);
|
||||
|
||||
/// Update with the clobbered registers, post-regalloc.
|
||||
fn set_clobbered(&mut self, clobbered: Vec<Writable<RealReg>>);
|
||||
|
||||
/// Get the address of a sized stackslot.
|
||||
fn sized_stackslot_addr(
|
||||
&self,
|
||||
slot: StackSlot,
|
||||
offset: u32,
|
||||
into_reg: Writable<Reg>,
|
||||
) -> Self::I;
|
||||
|
||||
/// Get the address of a dynamic stackslot.
|
||||
fn dynamic_stackslot_addr(&self, slot: DynamicStackSlot, into_reg: Writable<Reg>) -> Self::I;
|
||||
|
||||
/// Load from a spillslot.
|
||||
fn load_spillslot(
|
||||
&self,
|
||||
slot: SpillSlot,
|
||||
ty: Type,
|
||||
into_reg: ValueRegs<Writable<Reg>>,
|
||||
) -> SmallInstVec<Self::I>;
|
||||
|
||||
/// Store to a spillslot.
|
||||
fn store_spillslot(
|
||||
&self,
|
||||
slot: SpillSlot,
|
||||
ty: Type,
|
||||
from_reg: ValueRegs<Reg>,
|
||||
) -> SmallInstVec<Self::I>;
|
||||
|
||||
/// Generate a stack map, given a list of spillslots and the emission state
|
||||
/// at a given program point (prior to emission fo the safepointing
|
||||
/// instruction).
|
||||
fn spillslots_to_stack_map(
|
||||
&self,
|
||||
slots: &[SpillSlot],
|
||||
state: &<Self::I as MachInstEmit>::State,
|
||||
) -> StackMap;
|
||||
|
||||
/// Generate a prologue, post-regalloc. This should include any stack
|
||||
/// frame or other setup necessary to use the other methods (`load_arg`,
|
||||
/// `store_retval`, and spillslot accesses.) `self` is mutable so that we
|
||||
/// can store information in it which will be useful when creating the
|
||||
/// epilogue.
|
||||
fn gen_prologue(&mut self) -> SmallInstVec<Self::I>;
|
||||
|
||||
/// Generate an epilogue, post-regalloc. Note that this must generate the
|
||||
/// actual return instruction (rather than emitting this in the lowering
|
||||
/// logic), because the epilogue code comes before the return and the two are
|
||||
/// likely closely related.
|
||||
fn gen_epilogue(&self) -> SmallInstVec<Self::I>;
|
||||
|
||||
/// Returns the full frame size for the given function, after prologue
|
||||
/// emission has run. This comprises the spill slots and stack-storage slots
|
||||
/// (but not storage for clobbered callee-save registers, arguments pushed
|
||||
/// at callsites within this function, or other ephemeral pushes).
|
||||
fn frame_size(&self) -> u32;
|
||||
|
||||
/// Returns the size of arguments expected on the stack.
|
||||
fn stack_args_size(&self) -> u32;
|
||||
|
||||
/// Get the spill-slot size.
|
||||
fn get_spillslot_size(&self, rc: RegClass) -> u32;
|
||||
|
||||
/// Generate a spill.
|
||||
fn gen_spill(&self, to_slot: SpillSlot, from_reg: RealReg) -> Self::I;
|
||||
|
||||
/// Generate a reload (fill).
|
||||
fn gen_reload(&self, to_reg: Writable<RealReg>, from_slot: SpillSlot) -> Self::I;
|
||||
}
|
||||
|
||||
/// Trait implemented by an object that tracks ABI-related state and can
|
||||
/// generate code while emitting a *call* to a function.
|
||||
///
|
||||
@@ -177,11 +14,11 @@ pub trait ABICallee {
|
||||
/// callsite. It will usually be computed from the called function's
|
||||
/// signature.
|
||||
///
|
||||
/// Unlike `ABICallee` above, 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.
|
||||
/// 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 {
|
||||
|
||||
Reference in New Issue
Block a user