Skip to content

Commit

Permalink
pulley: Refactor register restores on tail-calls
Browse files Browse the repository at this point in the history
Use helpers from `abi.rs` where possible to avoid duplicating logic.
  • Loading branch information
alexcrichton committed Jan 15, 2025
1 parent bb5e4bb commit 1c03cf6
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 59 deletions.
25 changes: 8 additions & 17 deletions cranelift/codegen/src/isa/pulley_shared/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,16 +354,6 @@ where
_call_conv: isa::CallConv,
_flags: &settings::Flags,
_isa_flags: &PulleyFlags,
_frame_layout: &FrameLayout,
) -> SmallInstVec<Self::I> {
// Note that this is intentionally empty as `gen_return` does
// everything.
SmallVec::new()
}

fn gen_return(
_call_conv: isa::CallConv,
_isa_flags: &PulleyFlags,
frame_layout: &FrameLayout,
) -> SmallInstVec<Self::I> {
let mut insts = SmallVec::new();
Expand Down Expand Up @@ -412,16 +402,17 @@ where
));
}

// And finally, return.
//
// FIXME: if `frame_layout.tail_args_size` is zero this instruction
// should get folded into the macro-instructions above. No need to have
// all functions do `pop_frame; ret`, that could be `pop_frame_and_ret`.
// Should benchmark whether this is worth it though.
insts.push(RawInst::Ret {}.into());
insts
}

fn gen_return(
_call_conv: isa::CallConv,
_isa_flags: &PulleyFlags,
_frame_layout: &FrameLayout,
) -> SmallInstVec<Self::I> {
smallvec![RawInst::Ret {}.into()]
}

fn gen_probestack(_insts: &mut SmallInstVec<Self::I>, _frame_size: u32) {
// Pulley doesn't implement stack probes since all stack pointer
// decrements are checked already.
Expand Down
54 changes: 13 additions & 41 deletions cranelift/codegen/src/isa/pulley_shared/inst/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use super::*;
use crate::ir::{self, Endianness};
use crate::isa;
use crate::isa::pulley_shared::abi::PulleyMachineDeps;
use crate::isa::pulley_shared::PointerWidth;
use core::marker::PhantomData;
Expand All @@ -10,19 +11,19 @@ use pulley_interpreter::encode as enc;
use pulley_interpreter::regs::BinaryOperands;

pub struct EmitInfo {
#[allow(dead_code)] // Will get used as we fill out this backend.
call_conv: isa::CallConv,
shared_flags: settings::Flags,

#[allow(dead_code)] // Will get used as we fill out this backend.
isa_flags: crate::isa::pulley_shared::settings::Flags,
}

impl EmitInfo {
pub(crate) fn new(
call_conv: isa::CallConv,
shared_flags: settings::Flags,
isa_flags: crate::isa::pulley_shared::settings::Flags,
) -> Self {
Self {
call_conv,
shared_flags,
isa_flags,
}
Expand Down Expand Up @@ -644,46 +645,17 @@ fn return_call_emit_impl<T, P>(
) where
P: PulleyTargetKind,
{
let sp_to_fp_offset = {
let frame_layout = state.frame_layout();
i64::from(
frame_layout.clobber_size
+ frame_layout.fixed_frame_storage_size
+ frame_layout.outgoing_args_size,
)
};

// Restore all clobbered registers before leaving the function.
let mut clobber_offset = sp_to_fp_offset - 8;
for reg in state.frame_layout().clobbered_callee_saves.clone() {
let rreg = reg.to_reg();
let ty = match rreg.class() {
RegClass::Int => I64,
RegClass::Float => F64,
RegClass::Vector => unimplemented!("Vector Clobber Restores"),
};

<InstAndKind<P>>::from(Inst::gen_load(
reg.map(Reg::from),
Amode::SpOffset {
offset: clobber_offset.try_into().unwrap(),
},
ty,
MemFlags::trusted(),
))
.emit(sink, emit_info, state);

clobber_offset -= 8
let epilogue = <PulleyMachineDeps<P>>::gen_epilogue_frame_restore(
emit_info.call_conv,
&emit_info.shared_flags,
&emit_info.isa_flags,
&state.frame_layout,
);

for inst in epilogue {
inst.emit(sink, emit_info, state);
}

// Restore the link register and frame pointer using a `pop_frame`
// instruction. This will move `sp` to the current frame pointer and then
// restore the old lr/fp, so this restores all of sp/fp/lr in one
// instruction.
let setup_area_size = i64::from(state.frame_layout().setup_area_size);
assert!(setup_area_size > 0, "must have frame pointers enabled");
<InstAndKind<P>>::from(RawInst::PopFrame).emit(sink, emit_info, state);

// Now that `sp` is restored to what it was on function entry it may need to
// be adjusted if the stack arguments of our own function differ from the
// stack arguments of the callee. Perform any necessary adjustment here.
Expand Down
6 changes: 5 additions & 1 deletion cranelift/codegen/src/isa/pulley_shared/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,11 @@ where
domtree: &DominatorTree,
ctrl_plane: &mut ControlPlane,
) -> CodegenResult<(VCode<inst::InstAndKind<P>>, regalloc2::Output)> {
let emit_info = EmitInfo::new(self.flags.clone(), self.isa_flags.clone());
let emit_info = EmitInfo::new(
func.signature.call_conv,
self.flags.clone(),
self.isa_flags.clone(),
);
let sigs = SigSet::new::<abi::PulleyMachineDeps<P>>(func, &self.flags)?;
let abi = abi::PulleyCallee::new(func, self, &self.isa_flags, &sigs)?;
machinst::compile::<Self>(func, domtree, self, abi, emit_info, sigs, ctrl_plane)
Expand Down

0 comments on commit 1c03cf6

Please sign in to comment.