//===-- WinEHPrepare - Prepare exception handling for code generation ---===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass lowers LLVM IR exception handling into something closer to what the
// backend wants for functions using a personality function from a runtime
// provided by MSVC. Functions with other personality functions are left alone
// and may be prepared by other passes. In particular, all supported MSVC
// personality functions require cleanup code to be outlined, and the C++
// personality requires catch handler code to be outlined.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/Passes.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Analysis/LibCallSemantics.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/CodeGen/WinEHFuncInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/PromoteMemToReg.h"
#include <memory>

using namespace llvm;
using namespace llvm::PatternMatch;

#define DEBUG_TYPE "winehprepare"

namespace {

// This map is used to model frame variable usage during outlining, to
// construct a structure type to hold the frame variables in a frame
// allocation block, and to remap the frame variable allocas (including
// spill locations as needed) to GEPs that get the variable from the
// frame allocation structure.
typedef MapVector<Value *, TinyPtrVector<AllocaInst *>> FrameVarInfoMap;

// TinyPtrVector cannot hold nullptr, so we need our own sentinel that isn't
// quite null.
AllocaInst *getCatchObjectSentinel() {
  return static_cast<AllocaInst *>(nullptr) + 1;
}

typedef SmallSet<BasicBlock *, 4> VisitedBlockSet;

class LandingPadActions;
class LandingPadMap;

typedef DenseMap<const BasicBlock *, CatchHandler *> CatchHandlerMapTy;
typedef DenseMap<const BasicBlock *, CleanupHandler *> CleanupHandlerMapTy;

class WinEHPrepare : public FunctionPass {
public:
  static char ID; // Pass identification, replacement for typeid.
  WinEHPrepare(const TargetMachine *TM = nullptr)
      : FunctionPass(ID) {
    if (TM)
      TheTriple = Triple(TM->getTargetTriple());
  }

  bool runOnFunction(Function &Fn) override;

  bool doFinalization(Module &M) override;

  void getAnalysisUsage(AnalysisUsage &AU) const override;

  const char *getPassName() const override {
    return "Windows exception handling preparation";
  }

private:
  bool prepareExceptionHandlers(Function &F,
                                SmallVectorImpl<LandingPadInst *> &LPads);
  void identifyEHBlocks(Function &F, SmallVectorImpl<LandingPadInst *> &LPads);
  void promoteLandingPadValues(LandingPadInst *LPad);
  void demoteValuesLiveAcrossHandlers(Function &F,
                                      SmallVectorImpl<LandingPadInst *> &LPads);
  void findSEHEHReturnPoints(Function &F,
                             SetVector<BasicBlock *> &EHReturnBlocks);
  void findCXXEHReturnPoints(Function &F,
                             SetVector<BasicBlock *> &EHReturnBlocks);
  void getPossibleReturnTargets(Function *ParentF, Function *HandlerF,
                                SetVector<BasicBlock*> &Targets);
  void completeNestedLandingPad(Function *ParentFn,
                                LandingPadInst *OutlinedLPad,
                                const LandingPadInst *OriginalLPad,
                                FrameVarInfoMap &VarInfo);
  Function *createHandlerFunc(Type *RetTy, const Twine &Name, Module *M,
                              Value *&ParentFP);
  bool outlineHandler(ActionHandler *Action, Function *SrcFn,
                      LandingPadInst *LPad, BasicBlock *StartBB,
                      FrameVarInfoMap &VarInfo);
  void addStubInvokeToHandlerIfNeeded(Function *Handler);

  void mapLandingPadBlocks(LandingPadInst *LPad, LandingPadActions &Actions);
  CatchHandler *findCatchHandler(BasicBlock *BB, BasicBlock *&NextBB,
                                 VisitedBlockSet &VisitedBlocks);
  void findCleanupHandlers(LandingPadActions &Actions, BasicBlock *StartBB,
                           BasicBlock *EndBB);

  void processSEHCatchHandler(CatchHandler *Handler, BasicBlock *StartBB);

  Triple TheTriple;

  // All fields are reset by runOnFunction.
  DominatorTree *DT = nullptr;
  const TargetLibraryInfo *LibInfo = nullptr;
  EHPersonality Personality = EHPersonality::Unknown;
  CatchHandlerMapTy CatchHandlerMap;
  CleanupHandlerMapTy CleanupHandlerMap;
  DenseMap<const LandingPadInst *, LandingPadMap> LPadMaps;
  SmallPtrSet<BasicBlock *, 4> NormalBlocks;
  SmallPtrSet<BasicBlock *, 4> EHBlocks;
  SetVector<BasicBlock *> EHReturnBlocks;

  // This maps landing pad instructions found in outlined handlers to
  // the landing pad instruction in the parent function from which they
  // were cloned.  The cloned/nested landing pad is used as the key
  // because the landing pad may be cloned into multiple handlers.
  // This map will be used to add the llvm.eh.actions call to the nested
  // landing pads after all handlers have been outlined.
  DenseMap<LandingPadInst *, const LandingPadInst *> NestedLPtoOriginalLP;

  // This maps blocks in the parent function which are destinations of
  // catch handlers to cloned blocks in (other) outlined handlers. This
  // handles the case where a nested landing pads has a catch handler that
  // returns to a handler function rather than the parent function.
  // The original block is used as the key here because there should only
  // ever be one handler function from which the cloned block is not pruned.
  // The original block will be pruned from the parent function after all
  // handlers have been outlined.  This map will be used to adjust the
  // return instructions of handlers which return to the block that was
  // outlined into a handler.  This is done after all handlers have been
  // outlined but before the outlined code is pruned from the parent function.
  DenseMap<const BasicBlock *, BasicBlock *> LPadTargetBlocks;

  // Map from outlined handler to call to llvm.frameaddress(1). Only used for
  // 32-bit EH.
  DenseMap<Function *, Value *> HandlerToParentFP;

  AllocaInst *SEHExceptionCodeSlot = nullptr;
};

class WinEHFrameVariableMaterializer : public ValueMaterializer {
public:
  WinEHFrameVariableMaterializer(Function *OutlinedFn, Value *ParentFP,
                                 FrameVarInfoMap &FrameVarInfo);
  ~WinEHFrameVariableMaterializer() override {}

  Value *materializeValueFor(Value *V) override;

  void escapeCatchObject(Value *V);

private:
  FrameVarInfoMap &FrameVarInfo;
  IRBuilder<> Builder;
};

class LandingPadMap {
public:
  LandingPadMap() : OriginLPad(nullptr) {}
  void mapLandingPad(const LandingPadInst *LPad);

  bool isInitialized() { return OriginLPad != nullptr; }

  bool isOriginLandingPadBlock(const BasicBlock *BB) const;
  bool isLandingPadSpecificInst(const Instruction *Inst) const;

  void remapEHValues(ValueToValueMapTy &VMap, Value *EHPtrValue,
                     Value *SelectorValue) const;

private:
  const LandingPadInst *OriginLPad;
  // We will normally only see one of each of these instructions, but
  // if more than one occurs for some reason we can handle that.
  TinyPtrVector<const ExtractValueInst *> ExtractedEHPtrs;
  TinyPtrVector<const ExtractValueInst *> ExtractedSelectors;
};

class WinEHCloningDirectorBase : public CloningDirector {
public:
  WinEHCloningDirectorBase(Function *HandlerFn, Value *ParentFP,
                           FrameVarInfoMap &VarInfo, LandingPadMap &LPadMap)
      : Materializer(HandlerFn, ParentFP, VarInfo),
        SelectorIDType(Type::getInt32Ty(HandlerFn->getContext())),
        Int8PtrType(Type::getInt8PtrTy(HandlerFn->getContext())),
        LPadMap(LPadMap), ParentFP(ParentFP) {}

  CloningAction handleInstruction(ValueToValueMapTy &VMap,
                                  const Instruction *Inst,
                                  BasicBlock *NewBB) override;

  virtual CloningAction handleBeginCatch(ValueToValueMapTy &VMap,
                                         const Instruction *Inst,
                                         BasicBlock *NewBB) = 0;
  virtual CloningAction handleEndCatch(ValueToValueMapTy &VMap,
                                       const Instruction *Inst,
                                       BasicBlock *NewBB) = 0;
  virtual CloningAction handleTypeIdFor(ValueToValueMapTy &VMap,
                                        const Instruction *Inst,
                                        BasicBlock *NewBB) = 0;
  virtual CloningAction handleIndirectBr(ValueToValueMapTy &VMap,
                                         const IndirectBrInst *IBr,
                                         BasicBlock *NewBB) = 0;
  virtual CloningAction handleInvoke(ValueToValueMapTy &VMap,
                                     const InvokeInst *Invoke,
                                     BasicBlock *NewBB) = 0;
  virtual CloningAction handleResume(ValueToValueMapTy &VMap,
                                     const ResumeInst *Resume,
                                     BasicBlock *NewBB) = 0;
  virtual CloningAction handleCompare(ValueToValueMapTy &VMap,
                                      const CmpInst *Compare,
                                      BasicBlock *NewBB) = 0;
  virtual CloningAction handleLandingPad(ValueToValueMapTy &VMap,
                                         const LandingPadInst *LPad,
                                         BasicBlock *NewBB) = 0;

  ValueMaterializer *getValueMaterializer() override { return &Materializer; }

protected:
  WinEHFrameVariableMaterializer Materializer;
  Type *SelectorIDType;
  Type *Int8PtrType;
  LandingPadMap &LPadMap;

  /// The value representing the parent frame pointer.
  Value *ParentFP;
};

class WinEHCatchDirector : public WinEHCloningDirectorBase {
public:
  WinEHCatchDirector(
      Function *CatchFn, Value *ParentFP, Value *Selector,
      FrameVarInfoMap &VarInfo, LandingPadMap &LPadMap,
      DenseMap<LandingPadInst *, const LandingPadInst *> &NestedLPads,
      DominatorTree *DT, SmallPtrSetImpl<BasicBlock *> &EHBlocks)
      : WinEHCloningDirectorBase(CatchFn, ParentFP, VarInfo, LPadMap),
        CurrentSelector(Selector->stripPointerCasts()),
        ExceptionObjectVar(nullptr), NestedLPtoOriginalLP(NestedLPads),
        DT(DT), EHBlocks(EHBlocks) {}

  CloningAction handleBeginCatch(ValueToValueMapTy &VMap,
                                 const Instruction *Inst,
                                 BasicBlock *NewBB) override;
  CloningAction handleEndCatch(ValueToValueMapTy &VMap, const Instruction *Inst,
                               BasicBlock *NewBB) override;
  CloningAction handleTypeIdFor(ValueToValueMapTy &VMap,
                                const Instruction *Inst,
                                BasicBlock *NewBB) override;
  CloningAction handleIndirectBr(ValueToValueMapTy &VMap,
                                 const IndirectBrInst *IBr,
                                 BasicBlock *NewBB) override;
  CloningAction handleInvoke(ValueToValueMapTy &VMap, const InvokeInst *Invoke,
                             BasicBlock *NewBB) override;
  CloningAction handleResume(ValueToValueMapTy &VMap, const ResumeInst *Resume,
                             BasicBlock *NewBB) override;
  CloningAction handleCompare(ValueToValueMapTy &VMap, const CmpInst *Compare,
                              BasicBlock *NewBB) override;
  CloningAction handleLandingPad(ValueToValueMapTy &VMap,
                                 const LandingPadInst *LPad,
                                 BasicBlock *NewBB) override;

  Value *getExceptionVar() { return ExceptionObjectVar; }
  TinyPtrVector<BasicBlock *> &getReturnTargets() { return ReturnTargets; }

private:
  Value *CurrentSelector;

  Value *ExceptionObjectVar;
  TinyPtrVector<BasicBlock *> ReturnTargets;

  // This will be a reference to the field of the same name in the WinEHPrepare
  // object which instantiates this WinEHCatchDirector object.
  DenseMap<LandingPadInst *, const LandingPadInst *> &NestedLPtoOriginalLP;
  DominatorTree *DT;
  SmallPtrSetImpl<BasicBlock *> &EHBlocks;
};

class WinEHCleanupDirector : public WinEHCloningDirectorBase {
public:
  WinEHCleanupDirector(Function *CleanupFn, Value *ParentFP,
                       FrameVarInfoMap &VarInfo, LandingPadMap &LPadMap)
      : WinEHCloningDirectorBase(CleanupFn, ParentFP, VarInfo,
                                 LPadMap) {}

  CloningAction handleBeginCatch(ValueToValueMapTy &VMap,
                                 const Instruction *Inst,
                                 BasicBlock *NewBB) override;
  CloningAction handleEndCatch(ValueToValueMapTy &VMap, const Instruction *Inst,
                               BasicBlock *NewBB) override;
  CloningAction handleTypeIdFor(ValueToValueMapTy &VMap,
                                const Instruction *Inst,
                                BasicBlock *NewBB) override;
  CloningAction handleIndirectBr(ValueToValueMapTy &VMap,
                                 const IndirectBrInst *IBr,
                                 BasicBlock *NewBB) override;
  CloningAction handleInvoke(ValueToValueMapTy &VMap, const InvokeInst *Invoke,
                             BasicBlock *NewBB) override;
  CloningAction handleResume(ValueToValueMapTy &VMap, const ResumeInst *Resume,
                             BasicBlock *NewBB) override;
  CloningAction handleCompare(ValueToValueMapTy &VMap, const CmpInst *Compare,
                              BasicBlock *NewBB) override;
  CloningAction handleLandingPad(ValueToValueMapTy &VMap,
                                 const LandingPadInst *LPad,
                                 BasicBlock *NewBB) override;
};

class LandingPadActions {
public:
  LandingPadActions() : HasCleanupHandlers(false) {}

  void insertCatchHandler(CatchHandler *Action) { Actions.push_back(Action); }
  void insertCleanupHandler(CleanupHandler *Action) {
    Actions.push_back(Action);
    HasCleanupHandlers = true;
  }

  bool includesCleanup() const { return HasCleanupHandlers; }

