Merge pull request #2267 from cfallin/fix-aarch64-abi
Fix AArch64 ABI to respect half-caller-save, half-callee-save vec regs.
This commit is contained in:
4
Cargo.lock
generated
4
Cargo.lock
generated
@@ -1692,9 +1692,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regalloc"
|
name = "regalloc"
|
||||||
version = "0.0.30"
|
version = "0.0.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2041c2d34f6ff346d6f428974f03d8bf12679b0c816bb640dc5eb1d48848d8d1"
|
checksum = "571f7f397d61c4755285cd37853fe8e03271c243424a907415909379659381c5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ byteorder = { version = "1.3.2", default-features = false }
|
|||||||
peepmatic = { path = "../peepmatic", optional = true, version = "0.67.0" }
|
peepmatic = { path = "../peepmatic", optional = true, version = "0.67.0" }
|
||||||
peepmatic-traits = { path = "../peepmatic/crates/traits", optional = true, version = "0.67.0" }
|
peepmatic-traits = { path = "../peepmatic/crates/traits", optional = true, version = "0.67.0" }
|
||||||
peepmatic-runtime = { path = "../peepmatic/crates/runtime", optional = true, version = "0.67.0" }
|
peepmatic-runtime = { path = "../peepmatic/crates/runtime", optional = true, version = "0.67.0" }
|
||||||
regalloc = "0.0.30"
|
regalloc = { version = "0.0.31" }
|
||||||
souper-ir = { version = "1", optional = true }
|
souper-ir = { version = "1", optional = true }
|
||||||
wast = { version = "25.0.0", optional = true }
|
wast = { version = "25.0.0", optional = true }
|
||||||
# It is a goal of the cranelift-codegen crate to have minimal external dependencies.
|
# It is a goal of the cranelift-codegen crate to have minimal external dependencies.
|
||||||
|
|||||||
@@ -510,7 +510,7 @@ impl ABIMachineSpec for AArch64MachineDeps {
|
|||||||
fixed_frame_storage_size: u32,
|
fixed_frame_storage_size: u32,
|
||||||
) -> (u64, SmallVec<[Inst; 16]>) {
|
) -> (u64, SmallVec<[Inst; 16]>) {
|
||||||
let mut insts = SmallVec::new();
|
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 (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;
|
let total_save_bytes = (vec_save_bytes + int_save_bytes) as i32;
|
||||||
@@ -561,7 +561,7 @@ impl ABIMachineSpec for AArch64MachineDeps {
|
|||||||
clobbers: &Set<Writable<RealReg>>,
|
clobbers: &Set<Writable<RealReg>>,
|
||||||
) -> SmallVec<[Inst; 16]> {
|
) -> SmallVec<[Inst; 16]> {
|
||||||
let mut insts = SmallVec::new();
|
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 (int_save_bytes, vec_save_bytes) = saved_reg_stack_size(&clobbered_int, &clobbered_vec);
|
||||||
for (i, reg_pair) in clobbered_int.chunks(2).enumerate() {
|
for (i, reg_pair) in clobbered_int.chunks(2).enumerate() {
|
||||||
@@ -629,6 +629,8 @@ impl ABIMachineSpec for AArch64MachineDeps {
|
|||||||
loc: SourceLoc,
|
loc: SourceLoc,
|
||||||
opcode: ir::Opcode,
|
opcode: ir::Opcode,
|
||||||
tmp: Writable<Reg>,
|
tmp: Writable<Reg>,
|
||||||
|
callee_conv: isa::CallConv,
|
||||||
|
caller_conv: isa::CallConv,
|
||||||
) -> SmallVec<[(InstIsSafepoint, Inst); 2]> {
|
) -> SmallVec<[(InstIsSafepoint, Inst); 2]> {
|
||||||
let mut insts = SmallVec::new();
|
let mut insts = SmallVec::new();
|
||||||
match &dest {
|
match &dest {
|
||||||
@@ -641,6 +643,8 @@ impl ABIMachineSpec for AArch64MachineDeps {
|
|||||||
defs,
|
defs,
|
||||||
loc,
|
loc,
|
||||||
opcode,
|
opcode,
|
||||||
|
caller_callconv: caller_conv,
|
||||||
|
callee_callconv: callee_conv,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
@@ -663,6 +667,8 @@ impl ABIMachineSpec for AArch64MachineDeps {
|
|||||||
defs,
|
defs,
|
||||||
loc,
|
loc,
|
||||||
opcode,
|
opcode,
|
||||||
|
caller_callconv: caller_conv,
|
||||||
|
callee_callconv: callee_conv,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
@@ -676,6 +682,8 @@ impl ABIMachineSpec for AArch64MachineDeps {
|
|||||||
defs,
|
defs,
|
||||||
loc,
|
loc,
|
||||||
opcode,
|
opcode,
|
||||||
|
caller_callconv: caller_conv,
|
||||||
|
callee_callconv: callee_conv,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
@@ -704,17 +712,17 @@ impl ABIMachineSpec for AArch64MachineDeps {
|
|||||||
s.nominal_sp_to_fp
|
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();
|
let mut caller_saved = Vec::new();
|
||||||
for i in 0..29 {
|
for i in 0..29 {
|
||||||
let x = writable_xreg(i);
|
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);
|
caller_saved.push(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i in 0..32 {
|
for i in 0..32 {
|
||||||
let v = writable_vreg(i);
|
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);
|
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() {
|
if call_conv.extends_baldrdash() {
|
||||||
match r.get_class() {
|
match r.get_class() {
|
||||||
RegClass::I64 => {
|
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,
|
call_conv: isa::CallConv,
|
||||||
regs: &Set<Writable<RealReg>>,
|
regs: &Set<Writable<RealReg>>,
|
||||||
) -> (Vec<Writable<RealReg>>, Vec<Writable<RealReg>>) {
|
) -> (Vec<Writable<RealReg>>, Vec<Writable<RealReg>>) {
|
||||||
let mut int_saves = vec![];
|
let mut int_saves = vec![];
|
||||||
let mut vec_saves = vec![];
|
let mut vec_saves = vec![];
|
||||||
for ® in regs.iter() {
|
for ® 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() {
|
match reg.to_reg().get_class() {
|
||||||
RegClass::I64 => int_saves.push(reg),
|
RegClass::I64 => int_saves.push(reg),
|
||||||
RegClass::V128 => vec_saves.push(reg),
|
RegClass::V128 => vec_saves.push(reg),
|
||||||
@@ -781,8 +794,8 @@ fn get_callee_saves(
|
|||||||
(int_saves, vec_saves)
|
(int_saves, vec_saves)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_caller_save_reg(call_conv: isa::CallConv, r: RealReg) -> bool {
|
fn is_reg_clobbered_by_call(call_conv_of_callee: isa::CallConv, r: RealReg) -> bool {
|
||||||
if call_conv.extends_baldrdash() {
|
if call_conv_of_callee.extends_baldrdash() {
|
||||||
match r.get_class() {
|
match r.get_class() {
|
||||||
RegClass::I64 => {
|
RegClass::I64 => {
|
||||||
let enc = r.get_hw_encoding();
|
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
|
r.get_hw_encoding() <= 17
|
||||||
}
|
}
|
||||||
RegClass::V128 => {
|
RegClass::V128 => {
|
||||||
// v0 - v7 inclusive and v16 - v31 inclusive are caller-saves.
|
// v0 - v7 inclusive and v16 - v31 inclusive are caller-saves. The
|
||||||
r.get_hw_encoding() <= 7 || (r.get_hw_encoding() >= 16 && r.get_hw_encoding() <= 31)
|
// 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"),
|
_ => panic!("Unexpected RegClass"),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use crate::ir::Type;
|
|||||||
use crate::isa::aarch64::inst::*;
|
use crate::isa::aarch64::inst::*;
|
||||||
use crate::machinst::{ty_bits, MachLabel};
|
use crate::machinst::{ty_bits, MachLabel};
|
||||||
|
|
||||||
use regalloc::{RealRegUniverse, Reg, Writable};
|
use regalloc::{PrettyPrint, RealRegUniverse, Reg, Writable};
|
||||||
|
|
||||||
use core::convert::Into;
|
use core::convert::Into;
|
||||||
use std::string::String;
|
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 {
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
format!("{:?} {}", self.op(), self.amt().value())
|
format!("{:?} {}", self.op(), self.amt().value())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShowWithRRU for ExtendOp {
|
impl PrettyPrint for ExtendOp {
|
||||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
format!("{:?}", self)
|
format!("{:?}", self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShowWithRRU for MemLabel {
|
impl PrettyPrint for MemLabel {
|
||||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
match self {
|
match self {
|
||||||
&MemLabel::PCRel(off) => format!("pc+{}", off),
|
&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 {
|
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
match self {
|
match self {
|
||||||
&AMode::Unscaled(reg, simm9) => {
|
&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 {
|
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
match self {
|
match self {
|
||||||
&PairAMode::SignedOffset(reg, simm7) => {
|
&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 {
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
let mut s = format!("{:?}", self);
|
let mut s = format!("{:?}", self);
|
||||||
s.make_ascii_lowercase();
|
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 {
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
match self {
|
match self {
|
||||||
&BranchTarget::Label(label) => format!("label{:?}", label.get()),
|
&BranchTarget::Label(label) => format!("label{:?}", label.get()),
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use crate::ir::types::*;
|
use crate::ir::types::*;
|
||||||
use crate::isa::aarch64::inst::*;
|
use crate::isa::aarch64::inst::*;
|
||||||
use crate::isa::test_utils;
|
use crate::isa::test_utils;
|
||||||
|
use crate::isa::CallConv;
|
||||||
use crate::settings;
|
use crate::settings;
|
||||||
|
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
@@ -3789,6 +3790,8 @@ fn test_aarch64_binemit() {
|
|||||||
defs: Vec::new(),
|
defs: Vec::new(),
|
||||||
loc: SourceLoc::default(),
|
loc: SourceLoc::default(),
|
||||||
opcode: Opcode::Call,
|
opcode: Opcode::Call,
|
||||||
|
caller_callconv: CallConv::SystemV,
|
||||||
|
callee_callconv: CallConv::SystemV,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
"00000094",
|
"00000094",
|
||||||
@@ -3803,6 +3806,8 @@ fn test_aarch64_binemit() {
|
|||||||
defs: Vec::new(),
|
defs: Vec::new(),
|
||||||
loc: SourceLoc::default(),
|
loc: SourceLoc::default(),
|
||||||
opcode: Opcode::CallIndirect,
|
opcode: Opcode::CallIndirect,
|
||||||
|
caller_callconv: CallConv::SystemV,
|
||||||
|
callee_callconv: CallConv::SystemV,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
"40013FD6",
|
"40013FD6",
|
||||||
|
|||||||
@@ -5,9 +5,8 @@
|
|||||||
use crate::ir::types::*;
|
use crate::ir::types::*;
|
||||||
use crate::ir::Type;
|
use crate::ir::Type;
|
||||||
use crate::isa::aarch64::inst::OperandSize;
|
use crate::isa::aarch64::inst::OperandSize;
|
||||||
use crate::machinst::*;
|
|
||||||
|
|
||||||
use regalloc::RealRegUniverse;
|
use regalloc::{PrettyPrint, RealRegUniverse};
|
||||||
|
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
use std::string::String;
|
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 {
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
let fmt = |c: char, v| if v { c.to_ascii_uppercase() } else { c };
|
let fmt = |c: char, v| if v { c.to_ascii_uppercase() } else { c };
|
||||||
format!(
|
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 {
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
format!("#{}", self.value)
|
format!("#{}", self.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShowWithRRU for Imm12 {
|
impl PrettyPrint for Imm12 {
|
||||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
let shift = if self.shift12 { 12 } else { 0 };
|
let shift = if self.shift12 { 12 } else { 0 };
|
||||||
let value = u32::from(self.bits) << shift;
|
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 {
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
format!("#{}", self.value)
|
format!("#{}", self.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShowWithRRU for FPULeftShiftImm {
|
impl PrettyPrint for FPULeftShiftImm {
|
||||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
format!("#{}", self.amount)
|
format!("#{}", self.amount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShowWithRRU for FPURightShiftImm {
|
impl PrettyPrint for FPURightShiftImm {
|
||||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
format!("#{}", self.amount)
|
format!("#{}", self.amount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShowWithRRU for SImm9 {
|
impl PrettyPrint for SImm9 {
|
||||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
format!("#{}", self.value)
|
format!("#{}", self.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShowWithRRU for UImm12Scaled {
|
impl PrettyPrint for UImm12Scaled {
|
||||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
format!("#{}", self.value)
|
format!("#{}", self.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShowWithRRU for ImmLogic {
|
impl PrettyPrint for ImmLogic {
|
||||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
format!("#{}", self.value())
|
format!("#{}", self.value())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShowWithRRU for ImmShift {
|
impl PrettyPrint for ImmShift {
|
||||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
format!("#{}", self.imm)
|
format!("#{}", self.imm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShowWithRRU for MoveWideConst {
|
impl PrettyPrint for MoveWideConst {
|
||||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
if self.shift == 0 {
|
if self.shift == 0 {
|
||||||
format!("#{}", self.bits)
|
format!("#{}", self.bits)
|
||||||
|
|||||||
@@ -9,10 +9,11 @@ use crate::ir::types::{
|
|||||||
I32, I32X4, I64, I64X2, I8, I8X16, IFLAGS, R32, R64,
|
I32, I32X4, I64, I64X2, I8, I8X16, IFLAGS, R32, R64,
|
||||||
};
|
};
|
||||||
use crate::ir::{ExternalName, Opcode, SourceLoc, TrapCode, Type};
|
use crate::ir::{ExternalName, Opcode, SourceLoc, TrapCode, Type};
|
||||||
|
use crate::isa::CallConv;
|
||||||
use crate::machinst::*;
|
use crate::machinst::*;
|
||||||
use crate::{settings, CodegenError, CodegenResult};
|
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 regalloc::{RegUsageCollector, RegUsageMapper};
|
||||||
|
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
@@ -392,6 +393,8 @@ pub struct CallInfo {
|
|||||||
pub defs: Vec<Writable<Reg>>,
|
pub defs: Vec<Writable<Reg>>,
|
||||||
pub loc: SourceLoc,
|
pub loc: SourceLoc,
|
||||||
pub opcode: Opcode,
|
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
|
/// 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 defs: Vec<Writable<Reg>>,
|
||||||
pub loc: SourceLoc,
|
pub loc: SourceLoc,
|
||||||
pub opcode: Opcode,
|
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
|
/// 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> {
|
fn is_term<'a>(&'a self) -> MachTerminator<'a> {
|
||||||
match self {
|
match self {
|
||||||
&Inst::Ret | &Inst::EpiloguePlaceholder => MachTerminator::Ret,
|
&Inst::Ret | &Inst::EpiloguePlaceholder => MachTerminator::Ret,
|
||||||
@@ -2623,7 +2646,7 @@ fn mem_finalize_for_show(
|
|||||||
(mem_str, mem)
|
(mem_str, mem)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShowWithRRU for Inst {
|
impl PrettyPrint for Inst {
|
||||||
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
self.pretty_print(mb_rru, &mut EmitState::default())
|
self.pretty_print(mb_rru, &mut EmitState::default())
|
||||||
}
|
}
|
||||||
@@ -2883,13 +2906,13 @@ impl Inst {
|
|||||||
&Inst::StoreP64 { rt, rt2, ref mem } => {
|
&Inst::StoreP64 { rt, rt2, ref mem } => {
|
||||||
let rt = rt.show_rru(mb_rru);
|
let rt = rt.show_rru(mb_rru);
|
||||||
let rt2 = rt2.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)
|
format!("stp {}, {}, {}", rt, rt2, mem)
|
||||||
}
|
}
|
||||||
&Inst::LoadP64 { rt, rt2, ref mem } => {
|
&Inst::LoadP64 { rt, rt2, ref mem } => {
|
||||||
let rt = rt.to_reg().show_rru(mb_rru);
|
let rt = rt.to_reg().show_rru(mb_rru);
|
||||||
let rt2 = rt2.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)
|
format!("ldp {}, {}, {}", rt, rt2, mem)
|
||||||
}
|
}
|
||||||
&Inst::Mov64 { rd, rm } => {
|
&Inst::Mov64 { rd, rm } => {
|
||||||
|
|||||||
@@ -3,10 +3,11 @@
|
|||||||
use crate::isa::aarch64::inst::OperandSize;
|
use crate::isa::aarch64::inst::OperandSize;
|
||||||
use crate::isa::aarch64::inst::ScalarSize;
|
use crate::isa::aarch64::inst::ScalarSize;
|
||||||
use crate::isa::aarch64::inst::VectorSize;
|
use crate::isa::aarch64::inst::VectorSize;
|
||||||
use crate::machinst::*;
|
|
||||||
use crate::settings;
|
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};
|
use std::string::{String, ToString};
|
||||||
|
|
||||||
|
|||||||
@@ -1857,6 +1857,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
|
|
||||||
Opcode::Call | Opcode::CallIndirect => {
|
Opcode::Call | Opcode::CallIndirect => {
|
||||||
let loc = ctx.srcloc(insn);
|
let loc = ctx.srcloc(insn);
|
||||||
|
let caller_conv = ctx.abi().call_conv();
|
||||||
let (mut abi, inputs) = match op {
|
let (mut abi, inputs) = match op {
|
||||||
Opcode::Call => {
|
Opcode::Call => {
|
||||||
let (extname, dist) = ctx.call_target(insn).unwrap();
|
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!(inputs.len() == sig.params.len());
|
||||||
assert!(outputs.len() == sig.returns.len());
|
assert!(outputs.len() == sig.returns.len());
|
||||||
(
|
(
|
||||||
AArch64ABICaller::from_func(sig, &extname, dist, loc)?,
|
AArch64ABICaller::from_func(sig, &extname, dist, loc, caller_conv)?,
|
||||||
&inputs[..],
|
&inputs[..],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1874,7 +1875,10 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
let sig = ctx.call_sig(insn).unwrap();
|
let sig = ctx.call_sig(insn).unwrap();
|
||||||
assert!(inputs.len() - 1 == sig.params.len());
|
assert!(inputs.len() - 1 == sig.params.len());
|
||||||
assert!(outputs.len() == sig.returns.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!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,15 +3,13 @@
|
|||||||
use crate::ir::condcodes::IntCC;
|
use crate::ir::condcodes::IntCC;
|
||||||
use crate::ir::Function;
|
use crate::ir::Function;
|
||||||
use crate::isa::Builder as IsaBuilder;
|
use crate::isa::Builder as IsaBuilder;
|
||||||
use crate::machinst::{
|
use crate::machinst::{compile, MachBackend, MachCompileResult, TargetIsaAdapter, VCode};
|
||||||
compile, MachBackend, MachCompileResult, ShowWithRRU, TargetIsaAdapter, VCode,
|
|
||||||
};
|
|
||||||
use crate::result::CodegenResult;
|
use crate::result::CodegenResult;
|
||||||
use crate::settings;
|
use crate::settings;
|
||||||
|
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
|
|
||||||
use regalloc::RealRegUniverse;
|
use regalloc::{PrettyPrint, RealRegUniverse};
|
||||||
use target_lexicon::{Aarch64Architecture, Architecture, Triple};
|
use target_lexicon::{Aarch64Architecture, Architecture, Triple};
|
||||||
|
|
||||||
// New backend:
|
// New backend:
|
||||||
|
|||||||
@@ -361,6 +361,8 @@ impl ABIMachineSpec for Arm32MachineDeps {
|
|||||||
loc: SourceLoc,
|
loc: SourceLoc,
|
||||||
opcode: ir::Opcode,
|
opcode: ir::Opcode,
|
||||||
tmp: Writable<Reg>,
|
tmp: Writable<Reg>,
|
||||||
|
_callee_conv: isa::CallConv,
|
||||||
|
_caller_conv: isa::CallConv,
|
||||||
) -> SmallVec<[(InstIsSafepoint, Inst); 2]> {
|
) -> SmallVec<[(InstIsSafepoint, Inst); 2]> {
|
||||||
let mut insts = SmallVec::new();
|
let mut insts = SmallVec::new();
|
||||||
match &dest {
|
match &dest {
|
||||||
@@ -431,11 +433,11 @@ impl ABIMachineSpec for Arm32MachineDeps {
|
|||||||
s.nominal_sp_to_fp
|
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();
|
let mut caller_saved = Vec::new();
|
||||||
for i in 0..15 {
|
for i in 0..15 {
|
||||||
let r = writable_rreg(i);
|
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);
|
caller_saved.push(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -461,7 +463,7 @@ fn get_callee_saves(regs: &Set<Writable<RealReg>>) -> Vec<Writable<RealReg>> {
|
|||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_caller_save(r: RealReg) -> bool {
|
fn is_reg_clobbered_by_call(r: RealReg) -> bool {
|
||||||
let enc = r.get_hw_encoding();
|
let enc = r.get_hw_encoding();
|
||||||
enc <= 3
|
enc <= 3
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use crate::isa::arm32::inst::*;
|
use crate::isa::arm32::inst::*;
|
||||||
|
|
||||||
use regalloc::{RealRegUniverse, Reg};
|
use regalloc::{PrettyPrint, RealRegUniverse, Reg};
|
||||||
|
|
||||||
use std::string::String;
|
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 {
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
let op = match self.op() {
|
let op = match self.op() {
|
||||||
ShiftOp::LSL => "lsl",
|
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 {
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
format!("#{}", self.value)
|
format!("#{}", self.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShowWithRRU for UImm12 {
|
impl PrettyPrint for UImm12 {
|
||||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
format!("#{}", self.value)
|
format!("#{}", self.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShowWithRRU for AMode {
|
impl PrettyPrint for AMode {
|
||||||
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
match self {
|
match self {
|
||||||
&AMode::RegReg(rn, rm, imm2) => {
|
&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 {
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
let mut s = format!("{:?}", self);
|
let mut s = format!("{:?}", self);
|
||||||
s.make_ascii_lowercase();
|
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 {
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
match self {
|
match self {
|
||||||
&BranchTarget::Label(label) => format!("label{:?}", label.get()),
|
&BranchTarget::Label(label) => format!("label{:?}", label.get()),
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use crate::ir::{ExternalName, Opcode, SourceLoc, TrapCode, Type};
|
|||||||
use crate::machinst::*;
|
use crate::machinst::*;
|
||||||
use crate::{settings, CodegenError, CodegenResult};
|
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 regalloc::{RegUsageCollector, RegUsageMapper};
|
||||||
|
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
@@ -897,7 +897,7 @@ fn mem_finalize_for_show(
|
|||||||
(mem_str, mem)
|
(mem_str, mem)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShowWithRRU for Inst {
|
impl PrettyPrint for Inst {
|
||||||
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
self.pretty_print(mb_rru, &mut EmitState::default())
|
self.pretty_print(mb_rru, &mut EmitState::default())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -513,6 +513,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
}
|
}
|
||||||
Opcode::Call | Opcode::CallIndirect => {
|
Opcode::Call | Opcode::CallIndirect => {
|
||||||
let loc = ctx.srcloc(insn);
|
let loc = ctx.srcloc(insn);
|
||||||
|
let caller_conv = ctx.abi().call_conv();
|
||||||
let (mut abi, inputs) = match op {
|
let (mut abi, inputs) = match op {
|
||||||
Opcode::Call => {
|
Opcode::Call => {
|
||||||
let (extname, dist) = ctx.call_target(insn).unwrap();
|
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!(inputs.len(), sig.params.len());
|
||||||
assert_eq!(outputs.len(), sig.returns.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[..],
|
&inputs[..],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -530,7 +531,10 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
let sig = ctx.call_sig(insn).unwrap();
|
let sig = ctx.call_sig(insn).unwrap();
|
||||||
assert_eq!(inputs.len() - 1, sig.params.len());
|
assert_eq!(inputs.len() - 1, sig.params.len());
|
||||||
assert_eq!(outputs.len(), sig.returns.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!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,14 +3,12 @@
|
|||||||
use crate::ir::condcodes::IntCC;
|
use crate::ir::condcodes::IntCC;
|
||||||
use crate::ir::Function;
|
use crate::ir::Function;
|
||||||
use crate::isa::Builder as IsaBuilder;
|
use crate::isa::Builder as IsaBuilder;
|
||||||
use crate::machinst::{
|
use crate::machinst::{compile, MachBackend, MachCompileResult, TargetIsaAdapter, VCode};
|
||||||
compile, MachBackend, MachCompileResult, ShowWithRRU, TargetIsaAdapter, VCode,
|
|
||||||
};
|
|
||||||
use crate::result::CodegenResult;
|
use crate::result::CodegenResult;
|
||||||
use crate::settings;
|
use crate::settings;
|
||||||
|
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use regalloc::RealRegUniverse;
|
use regalloc::{PrettyPrint, RealRegUniverse};
|
||||||
use target_lexicon::{Architecture, ArmArchitecture, Triple};
|
use target_lexicon::{Architecture, ArmArchitecture, Triple};
|
||||||
|
|
||||||
// New backend:
|
// New backend:
|
||||||
|
|||||||
@@ -493,6 +493,8 @@ impl ABIMachineSpec for X64ABIMachineSpec {
|
|||||||
loc: SourceLoc,
|
loc: SourceLoc,
|
||||||
opcode: ir::Opcode,
|
opcode: ir::Opcode,
|
||||||
tmp: Writable<Reg>,
|
tmp: Writable<Reg>,
|
||||||
|
_callee_conv: isa::CallConv,
|
||||||
|
_caller_conv: isa::CallConv,
|
||||||
) -> SmallVec<[(InstIsSafepoint, Self::I); 2]> {
|
) -> SmallVec<[(InstIsSafepoint, Self::I); 2]> {
|
||||||
let mut insts = SmallVec::new();
|
let mut insts = SmallVec::new();
|
||||||
match dest {
|
match dest {
|
||||||
@@ -545,7 +547,7 @@ impl ABIMachineSpec for X64ABIMachineSpec {
|
|||||||
s.nominal_sp_to_fp
|
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![
|
let mut caller_saved = vec![
|
||||||
// Systemv calling convention:
|
// Systemv calling convention:
|
||||||
// - GPR: all except RBX, RBP, R12 to R15 (which are callee-saved).
|
// - 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()),
|
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::r12()));
|
||||||
caller_saved.push(Writable::from_reg(regs::r13()));
|
caller_saved.push(Writable::from_reg(regs::r13()));
|
||||||
// Not r14; implicitly preserved in the entry.
|
// Not r14; implicitly preserved in the entry.
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ use super::EmitState;
|
|||||||
use crate::ir::condcodes::{FloatCC, IntCC};
|
use crate::ir::condcodes::{FloatCC, IntCC};
|
||||||
use crate::machinst::*;
|
use crate::machinst::*;
|
||||||
use core::fmt::Debug;
|
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::fmt;
|
||||||
use std::string::{String, ToString};
|
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 {
|
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
match self {
|
match self {
|
||||||
Amode::ImmReg { simm32, base } => {
|
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 {
|
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
match self {
|
match self {
|
||||||
SyntheticAmode::Real(addr) => addr.show_rru(mb_rru),
|
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 {
|
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
self.show_rru_sized(mb_rru, 8)
|
self.show_rru_sized(mb_rru, 8)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrettyPrintSized for RegMemImm {
|
||||||
fn show_rru_sized(&self, mb_rru: Option<&RealRegUniverse>, size: u8) -> String {
|
fn show_rru_sized(&self, mb_rru: Option<&RealRegUniverse>, size: u8) -> String {
|
||||||
match self {
|
match self {
|
||||||
Self::Reg { reg } => show_ireg_sized(*reg, mb_rru, size),
|
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 {
|
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
self.show_rru_sized(mb_rru, 8)
|
self.show_rru_sized(mb_rru, 8)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrettyPrintSized for RegMem {
|
||||||
fn show_rru_sized(&self, mb_rru: Option<&RealRegUniverse>, size: u8) -> String {
|
fn show_rru_sized(&self, mb_rru: Option<&RealRegUniverse>, size: u8) -> String {
|
||||||
match self {
|
match self {
|
||||||
RegMem::Reg { reg } => show_ireg_sized(*reg, mb_rru, size),
|
RegMem::Reg { reg } => show_ireg_sized(*reg, mb_rru, size),
|
||||||
@@ -1098,7 +1105,7 @@ pub enum BranchTarget {
|
|||||||
ResolvedOffset(isize),
|
ResolvedOffset(isize),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShowWithRRU for BranchTarget {
|
impl PrettyPrint for BranchTarget {
|
||||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
match self {
|
match self {
|
||||||
BranchTarget::Label(l) => format!("{:?}", l),
|
BranchTarget::Label(l) => format!("{:?}", l),
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ use crate::{settings, settings::Flags, CodegenError, CodegenResult};
|
|||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use regalloc::{
|
use regalloc::{
|
||||||
RealRegUniverse, Reg, RegClass, RegUsageCollector, RegUsageMapper, SpillSlot, VirtualReg,
|
PrettyPrint, PrettyPrintSized, RealRegUniverse, Reg, RegClass, RegUsageCollector,
|
||||||
Writable,
|
RegUsageMapper, SpillSlot, VirtualReg, Writable,
|
||||||
};
|
};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@@ -1165,7 +1165,7 @@ impl Inst {
|
|||||||
//=============================================================================
|
//=============================================================================
|
||||||
// Instructions: printing
|
// Instructions: printing
|
||||||
|
|
||||||
impl ShowWithRRU for Inst {
|
impl PrettyPrint for Inst {
|
||||||
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
fn ljustify(s: String) -> String {
|
fn ljustify(s: String) -> String {
|
||||||
let w = 7;
|
let w = 7;
|
||||||
|
|||||||
@@ -10,9 +10,11 @@
|
|||||||
//! Also, they will have to be ABI dependent. Need to find a way to avoid constructing a universe
|
//! Also, they will have to be ABI dependent. Need to find a way to avoid constructing a universe
|
||||||
//! for each function we compile.
|
//! for each function we compile.
|
||||||
|
|
||||||
use crate::{machinst::pretty_print::ShowWithRRU, settings};
|
use crate::settings;
|
||||||
use alloc::vec::Vec;
|
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;
|
use std::string::String;
|
||||||
|
|
||||||
// Hardware encodings for a few registers.
|
// Hardware encodings for a few registers.
|
||||||
|
|||||||
@@ -384,9 +384,10 @@ fn emit_vm_call<C: LowerCtx<I = Inst>>(
|
|||||||
// TODO avoid recreating signatures for every single Libcall function.
|
// TODO avoid recreating signatures for every single Libcall function.
|
||||||
let call_conv = CallConv::for_libcall(flags, CallConv::triple_default(triple));
|
let call_conv = CallConv::for_libcall(flags, CallConv::triple_default(triple));
|
||||||
let sig = make_libcall_sig(ctx, insn, call_conv, types::I64);
|
let sig = make_libcall_sig(ctx, insn, call_conv, types::I64);
|
||||||
|
let caller_conv = ctx.abi().call_conv();
|
||||||
|
|
||||||
let loc = ctx.srcloc(insn);
|
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);
|
abi.emit_stack_pre_adjust(ctx);
|
||||||
|
|
||||||
@@ -1558,6 +1559,7 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
|
|
||||||
Opcode::Call | Opcode::CallIndirect => {
|
Opcode::Call | Opcode::CallIndirect => {
|
||||||
let loc = ctx.srcloc(insn);
|
let loc = ctx.srcloc(insn);
|
||||||
|
let caller_conv = ctx.abi().call_conv();
|
||||||
let (mut abi, inputs) = match op {
|
let (mut abi, inputs) = match op {
|
||||||
Opcode::Call => {
|
Opcode::Call => {
|
||||||
let (extname, dist) = ctx.call_target(insn).unwrap();
|
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!(inputs.len(), sig.params.len());
|
||||||
assert_eq!(outputs.len(), sig.returns.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[..],
|
&inputs[..],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1575,7 +1577,10 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
let sig = ctx.call_sig(insn).unwrap();
|
let sig = ctx.call_sig(insn).unwrap();
|
||||||
assert_eq!(inputs.len() - 1, sig.params.len());
|
assert_eq!(inputs.len() - 1, sig.params.len());
|
||||||
assert_eq!(outputs.len(), sig.returns.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!(),
|
_ => unreachable!(),
|
||||||
|
|||||||
@@ -4,13 +4,11 @@ use super::TargetIsa;
|
|||||||
use crate::ir::{condcodes::IntCC, Function};
|
use crate::ir::{condcodes::IntCC, Function};
|
||||||
use crate::isa::x64::{inst::regs::create_reg_universe_systemv, settings as x64_settings};
|
use crate::isa::x64::{inst::regs::create_reg_universe_systemv, settings as x64_settings};
|
||||||
use crate::isa::Builder as IsaBuilder;
|
use crate::isa::Builder as IsaBuilder;
|
||||||
use crate::machinst::{
|
use crate::machinst::{compile, MachBackend, MachCompileResult, TargetIsaAdapter, VCode};
|
||||||
compile, pretty_print::ShowWithRRU, MachBackend, MachCompileResult, TargetIsaAdapter, VCode,
|
|
||||||
};
|
|
||||||
use crate::result::CodegenResult;
|
use crate::result::CodegenResult;
|
||||||
use crate::settings::{self as shared_settings, Flags};
|
use crate::settings::{self as shared_settings, Flags};
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use regalloc::RealRegUniverse;
|
use regalloc::{PrettyPrint, RealRegUniverse};
|
||||||
use target_lexicon::Triple;
|
use target_lexicon::Triple;
|
||||||
|
|
||||||
mod abi;
|
mod abi;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use crate::binemit::StackMap;
|
use crate::binemit::StackMap;
|
||||||
use crate::ir::StackSlot;
|
use crate::ir::StackSlot;
|
||||||
|
use crate::isa::CallConv;
|
||||||
use crate::machinst::*;
|
use crate::machinst::*;
|
||||||
use crate::settings;
|
use crate::settings;
|
||||||
|
|
||||||
@@ -25,6 +26,9 @@ pub trait ABICallee {
|
|||||||
/// Get the settings controlling this function's compilation.
|
/// Get the settings controlling this function's compilation.
|
||||||
fn flags(&self) -> &settings::Flags;
|
fn flags(&self) -> &settings::Flags;
|
||||||
|
|
||||||
|
/// Get the calling convention implemented by this ABI object.
|
||||||
|
fn call_conv(&self) -> CallConv;
|
||||||
|
|
||||||
/// Get the liveins of the function.
|
/// Get the liveins of the function.
|
||||||
fn liveins(&self) -> Set<RealReg>;
|
fn liveins(&self) -> Set<RealReg>;
|
||||||
|
|
||||||
|
|||||||
@@ -347,6 +347,8 @@ pub trait ABIMachineSpec {
|
|||||||
loc: SourceLoc,
|
loc: SourceLoc,
|
||||||
opcode: ir::Opcode,
|
opcode: ir::Opcode,
|
||||||
tmp: Writable<Reg>,
|
tmp: Writable<Reg>,
|
||||||
|
callee_conv: isa::CallConv,
|
||||||
|
callee_conv: isa::CallConv,
|
||||||
) -> SmallVec<[(InstIsSafepoint, Self::I); 2]>;
|
) -> SmallVec<[(InstIsSafepoint, Self::I); 2]>;
|
||||||
|
|
||||||
/// Get the number of spillslots required for the given register-class and
|
/// Get the number of spillslots required for the given register-class and
|
||||||
@@ -359,8 +361,9 @@ pub trait ABIMachineSpec {
|
|||||||
/// Get the "nominal SP to FP" offset from an instruction-emission state.
|
/// Get the "nominal SP to FP" offset from an instruction-emission state.
|
||||||
fn get_nominal_sp_to_fp(s: &<Self::I as MachInstEmit>::State) -> i64;
|
fn get_nominal_sp_to_fp(s: &<Self::I as MachInstEmit>::State) -> i64;
|
||||||
|
|
||||||
/// Get all caller-save registers.
|
/// Get all caller-save registers, that is, registers that we expect
|
||||||
fn get_caller_saves(call_conv: isa::CallConv) -> Vec<Writable<Reg>>;
|
/// not to be saved across a call to a callee with the given ABI.
|
||||||
|
fn get_regs_clobbered_by_call(call_conv_of_callee: isa::CallConv) -> Vec<Writable<Reg>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ABI information shared between body (callee) and caller.
|
/// ABI information shared between body (callee) and caller.
|
||||||
@@ -682,6 +685,10 @@ impl<M: ABIMachineSpec> ABICallee for ABICalleeImpl<M> {
|
|||||||
&self.flags
|
&self.flags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn call_conv(&self) -> isa::CallConv {
|
||||||
|
self.sig.call_conv
|
||||||
|
}
|
||||||
|
|
||||||
fn liveins(&self) -> Set<RealReg> {
|
fn liveins(&self) -> Set<RealReg> {
|
||||||
let mut set: Set<RealReg> = Set::empty();
|
let mut set: Set<RealReg> = Set::empty();
|
||||||
for &arg in &self.sig.args {
|
for &arg in &self.sig.args {
|
||||||
@@ -1040,7 +1047,7 @@ fn abisig_to_uses_and_defs<M: ABIMachineSpec>(sig: &ABISig) -> (Vec<Reg>, Vec<Wr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compute defs: all retval regs, and all caller-save (clobbered) regs.
|
// Compute defs: all retval regs, and all caller-save (clobbered) regs.
|
||||||
let mut defs = M::get_caller_saves(sig.call_conv);
|
let mut defs = M::get_regs_clobbered_by_call(sig.call_conv);
|
||||||
for ret in &sig.rets {
|
for ret in &sig.rets {
|
||||||
match ret {
|
match ret {
|
||||||
&ABIArg::Reg(reg, ..) => defs.push(Writable::from_reg(reg.to_reg())),
|
&ABIArg::Reg(reg, ..) => defs.push(Writable::from_reg(reg.to_reg())),
|
||||||
@@ -1063,8 +1070,10 @@ pub struct ABICallerImpl<M: ABIMachineSpec> {
|
|||||||
dest: CallDest,
|
dest: CallDest,
|
||||||
/// Location of callsite.
|
/// Location of callsite.
|
||||||
loc: ir::SourceLoc,
|
loc: ir::SourceLoc,
|
||||||
/// Actuall call opcode; used to distinguish various types of calls.
|
/// Actual call opcode; used to distinguish various types of calls.
|
||||||
opcode: ir::Opcode,
|
opcode: ir::Opcode,
|
||||||
|
/// Caller's calling convention.
|
||||||
|
caller_conv: isa::CallConv,
|
||||||
|
|
||||||
_mach: PhantomData<M>,
|
_mach: PhantomData<M>,
|
||||||
}
|
}
|
||||||
@@ -1085,6 +1094,7 @@ impl<M: ABIMachineSpec> ABICallerImpl<M> {
|
|||||||
extname: &ir::ExternalName,
|
extname: &ir::ExternalName,
|
||||||
dist: RelocDistance,
|
dist: RelocDistance,
|
||||||
loc: ir::SourceLoc,
|
loc: ir::SourceLoc,
|
||||||
|
caller_conv: isa::CallConv,
|
||||||
) -> CodegenResult<ABICallerImpl<M>> {
|
) -> CodegenResult<ABICallerImpl<M>> {
|
||||||
let sig = ABISig::from_func_sig::<M>(sig)?;
|
let sig = ABISig::from_func_sig::<M>(sig)?;
|
||||||
let (uses, defs) = abisig_to_uses_and_defs::<M>(&sig);
|
let (uses, defs) = abisig_to_uses_and_defs::<M>(&sig);
|
||||||
@@ -1095,6 +1105,7 @@ impl<M: ABIMachineSpec> ABICallerImpl<M> {
|
|||||||
dest: CallDest::ExtName(extname.clone(), dist),
|
dest: CallDest::ExtName(extname.clone(), dist),
|
||||||
loc,
|
loc,
|
||||||
opcode: ir::Opcode::Call,
|
opcode: ir::Opcode::Call,
|
||||||
|
caller_conv,
|
||||||
_mach: PhantomData,
|
_mach: PhantomData,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1106,6 +1117,7 @@ impl<M: ABIMachineSpec> ABICallerImpl<M> {
|
|||||||
ptr: Reg,
|
ptr: Reg,
|
||||||
loc: ir::SourceLoc,
|
loc: ir::SourceLoc,
|
||||||
opcode: ir::Opcode,
|
opcode: ir::Opcode,
|
||||||
|
caller_conv: isa::CallConv,
|
||||||
) -> CodegenResult<ABICallerImpl<M>> {
|
) -> CodegenResult<ABICallerImpl<M>> {
|
||||||
let sig = ABISig::from_func_sig::<M>(sig)?;
|
let sig = ABISig::from_func_sig::<M>(sig)?;
|
||||||
let (uses, defs) = abisig_to_uses_and_defs::<M>(&sig);
|
let (uses, defs) = abisig_to_uses_and_defs::<M>(&sig);
|
||||||
@@ -1116,6 +1128,7 @@ impl<M: ABIMachineSpec> ABICallerImpl<M> {
|
|||||||
dest: CallDest::Reg(ptr),
|
dest: CallDest::Reg(ptr),
|
||||||
loc,
|
loc,
|
||||||
opcode,
|
opcode,
|
||||||
|
caller_conv,
|
||||||
_mach: PhantomData,
|
_mach: PhantomData,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1255,8 +1268,17 @@ impl<M: ABIMachineSpec> ABICaller for ABICallerImpl<M> {
|
|||||||
self.emit_copy_reg_to_arg(ctx, i, rd.to_reg());
|
self.emit_copy_reg_to_arg(ctx, i, rd.to_reg());
|
||||||
}
|
}
|
||||||
let tmp = ctx.alloc_tmp(word_rc, word_type);
|
let tmp = ctx.alloc_tmp(word_rc, word_type);
|
||||||
for (is_safepoint, inst) in
|
for (is_safepoint, inst) in M::gen_call(
|
||||||
M::gen_call(&self.dest, uses, defs, self.loc, self.opcode, tmp).into_iter()
|
&self.dest,
|
||||||
|
uses,
|
||||||
|
defs,
|
||||||
|
self.loc,
|
||||||
|
self.opcode,
|
||||||
|
tmp,
|
||||||
|
self.sig.call_conv,
|
||||||
|
self.caller_conv,
|
||||||
|
)
|
||||||
|
.into_iter()
|
||||||
{
|
{
|
||||||
match is_safepoint {
|
match is_safepoint {
|
||||||
InstIsSafepoint::Yes => ctx.emit_safepoint(inst),
|
InstIsSafepoint::Yes => ctx.emit_safepoint(inst),
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use crate::settings;
|
|||||||
use crate::timing;
|
use crate::timing;
|
||||||
|
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use regalloc::{allocate_registers_with_opts, Algorithm, Options};
|
use regalloc::{allocate_registers_with_opts, Algorithm, Options, PrettyPrint};
|
||||||
|
|
||||||
/// Compile the given function down to VCode with allocated registers, ready
|
/// Compile the given function down to VCode with allocated registers, ready
|
||||||
/// for binary emission.
|
/// for binary emission.
|
||||||
@@ -16,7 +16,7 @@ pub fn compile<B: LowerBackend + MachBackend>(
|
|||||||
abi: Box<dyn ABICallee<I = B::MInst>>,
|
abi: Box<dyn ABICallee<I = B::MInst>>,
|
||||||
) -> CodegenResult<VCode<B::MInst>>
|
) -> CodegenResult<VCode<B::MInst>>
|
||||||
where
|
where
|
||||||
B::MInst: ShowWithRRU,
|
B::MInst: PrettyPrint,
|
||||||
{
|
{
|
||||||
// Compute lowered block order.
|
// Compute lowered block order.
|
||||||
let block_order = BlockLoweringOrder::new(f);
|
let block_order = BlockLoweringOrder::new(f);
|
||||||
|
|||||||
@@ -125,8 +125,6 @@ pub mod abi;
|
|||||||
pub use abi::*;
|
pub use abi::*;
|
||||||
pub mod abi_impl;
|
pub mod abi_impl;
|
||||||
pub use abi_impl::*;
|
pub use abi_impl::*;
|
||||||
pub mod pretty_print;
|
|
||||||
pub use pretty_print::*;
|
|
||||||
pub mod buffer;
|
pub mod buffer;
|
||||||
pub use buffer::*;
|
pub use buffer::*;
|
||||||
pub mod adapter;
|
pub mod adapter;
|
||||||
@@ -156,6 +154,11 @@ pub trait MachInst: Clone + Debug {
|
|||||||
/// Returns true if the instruction is an epilogue placeholder.
|
/// Returns true if the instruction is an epilogue placeholder.
|
||||||
fn is_epilogue_placeholder(&self) -> bool;
|
fn is_epilogue_placeholder(&self) -> bool;
|
||||||
|
|
||||||
|
/// Should this instruction be included in the clobber-set?
|
||||||
|
fn is_included_in_clobbers(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
/// Generate a move.
|
/// Generate a move.
|
||||||
fn gen_move(to_reg: Writable<Reg>, from_reg: Reg, ty: Type) -> Self;
|
fn gen_move(to_reg: Writable<Reg>, from_reg: Reg, ty: Type) -> Self;
|
||||||
|
|
||||||
|
|||||||
@@ -1,66 +0,0 @@
|
|||||||
//! Pretty-printing for machine code (virtual-registerized or final).
|
|
||||||
|
|
||||||
use regalloc::{RealRegUniverse, Reg, Writable};
|
|
||||||
|
|
||||||
use std::fmt::Debug;
|
|
||||||
use std::hash::Hash;
|
|
||||||
use std::string::{String, ToString};
|
|
||||||
|
|
||||||
// FIXME: Should this go into regalloc.rs instead?
|
|
||||||
|
|
||||||
/// A trait for printing instruction bits and pieces, with the the ability to
|
|
||||||
/// take a contextualising RealRegUniverse that is used to give proper names to
|
|
||||||
/// registers.
|
|
||||||
pub trait ShowWithRRU {
|
|
||||||
/// Return a string that shows the implementing object in context of the
|
|
||||||
/// given `RealRegUniverse`, if provided.
|
|
||||||
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String;
|
|
||||||
|
|
||||||
/// The same as |show_rru|, but with an optional hint giving a size in
|
|
||||||
/// bytes. Its interpretation is object-dependent, and it is intended to
|
|
||||||
/// pass around enough information to facilitate printing sub-parts of
|
|
||||||
/// real registers correctly. Objects may ignore size hints that are
|
|
||||||
/// irrelevant to them.
|
|
||||||
fn show_rru_sized(&self, mb_rru: Option<&RealRegUniverse>, _size: u8) -> String {
|
|
||||||
// Default implementation is to ignore the hint.
|
|
||||||
self.show_rru(mb_rru)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ShowWithRRU for Reg {
|
|
||||||
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
|
||||||
if self.is_real() {
|
|
||||||
if let Some(rru) = mb_rru {
|
|
||||||
let reg_ix = self.get_index();
|
|
||||||
if reg_ix < rru.regs.len() {
|
|
||||||
return rru.regs[reg_ix].1.to_string();
|
|
||||||
} else {
|
|
||||||
// We have a real reg which isn't listed in the universe.
|
|
||||||
// Per the regalloc.rs interface requirements, this is
|
|
||||||
// Totally Not Allowed. Print it generically anyway, so
|
|
||||||
// we have something to debug.
|
|
||||||
return format!("!!{:?}!!", self);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// The reg is virtual, or we have no universe. Be generic.
|
|
||||||
format!("%{:?}", self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn show_rru_sized(&self, _mb_rru: Option<&RealRegUniverse>, _size: u8) -> String {
|
|
||||||
// For the specific case of Reg, we demand not to have a size hint,
|
|
||||||
// since interpretation of the size is target specific, but this code
|
|
||||||
// is used by all targets.
|
|
||||||
panic!("Reg::show_rru_sized: impossible to implement");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<R: ShowWithRRU + Copy + Ord + Hash + Eq + Debug> ShowWithRRU for Writable<R> {
|
|
||||||
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
|
||||||
self.to_reg().show_rru(mb_rru)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn show_rru_sized(&self, mb_rru: Option<&RealRegUniverse>, size: u8) -> String {
|
|
||||||
self.to_reg().show_rru_sized(mb_rru, size)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -25,8 +25,8 @@ use crate::timing;
|
|||||||
use regalloc::Function as RegallocFunction;
|
use regalloc::Function as RegallocFunction;
|
||||||
use regalloc::Set as RegallocSet;
|
use regalloc::Set as RegallocSet;
|
||||||
use regalloc::{
|
use regalloc::{
|
||||||
BlockIx, InstIx, Range, RegAllocResult, RegClass, RegUsageCollector, RegUsageMapper, SpillSlot,
|
BlockIx, InstIx, PrettyPrint, Range, RegAllocResult, RegClass, RegUsageCollector,
|
||||||
StackmapRequestInfo,
|
RegUsageMapper, SpillSlot, StackmapRequestInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
@@ -543,6 +543,10 @@ impl<I: VCodeInst> RegallocFunction for VCode<I> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_included_in_clobbers(&self, insn: &I) -> bool {
|
||||||
|
insn.is_included_in_clobbers()
|
||||||
|
}
|
||||||
|
|
||||||
fn get_regs(insn: &I, collector: &mut RegUsageCollector) {
|
fn get_regs(insn: &I, collector: &mut RegUsageCollector) {
|
||||||
insn.get_regs(collector)
|
insn.get_regs(collector)
|
||||||
}
|
}
|
||||||
@@ -624,7 +628,7 @@ impl<I: VCodeInst> fmt::Debug for VCode<I> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Pretty-printing with `RealRegUniverse` context.
|
/// Pretty-printing with `RealRegUniverse` context.
|
||||||
impl<I: VCodeInst> ShowWithRRU for VCode<I> {
|
impl<I: VCodeInst> PrettyPrint for VCode<I> {
|
||||||
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
|
|||||||
@@ -151,34 +151,27 @@ block0:
|
|||||||
|
|
||||||
; check: stp fp, lr, [sp, #-16]!
|
; check: stp fp, lr, [sp, #-16]!
|
||||||
; nextln: mov fp, sp
|
; nextln: mov fp, sp
|
||||||
; nextln: sub sp, sp, #48
|
; nextln: sub sp, sp, #32
|
||||||
; nextln: str q8, [sp]
|
|
||||||
; nextln: str q9, [sp, #16]
|
|
||||||
; nextln: str q10, [sp, #32]
|
|
||||||
; nextln: virtual_sp_offset_adjust 48
|
|
||||||
; nextln: ldr x0, 8 ; b 12 ; data
|
; nextln: ldr x0, 8 ; b 12 ; data
|
||||||
; nextln: blr x0
|
; nextln: blr x0
|
||||||
; nextln: mov v8.16b, v0.16b
|
; nextln: str s0, [sp]
|
||||||
; nextln: ldr x0, 8 ; b 12 ; data
|
; nextln: ldr x0, 8 ; b 12 ; data
|
||||||
; nextln: blr x0
|
; nextln: blr x0
|
||||||
; nextln: mov v9.16b, v0.16b
|
; nextln: str d0, [sp, #8]
|
||||||
; nextln: ldr x0, 8 ; b 12 ; data
|
; nextln: ldr x0, 8 ; b 12 ; data
|
||||||
; nextln: blr x0
|
; nextln: blr x0
|
||||||
; nextln: mov v10.16b, v0.16b
|
; nextln: str d0, [sp, #16]
|
||||||
; nextln: ldr x0, 8 ; b 12 ; data
|
; nextln: ldr x0, 8 ; b 12 ; data
|
||||||
; nextln: blr x0
|
; nextln: blr x0
|
||||||
; nextln: mov v0.16b, v8.16b
|
; nextln: ldr s0, [sp]
|
||||||
; nextln: ldr x0, 8 ; b 12 ; data
|
; nextln: ldr x0, 8 ; b 12 ; data
|
||||||
; nextln: blr x0
|
; nextln: blr x0
|
||||||
; nextln: mov v0.16b, v9.16b
|
; nextln: ldr d0, [sp, #8]
|
||||||
; nextln: ldr x0, 8 ; b 12 ; data
|
; nextln: ldr x0, 8 ; b 12 ; data
|
||||||
; nextln: blr x0
|
; nextln: blr x0
|
||||||
; nextln: mov v0.16b, v10.16b
|
; nextln: ldr d0, [sp, #16]
|
||||||
; nextln: ldr x0, 8 ; b 12 ; data
|
; nextln: ldr x0, 8 ; b 12 ; data
|
||||||
; nextln: blr x0
|
; nextln: blr x0
|
||||||
; nextln: ldr q8, [sp]
|
|
||||||
; nextln: ldr q9, [sp, #16]
|
|
||||||
; nextln: ldr q10, [sp, #32]
|
|
||||||
; nextln: mov sp, fp
|
; nextln: mov sp, fp
|
||||||
; nextln: ldp fp, lr, [sp], #16
|
; nextln: ldp fp, lr, [sp], #16
|
||||||
; nextln: ret
|
; nextln: ret
|
||||||
@@ -202,33 +195,26 @@ block0:
|
|||||||
; check: stp fp, lr, [sp, #-16]!
|
; check: stp fp, lr, [sp, #-16]!
|
||||||
; nextln: mov fp, sp
|
; nextln: mov fp, sp
|
||||||
; nextln: sub sp, sp, #48
|
; nextln: sub sp, sp, #48
|
||||||
; nextln: str q8, [sp]
|
|
||||||
; nextln: str q9, [sp, #16]
|
|
||||||
; nextln: str q10, [sp, #32]
|
|
||||||
; nextln: virtual_sp_offset_adjust 48
|
|
||||||
; nextln: ldr x0, 8 ; b 12 ; data
|
; nextln: ldr x0, 8 ; b 12 ; data
|
||||||
; nextln: blr x0
|
; nextln: blr x0
|
||||||
; nextln: mov v8.16b, v0.16b
|
; nextln: str q0, [sp]
|
||||||
; nextln: ldr x0, 8 ; b 12 ; data
|
; nextln: ldr x0, 8 ; b 12 ; data
|
||||||
; nextln: blr x0
|
; nextln: blr x0
|
||||||
; nextln: mov v9.16b, v0.16b
|
; nextln: str q0, [sp, #16]
|
||||||
; nextln: ldr x0, 8 ; b 12 ; data
|
; nextln: ldr x0, 8 ; b 12 ; data
|
||||||
; nextln: blr x0
|
; nextln: blr x0
|
||||||
; nextln: mov v10.16b, v0.16b
|
; nextln: str q0, [sp, #32]
|
||||||
; nextln: ldr x0, 8 ; b 12 ; data
|
; nextln: ldr x0, 8 ; b 12 ; data
|
||||||
; nextln: blr x0
|
; nextln: blr x0
|
||||||
; nextln: mov v0.16b, v8.16b
|
; nextln: ldr q0, [sp]
|
||||||
; nextln: ldr x0, 8 ; b 12 ; data
|
; nextln: ldr x0, 8 ; b 12 ; data
|
||||||
; nextln: blr x0
|
; nextln: blr x0
|
||||||
; nextln: mov v0.16b, v9.16b
|
; nextln: ldr q0, [sp, #16]
|
||||||
; nextln: ldr x0, 8 ; b 12 ; data
|
; nextln: ldr x0, 8 ; b 12 ; data
|
||||||
; nextln: blr x0
|
; nextln: blr x0
|
||||||
; nextln: mov v0.16b, v10.16b
|
; nextln: ldr q0, [sp, #32]
|
||||||
; nextln: ldr x0, 8 ; b 12 ; data
|
; nextln: ldr x0, 8 ; b 12 ; data
|
||||||
; nextln: blr x0
|
; nextln: blr x0
|
||||||
; nextln: ldr q8, [sp]
|
|
||||||
; nextln: ldr q9, [sp, #16]
|
|
||||||
; nextln: ldr q10, [sp, #32]
|
|
||||||
; nextln: mov sp, fp
|
; nextln: mov sp, fp
|
||||||
; nextln: ldp fp, lr, [sp], #16
|
; nextln: ldp fp, lr, [sp], #16
|
||||||
; nextln: ret
|
; nextln: ret
|
||||||
@@ -255,34 +241,27 @@ block0:
|
|||||||
|
|
||||||
; check: stp fp, lr, [sp, #-16]!
|
; check: stp fp, lr, [sp, #-16]!
|
||||||
; nextln: mov fp, sp
|
; nextln: mov fp, sp
|
||||||
; nextln: sub sp, sp, #48
|
; nextln: sub sp, sp, #32
|
||||||
; nextln: str q8, [sp]
|
|
||||||
; nextln: str q9, [sp, #16]
|
|
||||||
; nextln: str q10, [sp, #32]
|
|
||||||
; nextln: virtual_sp_offset_adjust 48
|
|
||||||
; nextln: ldr x0, 8 ; b 12 ; data
|
; nextln: ldr x0, 8 ; b 12 ; data
|
||||||
; nextln: blr x0
|
; nextln: blr x0
|
||||||
; nextln: mov v8.16b, v0.16b
|
; nextln: str s0, [sp]
|
||||||
; nextln: ldr x0, 8 ; b 12 ; data
|
; nextln: ldr x0, 8 ; b 12 ; data
|
||||||
; nextln: blr x0
|
; nextln: blr x0
|
||||||
; nextln: mov v9.16b, v0.16b
|
; nextln: str d0, [sp, #8]
|
||||||
; nextln: ldr x0, 8 ; b 12 ; data
|
; nextln: ldr x0, 8 ; b 12 ; data
|
||||||
; nextln: blr x0
|
; nextln: blr x0
|
||||||
; nextln: mov v10.16b, v0.16b
|
; nextln: str q0, [sp, #16]
|
||||||
; nextln: ldr x0, 8 ; b 12 ; data
|
; nextln: ldr x0, 8 ; b 12 ; data
|
||||||
; nextln: blr x0
|
; nextln: blr x0
|
||||||
; nextln: mov v0.16b, v8.16b
|
; nextln: ldr s0, [sp]
|
||||||
; nextln: ldr x0, 8 ; b 12 ; data
|
; nextln: ldr x0, 8 ; b 12 ; data
|
||||||
; nextln: blr x0
|
; nextln: blr x0
|
||||||
; nextln: mov v0.16b, v9.16b
|
; nextln: ldr d0, [sp, #8]
|
||||||
; nextln: ldr x0, 8 ; b 12 ; data
|
; nextln: ldr x0, 8 ; b 12 ; data
|
||||||
; nextln: blr x0
|
; nextln: blr x0
|
||||||
; nextln: mov v0.16b, v10.16b
|
; nextln: ldr q0, [sp, #16]
|
||||||
; nextln: ldr x0, 8 ; b 12 ; data
|
; nextln: ldr x0, 8 ; b 12 ; data
|
||||||
; nextln: blr x0
|
; nextln: blr x0
|
||||||
; nextln: ldr q8, [sp]
|
|
||||||
; nextln: ldr q9, [sp, #16]
|
|
||||||
; nextln: ldr q10, [sp, #32]
|
|
||||||
; nextln: mov sp, fp
|
; nextln: mov sp, fp
|
||||||
; nextln: ldp fp, lr, [sp], #16
|
; nextln: ldp fp, lr, [sp], #16
|
||||||
; nextln: ret
|
; nextln: ret
|
||||||
|
|||||||
99
cranelift/filetests/filetests/isa/aarch64/prologue.clif
Normal file
99
cranelift/filetests/filetests/isa/aarch64/prologue.clif
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
test compile
|
||||||
|
target aarch64
|
||||||
|
|
||||||
|
function %f(f64) -> f64 {
|
||||||
|
block0(v0: f64):
|
||||||
|
v1 = fadd.f64 v0, v0
|
||||||
|
v2 = fadd.f64 v0, v0
|
||||||
|
v3 = fadd.f64 v0, v0
|
||||||
|
v4 = fadd.f64 v0, v0
|
||||||
|
v5 = fadd.f64 v0, v0
|
||||||
|
v6 = fadd.f64 v0, v0
|
||||||
|
v7 = fadd.f64 v0, v0
|
||||||
|
v8 = fadd.f64 v0, v0
|
||||||
|
v9 = fadd.f64 v0, v0
|
||||||
|
v10 = fadd.f64 v0, v0
|
||||||
|
v11 = fadd.f64 v0, v0
|
||||||
|
v12 = fadd.f64 v0, v0
|
||||||
|
v13 = fadd.f64 v0, v0
|
||||||
|
v14 = fadd.f64 v0, v0
|
||||||
|
v15 = fadd.f64 v0, v0
|
||||||
|
v16 = fadd.f64 v0, v0
|
||||||
|
v17 = fadd.f64 v0, v0
|
||||||
|
v18 = fadd.f64 v0, v0
|
||||||
|
v19 = fadd.f64 v0, v0
|
||||||
|
v20 = fadd.f64 v0, v0
|
||||||
|
v21 = fadd.f64 v0, v0
|
||||||
|
v22 = fadd.f64 v0, v0
|
||||||
|
v23 = fadd.f64 v0, v0
|
||||||
|
v24 = fadd.f64 v0, v0
|
||||||
|
v25 = fadd.f64 v0, v0
|
||||||
|
v26 = fadd.f64 v0, v0
|
||||||
|
v27 = fadd.f64 v0, v0
|
||||||
|
v28 = fadd.f64 v0, v0
|
||||||
|
v29 = fadd.f64 v0, v0
|
||||||
|
v30 = fadd.f64 v0, v0
|
||||||
|
v31 = fadd.f64 v0, v0
|
||||||
|
|
||||||
|
v32 = fadd.f64 v0, v1
|
||||||
|
v33 = fadd.f64 v2, v3
|
||||||
|
v34 = fadd.f64 v4, v5
|
||||||
|
v35 = fadd.f64 v6, v7
|
||||||
|
v36 = fadd.f64 v8, v9
|
||||||
|
v37 = fadd.f64 v10, v11
|
||||||
|
v38 = fadd.f64 v12, v13
|
||||||
|
v39 = fadd.f64 v14, v15
|
||||||
|
v40 = fadd.f64 v16, v17
|
||||||
|
v41 = fadd.f64 v18, v19
|
||||||
|
v42 = fadd.f64 v20, v21
|
||||||
|
v43 = fadd.f64 v22, v23
|
||||||
|
v44 = fadd.f64 v24, v25
|
||||||
|
v45 = fadd.f64 v26, v27
|
||||||
|
v46 = fadd.f64 v28, v29
|
||||||
|
v47 = fadd.f64 v30, v31
|
||||||
|
|
||||||
|
v48 = fadd.f64 v32, v33
|
||||||
|
v49 = fadd.f64 v34, v35
|
||||||
|
v50 = fadd.f64 v36, v37
|
||||||
|
v51 = fadd.f64 v38, v39
|
||||||
|
v52 = fadd.f64 v40, v41
|
||||||
|
v53 = fadd.f64 v42, v43
|
||||||
|
v54 = fadd.f64 v44, v45
|
||||||
|
v55 = fadd.f64 v46, v47
|
||||||
|
|
||||||
|
v56 = fadd.f64 v48, v49
|
||||||
|
v57 = fadd.f64 v50, v51
|
||||||
|
v58 = fadd.f64 v52, v53
|
||||||
|
v59 = fadd.f64 v54, v55
|
||||||
|
|
||||||
|
v60 = fadd.f64 v56, v57
|
||||||
|
v61 = fadd.f64 v58, v59
|
||||||
|
|
||||||
|
v62 = fadd.f64 v60, v61
|
||||||
|
|
||||||
|
return v62
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: stp fp, lr, [sp, #-16]!
|
||||||
|
; nextln: mov fp, sp
|
||||||
|
; nextln: sub sp, sp, #128
|
||||||
|
; nextln: str q8, [sp]
|
||||||
|
; nextln: str q9, [sp, #16]
|
||||||
|
; nextln: str q10, [sp, #32]
|
||||||
|
; nextln: str q11, [sp, #48]
|
||||||
|
; nextln: str q12, [sp, #64]
|
||||||
|
; nextln: str q13, [sp, #80]
|
||||||
|
; nextln: str q14, [sp, #96]
|
||||||
|
; nextln: str q15, [sp, #112]
|
||||||
|
|
||||||
|
; check: ldr q8, [sp]
|
||||||
|
; nextln: ldr q9, [sp, #16]
|
||||||
|
; nextln: ldr q10, [sp, #32]
|
||||||
|
; nextln: ldr q11, [sp, #48]
|
||||||
|
; nextln: ldr q12, [sp, #64]
|
||||||
|
; nextln: ldr q13, [sp, #80]
|
||||||
|
; nextln: ldr q14, [sp, #96]
|
||||||
|
; nextln: ldr q15, [sp, #112]
|
||||||
|
; nextln: mov sp, fp
|
||||||
|
; nextln: ldp fp, lr, [sp], #16
|
||||||
|
; nextln: ret
|
||||||
Reference in New Issue
Block a user