diff --git a/cranelift/codegen/src/isa/aarch64/inst/unwind/systemv.rs b/cranelift/codegen/src/isa/aarch64/inst/unwind/systemv.rs index 9f2eb741a0..b514dc20b8 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/unwind/systemv.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/unwind/systemv.rs @@ -56,8 +56,8 @@ impl crate::isa::unwind::systemv::RegisterMapper 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 { + Some(regs::fp_reg().get_hw_encoding().into()) } fn lr(&self) -> Option { Some(regs::link_reg().get_hw_encoding().into()) diff --git a/cranelift/codegen/src/isa/unwind.rs b/cranelift/codegen/src/isa/unwind.rs index 7c9718a570..13397c3266 100644 --- a/cranelift/codegen/src/isa/unwind.rs +++ b/cranelift/codegen/src/isa/unwind.rs @@ -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. /// diff --git a/cranelift/codegen/src/isa/unwind/systemv.rs b/cranelift/codegen/src/isa/unwind/systemv.rs index 965603d4e1..5ceadef93f 100644 --- a/cranelift/codegen/src/isa/unwind/systemv.rs +++ b/cranelift/codegen/src/isa/unwind/systemv.rs @@ -122,8 +122,10 @@ pub(crate) trait RegisterMapper { fn map(&self, reg: Reg) -> Result; /// 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 { + None + } /// Gets the link register, if any. fn lr(&self) -> Option { None @@ -151,6 +153,7 @@ pub(crate) fn create_unwind_info_from_insts>( ) -> CodegenResult { 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 { @@ -163,10 +166,14 @@ pub(crate) fn create_unwind_info_from_insts>( 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. @@ -188,15 +195,29 @@ pub(crate) fn create_unwind_info_from_insts>( // 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, diff --git a/cranelift/codegen/src/isa/unwind/winx64.rs b/cranelift/codegen/src/isa/unwind/winx64.rs index f447d341ae..adac7caefa 100644 --- a/cranelift/codegen/src/isa/unwind/winx64.rs +++ b/cranelift/codegen/src/isa/unwind/winx64.rs @@ -356,6 +356,12 @@ pub(crate) fn create_unwind_info_from_insts>( 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, diff --git a/cranelift/codegen/src/isa/x64/inst/unwind/systemv.rs b/cranelift/codegen/src/isa/x64/inst/unwind/systemv.rs index c2a04a5c8e..9115db0671 100644 --- a/cranelift/codegen/src/isa/x64/inst/unwind/systemv.rs +++ b/cranelift/codegen/src/isa/x64/inst/unwind/systemv.rs @@ -89,8 +89,8 @@ impl crate::isa::unwind::systemv::RegisterMapper for RegisterMapper { fn sp(&self) -> u16 { X86_64::RSP.0 } - fn fp(&self) -> u16 { - X86_64::RBP.0 + fn fp(&self) -> Option { + Some(X86_64::RBP.0) } } diff --git a/cranelift/codegen/src/isa/x86/unwind/systemv.rs b/cranelift/codegen/src/isa/x86/unwind/systemv.rs index 0c3e749762..31fc64c9fb 100644 --- a/cranelift/codegen/src/isa/x86/unwind/systemv.rs +++ b/cranelift/codegen/src/isa/x86/unwind/systemv.rs @@ -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 { + Some(X86_64::RBP.0) } } let map = RegisterMapper(isa);