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 the ABICaller trait #4711

Merged
merged 2 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
2 changes: 1 addition & 1 deletion cranelift/codegen/src/isa/aarch64/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use smallvec::{smallvec, SmallVec};
pub(crate) type AArch64Callee = Callee<AArch64MachineDeps>;

/// Support for the AArch64 ABI from the caller side (at a callsite).
pub(crate) type AArch64ABICaller = ABICallerImpl<AArch64MachineDeps>;
pub(crate) type AArch64Caller = Caller<AArch64MachineDeps>;

/// This is the limit for the size of argument and return-value areas on the
/// stack. We place a reasonable limit here to avoid integer overflow issues
Expand Down
4 changes: 2 additions & 2 deletions cranelift/codegen/src/isa/aarch64/lower_inst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ pub(crate) fn lower_insn_to_regs(
assert!(inputs.len() == sig.params.len());
assert!(outputs.len() == sig.returns.len());
(
AArch64ABICaller::from_func(sig, &extname, dist, caller_conv, flags)?,
AArch64Caller::from_func(sig, &extname, dist, caller_conv, flags)?,
&inputs[..],
)
}
Expand All @@ -615,7 +615,7 @@ pub(crate) fn lower_insn_to_regs(
assert!(inputs.len() - 1 == sig.params.len());
assert!(outputs.len() == sig.returns.len());
(
AArch64ABICaller::from_ptr(sig, ptr, op, caller_conv, flags)?,
AArch64Caller::from_ptr(sig, ptr, op, caller_conv, flags)?,
&inputs[1..],
)
}
Expand Down
2 changes: 1 addition & 1 deletion cranelift/codegen/src/isa/x64/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ static STACK_ARG_RET_SIZE_LIMIT: u64 = 128 * 1024 * 1024;
pub(crate) type X64Callee = Callee<X64ABIMachineSpec>;

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

/// Implementation of ABI primitives for x64.
pub struct X64ABIMachineSpec;
Expand Down
2 changes: 1 addition & 1 deletion cranelift/codegen/src/isa/x64/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ fn emit_vm_call(
let sig = libcall.signature(call_conv);
let caller_conv = ctx.abi().call_conv();

let mut abi = X64ABICaller::from_func(&sig, &extname, dist, caller_conv, flags)?;
let mut abi = X64Caller::from_func(&sig, &extname, dist, caller_conv, flags)?;

abi.emit_stack_pre_adjust(ctx);

Expand Down
13 changes: 6 additions & 7 deletions cranelift/codegen/src/isa/x64/lower/isle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ use crate::{
settings::Flags,
unwind::UnwindInst,
x64::{
abi::{X64ABICaller, X64ABIMachineSpec},
abi::{X64ABIMachineSpec, X64Caller},
inst::{args::*, regs, CallInfo},
settings::Flags as IsaFlags,
},
},
machinst::{
isle::*, valueregs, ABICaller, InsnInput, InsnOutput, Lower, MachAtomicRmwOp, MachInst,
VCodeConstant, VCodeConstantData,
isle::*, valueregs, InsnInput, InsnOutput, Lower, MachAtomicRmwOp, MachInst, VCodeConstant,
VCodeConstantData,
},
};
use regalloc2::PReg;
Expand Down Expand Up @@ -673,7 +673,7 @@ impl Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6> {
let sig = &self.lower_ctx.dfg().signatures[sig_ref];
let num_rets = sig.returns.len();
let abi = ABISig::from_func_sig::<X64ABIMachineSpec>(sig, self.flags).unwrap();
let caller = X64ABICaller::from_func(sig, &extname, dist, caller_conv, self.flags).unwrap();
let caller = X64Caller::from_func(sig, &extname, dist, caller_conv, self.flags).unwrap();

assert_eq!(
inputs.len(&self.lower_ctx.dfg().value_lists) - off,
Expand All @@ -695,8 +695,7 @@ impl Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6> {
let num_rets = sig.returns.len();
let abi = ABISig::from_func_sig::<X64ABIMachineSpec>(sig, self.flags).unwrap();
let caller =
X64ABICaller::from_ptr(sig, ptr, Opcode::CallIndirect, caller_conv, self.flags)
.unwrap();
X64Caller::from_ptr(sig, ptr, Opcode::CallIndirect, caller_conv, self.flags).unwrap();

assert_eq!(
inputs.len(&self.lower_ctx.dfg().value_lists) - off,
Expand Down Expand Up @@ -807,7 +806,7 @@ impl IsleContext<'_, '_, MInst, Flags, IsaFlags, 6> {
&mut self,
abi: ABISig,
num_rets: usize,
mut caller: X64ABICaller,
mut caller: X64Caller,
(inputs, off): ValueSlice,
) -> InstOutput {
caller.emit_stack_pre_adjust(self.lower_ctx);
Expand Down
76 changes: 0 additions & 76 deletions cranelift/codegen/src/machinst/abi.rs
Original file line number Diff line number Diff line change
@@ -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>);
}
66 changes: 42 additions & 24 deletions cranelift/codegen/src/machinst/abi_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -1668,19 +1668,19 @@ 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,
extname: &ir::ExternalName,
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,
Expand All @@ -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,
Expand All @@ -1730,35 +1730,36 @@ 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 {
self.sig.args.len()
}
}

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>,
) {
Expand Down Expand Up @@ -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>,
) {
Expand Down Expand Up @@ -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>>,
) {
Expand Down Expand Up @@ -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()),
Expand Down