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

Allow unwind support to work without a frame pointer #2838

Merged
merged 1 commit into from
Apr 14, 2021
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/inst/unwind/systemv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ impl crate::isa::unwind::systemv::RegisterMapper<Reg> for RegisterMapper {
fn sp(&self) -> u16 {
regs::stack_reg().get_hw_encoding().into()
}
fn fp(&self) -> u16 {
regs::fp_reg().get_hw_encoding().into()
fn fp(&self) -> Option<u16> {
Some(regs::fp_reg().get_hw_encoding().into())
}
fn lr(&self) -> Option<u16> {
Some(regs::link_reg().get_hw_encoding().into())
Expand Down
5 changes: 5 additions & 0 deletions cranelift/codegen/src/isa/unwind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,11 @@ pub enum UnwindInst {
/// the clobber area.
offset_downward_to_clobbers: u32,
},
/// The stack pointer was adjusted to allocate the stack.
StackAlloc {
/// Size to allocate.
size: u32,
},
/// The stack slot at the given offset from the clobber-area base has been
/// used to save the given register.
///
Expand Down
39 changes: 30 additions & 9 deletions cranelift/codegen/src/isa/unwind/systemv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,10 @@ pub(crate) trait RegisterMapper<Reg> {
fn map(&self, reg: Reg) -> Result<Register, RegisterMappingError>;
/// Gets stack pointer register.
fn sp(&self) -> Register;
/// Gets the frame pointer register.
fn fp(&self) -> Register;
/// Gets the frame pointer register, if any.
fn fp(&self) -> Option<Register> {
None
}
/// Gets the link register, if any.
fn lr(&self) -> Option<Register> {
None
Expand Down Expand Up @@ -151,6 +153,7 @@ pub(crate) fn create_unwind_info_from_insts<MR: RegisterMapper<regalloc::Reg>>(
) -> CodegenResult<UnwindInfo> {
let mut instructions = vec![];

let mut cfa_offset = 0;
let mut clobber_offset_to_cfa = 0;
for &(instruction_offset, ref inst) in insts {
match inst {
Expand All @@ -163,10 +166,14 @@ pub(crate) fn create_unwind_info_from_insts<MR: RegisterMapper<regalloc::Reg>>(
instruction_offset,
CallFrameInstruction::CfaOffset(offset_upward_to_caller_sp as i32),
));
// Note that we saved the old FP value on the stack.
// Note that we saved the old FP value on the stack. Use of this
// operation implies that the target defines a FP register.
instructions.push((
instruction_offset,
CallFrameInstruction::Offset(mr.fp(), -(offset_upward_to_caller_sp as i32)),
CallFrameInstruction::Offset(
mr.fp().unwrap(),
-(offset_upward_to_caller_sp as i32),
),
));
// If there is a link register on this architecture, note that
// we saved it as well.
Expand All @@ -188,15 +195,29 @@ pub(crate) fn create_unwind_info_from_insts<MR: RegisterMapper<regalloc::Reg>>(
// Define CFA in terms of FP. Note that we assume it was already
// defined correctly in terms of the current SP, and FP has just
// been set to the current SP, so we do not need to change the
// offset, only the register.
instructions.push((
instruction_offset,
CallFrameInstruction::CfaRegister(mr.fp()),
));
// offset, only the register. (This is done only if the target
// defines a frame pointer register.)
if let Some(fp) = mr.fp() {
instructions.push((instruction_offset, CallFrameInstruction::CfaRegister(fp)));
}
// Record initial CFA offset. This will be used with later
// StackAlloc calls if we do not have a frame pointer.
cfa_offset = offset_upward_to_caller_sp;
// Record distance from CFA downward to clobber area so we can
// express clobber offsets later in terms of CFA.
clobber_offset_to_cfa = offset_upward_to_caller_sp + offset_downward_to_clobbers;
}
&UnwindInst::StackAlloc { size } => {
// If we do not use a frame pointer, we need to update the
// CFA offset whenever the stack pointer changes.
if mr.fp().is_none() {
cfa_offset += size;
instructions.push((
instruction_offset,
CallFrameInstruction::CfaOffset(cfa_offset as i32),
));
}
}
&UnwindInst::SaveReg {
clobber_offset,
reg,
Expand Down
6 changes: 6 additions & 0 deletions cranelift/codegen/src/isa/unwind/winx64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,12 @@ pub(crate) fn create_unwind_info_from_insts<MR: RegisterMapper<regalloc::Reg>>(
frame_register_offset = ensure_unwind_offset(offset_downward_to_clobbers)?;
unwind_codes.push(UnwindCode::SetFPReg { instruction_offset });
}
&UnwindInst::StackAlloc { size } => {
unwind_codes.push(UnwindCode::StackAlloc {
instruction_offset,
size,
});
}
&UnwindInst::SaveReg {
clobber_offset,
reg,
Expand Down
4 changes: 2 additions & 2 deletions cranelift/codegen/src/isa/x64/inst/unwind/systemv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ impl crate::isa::unwind::systemv::RegisterMapper<Reg> for RegisterMapper {
fn sp(&self) -> u16 {
X86_64::RSP.0
}
fn fp(&self) -> u16 {
X86_64::RBP.0
fn fp(&self) -> Option<u16> {
Some(X86_64::RBP.0)
}
}

Expand Down
4 changes: 2 additions & 2 deletions cranelift/codegen/src/isa/x86/unwind/systemv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@ pub(crate) fn create_unwind_info(
fn sp(&self) -> u16 {
X86_64::RSP.0
}
fn fp(&self) -> u16 {
X86_64::RBP.0
fn fp(&self) -> Option<u16> {
Some(X86_64::RBP.0)
}
}
let map = RegisterMapper(isa);
Expand Down