  SmallVectorImpl<ActionHandler *> &actions() { return Actions; }
  SmallVectorImpl<ActionHandler *>::iterator begin() { return Actions.begin(); }
  SmallVectorImpl<ActionHandler *>::iterator end() { return Actions.end(); }

private:
  // Note that this class does not own the ActionHandler objects in this vector.
  // The ActionHandlers are owned by the CatchHandlerMap and CleanupHandlerMap
  // in the WinEHPrepare class.
  SmallVector<ActionHandler *, 4> Actions;
  bool HasCleanupHandlers;
};

} // end anonymous namespace

char WinEHPrepare::ID = 0;
INITIALIZE_TM_PASS(WinEHPrepare, "winehprepare", "Prepare Windows exceptions",
                   false, false)

FunctionPass *llvm::createWinEHPass(const TargetMachine *TM) {
  return new WinEHPrepare(TM);
}

bool WinEHPrepare::runOnFunction(Function &Fn) {
  // No need to prepare outlined handlers.
  if (Fn.hasFnAttribute("wineh-parent"))
    return false;

  SmallVector<LandingPadInst *, 4> LPads;
  SmallVector<ResumeInst *, 4> Resumes;
  for (BasicBlock &BB : Fn) {
    if (auto *LP = BB.getLandingPadInst())
      LPads.push_back(LP);
    if (auto *Resume = dyn_cast<ResumeInst>(BB.getTerminator()))
      Resumes.push_back(Resume);
  }

  // No need to prepare functions that lack landing pads.
  if (LPads.empty())
    return false;

  // Classify the personality to see what kind of preparation we need.
  Personality = classifyEHPersonality(Fn.getPersonalityFn());

  // Do nothing if this is not an MSVC personality.
  if (!isMSVCEHPersonality(Personality))
    return false;

  DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
  LibInfo = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();

  // If there were any landing pads, prepareExceptionHandlers will make changes.
  prepareExceptionHandlers(Fn, LPads);
  return true;
}

bool WinEHPrepare::doFinalization(Module &M) { return false; }

void WinEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.addRequired<DominatorTreeWrapperPass>();
  AU.addRequired<TargetLibraryInfoWrapperPass>();
}

static bool isSelectorDispatch(BasicBlock *BB, BasicBlock *&CatchHandler,
                               Constant *&Selector, BasicBlock *&NextBB);

// Finds blocks reachable from the starting set Worklist. Does not follow unwind
// edges or blocks listed in StopPoints.
static void findReachableBlocks(SmallPtrSetImpl<BasicBlock *> &ReachableBBs,
                                SetVector<BasicBlock *> &Worklist,
                                const SetVector<BasicBlock *> *StopPoints) {
  while (!Worklist.empty()) {
    BasicBlock *BB = Worklist.pop_back_val();

    // Don't cross blocks that we should stop at.
    if (StopPoints && StopPoints->count(BB))
      continue;

    if (!ReachableBBs.insert(BB).second)
      continue; // Already visited.

    // Don't follow unwind edges of invokes.
    if (auto *II = dyn_cast<InvokeInst>(BB->getTerminator())) {
      Worklist.insert(II->getNormalDest());
      continue;
    }

    // Otherwise, follow all successors.
    Worklist.insert(succ_begin(BB), succ_end(BB));
  }
}

// Attempt to find an instruction where a block can be split before
// a call to llvm.eh.begincatch and its operands.  If the block
// begins with the begincatch call or one of its adjacent operands
// the block will not be split.
static Instruction *findBeginCatchSplitPoint(BasicBlock *BB,
                                             IntrinsicInst *II) {
  // If the begincatch call is already the first instruction in the block,
  // don't split.
  Instruction *FirstNonPHI = BB->getFirstNonPHI();
  if (II == FirstNonPHI)
    return nullptr;

  // If either operand is in the same basic block as the instruction and
  // isn't used by another instruction before the begincatch call, include it
  // in the split block.
  auto *Op0 = dyn_cast<Instruction>(II->getOperand(0));
  auto *Op1 = dyn_cast<Instruction>(II->getOperand(1));

  Instruction *I = II->getPrevNode();
  Instruction *LastI = II;

  while (I == Op0 || I == Op1) {
    // If the block begins with one of the operands and there are no other
    // instructions between the operand and the begincatch call, don't split.
    if (I == FirstNonPHI)
      return nullptr;

    LastI = I;
    I = I->getPrevNode();
  }

  // If there is at least one instruction in the block before the begincatch
  // call and its operands, split the block at either the begincatch or
  // its operand.
  return LastI;
}

/// Find all points where exceptional control rejoins normal control flow via
/// llvm.eh.endcatch. Add them to the normal bb reachability worklist.
void WinEHPrepare::findCXXEHReturnPoints(
    Function &F, SetVector<BasicBlock *> &EHReturnBlocks) {
  for (auto BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI) {
    BasicBlock *BB = BBI;
    for (Instruction &I : *BB) {
      if (match(&I, m_Intrinsic<Intrinsic::eh_begincatch>())) {
        Instruction *SplitPt =
            findBeginCatchSplitPoint(BB, cast<IntrinsicInst>(&I));
        if (SplitPt) {
          // Split the block before the llvm.eh.begincatch call to allow
          // cleanup and catch code to be distinguished later.
          // Do not update BBI because we still need to process the
          // portion of the block that we are splitting off.
          SplitBlock(BB, SplitPt, DT);
          break;
        }
      }
      if (match(&I, m_Intrinsic<Intrinsic::eh_endcatch>())) {
        // Split the block after the call to llvm.eh.endcatch if there is
        // anything other than an unconditional branch, or if the successor
        // starts with a phi.
        auto *Br = dyn_cast<BranchInst>(I.getNextNode());
        if (!Br || !Br->isUnconditional() ||
            isa<PHINode>(Br->getSuccessor(0)->begin())) {
          DEBUG(dbgs() << "splitting block " << BB->getName()
                       << " with llvm.eh.endcatch\n");
          BBI = SplitBlock(BB, I.getNextNode(), DT);
        }
        // The next BB is normal control flow.
        EHReturnBlocks.insert(BB->getTerminator()->getSuccessor(0));
        break;
      }
    }
  }
}

static bool isCatchAllLandingPad(const BasicBlock *BB) {
  const LandingPadInst *LP = BB->getLandingPadInst();
  if (!LP)
    return false;
  unsigned N = LP->getNumClauses();
  return (N > 0 && LP->isCatch(N - 1) &&
          isa<ConstantPointerNull>(LP->getClause(N - 1)));
}

/// Find all points where exceptions control rejoins normal control flow via
/// selector dispatch.
void WinEHPrepare::findSEHEHReturnPoints(
    Function &F, SetVector<BasicBlock *> &EHReturnBlocks) {
  for (auto BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI) {
    BasicBlock *BB = BBI;
    // If the landingpad is a catch-all, treat the whole lpad as if it is
    // reachable from normal control flow.
    // FIXME: This is imprecise. We need a better way of identifying where a
    // catch-all starts and cleanups stop. As far as LLVM is concerned, there
    // is no difference.
    if (isCatchAllLandingPad(BB)) {
      EHReturnBlocks.insert(BB);
      continue;
    }

    BasicBlock *CatchHandler;
    BasicBlock *NextBB;
    Constant *Selector;
    if (isSelectorDispatch(BB, CatchHandler, Selector, NextBB)) {
      // Split the edge if there is a phi node. Returning from EH to a phi node
      // is just as impossible as having a phi after an indirectbr.
      if (isa<PHINode>(CatchHandler->begin())) {
        DEBUG(dbgs() << "splitting EH return edge from " << BB->getName()
                     << " to " << CatchHandler->getName() << '\n');
        BBI = CatchHandler = SplitCriticalEdge(
            BB, std::find(succ_begin(BB), succ_end(BB), CatchHandler));
      }
      EHReturnBlocks.insert(CatchHandler);
    }
  }
}

void WinEHPrepare::identifyEHBlocks(Function &F, 
                                    SmallVectorImpl<LandingPadInst *> &LPads) {
  DEBUG(dbgs() << "Demoting values live across exception handlers in function "
               << F.getName() << '\n');

  // Build a set of all non-exceptional blocks and exceptional blocks.
  // - Non-exceptional blocks are blocks reachable from the entry block while
  //   not following invoke unwind edges.
  // - Exceptional blocks are blocks reachable from landingpads. Analysis does
  //   not follow llvm.eh.endcatch blocks, which mark a transition from
  //   exceptional to normal control.

  if (Personality == EHPersonality::MSVC_CXX)
    findCXXEHReturnPoints(F, EHReturnBlocks);
  else
    findSEHEHReturnPoints(F, EHReturnBlocks);

  DEBUG({
    dbgs() << "identified the following blocks as EH return points:\n";
    for (BasicBlock *BB : EHReturnBlocks)
      dbgs() << "  " << BB->getName() << '\n';
  });

// Join points should not have phis at this point, unless they are a
// landingpad, in which case we will demote their phis later.
#ifndef NDEBUG
  for (BasicBlock *BB : EHReturnBlocks)
    assert((BB->isLandingPad() || !isa<PHINode>(BB->begin())) &&
           "non-lpad EH return block has phi");
#endif

  // Normal blocks are the blocks reachable from the entry block and all EH
  // return points.
  SetVector<BasicBlock *> Worklist;
  Worklist = EHReturnBlocks;
  Worklist.insert(&F.getEntryBlock());
  findReachableBlocks(NormalBlocks, Worklist, nullptr);
  DEBUG({
    dbgs() << "marked the following blocks as normal:\n";
    for (BasicBlock *BB : NormalBlocks)
      dbgs() << "  " << BB->getName() << '\n';
  });

  // Exceptional blocks are the blocks reachable from landingpads that don't
  // cross EH return points.
  Worklist.clear();
  for (auto *LPI : LPads)
    Worklist.insert(LPI->getParent());
  findReachableBlocks(EHBlocks, Worklist, &EHReturnBlocks);
  DEBUG({
    dbgs() << "marked the following blocks as exceptional:\n";
    for (BasicBlock *BB : EHBlocks)
      dbgs() << "  " << BB->getName() << '\n';
  });

}

/// Ensure that all values live into and out of exception handlers are stored
/// in memory.
/// FIXME: This falls down when values are defined in one handler and live into
/// another handler. For example, a cleanup defines a value used only by a
/// catch handler.
void WinEHPrepare::demoteValuesLiveAcrossHandlers(
    Function &F, SmallVectorImpl<LandingPadInst *> &LPads) {
  DEBUG(dbgs() << "Demoting values live across exception handlers in function "
               << F.getName() << '\n');

  // identifyEHBlocks() should have been called before this function.
  assert(!NormalBlocks.empty());

  SetVector<Argument *> ArgsToDemote;
  SetVector<Instruction *> InstrsToDemote;
  for (BasicBlock &BB : F) {
    bool IsNormalBB = NormalBlocks.count(&BB);
    bool IsEHBB = EHBlocks.count(&BB);
    if (!IsNormalBB && !IsEHBB)
      continue; // Blocks that are neither normal nor EH are unreachable.
    for (Instruction &I : BB) {
      for (Value *Op : I.operands()) {
        // Don't demote static allocas, constants, and labels.
        if (isa<Constant>(Op) || isa<BasicBlock>(Op) || isa<InlineAsm>(Op))
          continue;
        auto *AI = dyn_cast<AllocaInst>(Op);
        if (AI && AI->isStaticAlloca())
          continue;

        if (auto *Arg = dyn_cast<Argument>(Op)) {
          if (IsEHBB) {
            DEBUG(dbgs() << "Demoting argument " << *Arg
                         << " used by EH instr: " << I << "\n");
            ArgsToDemote.insert(Arg);
          }
          continue;
        }

        auto *OpI = cast<Instruction>(Op);
        BasicBlock *OpBB = OpI->getParent();
        // If a value is produced and consumed in the same BB, we don't need to
        // demote it.
        if (OpBB == &BB)
          continue;
        bool IsOpNormalBB = NormalBlocks.count(OpBB);
        bool IsOpEHBB = EHBlocks.count(OpBB);
        if (IsNormalBB != IsOpNormalBB || IsEHBB != IsOpEHBB) {
          DEBUG({
            dbgs() << "Demoting instruction live in-out from EH:\n";
            dbgs() << "Instr: " << *OpI << '\n';
            dbgs() << "User: " << I << '\n';
          });
          InstrsToDemote.insert(OpI);
        }
      }
    }
  }

  // Demote values live into and out of handlers.
  // FIXME: This demotion is inefficient. We should insert spills at the point
  // of definition, insert one reload in each handler that uses the value, and
  // insert reloads in the BB used to rejoin normal control flow.
  Instruction *AllocaInsertPt = F.getEntryBlock().getFirstInsertionPt();
  for (Instruction *I : InstrsToDemote)
    DemoteRegToStack(*I, false, AllocaInsertPt);

  // Demote arguments separately, and only for uses in EH blocks.
  for (Argument *Arg : ArgsToDemote) {
    auto *Slot = new AllocaInst(Arg->getType(), nullptr,
                                Arg->getName() + ".reg2mem", AllocaInsertPt);
    SmallVector<User *, 4> Users(Arg->user_begin(), Arg->user_end());
    for (User *U : Users) {
      auto *I = dyn_cast<Instruction>(U);
      if (I && EHBlocks.count(I->getParent())) {
        auto *Reload = new LoadInst(Slot, Arg->getName() + ".reload", false, I);
        U->replaceUsesOfWith(Arg, Reload);
      }
    }
    new StoreInst(Arg, Slot, AllocaInsertPt);
  }

  // Demote landingpad phis, as the landingpad will be removed from the machine
  // CFG.
  for (LandingPadInst *LPI : LPads) {
    BasicBlock *BB = LPI->getParent();
    while (auto *Phi = dyn_cast<PHINode>(BB->begin()))
      DemotePHIToStack(Phi, AllocaInsertPt);
  }

  DEBUG(dbgs() << "Demoted " << InstrsToDemote.size() << " instructions and "
               << ArgsToDemote.size() << " arguments for WinEHPrepare\n\n");
}

