Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cranelift: Remove ABICallee trait #4701

Merged
merged 5 commits into from
Aug 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cranelift/codegen/src/isa/aarch64/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use smallvec::{smallvec, SmallVec};
// these ABIs are very similar.

/// Support for the AArch64 ABI from the callee side (within a function body).
pub(crate) type AArch64ABICallee = ABICalleeImpl<AArch64MachineDeps>;
pub(crate) type AArch64Callee = Callee<AArch64MachineDeps>;

/// Support for the AArch64 ABI from the caller side (at a callsite).
pub(crate) type AArch64ABICaller = ABICallerImpl<AArch64MachineDeps>;
Expand Down Expand Up @@ -65,7 +65,7 @@ fn saved_reg_stack_size(

/// AArch64-specific ABI behavior. This struct just serves as an implementation
/// point for the trait; it is never actually instantiated.
pub(crate) struct AArch64MachineDeps;
pub struct AArch64MachineDeps;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it is public now that there is the MachInst::ABIMachineSpec associated type.


impl IsaFlags for aarch64_settings::Flags {}

Expand Down
2 changes: 1 addition & 1 deletion cranelift/codegen/src/isa/aarch64/inst/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ pub struct EmitState {
}

impl MachInstEmitState<Inst> for EmitState {
fn new(abi: &dyn ABICallee<I = Inst>) -> Self {
fn new(abi: &Callee<AArch64MachineDeps>) -> Self {
EmitState {
virtual_sp_offset: 0,
nominal_sp_to_fp: abi.frame_size() as i64,
Expand Down
1 change: 1 addition & 0 deletions cranelift/codegen/src/isa/aarch64/inst/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1056,6 +1056,7 @@ fn aarch64_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut Operan
// Instructions: misc functions and external interface

impl MachInst for Inst {
type ABIMachineSpec = AArch64MachineDeps;
type LabelUse = LabelUse;

fn get_operands<F: Fn(VReg) -> VReg>(&self, collector: &mut OperandCollector<'_, F>) {
Expand Down
2 changes: 1 addition & 1 deletion cranelift/codegen/src/isa/aarch64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl AArch64Backend {
flags: shared_settings::Flags,
) -> CodegenResult<(VCode<inst::Inst>, regalloc2::Output)> {
let emit_info = EmitInfo::new(flags.clone());
let abi = Box::new(abi::AArch64ABICallee::new(func, self, &self.isa_flags)?);
let abi = abi::AArch64Callee::new(func, self, &self.isa_flags)?;
compile::compile::<AArch64Backend>(func, self, abi, &self.machine_env, emit_info)
}
}
Expand Down
2 changes: 1 addition & 1 deletion cranelift/codegen/src/isa/s390x/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ use std::convert::TryFrom;
// We use a generic implementation that factors out ABI commonalities.

/// Support for the S390x ABI from the callee side (within a function body).
pub type S390xABICallee = ABICalleeImpl<S390xMachineDeps>;
pub type S390xCallee = Callee<S390xMachineDeps>;

/// ABI Register usage

Expand Down
6 changes: 3 additions & 3 deletions cranelift/codegen/src/isa/s390x/inst/emit.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! S390x ISA: binary code emission.

use crate::binemit::{Reloc, StackMap};
use crate::ir::TrapCode;
use crate::ir::{MemFlags, RelSourceLoc};
use crate::ir::{MemFlags, RelSourceLoc, TrapCode};
use crate::isa::s390x::abi::S390xMachineDeps;
use crate::isa::s390x::inst::*;
use crate::isa::s390x::settings as s390x_settings;
use crate::machinst::reg::count_operands;
Expand Down Expand Up @@ -1260,7 +1260,7 @@ pub struct EmitState {
}

impl MachInstEmitState<Inst> for EmitState {
fn new(abi: &dyn ABICallee<I = Inst>) -> Self {
fn new(abi: &Callee<S390xMachineDeps>) -> Self {
EmitState {
virtual_sp_offset: 0,
initial_sp_offset: abi.frame_size() as i64,
Expand Down
2 changes: 2 additions & 0 deletions cranelift/codegen/src/isa/s390x/inst/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use crate::binemit::{Addend, CodeOffset, Reloc};
use crate::ir::{types, ExternalName, Opcode, Type};
use crate::isa::s390x::abi::S390xMachineDeps;
use crate::isa::CallConv;
use crate::machinst::*;
use crate::{settings, CodegenError, CodegenResult};
Expand Down Expand Up @@ -977,6 +978,7 @@ fn s390x_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandC
// Instructions: misc functions and external interface

impl MachInst for Inst {
type ABIMachineSpec = S390xMachineDeps;
type LabelUse = LabelUse;

fn get_operands<F: Fn(VReg) -> VReg>(&self, collector: &mut OperandCollector<'_, F>) {
Expand Down
2 changes: 1 addition & 1 deletion cranelift/codegen/src/isa/s390x/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ impl S390xBackend {
func: &Function,
) -> CodegenResult<(VCode<inst::Inst>, regalloc2::Output)> {
let emit_info = EmitInfo::new(self.isa_flags.clone());
let abi = Box::new(abi::S390xABICallee::new(func, self, &self.isa_flags)?);
let abi = abi::S390xCallee::new(func, self, &self.isa_flags)?;
compile::compile::<S390xBackend>(func, self, abi, &self.machine_env, emit_info)
}
}
Expand Down
4 changes: 2 additions & 2 deletions cranelift/codegen/src/isa/x64/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ use std::convert::TryFrom;
static STACK_ARG_RET_SIZE_LIMIT: u64 = 128 * 1024 * 1024;

/// Support for the x64 ABI from the callee side (within a function body).
pub(crate) type X64ABICallee = ABICalleeImpl<X64ABIMachineSpec>;
pub(crate) type X64Callee = Callee<X64ABIMachineSpec>;

/// Support for the x64 ABI from the caller side (at a callsite).
pub(crate) type X64ABICaller = ABICallerImpl<X64ABIMachineSpec>;

/// Implementation of ABI primitives for x64.
pub(crate) struct X64ABIMachineSpec;
pub struct X64ABIMachineSpec;

impl IsaFlags for x64_settings::Flags {}

Expand Down
4 changes: 3 additions & 1 deletion cranelift/codegen/src/isa/x64/inst/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2157,6 +2157,8 @@ fn x64_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandCol
// Instructions: misc functions and external interface

impl MachInst for Inst {
type ABIMachineSpec = X64ABIMachineSpec;

fn get_operands<F: Fn(VReg) -> VReg>(&self, collector: &mut OperandCollector<'_, F>) {
x64_get_operands(&self, collector)
}
Expand Down Expand Up @@ -2460,7 +2462,7 @@ impl MachInstEmit for Inst {
}

impl MachInstEmitState<Inst> for EmitState {
fn new(abi: &dyn ABICallee<I = Inst>) -> Self {
fn new(abi: &Callee<X64ABIMachineSpec>) -> Self {
EmitState {
virtual_sp_offset: 0,
nominal_sp_to_fp: abi.frame_size() as i64,
Expand Down
2 changes: 1 addition & 1 deletion cranelift/codegen/src/isa/x64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl X64Backend {
// This performs lowering to VCode, register-allocates the code, computes
// block layout and finalizes branches. The result is ready for binary emission.
let emit_info = EmitInfo::new(flags.clone(), self.x64_flags.clone());
let abi = Box::new(abi::X64ABICallee::new(&func, self, &self.x64_flags)?);
let abi = abi::X64Callee::new(&func, self, &self.x64_flags)?;
compile::compile::<Self>(&func, self, abi, &self.reg_env, emit_info)
}
}
Expand Down
173 changes: 5 additions & 168 deletions cranelift/codegen/src/machinst/abi.rs
Original file line number Diff line number Diff line change
@@ -1,187 +1,24 @@
//! 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.
///
/// An instance of this trait returns information for a *particular*
/// 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 {
Expand Down
Loading