mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +01:00
Fix register clobbering on aarch64 GHC when mixing tail/non-tail calls
By default LLVM doesn't save any regs for GHC on arm64. This means we'll clobber LR on arm64 if we make non-tail calls (e.g. L2 syscall) So we should save LR on non-tail calls, and not assume we won't make non-tail calls.
This commit is contained in:
parent
c725f494c9
commit
5521155be5
@ -508,6 +508,9 @@ def CSR_Darwin_AArch64_CXX_TLS_ViaCopy
|
|||||||
def CSR_Darwin_AArch64_RT_MostRegs
|
def CSR_Darwin_AArch64_RT_MostRegs
|
||||||
: CalleeSavedRegs<(add CSR_Darwin_AArch64_AAPCS, (sequence "X%u", 9, 15))>;
|
: CalleeSavedRegs<(add CSR_Darwin_AArch64_AAPCS, (sequence "X%u", 9, 15))>;
|
||||||
|
|
||||||
|
def CSR_AArch64_NoRegs_LR
|
||||||
|
: CalleeSavedRegs<(add CSR_AArch64_NoRegs, LR)>;
|
||||||
|
|
||||||
// Variants of the standard calling conventions for shadow call stack.
|
// Variants of the standard calling conventions for shadow call stack.
|
||||||
// These all preserve x18 in addition to any other registers.
|
// These all preserve x18 in addition to any other registers.
|
||||||
def CSR_AArch64_NoRegs_SCS
|
def CSR_AArch64_NoRegs_SCS
|
||||||
|
@ -1165,11 +1165,6 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
|
|||||||
.setMIFlag(MachineInstr::FrameSetup);
|
.setMIFlag(MachineInstr::FrameSetup);
|
||||||
}
|
}
|
||||||
|
|
||||||
// All calls are tail calls in GHC calling conv, and functions have no
|
|
||||||
// prologue/epilogue.
|
|
||||||
if (MF.getFunction().getCallingConv() == CallingConv::GHC)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Set tagged base pointer to the requested stack slot.
|
// Set tagged base pointer to the requested stack slot.
|
||||||
// Ideally it should match SP value after prologue.
|
// Ideally it should match SP value after prologue.
|
||||||
Optional<int> TBPI = AFI->getTaggedBasePointerIndex();
|
Optional<int> TBPI = AFI->getTaggedBasePointerIndex();
|
||||||
@ -1677,11 +1672,6 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
|
|||||||
: MFI.getStackSize();
|
: MFI.getStackSize();
|
||||||
AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
|
AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
|
||||||
|
|
||||||
// All calls are tail calls in GHC calling conv, and functions have no
|
|
||||||
// prologue/epilogue.
|
|
||||||
if (MF.getFunction().getCallingConv() == CallingConv::GHC)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// How much of the stack used by incoming arguments this function is expected
|
// How much of the stack used by incoming arguments this function is expected
|
||||||
// to restore in this particular epilogue.
|
// to restore in this particular epilogue.
|
||||||
int64_t ArgumentStackToRestore = getArgumentStackToRestore(MF, MBB);
|
int64_t ArgumentStackToRestore = getArgumentStackToRestore(MF, MBB);
|
||||||
@ -2733,10 +2723,6 @@ bool AArch64FrameLowering::restoreCalleeSavedRegisters(
|
|||||||
void AArch64FrameLowering::determineCalleeSaves(MachineFunction &MF,
|
void AArch64FrameLowering::determineCalleeSaves(MachineFunction &MF,
|
||||||
BitVector &SavedRegs,
|
BitVector &SavedRegs,
|
||||||
RegScavenger *RS) const {
|
RegScavenger *RS) const {
|
||||||
// All calls are tail calls in GHC calling conv, and functions have no
|
|
||||||
// prologue/epilogue.
|
|
||||||
if (MF.getFunction().getCallingConv() == CallingConv::GHC)
|
|
||||||
return;
|
|
||||||
|
|
||||||
TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
|
TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
|
||||||
const AArch64RegisterInfo *RegInfo = static_cast<const AArch64RegisterInfo *>(
|
const AArch64RegisterInfo *RegInfo = static_cast<const AArch64RegisterInfo *>(
|
||||||
|
@ -5526,7 +5526,7 @@ SDValue AArch64TargetLowering::LowerCallResult(
|
|||||||
/// Return true if the calling convention is one that we can guarantee TCO for.
|
/// Return true if the calling convention is one that we can guarantee TCO for.
|
||||||
static bool canGuaranteeTCO(CallingConv::ID CC, bool GuaranteeTailCalls) {
|
static bool canGuaranteeTCO(CallingConv::ID CC, bool GuaranteeTailCalls) {
|
||||||
return (CC == CallingConv::Fast && GuaranteeTailCalls) ||
|
return (CC == CallingConv::Fast && GuaranteeTailCalls) ||
|
||||||
CC == CallingConv::Tail || CC == CallingConv::SwiftTail || CC == CallingConv::GHC;
|
CC == CallingConv::Tail || CC == CallingConv::SwiftTail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true if we might ever do TCO for calls with this calling convention.
|
/// Return true if we might ever do TCO for calls with this calling convention.
|
||||||
|
@ -76,9 +76,7 @@ AArch64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
|
|||||||
assert(MF && "Invalid MachineFunction pointer.");
|
assert(MF && "Invalid MachineFunction pointer.");
|
||||||
|
|
||||||
if (MF->getFunction().getCallingConv() == CallingConv::GHC)
|
if (MF->getFunction().getCallingConv() == CallingConv::GHC)
|
||||||
// GHC set of callee saved regs is empty as all those regs are
|
return CSR_AArch64_NoRegs_LR_SaveList;
|
||||||
// used for passing STG regs around
|
|
||||||
return CSR_AArch64_NoRegs_SaveList;
|
|
||||||
if (MF->getFunction().getCallingConv() == CallingConv::AnyReg)
|
if (MF->getFunction().getCallingConv() == CallingConv::AnyReg)
|
||||||
return CSR_AArch64_AllRegs_SaveList;
|
return CSR_AArch64_AllRegs_SaveList;
|
||||||
|
|
||||||
@ -215,8 +213,10 @@ AArch64RegisterInfo::getCallPreservedMask(const MachineFunction &MF,
|
|||||||
CallingConv::ID CC) const {
|
CallingConv::ID CC) const {
|
||||||
bool SCS = MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack);
|
bool SCS = MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack);
|
||||||
if (CC == CallingConv::GHC)
|
if (CC == CallingConv::GHC)
|
||||||
// This is academic because all GHC calls are (supposed to be) tail calls
|
// By default LLVM doesn't save any regs for GHC.
|
||||||
return SCS ? CSR_AArch64_NoRegs_SCS_RegMask : CSR_AArch64_NoRegs_RegMask;
|
// This means we'll clobber LR on arm64 if we make non-tail calls (e.g. L2 syscall)
|
||||||
|
// CSR_AArch64_NoRegs_LR saves LR to fix this
|
||||||
|
return CSR_AArch64_NoRegs_LR_RegMask;
|
||||||
if (CC == CallingConv::AnyReg)
|
if (CC == CallingConv::AnyReg)
|
||||||
return SCS ? CSR_AArch64_AllRegs_SCS_RegMask : CSR_AArch64_AllRegs_RegMask;
|
return SCS ? CSR_AArch64_AllRegs_SCS_RegMask : CSR_AArch64_AllRegs_RegMask;
|
||||||
|
|
||||||
|
@ -615,6 +615,7 @@ static bool mayTailCallThisCC(CallingConv::ID CC) {
|
|||||||
case CallingConv::SwiftTail:
|
case CallingConv::SwiftTail:
|
||||||
case CallingConv::Tail:
|
case CallingConv::Tail:
|
||||||
case CallingConv::Fast:
|
case CallingConv::Fast:
|
||||||
|
case CallingConv::GHC:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
Loading…
Reference in New Issue
Block a user