s390x: Small refactoring of ABI code (#4465)
Remove a bit of duplicated code and eliminate some unnecessary allocations.
This commit is contained in:
@@ -71,7 +71,7 @@ use crate::machinst::{RealReg, Reg, RegClass, Writable};
|
|||||||
use crate::settings;
|
use crate::settings;
|
||||||
use crate::{CodegenError, CodegenResult};
|
use crate::{CodegenError, CodegenResult};
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use regalloc2::{PReg, PRegSet, VReg};
|
use regalloc2::{PReg, PRegSet};
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
@@ -509,30 +509,11 @@ impl ABIMachineSpec for S390xMachineDeps {
|
|||||||
outgoing_args_size: u32,
|
outgoing_args_size: u32,
|
||||||
) -> (u64, SmallVec<[Inst; 16]>) {
|
) -> (u64, SmallVec<[Inst; 16]>) {
|
||||||
let mut insts = SmallVec::new();
|
let mut insts = SmallVec::new();
|
||||||
let mut clobbered_fpr = vec![];
|
|
||||||
let mut clobbered_gpr = vec![];
|
|
||||||
|
|
||||||
for ® in clobbered_callee_saves.iter() {
|
// Collect clobbered registers.
|
||||||
match reg.to_reg().class() {
|
let is_leaf = outgoing_args_size == 0;
|
||||||
RegClass::Int => clobbered_gpr.push(reg),
|
let (first_clobbered_gpr, clobbered_fpr) =
|
||||||
RegClass::Float => clobbered_fpr.push(reg),
|
get_clobbered_gpr_fpr(clobbered_callee_saves, is_leaf);
|
||||||
}
|
|
||||||
}
|
|
||||||
// We need to save the link register in non-leaf functions.
|
|
||||||
// FIXME: This should be included in the clobber list to begin with,
|
|
||||||
// but isn't because we have have excluded call instructions via the
|
|
||||||
// is_included_in_clobbers callback.
|
|
||||||
if outgoing_args_size > 0 {
|
|
||||||
clobbered_gpr.push(Writable::from_reg(RealReg::from(gpr_preg(14))));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut first_clobbered_gpr = 16;
|
|
||||||
for reg in clobbered_gpr {
|
|
||||||
let enc = reg.to_reg().hw_enc();
|
|
||||||
if enc < first_clobbered_gpr {
|
|
||||||
first_clobbered_gpr = enc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let clobber_size = clobbered_fpr.len() * 8;
|
let clobber_size = clobbered_fpr.len() * 8;
|
||||||
if flags.unwind_info() {
|
if flags.unwind_info() {
|
||||||
insts.push(Inst::Unwind {
|
insts.push(Inst::Unwind {
|
||||||
@@ -607,30 +588,20 @@ impl ABIMachineSpec for S390xMachineDeps {
|
|||||||
|
|
||||||
fn gen_clobber_restore(
|
fn gen_clobber_restore(
|
||||||
call_conv: isa::CallConv,
|
call_conv: isa::CallConv,
|
||||||
_: &Signature,
|
sig: &Signature,
|
||||||
_: &settings::Flags,
|
flags: &settings::Flags,
|
||||||
clobbers: &[Writable<RealReg>],
|
clobbers: &[Writable<RealReg>],
|
||||||
fixed_frame_storage_size: u32,
|
fixed_frame_storage_size: u32,
|
||||||
outgoing_args_size: u32,
|
outgoing_args_size: u32,
|
||||||
) -> SmallVec<[Inst; 16]> {
|
) -> SmallVec<[Inst; 16]> {
|
||||||
let mut insts = SmallVec::new();
|
let mut insts = SmallVec::new();
|
||||||
|
let clobbered_callee_saves =
|
||||||
|
Self::get_clobbered_callee_saves(call_conv, flags, sig, clobbers);
|
||||||
|
|
||||||
// Collect clobbered registers.
|
// Collect clobbered registers.
|
||||||
let (mut clobbered_gpr, clobbered_fpr) = get_regs_saved_in_prologue(call_conv, clobbers);
|
let is_leaf = outgoing_args_size == 0;
|
||||||
// We need to restore the link register in non-leaf functions.
|
let (first_clobbered_gpr, clobbered_fpr) =
|
||||||
// FIXME: This should be included in the clobber list to begin with,
|
get_clobbered_gpr_fpr(&clobbered_callee_saves, is_leaf);
|
||||||
// but isn't because we have have excluded call instructions via the
|
|
||||||
// is_included_in_clobbers callback.
|
|
||||||
if outgoing_args_size > 0 {
|
|
||||||
clobbered_gpr.push(Writable::from_reg(RealReg::from(gpr_preg(14))));
|
|
||||||
}
|
|
||||||
let mut first_clobbered_gpr = 16;
|
|
||||||
for reg in clobbered_gpr {
|
|
||||||
let enc = reg.to_reg().hw_enc();
|
|
||||||
if enc < first_clobbered_gpr {
|
|
||||||
first_clobbered_gpr = enc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let clobber_size = clobbered_fpr.len() * 8;
|
let clobber_size = clobbered_fpr.len() * 8;
|
||||||
|
|
||||||
// Restore FPRs.
|
// Restore FPRs.
|
||||||
@@ -770,24 +741,38 @@ fn is_reg_saved_in_prologue(_call_conv: isa::CallConv, r: RealReg) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_regs_saved_in_prologue(
|
fn get_clobbered_gpr_fpr(
|
||||||
call_conv: isa::CallConv,
|
clobbered_callee_saves: &[Writable<RealReg>],
|
||||||
regs: &[Writable<RealReg>],
|
is_leaf: bool,
|
||||||
) -> (Vec<Writable<RealReg>>, Vec<Writable<RealReg>>) {
|
) -> (u8, SmallVec<[Writable<RealReg>; 8]>) {
|
||||||
let mut int_saves = vec![];
|
// Collect clobbered registers. Note we save/restore GPR always as
|
||||||
let mut fpr_saves = vec![];
|
// a block of registers using LOAD MULTIPLE / STORE MULTIPLE, starting
|
||||||
for ® in regs {
|
// with the clobbered GPR with the lowest number up to %r15. We
|
||||||
if is_reg_saved_in_prologue(call_conv, reg.to_reg()) {
|
// return the number of that first GPR (or 16 if none is to be saved).
|
||||||
match reg.to_reg().class() {
|
let mut clobbered_fpr = SmallVec::new();
|
||||||
RegClass::Int => int_saves.push(reg),
|
let mut first_clobbered_gpr = 16;
|
||||||
RegClass::Float => fpr_saves.push(reg),
|
|
||||||
|
// We need to save/restore the link register in non-leaf functions.
|
||||||
|
// FIXME: This should be included in the clobber list to begin with,
|
||||||
|
// but isn't because we have have excluded call instructions via the
|
||||||
|
// is_included_in_clobbers callback.
|
||||||
|
if !is_leaf {
|
||||||
|
first_clobbered_gpr = 14;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ® in clobbered_callee_saves.iter() {
|
||||||
|
match reg.to_reg().class() {
|
||||||
|
RegClass::Int => {
|
||||||
|
let enc = reg.to_reg().hw_enc();
|
||||||
|
if enc < first_clobbered_gpr {
|
||||||
|
first_clobbered_gpr = enc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
RegClass::Float => clobbered_fpr.push(reg),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Sort registers for deterministic code output.
|
|
||||||
int_saves.sort_by_key(|r| VReg::from(r.to_reg()).vreg());
|
(first_clobbered_gpr, clobbered_fpr)
|
||||||
fpr_saves.sort_by_key(|r| VReg::from(r.to_reg()).vreg());
|
|
||||||
(int_saves, fpr_saves)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn clobbers() -> PRegSet {
|
const fn clobbers() -> PRegSet {
|
||||||
|
|||||||
Reference in New Issue
Block a user