+ // Don't materialize other values.
+ return nullptr;
+}
+
+// This function maps the catch and cleanup handlers that are reachable from the
+// specified landing pad. The landing pad sequence will have this basic shape:
+//
+// <cleanup handler>
+// <selector comparison>
+// <catch handler>
+// <cleanup handler>
+// <selector comparison>
+// <catch handler>
+// <cleanup handler>
+// ...
+//
+// Any of the cleanup slots may be absent. The cleanup slots may be occupied by
+// any arbitrary control flow, but all paths through the cleanup code must
+// eventually reach the next selector comparison and no path can skip to a
+// different selector comparisons, though some paths may terminate abnormally.
+// Therefore, we will use a depth first search from the start of any given
+// cleanup block and stop searching when we find the next selector comparison.
+//
+// If the landingpad instruction does not have a catch clause, we will assume
+// that any instructions other than selector comparisons and catch handlers can
+// be ignored. In practice, these will only be the boilerplate instructions.
+//
+// The catch handlers may also have any control structure, but we are only
+// interested in the start of the catch handlers, so we don't need to actually
+// follow the flow of the catch handlers. The start of the catch handlers can
+// be located from the compare instructions, but they can be skipped in the
+// flow by following the contrary branch.
+void WinEHPrepare::mapLandingPadBlocks(LandingPadInst *LPad,
+ LandingPadActions &Actions) {
+ unsigned int NumClauses = LPad->getNumClauses();
+ unsigned int HandlersFound = 0;
+ BasicBlock *BB = LPad->getParent();
+
+ DEBUG(dbgs() << "Mapping landing pad: " << BB->getName() << "\n");
+
+ if (NumClauses == 0) {
+ // This landing pad contains only cleanup code.
+ CleanupHandler *Action = new CleanupHandler(BB);
+ CleanupHandlerMap[BB] = Action;
+ Actions.insertCleanupHandler(Action);
+ DEBUG(dbgs() << " Assuming cleanup code in block " << BB->getName()
+ << "\n");
+ assert(LPad->isCleanup());
+ return;
+ }
+
+ VisitedBlockSet VisitedBlocks;
+
+ while (HandlersFound != NumClauses) {
+ BasicBlock *NextBB = nullptr;
+
+ // See if the clause we're looking for is a catch-all.
+ // If so, the catch begins immediately.
+ if (isa<ConstantPointerNull>(LPad->getClause(HandlersFound))) {
+ // The catch all must occur last.
+ assert(HandlersFound == NumClauses - 1);
+
+ // For C++ EH, check if there is any interesting cleanup code before we
+ // begin the catch. This is important because cleanups cannot rethrow
+ // exceptions but code called from catches can. For SEH, it isn't
+ // important if some finally code before a catch-all is executed out of
+ // line or after recovering from the exception.
+ if (Personality == EHPersonality::MSVC_CXX) {
+ if (auto *CleanupAction = findCleanupHandler(BB, BB)) {
+ // Add a cleanup entry to the list
+ Actions.insertCleanupHandler(CleanupAction);
+ DEBUG(dbgs() << " Found cleanup code in block "
+ << CleanupAction->getStartBlock()->getName() << "\n");
+ }
+ }
+
+ // Add the catch handler to the action list.
+ CatchHandler *Action =
+ new CatchHandler(BB, LPad->getClause(HandlersFound), nullptr);
+ CatchHandlerMap[BB] = Action;
+ Actions.insertCatchHandler(Action);
+ DEBUG(dbgs() << " Catch all handler at block " << BB->getName() << "\n");
+ ++HandlersFound;
+
+ // Once we reach a catch-all, don't expect to hit a resume instruction.
+ BB = nullptr;
+ break;
+ }
+
+ CatchHandler *CatchAction = findCatchHandler(BB, NextBB, VisitedBlocks);
+ // See if there is any interesting code executed before the dispatch.
+ if (auto *CleanupAction =
+ findCleanupHandler(BB, CatchAction->getStartBlock())) {
+ // Add a cleanup entry to the list
+ Actions.insertCleanupHandler(CleanupAction);
+ DEBUG(dbgs() << " Found cleanup code in block "
+ << CleanupAction->getStartBlock()->getName() << "\n");
+ }
+
+ assert(CatchAction);
+ ++HandlersFound;
+
+ // Add the catch handler to the action list.
+ Actions.insertCatchHandler(CatchAction);
+ DEBUG(dbgs() << " Found catch dispatch in block "
+ << CatchAction->getStartBlock()->getName() << "\n");
+
+ // Move on to the block after the catch handler.
+ BB = NextBB;
+ }
+
+ // If we didn't wind up in a catch-all, see if there is any interesting code
+ // executed before the resume.
+ if (auto *CleanupAction = findCleanupHandler(BB, BB)) {
+ // Add a cleanup entry to the list
+ Actions.insertCleanupHandler(CleanupAction);
+ DEBUG(dbgs() << " Found cleanup code in block "
+ << CleanupAction->getStartBlock()->getName() << "\n");
+ }
+
+ // It's possible that some optimization moved code into a landingpad that
+ // wasn't
+ // previously being used for cleanup. If that happens, we need to execute
+ // that
+ // extra code from a cleanup handler.
+ if (Actions.includesCleanup() && !LPad->isCleanup())
+ LPad->setCleanup(true);
+}
+
+// This function searches starting with the input block for the next
+// block that terminates with a branch whose condition is based on a selector
+// comparison. This may be the input block. See the mapLandingPadBlocks
+// comments for a discussion of control flow assumptions.
+//
+CatchHandler *WinEHPrepare::findCatchHandler(BasicBlock *BB,
+ BasicBlock *&NextBB,
+ VisitedBlockSet &VisitedBlocks) {
+ // See if we've already found a catch handler use it.
+ // Call count() first to avoid creating a null entry for blocks
+ // we haven't seen before.
+ if (CatchHandlerMap.count(BB) && CatchHandlerMap[BB] != nullptr) {
+ CatchHandler *Action = cast<CatchHandler>(CatchHandlerMap[BB]);
+ NextBB = Action->getNextBB();
+ return Action;
+ }
+
+ // VisitedBlocks applies only to the current search. We still
+ // need to consider blocks that we've visited while mapping other
+ // landing pads.
+ VisitedBlocks.insert(BB);
+
+ BasicBlock *CatchBlock = nullptr;
+ Constant *Selector = nullptr;
+
+ // If this is the first time we've visited this block from any landing pad
+ // look to see if it is a selector dispatch block.
+ if (!CatchHandlerMap.count(BB)) {
+ if (isSelectorDispatch(BB, CatchBlock, Selector, NextBB)) {
+ CatchHandler *Action = new CatchHandler(BB, Selector, NextBB);
+ CatchHandlerMap[BB] = Action;
+ return Action;
+ }
+ }
+
+ // Visit each successor, looking for the dispatch.
+ // FIXME: We expect to find the dispatch quickly, so this will probably
+ // work better as a breadth first search.
+ for (BasicBlock *Succ : successors(BB)) {
+ if (VisitedBlocks.count(Succ))
+ continue;
+
+ CatchHandler *Action = findCatchHandler(Succ, NextBB, VisitedBlocks);
+ if (Action)
+ return Action;
+ }
+ return nullptr;
+}
+
+// These are helper functions to combine repeated code from findCleanupHandler.
+static CleanupHandler *createCleanupHandler(CleanupHandlerMapTy &CleanupHandlerMap,
+ BasicBlock *BB) {
+ CleanupHandler *Action = new CleanupHandler(BB);
+ CleanupHandlerMap[BB] = Action;
+ return Action;
+}
+
+// This function searches starting with the input block for the next block that
+// contains code that is not part of a catch handler and would not be eliminated
+// during handler outlining.
+//
+CleanupHandler *WinEHPrepare::findCleanupHandler(BasicBlock *StartBB,
+ BasicBlock *EndBB) {
+ // Here we will skip over the following:
+ //
+ // landing pad prolog:
+ //
+ // Unconditional branches
+ //
+ // Selector dispatch
+ //
+ // Resume pattern
+ //
+ // Anything else marks the start of an interesting block
+
+ BasicBlock *BB = StartBB;
+ // Anything other than an unconditional branch will kick us out of this loop
+ // one way or another.
+ while (BB) {
+ // If we've already scanned this block, don't scan it again. If it is
+ // a cleanup block, there will be an action in the CleanupHandlerMap.
+ // If we've scanned it and it is not a cleanup block, there will be a
+ // nullptr in the CleanupHandlerMap. If we have not scanned it, there will
+ // be no entry in the CleanupHandlerMap. We must call count() first to
+ // avoid creating a null entry for blocks we haven't scanned.
+ if (CleanupHandlerMap.count(BB)) {
+ if (auto *Action = CleanupHandlerMap[BB]) {
+ return cast<CleanupHandler>(Action);
+ } else {
+ // Here we handle the case where the cleanup handler map contains a
+ // value for this block but the value is a nullptr. This means that
+ // we have previously analyzed the block and determined that it did
+ // not contain any cleanup code. Based on the earlier analysis, we
+ // know the the block must end in either an unconditional branch, a
+ // resume or a conditional branch that is predicated on a comparison
+ // with a selector. Either the resume or the selector dispatch
+ // would terminate the search for cleanup code, so the unconditional
+ // branch is the only case for which we might need to continue
+ // searching.
+ if (BB == EndBB)
+ return nullptr;
+ BasicBlock *SuccBB;
+ if (!match(BB->getTerminator(), m_UnconditionalBr(SuccBB)))
+ return nullptr;
+ BB = SuccBB;
+ continue;
+ }
+ }
+
+ // Create an entry in the cleanup handler map for this block. Initially
+ // we create an entry that says this isn't a cleanup block. If we find
+ // cleanup code, the caller will replace this entry.
+ CleanupHandlerMap[BB] = nullptr;
+
+ TerminatorInst *Terminator = BB->getTerminator();
+
+ // Landing pad blocks have extra instructions we need to accept.
+ LandingPadMap *LPadMap = nullptr;
+ if (BB->isLandingPad()) {
+ LandingPadInst *LPad = BB->getLandingPadInst();
+ LPadMap = &LPadMaps[LPad];
+ if (!LPadMap->isInitialized())
+ LPadMap->mapLandingPad(LPad);
+ }
+
+ // Look for the bare resume pattern:
+ // %lpad.val1 = insertvalue { i8*, i32 } undef, i8* %exn, 0
+ // %lpad.val2 = insertvalue { i8*, i32 } %lpad.val1, i32 %sel, 1
+ // resume { i8*, i32 } %lpad.val2
+ if (auto *Resume = dyn_cast<ResumeInst>(Terminator)) {
+ InsertValueInst *Insert1 = nullptr;
+ InsertValueInst *Insert2 = nullptr;
+ Value *ResumeVal = Resume->getOperand(0);
+ // If there is only one landingpad, we may use the lpad directly with no
+ // insertions.
+ if (isa<LandingPadInst>(ResumeVal))
+ return nullptr;
+ if (!isa<PHINode>(ResumeVal)) {
+ Insert2 = dyn_cast<InsertValueInst>(ResumeVal);
+ if (!Insert2)
+ return createCleanupHandler(CleanupHandlerMap, BB);
+ Insert1 = dyn_cast<InsertValueInst>(Insert2->getAggregateOperand());
+ if (!Insert1)
+ return createCleanupHandler(CleanupHandlerMap, BB);
+ }
+ for (BasicBlock::iterator II = BB->getFirstNonPHIOrDbg(), IE = BB->end();
+ II != IE; ++II) {
+ Instruction *Inst = II;
+ if (LPadMap && LPadMap->isLandingPadSpecificInst(Inst))
+ continue;
+ if (Inst == Insert1 || Inst == Insert2 || Inst == Resume)
+ continue;
+ if (!Inst->hasOneUse() ||
+ (Inst->user_back() != Insert1 && Inst->user_back() != Insert2)) {
+ return createCleanupHandler(CleanupHandlerMap, BB);
+ }
+ }
+ return nullptr;
+ }
+
+ BranchInst *Branch = dyn_cast<BranchInst>(Terminator);
+ if (Branch && Branch->isConditional()) {
+ // Look for the selector dispatch.
+ // %2 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIf to i8*))
+ // %matches = icmp eq i32 %sel, %2
+ // br i1 %matches, label %catch14, label %eh.resume
+ CmpInst *Compare = dyn_cast<CmpInst>(Branch->getCondition());
+ if (!Compare || !Compare->isEquality())
+ return createCleanupHandler(CleanupHandlerMap, BB);
+ for (BasicBlock::iterator II = BB->getFirstNonPHIOrDbg(),
+ IE = BB->end();
+ II != IE; ++II) {
+ Instruction *Inst = II;
+ if (LPadMap && LPadMap->isLandingPadSpecificInst(Inst))
+ continue;
+ if (Inst == Compare || Inst == Branch)
+ continue;
+ if (match(Inst, m_Intrinsic<Intrinsic::eh_typeid_for>()))
+ continue;
+ return createCleanupHandler(CleanupHandlerMap, BB);
+ }
+ // The selector dispatch block should always terminate our search.
+ assert(BB == EndBB);
+ return nullptr;
+ }
+
+ // Anything else is either a catch block or interesting cleanup code.
+ for (BasicBlock::iterator II = BB->getFirstNonPHIOrDbg(),
+ IE = BB->end();
+ II != IE; ++II) {
+ Instruction *Inst = II;
+ if (LPadMap && LPadMap->isLandingPadSpecificInst(Inst))
+ continue;
+ // Unconditional branches fall through to this loop.
+ if (Inst == Branch)
+ continue;
+ // If this is a catch block, there is no cleanup code to be found.
+ if (match(Inst, m_Intrinsic<Intrinsic::eh_begincatch>()))
+ return nullptr;
+ // Anything else makes this interesting cleanup code.
+ return createCleanupHandler(CleanupHandlerMap, BB);
+ }
+
+ // Only unconditional branches in empty blocks should get this far.
+ assert(Branch && Branch->isUnconditional());
+ if (BB == EndBB)
+ return nullptr;
+ BB = Branch->getSuccessor(0);
+ }