bool WinEHPrepare::prepareExceptionHandlers(
    Function &F, SmallVectorImpl<LandingPadInst *> &LPads) {
  // Don't run on functions that are already prepared.
  for (LandingPadInst *LPad : LPads) {
    BasicBlock *LPadBB = LPad->getParent();
    for (Instruction &Inst : *LPadBB)
      if (match(&Inst, m_Intrinsic<Intrinsic::eh_actions>()))
        return false;
  }

  identifyEHBlocks(F, LPads);
  demoteValuesLiveAcrossHandlers(F, LPads);

  // These containers are used to re-map frame variables that are used in
  // outlined catch and cleanup handlers.  They will be populated as the
  // handlers are outlined.
  FrameVarInfoMap FrameVarInfo;

  bool HandlersOutlined = false;

  Module *M = F.getParent();
  LLVMContext &Context = M->getContext();

  // Create a new function to receive the handler contents.
  PointerType *Int8PtrType = Type::getInt8PtrTy(Context);
  Type *Int32Type = Type::getInt32Ty(Context);
  Function *ActionIntrin = Intrinsic::getDeclaration(M, Intrinsic::eh_actions);

  if (isAsynchronousEHPersonality(Personality)) {
    // FIXME: Switch the ehptr type to i32 and then switch this.
    SEHExceptionCodeSlot =
        new AllocaInst(Int8PtrType, nullptr, "seh_exception_code",
                       F.getEntryBlock().getFirstInsertionPt());
  }

  // In order to handle the case where one outlined catch handler returns
  // to a block within another outlined catch handler that would otherwise
  // be unreachable, we need to outline the nested landing pad before we
  // outline the landing pad which encloses it.
  if (!isAsynchronousEHPersonality(Personality))
    std::sort(LPads.begin(), LPads.end(),
              [this](LandingPadInst *const &L, LandingPadInst *const &R) {
                return DT->properlyDominates(R->getParent(), L->getParent());
              });

  // This container stores the llvm.eh.recover and IndirectBr instructions
  // that make up the body of each landing pad after it has been outlined.
  // We need to defer the population of the target list for the indirectbr
  // until all landing pads have been outlined so that we can handle the
  // case of blocks in the target that are reached only from nested
  // landing pads.
  SmallVector<std::pair<CallInst*, IndirectBrInst *>, 4> LPadImpls;

  for (LandingPadInst *LPad : LPads) {
    // Look for evidence that this landingpad has already been processed.
    bool LPadHasActionList = false;
    BasicBlock *LPadBB = LPad->getParent();
    for (Instruction &Inst : *LPadBB) {
      if (match(&Inst, m_Intrinsic<Intrinsic::eh_actions>())) {
        LPadHasActionList = true;
        break;
      }
    }

    // If we've already outlined the handlers for this landingpad,
    // there's nothing more to do here.
    if (LPadHasActionList)
      continue;

    // If either of the values in the aggregate returned by the landing pad is
    // extracted and stored to memory, promote the stored value to a register.
    promoteLandingPadValues(LPad);

    LandingPadActions Actions;
    mapLandingPadBlocks(LPad, Actions);

    HandlersOutlined |= !Actions.actions().empty();
    for (ActionHandler *Action : Actions) {
      if (Action->hasBeenProcessed())
        continue;
      BasicBlock *StartBB = Action->getStartBlock();

      // SEH doesn't do any outlining for catches. Instead, pass the handler
      // basic block addr to llvm.eh.actions and list the block as a return
      // target.
      if (isAsynchronousEHPersonality(Personality)) {
        if (auto *CatchAction = dyn_cast<CatchHandler>(Action)) {
          processSEHCatchHandler(CatchAction, StartBB);
          continue;
        }
      }

      outlineHandler(Action, &F, LPad, StartBB, FrameVarInfo);
    }

    // Split the block after the landingpad instruction so that it is just a
    // call to llvm.eh.actions followed by indirectbr.
    assert(!isa<PHINode>(LPadBB->begin()) && "lpad phi not removed");
    SplitBlock(LPadBB, LPad->getNextNode(), DT);
    // Erase the branch inserted by the split so we can insert indirectbr.
    LPadBB->getTerminator()->eraseFromParent();

    // Replace all extracted values with undef and ultimately replace the
    // landingpad with undef.
    SmallVector<Instruction *, 4> SEHCodeUses;
    SmallVector<Instruction *, 4> EHUndefs;
    for (User *U : LPad->users()) {
      auto *E = dyn_cast<ExtractValueInst>(U);
      if (!E)
        continue;
      assert(E->getNumIndices() == 1 &&
             "Unexpected operation: extracting both landing pad values");
      unsigned Idx = *E->idx_begin();
      assert((Idx == 0 || Idx == 1) && "unexpected index");
      if (Idx == 0 && isAsynchronousEHPersonality(Personality))
        SEHCodeUses.push_back(E);
      else
        EHUndefs.push_back(E);
    }
    for (Instruction *E : EHUndefs) {
      E->replaceAllUsesWith(UndefValue::get(E->getType()));
      E->eraseFromParent();
    }
    LPad->replaceAllUsesWith(UndefValue::get(LPad->getType()));

    // Rewrite uses of the exception pointer to loads of an alloca.
    for (Instruction *E : SEHCodeUses) {
      SmallVector<Use *, 4> Uses;
      for (Use &U : E->uses())
        Uses.push_back(&U);
      for (Use *U : Uses) {
        auto *I = cast<Instruction>(U->getUser());
        if (isa<ResumeInst>(I))
          continue;
        LoadInst *LI;
        if (auto *Phi = dyn_cast<PHINode>(I))
          LI = new LoadInst(SEHExceptionCodeSlot, "sehcode", false,
                            Phi->getIncomingBlock(*U));
        else
          LI = new LoadInst(SEHExceptionCodeSlot, "sehcode", false, I);
        U->set(LI);
      }
      E->replaceAllUsesWith(UndefValue::get(E->getType()));
      E->eraseFromParent();
    }

    // Add a call to describe the actions for this landing pad.
    std::vector<Value *> ActionArgs;
    for (ActionHandler *Action : Actions) {
      // Action codes from docs are: 0 cleanup, 1 catch.
      if (auto *CatchAction = dyn_cast<CatchHandler>(Action)) {
        ActionArgs.push_back(ConstantInt::get(Int32Type, 1));
        ActionArgs.push_back(CatchAction->getSelector());
        // Find the frame escape index of the exception object alloca in the
        // parent.
        int FrameEscapeIdx = -1;
        Value *EHObj = const_cast<Value *>(CatchAction->getExceptionVar());
        if (EHObj && !isa<ConstantPointerNull>(EHObj)) {
          auto I = FrameVarInfo.find(EHObj);
          assert(I != FrameVarInfo.end() &&
                 "failed to map llvm.eh.begincatch var");
          FrameEscapeIdx = std::distance(FrameVarInfo.begin(), I);
        }
        ActionArgs.push_back(ConstantInt::get(Int32Type, FrameEscapeIdx));
      } else {
        ActionArgs.push_back(ConstantInt::get(Int32Type, 0));
      }
      ActionArgs.push_back(Action->getHandlerBlockOrFunc());
    }
    CallInst *Recover =
        CallInst::Create(ActionIntrin, ActionArgs, "recover", LPadBB);

    SetVector<BasicBlock *> ReturnTargets;
    for (ActionHandler *Action : Actions) {
      if (auto *CatchAction = dyn_cast<CatchHandler>(Action)) {
        const auto &CatchTargets = CatchAction->getReturnTargets();
        ReturnTargets.insert(CatchTargets.begin(), CatchTargets.end());
      }
    }
    IndirectBrInst *Branch =
        IndirectBrInst::Create(Recover, ReturnTargets.size(), LPadBB);
    for (BasicBlock *Target : ReturnTargets)
      Branch->addDestination(Target);

    if (!isAsynchronousEHPersonality(Personality)) {
      // C++ EH must repopulate the targets later to handle the case of
      // targets that are reached indirectly through nested landing pads.
      LPadImpls.push_back(std::make_pair(Recover, Branch));
    }

  } // End for each landingpad

  // If nothing got outlined, there is no more processing to be done.
  if (!HandlersOutlined)
    return false;

  // Replace any nested landing pad stubs with the correct action handler.
  // This must be done before we remove unreachable blocks because it
  // cleans up references to outlined blocks that will be deleted.
  for (auto &LPadPair : NestedLPtoOriginalLP)
    completeNestedLandingPad(&F, LPadPair.first, LPadPair.second, FrameVarInfo);
  NestedLPtoOriginalLP.clear();

  // Update the indirectbr instructions' target lists if necessary.
  SetVector<BasicBlock*> CheckedTargets;
  SmallVector<std::unique_ptr<ActionHandler>, 4> ActionList;
  for (auto &LPadImplPair : LPadImpls) {
    IntrinsicInst *Recover = cast<IntrinsicInst>(LPadImplPair.first);
    IndirectBrInst *Branch = LPadImplPair.second;

    // Get a list of handlers called by 
    parseEHActions(Recover, ActionList);

    // Add an indirect branch listing possible successors of the catch handlers.
    SetVector<BasicBlock *> ReturnTargets;
    for (const auto &Action : ActionList) {
      if (auto *CA = dyn_cast<CatchHandler>(Action.get())) {
        Function *Handler = cast<Function>(CA->getHandlerBlockOrFunc());
        getPossibleReturnTargets(&F, Handler, ReturnTargets);
      }
    }
    ActionList.clear();
    // Clear any targets we already knew about.
    for (unsigned int I = 0, E = Branch->getNumDestinations(); I < E; ++I) {
      BasicBlock *KnownTarget = Branch->getDestination(I);
      if (ReturnTargets.count(KnownTarget))
        ReturnTargets.remove(KnownTarget);
    }
    for (BasicBlock *Target : ReturnTargets) {
      Branch->addDestination(Target);
      // The target may be a block that we excepted to get pruned.
      // If it is, it may contain a call to llvm.eh.endcatch.
      if (CheckedTargets.insert(Target)) {
        // Earlier preparations guarantee that all calls to llvm.eh.endcatch
        // will be followed by an unconditional branch.
        auto *Br = dyn_cast<BranchInst>(Target->getTerminator());
        if (Br && Br->isUnconditional() &&
            Br != Target->getFirstNonPHIOrDbgOrLifetime()) {
          Instruction *Prev = Br->getPrevNode();
          if (match(cast<Value>(Prev), m_Intrinsic<Intrinsic::eh_endcatch>()))
            Prev->eraseFromParent();
        }
      }
    }
  }
  LPadImpls.clear();

  F.addFnAttr("wineh-parent", F.getName());

  // Delete any blocks that were only used by handlers that were outlined above.
  removeUnreachableBlocks(F);

  BasicBlock *Entry = &F.getEntryBlock();
  IRBuilder<> Builder(F.getParent()->getContext());
  Builder.SetInsertPoint(Entry->getFirstInsertionPt());

  Function *FrameEscapeFn =
      Intrinsic::getDeclaration(M, Intrinsic::frameescape);
  Function *RecoverFrameFn =
      Intrinsic::getDeclaration(M, Intrinsic::framerecover);
  SmallVector<Value *, 8> AllocasToEscape;

  // Scan the entry block for an existing call to llvm.frameescape. We need to
  // keep escaping those objects.
  for (Instruction &I : F.front()) {
    auto *II = dyn_cast<IntrinsicInst>(&I);
    if (II && II->getIntrinsicID() == Intrinsic::frameescape) {
      auto Args = II->arg_operands();
      AllocasToEscape.append(Args.begin(), Args.end());
      II->eraseFromParent();
      break;
    }
  }

  // Finally, replace all of the temporary allocas for frame variables used in
  // the outlined handlers with calls to llvm.framerecover.
  for (auto &VarInfoEntry : FrameVarInfo) {
    Value *ParentVal = VarInfoEntry.first;
    TinyPtrVector<AllocaInst *> &Allocas = VarInfoEntry.second;
    AllocaInst *ParentAlloca = cast<AllocaInst>(ParentVal);

    // FIXME: We should try to sink unescaped allocas from the parent frame into
    // the child frame. If the alloca is escaped, we have to use the lifetime
    // markers to ensure that the alloca is only live within the child frame.

    // Add this alloca to the list of things to escape.
    AllocasToEscape.push_back(ParentAlloca);

    // Next replace all outlined allocas that are mapped to it.
    for (AllocaInst *TempAlloca : Allocas) {
      if (TempAlloca == getCatchObjectSentinel())
        continue; // Skip catch parameter sentinels.
      Function *HandlerFn = TempAlloca->getParent()->getParent();
      llvm::Value *FP = HandlerToParentFP[HandlerFn];
      assert(FP);

      // FIXME: Sink this framerecover into the blocks where it is used.
      Builder.SetInsertPoint(TempAlloca);
      Builder.SetCurrentDebugLocation(TempAlloca->getDebugLoc());
      Value *RecoverArgs[] = {
          Builder.CreateBitCast(&F, Int8PtrType, ""), FP,
          llvm::ConstantInt::get(Int32Type, AllocasToEscape.size() - 1)};
      Instruction *RecoveredAlloca =
          Builder.CreateCall(RecoverFrameFn, RecoverArgs);

      // Add a pointer bitcast if the alloca wasn't an i8.
      if (RecoveredAlloca->getType() != TempAlloca->getType()) {
        RecoveredAlloca->setName(Twine(TempAlloca->getName()) + ".i8");
        RecoveredAlloca = cast<Instruction>(
            Builder.CreateBitCast(RecoveredAlloca, TempAlloca->getType()));
      }
      TempAlloca->replaceAllUsesWith(RecoveredAlloca);
      TempAlloca->removeFromParent();
      RecoveredAlloca->takeName(TempAlloca);
      delete TempAlloca;
    }
  } // End for each FrameVarInfo entry.

  // Insert 'call void (...)* @llvm.frameescape(...)' at the end of the entry
  // block.
  Builder.SetInsertPoint(&F.getEntryBlock().back());
  Builder.CreateCall(FrameEscapeFn, AllocasToEscape);

  if (SEHExceptionCodeSlot) {
    if (isAllocaPromotable(SEHExceptionCodeSlot)) {
      SmallPtrSet<BasicBlock *, 4> UserBlocks;
      for (User *U : SEHExceptionCodeSlot->users()) {
        if (auto *Inst = dyn_cast<Instruction>(U))
          UserBlocks.insert(Inst->getParent());
      }
      PromoteMemToReg(SEHExceptionCodeSlot, *DT);
      // After the promotion, kill off dead instructions.
      for (BasicBlock *BB : UserBlocks)
        SimplifyInstructionsInBlock(BB, LibInfo);
    }
  }

  // Clean up the handler action maps we created for this function
  DeleteContainerSeconds(CatchHandlerMap);
  CatchHandlerMap.clear();
  DeleteContainerSeconds(CleanupHandlerMap);
  CleanupHandlerMap.clear();
  HandlerToParentFP.clear();
  DT = nullptr;
  LibInfo = nullptr;
  SEHExceptionCodeSlot = nullptr;
  EHBlocks.clear();
  NormalBlocks.clear();
  EHReturnBlocks.clear();

  return HandlersOutlined;
}

