summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/AArch64/AArch64FrameLowering.cpp147
-rw-r--r--llvm/lib/Target/AArch64/AArch64FrameLowering.h11
-rw-r--r--llvm/lib/Target/AArch64/AArch64ISelLowering.cpp24
-rw-r--r--llvm/lib/Target/AArch64/AArch64ISelLowering.h8
-rw-r--r--llvm/lib/Target/AArch64/AArch64InstrInfo.cpp30
-rw-r--r--llvm/lib/Target/AArch64/AArch64InstrInfo.td14
-rw-r--r--llvm/lib/Target/AArch64/AArch64MCInstLower.cpp13
-rw-r--r--llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp13
-rw-r--r--llvm/lib/Target/AArch64/AArch64RegisterInfo.h3
9 files changed, 243 insertions, 20 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
index 9c85001481d..7df25bb424a 100644
--- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
@@ -204,6 +204,11 @@ bool AArch64FrameLowering::canUseRedZone(const MachineFunction &MF) const {
bool AArch64FrameLowering::hasFP(const MachineFunction &MF) const {
const MachineFrameInfo &MFI = MF.getFrameInfo();
const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
+ // Win64 EH requires a frame pointer if funclets are present, as the locals
+ // are accessed off the frame pointer in both the parent function and the
+ // funclets.
+ if (MF.hasEHFunclets())
+ return true;
// Retain behavior of always omitting the FP for leaf functions when possible.
if (MFI.hasCalls() && MF.getTarget().Options.DisableFramePointerElim(MF))
return true;
@@ -774,6 +779,12 @@ static bool ShouldSignWithAKey(MachineFunction &MF) {
return Key.equals_lower("a_key");
}
+static bool needsWinCFI(const MachineFunction &MF) {
+ const Function &F = MF.getFunction();
+ return MF.getTarget().getMCAsmInfo()->usesWindowsCFI() &&
+ F.needsUnwindTableEntry();
+}
+
void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
MachineBasicBlock::iterator MBBI = MBB.begin();
@@ -787,9 +798,10 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
bool needsFrameMoves = (MMI.hasDebugInfo() || F.needsUnwindTableEntry()) &&
!MF.getTarget().getMCAsmInfo()->usesWindowsCFI();
bool HasFP = hasFP(MF);
- bool NeedsWinCFI = MF.getTarget().getMCAsmInfo()->usesWindowsCFI() &&
- F.needsUnwindTableEntry();
+ bool NeedsWinCFI = needsWinCFI(MF);
MF.setHasWinCFI(NeedsWinCFI);
+ bool IsFunclet = MBB.isEHFuncletEntry();
+
// At this point, we're going to decide whether or not the function uses a
// redzone. In most cases, the function doesn't have a redzone so let's
// assume that's false and set it to true in the case that there's a redzone.
@@ -811,7 +823,14 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
if (MF.getFunction().getCallingConv() == CallingConv::GHC)
return;
- int NumBytes = (int)MFI.getStackSize();
+ // getStackSize() includes all the locals in its size calculation. We don't
+ // include these locals when computing the stack size of a funclet, as they
+ // are allocated in the parent's stack frame and accessed via the frame
+ // pointer from the funclet. We only save the callee saved registers in the
+ // funclet, which are really the callee saved registers of the parent
+ // function, including the funclet.
+ int NumBytes = IsFunclet ? (int)getWinEHFuncletFrameSize(MF)
+ : (int)MFI.getStackSize();
if (!AFI->hasStackFrame() && !windowsRequiresStackProbe(MF, NumBytes)) {
assert(!HasFP && "unexpected function without stack frame but with FP");
// All of the stack allocation is for locals.
@@ -847,7 +866,10 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
bool IsWin64 =
Subtarget.isCallingConvWin64(MF.getFunction().getCallingConv());
- unsigned FixedObject = IsWin64 ? alignTo(AFI->getVarArgsGPRSize(), 16) : 0;
+ // Var args are accounted for in the containing function, so don't
+ // include them for funclets.
+ unsigned FixedObject = (IsWin64 && !IsFunclet) ?
+ alignTo(AFI->getVarArgsGPRSize(), 16) : 0;
auto PrologueSaveSize = AFI->getCalleeSavedStackSize() + FixedObject;
// All of the remaining stack allocations are for locals.
@@ -875,6 +897,16 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
++MBBI;
}
+ // The code below is not applicable to funclets. We have emitted all the SEH
+ // opcodes that we needed to emit. The FP and BP belong to the containing
+ // function.
+ if (IsFunclet) {
+ if (NeedsWinCFI)
+ BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PrologEnd))
+ .setMIFlag(MachineInstr::FrameSetup);
+ return;
+ }
+
if (HasFP) {
// Only set up FP if we actually need to. Frame pointer is fp =
// sp - fixedobject - 16.
@@ -1165,6 +1197,16 @@ static void InsertReturnAddressAuth(MachineFunction &MF,
}
}
+static bool isFuncletReturnInstr(const MachineInstr &MI) {
+ switch (MI.getOpcode()) {
+ default:
+ return false;
+ case AArch64::CATCHRET:
+ case AArch64::CLEANUPRET:
+ return true;
+ }
+}
+
void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
@@ -1173,8 +1215,8 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
DebugLoc DL;
bool IsTailCallReturn = false;
- bool NeedsWinCFI = MF.getTarget().getMCAsmInfo()->usesWindowsCFI() &&
- MF.getFunction().needsUnwindTableEntry();
+ bool NeedsWinCFI = needsWinCFI(MF);
+ bool IsFunclet = false;
if (MBB.end() != MBBI) {
DL = MBBI->getDebugLoc();
@@ -1182,9 +1224,11 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
IsTailCallReturn = RetOpcode == AArch64::TCRETURNdi ||
RetOpcode == AArch64::TCRETURNri ||
RetOpcode == AArch64::TCRETURNriBTI;
+ IsFunclet = isFuncletReturnInstr(*MBBI);
}
- int NumBytes = MFI.getStackSize();
+ int NumBytes = IsFunclet ? (int)getWinEHFuncletFrameSize(MF)
+ : MFI.getStackSize();
AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
// All calls are tail calls in GHC calling conv, and functions have no
@@ -1245,6 +1289,10 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
uint64_t AfterCSRPopSize = ArgumentPopSize;
auto PrologueSaveSize = AFI->getCalleeSavedStackSize() + FixedObject;
+ // Var args are accounted for in the containting function, so don't
+ // include them for funclets.
+ if (MF.hasEHFunclets())
+ AFI->setLocalStackSize(NumBytes - PrologueSaveSize);
bool CombineSPBump = shouldCombineCSRLocalStackBump(MF, NumBytes);
// Assume we can't combine the last pop with the sp restore.
@@ -1340,7 +1388,7 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
// FIXME: Rather than doing the math here, we should instead just use
// non-post-indexed loads for the restores if we aren't actually going to
// be able to save any instructions.
- if (MFI.hasVarSizedObjects() || AFI->isStackRealigned())
+ if (!IsFunclet && (MFI.hasVarSizedObjects() || AFI->isStackRealigned()))
emitFrameOffset(MBB, LastPopI, DL, AArch64::SP, AArch64::FP,
-AFI->getCalleeSavedStackSize() + 16, TII,
MachineInstr::FrameDestroy, false, NeedsWinCFI);
@@ -1445,6 +1493,14 @@ int AArch64FrameLowering::resolveFrameIndexReference(const MachineFunction &MF,
// being in range for direct access. If the FPOffset is positive,
// that'll always be best, as the SP will be even further away.
UseFP = true;
+ } else if (MF.hasEHFunclets() && !RegInfo->hasBasePointer(MF)) {
+ // Funclets access the locals contained in the parent's stack frame
+ // via the frame pointer, so we have to use the FP in the parent
+ // function.
+ assert(
+ Subtarget.isCallingConvWin64(MF.getFunction().getCallingConv()) &&
+ "Funclets should only be present on Win64");
+ UseFP = true;
} else {
// We have the choice between FP and (SP or BP).
if (FPOffsetFits && PreferFP) // If FP is the best fit, use it.
@@ -1538,8 +1594,7 @@ static void computeCalleeSaveRegisterPairs(
if (CSI.empty())
return;
- bool NeedsWinCFI = MF.getTarget().getMCAsmInfo()->usesWindowsCFI() &&
- MF.getFunction().needsUnwindTableEntry();
+ bool NeedsWinCFI = needsWinCFI(MF);
AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
MachineFrameInfo &MFI = MF.getFrameInfo();
CallingConv::ID CC = MF.getFunction().getCallingConv();
@@ -1652,8 +1707,7 @@ bool AArch64FrameLowering::spillCalleeSavedRegisters(
const TargetRegisterInfo *TRI) const {
MachineFunction &MF = *MBB.getParent();
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
- bool NeedsWinCFI = MF.getTarget().getMCAsmInfo()->usesWindowsCFI() &&
- MF.getFunction().needsUnwindTableEntry();
+ bool NeedsWinCFI = needsWinCFI(MF);
DebugLoc DL;
SmallVector<RegPairInfo, 8> RegPairs;
@@ -1765,8 +1819,7 @@ bool AArch64FrameLowering::restoreCalleeSavedRegisters(
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
DebugLoc DL;
SmallVector<RegPairInfo, 8> RegPairs;
- bool NeedsWinCFI = MF.getTarget().getMCAsmInfo()->usesWindowsCFI() &&
- MF.getFunction().needsUnwindTableEntry();
+ bool NeedsWinCFI = needsWinCFI(MF);
if (MI != MBB.end())
DL = MI->getDebugLoc();
@@ -1998,3 +2051,69 @@ bool AArch64FrameLowering::enableStackSlotScavenging(
const AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
return AFI->hasCalleeSaveStackFreeSpace();
}
+
+void AArch64FrameLowering::processFunctionBeforeFrameFinalized(
+ MachineFunction &MF, RegScavenger *RS) const {
+ // If this function isn't doing Win64-style C++ EH, we don't need to do
+ // anything.
+ if (!MF.hasEHFunclets())
+ return;
+ const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
+ MachineFrameInfo &MFI = MF.getFrameInfo();
+ WinEHFuncInfo &EHInfo = *MF.getWinEHFuncInfo();
+
+ MachineBasicBlock &MBB = MF.front();
+ auto MBBI = MBB.begin();
+ while (MBBI != MBB.end() && MBBI->getFlag(MachineInstr::FrameSetup))
+ ++MBBI;
+
+ if (MBBI->isTerminator())
+ return;
+
+ // Create an UnwindHelp object.
+ int UnwindHelpFI =
+ MFI.CreateStackObject(/*size*/8, /*alignment*/16, false);
+ EHInfo.UnwindHelpFrameIdx = UnwindHelpFI;
+ // We need to store -2 into the UnwindHelp object at the start of the
+ // function.
+ DebugLoc DL;
+ RS->enterBasicBlock(MBB);
+ unsigned DstReg = RS->scavengeRegister(&AArch64::GPR64RegClass, MBBI, 0);
+ BuildMI(MBB, MBBI, DL, TII.get(AArch64::MOVi64imm), DstReg).addImm(-2);
+ BuildMI(MBB, MBBI, DL, TII.get(AArch64::STURXi))
+ .addReg(DstReg, getKillRegState(true))
+ .addFrameIndex(UnwindHelpFI)
+ .addImm(0);
+}
+
+/// For Win64 AArch64 EH, the offset to the Unwind object is from the SP before
+/// the update. This is easily retrieved as it is exactly the offset that is set
+/// in processFunctionBeforeFrameFinalized.
+int AArch64FrameLowering::getFrameIndexReferencePreferSP(
+ const MachineFunction &MF, int FI, unsigned &FrameReg,
+ bool IgnoreSPUpdates) const {
+ const MachineFrameInfo &MFI = MF.getFrameInfo();
+ LLVM_DEBUG(dbgs() << "Offset from the SP for " << FI << " is "
+ << MFI.getObjectOffset(FI) << "\n");
+ FrameReg = AArch64::SP;
+ return MFI.getObjectOffset(FI);
+}
+
+/// The parent frame offset (aka dispFrame) is only used on X86_64 to retrieve
+/// the parent's frame pointer
+unsigned AArch64FrameLowering::getWinEHParentFrameOffset(
+ const MachineFunction &MF) const {
+ return 0;
+}
+
+/// Funclets only need to account for space for the callee saved registers,
+/// as the locals are accounted for in the parent's stack frame.
+unsigned AArch64FrameLowering::getWinEHFuncletFrameSize(
+ const MachineFunction &MF) const {
+ // This is the size of the pushed CSRs.
+ unsigned CSSize =
+ MF.getInfo<AArch64FunctionInfo>()->getCalleeSavedStackSize();
+ // This is the amount of stack a funclet needs to allocate.
+ return alignTo(CSSize + MF.getFrameInfo().getMaxCallFrameSize(),
+ getStackAlignment());
+}
diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.h b/llvm/lib/Target/AArch64/AArch64FrameLowering.h
index 104e52b5f1f..0d0385acf46 100644
--- a/llvm/lib/Target/AArch64/AArch64FrameLowering.h
+++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.h
@@ -69,6 +69,17 @@ public:
bool enableStackSlotScavenging(const MachineFunction &MF) const override;
+ void processFunctionBeforeFrameFinalized(MachineFunction &MF,
+ RegScavenger *RS) const override;
+
+ unsigned getWinEHParentFrameOffset(const MachineFunction &MF) const override;
+
+ unsigned getWinEHFuncletFrameSize(const MachineFunction &MF) const;
+
+ int getFrameIndexReferencePreferSP(const MachineFunction &MF, int FI,
+ unsigned &FrameReg,
+ bool IgnoreSPUpdates) const override;
+
private:
bool shouldCombineCSRLocalStackBump(MachineFunction &MF,
unsigned StackBumpBytes) const;
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index e3183389a91..44ad6ae6cd2 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -1273,6 +1273,20 @@ AArch64TargetLowering::EmitF128CSEL(MachineInstr &MI,
return EndBB;
}
+MachineBasicBlock *AArch64TargetLowering::EmitLoweredCatchRet(
+ MachineInstr &MI, MachineBasicBlock *BB) const {
+ assert(!isAsynchronousEHPersonality(classifyEHPersonality(
+ BB->getParent()->getFunction().getPersonalityFn())) &&
+ "SEH does not use catchret!");
+ return BB;
+}
+
+MachineBasicBlock *AArch64TargetLowering::EmitLoweredCatchPad(
+ MachineInstr &MI, MachineBasicBlock *BB) const {
+ MI.eraseFromParent();
+ return BB;
+}
+
MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter(
MachineInstr &MI, MachineBasicBlock *BB) const {
switch (MI.getOpcode()) {
@@ -1288,6 +1302,11 @@ MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter(
case TargetOpcode::STACKMAP:
case TargetOpcode::PATCHPOINT:
return emitPatchPoint(MI, BB);
+
+ case AArch64::CATCHRET:
+ return EmitLoweredCatchRet(MI, BB);
+ case AArch64::CATCHPAD:
+ return EmitLoweredCatchPad(MI, BB);
}
}
@@ -11805,3 +11824,8 @@ void AArch64TargetLowering::finalizeLowering(MachineFunction &MF) const {
MF.getFrameInfo().computeMaxCallFrameSize(MF);
TargetLoweringBase::finalizeLowering(MF);
}
+
+// Unlike X86, we let frame lowering assign offsets to all catch objects.
+bool AArch64TargetLowering::needsFixedCatchObjects() const {
+ return false;
+}
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
index b1b31e05bd2..ffc4cc3ef53 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
@@ -302,6 +302,12 @@ public:
MachineBasicBlock *EmitF128CSEL(MachineInstr &MI,
MachineBasicBlock *BB) const;
+ MachineBasicBlock *EmitLoweredCatchRet(MachineInstr &MI,
+ MachineBasicBlock *BB) const;
+
+ MachineBasicBlock *EmitLoweredCatchPad(MachineInstr &MI,
+ MachineBasicBlock *BB) const;
+
MachineBasicBlock *
EmitInstrWithCustomInserter(MachineInstr &MI,
MachineBasicBlock *MBB) const override;
@@ -521,6 +527,8 @@ public:
bool functionArgumentNeedsConsecutiveRegisters(Type *Ty,
CallingConv::ID CallConv,
bool isVarArg) const override;
+ /// Used for exception handling on Win64.
+ bool needsFixedCatchObjects() const override;
private:
/// Keep a pointer to the AArch64Subtarget around so that we can
/// make the right decision when generating code for different targets.
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index 7b4e0512805..bcf278e7888 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -66,7 +66,8 @@ static cl::opt<unsigned>
cl::desc("Restrict range of Bcc instructions (DEBUG)"));
AArch64InstrInfo::AArch64InstrInfo(const AArch64Subtarget &STI)
- : AArch64GenInstrInfo(AArch64::ADJCALLSTACKDOWN, AArch64::ADJCALLSTACKUP),
+ : AArch64GenInstrInfo(AArch64::ADJCALLSTACKDOWN, AArch64::ADJCALLSTACKUP,
+ AArch64::CATCHRET),
RI(STI.getTargetTriple()), Subtarget(STI) {}
/// GetInstSize - Return the number of bytes of code the specified
@@ -1657,11 +1658,36 @@ bool AArch64InstrInfo::substituteCmpToZero(
}
bool AArch64InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
- if (MI.getOpcode() != TargetOpcode::LOAD_STACK_GUARD)
+ if (MI.getOpcode() != TargetOpcode::LOAD_STACK_GUARD &&
+ MI.getOpcode() != AArch64::CATCHRET)
return false;
MachineBasicBlock &MBB = *MI.getParent();
DebugLoc DL = MI.getDebugLoc();
+
+ if (MI.getOpcode() == AArch64::CATCHRET) {
+ // Skip to the first instruction before the epilog.
+ const TargetInstrInfo *TII =
+ MBB.getParent()->getSubtarget().getInstrInfo();
+ MachineBasicBlock *TargetMBB = MI.getOperand(0).getMBB();
+ auto MBBI = MachineBasicBlock::iterator(MI);
+ MachineBasicBlock::iterator FirstEpilogSEH = std::prev(MBBI);
+ while (FirstEpilogSEH->getFlag(MachineInstr::FrameDestroy) &&
+ FirstEpilogSEH != MBB.begin())
+ FirstEpilogSEH = std::prev(FirstEpilogSEH);
+ if (FirstEpilogSEH != MBB.begin())
+ FirstEpilogSEH = std::next(FirstEpilogSEH);
+ BuildMI(MBB, FirstEpilogSEH, DL, TII->get(AArch64::ADRP))
+ .addReg(AArch64::X0, RegState::Define)
+ .addMBB(TargetMBB);
+ BuildMI(MBB, FirstEpilogSEH, DL, TII->get(AArch64::ADDXri))
+ .addReg(AArch64::X0, RegState::Define)
+ .addReg(AArch64::X0)
+ .addMBB(TargetMBB)
+ .addImm(0);
+ return true;
+ }
+
unsigned Reg = MI.getOperand(0).getReg();
const GlobalValue *GV =
cast<GlobalValue>((*MI.memoperands_begin())->getValue());
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 37d3967df44..3c949f5d6f6 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -3175,6 +3175,20 @@ let isPseudo = 1 in {
def SEH_EpilogEnd : Pseudo<(outs), (ins), []>, Sched<[]>;
}
+// Pseudo instructions for Windows EH
+//===----------------------------------------------------------------------===//
+let isTerminator = 1, hasSideEffects = 1, isBarrier = 1, hasCtrlDep = 1,
+ isCodeGenOnly = 1, isReturn = 1, isEHScopeReturn = 1, isPseudo = 1 in {
+ def CLEANUPRET : Pseudo<(outs), (ins), [(cleanupret)]>, Sched<[]>;
+ let usesCustomInserter = 1 in
+ def CATCHRET : Pseudo<(outs), (ins am_brcond:$dst, am_brcond:$src), [(catchret bb:$dst, bb:$src)]>,
+ Sched<[]>;
+}
+
+let hasSideEffects = 1, hasCtrlDep = 1, isCodeGenOnly = 1,
+ usesCustomInserter = 1 in
+def CATCHPAD : Pseudo<(outs), (ins), [(catchpad)]>, Sched<[]>;
+
//===----------------------------------------------------------------------===//
// Floating point immediate move.
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp b/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp
index 6e1824f632e..07295989ec8 100644
--- a/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp
+++ b/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp
@@ -269,4 +269,17 @@ void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
if (lowerOperand(MO, MCOp))
OutMI.addOperand(MCOp);
}
+
+ switch (OutMI.getOpcode()) {
+ case AArch64::CATCHRET:
+ OutMI = MCInst();
+ OutMI.setOpcode(AArch64::RET);
+ OutMI.addOperand(MCOperand::createReg(AArch64::LR));
+ break;
+ case AArch64::CLEANUPRET:
+ OutMI = MCInst();
+ OutMI.setOpcode(AArch64::RET);
+ OutMI.addOperand(MCOperand::createReg(AArch64::LR));
+ break;
+ }
}
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
index 0bab5c05ba6..55631bcba23 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
@@ -161,6 +161,10 @@ void AArch64RegisterInfo::UpdateCustomCallPreservedMask(MachineFunction &MF,
*Mask = UpdatedMask;
}
+const uint32_t *AArch64RegisterInfo::getNoPreservedMask() const {
+ return CSR_AArch64_NoRegs_RegMask;
+}
+
const uint32_t *
AArch64RegisterInfo::getThisReturnPreservedMask(const MachineFunction &MF,
CallingConv::ID CC) const {
@@ -251,14 +255,15 @@ unsigned AArch64RegisterInfo::getBaseRegister() const { return AArch64::X19; }
bool AArch64RegisterInfo::hasBasePointer(const MachineFunction &MF) const {
const MachineFrameInfo &MFI = MF.getFrameInfo();
- // In the presence of variable sized objects, if the fixed stack size is
- // large enough that referencing from the FP won't result in things being
- // in range relatively often, we can use a base pointer to allow access
+ // In the presence of variable sized objects or funclets, if the fixed stack
+ // size is large enough that referencing from the FP won't result in things
+ // being in range relatively often, we can use a base pointer to allow access
// from the other direction like the SP normally works.
+ //
// Furthermore, if both variable sized objects are present, and the
// stack needs to be dynamically re-aligned, the base pointer is the only
// reliable way to reference the locals.
- if (MFI.hasVarSizedObjects()) {
+ if (MFI.hasVarSizedObjects() || MF.hasEHFunclets()) {
if (needsStackRealignment(MF))
return true;
// Conservatively estimate whether the negative offset from the frame
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h
index 4653c7af59d..c4153228a7c 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h
@@ -65,6 +65,9 @@ public:
// normal calls, so they need a different mask to represent this.
const uint32_t *getTLSCallPreservedMask() const;
+ // Funclets on ARM64 Windows don't preserve any registers.
+ const uint32_t *getNoPreservedMask() const override;
+
/// getThisReturnPreservedMask - Returns a call preserved mask specific to the
/// case that 'returned' is on an i64 first argument if the calling convention
/// is one that can (partially) model this attribute with a preserved mask
OpenPOWER on IntegriCloud