From 694658b9494f8e6e3d764aa58e2441ba8b81fb73 Mon Sep 17 00:00:00 2001 From: Tyler McMullen Date: Mon, 4 Dec 2017 00:01:53 -0800 Subject: [PATCH] Move entirety of prologue_epilogue logic to abi module. --- lib/cretonne/src/isa/intel/abi.rs | 137 +++++++++++++++++++++++++++++- lib/cretonne/src/isa/intel/mod.rs | 123 +-------------------------- 2 files changed, 137 insertions(+), 123 deletions(-) diff --git a/lib/cretonne/src/isa/intel/abi.rs b/lib/cretonne/src/isa/intel/abi.rs index fdb0d0fe17..1a6aa0aeff 100644 --- a/lib/cretonne/src/isa/intel/abi.rs +++ b/lib/cretonne/src/isa/intel/abi.rs @@ -1,13 +1,18 @@ //! Intel ABI implementation. use ir; -use isa::{RegClass, RegUnit}; +use isa::{RegClass, RegUnit, TargetIsa}; use regalloc::AllocatableSet; use settings as shared_settings; use super::registers::{GPR, FPR, RU}; use abi::{ArgAction, ValueConversion, ArgAssigner, legalize_args}; -use ir::{AbiParam, ArgumentPurpose, ArgumentLoc, ArgumentExtension, CallConv}; +use ir::{AbiParam, ArgumentPurpose, ArgumentLoc, ArgumentExtension, CallConv, InstBuilder}; +use ir::immediates::Imm64; +use stack_layout::layout_stack; use std::i32; +use cursor::{Cursor, EncCursor}; +use result; + /// Argument registers for x86-64 static ARG_GPRS: [RU; 6] = [RU::rdi, RU::rsi, RU::rdx, RU::rcx, RU::r8, RU::r9]; @@ -154,6 +159,7 @@ pub fn allocatable_registers( regs } +/// Get the set of callee-saved registers. pub fn callee_saved_registers(flags: &shared_settings::Flags) -> &'static [RU] { if flags.is_64bit() { &[RU::rbx, RU::r12, RU::r13, RU::r14, RU::r15] @@ -161,3 +167,130 @@ pub fn callee_saved_registers(flags: &shared_settings::Flags) -> &'static [RU] { &[RU::rbx, RU::rsi, RU::rdi] } } + +/// Insert a System V-compatible prologue and epilogue. +pub fn prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> result::CtonResult { + let word_size = if isa.flags().is_64bit() { 8 } else { 4 }; + let csr_type = if isa.flags().is_64bit() { + ir::types::I64 + } else { + ir::types::I32 + }; + let csrs = callee_saved_registers(isa.flags()); + let csr_stack_size = ((csrs.len() + 1) * word_size as usize) as i32; + + func.create_stack_slot(ir::StackSlotData { + kind: ir::StackSlotKind::IncomingArg, + size: csr_stack_size as u32, + offset: -csr_stack_size, + }); + + let total_stack_size = layout_stack(&mut func.stack_slots, word_size)? as i32; + let local_stack_size = (total_stack_size - csr_stack_size) as i64; + + // Add CSRs to function signature + let fp_arg = ir::AbiParam::special_reg( + csr_type, + ir::ArgumentPurpose::FramePointer, + RU::rbp as RegUnit, + ); + func.signature.params.push(fp_arg); + func.signature.returns.push(fp_arg); + + for csr in csrs.iter() { + let csr_arg = + ir::AbiParam::special_reg(csr_type, ir::ArgumentPurpose::CalleeSaved, *csr as RegUnit); + func.signature.params.push(csr_arg); + func.signature.returns.push(csr_arg); + } + + // Finally, insert the prologue and epilogues + let entry_ebb = func.layout.entry_block().expect("missing entry block"); + let mut pos = EncCursor::new(func, isa).at_first_insertion_point(entry_ebb); + + insert_prologue(&mut pos, local_stack_size, csr_type, csrs); + insert_epilogues(&mut pos, local_stack_size, csr_type, csrs); + + Ok(()) +} + +/// Insert the prologue for a given function. +fn insert_prologue( + pos: &mut EncCursor, + stack_size: i64, + csr_type: ir::types::Type, + csrs: &'static [RU], +) { + // Append param to entry EBB + let ebb = pos.current_ebb().expect("missing ebb under cursor"); + let fp = pos.func.dfg.append_ebb_param(ebb, csr_type); + pos.func.locations[fp] = ir::ValueLoc::Reg(RU::rbp as RegUnit); + + pos.ins().x86_push(fp); + pos.ins().copy_special( + RU::rsp as RegUnit, + RU::rbp as RegUnit, + ); + + if stack_size > 0 { + pos.ins().adjust_sp_imm(Imm64::new(-stack_size)); + } + + for reg in csrs.iter() { + // Append param to entry EBB + let csr_arg = pos.func.dfg.append_ebb_param(ebb, csr_type); + + // Assign it a location + pos.func.locations[csr_arg] = ir::ValueLoc::Reg(*reg as RegUnit); + + // Remember it so we can push it momentarily + pos.ins().x86_push(csr_arg); + } +} + +/// Find all `return` instructions and insert epilogues before them. +fn insert_epilogues( + pos: &mut EncCursor, + stack_size: i64, + csr_type: ir::types::Type, + csrs: &'static [RU], +) { + while let Some(ebb) = pos.next_ebb() { + pos.goto_last_inst(ebb); + if let Some(inst) = pos.current_inst() { + if pos.func.dfg[inst].opcode().is_return() { + insert_epilogue(inst, stack_size, pos, csr_type, csrs); + } + } + } + +} + +/// Insert an epilogue given a specific `return` instruction. +fn insert_epilogue( + inst: ir::Inst, + stack_size: i64, + pos: &mut EncCursor, + csr_type: ir::types::Type, + csrs: &'static [RU], +) { + if stack_size > 0 { + pos.ins().adjust_sp_imm(Imm64::new(stack_size)); + } + + // Pop all the callee-saved registers, stepping backward each time to + // preserve the correct order. + let fp_ret = pos.ins().x86_pop(csr_type); + pos.prev_inst(); + + pos.func.locations[fp_ret] = ir::ValueLoc::Reg(RU::rbp as RegUnit); + pos.func.dfg.append_inst_arg(inst, fp_ret); + + for reg in csrs.iter() { + let csr_ret = pos.ins().x86_pop(csr_type); + pos.prev_inst(); + + pos.func.locations[csr_ret] = ir::ValueLoc::Reg(*reg as RegUnit); + pos.func.dfg.append_inst_arg(inst, csr_ret); + } +} diff --git a/lib/cretonne/src/isa/intel/mod.rs b/lib/cretonne/src/isa/intel/mod.rs index 541f329726..96048c5fbd 100644 --- a/lib/cretonne/src/isa/intel/mod.rs +++ b/lib/cretonne/src/isa/intel/mod.rs @@ -10,15 +10,10 @@ use binemit::{CodeSink, MemoryCodeSink, emit_function}; use super::super::settings as shared_settings; use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, Encodings}; use isa::Builder as IsaBuilder; -use isa::{TargetIsa, RegInfo, RegClass, EncInfo, RegUnit}; -use self::registers::RU; +use isa::{TargetIsa, RegInfo, RegClass, EncInfo}; use ir; use regalloc; use result; -use ir::InstBuilder; -use ir::immediates::Imm64; -use stack_layout::layout_stack; -use cursor::{Cursor, EncCursor}; #[allow(dead_code)] @@ -120,120 +115,6 @@ impl TargetIsa for Isa { } fn prologue_epilogue(&self, func: &mut ir::Function) -> result::CtonResult { - let word_size = if self.flags().is_64bit() { 8 } else { 4 }; - let csr_type = if self.flags().is_64bit() { - ir::types::I64 - } else { - ir::types::I32 - }; - let csrs = abi::callee_saved_registers(&self.shared_flags); - let csr_stack_size = ((csrs.len() + 1) * word_size as usize) as i32; - - func.create_stack_slot(ir::StackSlotData { - kind: ir::StackSlotKind::IncomingArg, - size: csr_stack_size as u32, - offset: -csr_stack_size, - }); - - let total_stack_size = layout_stack(&mut func.stack_slots, word_size)? as i32; - let local_stack_size = (total_stack_size - csr_stack_size) as i64; - - // Add CSRs to function signature - let fp_arg = ir::AbiParam::special_reg( - csr_type, - ir::ArgumentPurpose::FramePointer, - RU::rbp as RegUnit, - ); - func.signature.params.push(fp_arg); - func.signature.returns.push(fp_arg); - - for csr in csrs.iter() { - let csr_arg = ir::AbiParam::special_reg( - csr_type, - ir::ArgumentPurpose::CalleeSaved, - *csr as RegUnit, - ); - func.signature.params.push(csr_arg); - func.signature.returns.push(csr_arg); - } - - - let entry_ebb = func.layout.entry_block().expect("missing entry block"); - let mut pos = EncCursor::new(func, self).at_first_insertion_point(entry_ebb); - - self.insert_prologue(&mut pos, local_stack_size, csr_type); - self.insert_epilogues(&mut pos, local_stack_size, csr_type); - - Ok(()) - } -} - -impl Isa { - fn insert_prologue(&self, pos: &mut EncCursor, stack_size: i64, csr_type: ir::types::Type) { - // Append param to entry EBB - let ebb = pos.current_ebb().expect("missing ebb under cursor"); - let fp = pos.func.dfg.append_ebb_param(ebb, csr_type); - pos.func.locations[fp] = ir::ValueLoc::Reg(RU::rbp as RegUnit); - - pos.ins().x86_push(fp); - pos.ins().copy_special( - RU::rsp as RegUnit, - RU::rbp as RegUnit, - ); - - if stack_size > 0 { - pos.ins().adjust_sp_imm(Imm64::new(-stack_size)); - } - - let csrs = abi::callee_saved_registers(&self.shared_flags); - for reg in csrs.iter() { - // Append param to entry EBB - let csr_arg = pos.func.dfg.append_ebb_param(ebb, csr_type); - - // Assign it a location - pos.func.locations[csr_arg] = ir::ValueLoc::Reg(*reg as RegUnit); - - // Remember it so we can push it momentarily - pos.ins().x86_push(csr_arg); - } - } - - fn insert_epilogues(&self, pos: &mut EncCursor, stack_size: i64, csr_type: ir::types::Type) { - while let Some(ebb) = pos.next_ebb() { - pos.goto_last_inst(ebb); - if let Some(inst) = pos.current_inst() { - if pos.func.dfg[inst].opcode().is_return() { - self.insert_epilogue(inst, stack_size, pos, csr_type); - } - } - } - - } - - fn insert_epilogue( - &self, - inst: ir::Inst, - stack_size: i64, - pos: &mut EncCursor, - csr_type: ir::types::Type, - ) { - if stack_size > 0 { - pos.ins().adjust_sp_imm(Imm64::new(stack_size)); - } - - let fp_ret = pos.ins().x86_pop(csr_type); - pos.prev_inst(); - - pos.func.locations[fp_ret] = ir::ValueLoc::Reg(RU::rbp as RegUnit); - pos.func.dfg.append_inst_arg(inst, fp_ret); - - let csrs = abi::callee_saved_registers(&self.shared_flags); - for reg in csrs.iter() { - let csr_ret = pos.ins().x86_pop(csr_type); - pos.prev_inst(); - - pos.func.locations[csr_ret] = ir::ValueLoc::Reg(*reg as RegUnit); - pos.func.dfg.append_inst_arg(inst, csr_ret); - } + abi::prologue_epilogue(func, self) } }