+void SelectionDAGBuilder::visitCatchPad(const CatchPadInst &I) {
+ llvm_unreachable("should never codegen catchpads");
+}
+
+void SelectionDAGBuilder::visitCatchRet(const CatchReturnInst &I) {
+ // Update machine-CFG edge.
+ MachineBasicBlock *TargetMBB = FuncInfo.MBBMap[I.getSuccessor()];
+ FuncInfo.MBB->addSuccessor(TargetMBB);
+
+ // Create the terminator node.
+ SDValue Ret = DAG.getNode(ISD::CATCHRET, getCurSDLoc(), MVT::Other,
+ getControlRoot(), DAG.getBasicBlock(TargetMBB));
+ DAG.setRoot(Ret);
+}
+
+void SelectionDAGBuilder::visitCatchEndPad(const CatchEndPadInst &I) {
+ llvm_unreachable("should never codegen catchendpads");
+}
+
+void SelectionDAGBuilder::visitCleanupPad(const CleanupPadInst &CPI) {
+ // Don't emit any special code for the cleanuppad instruction. It just marks
+ // the start of a funclet.
+ FuncInfo.MBB->setIsEHFuncletEntry();
+ FuncInfo.MBB->setIsCleanupFuncletEntry();
+}
+
+/// 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) {
+ // 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) {
+ report_fatal_error("visitCleanupEndPad not yet implemented!");
+}
+
+void SelectionDAGBuilder::visitTerminatePad(const TerminatePadInst &TPI) {
+ report_fatal_error("visitTerminatePad not yet implemented!");
+}
+