void WinEHPrepare::promoteLandingPadValues(LandingPadInst *LPad) {
  // If the return values of the landing pad instruction are extracted and
  // stored to memory, we want to promote the store locations to reg values.
  SmallVector<AllocaInst *, 2> EHAllocas;

  // The landingpad instruction returns an aggregate value.  Typically, its
  // value will be passed to a pair of extract value instructions and the
  // results of those extracts are often passed to store instructions.
  // In unoptimized code the stored value will often be loaded and then stored
  // again.
  for (auto *U : LPad->users()) {
    ExtractValueInst *Extract = dyn_cast<ExtractValueInst>(U);
    if (!Extract)
      continue;

    for (auto *EU : Extract->users()) {
      if (auto *Store = dyn_cast<StoreInst>(EU)) {
        auto *AV = cast<AllocaInst>(Store->getPointerOperand());
        EHAllocas.push_back(AV);
      }
    }
  }

  // We can't do this without a dominator tree.
  assert(DT);

  if (!EHAllocas.empty()) {
    PromoteMemToReg(EHAllocas, *DT);
    EHAllocas.clear();
  }

  // After promotion, some extracts may be trivially dead. Remove them.
  SmallVector<Value *, 4> Users(LPad->user_begin(), LPad->user_end());
  for (auto *U : Users)
    RecursivelyDeleteTriviallyDeadInstructions(U);
}

void WinEHPrepare::getPossibleReturnTargets(Function *ParentF,
                                            Function *HandlerF,
                                            SetVector<BasicBlock*> &Targets) {
  for (BasicBlock &BB : *HandlerF) {
    // If the handler contains landing pads, check for any
    // handlers that may return directly to a block in the
    // parent function.
    if (auto *LPI = BB.getLandingPadInst()) {
      IntrinsicInst *Recover = cast<IntrinsicInst>(LPI->getNextNode());
      SmallVector<std::unique_ptr<ActionHandler>, 4> ActionList;
      parseEHActions(Recover, ActionList);
      for (const auto &Action : ActionList) {
        if (auto *CH = dyn_cast<CatchHandler>(Action.get())) {
          Function *NestedF = cast<Function>(CH->getHandlerBlockOrFunc());
          getPossibleReturnTargets(ParentF, NestedF, Targets);
        }
      }
    }

    auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator());
    if (!Ret)
      continue;

    // Handler functions must always return a block address.
    BlockAddress *BA = cast<BlockAddress>(Ret->getReturnValue());

    // If this is the handler for a nested landing pad, the
    // return address may have been remapped to a block in the
    // parent handler.  We're not interested in those.
    if (BA->getFunction() != ParentF)
      continue;

    Targets.insert(BA->getBasicBlock());
  }
}

void WinEHPrepare::completeNestedLandingPad(Function *ParentFn,
                                            LandingPadInst *OutlinedLPad,
                                            const LandingPadInst *OriginalLPad,
                                            FrameVarInfoMap &FrameVarInfo) {
  // Get the nested block and erase the unreachable instruction that was
  // temporarily inserted as its terminator.
  LLVMContext &Context = ParentFn->getContext();
  BasicBlock *OutlinedBB = OutlinedLPad->getParent();
  // If the nested landing pad was outlined before the landing pad that enclosed
  // it, it will already be in outlined form.  In that case, we just need to see
  // if the returns and the enclosing branch instruction need to be updated.
  IndirectBrInst *Branch =
      dyn_cast<IndirectBrInst>(OutlinedBB->getTerminator());
  if (!Branch) {
    // If the landing pad wasn't in outlined form, it should be a stub with
    // an unreachable terminator.
    assert(isa<UnreachableInst>(OutlinedBB->getTerminator()));
    OutlinedBB->getTerminator()->eraseFromParent();
    // That should leave OutlinedLPad as the last instruction in its block.
    assert(&OutlinedBB->back() == OutlinedLPad);
  }

  // The original landing pad will have already had its action intrinsic
  // built by the outlining loop.  We need to clone that into the outlined
  // location.  It may also be necessary to add references to the exception
  // variables to the outlined handler in which this landing pad is nested
  // and remap return instructions in the nested handlers that should return
  // to an address in the outlined handler.
  Function *OutlinedHandlerFn = OutlinedBB->getParent();
  BasicBlock::const_iterator II = OriginalLPad;
  ++II;
  // The instruction after the landing pad should now be a call to eh.actions.
  const Instruction *Recover = II;
  const IntrinsicInst *EHActions = cast<IntrinsicInst>(Recover);

  // Remap the return target in the nested handler.
  SmallVector<BlockAddress *, 4> ActionTargets;
  SmallVector<std::unique_ptr<ActionHandler>, 4> ActionList;
  parseEHActions(EHActions, ActionList);
  for (const auto &Action : ActionList) {
    auto *Catch = dyn_cast<CatchHandler>(Action.get());
    if (!Catch)
      continue;
    // The dyn_cast to function here selects C++ catch handlers and skips
    // SEH catch handlers.
    auto *Handler = dyn_cast<Function>(Catch->getHandlerBlockOrFunc());
    if (!Handler)
      continue;
    // Visit all the return instructions, looking for places that return
    // to a location within OutlinedHandlerFn.
    for (BasicBlock &NestedHandlerBB : *Handler) {
      auto *Ret = dyn_cast<ReturnInst>(NestedHandlerBB.getTerminator());
      if (!Ret)
        continue;

      // Handler functions must always return a block address.
      BlockAddress *BA = cast<BlockAddress>(Ret->getReturnValue());
      // The original target will have been in the main parent function,
      // but if it is the address of a block that has been outlined, it
      // should be a block that was outlined into OutlinedHandlerFn.
      assert(BA->getFunction() == ParentFn);

      // Ignore targets that aren't part of an outlined handler function.
      if (!LPadTargetBlocks.count(BA->getBasicBlock()))
        continue;

      // If the return value is the address ofF a block that we
      // previously outlined into the parent handler function, replace
      // the return instruction and add the mapped target to the list
      // of possible return addresses.
      BasicBlock *MappedBB = LPadTargetBlocks[BA->getBasicBlock()];
      assert(MappedBB->getParent() == OutlinedHandlerFn);
      BlockAddress *NewBA = BlockAddress::get(OutlinedHandlerFn, MappedBB);
      Ret->eraseFromParent();
      ReturnInst::Create(Context, NewBA, &NestedHandlerBB);
      ActionTargets.push_back(NewBA);
    }
  }
  ActionList.clear();

  if (Branch) {
    // If the landing pad was already in outlined form, just update its targets.
    for (unsigned int I = Branch->getNumDestinations(); I > 0; --I)
      Branch->removeDestination(I);
    // Add the previously collected action targets.
    for (auto *Target : ActionTargets)
      Branch->addDestination(Target->getBasicBlock());
  } else {
    // If the landing pad was previously stubbed out, fill in its outlined form.
    IntrinsicInst *NewEHActions = cast<IntrinsicInst>(EHActions->clone());
    OutlinedBB->getInstList().push_back(NewEHActions);

    // Insert an indirect branch into the outlined landing pad BB.
    IndirectBrInst *IBr = IndirectBrInst::Create(NewEHActions, 0, OutlinedBB);
    // Add the previously collected action targets.
    for (auto *Target : ActionTargets)
      IBr->addDestination(Target->getBasicBlock());
  }
}

// This function examines a block to determine whether the block ends with a
// conditional branch to a catch handler based on a selector comparison.
// This function is used both by the WinEHPrepare::findSelectorComparison() and
// WinEHCleanupDirector::handleTypeIdFor().
static bool isSelectorDispatch(BasicBlock *BB, BasicBlock *&CatchHandler,
                               Constant *&Selector, BasicBlock *&NextBB) {
  ICmpInst::Predicate Pred;
  BasicBlock *TBB, *FBB;
  Value *LHS, *RHS;

  if (!match(BB->getTerminator(),
             m_Br(m_ICmp(Pred, m_Value(LHS), m_Value(RHS)), TBB, FBB)))
    return false;

  if (!match(LHS,
             m_Intrinsic<Intrinsic::eh_typeid_for>(m_Constant(Selector))) &&
      !match(RHS, m_Intrinsic<Intrinsic::eh_typeid_for>(m_Constant(Selector))))
    return false;

  if (Pred == CmpInst::ICMP_EQ) {
    CatchHandler = TBB;
    NextBB = FBB;
    return true;
  }

  if (Pred == CmpInst::ICMP_NE) {
    CatchHandler = FBB;
    NextBB = TBB;
    return true;
  }

  return false;
}

static bool isCatchBlock(BasicBlock *BB) {
  for (BasicBlock::iterator II = BB->getFirstNonPHIOrDbg(), IE = BB->end();
       II != IE; ++II) {
    if (match(cast<Value>(II), m_Intrinsic<Intrinsic::eh_begincatch>()))
      return true;
  }
  return false;
}

static BasicBlock *createStubLandingPad(Function *Handler) {
  // FIXME: Finish this!
  LLVMContext &Context = Handler->getContext();
  BasicBlock *StubBB = BasicBlock::Create(Context, "stub");
  Handler->getBasicBlockList().push_back(StubBB);
  IRBuilder<> Builder(StubBB);
  LandingPadInst *LPad = Builder.CreateLandingPad(
      llvm::StructType::get(Type::getInt8PtrTy(Context),
                            Type::getInt32Ty(Context), nullptr),
      0);
  // Insert a call to llvm.eh.actions so that we don't try to outline this lpad.
  Function *ActionIntrin =
      Intrinsic::getDeclaration(Handler->getParent(), Intrinsic::eh_actions);
  Builder.CreateCall(ActionIntrin, {}, "recover");
  LPad->setCleanup(true);
  Builder.CreateUnreachable();
  return StubBB;
}

// Cycles through the blocks in an outlined handler function looking for an
// invoke instruction and inserts an invoke of llvm.donothing with an empty
// landing pad if none is found.  The code that generates the .xdata tables for
// the handler needs at least one landing pad to identify the parent function's
// personality.
void WinEHPrepare::addStubInvokeToHandlerIfNeeded(Function *Handler) {
  ReturnInst *Ret = nullptr;
  UnreachableInst *Unreached = nullptr;
  for (BasicBlock &BB : *Handler) {
    TerminatorInst *Terminator = BB.getTerminator();
    // If we find an invoke, there is nothing to be done.
    auto *II = dyn_cast<InvokeInst>(Terminator);
    if (II)
      return;
    // If we've already recorded a return instruction, keep looking for invokes.
    if (!Ret)
      Ret = dyn_cast<ReturnInst>(Terminator);
    // If we haven't recorded an unreachable instruction, try this terminator.
    if (!Unreached)
      Unreached = dyn_cast<UnreachableInst>(Terminator);
  }

  // If we got this far, the handler contains no invokes.  We should have seen
  // at least one return or unreachable instruction.  We'll insert an invoke of
  // llvm.donothing ahead of that instruction.
  assert(Ret || Unreached);
  TerminatorInst *Term;
  if (Ret)
    Term = Ret;
  else
    Term = Unreached;
  BasicBlock *OldRetBB = Term->getParent();
  BasicBlock *NewRetBB = SplitBlock(OldRetBB, Term, DT);
  // SplitBlock adds an unconditional branch instruction at the end of the
  // parent block.  We want to replace that with an invoke call, so we can
  // erase it now.
  OldRetBB->getTerminator()->eraseFromParent();
  BasicBlock *StubLandingPad = createStubLandingPad(Handler);
  Function *F =
      Intrinsic::getDeclaration(Handler->getParent(), Intrinsic::donothing);
  InvokeInst::Create(F, NewRetBB, StubLandingPad, None, "", OldRetBB);
}

// FIXME: Consider sinking this into lib/Target/X86 somehow. TargetLowering
// usually doesn't build LLVM IR, so that's probably the wrong place.
Function *WinEHPrepare::createHandlerFunc(Type *RetTy, const Twine &Name,
                                          Module *M, Value *&ParentFP) {
  // x64 uses a two-argument prototype where the parent FP is the second
  // argument. x86 uses no arguments, just the incoming EBP value.
  LLVMContext &Context = M->getContext();
  FunctionType *FnType;
  if (TheTriple.getArch() == Triple::x86_64) {
    Type *Int8PtrType = Type::getInt8PtrTy(Context);
    Type *ArgTys[2] = {Int8PtrType, Int8PtrType};
    FnType = FunctionType::get(RetTy, ArgTys, false);
  } else {
    FnType = FunctionType::get(RetTy, None, false);
  }

  Function *Handler =
      Function::Create(FnType, GlobalVariable::InternalLinkage, Name, M);
  BasicBlock *Entry = BasicBlock::Create(Context, "entry");
  Handler->getBasicBlockList().push_front(Entry);
  if (TheTriple.getArch() == Triple::x86_64) {
    ParentFP = &(Handler->getArgumentList().back());
  } else {
    assert(M);
    Function *FrameAddressFn =
        Intrinsic::getDeclaration(M, Intrinsic::frameaddress);
    Value *Args[1] = {ConstantInt::get(Type::getInt32Ty(Context), 1)};
    ParentFP = CallInst::Create(FrameAddressFn, Args, "parent_fp",
                                &Handler->getEntryBlock());
  }
  return Handler;
}

