Skip to content

Commit 112d1a6

Browse files
authored
pulley: Refactor register restores on tail-calls (bytecodealliance#10022)
* pulley: Refactor register restores on tail-calls Use helpers from `abi.rs` where possible to avoid duplicating logic. * Shuffle where stack increments from tail args happens
1 parent 168be6d commit 112d1a6

File tree

3 files changed

+29
-59
lines changed

3 files changed

+29
-59
lines changed

cranelift/codegen/src/isa/pulley_shared/abi.rs

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -360,16 +360,6 @@ where
360360
_call_conv: isa::CallConv,
361361
_flags: &settings::Flags,
362362
_isa_flags: &PulleyFlags,
363-
_frame_layout: &FrameLayout,
364-
) -> SmallInstVec<Self::I> {
365-
// Note that this is intentionally empty as `gen_return` does
366-
// everything.
367-
SmallVec::new()
368-
}
369-
370-
fn gen_return(
371-
_call_conv: isa::CallConv,
372-
_isa_flags: &PulleyFlags,
373363
frame_layout: &FrameLayout,
374364
) -> SmallInstVec<Self::I> {
375365
let mut insts = SmallVec::new();
@@ -411,20 +401,24 @@ where
411401
}
412402
}
413403

404+
insts
405+
}
406+
407+
fn gen_return(
408+
_call_conv: isa::CallConv,
409+
_isa_flags: &PulleyFlags,
410+
frame_layout: &FrameLayout,
411+
) -> SmallInstVec<Self::I> {
412+
let mut insts = SmallVec::new();
413+
414414
// Handle final stack adjustments for the tail-call ABI.
415415
if frame_layout.tail_args_size > 0 {
416416
insts.extend(Self::gen_sp_reg_adjust(
417417
frame_layout.tail_args_size.try_into().unwrap(),
418418
));
419419
}
420-
421-
// And finally, return.
422-
//
423-
// FIXME: if `frame_layout.tail_args_size` is zero this instruction
424-
// should get folded into the macro-instructions above. No need to have
425-
// all functions do `pop_frame; ret`, that could be `pop_frame_and_ret`.
426-
// Should benchmark whether this is worth it though.
427420
insts.push(RawInst::Ret {}.into());
421+
428422
insts
429423
}
430424

cranelift/codegen/src/isa/pulley_shared/inst/emit.rs

Lines changed: 13 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use super::*;
44
use crate::ir::{self, Endianness};
5+
use crate::isa;
56
use crate::isa::pulley_shared::abi::PulleyMachineDeps;
67
use crate::isa::pulley_shared::PointerWidth;
78
use core::marker::PhantomData;
@@ -10,19 +11,19 @@ use pulley_interpreter::encode as enc;
1011
use pulley_interpreter::regs::BinaryOperands;
1112

1213
pub struct EmitInfo {
13-
#[allow(dead_code)] // Will get used as we fill out this backend.
14+
call_conv: isa::CallConv,
1415
shared_flags: settings::Flags,
15-
16-
#[allow(dead_code)] // Will get used as we fill out this backend.
1716
isa_flags: crate::isa::pulley_shared::settings::Flags,
1817
}
1918

2019
impl EmitInfo {
2120
pub(crate) fn new(
21+
call_conv: isa::CallConv,
2222
shared_flags: settings::Flags,
2323
isa_flags: crate::isa::pulley_shared::settings::Flags,
2424
) -> Self {
2525
Self {
26+
call_conv,
2627
shared_flags,
2728
isa_flags,
2829
}
@@ -644,46 +645,17 @@ fn return_call_emit_impl<T, P>(
644645
) where
645646
P: PulleyTargetKind,
646647
{
647-
let sp_to_fp_offset = {
648-
let frame_layout = state.frame_layout();
649-
i64::from(
650-
frame_layout.clobber_size
651-
+ frame_layout.fixed_frame_storage_size
652-
+ frame_layout.outgoing_args_size,
653-
)
654-
};
655-
656-
// Restore all clobbered registers before leaving the function.
657-
let mut clobber_offset = sp_to_fp_offset - 8;
658-
for reg in state.frame_layout().clobbered_callee_saves.clone() {
659-
let rreg = reg.to_reg();
660-
let ty = match rreg.class() {
661-
RegClass::Int => I64,
662-
RegClass::Float => F64,
663-
RegClass::Vector => unimplemented!("Vector Clobber Restores"),
664-
};
665-
666-
<InstAndKind<P>>::from(Inst::gen_load(
667-
reg.map(Reg::from),
668-
Amode::SpOffset {
669-
offset: clobber_offset.try_into().unwrap(),
670-
},
671-
ty,
672-
MemFlags::trusted(),
673-
))
674-
.emit(sink, emit_info, state);
675-
676-
clobber_offset -= 8
648+
let epilogue = <PulleyMachineDeps<P>>::gen_epilogue_frame_restore(
649+
emit_info.call_conv,
650+
&emit_info.shared_flags,
651+
&emit_info.isa_flags,
652+
&state.frame_layout,
653+
);
654+
655+
for inst in epilogue {
656+
inst.emit(sink, emit_info, state);
677657
}
678658

679-
// Restore the link register and frame pointer using a `pop_frame`
680-
// instruction. This will move `sp` to the current frame pointer and then
681-
// restore the old lr/fp, so this restores all of sp/fp/lr in one
682-
// instruction.
683-
let setup_area_size = i64::from(state.frame_layout().setup_area_size);
684-
assert!(setup_area_size > 0, "must have frame pointers enabled");
685-
<InstAndKind<P>>::from(RawInst::PopFrame).emit(sink, emit_info, state);
686-
687659
// Now that `sp` is restored to what it was on function entry it may need to
688660
// be adjusted if the stack arguments of our own function differ from the
689661
// stack arguments of the callee. Perform any necessary adjustment here.

cranelift/codegen/src/isa/pulley_shared/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,11 @@ where
124124
domtree: &DominatorTree,
125125
ctrl_plane: &mut ControlPlane,
126126
) -> CodegenResult<(VCode<inst::InstAndKind<P>>, regalloc2::Output)> {
127-
let emit_info = EmitInfo::new(self.flags.clone(), self.isa_flags.clone());
127+
let emit_info = EmitInfo::new(
128+
func.signature.call_conv,
129+
self.flags.clone(),
130+
self.isa_flags.clone(),
131+
);
128132
let sigs = SigSet::new::<abi::PulleyMachineDeps<P>>(func, &self.flags)?;
129133
let abi = abi::PulleyCallee::new(func, self, &self.isa_flags, &sigs)?;
130134
machinst::compile::<Self>(func, domtree, self, abi, emit_info, sigs, ctrl_plane)

0 commit comments

Comments
 (0)