summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/X86/X86FrameLowering.cpp
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2015-11-13 21:27:00 +0000
committerReid Kleckner <rnk@google.com>2015-11-13 21:27:00 +0000
commit75b4be9a1198c53384980eadca2708628b97622c (patch)
treef12c5cb7442b9338145c652f46a5bfdfcec4d201 /llvm/lib/Target/X86/X86FrameLowering.cpp
parent447bbdb17134e9463e45d41610b9e0dd73323dcf (diff)
downloadbcm5719-llvm-75b4be9a1198c53384980eadca2708628b97622c.tar.gz
bcm5719-llvm-75b4be9a1198c53384980eadca2708628b97622c.zip
[WinEH] Fix ESP management with 32-bit __CxxFrameHandler3
The C++ EH personality automatically restores ESP from the C++ EH registration node after a catchret. I mistakenly thought it was like SEH, which does not restore ESP. It makes sense for C++ EH to differ from SEH here because SEH does not use funclets for catches, and does not allow catching inside of finally. C++ EH may need to unwind through multiple catch funclets and eventually catchret to some outer funclet. Therefore, the runtime has to keep track of which ESP to use with catchret, rather than having the compiler reload it manually. llvm-svn: 253084
Diffstat (limited to 'llvm/lib/Target/X86/X86FrameLowering.cpp')
-rw-r--r--llvm/lib/Target/X86/X86FrameLowering.cpp13
1 files changed, 13 insertions, 0 deletions
diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp
index 302fc936744..394151b0b06 100644
--- a/llvm/lib/Target/X86/X86FrameLowering.cpp
+++ b/llvm/lib/Target/X86/X86FrameLowering.cpp
@@ -1246,6 +1246,19 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
} else if (IsFunclet && STI.is32Bit()) {
// Reset EBP / ESI to something good for funclets.
MBBI = restoreWin32EHStackPointers(MBB, MBBI, DL);
+ // If we're a catch funclet, we can be returned to via catchret. Save ESP
+ // into the registration node so that the runtime will restore it for us.
+ if (!MBB.isCleanupFuncletEntry()) {
+ assert(classifyEHPersonality(Fn->getPersonalityFn()) ==
+ EHPersonality::MSVC_CXX);
+ unsigned FrameReg;
+ int FI = MMI.getWinEHFuncInfo(Fn).EHRegNodeFrameIndex;
+ int64_t EHRegOffset = getFrameIndexReference(MF, FI, FrameReg);
+ // ESP is the first field, so no extra displacement is needed.
+ addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32mr)), FrameReg,
+ false, EHRegOffset)
+ .addReg(X86::ESP);
+ }
}
while (MBBI != MBB.end() && MBBI->getFlag(MachineInstr::FrameSetup)) {
OpenPOWER on IntegriCloud