bool WinEHPrepare::outlineHandler(ActionHandler *Action, Function *SrcFn,
                                  LandingPadInst *LPad, BasicBlock *StartBB,
                                  FrameVarInfoMap &VarInfo) {
  Module *M = SrcFn->getParent();
  LLVMContext &Context = M->getContext();
  Type *Int8PtrType = Type::getInt8PtrTy(Context);

  // Create a new function to receive the handler contents.
  Value *ParentFP;
  Function *Handler;
  if (Action->getType() == Catch) {
    Handler = createHandlerFunc(Int8PtrType, SrcFn->getName() + ".catch", M,
                                ParentFP);
  } else {
    Handler = createHandlerFunc(Type::getVoidTy(Context),
                                SrcFn->getName() + ".cleanup", M, ParentFP);
  }
  Handler->setPersonalityFn(SrcFn->getPersonalityFn());
  HandlerToParentFP[Handler] = ParentFP;
  Handler->addFnAttr("wineh-parent", SrcFn->getName());
  BasicBlock *Entry = &Handler->getEntryBlock();

  // Generate a standard prolog to setup the frame recovery structure.
  IRBuilder<> Builder(Context);
  Builder.SetInsertPoint(Entry);
  Builder.SetCurrentDebugLocation(LPad->getDebugLoc());

  std::unique_ptr<WinEHCloningDirectorBase> Director;

  ValueToValueMapTy VMap;

  LandingPadMap &LPadMap = LPadMaps[LPad];
  if (!LPadMap.isInitialized())
    LPadMap.mapLandingPad(LPad);
  if (auto *CatchAction = dyn_cast<CatchHandler>(Action)) {
    Constant *Sel = CatchAction->getSelector();
    Director.reset(new WinEHCatchDirector(Handler, ParentFP, Sel, VarInfo,
                                          LPadMap, NestedLPtoOriginalLP, DT,
                                          EHBlocks));
    LPadMap.remapEHValues(VMap, UndefValue::get(Int8PtrType),
                          ConstantInt::get(Type::getInt32Ty(Context), 1));
  } else {
    Director.reset(
        new WinEHCleanupDirector(Handler, ParentFP, VarInfo, LPadMap));
    LPadMap.remapEHValues(VMap, UndefValue::get(Int8PtrType),
                          UndefValue::get(Type::getInt32Ty(Context)));
  }

  SmallVector<ReturnInst *, 8> Returns;
  ClonedCodeInfo OutlinedFunctionInfo;

  // If the start block contains PHI nodes, we need to map them.
  BasicBlock::iterator II = StartBB->begin();
  while (auto *PN = dyn_cast<PHINode>(II)) {
    bool Mapped = false;
    // Look for PHI values that we have already mapped (such as the selector).
    for (Value *Val : PN->incoming_values()) {
      if (VMap.count(Val)) {
        VMap[PN] = VMap[Val];
        Mapped = true;
      }
    }
    // If we didn't find a match for this value, map it as an undef.
    if (!Mapped) {
      VMap[PN] = UndefValue::get(PN->getType());
    }
    ++II;
  }

  // The landing pad value may be used by PHI nodes.  It will ultimately be
  // eliminated, but we need it in the map for intermediate handling.
  VMap[LPad] = UndefValue::get(LPad->getType());

  // Skip over PHIs and, if applicable, landingpad instructions.
  II = StartBB->getFirstInsertionPt();

  CloneAndPruneIntoFromInst(Handler, SrcFn, II, VMap,
                            /*ModuleLevelChanges=*/false, Returns, "",
                            &OutlinedFunctionInfo, Director.get());

  // Move all the instructions in the cloned "entry" block into our entry block.
  // Depending on how the parent function was laid out, the block that will
  // correspond to the outlined entry block may not be the first block in the
  // list.  We can recognize it, however, as the cloned block which has no
  // predecessors.  Any other block wouldn't have been cloned if it didn't
  // have a predecessor which was also cloned.
  Function::iterator ClonedIt = std::next(Function::iterator(Entry));
  while (!pred_empty(ClonedIt))
    ++ClonedIt;
  BasicBlock *ClonedEntryBB = ClonedIt;
  assert(ClonedEntryBB);
  Entry->getInstList().splice(Entry->end(), ClonedEntryBB->getInstList());
  ClonedEntryBB->eraseFromParent();

  // Make sure we can identify the handler's personality later.
  addStubInvokeToHandlerIfNeeded(Handler);

  if (auto *CatchAction = dyn_cast<CatchHandler>(Action)) {
    WinEHCatchDirector *CatchDirector =
        reinterpret_cast<WinEHCatchDirector *>(Director.get());
    CatchAction->setExceptionVar(CatchDirector->getExceptionVar());
    CatchAction->setReturnTargets(CatchDirector->getReturnTargets());

    // Look for blocks that are not part of the landing pad that we just
    // outlined but terminate with a call to llvm.eh.endcatch and a
    // branch to a block that is in the handler we just outlined.
    // These blocks will be part of a nested landing pad that intends to
    // return to an address in this handler.  This case is best handled
    // after both landing pads have been outlined, so for now we'll just
    // save the association of the blocks in LPadTargetBlocks.  The
    // return instructions which are created from these branches will be
    // replaced after all landing pads have been outlined.
    for (const auto MapEntry : VMap) {
      // VMap maps all values and blocks that were just cloned, but dead
      // blocks which were pruned will map to nullptr.
      if (!isa<BasicBlock>(MapEntry.first) || MapEntry.second == nullptr)
        continue;
      const BasicBlock *MappedBB = cast<BasicBlock>(MapEntry.first);
      for (auto *Pred : predecessors(const_cast<BasicBlock *>(MappedBB))) {
        auto *Branch = dyn_cast<BranchInst>(Pred->getTerminator());
        if (!Branch || !Branch->isUnconditional() || Pred->size() <= 1)
          continue;
        BasicBlock::iterator II = const_cast<BranchInst *>(Branch);
        --II;
        if (match(cast<Value>(II), m_Intrinsic<Intrinsic::eh_endcatch>())) {
          // This would indicate that a nested landing pad wants to return
          // to a block that is outlined into two different handlers.
          assert(!LPadTargetBlocks.count(MappedBB));
          LPadTargetBlocks[MappedBB] = cast<BasicBlock>(MapEntry.second);
        }
      }
    }
  } // End if (CatchAction)

  Action->setHandlerBlockOrFunc(Handler);

  return true;
}

/// This BB must end in a selector dispatch. All we need to do is pass the
/// handler block to llvm.eh.actions and list it as a possible indirectbr
/// target.
void WinEHPrepare::processSEHCatchHandler(CatchHandler *CatchAction,
                                          BasicBlock *StartBB) {
  BasicBlock *HandlerBB;
  BasicBlock *NextBB;
  Constant *Selector;
  bool Res = isSelectorDispatch(StartBB, HandlerBB, Selector, NextBB);
  if (Res) {
    // If this was EH dispatch, this must be a conditional branch to the handler
    // block.
    // FIXME: Handle instructions in the dispatch block. Currently we drop them,
    // leading to crashes if some optimization hoists stuff here.
    assert(CatchAction->getSelector() && HandlerBB &&
           "expected catch EH dispatch");
  } else {
    // This must be a catch-all. Split the block after the landingpad.
    assert(CatchAction->getSelector()->isNullValue() && "expected catch-all");
    HandlerBB = SplitBlock(StartBB, StartBB->getFirstInsertionPt(), DT);
  }
  IRBuilder<> Builder(HandlerBB->getFirstInsertionPt());
  Function *EHCodeFn = Intrinsic::getDeclaration(
      StartBB->getParent()->getParent(), Intrinsic::eh_exceptioncode);
  Value *Code = Builder.CreateCall(EHCodeFn, {}, "sehcode");
  Code = Builder.CreateIntToPtr(Code, SEHExceptionCodeSlot->getAllocatedType());
  Builder.CreateStore(Code, SEHExceptionCodeSlot);
  CatchAction->setHandlerBlockOrFunc(BlockAddress::get(HandlerBB));
  TinyPtrVector<BasicBlock *> Targets(HandlerBB);
  CatchAction->setReturnTargets(Targets);
}

void LandingPadMap::mapLandingPad(const LandingPadInst *LPad) {
  // Each instance of this class should only ever be used to map a single
  // landing pad.
  assert(OriginLPad == nullptr || OriginLPad == LPad);

  // If the landing pad has already been mapped, there's nothing more to do.
  if (OriginLPad == LPad)
    return;

  OriginLPad = LPad;

  // The landingpad instruction returns an aggregate value.  Typically, its
  // value will be passed to a pair of extract value instructions and the
  // results of those extracts will have been promoted to reg values before
  // this routine is called.
  for (auto *U : LPad->users()) {
    const ExtractValueInst *Extract = dyn_cast<ExtractValueInst>(U);
    if (!Extract)
      continue;
    assert(Extract->getNumIndices() == 1 &&
           "Unexpected operation: extracting both landing pad values");
    unsigned int Idx = *(Extract->idx_begin());
    assert((Idx == 0 || Idx == 1) &&
           "Unexpected operation: extracting an unknown landing pad element");
    if (Idx == 0) {
      ExtractedEHPtrs.push_back(Extract);
    } else if (Idx == 1) {
      ExtractedSelectors.push_back(Extract);
    }
  }
}

bool LandingPadMap::isOriginLandingPadBlock(const BasicBlock *BB) const {
  return BB->getLandingPadInst() == OriginLPad;
}

bool LandingPadMap::isLandingPadSpecificInst(const Instruction *Inst) const {
  if (Inst == OriginLPad)
    return true;
  for (auto *Extract : ExtractedEHPtrs) {
    if (Inst == Extract)
      return true;
  }
  for (auto *Extract : ExtractedSelectors) {
    if (Inst == Extract)
      return true;
  }
  return false;
}

void LandingPadMap::remapEHValues(ValueToValueMapTy &VMap, Value *EHPtrValue,
                                  Value *SelectorValue) const {
  // Remap all landing pad extract instructions to the specified values.
  for (auto *Extract : ExtractedEHPtrs)
    VMap[Extract] = EHPtrValue;
  for (auto *Extract : ExtractedSelectors)
    VMap[Extract] = SelectorValue;
}

static bool isFrameAddressCall(const Value *V) {
  return match(const_cast<Value *>(V),
               m_Intrinsic<Intrinsic::frameaddress>(m_SpecificInt(0)));
}

CloningDirector::CloningAction WinEHCloningDirectorBase::handleInstruction(
    ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) {
  // If this is one of the boilerplate landing pad instructions, skip it.
  // The instruction will have already been remapped in VMap.
  if (LPadMap.isLandingPadSpecificInst(Inst))
    return CloningDirector::SkipInstruction;

  // Nested landing pads that have not already been outlined will be cloned as
  // stubs, with just the landingpad instruction and an unreachable instruction.
  // When all landingpads have been outlined, we'll replace this with the
  // llvm.eh.actions call and indirect branch created when the landing pad was
  // outlined.
  if (auto *LPad = dyn_cast<LandingPadInst>(Inst)) {
    return handleLandingPad(VMap, LPad, NewBB);
  }

  // Nested landing pads that have already been outlined will be cloned in their
  // outlined form, but we need to intercept the ibr instruction to filter out
  // targets that do not return to the handler we are outlining.
  if (auto *IBr = dyn_cast<IndirectBrInst>(Inst)) {
    return handleIndirectBr(VMap, IBr, NewBB);
  }

  if (auto *Invoke = dyn_cast<InvokeInst>(Inst))
    return handleInvoke(VMap, Invoke, NewBB);

  if (auto *Resume = dyn_cast<ResumeInst>(Inst))
    return handleResume(VMap, Resume, NewBB);

  if (auto *Cmp = dyn_cast<CmpInst>(Inst))
    return handleCompare(VMap, Cmp, NewBB);

  if (match(Inst, m_Intrinsic<Intrinsic::eh_begincatch>()))
    return handleBeginCatch(VMap, Inst, NewBB);
  if (match(Inst, m_Intrinsic<Intrinsic::eh_endcatch>()))
    return handleEndCatch(VMap, Inst, NewBB);
  if (match(Inst, m_Intrinsic<Intrinsic::eh_typeid_for>()))
    return handleTypeIdFor(VMap, Inst, NewBB);

  // When outlining llvm.frameaddress(i32 0), remap that to the second argument,
  // which is the FP of the parent.
  if (isFrameAddressCall(Inst)) {
    VMap[Inst] = ParentFP;
    return CloningDirector::SkipInstruction;
  }

  // Continue with the default cloning behavior.
  return CloningDirector::CloneInstruction;
}

CloningDirector::CloningAction WinEHCatchDirector::handleLandingPad(
    ValueToValueMapTy &VMap, const LandingPadInst *LPad, BasicBlock *NewBB) {
  // If the instruction after the landing pad is a call to llvm.eh.actions
  // the landing pad has already been outlined.  In this case, we should
  // clone it because it may return to a block in the handler we are
  // outlining now that would otherwise be unreachable.  The landing pads
  // are sorted before outlining begins to enable this case to work
  // properly.
  const Instruction *NextI = LPad->getNextNode();
  if (match(NextI, m_Intrinsic<Intrinsic::eh_actions>()))
    return CloningDirector::CloneInstruction;

  // If the landing pad hasn't been outlined yet, the landing pad we are
  // outlining now does not dominate it and so it cannot return to a block
  // in this handler.  In that case, we can just insert a stub landing
  // pad now and patch it up later.
  Instruction *NewInst = LPad->clone();
  if (LPad->hasName())
    NewInst->setName(LPad->getName());
  // Save this correlation for later processing.
  NestedLPtoOriginalLP[cast<LandingPadInst>(NewInst)] = LPad;
  VMap[LPad] = NewInst;
  BasicBlock::InstListType &InstList = NewBB->getInstList();
  InstList.push_back(NewInst);
  InstList.push_back(new UnreachableInst(NewBB->getContext()));
  return CloningDirector::StopCloningBB;
}

