Cranelift: fix use of pinned reg with SysV calling convention. (#4176)
Previously, the pinned register (enabled by the `enable_pinned_reg` Cranelift setting and used via the `get_pinned_reg` and `set_pinned_reg` CLIF ops) was only used when Cranelift was embedded in SpiderMonkey, in order to support a pinned heap register. SpiderMonkey has its own calling convention in Cranelift (named after the integration layer, "Baldrdash"). However, the feature is more general, and should be usable with the default system calling convention too, e.g. SysV or Windows Fastcall. This PR fixes the ABI code to properly treat the pinned register as a globally allocated register -- and hence an implicit input and output to every function, not saved/restored in the prologue/epilogue -- for SysV on x86-64 and aarch64, and Fastcall on x86-64. Fixes #4170.
This commit is contained in:
@@ -397,7 +397,7 @@ impl ABIMachineSpec for X64ABIMachineSpec {
|
||||
|
||||
fn get_stacklimit_reg() -> Reg {
|
||||
debug_assert!(
|
||||
!is_callee_save_systemv(regs::r10().to_real_reg().unwrap())
|
||||
!is_callee_save_systemv(regs::r10().to_real_reg().unwrap(), false)
|
||||
&& !is_callee_save_baldrdash(regs::r10().to_real_reg().unwrap())
|
||||
);
|
||||
|
||||
@@ -577,7 +577,7 @@ impl ABIMachineSpec for X64ABIMachineSpec {
|
||||
) -> SmallVec<[Self::I; 16]> {
|
||||
let mut insts = SmallVec::new();
|
||||
|
||||
let clobbered_callee_saves = Self::get_clobbered_callee_saves(call_conv, clobbers);
|
||||
let clobbered_callee_saves = Self::get_clobbered_callee_saves(call_conv, flags, clobbers);
|
||||
let stack_size = fixed_frame_storage_size + compute_clobber_size(&clobbered_callee_saves);
|
||||
|
||||
// Restore regs by loading from offsets of RSP. RSP will be
|
||||
@@ -788,6 +788,7 @@ impl ABIMachineSpec for X64ABIMachineSpec {
|
||||
|
||||
fn get_clobbered_callee_saves(
|
||||
call_conv: CallConv,
|
||||
flags: &settings::Flags,
|
||||
regs: &[Writable<RealReg>],
|
||||
) -> Vec<Writable<RealReg>> {
|
||||
let mut regs: Vec<Writable<RealReg>> = match call_conv {
|
||||
@@ -802,12 +803,12 @@ impl ABIMachineSpec for X64ABIMachineSpec {
|
||||
CallConv::Fast | CallConv::Cold | CallConv::SystemV | CallConv::WasmtimeSystemV => regs
|
||||
.iter()
|
||||
.cloned()
|
||||
.filter(|r| is_callee_save_systemv(r.to_reg()))
|
||||
.filter(|r| is_callee_save_systemv(r.to_reg(), flags.enable_pinned_reg()))
|
||||
.collect(),
|
||||
CallConv::WindowsFastcall | CallConv::WasmtimeFastcall => regs
|
||||
.iter()
|
||||
.cloned()
|
||||
.filter(|r| is_callee_save_fastcall(r.to_reg()))
|
||||
.filter(|r| is_callee_save_fastcall(r.to_reg(), flags.enable_pinned_reg()))
|
||||
.collect(),
|
||||
CallConv::Probestack => todo!("probestack?"),
|
||||
CallConv::AppleAarch64 | CallConv::WasmtimeAppleAarch64 => unreachable!(),
|
||||
@@ -969,11 +970,15 @@ fn get_fltreg_for_retval(
|
||||
}
|
||||
}
|
||||
|
||||
fn is_callee_save_systemv(r: RealReg) -> bool {
|
||||
fn is_callee_save_systemv(r: RealReg, enable_pinned_reg: bool) -> bool {
|
||||
use regs::*;
|
||||
match r.class() {
|
||||
RegClass::Int => match r.hw_enc() {
|
||||
ENC_RBX | ENC_RBP | ENC_R12 | ENC_R13 | ENC_R14 | ENC_R15 => true,
|
||||
ENC_RBX | ENC_RBP | ENC_R12 | ENC_R13 | ENC_R14 => true,
|
||||
// R15 is the pinned register; if we're using it that way,
|
||||
// it is effectively globally-allocated, and is not
|
||||
// callee-saved.
|
||||
ENC_R15 => !enable_pinned_reg,
|
||||
_ => false,
|
||||
},
|
||||
RegClass::Float => false,
|
||||
@@ -989,18 +994,20 @@ fn is_callee_save_baldrdash(r: RealReg) -> bool {
|
||||
false
|
||||
} else {
|
||||
// Defer to native for the other ones.
|
||||
is_callee_save_systemv(r)
|
||||
is_callee_save_systemv(r, /* enable_pinned_reg = */ true)
|
||||
}
|
||||
}
|
||||
RegClass::Float => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_callee_save_fastcall(r: RealReg) -> bool {
|
||||
fn is_callee_save_fastcall(r: RealReg, enable_pinned_reg: bool) -> bool {
|
||||
use regs::*;
|
||||
match r.class() {
|
||||
RegClass::Int => match r.hw_enc() {
|
||||
ENC_RBX | ENC_RBP | ENC_RSI | ENC_RDI | ENC_R12 | ENC_R13 | ENC_R14 | ENC_R15 => true,
|
||||
ENC_RBX | ENC_RBP | ENC_RSI | ENC_RDI | ENC_R12 | ENC_R13 | ENC_R14 => true,
|
||||
// See above for SysV: we must treat the pinned reg specially.
|
||||
ENC_R15 => !enable_pinned_reg,
|
||||
_ => false,
|
||||
},
|
||||
RegClass::Float => match r.hw_enc() {
|
||||
|
||||
Reference in New Issue
Block a user