From: Reid Kleckner Date: Fri, 13 Nov 2015 21:27:00 +0000 (+0000) Subject: [WinEH] Fix ESP management with 32-bit __CxxFrameHandler3 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=c6477179dd3a3b6334a5be415a7a86f77db5f5e8;p=oota-llvm.git [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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@253084 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/X86/X86ExpandPseudo.cpp b/lib/Target/X86/X86ExpandPseudo.cpp index 9e5a51c4da1..6015d3465de 100644 --- a/lib/Target/X86/X86ExpandPseudo.cpp +++ b/lib/Target/X86/X86ExpandPseudo.cpp @@ -19,6 +19,7 @@ #include "X86InstrInfo.h" #include "X86MachineFunctionInfo.h" #include "X86Subtarget.h" +#include "llvm/Analysis/LibCallSemantics.h" #include "llvm/CodeGen/Passes.h" // For IDs of passes that are preserved. #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -144,7 +145,9 @@ bool X86ExpandPseudo::ExpandMI(MachineBasicBlock &MBB, case X86::EH_RESTORE: { // Restore ESP and EBP, and optionally ESI if required. - X86FL->restoreWin32EHStackPointers(MBB, MBBI, DL, /*RestoreSP=*/true); + bool IsSEH = isAsynchronousEHPersonality(classifyEHPersonality( + MBB.getParent()->getFunction()->getPersonalityFn())); + X86FL->restoreWin32EHStackPointers(MBB, MBBI, DL, /*RestoreSP=*/IsSEH); MBBI->eraseFromParent(); return true; } diff --git a/lib/Target/X86/X86FrameLowering.cpp b/lib/Target/X86/X86FrameLowering.cpp index 302fc936744..394151b0b06 100644 --- a/lib/Target/X86/X86FrameLowering.cpp +++ b/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)) { diff --git a/test/CodeGen/X86/catchret-fallthrough.ll b/test/CodeGen/X86/catchret-fallthrough.ll index 497f6fb3a9d..f732566d0cb 100644 --- a/test/CodeGen/X86/catchret-fallthrough.ll +++ b/test/CodeGen/X86/catchret-fallthrough.ll @@ -41,6 +41,5 @@ nrvo.skipdtor: ; preds = %invoke.cont.3, %inv ; CHECK-NOT: jmp ; CHECK-NOT: movl {{.*}}, %esp ; CHECK: retl -; CHECK: movl {{.*}}, %esp ; CHECK: addl $12, %ebp ; CHECK: jmp LBB0_{{.*}} diff --git a/test/CodeGen/X86/win-catchpad-csrs.ll b/test/CodeGen/X86/win-catchpad-csrs.ll index f759a4ef0d9..b6b4a9319b0 100644 --- a/test/CodeGen/X86/win-catchpad-csrs.ll +++ b/test/CodeGen/X86/win-catchpad-csrs.ll @@ -67,7 +67,6 @@ catchendblock: ; preds = %catch, ; X86: retl ; X86: [[restorebb:LBB0_[0-9]+]]: -; X86: movl -16(%ebp), %esp ; X86: addl $12, %ebp ; X86: jmp [[contbb]] diff --git a/test/CodeGen/X86/win-catchpad.ll b/test/CodeGen/X86/win-catchpad.ll index 826fae522a3..d9c8307cb08 100644 --- a/test/CodeGen/X86/win-catchpad.ll +++ b/test/CodeGen/X86/win-catchpad.ll @@ -66,6 +66,7 @@ catchendblock: ; preds = %catch, %catch.2, %c } ; X86-LABEL: _try_catch_catch: +; X86: movl %esp, -[[sp_offset:[0-9]+]](%ebp) ; X86: movl $0, -{{[0-9]+}}(%ebp) ; X86: leal -[[local_offs:[0-9]+]](%ebp), %[[addr_reg:[a-z]+]] ; X86-DAG: movl %[[addr_reg]], 4(%esp) @@ -76,15 +77,13 @@ catchendblock: ; preds = %catch, %catch.2, %c ; X86: [[restorebb1:LBB0_[0-9]+]]: # Block address taken ; X86-NEXT: # %invoke.cont.2 -; X86: movl -16(%ebp), %esp -; X86: addl $12, %ebp +; X86-NEXT: addl $12, %ebp ; X86: jmp [[contbb]] ; FIXME: These should be de-duplicated. ; X86: [[restorebb2:LBB0_[0-9]+]]: # Block address taken ; X86-NEXT: # %invoke.cont.3 -; X86: movl -16(%ebp), %esp -; X86: addl $12, %ebp +; X86-NEXT: addl $12, %ebp ; X86: jmp [[contbb]] ; X86: "?catch$[[catch1bb:[0-9]+]]@?0?try_catch_catch@4HA": @@ -92,6 +91,7 @@ catchendblock: ; preds = %catch, %catch.2, %c ; X86: pushl %ebp ; X86: subl $8, %esp ; X86: addl $12, %ebp +; X86: movl %esp, -[[sp_offset]](%ebp) ; X86: leal -[[local_offs]](%ebp), %[[addr_reg:[a-z]+]] ; X86: movl -32(%ebp), %[[e_reg:[a-z]+]] ; X86: movl $1, -{{[0-9]+}}(%ebp) @@ -108,6 +108,7 @@ catchendblock: ; preds = %catch, %catch.2, %c ; X86: pushl %ebp ; X86: subl $8, %esp ; X86: addl $12, %ebp +; X86: movl %esp, -[[sp_offset]](%ebp) ; X86: leal -[[local_offs]](%ebp), %[[addr_reg:[a-z]+]] ; X86: movl $1, -{{[0-9]+}}(%ebp) ; X86-DAG: movl %[[addr_reg]], 4(%esp) @@ -258,8 +259,7 @@ catchendblock: ; X86: [[restorebb:LBB1_[0-9]+]]: # Block address taken ; X86-NEXT: # %catch.done -; X86: movl -16(%ebp), %esp -; X86: addl $12, %ebp +; X86-NEXT: addl $12, %ebp ; X86: jmp [[contbb]] ; X86: "?catch$[[catchdispbb:[0-9]+]]@?0?branch_to_normal_dest@4HA":