summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/X86/X86ISelLowering.cpp
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2015-11-06 01:49:05 +0000
committerReid Kleckner <rnk@google.com>2015-11-06 01:49:05 +0000
commit51460c139eb95d1ee2daf62ebed082f735016392 (patch)
treeb80ea144ab445ec34be42fcb0f920d19cc36a1fb /llvm/lib/Target/X86/X86ISelLowering.cpp
parent8d372b9761e73455873069660491e10c289009ab (diff)
downloadbcm5719-llvm-51460c139eb95d1ee2daf62ebed082f735016392.tar.gz
bcm5719-llvm-51460c139eb95d1ee2daf62ebed082f735016392.zip
[WinEH] Split EH_RESTORE out of CATCHRET for 32-bit EH
This adds the EH_RESTORE x86 pseudo instr, which is responsible for restoring the stack pointers: EBP and ESP, and ESI if stack realignment is involved. We only need this on 32-bit x86, because on x64 the runtime restores CSRs for us. Previously we had to keep the CATCHRET instruction around during SEH so that we could convince X86FrameLowering to restore our frame pointers. Now we can split these instructions earlier. This was confusing, because we had a return instruction which wasn't really a return and was ultimately going to be removed by X86FrameLowering. This change also simplifies X86FrameLowering, which really shouldn't be building new MBBs. No observable functional change currently, but with the new register mask stuff in D14407, CATCHRET will become a register allocator barrier, and our existing tests rely on us having reasonable register allocation around SEH. llvm-svn: 252266
Diffstat (limited to 'llvm/lib/Target/X86/X86ISelLowering.cpp')
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp42
1 files changed, 42 insertions, 0 deletions
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index d13d0510a0c..c9218a17a0b 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -21338,6 +21338,46 @@ X86TargetLowering::EmitLoweredWinAlloca(MachineInstr *MI,
}
MachineBasicBlock *
+X86TargetLowering::EmitLoweredCatchRet(MachineInstr *MI,
+ MachineBasicBlock *BB) const {
+ MachineFunction *MF = BB->getParent();
+ const Constant *PerFn = MF->getFunction()->getPersonalityFn();
+ bool IsSEH = isAsynchronousEHPersonality(classifyEHPersonality(PerFn));
+ const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
+ MachineBasicBlock *TargetMBB = MI->getOperand(0).getMBB();
+ DebugLoc DL = MI->getDebugLoc();
+
+ // SEH does not outline catch bodies into funclets. Turn CATCHRETs into
+ // JMP_4s, possibly with some extra restoration code for 32-bit EH.
+ if (IsSEH) {
+ if (Subtarget->is32Bit())
+ BuildMI(*BB, MI, DL, TII.get(X86::EH_RESTORE));
+ BuildMI(*BB, MI, DL, TII.get(X86::JMP_4)).addMBB(TargetMBB);
+ MI->eraseFromParent();
+ return BB;
+ }
+
+ // Only 32-bit EH needs to worry about manually restoring stack pointers.
+ if (!Subtarget->is32Bit())
+ return BB;
+
+ // C++ EH creates a new target block to hold the restore code, and wires up
+ // the new block to the return destination with a normal JMP_4.
+ MachineBasicBlock *RestoreMBB =
+ MF->CreateMachineBasicBlock(BB->getBasicBlock());
+ MF->insert(TargetMBB->getIterator(), RestoreMBB);
+ BB->removeSuccessor(TargetMBB);
+ BB->addSuccessor(RestoreMBB);
+ RestoreMBB->addSuccessor(TargetMBB);
+ MI->getOperand(0).setMBB(RestoreMBB);
+
+ auto RestoreMBBI = RestoreMBB->begin();
+ BuildMI(*RestoreMBB, RestoreMBBI, DL, TII.get(X86::EH_RESTORE));
+ BuildMI(*RestoreMBB, RestoreMBBI, DL, TII.get(X86::JMP_4)).addMBB(TargetMBB);
+ return BB;
+}
+
+MachineBasicBlock *
X86TargetLowering::EmitLoweredTLSCall(MachineInstr *MI,
MachineBasicBlock *BB) const {
// This is pretty easy. We're taking the value that we received from
@@ -21717,6 +21757,8 @@ X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
return BB;
case X86::WIN_ALLOCA:
return EmitLoweredWinAlloca(MI, BB);
+ case X86::CATCHRET:
+ return EmitLoweredCatchRet(MI, BB);
case X86::SEG_ALLOCA_32:
case X86::SEG_ALLOCA_64:
return EmitLoweredSegAlloca(MI, BB);
OpenPOWER on IntegriCloud