CloningDirector::CloningAction WinEHCatchDirector::handleBeginCatch(
    ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) {
  // The argument to the call is some form of the first element of the
  // landingpad aggregate value, but that doesn't matter.  It isn't used
  // here.
  // The second argument is an outparameter where the exception object will be
  // stored. Typically the exception object is a scalar, but it can be an
  // aggregate when catching by value.
  // FIXME: Leave something behind to indicate where the exception object lives
  // for this handler. Should it be part of llvm.eh.actions?
  assert(ExceptionObjectVar == nullptr && "Multiple calls to "
                                          "llvm.eh.begincatch found while "
                                          "outlining catch handler.");
  ExceptionObjectVar = Inst->getOperand(1)->stripPointerCasts();
  if (isa<ConstantPointerNull>(ExceptionObjectVar))
    return CloningDirector::SkipInstruction;
  assert(cast<AllocaInst>(ExceptionObjectVar)->isStaticAlloca() &&
         "catch parameter is not static alloca");
  Materializer.escapeCatchObject(ExceptionObjectVar);
  return CloningDirector::SkipInstruction;
}

CloningDirector::CloningAction
WinEHCatchDirector::handleEndCatch(ValueToValueMapTy &VMap,
                                   const Instruction *Inst, BasicBlock *NewBB) {
  auto *IntrinCall = dyn_cast<IntrinsicInst>(Inst);
  // It might be interesting to track whether or not we are inside a catch
  // function, but that might make the algorithm more brittle than it needs
  // to be.

  // The end catch call can occur in one of two places: either in a
  // landingpad block that is part of the catch handlers exception mechanism,
  // or at the end of the catch block.  However, a catch-all handler may call
  // end catch from the original landing pad.  If the call occurs in a nested
  // landing pad block, we must skip it and continue so that the landing pad
  // gets cloned.
  auto *ParentBB = IntrinCall->getParent();
  if (ParentBB->isLandingPad() && !LPadMap.isOriginLandingPadBlock(ParentBB))
    return CloningDirector::SkipInstruction;

  // If an end catch occurs anywhere else we want to terminate the handler
  // with a return to the code that follows the endcatch call.  If the
  // next instruction is not an unconditional branch, we need to split the
  // block to provide a clear target for the return instruction.
  BasicBlock *ContinueBB;
  auto Next = std::next(BasicBlock::const_iterator(IntrinCall));
  const BranchInst *Branch = dyn_cast<BranchInst>(Next);
  if (!Branch || !Branch->isUnconditional()) {
    // We're interrupting the cloning process at this location, so the
    // const_cast we're doing here will not cause a problem.
    ContinueBB = SplitBlock(const_cast<BasicBlock *>(ParentBB),
                            const_cast<Instruction *>(cast<Instruction>(Next)));
  } else {
    ContinueBB = Branch->getSuccessor(0);
  }

  ReturnInst::Create(NewBB->getContext(), BlockAddress::get(ContinueBB), NewBB);
  ReturnTargets.push_back(ContinueBB);

  // We just added a terminator to the cloned block.
  // Tell the caller to stop processing the current basic block so that
  // the branch instruction will be skipped.
  return CloningDirector::StopCloningBB;
}

CloningDirector::CloningAction WinEHCatchDirector::handleTypeIdFor(
    ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) {
  auto *IntrinCall = dyn_cast<IntrinsicInst>(Inst);
  Value *Selector = IntrinCall->getArgOperand(0)->stripPointerCasts();
  // This causes a replacement that will collapse the landing pad CFG based
  // on the filter function we intend to match.
  if (Selector == CurrentSelector)
    VMap[Inst] = ConstantInt::get(SelectorIDType, 1);
  else
    VMap[Inst] = ConstantInt::get(SelectorIDType, 0);
  // Tell the caller not to clone this instruction.
  return CloningDirector::SkipInstruction;
}

CloningDirector::CloningAction WinEHCatchDirector::handleIndirectBr(
    ValueToValueMapTy &VMap,
    const IndirectBrInst *IBr,
    BasicBlock *NewBB) {
  // If this indirect branch is not part of a landing pad block, just clone it.
  const BasicBlock *ParentBB = IBr->getParent();
  if (!ParentBB->isLandingPad())
    return CloningDirector::CloneInstruction;

  // If it is part of a landing pad, we want to filter out target blocks
  // that are not part of the handler we are outlining.
  const LandingPadInst *LPad = ParentBB->getLandingPadInst();

  // Save this correlation for later processing.
  NestedLPtoOriginalLP[cast<LandingPadInst>(VMap[LPad])] = LPad;

  // We should only get here for landing pads that have already been outlined.
  assert(match(LPad->getNextNode(), m_Intrinsic<Intrinsic::eh_actions>()));

  // Copy the indirectbr, but only include targets that were previously
  // identified as EH blocks and are dominated by the nested landing pad.
  SetVector<const BasicBlock *> ReturnTargets;
  for (int I = 0, E = IBr->getNumDestinations(); I < E; ++I) {
    auto *TargetBB = IBr->getDestination(I);
    if (EHBlocks.count(const_cast<BasicBlock*>(TargetBB)) &&
        DT->dominates(ParentBB, TargetBB)) {
      DEBUG(dbgs() << "  Adding destination " << TargetBB->getName() << "\n");
      ReturnTargets.insert(TargetBB);
    }
  }
  IndirectBrInst *NewBranch = 
        IndirectBrInst::Create(const_cast<Value *>(IBr->getAddress()),
                               ReturnTargets.size(), NewBB);
  for (auto *Target : ReturnTargets)
    NewBranch->addDestination(const_cast<BasicBlock*>(Target));

  // The operands and targets of the branch instruction are remapped later
  // because it is a terminator.  Tell the cloning code to clone the
  // blocks we just added to the target list.
  return CloningDirector::CloneSuccessors;
}

CloningDirector::CloningAction
WinEHCatchDirector::handleInvoke(ValueToValueMapTy &VMap,
                                 const InvokeInst *Invoke, BasicBlock *NewBB) {
  return CloningDirector::CloneInstruction;
}

CloningDirector::CloningAction
WinEHCatchDirector::handleResume(ValueToValueMapTy &VMap,
                                 const ResumeInst *Resume, BasicBlock *NewBB) {
  // Resume instructions shouldn't be reachable from catch handlers.
  // We still need to handle it, but it will be pruned.
  BasicBlock::InstListType &InstList = NewBB->getInstList();
  InstList.push_back(new UnreachableInst(NewBB->getContext()));
  return CloningDirector::StopCloningBB;
}

CloningDirector::CloningAction
WinEHCatchDirector::handleCompare(ValueToValueMapTy &VMap,
                                  const CmpInst *Compare, BasicBlock *NewBB) {
  const IntrinsicInst *IntrinCall = nullptr;
  if (match(Compare->getOperand(0), m_Intrinsic<Intrinsic::eh_typeid_for>())) {
    IntrinCall = dyn_cast<IntrinsicInst>(Compare->getOperand(0));
  } else if (match(Compare->getOperand(1),
                   m_Intrinsic<Intrinsic::eh_typeid_for>())) {
    IntrinCall = dyn_cast<IntrinsicInst>(Compare->getOperand(1));
  }
  if (IntrinCall) {
    Value *Selector = IntrinCall->getArgOperand(0)->stripPointerCasts();
    // This causes a replacement that will collapse the landing pad CFG based
    // on the filter function we intend to match.
    if (Selector == CurrentSelector->stripPointerCasts()) {
      VMap[Compare] = ConstantInt::get(SelectorIDType, 1);
    } else {
      VMap[Compare] = ConstantInt::get(SelectorIDType, 0);
    }
    return CloningDirector::SkipInstruction;
  }
  return CloningDirector::CloneInstruction;
}

CloningDirector::CloningAction WinEHCleanupDirector::handleLandingPad(
    ValueToValueMapTy &VMap, const LandingPadInst *LPad, BasicBlock *NewBB) {
  // The MS runtime will terminate the process if an exception occurs in a
  // cleanup handler, so we shouldn't encounter landing pads in the actual
  // cleanup code, but they may appear in catch blocks.  Depending on where
  // we started cloning we may see one, but it will get dropped during dead
  // block pruning.
  Instruction *NewInst = new UnreachableInst(NewBB->getContext());
  VMap[LPad] = NewInst;
  BasicBlock::InstListType &InstList = NewBB->getInstList();
  InstList.push_back(NewInst);
  return CloningDirector::StopCloningBB;
}

CloningDirector::CloningAction WinEHCleanupDirector::handleBeginCatch(
    ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) {
  // Cleanup code may flow into catch blocks or the catch block may be part
  // of a branch that will be optimized away.  We'll insert a return
  // instruction now, but it may be pruned before the cloning process is
  // complete.
  ReturnInst::Create(NewBB->getContext(), nullptr, NewBB);
  return CloningDirector::StopCloningBB;
}

CloningDirector::CloningAction WinEHCleanupDirector::handleEndCatch(
    ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) {
  // Cleanup handlers nested within catch handlers may begin with a call to
  // eh.endcatch.  We can just ignore that instruction.
  return CloningDirector::SkipInstruction;
}

CloningDirector::CloningAction WinEHCleanupDirector::handleTypeIdFor(
    ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) {
  // If we encounter a selector comparison while cloning a cleanup handler,
  // we want to stop cloning immediately.  Anything after the dispatch
  // will be outlined into a different handler.
  BasicBlock *CatchHandler;
  Constant *Selector;
  BasicBlock *NextBB;
  if (isSelectorDispatch(const_cast<BasicBlock *>(Inst->getParent()),
                         CatchHandler, Selector, NextBB)) {
    ReturnInst::Create(NewBB->getContext(), nullptr, NewBB);
    return CloningDirector::StopCloningBB;
  }
  // If eg.typeid.for is called for any other reason, it can be ignored.
  VMap[Inst] = ConstantInt::get(SelectorIDType, 0);
  return CloningDirector::SkipInstruction;
}

CloningDirector::CloningAction WinEHCleanupDirector::handleIndirectBr(
    ValueToValueMapTy &VMap,
    const IndirectBrInst *IBr,
    BasicBlock *NewBB) {
  // No special handling is required for cleanup cloning.
  return CloningDirector::CloneInstruction;
}

CloningDirector::CloningAction WinEHCleanupDirector::handleInvoke(
    ValueToValueMapTy &VMap, const InvokeInst *Invoke, BasicBlock *NewBB) {
  // All invokes in cleanup handlers can be replaced with calls.
  SmallVector<Value *, 16> CallArgs(Invoke->op_begin(), Invoke->op_end() - 3);
  // Insert a normal call instruction...
  CallInst *NewCall =
      CallInst::Create(const_cast<Value *>(Invoke->getCalledValue()), CallArgs,
                       Invoke->getName(), NewBB);
  NewCall->setCallingConv(Invoke->getCallingConv());
  NewCall->setAttributes(Invoke->getAttributes());
  NewCall->setDebugLoc(Invoke->getDebugLoc());
  VMap[Invoke] = NewCall;

  // Remap the operands.
  llvm::RemapInstruction(NewCall, VMap, RF_None, nullptr, &Materializer);

  // Insert an unconditional branch to the normal destination.
  BranchInst::Create(Invoke->getNormalDest(), NewBB);

  // The unwind destination won't be cloned into the new function, so
  // we don't need to clean up its phi nodes.

  // We just added a terminator to the cloned block.
  // Tell the caller to stop processing the current basic block.
  return CloningDirector::CloneSuccessors;
}

CloningDirector::CloningAction WinEHCleanupDirector::handleResume(
    ValueToValueMapTy &VMap, const ResumeInst *Resume, BasicBlock *NewBB) {
  ReturnInst::Create(NewBB->getContext(), nullptr, NewBB);

  // We just added a terminator to the cloned block.
  // Tell the caller to stop processing the current basic block so that
  // the branch instruction will be skipped.
  return CloningDirector::StopCloningBB;
}

CloningDirector::CloningAction
WinEHCleanupDirector::handleCompare(ValueToValueMapTy &VMap,
                                    const CmpInst *Compare, BasicBlock *NewBB) {
  if (match(Compare->getOperand(0), m_Intrinsic<Intrinsic::eh_typeid_for>()) ||
      match(Compare->getOperand(1), m_Intrinsic<Intrinsic::eh_typeid_for>())) {
    VMap[Compare] = ConstantInt::get(SelectorIDType, 1);
    return CloningDirector::SkipInstruction;
  }
  return CloningDirector::CloneInstruction;
}

WinEHFrameVariableMaterializer::WinEHFrameVariableMaterializer(
    Function *OutlinedFn, Value *ParentFP, FrameVarInfoMap &FrameVarInfo)
    : FrameVarInfo(FrameVarInfo), Builder(OutlinedFn->getContext()) {
  BasicBlock *EntryBB = &OutlinedFn->getEntryBlock();

  // New allocas should be inserted in the entry block, but after the parent FP
  // is established if it is an instruction.
  Instruction *InsertPoint = EntryBB->getFirstInsertionPt();
  if (auto *FPInst = dyn_cast<Instruction>(ParentFP))
    InsertPoint = FPInst->getNextNode();
  Builder.SetInsertPoint(EntryBB, InsertPoint);
}

Value *WinEHFrameVariableMaterializer::materializeValueFor(Value *V) {
  // If we're asked to materialize a static alloca, we temporarily create an
  // alloca in the outlined function and add this to the FrameVarInfo map.  When
  // all the outlining is complete, we'll replace these temporary allocas with
  // calls to llvm.framerecover.
  if (auto *AV = dyn_cast<AllocaInst>(V)) {
    assert(AV->isStaticAlloca() &&
           "cannot materialize un-demoted dynamic alloca");
    AllocaInst *NewAlloca = dyn_cast<AllocaInst>(AV->clone());
    Builder.Insert(NewAlloca, AV->getName());
    FrameVarInfo[AV].push_back(NewAlloca);
    return NewAlloca;
  }

  if (isa<Instruction>(V) || isa<Argument>(V)) {
    Function *Parent = isa<Instruction>(V)
                           ? cast<Instruction>(V)->getParent()->getParent()
                           : cast<Argument>(V)->getParent();
    errs()
        << "Failed to demote instruction used in exception handler of function "
        << GlobalValue::getRealLinkageName(Parent->getName()) << ":\n";
    errs() << "  " << *V << '\n';
    report_fatal_error("WinEHPrepare failed to demote instruction");
  }

  // Don't materialize other values.
  return nullptr;
}

