+
+/// [LIBUNWIND] Find the (possibly absent) call to @llvm.eh.selector
+/// in the given landing pad. In principle, llvm.eh.exception is
+/// required to be in the landing pad; in practice, SplitCriticalEdge
+/// can break that invariant, and then inlining can break it further.
+/// There's a real need for a reliable solution here, but until that
+/// happens, we have some fragile workarounds here.
+static EHSelectorInst *findSelectorForLandingPad(BasicBlock *lpad) {
+ // Look for an exception call in the actual landing pad.
+ EHExceptionInst *exn = findExceptionInBlock(lpad);
+ if (exn) return findSelectorForException(exn);
+
+ // Okay, if that failed, look for one in an obvious successor. If
+ // we find one, we'll fix the IR by moving things back to the
+ // landing pad.
+
+ bool dominates = true; // does the lpad dominate the exn call
+ BasicBlock *nonDominated = 0; // if not, the first non-dominated block
+ BasicBlock *lastDominated = 0; // and the block which branched to it
+
+ BasicBlock *exnBlock = lpad;
+
+ // We need to protect against lpads that lead into infinite loops.
+ SmallPtrSet<BasicBlock*,4> visited;
+ visited.insert(exnBlock);
+
+ do {
+ // We're not going to apply this hack to anything more complicated
+ // than a series of unconditional branches, so if the block
+ // doesn't terminate in an unconditional branch, just fail. More
+ // complicated cases can arise when, say, sinking a call into a
+ // split unwind edge and then inlining it; but that can do almost
+ // *anything* to the CFG, including leaving the selector
+ // completely unreachable. The only way to fix that properly is
+ // to (1) prohibit transforms which move the exception or selector
+ // values away from the landing pad, e.g. by producing them with
+ // instructions that are pinned to an edge like a phi, or
+ // producing them with not-really-instructions, and (2) making
+ // transforms which split edges deal with that.
+ BranchInst *branch = dyn_cast<BranchInst>(&exnBlock->back());
+ if (!branch || branch->isConditional()) return 0;
+
+ BasicBlock *successor = branch->getSuccessor(0);
+
+ // Fail if we found an infinite loop.
+ if (!visited.insert(successor)) return 0;
+
+ // If the successor isn't dominated by exnBlock:
+ if (!successor->getSinglePredecessor()) {
+ // We don't want to have to deal with threading the exception
+ // through multiple levels of phi, so give up if we've already
+ // followed a non-dominating edge.
+ if (!dominates) return 0;
+
+ // Otherwise, remember this as a non-dominating edge.
+ dominates = false;
+ nonDominated = successor;
+ lastDominated = exnBlock;
+ }
+
+ exnBlock = successor;
+
+ // Can we stop here?
+ exn = findExceptionInBlock(exnBlock);
+ } while (!exn);
+
+ // Look for a selector call for the exception we found.
+ EHSelectorInst *selector = findSelectorForException(exn);
+ if (!selector) return 0;
+
+ // The easy case is when the landing pad still dominates the
+ // exception call, in which case we can just move both calls back to
+ // the landing pad.
+ if (dominates) {
+ selector->moveBefore(lpad->getFirstNonPHI());
+ exn->moveBefore(selector);
+ return selector;
+ }
+
+ // Otherwise, we have to split at the first non-dominating block.
+ // The CFG looks basically like this:
+ // lpad:
+ // phis_0
+ // insnsAndBranches_1
+ // br label %nonDominated
+ // nonDominated:
+ // phis_2
+ // insns_3
+ // %exn = call i8* @llvm.eh.exception()
+ // insnsAndBranches_4
+ // %selector = call @llvm.eh.selector(i8* %exn, ...
+ // We need to turn this into:
+ // lpad:
+ // phis_0
+ // %exn0 = call i8* @llvm.eh.exception()
+ // %selector0 = call @llvm.eh.selector(i8* %exn0, ...
+ // insnsAndBranches_1
+ // br label %split // from lastDominated
+ // nonDominated:
+ // phis_2 (without edge from lastDominated)
+ // %exn1 = call i8* @llvm.eh.exception()
+ // %selector1 = call i8* @llvm.eh.selector(i8* %exn1, ...
+ // br label %split
+ // split:
+ // phis_2 (edge from lastDominated, edge from split)
+ // %exn = phi ...
+ // %selector = phi ...
+ // insns_3
+ // insnsAndBranches_4
+
+ assert(nonDominated);
+ assert(lastDominated);
+
+ // First, make clones of the intrinsics to go in lpad.
+ EHExceptionInst *lpadExn = cast<EHExceptionInst>(exn->clone());
+ EHSelectorInst *lpadSelector = cast<EHSelectorInst>(selector->clone());
+ lpadSelector->setArgOperand(0, lpadExn);
+ lpadSelector->insertBefore(lpad->getFirstNonPHI());
+ lpadExn->insertBefore(lpadSelector);
+
+ // Split the non-dominated block.
+ BasicBlock *split =
+ nonDominated->splitBasicBlock(nonDominated->getFirstNonPHI(),
+ nonDominated->getName() + ".lpad-fix");
+
+ // Redirect the last dominated branch there.
+ cast<BranchInst>(lastDominated->back()).setSuccessor(0, split);
+
+ // Move the existing intrinsics to the end of the old block.
+ selector->moveBefore(&nonDominated->back());
+ exn->moveBefore(selector);
+
+ Instruction *splitIP = &split->front();
+
+ // For all the phis in nonDominated, make a new phi in split to join
+ // that phi with the edge from lastDominated.
+ for (BasicBlock::iterator
+ i = nonDominated->begin(), e = nonDominated->end(); i != e; ++i) {
+ PHINode *phi = dyn_cast<PHINode>(i);
+ if (!phi) break;
+
+ PHINode *splitPhi = PHINode::Create(phi->getType(), 2, phi->getName(),
+ splitIP);
+ phi->replaceAllUsesWith(splitPhi);
+ splitPhi->addIncoming(phi, nonDominated);
+ splitPhi->addIncoming(phi->removeIncomingValue(lastDominated),
+ lastDominated);
+ }
+
+ // Make new phis for the exception and selector.
+ PHINode *exnPhi = PHINode::Create(exn->getType(), 2, "", splitIP);
+ exn->replaceAllUsesWith(exnPhi);
+ selector->setArgOperand(0, exn); // except for this use
+ exnPhi->addIncoming(exn, nonDominated);
+ exnPhi->addIncoming(lpadExn, lastDominated);
+
+ PHINode *selectorPhi = PHINode::Create(selector->getType(), 2, "", splitIP);
+ selector->replaceAllUsesWith(selectorPhi);
+ selectorPhi->addIncoming(selector, nonDominated);
+ selectorPhi->addIncoming(lpadSelector, lastDominated);
+
+ return lpadSelector;
+}
+
+namespace {
+ /// A class for recording information about inlining through an invoke.
+ class InvokeInliningInfo {
+ BasicBlock *OuterUnwindDest;
+ EHSelectorInst *OuterSelector;
+ BasicBlock *InnerUnwindDest;
+ PHINode *InnerExceptionPHI;
+ PHINode *InnerSelectorPHI;
+ SmallVector<Value*, 8> UnwindDestPHIValues;
+
+ public:
+ InvokeInliningInfo(InvokeInst *II) :
+ OuterUnwindDest(II->getUnwindDest()), OuterSelector(0),
+ InnerUnwindDest(0), InnerExceptionPHI(0), InnerSelectorPHI(0) {
+
+ // If there are PHI nodes in the unwind destination block, we
+ // need to keep track of which values came into them from the
+ // invoke before removing the edge from this block.
+ llvm::BasicBlock *invokeBB = II->getParent();
+ for (BasicBlock::iterator I = OuterUnwindDest->begin();
+ isa<PHINode>(I); ++I) {
+ // Save the value to use for this edge.
+ PHINode *phi = cast<PHINode>(I);
+ UnwindDestPHIValues.push_back(phi->getIncomingValueForBlock(invokeBB));
+ }
+ }
+
+ /// The outer unwind destination is the target of unwind edges
+ /// introduced for calls within the inlined function.
+ BasicBlock *getOuterUnwindDest() const {
+ return OuterUnwindDest;
+ }
+
+ EHSelectorInst *getOuterSelector() {
+ if (!OuterSelector)
+ OuterSelector = findSelectorForLandingPad(OuterUnwindDest);
+ return OuterSelector;
+ }
+
+ BasicBlock *getInnerUnwindDest();
+
+ bool forwardEHResume(CallInst *call, BasicBlock *src);
+
+ /// Add incoming-PHI values to the unwind destination block for
+ /// the given basic block, using the values for the original
+ /// invoke's source block.
+ void addIncomingPHIValuesFor(BasicBlock *BB) const {
+ addIncomingPHIValuesForInto(BB, OuterUnwindDest);
+ }
+
+ void addIncomingPHIValuesForInto(BasicBlock *src, BasicBlock *dest) const {
+ BasicBlock::iterator I = dest->begin();
+ for (unsigned i = 0, e = UnwindDestPHIValues.size(); i != e; ++i, ++I) {
+ PHINode *phi = cast<PHINode>(I);
+ phi->addIncoming(UnwindDestPHIValues[i], src);
+ }
+ }
+ };
+}
+
+/// Get or create a target for the branch out of rewritten calls to
+/// llvm.eh.resume.
+BasicBlock *InvokeInliningInfo::getInnerUnwindDest() {
+ if (InnerUnwindDest) return InnerUnwindDest;
+
+ // Find and hoist the llvm.eh.exception and llvm.eh.selector calls
+ // in the outer landing pad to immediately following the phis.
+ EHSelectorInst *selector = getOuterSelector();
+ if (!selector) return 0;
+
+ // The call to llvm.eh.exception *must* be in the landing pad.
+ Instruction *exn = cast<Instruction>(selector->getArgOperand(0));
+ assert(exn->getParent() == OuterUnwindDest);
+
+ // TODO: recognize when we've already done this, so that we don't
+ // get a linear number of these when inlining calls into lots of
+ // invokes with the same landing pad.
+
+ // Do the hoisting.
+ Instruction *splitPoint = exn->getParent()->getFirstNonPHI();
+ assert(splitPoint != selector && "selector-on-exception dominance broken!");
+ if (splitPoint == exn) {
+ selector->removeFromParent();
+ selector->insertAfter(exn);
+ splitPoint = selector->getNextNode();
+ } else {
+ exn->moveBefore(splitPoint);
+ selector->moveBefore(splitPoint);
+ }
+
+ // Split the landing pad.
+ InnerUnwindDest = OuterUnwindDest->splitBasicBlock(splitPoint,
+ OuterUnwindDest->getName() + ".body");
+
+ // The number of incoming edges we expect to the inner landing pad.
+ const unsigned phiCapacity = 2;
+
+ // Create corresponding new phis for all the phis in the outer landing pad.
+ BasicBlock::iterator insertPoint = InnerUnwindDest->begin();
+ BasicBlock::iterator I = OuterUnwindDest->begin();
+ for (unsigned i = 0, e = UnwindDestPHIValues.size(); i != e; ++i, ++I) {
+ PHINode *outerPhi = cast<PHINode>(I);
+ PHINode *innerPhi = PHINode::Create(outerPhi->getType(), phiCapacity,
+ outerPhi->getName() + ".lpad-body",
+ insertPoint);
+ outerPhi->replaceAllUsesWith(innerPhi);
+ innerPhi->addIncoming(outerPhi, OuterUnwindDest);
+ }
+
+ // Create a phi for the exception value...
+ InnerExceptionPHI = PHINode::Create(exn->getType(), phiCapacity,
+ "exn.lpad-body", insertPoint);
+ exn->replaceAllUsesWith(InnerExceptionPHI);
+ selector->setArgOperand(0, exn); // restore this use
+ InnerExceptionPHI->addIncoming(exn, OuterUnwindDest);
+
+ // ...and the selector.
+ InnerSelectorPHI = PHINode::Create(selector->getType(), phiCapacity,
+ "selector.lpad-body", insertPoint);
+ selector->replaceAllUsesWith(InnerSelectorPHI);
+ InnerSelectorPHI->addIncoming(selector, OuterUnwindDest);
+
+ // All done.
+ return InnerUnwindDest;
+}
+
+/// [LIBUNWIND] Try to forward the given call, which logically occurs
+/// at the end of the given block, as a branch to the inner unwind
+/// block. Returns true if the call was forwarded.
+bool InvokeInliningInfo::forwardEHResume(CallInst *call, BasicBlock *src) {
+ // First, check whether this is a call to the intrinsic.
+ Function *fn = dyn_cast<Function>(call->getCalledValue());
+ if (!fn || fn->getName() != "llvm.eh.resume")
+ return false;
+
+ // At this point, we need to return true on all paths, because
+ // otherwise we'll construct an invoke of the intrinsic, which is
+ // not well-formed.
+
+ // Try to find or make an inner unwind dest, which will fail if we
+ // can't find a selector call for the outer unwind dest.
+ BasicBlock *dest = getInnerUnwindDest();
+ bool hasSelector = (dest != 0);
+
+ // If we failed, just use the outer unwind dest, dropping the
+ // exception and selector on the floor.
+ if (!hasSelector)
+ dest = OuterUnwindDest;
+
+ // Make a branch.
+ BranchInst::Create(dest, src);
+
+ // Update the phis in the destination. They were inserted in an
+ // order which makes this work.
+ addIncomingPHIValuesForInto(src, dest);
+
+ if (hasSelector) {
+ InnerExceptionPHI->addIncoming(call->getArgOperand(0), src);
+ InnerSelectorPHI->addIncoming(call->getArgOperand(1), src);
+ }
+
+ return true;
+}
+
+/// [LIBUNWIND] Check whether this selector is "only cleanups":
+/// call i32 @llvm.eh.selector(blah, blah, i32 0)
+static bool isCleanupOnlySelector(EHSelectorInst *selector) {
+ if (selector->getNumArgOperands() != 3) return false;
+ ConstantInt *val = dyn_cast<ConstantInt>(selector->getArgOperand(2));
+ return (val && val->isZero());