Skip to content
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
8 changes: 5 additions & 3 deletions cranelift/codegen/src/isa/aarch64/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ impl ABIMachineSpec for AArch64MachineDeps {
insts
}

fn gen_prologue_frame_setup(flags: &settings::Flags) -> SmallInstVec<Inst> {
fn gen_prologue_frame_setup(flags: &settings::Flags) -> (SmallInstVec<Inst>, u32) {
let mut insts = SmallVec::new();

// stp fp (x29), lr (x30), [sp, #-16]!
Expand All @@ -597,10 +597,11 @@ impl ABIMachineSpec for AArch64MachineDeps {
flags: MemFlags::trusted(),
});

let setup_area_size = 16; // FP, LR
if flags.unwind_info() {
insts.push(Inst::Unwind {
inst: UnwindInst::PushFrameRegs {
offset_upward_to_caller_sp: 16, // FP, LR
offset_upward_to_caller_sp: setup_area_size,
},
});
}
Expand All @@ -617,7 +618,8 @@ impl ABIMachineSpec for AArch64MachineDeps {
shift12: false,
},
});
insts

(insts, setup_area_size)
}

fn gen_epilogue_frame_restore(_: &settings::Flags) -> SmallInstVec<Inst> {
Expand Down
4 changes: 2 additions & 2 deletions cranelift/codegen/src/isa/aarch64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,10 @@ impl TargetIsa for AArch64Backend {
fn emit_unwind_info(
&self,
result: &CompiledCode,
kind: crate::machinst::UnwindInfoKind,
kind: crate::isa::unwind::UnwindInfoKind,
) -> CodegenResult<Option<crate::isa::unwind::UnwindInfo>> {
use crate::isa::unwind::UnwindInfo;
use crate::machinst::UnwindInfoKind;
use crate::isa::unwind::UnwindInfoKind;
Ok(match kind {
UnwindInfoKind::SystemV => {
let mapper = self::inst::unwind::systemv::RegisterMapper;
Expand Down
4 changes: 2 additions & 2 deletions cranelift/codegen/src/isa/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ pub use crate::isa::call_conv::CallConv;
use crate::flowgraph;
use crate::ir::{self, Function, Type};
#[cfg(feature = "unwind")]
use crate::isa::unwind::systemv::RegisterMappingError;
use crate::machinst::{CompiledCode, CompiledCodeStencil, TextSectionBuilder, UnwindInfoKind};
use crate::isa::unwind::{systemv::RegisterMappingError, UnwindInfoKind};
use crate::machinst::{CompiledCode, CompiledCodeStencil, TextSectionBuilder};
use crate::settings;
use crate::settings::SetResult;
use crate::CodegenResult;
Expand Down
9 changes: 6 additions & 3 deletions cranelift/codegen/src/isa/riscv64/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ impl ABIMachineSpec for Riscv64MachineDeps {
}
}

fn gen_prologue_frame_setup(flags: &settings::Flags) -> SmallInstVec<Inst> {
fn gen_prologue_frame_setup(flags: &settings::Flags) -> (SmallInstVec<Self::I>, u32) {
// add sp,sp,-16 ;; alloc stack space for fp.
// sd ra,8(sp) ;; save ra.
// sd fp,0(sp) ;; store old fp.
Expand All @@ -358,10 +358,12 @@ impl ABIMachineSpec for Riscv64MachineDeps {
fp_reg(),
I64,
));

let setup_area_size = 16; // FP, LR
if flags.unwind_info() {
insts.push(Inst::Unwind {
inst: UnwindInst::PushFrameRegs {
offset_upward_to_caller_sp: 16, // FP, LR
offset_upward_to_caller_sp: setup_area_size,
},
});
}
Expand All @@ -370,7 +372,8 @@ impl ABIMachineSpec for Riscv64MachineDeps {
rm: stack_reg(),
ty: I64,
});
insts

(insts, setup_area_size)
}
/// reverse of gen_prologue_frame_setup.
fn gen_epilogue_frame_restore(_: &settings::Flags) -> SmallInstVec<Inst> {
Expand Down
4 changes: 2 additions & 2 deletions cranelift/codegen/src/isa/riscv64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,10 @@ impl TargetIsa for Riscv64Backend {
fn emit_unwind_info(
&self,
result: &CompiledCode,
kind: crate::machinst::UnwindInfoKind,
kind: crate::isa::unwind::UnwindInfoKind,
) -> CodegenResult<Option<crate::isa::unwind::UnwindInfo>> {
use crate::isa::unwind::UnwindInfo;
use crate::machinst::UnwindInfoKind;
use crate::isa::unwind::UnwindInfoKind;
Ok(match kind {
UnwindInfoKind::SystemV => {
let mapper = self::inst::unwind::systemv::RegisterMapper;
Expand Down
4 changes: 2 additions & 2 deletions cranelift/codegen/src/isa/s390x/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -556,8 +556,8 @@ impl ABIMachineSpec for S390xMachineDeps {
}
}

fn gen_prologue_frame_setup(_flags: &settings::Flags) -> SmallInstVec<Inst> {
SmallVec::new()
fn gen_prologue_frame_setup(_flags: &settings::Flags) -> (SmallInstVec<Inst>, u32) {
(SmallVec::new(), 0)
}

fn gen_epilogue_frame_restore(_flags: &settings::Flags) -> SmallInstVec<Inst> {
Expand Down
4 changes: 2 additions & 2 deletions cranelift/codegen/src/isa/s390x/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,10 @@ impl TargetIsa for S390xBackend {
fn emit_unwind_info(
&self,
result: &CompiledCode,
kind: crate::machinst::UnwindInfoKind,
kind: crate::isa::unwind::UnwindInfoKind,
) -> CodegenResult<Option<crate::isa::unwind::UnwindInfo>> {
use crate::isa::unwind::UnwindInfo;
use crate::machinst::UnwindInfoKind;
use crate::isa::unwind::UnwindInfoKind;
Ok(match kind {
UnwindInfoKind::SystemV => {
let mapper = self::inst::unwind::systemv::RegisterMapper;
Expand Down
19 changes: 18 additions & 1 deletion cranelift/codegen/src/isa/unwind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,23 @@ pub mod systemv;
#[cfg(feature = "unwind")]
pub mod winx64;

/// CFA-based unwind information used on SystemV.
pub type CfaUnwindInfo = systemv::UnwindInfo;

/// Expected unwind info type.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum UnwindInfoKind {
/// No unwind info.
None,
/// SystemV CIE/FDE unwind info.
#[cfg(feature = "unwind")]
SystemV,
/// Windows X64 Unwind info
#[cfg(feature = "unwind")]
Windows,
}

/// Represents unwind information for a single function.
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
Expand All @@ -21,7 +38,7 @@ pub enum UnwindInfo {
WindowsX64(winx64::UnwindInfo),
/// System V ABI unwind information.
#[cfg(feature = "unwind")]
SystemV(systemv::UnwindInfo),
SystemV(CfaUnwindInfo),
}

/// Unwind pseudoinstruction used in VCode backends: represents that
Expand Down
6 changes: 6 additions & 0 deletions cranelift/codegen/src/isa/unwind/systemv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,12 @@ pub struct UnwindInfo {
len: u32,
}

/// Offset from the caller's SP to CFA as we define it.
pub(crate) fn caller_sp_to_cfa_offset() -> u32 {
// Currently we define them to always be equal.
0
}

pub(crate) fn create_unwind_info_from_insts<MR: RegisterMapper<Reg>>(
insts: &[(CodeOffset, UnwindInst)],
code_len: usize,
Expand Down
8 changes: 5 additions & 3 deletions cranelift/codegen/src/isa/x64/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ impl ABIMachineSpec for X64ABIMachineSpec {
}
}

fn gen_prologue_frame_setup(flags: &settings::Flags) -> SmallInstVec<Self::I> {
fn gen_prologue_frame_setup(flags: &settings::Flags) -> (SmallInstVec<Self::I>, u32) {
let r_rsp = regs::rsp();
let r_rbp = regs::rbp();
let w_rbp = Writable::from_reg(r_rbp);
Expand All @@ -453,18 +453,20 @@ impl ABIMachineSpec for X64ABIMachineSpec {
// RSP before the call will be 0 % 16. So here, it is 8 % 16.
insts.push(Inst::push64(RegMemImm::reg(r_rbp)));

let setup_area_size = 16; // RBP, return address
if flags.unwind_info() {
insts.push(Inst::Unwind {
inst: UnwindInst::PushFrameRegs {
offset_upward_to_caller_sp: 16, // RBP, return address
offset_upward_to_caller_sp: setup_area_size,
},
});
}

// `mov %rsp, %rbp`
// RSP is now 0 % 16
insts.push(Inst::mov_r_r(OperandSize::Size64, r_rsp, w_rbp));
insts

(insts, setup_area_size)
}

fn gen_epilogue_frame_restore(_: &settings::Flags) -> SmallInstVec<Self::I> {
Expand Down
4 changes: 2 additions & 2 deletions cranelift/codegen/src/isa/x64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,10 @@ impl TargetIsa for X64Backend {
fn emit_unwind_info(
&self,
result: &CompiledCode,
kind: crate::machinst::UnwindInfoKind,
kind: crate::isa::unwind::UnwindInfoKind,
) -> CodegenResult<Option<crate::isa::unwind::UnwindInfo>> {
use crate::isa::unwind::UnwindInfo;
use crate::machinst::UnwindInfoKind;
use crate::isa::unwind::UnwindInfoKind;
Ok(match kind {
UnwindInfoKind::SystemV => {
let mapper = self::inst::unwind::systemv::RegisterMapper;
Expand Down
45 changes: 30 additions & 15 deletions cranelift/codegen/src/machinst/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -522,8 +522,8 @@ pub trait ABIMachineSpec {

/// Generate the usual frame-setup sequence for this architecture: e.g.,
/// `push rbp / mov rbp, rsp` on x86-64, or `stp fp, lr, [sp, #-16]!` on
/// AArch64.
fn gen_prologue_frame_setup(flags: &settings::Flags) -> SmallInstVec<Self::I>;
/// AArch64. Return generated instructions and stack size of the setup area.
fn gen_prologue_frame_setup(flags: &settings::Flags) -> (SmallInstVec<Self::I>, u32);

/// Generate the usual frame-restore sequence for this architecture.
fn gen_epilogue_frame_restore(flags: &settings::Flags) -> SmallInstVec<Self::I>;
Expand Down Expand Up @@ -1021,6 +1021,9 @@ pub struct Callee<M: ABIMachineSpec> {
/// Storage allocated for the fixed part of the stack frame. This is
/// usually the same as the total frame size below.
fixed_frame_storage_size: u32,
/// Size of the area between the FP as defined in the prolog and caller's SP.
/// It will usually contain the saved FP/LR pair.
frame_setup_area_size: u32,
/// "Total frame size", as defined by "distance between FP and nominal SP".
/// Some items are pushed below nominal SP, so the function may actually use
/// more stack than this would otherwise imply. It is simply the initial
Expand Down Expand Up @@ -1185,6 +1188,7 @@ impl<M: ABIMachineSpec> Callee<M> {
clobbered: vec![],
spillslots: None,
fixed_frame_storage_size: 0,
frame_setup_area_size: 0,
total_frame_size: None,
ret_area_ptr: None,
arg_temp_reg: vec![],
Expand Down Expand Up @@ -1760,10 +1764,7 @@ impl<M: ABIMachineSpec> Callee<M> {
ty: Type,
into_regs: ValueRegs<Writable<Reg>>,
) -> SmallInstVec<M::I> {
// Offset from beginning of spillslot area, which is at nominal SP + stackslots_size.
let islot = slot.index() as i64;
let spill_off = islot * M::word_bytes() as i64;
let sp_off = self.stackslots_size as i64 + spill_off;
let sp_off = self.get_spillslot_offset(slot);
trace!("load_spillslot: slot {:?} -> sp_off {}", slot, sp_off);

gen_load_stack_multi::<M>(StackAMode::NominalSPOffset(sp_off, ty), into_regs, ty)
Expand All @@ -1776,10 +1777,7 @@ impl<M: ABIMachineSpec> Callee<M> {
ty: Type,
from_regs: ValueRegs<Reg>,
) -> SmallInstVec<M::I> {
// Offset from beginning of spillslot area, which is at nominal SP + stackslots_size.
let islot = slot.index() as i64;
let spill_off = islot * M::word_bytes() as i64;
let sp_off = self.stackslots_size as i64 + spill_off;
let sp_off = self.get_spillslot_offset(slot);
trace!("store_spillslot: slot {:?} -> sp_off {}", slot, sp_off);

gen_store_stack_multi::<M>(StackAMode::NominalSPOffset(sp_off, ty), from_regs, ty)
Expand Down Expand Up @@ -1890,8 +1888,9 @@ impl<M: ABIMachineSpec> Callee<M> {
);

if self.setup_frame {
// set up frame
insts.extend(M::gen_prologue_frame_setup(&self.flags).into_iter());
let (setup_insts, setup_area_size) = M::gen_prologue_frame_setup(&self.flags);
insts.extend(setup_insts.into_iter());
self.frame_setup_area_size = setup_area_size;
}

// Leaf functions with zero stack don't need a stack check if one's
Expand Down Expand Up @@ -1992,14 +1991,20 @@ impl<M: ABIMachineSpec> Callee<M> {
}

/// 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).
/// emission has run. This comprises the spill slots and stack-storage
/// slots as well as storage for clobbered callee-save registers, but
/// not arguments arguments pushed at callsites within this function,
/// or other ephemeral pushes.
pub fn frame_size(&self) -> u32 {
self.total_frame_size
.expect("frame size not computed before prologue generation")
}

/// Returns offset from the nominal SP to caller's SP.
pub fn nominal_sp_to_caller_sp_offset(&self) -> u32 {
self.frame_size() + self.frame_setup_area_size
}

/// Returns the size of arguments expected on the stack.
pub fn stack_args_size(&self, sigs: &SigSet) -> u32 {
sigs[self.sig].sized_stack_arg_space
Expand All @@ -2020,6 +2025,16 @@ impl<M: ABIMachineSpec> Callee<M> {
M::get_number_of_spillslots_for_value(rc, max, &self.isa_flags)
}

/// Get the spill slot offset relative to nominal SP.
pub fn get_spillslot_offset(&self, slot: SpillSlot) -> i64 {
// Offset from beginning of spillslot area, which is at nominal SP + stackslots_size.
let islot = slot.index() as i64;
let spill_off = islot * M::word_bytes() as i64;
let sp_off = self.stackslots_size as i64 + spill_off;

sp_off
}

/// Generate a spill.
pub fn gen_spill(&self, to_slot: SpillSlot, from_reg: RealReg) -> M::I {
let ty = M::I::canonical_type_for_rc(Reg::from(from_reg).class());
Expand Down
28 changes: 14 additions & 14 deletions cranelift/codegen/src/machinst/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,10 +482,24 @@ impl CompiledCode {
&self,
isa: &dyn crate::isa::TargetIsa,
) -> CodegenResult<Option<crate::isa::unwind::UnwindInfo>> {
use crate::isa::unwind::UnwindInfoKind;
let unwind_info_kind = match isa.triple().operating_system {
target_lexicon::OperatingSystem::Windows => UnwindInfoKind::Windows,
_ => UnwindInfoKind::SystemV,
};
self.create_unwind_info_of_kind(isa, unwind_info_kind)
}

/// Creates unwind information for the function using the supplied
/// "kind". Supports cross-OS (but not cross-arch) generation.
///
/// Returns `None` if the function has no unwind information.
#[cfg(feature = "unwind")]
pub fn create_unwind_info_of_kind(
&self,
isa: &dyn crate::isa::TargetIsa,
unwind_info_kind: crate::isa::unwind::UnwindInfoKind,
) -> CodegenResult<Option<crate::isa::unwind::UnwindInfo>> {
isa.emit_unwind_info(self, unwind_info_kind)
}
}
Expand Down Expand Up @@ -537,17 +551,3 @@ pub trait TextSectionBuilder {
/// the bytes of the text section.
fn finish(&mut self, ctrl_plane: &mut ControlPlane) -> Vec<u8>;
}

/// Expected unwind info type.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum UnwindInfoKind {
/// No unwind info.
None,
/// SystemV CIE/FDE unwind info.
#[cfg(feature = "unwind")]
SystemV,
/// Windows X64 Unwind info
#[cfg(feature = "unwind")]
Windows,
}
Loading