[WinEH] Call llvm.stackrestore in __except blocks
authorReid Kleckner <reid@kleckner.net>
Wed, 10 Jun 2015 01:34:54 +0000 (01:34 +0000)
committerReid Kleckner <reid@kleckner.net>
Wed, 10 Jun 2015 01:34:54 +0000 (01:34 +0000)
We have to do this manually, the runtime only sets up ebp. Fixes a crash
when returning after catching an exception.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239451 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86WinEHState.cpp
test/CodeGen/X86/seh-safe-div-win32.ll

index 16a94daa819886f7490b2b9bedf23f94371f3998..afad3f930daf3cdcfb9307b9a2d59a0cd26e6538 100644 (file)
@@ -263,7 +263,6 @@ void WinEHStatePass::emitExceptionRegistrationRecord(Function *F) {
   if (Personality == EHPersonality::MSVC_CXX) {
     RegNodeTy = getCXXEHRegistrationType();
     RegNode = Builder.CreateAlloca(RegNodeTy);
   if (Personality == EHPersonality::MSVC_CXX) {
     RegNodeTy = getCXXEHRegistrationType();
     RegNode = Builder.CreateAlloca(RegNodeTy);
-    // FIXME: We can skip this in -GS- mode, when we figure that out.
     // SavedESP = llvm.stacksave()
     Value *SP = Builder.CreateCall(
         Intrinsic::getDeclaration(TheModule, Intrinsic::stacksave), {});
     // SavedESP = llvm.stacksave()
     Value *SP = Builder.CreateCall(
         Intrinsic::getDeclaration(TheModule, Intrinsic::stacksave), {});
@@ -490,6 +489,7 @@ void WinEHStatePass::addSEHStateStores(Function &F, MachineModuleInfo &MMI) {
 
   // Iterate all the instructions and emit state number stores.
   int CurState = 0;
 
   // Iterate all the instructions and emit state number stores.
   int CurState = 0;
+  SmallPtrSet<BasicBlock *, 4> ExceptBlocks;
   for (BasicBlock &BB : F) {
     for (auto I = BB.begin(), E = BB.end(); I != E; ++I) {
       if (auto *CI = dyn_cast<CallInst>(I)) {
   for (BasicBlock &BB : F) {
     for (auto I = BB.begin(), E = BB.end(); I != E; ++I) {
       if (auto *CI = dyn_cast<CallInst>(I)) {
@@ -517,11 +517,29 @@ void WinEHStatePass::addSEHStateStores(Function &F, MachineModuleInfo &MMI) {
           assert(!ActionList.empty());
           CurState += ActionList.size();
           State += ActionList.size() - 1;
           assert(!ActionList.empty());
           CurState += ActionList.size();
           State += ActionList.size() - 1;
+
+          // Remember all the __except block targets.
+          for (auto &Handler : ActionList) {
+            if (auto *CH = dyn_cast<CatchHandler>(Handler.get())) {
+              auto *BA = cast<BlockAddress>(CH->getHandlerBlockOrFunc());
+              ExceptBlocks.insert(BA->getBasicBlock());
+            }
+          }
         }
         insertStateNumberStore(RegNode, II, State);
       }
     }
   }
         }
         insertStateNumberStore(RegNode, II, State);
       }
     }
   }
+
+  // Insert llvm.stackrestore into each __except block.
+  Function *StackRestore =
+      Intrinsic::getDeclaration(TheModule, Intrinsic::stackrestore);
+  for (BasicBlock *ExceptBB : ExceptBlocks) {
+    IRBuilder<> Builder(ExceptBB->begin());
+    Value *SP =
+        Builder.CreateLoad(Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
+    Builder.CreateCall(StackRestore, {SP});
+  }
 }
 
 /// Rewrite llvm.eh.exceptioncode and llvm.eh.exceptioninfo to memory loads in
 }
 
 /// Rewrite llvm.eh.exceptioncode and llvm.eh.exceptioninfo to memory loads in
index 669677970761787e5ff140c03442a2803d2e8c18..e5cbc587bb257747f42b57ca7d1caaaa207ed2bb 100644 (file)
@@ -77,11 +77,15 @@ __try.cont:
 
 ; CHECK: [[handler0:Ltmp[0-9]+]]: # Block address taken
 ; CHECK: # %handler0
 
 ; CHECK: [[handler0:Ltmp[0-9]+]]: # Block address taken
 ; CHECK: # %handler0
+;      Restore SP
+; CHECK: movl {{.*}}(%ebp), %esp
 ; CHECK: calll _puts
 ; CHECK: jmp [[cont_bb]]
 
 ; CHECK: [[handler1:Ltmp[0-9]+]]: # Block address taken
 ; CHECK: # %handler1
 ; CHECK: calll _puts
 ; CHECK: jmp [[cont_bb]]
 
 ; CHECK: [[handler1:Ltmp[0-9]+]]: # Block address taken
 ; CHECK: # %handler1
+;      Restore SP
+; CHECK: movl {{.*}}(%ebp), %esp
 ; CHECK: calll _puts
 ; CHECK: jmp [[cont_bb]]
 
 ; CHECK: calll _puts
 ; CHECK: jmp [[cont_bb]]