Fix AArch64 ABI to respect half-caller-save, half-callee-save vec regs.

This PR updates the AArch64 ABI implementation so that it (i) properly
respects that v8-v15 inclusive have callee-save lower halves, and
caller-save upper halves, by conservatively approximating (to full
registers) in the appropriate directions when generating prologue
caller-saves and when informing the regalloc of clobbered regs across
callsites.

In order to prevent saving all of these vector registers in the prologue
of every non-leaf function due to the above approximation, this also
makes use of a new regalloc.rs feature to exclude call instructions'
writes from the clobber set returned by register allocation. This is
safe whenever the caller and callee have the same ABI (because anything
the callee could clobber, the caller is allowed to clobber as well
without saving it in the prologue).

Fixes #2254.
This commit is contained in:
Chris Fallin
2020-10-05 18:43:26 -07:00
parent e22e2c3722
commit 71768bb6cf
29 changed files with 325 additions and 206 deletions

View File

@@ -510,7 +510,7 @@ impl ABIMachineSpec for AArch64MachineDeps {
fixed_frame_storage_size: u32,
) -> (u64, SmallVec<[Inst; 16]>) {
let mut insts = SmallVec::new();
let (clobbered_int, clobbered_vec) = get_callee_saves(call_conv, clobbers);
let (clobbered_int, clobbered_vec) = get_regs_saved_in_prologue(call_conv, clobbers);
let (int_save_bytes, vec_save_bytes) = saved_reg_stack_size(&clobbered_int, &clobbered_vec);
let total_save_bytes = (vec_save_bytes + int_save_bytes) as i32;
@@ -561,7 +561,7 @@ impl ABIMachineSpec for AArch64MachineDeps {
clobbers: &Set<Writable<RealReg>>,
) -> SmallVec<[Inst; 16]> {
let mut insts = SmallVec::new();
let (clobbered_int, clobbered_vec) = get_callee_saves(call_conv, clobbers);
let (clobbered_int, clobbered_vec) = get_regs_saved_in_prologue(call_conv, clobbers);
let (int_save_bytes, vec_save_bytes) = saved_reg_stack_size(&clobbered_int, &clobbered_vec);
for (i, reg_pair) in clobbered_int.chunks(2).enumerate() {
@@ -629,6 +629,8 @@ impl ABIMachineSpec for AArch64MachineDeps {
loc: SourceLoc,
opcode: ir::Opcode,
tmp: Writable<Reg>,
callee_conv: isa::CallConv,
caller_conv: isa::CallConv,
) -> SmallVec<[(InstIsSafepoint, Inst); 2]> {
let mut insts = SmallVec::new();
match &dest {
@@ -641,6 +643,8 @@ impl ABIMachineSpec for AArch64MachineDeps {
defs,
loc,
opcode,
caller_callconv: caller_conv,
callee_callconv: callee_conv,
}),
},
)),
@@ -663,6 +667,8 @@ impl ABIMachineSpec for AArch64MachineDeps {
defs,
loc,
opcode,
caller_callconv: caller_conv,
callee_callconv: callee_conv,
}),
},
));
@@ -676,6 +682,8 @@ impl ABIMachineSpec for AArch64MachineDeps {
defs,
loc,
opcode,
caller_callconv: caller_conv,
callee_callconv: callee_conv,
}),
},
)),
@@ -704,17 +712,17 @@ impl ABIMachineSpec for AArch64MachineDeps {
s.nominal_sp_to_fp
}
fn get_caller_saves(call_conv: isa::CallConv) -> Vec<Writable<Reg>> {
fn get_regs_clobbered_by_call(call_conv_of_callee: isa::CallConv) -> Vec<Writable<Reg>> {
let mut caller_saved = Vec::new();
for i in 0..29 {
let x = writable_xreg(i);
if is_caller_save_reg(call_conv, x.to_reg().to_real_reg()) {
if is_reg_clobbered_by_call(call_conv_of_callee, x.to_reg().to_real_reg()) {
caller_saved.push(x);
}
}
for i in 0..32 {
let v = writable_vreg(i);
if is_caller_save_reg(call_conv, v.to_reg().to_real_reg()) {
if is_reg_clobbered_by_call(call_conv_of_callee, v.to_reg().to_real_reg()) {
caller_saved.push(v);
}
}
@@ -731,7 +739,9 @@ fn legal_type_for_machine(ty: Type) -> bool {
}
}
fn is_callee_save_reg(call_conv: isa::CallConv, r: RealReg) -> bool {
/// Is the given register saved in the prologue if clobbered, i.e., is it a
/// callee-save?
fn is_reg_saved_in_prologue(call_conv: isa::CallConv, r: RealReg) -> bool {
if call_conv.extends_baldrdash() {
match r.get_class() {
RegClass::I64 => {
@@ -759,14 +769,17 @@ fn is_callee_save_reg(call_conv: isa::CallConv, r: RealReg) -> bool {
}
}
fn get_callee_saves(
/// Return the set of all integer and vector registers that must be saved in the
/// prologue and restored in the epilogue, given the set of all registers
/// written by the function's body.
fn get_regs_saved_in_prologue(
call_conv: isa::CallConv,
regs: &Set<Writable<RealReg>>,
) -> (Vec<Writable<RealReg>>, Vec<Writable<RealReg>>) {
let mut int_saves = vec![];
let mut vec_saves = vec![];
for &reg in regs.iter() {
if is_callee_save_reg(call_conv, reg.to_reg()) {
if is_reg_saved_in_prologue(call_conv, reg.to_reg()) {
match reg.to_reg().get_class() {
RegClass::I64 => int_saves.push(reg),
RegClass::V128 => vec_saves.push(reg),
@@ -781,8 +794,8 @@ fn get_callee_saves(
(int_saves, vec_saves)
}
fn is_caller_save_reg(call_conv: isa::CallConv, r: RealReg) -> bool {
if call_conv.extends_baldrdash() {
fn is_reg_clobbered_by_call(call_conv_of_callee: isa::CallConv, r: RealReg) -> bool {
if call_conv_of_callee.extends_baldrdash() {
match r.get_class() {
RegClass::I64 => {
let enc = r.get_hw_encoding();
@@ -808,8 +821,21 @@ fn is_caller_save_reg(call_conv: isa::CallConv, r: RealReg) -> bool {
r.get_hw_encoding() <= 17
}
RegClass::V128 => {
// v0 - v7 inclusive and v16 - v31 inclusive are caller-saves.
r.get_hw_encoding() <= 7 || (r.get_hw_encoding() >= 16 && r.get_hw_encoding() <= 31)
// v0 - v7 inclusive and v16 - v31 inclusive are caller-saves. The
// upper 64 bits of v8 - v15 inclusive are also caller-saves.
// However, because we cannot currently represent partial registers
// to regalloc.rs, we indicate here that every vector register is
// caller-save. Because this function is used at *callsites*,
// approximating in this direction (save more than necessary) is
// conservative and thus safe.
//
// Note that we set the 'not included in clobber set' flag in the
// regalloc.rs API when a call instruction's callee has the same ABI
// as the caller (the current function body); this is safe (anything
// clobbered by callee can be clobbered by caller as well) and
// avoids unnecessary saves of v8-v15 in the prologue even though we
// include them as defs here.
true
}
_ => panic!("Unexpected RegClass"),
}

View File

@@ -8,7 +8,7 @@ use crate::ir::Type;
use crate::isa::aarch64::inst::*;
use crate::machinst::{ty_bits, MachLabel};
use regalloc::{RealRegUniverse, Reg, Writable};
use regalloc::{PrettyPrint, RealRegUniverse, Reg, Writable};
use core::convert::Into;
use std::string::String;
@@ -348,19 +348,19 @@ impl BranchTarget {
}
}
impl ShowWithRRU for ShiftOpAndAmt {
impl PrettyPrint for ShiftOpAndAmt {
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
format!("{:?} {}", self.op(), self.amt().value())
}
}
impl ShowWithRRU for ExtendOp {
impl PrettyPrint for ExtendOp {
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
format!("{:?}", self)
}
}
impl ShowWithRRU for MemLabel {
impl PrettyPrint for MemLabel {
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
match self {
&MemLabel::PCRel(off) => format!("pc+{}", off),
@@ -379,7 +379,7 @@ fn shift_for_type(ty: Type) -> usize {
}
}
impl ShowWithRRU for AMode {
impl PrettyPrint for AMode {
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
match self {
&AMode::Unscaled(reg, simm9) => {
@@ -458,7 +458,7 @@ impl ShowWithRRU for AMode {
}
}
impl ShowWithRRU for PairAMode {
impl PrettyPrint for PairAMode {
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
match self {
&PairAMode::SignedOffset(reg, simm7) => {
@@ -482,7 +482,7 @@ impl ShowWithRRU for PairAMode {
}
}
impl ShowWithRRU for Cond {
impl PrettyPrint for Cond {
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
let mut s = format!("{:?}", self);
s.make_ascii_lowercase();
@@ -490,7 +490,7 @@ impl ShowWithRRU for Cond {
}
}
impl ShowWithRRU for BranchTarget {
impl PrettyPrint for BranchTarget {
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
match self {
&BranchTarget::Label(label) => format!("label{:?}", label.get()),

View File

@@ -1,6 +1,7 @@
use crate::ir::types::*;
use crate::isa::aarch64::inst::*;
use crate::isa::test_utils;
use crate::isa::CallConv;
use crate::settings;
use alloc::boxed::Box;
@@ -3789,6 +3790,8 @@ fn test_aarch64_binemit() {
defs: Vec::new(),
loc: SourceLoc::default(),
opcode: Opcode::Call,
caller_callconv: CallConv::SystemV,
callee_callconv: CallConv::SystemV,
}),
},
"00000094",
@@ -3803,6 +3806,8 @@ fn test_aarch64_binemit() {
defs: Vec::new(),
loc: SourceLoc::default(),
opcode: Opcode::CallIndirect,
caller_callconv: CallConv::SystemV,
callee_callconv: CallConv::SystemV,
}),
},
"40013FD6",

View File

@@ -5,9 +5,8 @@
use crate::ir::types::*;
use crate::ir::Type;
use crate::isa::aarch64::inst::OperandSize;
use crate::machinst::*;
use regalloc::RealRegUniverse;
use regalloc::{PrettyPrint, RealRegUniverse};
use core::convert::TryFrom;
use std::string::String;
@@ -668,7 +667,7 @@ impl MoveWideConst {
}
}
impl ShowWithRRU for NZCV {
impl PrettyPrint for NZCV {
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
let fmt = |c: char, v| if v { c.to_ascii_uppercase() } else { c };
format!(
@@ -681,13 +680,13 @@ impl ShowWithRRU for NZCV {
}
}
impl ShowWithRRU for UImm5 {
impl PrettyPrint for UImm5 {
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
format!("#{}", self.value)
}
}
impl ShowWithRRU for Imm12 {
impl PrettyPrint for Imm12 {
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
let shift = if self.shift12 { 12 } else { 0 };
let value = u32::from(self.bits) << shift;
@@ -695,49 +694,49 @@ impl ShowWithRRU for Imm12 {
}
}
impl ShowWithRRU for SImm7Scaled {
impl PrettyPrint for SImm7Scaled {
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
format!("#{}", self.value)
}
}
impl ShowWithRRU for FPULeftShiftImm {
impl PrettyPrint for FPULeftShiftImm {
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
format!("#{}", self.amount)
}
}
impl ShowWithRRU for FPURightShiftImm {
impl PrettyPrint for FPURightShiftImm {
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
format!("#{}", self.amount)
}
}
impl ShowWithRRU for SImm9 {
impl PrettyPrint for SImm9 {
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
format!("#{}", self.value)
}
}
impl ShowWithRRU for UImm12Scaled {
impl PrettyPrint for UImm12Scaled {
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
format!("#{}", self.value)
}
}
impl ShowWithRRU for ImmLogic {
impl PrettyPrint for ImmLogic {
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
format!("#{}", self.value())
}
}
impl ShowWithRRU for ImmShift {
impl PrettyPrint for ImmShift {
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
format!("#{}", self.imm)
}
}
impl ShowWithRRU for MoveWideConst {
impl PrettyPrint for MoveWideConst {
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
if self.shift == 0 {
format!("#{}", self.bits)

View File

@@ -9,10 +9,11 @@ use crate::ir::types::{
I32, I32X4, I64, I64X2, I8, I8X16, IFLAGS, R32, R64,
};
use crate::ir::{ExternalName, Opcode, SourceLoc, TrapCode, Type};
use crate::isa::CallConv;
use crate::machinst::*;
use crate::{settings, CodegenError, CodegenResult};
use regalloc::{RealRegUniverse, Reg, RegClass, SpillSlot, VirtualReg, Writable};
use regalloc::{PrettyPrint, RealRegUniverse, Reg, RegClass, SpillSlot, VirtualReg, Writable};
use regalloc::{RegUsageCollector, RegUsageMapper};
use alloc::boxed::Box;
@@ -392,6 +393,8 @@ pub struct CallInfo {
pub defs: Vec<Writable<Reg>>,
pub loc: SourceLoc,
pub opcode: Opcode,
pub caller_callconv: CallConv,
pub callee_callconv: CallConv,
}
/// Additional information for CallInd instructions, left out of line to lower the size of the Inst
@@ -403,6 +406,8 @@ pub struct CallIndInfo {
pub defs: Vec<Writable<Reg>>,
pub loc: SourceLoc,
pub opcode: Opcode,
pub caller_callconv: CallConv,
pub callee_callconv: CallConv,
}
/// Additional information for JTSequence instructions, left out of line to lower the size of the Inst
@@ -2491,6 +2496,24 @@ impl MachInst for Inst {
}
}
fn is_included_in_clobbers(&self) -> bool {
// We exclude call instructions from the clobber-set when they are calls
// from caller to callee with the same ABI. Such calls cannot possibly
// force any new registers to be saved in the prologue, because anything
// that the callee clobbers, the caller is also allowed to clobber. This
// both saves work and enables us to more precisely follow the
// half-caller-save, half-callee-save SysV ABI for some vector
// registers.
//
// See the note in [crate::isa::aarch64::abi::is_caller_save_reg] for
// more information on this ABI-implementation hack.
match self {
&Inst::Call { ref info } => info.caller_callconv != info.callee_callconv,
&Inst::CallInd { ref info } => info.caller_callconv != info.callee_callconv,
_ => true,
}
}
fn is_term<'a>(&'a self) -> MachTerminator<'a> {
match self {
&Inst::Ret | &Inst::EpiloguePlaceholder => MachTerminator::Ret,
@@ -2623,7 +2646,7 @@ fn mem_finalize_for_show(
(mem_str, mem)
}
impl ShowWithRRU for Inst {
impl PrettyPrint for Inst {
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
self.pretty_print(mb_rru, &mut EmitState::default())
}
@@ -2883,13 +2906,13 @@ impl Inst {
&Inst::StoreP64 { rt, rt2, ref mem } => {
let rt = rt.show_rru(mb_rru);
let rt2 = rt2.show_rru(mb_rru);
let mem = mem.show_rru_sized(mb_rru, /* size = */ 8);
let mem = mem.show_rru(mb_rru);
format!("stp {}, {}, {}", rt, rt2, mem)
}
&Inst::LoadP64 { rt, rt2, ref mem } => {
let rt = rt.to_reg().show_rru(mb_rru);
let rt2 = rt2.to_reg().show_rru(mb_rru);
let mem = mem.show_rru_sized(mb_rru, /* size = */ 8);
let mem = mem.show_rru(mb_rru);
format!("ldp {}, {}, {}", rt, rt2, mem)
}
&Inst::Mov64 { rd, rm } => {

View File

@@ -3,10 +3,11 @@
use crate::isa::aarch64::inst::OperandSize;
use crate::isa::aarch64::inst::ScalarSize;
use crate::isa::aarch64::inst::VectorSize;
use crate::machinst::*;
use crate::settings;
use regalloc::{RealRegUniverse, Reg, RegClass, RegClassInfo, Writable, NUM_REG_CLASSES};
use regalloc::{
PrettyPrint, RealRegUniverse, Reg, RegClass, RegClassInfo, Writable, NUM_REG_CLASSES,
};
use std::string::{String, ToString};

View File

@@ -1857,6 +1857,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
Opcode::Call | Opcode::CallIndirect => {
let loc = ctx.srcloc(insn);
let caller_conv = ctx.abi().call_conv();
let (mut abi, inputs) = match op {
Opcode::Call => {
let (extname, dist) = ctx.call_target(insn).unwrap();
@@ -1865,7 +1866,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
assert!(inputs.len() == sig.params.len());
assert!(outputs.len() == sig.returns.len());
(
AArch64ABICaller::from_func(sig, &extname, dist, loc)?,
AArch64ABICaller::from_func(sig, &extname, dist, loc, caller_conv)?,
&inputs[..],
)
}
@@ -1874,7 +1875,10 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
let sig = ctx.call_sig(insn).unwrap();
assert!(inputs.len() - 1 == sig.params.len());
assert!(outputs.len() == sig.returns.len());
(AArch64ABICaller::from_ptr(sig, ptr, loc, op)?, &inputs[1..])
(
AArch64ABICaller::from_ptr(sig, ptr, loc, op, caller_conv)?,
&inputs[1..],
)
}
_ => unreachable!(),
};

View File

@@ -3,15 +3,13 @@
use crate::ir::condcodes::IntCC;
use crate::ir::Function;
use crate::isa::Builder as IsaBuilder;
use crate::machinst::{
compile, MachBackend, MachCompileResult, ShowWithRRU, TargetIsaAdapter, VCode,
};
use crate::machinst::{compile, MachBackend, MachCompileResult, TargetIsaAdapter, VCode};
use crate::result::CodegenResult;
use crate::settings;
use alloc::boxed::Box;
use regalloc::RealRegUniverse;
use regalloc::{PrettyPrint, RealRegUniverse};
use target_lexicon::{Aarch64Architecture, Architecture, Triple};
// New backend:

View File

@@ -361,6 +361,8 @@ impl ABIMachineSpec for Arm32MachineDeps {
loc: SourceLoc,
opcode: ir::Opcode,
tmp: Writable<Reg>,
_callee_conv: isa::CallConv,
_caller_conv: isa::CallConv,
) -> SmallVec<[(InstIsSafepoint, Inst); 2]> {
let mut insts = SmallVec::new();
match &dest {
@@ -431,11 +433,11 @@ impl ABIMachineSpec for Arm32MachineDeps {
s.nominal_sp_to_fp
}
fn get_caller_saves(_call_conv: isa::CallConv) -> Vec<Writable<Reg>> {
fn get_regs_clobbered_by_call(_: isa::CallConv) -> Vec<Writable<Reg>> {
let mut caller_saved = Vec::new();
for i in 0..15 {
let r = writable_rreg(i);
if is_caller_save(r.to_reg().to_real_reg()) {
if is_reg_clobbered_by_call(r.to_reg().to_real_reg()) {
caller_saved.push(r);
}
}
@@ -461,7 +463,7 @@ fn get_callee_saves(regs: &Set<Writable<RealReg>>) -> Vec<Writable<RealReg>> {
ret
}
fn is_caller_save(r: RealReg) -> bool {
fn is_reg_clobbered_by_call(r: RealReg) -> bool {
let enc = r.get_hw_encoding();
enc <= 3
}

View File

@@ -2,7 +2,7 @@
use crate::isa::arm32::inst::*;
use regalloc::{RealRegUniverse, Reg};
use regalloc::{PrettyPrint, RealRegUniverse, Reg};
use std::string::String;
@@ -265,7 +265,7 @@ impl BranchTarget {
}
}
impl ShowWithRRU for ShiftOpAndAmt {
impl PrettyPrint for ShiftOpAndAmt {
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
let op = match self.op() {
ShiftOp::LSL => "lsl",
@@ -277,19 +277,19 @@ impl ShowWithRRU for ShiftOpAndAmt {
}
}
impl ShowWithRRU for UImm8 {
impl PrettyPrint for UImm8 {
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
format!("#{}", self.value)
}
}
impl ShowWithRRU for UImm12 {
impl PrettyPrint for UImm12 {
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
format!("#{}", self.value)
}
}
impl ShowWithRRU for AMode {
impl PrettyPrint for AMode {
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
match self {
&AMode::RegReg(rn, rm, imm2) => {
@@ -317,7 +317,7 @@ impl ShowWithRRU for AMode {
}
}
impl ShowWithRRU for Cond {
impl PrettyPrint for Cond {
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
let mut s = format!("{:?}", self);
s.make_ascii_lowercase();
@@ -325,7 +325,7 @@ impl ShowWithRRU for Cond {
}
}
impl ShowWithRRU for BranchTarget {
impl PrettyPrint for BranchTarget {
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
match self {
&BranchTarget::Label(label) => format!("label{:?}", label.get()),

View File

@@ -8,7 +8,7 @@ use crate::ir::{ExternalName, Opcode, SourceLoc, TrapCode, Type};
use crate::machinst::*;
use crate::{settings, CodegenError, CodegenResult};
use regalloc::{RealRegUniverse, Reg, RegClass, SpillSlot, VirtualReg, Writable};
use regalloc::{PrettyPrint, RealRegUniverse, Reg, RegClass, SpillSlot, VirtualReg, Writable};
use regalloc::{RegUsageCollector, RegUsageMapper};
use alloc::boxed::Box;
@@ -897,7 +897,7 @@ fn mem_finalize_for_show(
(mem_str, mem)
}
impl ShowWithRRU for Inst {
impl PrettyPrint for Inst {
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
self.pretty_print(mb_rru, &mut EmitState::default())
}

View File

@@ -513,6 +513,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
}
Opcode::Call | Opcode::CallIndirect => {
let loc = ctx.srcloc(insn);
let caller_conv = ctx.abi().call_conv();
let (mut abi, inputs) = match op {
Opcode::Call => {
let (extname, dist) = ctx.call_target(insn).unwrap();
@@ -521,7 +522,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
assert_eq!(inputs.len(), sig.params.len());
assert_eq!(outputs.len(), sig.returns.len());
(
Arm32ABICaller::from_func(sig, &extname, dist, loc)?,
Arm32ABICaller::from_func(sig, &extname, dist, loc, caller_conv)?,
&inputs[..],
)
}
@@ -530,7 +531,10 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
let sig = ctx.call_sig(insn).unwrap();
assert_eq!(inputs.len() - 1, sig.params.len());
assert_eq!(outputs.len(), sig.returns.len());
(Arm32ABICaller::from_ptr(sig, ptr, loc, op)?, &inputs[1..])
(
Arm32ABICaller::from_ptr(sig, ptr, loc, op, caller_conv)?,
&inputs[1..],
)
}
_ => unreachable!(),
};

View File

@@ -3,14 +3,12 @@
use crate::ir::condcodes::IntCC;
use crate::ir::Function;
use crate::isa::Builder as IsaBuilder;
use crate::machinst::{
compile, MachBackend, MachCompileResult, ShowWithRRU, TargetIsaAdapter, VCode,
};
use crate::machinst::{compile, MachBackend, MachCompileResult, TargetIsaAdapter, VCode};
use crate::result::CodegenResult;
use crate::settings;
use alloc::boxed::Box;
use regalloc::RealRegUniverse;
use regalloc::{PrettyPrint, RealRegUniverse};
use target_lexicon::{Architecture, ArmArchitecture, Triple};
// New backend:

View File

@@ -493,6 +493,8 @@ impl ABIMachineSpec for X64ABIMachineSpec {
loc: SourceLoc,
opcode: ir::Opcode,
tmp: Writable<Reg>,
_callee_conv: isa::CallConv,
_caller_conv: isa::CallConv,
) -> SmallVec<[(InstIsSafepoint, Self::I); 2]> {
let mut insts = SmallVec::new();
match dest {
@@ -545,7 +547,7 @@ impl ABIMachineSpec for X64ABIMachineSpec {
s.nominal_sp_to_fp
}
fn get_caller_saves(call_conv: isa::CallConv) -> Vec<Writable<Reg>> {
fn get_regs_clobbered_by_call(call_conv_of_callee: isa::CallConv) -> Vec<Writable<Reg>> {
let mut caller_saved = vec![
// Systemv calling convention:
// - GPR: all except RBX, RBP, R12 to R15 (which are callee-saved).
@@ -577,7 +579,7 @@ impl ABIMachineSpec for X64ABIMachineSpec {
Writable::from_reg(regs::xmm15()),
];
if call_conv.extends_baldrdash() {
if call_conv_of_callee.extends_baldrdash() {
caller_saved.push(Writable::from_reg(regs::r12()));
caller_saved.push(Writable::from_reg(regs::r13()));
// Not r14; implicitly preserved in the entry.

View File

@@ -5,7 +5,10 @@ use super::EmitState;
use crate::ir::condcodes::{FloatCC, IntCC};
use crate::machinst::*;
use core::fmt::Debug;
use regalloc::{RealRegUniverse, Reg, RegClass, RegUsageCollector, RegUsageMapper, Writable};
use regalloc::{
PrettyPrint, PrettyPrintSized, RealRegUniverse, Reg, RegClass, RegUsageCollector,
RegUsageMapper, Writable,
};
use std::fmt;
use std::string::{String, ToString};
@@ -68,7 +71,7 @@ impl Amode {
}
}
impl ShowWithRRU for Amode {
impl PrettyPrint for Amode {
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
match self {
Amode::ImmReg { simm32, base } => {
@@ -156,7 +159,7 @@ impl Into<SyntheticAmode> for Amode {
}
}
impl ShowWithRRU for SyntheticAmode {
impl PrettyPrint for SyntheticAmode {
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
match self {
SyntheticAmode::Real(addr) => addr.show_rru(mb_rru),
@@ -214,11 +217,13 @@ impl RegMemImm {
}
}
impl ShowWithRRU for RegMemImm {
impl PrettyPrint for RegMemImm {
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
self.show_rru_sized(mb_rru, 8)
}
}
impl PrettyPrintSized for RegMemImm {
fn show_rru_sized(&self, mb_rru: Option<&RealRegUniverse>, size: u8) -> String {
match self {
Self::Reg { reg } => show_ireg_sized(*reg, mb_rru, size),
@@ -271,11 +276,13 @@ impl From<Writable<Reg>> for RegMem {
}
}
impl ShowWithRRU for RegMem {
impl PrettyPrint for RegMem {
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
self.show_rru_sized(mb_rru, 8)
}
}
impl PrettyPrintSized for RegMem {
fn show_rru_sized(&self, mb_rru: Option<&RealRegUniverse>, size: u8) -> String {
match self {
RegMem::Reg { reg } => show_ireg_sized(*reg, mb_rru, size),
@@ -1098,7 +1105,7 @@ pub enum BranchTarget {
ResolvedOffset(isize),
}
impl ShowWithRRU for BranchTarget {
impl PrettyPrint for BranchTarget {
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
match self {
BranchTarget::Label(l) => format!("{:?}", l),

View File

@@ -8,8 +8,8 @@ use crate::{settings, settings::Flags, CodegenError, CodegenResult};
use alloc::boxed::Box;
use alloc::vec::Vec;
use regalloc::{
RealRegUniverse, Reg, RegClass, RegUsageCollector, RegUsageMapper, SpillSlot, VirtualReg,
Writable,
PrettyPrint, PrettyPrintSized, RealRegUniverse, Reg, RegClass, RegUsageCollector,
RegUsageMapper, SpillSlot, VirtualReg, Writable,
};
use smallvec::SmallVec;
use std::fmt;
@@ -1165,7 +1165,7 @@ impl Inst {
//=============================================================================
// Instructions: printing
impl ShowWithRRU for Inst {
impl PrettyPrint for Inst {
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
fn ljustify(s: String) -> String {
let w = 7;

View File

@@ -10,9 +10,11 @@
//! Also, they will have to be ABI dependent. Need to find a way to avoid constructing a universe
//! for each function we compile.
use crate::{machinst::pretty_print::ShowWithRRU, settings};
use crate::settings;
use alloc::vec::Vec;
use regalloc::{RealReg, RealRegUniverse, Reg, RegClass, RegClassInfo, NUM_REG_CLASSES};
use regalloc::{
PrettyPrint, RealReg, RealRegUniverse, Reg, RegClass, RegClassInfo, NUM_REG_CLASSES,
};
use std::string::String;
// Hardware encodings for a few registers.

View File

@@ -384,9 +384,10 @@ fn emit_vm_call<C: LowerCtx<I = Inst>>(
// TODO avoid recreating signatures for every single Libcall function.
let call_conv = CallConv::for_libcall(flags, CallConv::triple_default(triple));
let sig = make_libcall_sig(ctx, insn, call_conv, types::I64);
let caller_conv = ctx.abi().call_conv();
let loc = ctx.srcloc(insn);
let mut abi = X64ABICaller::from_func(&sig, &extname, dist, loc)?;
let mut abi = X64ABICaller::from_func(&sig, &extname, dist, loc, caller_conv)?;
abi.emit_stack_pre_adjust(ctx);
@@ -1558,6 +1559,7 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
Opcode::Call | Opcode::CallIndirect => {
let loc = ctx.srcloc(insn);
let caller_conv = ctx.abi().call_conv();
let (mut abi, inputs) = match op {
Opcode::Call => {
let (extname, dist) = ctx.call_target(insn).unwrap();
@@ -1565,7 +1567,7 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
assert_eq!(inputs.len(), sig.params.len());
assert_eq!(outputs.len(), sig.returns.len());
(
X64ABICaller::from_func(sig, &extname, dist, loc)?,
X64ABICaller::from_func(sig, &extname, dist, loc, caller_conv)?,
&inputs[..],
)
}
@@ -1575,7 +1577,10 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
let sig = ctx.call_sig(insn).unwrap();
assert_eq!(inputs.len() - 1, sig.params.len());
assert_eq!(outputs.len(), sig.returns.len());
(X64ABICaller::from_ptr(sig, ptr, loc, op)?, &inputs[1..])
(
X64ABICaller::from_ptr(sig, ptr, loc, op, caller_conv)?,
&inputs[1..],
)
}
_ => unreachable!(),

View File

@@ -4,13 +4,11 @@ use super::TargetIsa;
use crate::ir::{condcodes::IntCC, Function};
use crate::isa::x64::{inst::regs::create_reg_universe_systemv, settings as x64_settings};
use crate::isa::Builder as IsaBuilder;
use crate::machinst::{
compile, pretty_print::ShowWithRRU, MachBackend, MachCompileResult, TargetIsaAdapter, VCode,
};
use crate::machinst::{compile, MachBackend, MachCompileResult, TargetIsaAdapter, VCode};
use crate::result::CodegenResult;
use crate::settings::{self as shared_settings, Flags};
use alloc::boxed::Box;
use regalloc::RealRegUniverse;
use regalloc::{PrettyPrint, RealRegUniverse};
use target_lexicon::Triple;
mod abi;