1
0
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:
sguo35 2022-05-25 17:40:19 -07:00 committed by Ivan
parent c725f494c9
commit 5521155be5
5 changed files with 10 additions and 20 deletions

View File

@ -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

View File

@ -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 *>(

View File

@ -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.

View File

@ -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;

View File

@ -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;