void WinEHFrameVariableMaterializer::escapeCatchObject(Value *V) {
  // Catch parameter objects have to live in the parent frame. When we see a use
  // of a catch parameter, add a sentinel to the multimap to indicate that it's
  // used from another handler. This will prevent us from trying to sink the
  // alloca into the handler and ensure that the catch parameter is present in
  // the call to llvm.frameescape.
  FrameVarInfo[V].push_back(getCatchObjectSentinel());
}

// 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) {
    findCleanupHandlers(Actions, BB, nullptr);
    return;
  }

  VisitedBlockSet VisitedBlocks;

  while (HandlersFound != NumClauses) {
    BasicBlock *NextBB = nullptr;

    // Skip over filter clauses.
    if (LPad->isFilter(HandlersFound)) {
      ++HandlersFound;
      continue;
    }

    // See if the clause we're looking for is a catch-all.
    // If so, the catch begins immediately.
    Constant *ExpectedSelector =
        LPad->getClause(HandlersFound)->stripPointerCasts();
    if (isa<ConstantPointerNull>(ExpectedSelector)) {
      // The catch all must occur last.
      assert(HandlersFound == NumClauses - 1);

      // There can be additional selector dispatches in the call chain that we
      // need to ignore.
      BasicBlock *CatchBlock = nullptr;
      Constant *Selector;
      while (BB && isSelectorDispatch(BB, CatchBlock, Selector, NextBB)) {
        DEBUG(dbgs() << "  Found extra catch dispatch in block "
                     << CatchBlock->getName() << "\n");
        BB = NextBB;
      }

      // Add the catch handler to the action list.
      CatchHandler *Action = nullptr;
      if (CatchHandlerMap.count(BB) && CatchHandlerMap[BB] != nullptr) {
        // If the CatchHandlerMap already has an entry for this BB, re-use it.
        Action = CatchHandlerMap[BB];
        assert(Action->getSelector() == ExpectedSelector);
      } else {
        // We don't expect a selector dispatch, but there may be a call to
        // llvm.eh.begincatch, which separates catch handling code from
        // cleanup code in the same control flow.  This call looks for the
        // begincatch intrinsic.
        Action = findCatchHandler(BB, NextBB, VisitedBlocks);
        if (Action) {
          // 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)
            findCleanupHandlers(Actions, BB, BB);
        } else {
          // If an action was not found, it means that the control flows
          // directly into the catch-all handler and there is no cleanup code.
          // That's an expected situation and we must create a catch action.
          // Since this is a catch-all handler, the selector won't actually
          // appear in the code anywhere.  ExpectedSelector here is the constant
          // null ptr that we got from the landing pad instruction.
          Action = new CatchHandler(BB, ExpectedSelector, 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);
    assert(CatchAction);

    // See if there is any interesting code executed before the dispatch.
    findCleanupHandlers(Actions, BB, CatchAction->getStartBlock());

    // When the source program contains multiple nested try blocks the catch
    // handlers can get strung together in such a way that we can encounter
    // a dispatch for a selector that we've already had a handler for.
    if (CatchAction->getSelector()->stripPointerCasts() == ExpectedSelector) {
      ++HandlersFound;

      // Add the catch handler to the action list.
      DEBUG(dbgs() << "  Found catch dispatch in block "
                   << CatchAction->getStartBlock()->getName() << "\n");
      Actions.insertCatchHandler(CatchAction);
    } else {
      // Under some circumstances optimized IR will flow unconditionally into a
      // handler block without checking the selector.  This can only happen if
      // the landing pad has a catch-all handler and the handler for the
      // preceeding catch clause is identical to the catch-call handler
      // (typically an empty catch).  In this case, the handler must be shared
      // by all remaining clauses.
      if (isa<ConstantPointerNull>(
              CatchAction->getSelector()->stripPointerCasts())) {
        DEBUG(dbgs() << "  Applying early catch-all handler in block "
                     << CatchAction->getStartBlock()->getName()
                     << "  to all remaining clauses.\n");
        Actions.insertCatchHandler(CatchAction);
        return;
      }

      DEBUG(dbgs() << "  Found extra 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.
  findCleanupHandlers(Actions, BB, BB);

  // 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;
    }
    // If we encounter a block containing an llvm.eh.begincatch before we
    // find a selector dispatch block, the handler is assumed to be
    // reached unconditionally.  This happens for catch-all blocks, but
    // it can also happen for other catch handlers that have been combined
    // with the catch-all handler during optimization.
    if (isCatchBlock(BB)) {
      PointerType *Int8PtrTy = Type::getInt8PtrTy(BB->getContext());
      Constant *NullSelector = ConstantPointerNull::get(Int8PtrTy);
      CatchHandler *Action = new CatchHandler(BB, NullSelector, nullptr);
      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 findCleanupHandlers.
static void createCleanupHandler(LandingPadActions &Actions,
                                 CleanupHandlerMapTy &CleanupHandlerMap,
                                 BasicBlock *BB) {
  CleanupHandler *Action = new CleanupHandler(BB);
  CleanupHandlerMap[BB] = Action;
  Actions.insertCleanupHandler(Action);
  DEBUG(dbgs() << "  Found cleanup code in block "
               << Action->getStartBlock()->getName() << "\n");
}

static CallSite matchOutlinedFinallyCall(BasicBlock *BB,
                                         Instruction *MaybeCall) {
  // Look for finally blocks that Clang has already outlined for us.
  //   %fp = call i8* @llvm.frameaddress(i32 0)
  //   call void @"fin$parent"(iN 1, i8* %fp)
  if (isFrameAddressCall(MaybeCall) && MaybeCall != BB->getTerminator())
    MaybeCall = MaybeCall->getNextNode();
  CallSite FinallyCall(MaybeCall);
  if (!FinallyCall || FinallyCall.arg_size() != 2)
    return CallSite();
  if (!match(FinallyCall.getArgument(0), m_SpecificInt(1)))
    return CallSite();
  if (!isFrameAddressCall(FinallyCall.getArgument(1)))
    return CallSite();
  return FinallyCall;
}

static BasicBlock *followSingleUnconditionalBranches(BasicBlock *BB) {
  // Skip single ubr blocks.
  while (BB->getFirstNonPHIOrDbg() == BB->getTerminator()) {
    auto *Br = dyn_cast<BranchInst>(BB->getTerminator());
    if (Br && Br->isUnconditional())
      BB = Br->getSuccessor(0);
    else
      return BB;
  }
  return BB;
}

// 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.
//
void WinEHPrepare::findCleanupHandlers(LandingPadActions &Actions,
                                       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) {
    BB = followSingleUnconditionalBranches(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]) {
        Actions.insertCleanupHandler(Action);
        DEBUG(dbgs() << "  Found cleanup code in block "
                     << Action->getStartBlock()->getName() << "\n");
        // FIXME: This cleanup might chain into another, and we need to discover
        // that.
        return;
      } 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 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.
        BasicBlock *SuccBB = followSingleUnconditionalBranches(BB);
        if (SuccBB == BB || SuccBB == EndBB)
          return;
        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 the resume value isn't a phi or landingpad value, it should be a
      // series of insertions. Identify them so we can avoid them when scanning
      // for cleanups.
      if (!isa<PHINode>(ResumeVal) && !isa<LandingPadInst>(ResumeVal)) {
        Insert2 = dyn_cast<InsertValueInst>(ResumeVal);
        if (!Insert2)
          return createCleanupHandler(Actions, CleanupHandlerMap, BB);
        Insert1 = dyn_cast<InsertValueInst>(Insert2->getAggregateOperand());
        if (!Insert1)
          return createCleanupHandler(Actions, 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(Actions, CleanupHandlerMap, BB);
        }
      }
      return;
    }

    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(Actions, 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(Actions, CleanupHandlerMap, BB);
      }
      // The selector dispatch block should always terminate our search.
      assert(BB == EndBB);
      return;
    }

    if (isAsynchronousEHPersonality(Personality)) {
      // If this is a landingpad block, split the block at the first non-landing
      // pad instruction.
      Instruction *MaybeCall = BB->getFirstNonPHIOrDbg();
      if (LPadMap) {
        while (MaybeCall != BB->getTerminator() &&
               LPadMap->isLandingPadSpecificInst(MaybeCall))
          MaybeCall = MaybeCall->getNextNode();
      }

      // Look for outlined finally calls.
      if (CallSite FinallyCall = matchOutlinedFinallyCall(BB, MaybeCall)) {
        Function *Fin = FinallyCall.getCalledFunction();
        assert(Fin && "outlined finally call should be direct");
        auto *Action = new CleanupHandler(BB);
        Action->setHandlerBlockOrFunc(Fin);
        Actions.insertCleanupHandler(Action);
        CleanupHandlerMap[BB] = Action;
        DEBUG(dbgs() << "  Found frontend-outlined finally call to "
                     << Fin->getName() << " in block "
                     << Action->getStartBlock()->getName() << "\n");

        // Split the block if there were more interesting instructions and look
        // for finally calls in the normal successor block.
        BasicBlock *SuccBB = BB;
        if (FinallyCall.getInstruction() != BB->getTerminator() &&
            FinallyCall.getInstruction()->getNextNode() !=
                BB->getTerminator()) {
          SuccBB =
              SplitBlock(BB, FinallyCall.getInstruction()->getNextNode(), DT);
        } else {
          if (FinallyCall.isInvoke()) {
            SuccBB =
                cast<InvokeInst>(FinallyCall.getInstruction())->getNormalDest();
          } else {
            SuccBB = BB->getUniqueSuccessor();
            assert(SuccBB &&
                   "splitOutlinedFinallyCalls didn't insert a branch");
          }
        }
        BB = SuccBB;
        if (BB == EndBB)
          return;
        continue;
      }
    }

    // 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;
      // If this a nested landing pad, it may contain an endcatch call.
      if (match(Inst, m_Intrinsic<Intrinsic::eh_endcatch>()))
        return;
      // Anything else makes this interesting cleanup code.
      return createCleanupHandler(Actions, CleanupHandlerMap, BB);
    }

    // Only unconditional branches in empty blocks should get this far.
    assert(Branch && Branch->isUnconditional());
    if (BB == EndBB)
      return;
    BB = Branch->getSuccessor(0);
  }
}

// This is a public function, declared in WinEHFuncInfo.h and is also
// referenced by WinEHNumbering in FunctionLoweringInfo.cpp.
void llvm::parseEHActions(
    const IntrinsicInst *II,
    SmallVectorImpl<std::unique_ptr<ActionHandler>> &Actions) {
  assert(II->getIntrinsicID() == Intrinsic::eh_actions &&
         "attempted to parse non eh.actions intrinsic");
  for (unsigned I = 0, E = II->getNumArgOperands(); I != E;) {
    uint64_t ActionKind =
        cast<ConstantInt>(II->getArgOperand(I))->getZExtValue();
    if (ActionKind == /*catch=*/1) {
      auto *Selector = cast<Constant>(II->getArgOperand(I + 1));
      ConstantInt *EHObjIndex = cast<ConstantInt>(II->getArgOperand(I + 2));
      int64_t EHObjIndexVal = EHObjIndex->getSExtValue();
      Constant *Handler = cast<Constant>(II->getArgOperand(I + 3));
      I += 4;
      auto CH = make_unique<CatchHandler>(/*BB=*/nullptr, Selector,
                                          /*NextBB=*/nullptr);
      CH->setHandlerBlockOrFunc(Handler);
      CH->setExceptionVarIndex(EHObjIndexVal);
      Actions.push_back(std::move(CH));
    } else if (ActionKind == 0) {
      Constant *Handler = cast<Constant>(II->getArgOperand(I + 1));
      I += 2;
      auto CH = make_unique<CleanupHandler>(/*BB=*/nullptr);
      CH->setHandlerBlockOrFunc(Handler);
      Actions.push_back(std::move(CH));
    } else {
      llvm_unreachable("Expected either a catch or cleanup handler!");
    }
  }
  std::reverse(Actions.begin(), Actions.end());
}

namespace {
struct WinEHNumbering {
  WinEHNumbering(WinEHFuncInfo &FuncInfo) : FuncInfo(FuncInfo),
      CurrentBaseState(-1), NextState(0) {}

  WinEHFuncInfo &FuncInfo;
  int CurrentBaseState;
  int NextState;

  SmallVector<std::unique_ptr<ActionHandler>, 4> HandlerStack;
  SmallPtrSet<const Function *, 4> VisitedHandlers;

  int currentEHNumber() const {
    return HandlerStack.empty() ? CurrentBaseState : HandlerStack.back()->getEHState();
  }

  void createUnwindMapEntry(int ToState, ActionHandler *AH);
  void createTryBlockMapEntry(int TryLow, int TryHigh,
                              ArrayRef<CatchHandler *> Handlers);
  void processCallSite(MutableArrayRef<std::unique_ptr<ActionHandler>> Actions,
                       ImmutableCallSite CS);
  void popUnmatchedActions(int FirstMismatch);
  void calculateStateNumbers(const Function &F);
  void findActionRootLPads(const Function &F);
};
} // namespace

void WinEHNumbering::createUnwindMapEntry(int ToState, ActionHandler *AH) {
  WinEHUnwindMapEntry UME;
  UME.ToState = ToState;
  if (auto *CH = dyn_cast_or_null<CleanupHandler>(AH))
    UME.Cleanup = cast<Function>(CH->getHandlerBlockOrFunc());
  else
    UME.Cleanup = nullptr;
  FuncInfo.UnwindMap.push_back(UME);
}

void WinEHNumbering::createTryBlockMapEntry(int TryLow, int TryHigh,
                                            ArrayRef<CatchHandler *> Handlers) {
  // See if we already have an entry for this set of handlers.
  // This is using iterators rather than a range-based for loop because
  // if we find the entry we're looking for we'll need the iterator to erase it.
  int NumHandlers = Handlers.size();
  auto I = FuncInfo.TryBlockMap.begin();
  auto E = FuncInfo.TryBlockMap.end();
  for ( ; I != E; ++I) {
    auto &Entry = *I;
    if (Entry.HandlerArray.size() != (size_t)NumHandlers)
      continue;
    int N;
    for (N = 0; N < NumHandlers; ++N) {
      if (Entry.HandlerArray[N].Handler != Handlers[N]->getHandlerBlockOrFunc())
        break; // breaks out of inner loop
    }
    // If all the handlers match, this is what we were looking for.
    if (N == NumHandlers) {
      break;
    }
  }

  // If we found an existing entry for this set of handlers, extend the range
  // but move the entry to the end of the map vector.  The order of entries
  // in the map is critical to the way that the runtime finds handlers.
  // FIXME: Depending on what has happened with block ordering, this may
  //        incorrectly combine entries that should remain separate.
  if (I != E) {
    // Copy the existing entry.
    WinEHTryBlockMapEntry Entry = *I;
    Entry.TryLow = std::min(TryLow, Entry.TryLow);
    Entry.TryHigh = std::max(TryHigh, Entry.TryHigh);
    assert(Entry.TryLow <= Entry.TryHigh);
    // Erase the old entry and add this one to the back.
    FuncInfo.TryBlockMap.erase(I);
    FuncInfo.TryBlockMap.push_back(Entry);
    return;
  }

  // If we didn't find an entry, create a new one.
  WinEHTryBlockMapEntry TBME;
  TBME.TryLow = TryLow;
  TBME.TryHigh = TryHigh;
  assert(TBME.TryLow <= TBME.TryHigh);
  for (CatchHandler *CH : Handlers) {
    WinEHHandlerType HT;
    if (CH->getSelector()->isNullValue()) {
      HT.Adjectives = 0x40;
      HT.TypeDescriptor = nullptr;
    } else {
      auto *GV = cast<GlobalVariable>(CH->getSelector()->stripPointerCasts());
      // Selectors are always pointers to GlobalVariables with 'struct' type.
      // The struct has two fields, adjectives and a type descriptor.
      auto *CS = cast<ConstantStruct>(GV->getInitializer());
      HT.Adjectives =
          cast<ConstantInt>(CS->getAggregateElement(0U))->getZExtValue();
      HT.TypeDescriptor =
          cast<GlobalVariable>(CS->getAggregateElement(1)->stripPointerCasts());
    }
    HT.Handler = cast<Function>(CH->getHandlerBlockOrFunc());
    HT.CatchObjRecoverIdx = CH->getExceptionVarIndex();
    TBME.HandlerArray.push_back(HT);
  }
  FuncInfo.TryBlockMap.push_back(TBME);
}

static void print_name(const Value *V) {
#ifndef NDEBUG
  if (!V) {
    DEBUG(dbgs() << "null");
    return;
  }

  if (const auto *F = dyn_cast<Function>(V))
    DEBUG(dbgs() << F->getName());
  else
    DEBUG(V->dump());
#endif
}

void WinEHNumbering::processCallSite(
    MutableArrayRef<std::unique_ptr<ActionHandler>> Actions,
    ImmutableCallSite CS) {
  DEBUG(dbgs() << "processCallSite (EH state = " << currentEHNumber()
               << ") for: ");
  print_name(CS ? CS.getCalledValue() : nullptr);
  DEBUG(dbgs() << '\n');

  DEBUG(dbgs() << "HandlerStack: \n");
  for (int I = 0, E = HandlerStack.size(); I < E; ++I) {
    DEBUG(dbgs() << "  ");
    print_name(HandlerStack[I]->getHandlerBlockOrFunc());
    DEBUG(dbgs() << '\n');
  }
  DEBUG(dbgs() << "Actions: \n");
  for (int I = 0, E = Actions.size(); I < E; ++I) {
    DEBUG(dbgs() << "  ");
    print_name(Actions[I]->getHandlerBlockOrFunc());
    DEBUG(dbgs() << '\n');
  }
  int FirstMismatch = 0;
  for (int E = std::min(HandlerStack.size(), Actions.size()); FirstMismatch < E;
       ++FirstMismatch) {
    if (HandlerStack[FirstMismatch]->getHandlerBlockOrFunc() !=
        Actions[FirstMismatch]->getHandlerBlockOrFunc())
      break;
  }

  // Remove unmatched actions from the stack and process their EH states.
  popUnmatchedActions(FirstMismatch);

  DEBUG(dbgs() << "Pushing actions for CallSite: ");
  print_name(CS ? CS.getCalledValue() : nullptr);
  DEBUG(dbgs() << '\n');

  bool LastActionWasCatch = false;
  const LandingPadInst *LastRootLPad = nullptr;
  for (size_t I = FirstMismatch; I != Actions.size(); ++I) {
    // We can reuse eh states when pushing two catches for the same invoke.
    bool CurrActionIsCatch = isa<CatchHandler>(Actions[I].get());
    auto *Handler = cast<Function>(Actions[I]->getHandlerBlockOrFunc());
    // Various conditions can lead to a handler being popped from the
    // stack and re-pushed later.  That shouldn't create a new state.
    // FIXME: Can code optimization lead to re-used handlers?
    if (FuncInfo.HandlerEnclosedState.count(Handler)) {
      // If we already assigned the state enclosed by this handler re-use it.
      Actions[I]->setEHState(FuncInfo.HandlerEnclosedState[Handler]);
      continue;
    }
    const LandingPadInst* RootLPad = FuncInfo.RootLPad[Handler];
    if (CurrActionIsCatch && LastActionWasCatch && RootLPad == LastRootLPad) {
      DEBUG(dbgs() << "setEHState for handler to " << currentEHNumber() << "\n");
      Actions[I]->setEHState(currentEHNumber());
    } else {
      DEBUG(dbgs() << "createUnwindMapEntry(" << currentEHNumber() << ", ");
      print_name(Actions[I]->getHandlerBlockOrFunc());
      DEBUG(dbgs() << ") with EH state " << NextState << "\n");
      createUnwindMapEntry(currentEHNumber(), Actions[I].get());
      DEBUG(dbgs() << "setEHState for handler to " << NextState << "\n");
      Actions[I]->setEHState(NextState);
      NextState++;
    }
    HandlerStack.push_back(std::move(Actions[I]));
    LastActionWasCatch = CurrActionIsCatch;
    LastRootLPad = RootLPad;
  }

  // This is used to defer numbering states for a handler until after the
  // last time it appears in an invoke action list.
  if (CS.isInvoke()) {
    for (int I = 0, E = HandlerStack.size(); I < E; ++I) {
      auto *Handler = cast<Function>(HandlerStack[I]->getHandlerBlockOrFunc());
      if (FuncInfo.LastInvoke[Handler] != cast<InvokeInst>(CS.getInstruction()))
        continue;
      FuncInfo.LastInvokeVisited[Handler] = true;
      DEBUG(dbgs() << "Last invoke of ");
      print_name(Handler);
      DEBUG(dbgs() << " has been visited.\n");
    }
  }

  DEBUG(dbgs() << "In EHState " << currentEHNumber() << " for CallSite: ");
  print_name(CS ? CS.getCalledValue() : nullptr);
  DEBUG(dbgs() << '\n');
}

void WinEHNumbering::popUnmatchedActions(int FirstMismatch) {
  // Don't recurse while we are looping over the handler stack.  Instead, defer
  // the numbering of the catch handlers until we are done popping.
  SmallVector<CatchHandler *, 4> PoppedCatches;
  for (int I = HandlerStack.size() - 1; I >= FirstMismatch; --I) {
    std::unique_ptr<ActionHandler> Handler = HandlerStack.pop_back_val();
    if (isa<CatchHandler>(Handler.get()))
      PoppedCatches.push_back(cast<CatchHandler>(Handler.release()));
  }

  int TryHigh = NextState - 1;
  int LastTryLowIdx = 0;
  for (int I = 0, E = PoppedCatches.size(); I != E; ++I) {
    CatchHandler *CH = PoppedCatches[I];
    DEBUG(dbgs() << "Popped handler with state " << CH->getEHState() << "\n");
    if (I + 1 == E || CH->getEHState() != PoppedCatches[I + 1]->getEHState()) {
      int TryLow = CH->getEHState();
      auto Handlers =
          makeArrayRef(&PoppedCatches[LastTryLowIdx], I - LastTryLowIdx + 1);
      DEBUG(dbgs() << "createTryBlockMapEntry(" << TryLow << ", " << TryHigh);
      for (size_t J = 0; J < Handlers.size(); ++J) {
        DEBUG(dbgs() << ", ");
        print_name(Handlers[J]->getHandlerBlockOrFunc());
      }
      DEBUG(dbgs() << ")\n");
      createTryBlockMapEntry(TryLow, TryHigh, Handlers);
      LastTryLowIdx = I + 1;
    }
  }

  for (CatchHandler *CH : PoppedCatches) {
    if (auto *F = dyn_cast<Function>(CH->getHandlerBlockOrFunc())) {
      if (FuncInfo.LastInvokeVisited[F]) {
        DEBUG(dbgs() << "Assigning base state " << NextState << " to ");
        print_name(F);
        DEBUG(dbgs() << '\n');
        FuncInfo.HandlerBaseState[F] = NextState;
        DEBUG(dbgs() << "createUnwindMapEntry(" << currentEHNumber()
                     << ", null)\n");
        createUnwindMapEntry(currentEHNumber(), nullptr);
        ++NextState;
        calculateStateNumbers(*F);
      }
      else {
        DEBUG(dbgs() << "Deferring handling of ");
        print_name(F);
        DEBUG(dbgs() << " until last invoke visited.\n");
      }
    }
    delete CH;
  }
}

void WinEHNumbering::calculateStateNumbers(const Function &F) {
  auto I = VisitedHandlers.insert(&F);
  if (!I.second)
    return; // We've already visited this handler, don't renumber it.

  int OldBaseState = CurrentBaseState;
  if (FuncInfo.HandlerBaseState.count(&F)) {
    CurrentBaseState = FuncInfo.HandlerBaseState[&F];
  }

  size_t SavedHandlerStackSize = HandlerStack.size();

  DEBUG(dbgs() << "Calculating state numbers for: " << F.getName() << '\n');
  SmallVector<std::unique_ptr<ActionHandler>, 4> ActionList;
  for (const BasicBlock &BB : F) {
    for (const Instruction &I : BB) {
      const auto *CI = dyn_cast<CallInst>(&I);
      if (!CI || CI->doesNotThrow())
        continue;
      processCallSite(None, CI);
    }
    const auto *II = dyn_cast<InvokeInst>(BB.getTerminator());
    if (!II)
      continue;
    const LandingPadInst *LPI = II->getLandingPadInst();
    auto *ActionsCall = dyn_cast<IntrinsicInst>(LPI->getNextNode());
    if (!ActionsCall)
      continue;
    parseEHActions(ActionsCall, ActionList);
    if (ActionList.empty())
      continue;
    processCallSite(ActionList, II);
    ActionList.clear();
    FuncInfo.LandingPadStateMap[LPI] = currentEHNumber();
    DEBUG(dbgs() << "Assigning state " << currentEHNumber()
                  << " to landing pad at " << LPI->getParent()->getName()
                  << '\n');
  }

  // Pop any actions that were pushed on the stack for this function.
  popUnmatchedActions(SavedHandlerStackSize);

  DEBUG(dbgs() << "Assigning max state " << NextState - 1
               << " to " << F.getName() << '\n');
  FuncInfo.CatchHandlerMaxState[&F] = NextState - 1;

  CurrentBaseState = OldBaseState;
}

// This function follows the same basic traversal as calculateStateNumbers
// but it is necessary to identify the root landing pad associated
// with each action before we start assigning state numbers.
void WinEHNumbering::findActionRootLPads(const Function &F) {
  auto I = VisitedHandlers.insert(&F);
  if (!I.second)
    return; // We've already visited this handler, don't revisit it.

  SmallVector<std::unique_ptr<ActionHandler>, 4> ActionList;
  for (const BasicBlock &BB : F) {
    const auto *II = dyn_cast<InvokeInst>(BB.getTerminator());
    if (!II)
      continue;
    const LandingPadInst *LPI = II->getLandingPadInst();
    auto *ActionsCall = dyn_cast<IntrinsicInst>(LPI->getNextNode());
    if (!ActionsCall)
      continue;

    assert(ActionsCall->getIntrinsicID() == Intrinsic::eh_actions);
    parseEHActions(ActionsCall, ActionList);
    if (ActionList.empty())
      continue;
    for (int I = 0, E = ActionList.size(); I < E; ++I) {
      if (auto *Handler
              = dyn_cast<Function>(ActionList[I]->getHandlerBlockOrFunc())) {
        FuncInfo.LastInvoke[Handler] = II;
        // Don't replace the root landing pad if we previously saw this
        // handler in a different function.
        if (FuncInfo.RootLPad.count(Handler) &&
            FuncInfo.RootLPad[Handler]->getParent()->getParent() != &F)
          continue;
        DEBUG(dbgs() << "Setting root lpad for ");
        print_name(Handler);
        DEBUG(dbgs() << " to " << LPI->getParent()->getName() << '\n');
        FuncInfo.RootLPad[Handler] = LPI;
      }
    }
    // Walk the actions again and look for nested handlers.  This has to
    // happen after all of the actions have been processed in the current
    // function.
    for (int I = 0, E = ActionList.size(); I < E; ++I)
      if (auto *Handler
              = dyn_cast<Function>(ActionList[I]->getHandlerBlockOrFunc()))
        findActionRootLPads(*Handler);
    ActionList.clear();
  }
}

void llvm::calculateWinCXXEHStateNumbers(const Function *ParentFn,
                                         WinEHFuncInfo &FuncInfo) {
  // Return if it's already been done.
  if (!FuncInfo.LandingPadStateMap.empty())
    return;

  WinEHNumbering Num(FuncInfo);
  Num.findActionRootLPads(*ParentFn);
  // The VisitedHandlers list is used by both findActionRootLPads and
  // calculateStateNumbers, but both functions need to visit all handlers.
  Num.VisitedHandlers.clear();
  Num.calculateStateNumbers(*ParentFn);
  // Pop everything on the handler stack.
  // It may be necessary to call this more than once because a handler can
  // be pushed on the stack as a result of clearing the stack.
  while (!Num.HandlerStack.empty())
    Num.processCallSite(None, ImmutableCallSite());
}
