Skip to content

Commit

Permalink
group registers push/save
Browse files Browse the repository at this point in the history
  • Loading branch information
yurydelendik committed Oct 9, 2020
1 parent aa4e79d commit 51143ef
Showing 1 changed file with 38 additions and 14 deletions.
52 changes: 38 additions & 14 deletions cranelift/codegen/src/isa/x64/inst/unwind/systemv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

use crate::isa::unwind::systemv::{CallFrameInstruction, RegisterMappingError, UnwindInfo};
use crate::isa::x64::inst::{
args::{AluRmiROpcode, RegMemImm},
args::{AluRmiROpcode, Amode, RegMemImm, SyntheticAmode},
regs, Inst,
};
use crate::result::{CodegenError, CodegenResult};
use alloc::vec::Vec;
use gimli::{write::CommonInformationEntry, Encoding, Format, Register, X86_64};
use regalloc::{Reg, RegClass};
use std::boxed::Box;
use std::collections::HashSet;

/// Creates a new x86-64 common information entry (CIE).
pub fn create_cie() -> CommonInformationEntry {
Expand Down Expand Up @@ -90,6 +91,7 @@ pub fn map_reg(reg: Reg) -> Result<Register, RegisterMappingError> {
struct InstructionBuilder {
cfa_offset: i32,
frame_register: Option<Reg>,
saved_registers: HashSet<Reg>,
instructions: Vec<(u32, CallFrameInstruction)>,
}

Expand All @@ -98,20 +100,14 @@ impl InstructionBuilder {
Self {
cfa_offset: 8, // CFA offset starts at 8 to account to return address on stack
frame_register,
saved_registers: HashSet::new(),
instructions: Vec::new(),
}
}

fn push_reg(&mut self, offset: u32, arg: &RegMemImm) -> Result<(), RegisterMappingError> {
fn push_reg(&mut self, offset: u32, reg: Reg) -> Result<(), RegisterMappingError> {
self.cfa_offset += 8;

let reg = *match arg {
RegMemImm::Reg { reg } => reg,
_ => {
panic!();
}
};

// Update the CFA if this is the save of the frame pointer register or if a frame pointer isn't being used
// When using a frame pointer, we only need to update the CFA to account for the push of the frame pointer itself
if match self.frame_register {
Expand All @@ -121,38 +117,54 @@ impl InstructionBuilder {
self.instructions
.push((offset, CallFrameInstruction::CfaOffset(self.cfa_offset)));
}
self.store_reg_at(offset, 0, reg)
}

fn store_reg_at(
&mut self,
offset: u32,
pos: u32,
reg: Reg,
) -> Result<(), RegisterMappingError> {
if self.saved_registers.contains(&reg) {
// Already saved the register on stack.
return Ok(());
}

// Pushes in the prologue are register saves, so record an offset of the save
self.instructions.push((
offset,
CallFrameInstruction::Offset(map_reg(reg)?.0, -self.cfa_offset),
CallFrameInstruction::Offset(map_reg(reg)?.0, pos as i32 - self.cfa_offset),
));
self.saved_registers.insert(reg);

Ok(())
}

fn adjust_sp_down_imm(&mut self, offset: u32, imm: i64) {
assert!(imm <= core::u32::MAX as i64);

self.cfa_offset += imm as i32;

// Don't adjust the CFA if we're using a frame pointer
if self.frame_register.is_some() {
return;
}

self.cfa_offset += imm as i32;
self.instructions
.push((offset, CallFrameInstruction::CfaOffset(self.cfa_offset)));
}

fn adjust_sp_up_imm(&mut self, offset: u32, imm: i64) {
assert!(imm <= core::u32::MAX as i64);

self.cfa_offset -= imm as i32;

// Don't adjust the CFA if we're using a frame pointer
if self.frame_register.is_some() {
return;
}

self.cfa_offset -= imm as i32;
self.instructions
.push((offset, CallFrameInstruction::CfaOffset(self.cfa_offset)));
}
Expand Down Expand Up @@ -197,9 +209,11 @@ pub(crate) fn create_unwind_info(

// TODO sub and `mov reg, imm(rsp)`
match inst {
Inst::Push64 { src } => {
Inst::Push64 {
src: RegMemImm::Reg { reg },
} => {
builder
.push_reg(offset, src)
.push_reg(offset, *reg)
.map_err(CodegenError::RegisterMappingError)?;
}
Inst::MovRR { src, dst, .. } => {
Expand All @@ -217,6 +231,16 @@ pub(crate) fn create_unwind_info(
let imm = *simm32 as i32;
builder.adjust_sp_down_imm(offset, imm.into());
}
Inst::MovRM {
src,
dst: SyntheticAmode::Real(Amode::ImmReg { simm32, base }),
..
} if *base == regs::rsp() => {
// `mov reg, imm(rsp)` -- similar to push
builder
.store_reg_at(offset, *simm32, *src)
.map_err(CodegenError::RegisterMappingError)?;
}
Inst::AluRmiR {
is_64: true,
op: AluRmiROpcode::Add,
Expand Down

0 comments on commit 51143ef

Please sign in to comment.