[WinEH] Fix cleanup state numbering
[oota-llvm.git] / lib / CodeGen / WinEHPrepare.cpp
index a9fec81207179853cbac15a4f230a1306e4f17e0..1cb50514f681a2fe02d520a833c427a2d18f7cc5 100644 (file)
@@ -437,6 +437,11 @@ bool WinEHPrepare::runOnFunction(Function &Fn) {
   if (!isFuncletEHPersonality(Personality))
     return false;
 
+  // Remove unreachable blocks.  It is not valuable to assign them a color and
+  // their existence can trick us into thinking values are alive when they are
+  // not.
+  removeUnreachableBlocks(Fn);
+
   SmallVector<LandingPadInst *, 4> LPads;
   SmallVector<ResumeInst *, 4> Resumes;
   SmallVector<BasicBlock *, 4> EntryBlocks;
@@ -1614,7 +1619,7 @@ void WinEHPrepare::processSEHCatchHandler(CatchHandler *CatchAction,
   }
   IRBuilder<> Builder(HandlerBB->getFirstInsertionPt());
   Function *EHCodeFn = Intrinsic::getDeclaration(
-      StartBB->getParent()->getParent(), Intrinsic::eh_exceptioncode);
+      StartBB->getParent()->getParent(), Intrinsic::eh_exceptioncode_old);
   Value *Code = Builder.CreateCall(EHCodeFn, {}, "sehcode");
   Code = Builder.CreateIntToPtr(Code, SEHExceptionCodeSlot->getAllocatedType());
   Builder.CreateStore(Code, SEHExceptionCodeSlot);
