[WinEH] Add codegen support for cleanuppad and cleanupret

All of the complexity is in cleanupret, and it mostly follows the same
codepaths as catchret, except it doesn't take a return value in RAX.

This small example now compiles and executes successfully on win32:
  extern "C" int printf(const char *, ...) noexcept;
  struct Dtor {
    ~Dtor() { printf("~Dtor\n"); }
  };
  void has_cleanup() {
    Dtor o;
    throw 42;
  }
  int main() {
    try {
      has_cleanup();
    } catch (int) {
      printf("caught it\n");
    }
  }

Don't try to put the cleanup in the same function as the catch, or Bad
Things will happen.

llvm-svn: 247219
diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
index e706d73d..0953158 100644
--- a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
@@ -316,10 +316,11 @@
 /// Retreive the MCSymbol for a GlobalValue or MachineBasicBlock. GlobalValues
 /// are used in the old WinEH scheme, and they will be removed eventually.
 static MCSymbol *getMCSymbolForMBBOrGV(AsmPrinter *Asm, ValueOrMBB Handler) {
+  if (!Handler)
+    return nullptr;
   if (Handler.is<MachineBasicBlock *>())
     return Handler.get<MachineBasicBlock *>()->getSymbol();
-  else
-    return Asm->getSymbol(cast<GlobalValue>(Handler.get<const Value *>()));
+  return Asm->getSymbol(cast<GlobalValue>(Handler.get<const Value *>()));
 }
 
 void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {
@@ -404,8 +405,9 @@
   if (UnwindMapXData) {
     OS.EmitLabel(UnwindMapXData);
     for (const WinEHUnwindMapEntry &UME : FuncInfo.UnwindMap) {
-      OS.EmitIntValue(UME.ToState, 4);                // ToState
-      OS.EmitValue(create32bitRef(UME.Cleanup), 4);   // Action
+      MCSymbol *CleanupSym = getMCSymbolForMBBOrGV(Asm, UME.Cleanup);
+      OS.EmitIntValue(UME.ToState, 4);             // ToState
+      OS.EmitValue(create32bitRef(CleanupSym), 4); // Action
     }
   }
 
diff --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
index 15793f6..fe35977 100644
--- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
@@ -223,8 +223,6 @@
         assert(&*BB->begin() == I &&
                "WinEHPrepare failed to remove PHIs from imaginary BBs");
         continue;
-      } else if (!isa<LandingPadInst>(I)) {
-        llvm_unreachable("unhandled EH pad in MBB graph");
       }
     }
 
