summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/X86/X86FrameLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/X86/X86FrameLowering.cpp')
-rw-r--r--llvm/lib/Target/X86/X86FrameLowering.cpp70
1 files changed, 57 insertions, 13 deletions
diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp
index 489ab1a94a0..e4c35b115e0 100644
--- a/llvm/lib/Target/X86/X86FrameLowering.cpp
+++ b/llvm/lib/Target/X86/X86FrameLowering.cpp
@@ -711,7 +711,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
.addReg(MachineFramePtr, RegState::Kill)
.setMIFlag(MachineInstr::FrameSetup);
// Reset EBP / ESI to something good.
- MBBI = restoreWin32EHFrameAndBasePtr(MBB, MBBI, DL);
+ MBBI = restoreWin32EHStackPointers(MBB, MBBI, DL);
} else {
// FIXME: Add SEH directives.
NeedsWinCFI = false;
@@ -1038,9 +1038,7 @@ bool X86FrameLowering::canUseLEAForSPInEpilogue(
static bool isFuncletReturnInstr(MachineInstr *MI) {
switch (MI->getOpcode()) {
case X86::CATCHRET:
- case X86::CATCHRET64:
case X86::CLEANUPRET:
- case X86::CLEANUPRET64:
return true;
default:
return false;
@@ -1073,13 +1071,51 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
unsigned CSSize = X86FI->getCalleeSavedFrameSize();
uint64_t NumBytes = 0;
- if (isFuncletReturnInstr(MBBI)) {
+ if (MBBI->getOpcode() == X86::CATCHRET) {
NumBytes = MFI->getMaxCallFrameSize();
- assert(hasFP(MF) && "win64 EH funclets without FP not yet implemented");
+ assert(hasFP(MF) && "EH funclets without FP not yet implemented");
+ MachineBasicBlock *TargetMBB = MBBI->getOperand(0).getMBB();
+
+ // If this is SEH, this isn't really a funclet return.
+ bool IsSEH = isAsynchronousEHPersonality(
+ classifyEHPersonality(MF.getFunction()->getPersonalityFn()));
+ if (IsSEH) {
+ if (STI.is32Bit())
+ restoreWin32EHStackPointers(MBB, MBBI, DL, /*RestoreSP=*/true);
+ BuildMI(MBB, MBBI, DL, TII.get(X86::JMP_4)).addMBB(TargetMBB);
+ MBBI->eraseFromParent();
+ return;
+ }
+
+ // For 32-bit, create a new block for the restore code.
+ MachineBasicBlock *RestoreMBB = TargetMBB;
+ if (STI.is32Bit()) {
+ RestoreMBB = MF.CreateMachineBasicBlock(MBB.getBasicBlock());
+ MF.insert(TargetMBB, RestoreMBB);
+ MBB.transferSuccessors(RestoreMBB);
+ MBB.addSuccessor(RestoreMBB);
+ MBBI->getOperand(0).setMBB(RestoreMBB);
+ }
// Pop EBP.
BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r),
- MachineFramePtr).setMIFlag(MachineInstr::FrameDestroy);
+ MachineFramePtr)
+ .setMIFlag(MachineInstr::FrameDestroy);
+
+ // Insert frame restoration code in a new block.
+ if (STI.is32Bit()) {
+ auto RestoreMBBI = RestoreMBB->begin();
+ restoreWin32EHStackPointers(*RestoreMBB, RestoreMBBI, DL,
+ /*RestoreSP=*/true);
+ BuildMI(*RestoreMBB, RestoreMBBI, DL, TII.get(X86::JMP_4))
+ .addMBB(TargetMBB);
+ }
+ } else if (isFuncletReturnInstr(MBBI)) {
+ NumBytes = MFI->getMaxCallFrameSize();
+ assert(hasFP(MF) && "EH funclets without FP not yet implemented");
+ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r),
+ MachineFramePtr)
+ .setMIFlag(MachineInstr::FrameDestroy);
} else if (hasFP(MF)) {
// Calculate required stack adjustment.
uint64_t FrameSize = StackSize - SlotSize;
@@ -2067,9 +2103,9 @@ bool X86FrameLowering::canUseAsEpilogue(const MachineBasicBlock &MBB) const {
return !terminatorsNeedFlagsAsInput(MBB);
}
-MachineBasicBlock::iterator X86FrameLowering::restoreWin32EHFrameAndBasePtr(
+MachineBasicBlock::iterator X86FrameLowering::restoreWin32EHStackPointers(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
- DebugLoc DL) const {
+ DebugLoc DL, bool RestoreSP) const {
assert(STI.isTargetWindowsMSVC() && "funclets only supported in MSVC env");
assert(STI.isTargetWin32() && "EBP/ESI restoration only required on win32");
assert(STI.is32Bit() && !Uses64BitFramePtr &&
@@ -2087,13 +2123,22 @@ MachineBasicBlock::iterator X86FrameLowering::restoreWin32EHFrameAndBasePtr(
// FIXME: Don't set FrameSetup flag in catchret case.
int FI = FuncInfo.EHRegNodeFrameIndex;
+ int EHRegSize = MFI->getObjectSize(FI);
+
+ if (RestoreSP) {
+ // MOV32rm -EHRegSize(%ebp), %esp
+ addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32rm), X86::ESP),
+ X86::EBP, true, -EHRegSize)
+ .setMIFlag(MachineInstr::FrameSetup);
+ }
+
unsigned UsedReg;
int EHRegOffset = getFrameIndexReference(MF, FI, UsedReg);
- int EHRegSize = MFI->getObjectSize(FI);
int EndOffset = -EHRegOffset - EHRegSize;
FuncInfo.EHRegNodeEndOffset = EndOffset;
assert(EndOffset >= 0 &&
"end of registration object above normal EBP position!");
+
if (UsedReg == FramePtr) {
// ADD $offset, %ebp
assert(UsedReg == FramePtr);
@@ -2110,14 +2155,13 @@ MachineBasicBlock::iterator X86FrameLowering::restoreWin32EHFrameAndBasePtr(
addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(X86::LEA32r), BasePtr),
FramePtr, false, EndOffset)
.setMIFlag(MachineInstr::FrameSetup);
- // MOV32mr SavedEBPOffset(%esi), %ebp
+ // MOV32rm SavedEBPOffset(%esi), %ebp
assert(X86FI->getHasSEHFramePtrSave());
int Offset =
getFrameIndexReference(MF, X86FI->getSEHFramePtrSaveIndex(), UsedReg);
assert(UsedReg == BasePtr);
- addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32mr)), UsedReg, true,
- Offset)
- .addReg(FramePtr)
+ addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32rm), FramePtr),
+ UsedReg, true, Offset)
.setMIFlag(MachineInstr::FrameSetup);
}
return MBBI;
OpenPOWER on IntegriCloud