@@ -2710,6 +2715,9 @@ static void calculateExplicitCXXStateNumbers(WinEHFuncInfo &FuncInfo,
     DEBUG(dbgs() << "CatchHigh[" << FirstTryPad->getName() << "]: " << CatchHigh
                  << '\n');
   } else if (isa<CleanupPadInst>(FirstNonPHI)) {
+    // A cleanup can have multiple exits; don't re-process after the first.
+    if (FuncInfo.EHPadStateMap.count(FirstNonPHI))
+      return;
     int CleanupState = addUnwindMapEntry(FuncInfo, ParentState, &BB);
     FuncInfo.EHPadStateMap[FirstNonPHI] = CleanupState;
     DEBUG(dbgs() << "Assigning state #" << CleanupState << " to BB "
@@ -2717,6 +2725,15 @@ static void calculateExplicitCXXStateNumbers(WinEHFuncInfo &FuncInfo,
     for (const BasicBlock *PredBlock : predecessors(&BB))
       if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
         calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, CleanupState);
+  } else if (auto *CEPI = dyn_cast<CleanupEndPadInst>(FirstNonPHI)) {
+    // Propagate ParentState to the cleanuppad in case it doesn't have
+    // any cleanuprets.
+    BasicBlock *CleanupBlock = CEPI->getCleanupPad()->getParent();
+    calculateExplicitCXXStateNumbers(FuncInfo, *CleanupBlock, ParentState);
+    // Anything unwinding through CleanupEndPadInst is in ParentState.
+    for (const BasicBlock *PredBlock : predecessors(&BB))
+      if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
+        calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, ParentState);
   } else if (isa<TerminatePadInst>(FirstNonPHI)) {
     report_fatal_error("Not yet implemented!");
   } else {
@@ -2789,6 +2806,9 @@ static void calculateExplicitSEHStateNumbers(WinEHFuncInfo &FuncInfo,
       if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
         calculateExplicitSEHStateNumbers(FuncInfo, *PredBlock, ParentState);
   } else if (isa<CleanupPadInst>(FirstNonPHI)) {
+    // A cleanup can have multiple exits; don't re-process after the first.
+    if (FuncInfo.EHPadStateMap.count(FirstNonPHI))
+      return;
     int CleanupState = addSEHFinally(FuncInfo, ParentState, &BB);
     FuncInfo.EHPadStateMap[FirstNonPHI] = CleanupState;
     DEBUG(dbgs() << "Assigning state #" << CleanupState << " to BB "
@@ -2796,7 +2816,11 @@ static void calculateExplicitSEHStateNumbers(WinEHFuncInfo &FuncInfo,
     for (const BasicBlock *PredBlock : predecessors(&BB))
       if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
         calculateExplicitSEHStateNumbers(FuncInfo, *PredBlock, CleanupState);
-  } else if (isa<CleanupEndPadInst>(FirstNonPHI)) {
+  } else if (auto *CEPI = dyn_cast<CleanupEndPadInst>(FirstNonPHI)) {
+    // Propagate ParentState to the cleanuppad in case it doesn't have
+    // any cleanuprets.
+    BasicBlock *CleanupBlock = CEPI->getCleanupPad()->getParent();
+    calculateExplicitSEHStateNumbers(FuncInfo, *CleanupBlock, ParentState);
     // Anything unwinding through CleanupEndPadInst is in ParentState.
     FuncInfo.EHPadStateMap[FirstNonPHI] = ParentState;
     DEBUG(dbgs() << "Assigning state #" << ParentState << " to BB "
@@ -2854,9 +2878,6 @@ void llvm::calculateWinCXXEHStateNumbers(const Function *Fn,
     if (BB.isLandingPad())
       report_fatal_error("MSVC C++ EH cannot use landingpads");
     const Instruction *FirstNonPHI = BB.getFirstNonPHI();
-    // Skip cleanupendpads; they are exits, not entries.
-    if (isa<CleanupEndPadInst>(FirstNonPHI))
-      continue;
     if (!doesEHPadUnwindToCaller(FirstNonPHI))
       continue;
     calculateExplicitCXXStateNumbers(FuncInfo, BB, -1);
@@ -2928,11 +2949,11 @@ void llvm::calculateClrEHStateNumbers(const Function *Fn,
       // Preds of the endpad should get the parent state.
       PredState = ParentState;
     } else if (const CatchPadInst *Catch = dyn_cast<CatchPadInst>(Pad)) {
-      const BasicBlock *Handler = Catch->getNormalDest();
+      const BasicBlock *PadBlock = Catch->getParent();
       uint32_t TypeToken = static_cast<uint32_t>(
           cast<ConstantInt>(Catch->getArgOperand(0))->getZExtValue());
       int NewState = addClrEHHandler(FuncInfo, ParentState,
-                                     ClrHandlerType::Catch, TypeToken, Handler);
+                                     ClrHandlerType::Catch, TypeToken, PadBlock);
       FuncInfo.EHPadStateMap[Catch] = NewState;
       // Preds of the catch get its state
       PredState = NewState;
@@ -3019,12 +3040,11 @@ colorFunclets(Function &F, SmallVectorImpl<BasicBlock *> &EntryBlocks,
       // Mark this as a funclet head as a member of itself.
       FuncletBlocks[Visiting].insert(Visiting);
       // Queue exits with the parent color.
-      for (User *Exit : VisitingHead->users()) {
-        for (BasicBlock *Succ :
-             successors(cast<Instruction>(Exit)->getParent())) {
-          if (BlockColors[Succ].insert(Color).second) {
-            Worklist.push_back({Succ, Color});
-          }
+      for (User *U : VisitingHead->users()) {
+        if (auto *Exit = dyn_cast<TerminatorInst>(U)) {
+          for (BasicBlock *Succ : successors(Exit->getParent()))
+            if (BlockColors[Succ].insert(Color).second)
+              Worklist.push_back({Succ, Color});
         }
       }
       // Handle CatchPad specially since its successors need different colors.
@@ -3124,7 +3144,9 @@ void llvm::calculateCatchReturnSuccessorColors(const Function *Fn,
 
     // The users of a catchpad are always catchrets.
     for (User *Exit : CatchPad->users()) {
-      auto *CatchReturn = cast<CatchReturnInst>(Exit);
+      auto *CatchReturn = dyn_cast<CatchReturnInst>(Exit);
+      if (!CatchReturn)
+        continue;
       BasicBlock *CatchRetSuccessor = CatchReturn->getSuccessor();
       std::set<BasicBlock *> &SuccessorColors = BlockColors[CatchRetSuccessor];
       assert(SuccessorColors.size() == 1 && "Expected BB to be monochrome!");
@@ -3221,6 +3243,10 @@ void WinEHPrepare::cloneCommonBlocks(
       Orig2Clone[BB] = CBB;
     }
 
+    // If nothing was cloned, we're done cloning in this funclet.
+    if (Orig2Clone.empty())
+      continue;
+
     // Update our color mappings to reflect that one block has lost a color and
     // another has gained a color.
     for (auto &BBMapping : Orig2Clone) {
@@ -3234,12 +3260,13 @@ void WinEHPrepare::cloneCommonBlocks(
       BlockColors[OldBlock].erase(FuncletPadBB);
     }
 
-    // Loop over all of the instructions in the function, fixing up operand
+    // Loop over all of the instructions in this funclet, fixing up operand
     // references as we go.  This uses VMap to do all the hard work.
     for (BasicBlock *BB : BlocksInFunclet)
       // Loop over all instructions, fixing each one as we find it...
       for (Instruction &I : *BB)
-        RemapInstruction(&I, VMap, RF_IgnoreMissingEntries);
+        RemapInstruction(&I, VMap,
+                         RF_IgnoreMissingEntries | RF_NoModuleLevelChanges);
 
     // Check to see if SuccBB has PHI nodes. If so, we need to add entries to
     // the PHI nodes for NewBB now.
@@ -3402,11 +3429,6 @@ void WinEHPrepare::verifyPreparedFunclets(Function &F) {
 
 bool WinEHPrepare::prepareExplicitEH(
     Function &F, SmallVectorImpl<BasicBlock *> &EntryBlocks) {
-  // Remove unreachable blocks.  It is not valuable to assign them a color and
-  // their existence can trick us into thinking values are alive when they are
-  // not.
-  removeUnreachableBlocks(F);
-
   replaceTerminatePadWithCleanup(F);
 
   // Determine which blocks are reachable from which funclet entries.