@@ -269,7 +267,7 @@
   SmallVector<const LandingPadInst *, 4> LPads;
   for (BB = Fn->begin(); BB != EB; ++BB) {
     const Instruction *FNP = BB->getFirstNonPHI();
-    if (BB->isEHPad() && !isa<CatchPadInst>(FNP) && !isa<CatchEndPadInst>(FNP))
+    if (BB->isEHPad() && MBBMap.count(BB))
       MBBMap[BB]->setIsEHPad();
     if (const auto *LPI = dyn_cast<LandingPadInst>(FNP))
       LPads.push_back(LPI);
@@ -289,24 +287,27 @@
 
   // Calculate state numbers if we haven't already.
   WinEHFuncInfo &EHInfo = MMI.getWinEHFuncInfo(&fn);
-  if (Personality == EHPersonality::MSVC_CXX) {
-    const Function *WinEHParentFn = MMI.getWinEHParent(&fn);
+  const Function *WinEHParentFn = MMI.getWinEHParent(&fn);
+  if (Personality == EHPersonality::MSVC_CXX)
     calculateWinCXXEHStateNumbers(WinEHParentFn, EHInfo);
-  } else {
-    const Function *WinEHParentFn = MMI.getWinEHParent(&fn);
+  else
     calculateSEHStateNumbers(WinEHParentFn, EHInfo);
+
+  // Map all BB references in the WinEH data to MBBs.
+  for (WinEHTryBlockMapEntry &TBME : EHInfo.TryBlockMap)
+    for (WinEHHandlerType &H : TBME.HandlerArray)
+      if (const auto *BB =
+              dyn_cast<BasicBlock>(H.Handler.get<const Value *>()))
+        H.Handler = MBBMap[BB];
+  for (WinEHUnwindMapEntry &UME : EHInfo.UnwindMap)
+    if (UME.Cleanup)
+      if (const auto *BB = dyn_cast<BasicBlock>(UME.Cleanup.get<const Value *>()))
+        UME.Cleanup = MBBMap[BB];
+  for (SEHUnwindMapEntry &UME : EHInfo.SEHUnwindMap) {
+    const BasicBlock *BB = UME.Handler.get<const BasicBlock *>();
+    UME.Handler = MBBMap[BB];
   }
 
-    // Map all BB references in the EH data to MBBs.
-    for (WinEHTryBlockMapEntry &TBME : EHInfo.TryBlockMap)
-      for (WinEHHandlerType &H : TBME.HandlerArray)
-        if (const auto *BB =
-                dyn_cast<BasicBlock>(H.Handler.get<const Value *>()))
-          H.Handler = MBBMap[BB];
-    for (SEHUnwindMapEntry &UME : EHInfo.SEHUnwindMap) {
-      const BasicBlock *BB = UME.Handler.get<const BasicBlock *>();
-      UME.Handler = MBBMap[BB];
-    }
   // If there's an explicit EH registration node on the stack, record its
   // frame index.
   if (EHInfo.EHRegNode && EHInfo.EHRegNode->getParent()->getParent() == Fn) {
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 6fba18d..2885776 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -1165,9 +1165,8 @@
 
 void SelectionDAGBuilder::visitCatchRet(const CatchReturnInst &I) {
   // Update machine-CFG edge.
-  MachineBasicBlock *PadMBB = FuncInfo.MBB;
   MachineBasicBlock *TargetMBB = FuncInfo.MBBMap[I.getSuccessor()];
-  PadMBB->addSuccessor(TargetMBB);
+  FuncInfo.MBB->addSuccessor(TargetMBB);
 
   // Create the terminator node.
   SDValue Ret = DAG.getNode(ISD::CATCHRET, getCurSDLoc(), MVT::Other,
@@ -1180,11 +1179,64 @@
 }
 
 void SelectionDAGBuilder::visitCleanupPad(const CleanupPadInst &CPI) {
-  report_fatal_error("visitCleanupPad not yet implemented!");
+  // Don't emit any special code for the cleanuppad instruction. It just marks
+  // the start of a funclet.
+  FuncInfo.MBB->setIsEHFuncletEntry();
+}
+
+/// When an invoke or a cleanupret unwinds to the next EH pad, there are
+/// many places it could ultimately go. In the IR, we have a single unwind
+/// destination, but in the machine CFG, we enumerate all the possible blocks.
+/// This function skips over imaginary basic blocks that hold catchpad,
+/// terminatepad, or catchendpad instructions, and finds all the "real" machine
+/// basic block destinations.
+static void
+findUnwindDestinations(FunctionLoweringInfo &FuncInfo,
+                       const BasicBlock *EHPadBB,
+                       SmallVectorImpl<MachineBasicBlock *> &UnwindDests) {
+  bool IsMSVCCXX = classifyEHPersonality(FuncInfo.Fn->getPersonalityFn()) ==
+                   EHPersonality::MSVC_CXX;
+  while (EHPadBB) {
+    const Instruction *Pad = EHPadBB->getFirstNonPHI();
+    if (isa<LandingPadInst>(Pad)) {
+      // Stop on landingpads. They are not funclets.
+      UnwindDests.push_back(FuncInfo.MBBMap[EHPadBB]);
+      break;
+    } else if (isa<CleanupPadInst>(Pad) || isa<LandingPadInst>(Pad)) {
+      // Stop on cleanup pads. Cleanups are always funclet entries for all known
+      // personalities.
+      UnwindDests.push_back(FuncInfo.MBBMap[EHPadBB]);
+      UnwindDests.back()->setIsEHFuncletEntry();
+      break;
+    } else if (const auto *CPI = dyn_cast<CatchPadInst>(Pad)) {
+      // Add the catchpad handler to the possible destinations.
+      UnwindDests.push_back(FuncInfo.MBBMap[CPI->getNormalDest()]);
+      // In MSVC C++, catchblocks are funclets and need prologues.
+      if (IsMSVCCXX)
+        UnwindDests.back()->setIsEHFuncletEntry();
+      EHPadBB = CPI->getUnwindDest();
+    } else if (const auto *CEPI = dyn_cast<CatchEndPadInst>(Pad)) {
+      EHPadBB = CEPI->getUnwindDest();
+    } else if (const auto *CEPI = dyn_cast<CleanupEndPadInst>(Pad)) {
+      EHPadBB = CEPI->getUnwindDest();
+    }
+  }
 }
 
 void SelectionDAGBuilder::visitCleanupRet(const CleanupReturnInst &I) {
-  report_fatal_error("visitCleanupRet not yet implemented!");
+  // Update successor info.
+  // FIXME: The weights for catchpads will be wrong.
+  SmallVector<MachineBasicBlock *, 1> UnwindDests;
+  findUnwindDestinations(FuncInfo, I.getUnwindDest(), UnwindDests);
+  for (MachineBasicBlock *UnwindDest : UnwindDests) {
+    UnwindDest->setIsEHPad();
+    addSuccessorWithWeight(FuncInfo.MBB, UnwindDest);
+  }
+
+  // Create the terminator node.
+  SDValue Ret =
+      DAG.getNode(ISD::CLEANUPRET, getCurSDLoc(), MVT::Other, getControlRoot());
+  DAG.setRoot(Ret);
 }
 
 void SelectionDAGBuilder::visitCleanupEndPad(const CleanupEndPadInst &I) {
@@ -2020,37 +2072,8 @@
     CopyToExportRegsIfNeeded(&I);
   }
 
-  // Stop when we hit a pad that generates real code or we unwind to caller.
-  // Catchpads are conditional branches that add real MBB destinations and
-  // continue the loop. EH "end" pads are not real BBs and simply continue.
   SmallVector<MachineBasicBlock *, 1> UnwindDests;
-  bool IsMSVCCXX = classifyEHPersonality(FuncInfo.Fn->getPersonalityFn()) ==
-                   EHPersonality::MSVC_CXX;
-  while (EHPadBB) {
-    const Instruction *Pad = EHPadBB->getFirstNonPHI();
-    if (isa<LandingPadInst>(Pad)) {
-      // Stop on landingpads. They are not funclets.
-      UnwindDests.push_back(FuncInfo.MBBMap[EHPadBB]);
-      break;
-    } else if (isa<CleanupPadInst>(Pad) || isa<LandingPadInst>(Pad)) {
-      // Stop on cleanup pads. Cleanups are always funclet entries for all known
-      // personalities.
-      UnwindDests.push_back(FuncInfo.MBBMap[EHPadBB]);
-      UnwindDests.back()->setIsEHFuncletEntry();
-      break;
-    } else if (const auto *CPI = dyn_cast<CatchPadInst>(Pad)) {
-      // Add the catchpad handler to the possible destinations.
-      UnwindDests.push_back(FuncInfo.MBBMap[CPI->getNormalDest()]);
-      // In MSVC C++, catchblocks are funclets and need prologues.
-      if (IsMSVCCXX)
-        UnwindDests.back()->setIsEHFuncletEntry();
-      EHPadBB = CPI->getUnwindDest();
-    } else if (const auto *CEPI = dyn_cast<CatchEndPadInst>(Pad)) {
-      EHPadBB = CEPI->getUnwindDest();
-    } else if (const auto *CEPI = dyn_cast<CleanupEndPadInst>(Pad)) {
-      EHPadBB = CEPI->getUnwindDest();
-    }
-  }
+  findUnwindDestinations(FuncInfo, EHPadBB, UnwindDests);
 
   // Update successor info.
   // FIXME: The weights for catchpads will be wrong.
diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp
index ed3cd5d..ea43cb2 100644
--- a/llvm/lib/CodeGen/WinEHPrepare.cpp
+++ b/llvm/lib/CodeGen/WinEHPrepare.cpp
@@ -3053,7 +3053,7 @@
 }
 
 static int addSEHHandler(WinEHFuncInfo &FuncInfo, int ParentState,
-                          const Function *Filter, const BasicBlock *Handler) {
+                         const Function *Filter, const BasicBlock *Handler) {
   SEHUnwindMapEntry Entry;
   Entry.ToState = ParentState;
   Entry.Filter = Filter;