1245 lines
		
	
	
		
			50 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			1245 lines
		
	
	
		
			50 KiB
		
	
	
	
		
			C++
		
	
	
	
//===-- 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/Analysis/CFG.h"
 | 
						|
#include "llvm/Analysis/LibCallSemantics.h"
 | 
						|
#include "llvm/CodeGen/WinEHFuncInfo.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/SSAUpdater.h"
 | 
						|
 | 
						|
using namespace llvm;
 | 
						|
 | 
						|
#define DEBUG_TYPE "winehprepare"
 | 
						|
 | 
						|
static cl::opt<bool> DisableDemotion(
 | 
						|
    "disable-demotion", cl::Hidden,
 | 
						|
    cl::desc(
 | 
						|
        "Clone multicolor basic blocks but do not demote cross funclet values"),
 | 
						|
    cl::init(false));
 | 
						|
 | 
						|
static cl::opt<bool> DisableCleanups(
 | 
						|
    "disable-cleanups", cl::Hidden,
 | 
						|
    cl::desc("Do not remove implausible terminators or other similar cleanups"),
 | 
						|
    cl::init(false));
 | 
						|
 | 
						|
namespace {
 | 
						|
 | 
						|
class WinEHPrepare : public FunctionPass {
 | 
						|
public:
 | 
						|
  static char ID; // Pass identification, replacement for typeid.
 | 
						|
  WinEHPrepare(const TargetMachine *TM = nullptr) : FunctionPass(ID) {}
 | 
						|
 | 
						|
  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:
 | 
						|
  void insertPHIStores(PHINode *OriginalPHI, AllocaInst *SpillSlot);
 | 
						|
  void
 | 
						|
  insertPHIStore(BasicBlock *PredBlock, Value *PredVal, AllocaInst *SpillSlot,
 | 
						|
                 SmallVectorImpl<std::pair<BasicBlock *, Value *>> &Worklist);
 | 
						|
  AllocaInst *insertPHILoads(PHINode *PN, Function &F);
 | 
						|
  void replaceUseWithLoad(Value *V, Use &U, AllocaInst *&SpillSlot,
 | 
						|
                          DenseMap<BasicBlock *, Value *> &Loads, Function &F);
 | 
						|
  void demoteNonlocalUses(Value *V, std::set<BasicBlock *> &ColorsForBB,
 | 
						|
                          Function &F);
 | 
						|
  bool prepareExplicitEH(Function &F,
 | 
						|
                         SmallVectorImpl<BasicBlock *> &EntryBlocks);
 | 
						|
  void replaceTerminatePadWithCleanup(Function &F);
 | 
						|
  void colorFunclets(Function &F, SmallVectorImpl<BasicBlock *> &EntryBlocks);
 | 
						|
  void demotePHIsOnFunclets(Function &F);
 | 
						|
  void demoteUsesBetweenFunclets(Function &F);
 | 
						|
  void demoteArgumentUses(Function &F);
 | 
						|
  void cloneCommonBlocks(Function &F,
 | 
						|
                         SmallVectorImpl<BasicBlock *> &EntryBlocks);
 | 
						|
  void removeImplausibleTerminators(Function &F);
 | 
						|
  void cleanupPreparedFunclets(Function &F);
 | 
						|
  void verifyPreparedFunclets(Function &F);
 | 
						|
 | 
						|
  // All fields are reset by runOnFunction.
 | 
						|
  EHPersonality Personality = EHPersonality::Unknown;
 | 
						|
 | 
						|
  std::map<BasicBlock *, std::set<BasicBlock *>> BlockColors;
 | 
						|
  std::map<BasicBlock *, std::set<BasicBlock *>> FuncletBlocks;
 | 
						|
  std::map<BasicBlock *, std::set<BasicBlock *>> FuncletChildren;
 | 
						|
};
 | 
						|
 | 
						|
} // 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);
 | 
						|
}
 | 
						|
 | 
						|
static void findFuncletEntryPoints(Function &Fn,
 | 
						|
                                   SmallVectorImpl<BasicBlock *> &EntryBlocks) {
 | 
						|
  EntryBlocks.push_back(&Fn.getEntryBlock());
 | 
						|
  for (BasicBlock &BB : Fn) {
 | 
						|
    Instruction *First = BB.getFirstNonPHI();
 | 
						|
    if (!First->isEHPad())
 | 
						|
      continue;
 | 
						|
    assert(!isa<LandingPadInst>(First) &&
 | 
						|
           "landingpad cannot be used with funclet EH personality");
 | 
						|
    // Find EH pad blocks that represent funclet start points.
 | 
						|
    if (!isa<CatchEndPadInst>(First) && !isa<CleanupEndPadInst>(First))
 | 
						|
      EntryBlocks.push_back(&BB);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool WinEHPrepare::runOnFunction(Function &Fn) {
 | 
						|
  if (!Fn.hasPersonalityFn())
 | 
						|
    return false;
 | 
						|
 | 
						|
  // Classify the personality to see what kind of preparation we need.
 | 
						|
  Personality = classifyEHPersonality(Fn.getPersonalityFn());
 | 
						|
 | 
						|
  // Do nothing if this is not a funclet-based personality.
 | 
						|
  if (!isFuncletEHPersonality(Personality))
 | 
						|
    return false;
 | 
						|
 | 
						|
  // Remove unreachable blocks.  It is not valuable to assign them a color and
 | 
						|
  // their existence can trick us into thinking values are alive when they are
 | 
						|
  // not.
 | 
						|
  removeUnreachableBlocks(Fn);
 | 
						|
 | 
						|
  SmallVector<BasicBlock *, 4> EntryBlocks;
 | 
						|
  findFuncletEntryPoints(Fn, EntryBlocks);
 | 
						|
  return prepareExplicitEH(Fn, EntryBlocks);
 | 
						|
}
 | 
						|
 | 
						|
bool WinEHPrepare::doFinalization(Module &M) { return false; }
 | 
						|
 | 
						|
void WinEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const {}
 | 
						|
 | 
						|
static int addUnwindMapEntry(WinEHFuncInfo &FuncInfo, int ToState,
 | 
						|
                             const BasicBlock *BB) {
 | 
						|
  CxxUnwindMapEntry UME;
 | 
						|
  UME.ToState = ToState;
 | 
						|
  UME.Cleanup = BB;
 | 
						|
  FuncInfo.CxxUnwindMap.push_back(UME);
 | 
						|
  return FuncInfo.getLastStateNumber();
 | 
						|
}
 | 
						|
 | 
						|
static void addTryBlockMapEntry(WinEHFuncInfo &FuncInfo, int TryLow,
 | 
						|
                                int TryHigh, int CatchHigh,
 | 
						|
                                ArrayRef<const CatchPadInst *> Handlers) {
 | 
						|
  WinEHTryBlockMapEntry TBME;
 | 
						|
  TBME.TryLow = TryLow;
 | 
						|
  TBME.TryHigh = TryHigh;
 | 
						|
  TBME.CatchHigh = CatchHigh;
 | 
						|
  assert(TBME.TryLow <= TBME.TryHigh);
 | 
						|
  for (const CatchPadInst *CPI : Handlers) {
 | 
						|
    WinEHHandlerType HT;
 | 
						|
    Constant *TypeInfo = cast<Constant>(CPI->getArgOperand(0));
 | 
						|
    if (TypeInfo->isNullValue())
 | 
						|
      HT.TypeDescriptor = nullptr;
 | 
						|
    else
 | 
						|
      HT.TypeDescriptor = cast<GlobalVariable>(TypeInfo->stripPointerCasts());
 | 
						|
    HT.Adjectives = cast<ConstantInt>(CPI->getArgOperand(1))->getZExtValue();
 | 
						|
    HT.Handler = CPI->getParent();
 | 
						|
    if (isa<ConstantPointerNull>(CPI->getArgOperand(2)))
 | 
						|
      HT.CatchObj.Alloca = nullptr;
 | 
						|
    else
 | 
						|
      HT.CatchObj.Alloca = cast<AllocaInst>(CPI->getArgOperand(2));
 | 
						|
    TBME.HandlerArray.push_back(HT);
 | 
						|
  }
 | 
						|
  FuncInfo.TryBlockMap.push_back(TBME);
 | 
						|
}
 | 
						|
 | 
						|
static const CatchPadInst *getSingleCatchPadPredecessor(const BasicBlock *BB) {
 | 
						|
  for (const BasicBlock *PredBlock : predecessors(BB))
 | 
						|
    if (auto *CPI = dyn_cast<CatchPadInst>(PredBlock->getFirstNonPHI()))
 | 
						|
      return CPI;
 | 
						|
  return nullptr;
 | 
						|
}
 | 
						|
 | 
						|
/// Find all the catchpads that feed directly into the catchendpad. Frontends
 | 
						|
/// using this personality should ensure that each catchendpad and catchpad has
 | 
						|
/// one or zero catchpad predecessors.
 | 
						|
///
 | 
						|
/// The following C++ generates the IR after it:
 | 
						|
///   try {
 | 
						|
///   } catch (A) {
 | 
						|
///   } catch (B) {
 | 
						|
///   }
 | 
						|
///
 | 
						|
/// IR:
 | 
						|
///   %catchpad.A
 | 
						|
///     catchpad [i8* A typeinfo]
 | 
						|
///         to label %catch.A unwind label %catchpad.B
 | 
						|
///   %catchpad.B
 | 
						|
///     catchpad [i8* B typeinfo]
 | 
						|
///         to label %catch.B unwind label %endcatches
 | 
						|
///   %endcatches
 | 
						|
///     catchendblock unwind to caller
 | 
						|
static void
 | 
						|
findCatchPadsForCatchEndPad(const BasicBlock *CatchEndBB,
 | 
						|
                            SmallVectorImpl<const CatchPadInst *> &Handlers) {
 | 
						|
  const CatchPadInst *CPI = getSingleCatchPadPredecessor(CatchEndBB);
 | 
						|
  while (CPI) {
 | 
						|
    Handlers.push_back(CPI);
 | 
						|
    CPI = getSingleCatchPadPredecessor(CPI->getParent());
 | 
						|
  }
 | 
						|
  // We've pushed these back into reverse source order.  Reverse them to get
 | 
						|
  // the list back into source order.
 | 
						|
  std::reverse(Handlers.begin(), Handlers.end());
 | 
						|
}
 | 
						|
 | 
						|
// Given BB which ends in an unwind edge, return the EHPad that this BB belongs
 | 
						|
// to. If the unwind edge came from an invoke, return null.
 | 
						|
static const BasicBlock *getEHPadFromPredecessor(const BasicBlock *BB) {
 | 
						|
  const TerminatorInst *TI = BB->getTerminator();
 | 
						|
  if (isa<InvokeInst>(TI))
 | 
						|
    return nullptr;
 | 
						|
  if (TI->isEHPad())
 | 
						|
    return BB;
 | 
						|
  return cast<CleanupReturnInst>(TI)->getCleanupPad()->getParent();
 | 
						|
}
 | 
						|
 | 
						|
static void calculateExplicitCXXStateNumbers(WinEHFuncInfo &FuncInfo,
 | 
						|
                                             const BasicBlock &BB,
 | 
						|
                                             int ParentState) {
 | 
						|
  assert(BB.isEHPad());
 | 
						|
  const Instruction *FirstNonPHI = BB.getFirstNonPHI();
 | 
						|
  // All catchpad instructions will be handled when we process their
 | 
						|
  // respective catchendpad instruction.
 | 
						|
  if (isa<CatchPadInst>(FirstNonPHI))
 | 
						|
    return;
 | 
						|
 | 
						|
  if (isa<CatchEndPadInst>(FirstNonPHI)) {
 | 
						|
    SmallVector<const CatchPadInst *, 2> Handlers;
 | 
						|
    findCatchPadsForCatchEndPad(&BB, Handlers);
 | 
						|
    const BasicBlock *FirstTryPad = Handlers.front()->getParent();
 | 
						|
    int TryLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr);
 | 
						|
    FuncInfo.EHPadStateMap[Handlers.front()] = TryLow;
 | 
						|
    for (const BasicBlock *PredBlock : predecessors(FirstTryPad))
 | 
						|
      if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
 | 
						|
        calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, TryLow);
 | 
						|
    int CatchLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr);
 | 
						|
 | 
						|
    // catchpads are separate funclets in C++ EH due to the way rethrow works.
 | 
						|
    // In SEH, they aren't, so no invokes will unwind to the catchendpad.
 | 
						|
    FuncInfo.EHPadStateMap[FirstNonPHI] = CatchLow;
 | 
						|
    int TryHigh = CatchLow - 1;
 | 
						|
    for (const BasicBlock *PredBlock : predecessors(&BB))
 | 
						|
      if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
 | 
						|
        calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, CatchLow);
 | 
						|
    int CatchHigh = FuncInfo.getLastStateNumber();
 | 
						|
    addTryBlockMapEntry(FuncInfo, TryLow, TryHigh, CatchHigh, Handlers);
 | 
						|
    DEBUG(dbgs() << "TryLow[" << FirstTryPad->getName() << "]: " << TryLow
 | 
						|
                 << '\n');
 | 
						|
    DEBUG(dbgs() << "TryHigh[" << FirstTryPad->getName() << "]: " << TryHigh
 | 
						|
                 << '\n');
 | 
						|
    DEBUG(dbgs() << "CatchHigh[" << FirstTryPad->getName() << "]: " << CatchHigh
 | 
						|
                 << '\n');
 | 
						|
  } else if (isa<CleanupPadInst>(FirstNonPHI)) {
 | 
						|
    // A cleanup can have multiple exits; don't re-process after the first.
 | 
						|
    if (FuncInfo.EHPadStateMap.count(FirstNonPHI))
 | 
						|
      return;
 | 
						|
    int CleanupState = addUnwindMapEntry(FuncInfo, ParentState, &BB);
 | 
						|
    FuncInfo.EHPadStateMap[FirstNonPHI] = CleanupState;
 | 
						|
    DEBUG(dbgs() << "Assigning state #" << CleanupState << " to BB "
 | 
						|
                 << BB.getName() << '\n');
 | 
						|
    for (const BasicBlock *PredBlock : predecessors(&BB))
 | 
						|
      if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
 | 
						|
        calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, CleanupState);
 | 
						|
  } else if (auto *CEPI = dyn_cast<CleanupEndPadInst>(FirstNonPHI)) {
 | 
						|
    // Propagate ParentState to the cleanuppad in case it doesn't have
 | 
						|
    // any cleanuprets.
 | 
						|
    BasicBlock *CleanupBlock = CEPI->getCleanupPad()->getParent();
 | 
						|
    calculateExplicitCXXStateNumbers(FuncInfo, *CleanupBlock, ParentState);
 | 
						|
    // Anything unwinding through CleanupEndPadInst is in ParentState.
 | 
						|
    FuncInfo.EHPadStateMap[FirstNonPHI] = ParentState;
 | 
						|
    for (const BasicBlock *PredBlock : predecessors(&BB))
 | 
						|
      if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
 | 
						|
        calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, ParentState);
 | 
						|
  } else if (isa<TerminatePadInst>(FirstNonPHI)) {
 | 
						|
    report_fatal_error("Not yet implemented!");
 | 
						|
  } else {
 | 
						|
    llvm_unreachable("unexpected EH Pad!");
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
static int addSEHExcept(WinEHFuncInfo &FuncInfo, int ParentState,
 | 
						|
                        const Function *Filter, const BasicBlock *Handler) {
 | 
						|
  SEHUnwindMapEntry Entry;
 | 
						|
  Entry.ToState = ParentState;
 | 
						|
  Entry.IsFinally = false;
 | 
						|
  Entry.Filter = Filter;
 | 
						|
  Entry.Handler = Handler;
 | 
						|
  FuncInfo.SEHUnwindMap.push_back(Entry);
 | 
						|
  return FuncInfo.SEHUnwindMap.size() - 1;
 | 
						|
}
 | 
						|
 | 
						|
static int addSEHFinally(WinEHFuncInfo &FuncInfo, int ParentState,
 | 
						|
                         const BasicBlock *Handler) {
 | 
						|
  SEHUnwindMapEntry Entry;
 | 
						|
  Entry.ToState = ParentState;
 | 
						|
  Entry.IsFinally = true;
 | 
						|
  Entry.Filter = nullptr;
 | 
						|
  Entry.Handler = Handler;
 | 
						|
  FuncInfo.SEHUnwindMap.push_back(Entry);
 | 
						|
  return FuncInfo.SEHUnwindMap.size() - 1;
 | 
						|
}
 | 
						|
 | 
						|
static void calculateExplicitSEHStateNumbers(WinEHFuncInfo &FuncInfo,
 | 
						|
                                             const BasicBlock &BB,
 | 
						|
                                             int ParentState) {
 | 
						|
  assert(BB.isEHPad());
 | 
						|
  const Instruction *FirstNonPHI = BB.getFirstNonPHI();
 | 
						|
  // All catchpad instructions will be handled when we process their
 | 
						|
  // respective catchendpad instruction.
 | 
						|
  if (isa<CatchPadInst>(FirstNonPHI))
 | 
						|
    return;
 | 
						|
 | 
						|
  if (isa<CatchEndPadInst>(FirstNonPHI)) {
 | 
						|
    // Extract the filter function and the __except basic block and create a
 | 
						|
    // state for them.
 | 
						|
    SmallVector<const CatchPadInst *, 1> Handlers;
 | 
						|
    findCatchPadsForCatchEndPad(&BB, Handlers);
 | 
						|
    assert(Handlers.size() == 1 &&
 | 
						|
           "SEH doesn't have multiple handlers per __try");
 | 
						|
    const CatchPadInst *CPI = Handlers.front();
 | 
						|
    const BasicBlock *CatchPadBB = CPI->getParent();
 | 
						|
    const Constant *FilterOrNull =
 | 
						|
        cast<Constant>(CPI->getArgOperand(0)->stripPointerCasts());
 | 
						|
    const Function *Filter = dyn_cast<Function>(FilterOrNull);
 | 
						|
    assert((Filter || FilterOrNull->isNullValue()) &&
 | 
						|
           "unexpected filter value");
 | 
						|
    int TryState = addSEHExcept(FuncInfo, ParentState, Filter, CatchPadBB);
 | 
						|
 | 
						|
    // Everything in the __try block uses TryState as its parent state.
 | 
						|
    FuncInfo.EHPadStateMap[CPI] = TryState;
 | 
						|
    DEBUG(dbgs() << "Assigning state #" << TryState << " to BB "
 | 
						|
                 << CatchPadBB->getName() << '\n');
 | 
						|
    for (const BasicBlock *PredBlock : predecessors(CatchPadBB))
 | 
						|
      if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
 | 
						|
        calculateExplicitSEHStateNumbers(FuncInfo, *PredBlock, TryState);
 | 
						|
 | 
						|
    // Everything in the __except block unwinds to ParentState, just like code
 | 
						|
    // outside the __try.
 | 
						|
    FuncInfo.EHPadStateMap[FirstNonPHI] = ParentState;
 | 
						|
    DEBUG(dbgs() << "Assigning state #" << ParentState << " to BB "
 | 
						|
                 << BB.getName() << '\n');
 | 
						|
    for (const BasicBlock *PredBlock : predecessors(&BB))
 | 
						|
      if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
 | 
						|
        calculateExplicitSEHStateNumbers(FuncInfo, *PredBlock, ParentState);
 | 
						|
  } else if (isa<CleanupPadInst>(FirstNonPHI)) {
 | 
						|
    // A cleanup can have multiple exits; don't re-process after the first.
 | 
						|
    if (FuncInfo.EHPadStateMap.count(FirstNonPHI))
 | 
						|
      return;
 | 
						|
    int CleanupState = addSEHFinally(FuncInfo, ParentState, &BB);
 | 
						|
    FuncInfo.EHPadStateMap[FirstNonPHI] = CleanupState;
 | 
						|
    DEBUG(dbgs() << "Assigning state #" << CleanupState << " to BB "
 | 
						|
                 << BB.getName() << '\n');
 | 
						|
    for (const BasicBlock *PredBlock : predecessors(&BB))
 | 
						|
      if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
 | 
						|
        calculateExplicitSEHStateNumbers(FuncInfo, *PredBlock, CleanupState);
 | 
						|
  } else if (auto *CEPI = dyn_cast<CleanupEndPadInst>(FirstNonPHI)) {
 | 
						|
    // Propagate ParentState to the cleanuppad in case it doesn't have
 | 
						|
    // any cleanuprets.
 | 
						|
    BasicBlock *CleanupBlock = CEPI->getCleanupPad()->getParent();
 | 
						|
    calculateExplicitSEHStateNumbers(FuncInfo, *CleanupBlock, ParentState);
 | 
						|
    // Anything unwinding through CleanupEndPadInst is in ParentState.
 | 
						|
    FuncInfo.EHPadStateMap[FirstNonPHI] = ParentState;
 | 
						|
    DEBUG(dbgs() << "Assigning state #" << ParentState << " to BB "
 | 
						|
                 << BB.getName() << '\n');
 | 
						|
    for (const BasicBlock *PredBlock : predecessors(&BB))
 | 
						|
      if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
 | 
						|
        calculateExplicitSEHStateNumbers(FuncInfo, *PredBlock, ParentState);
 | 
						|
  } else if (isa<TerminatePadInst>(FirstNonPHI)) {
 | 
						|
    report_fatal_error("Not yet implemented!");
 | 
						|
  } else {
 | 
						|
    llvm_unreachable("unexpected EH Pad!");
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/// Check if the EH Pad unwinds to caller.  Cleanups are a little bit of a
 | 
						|
/// special case because we have to look at the cleanupret instruction that uses
 | 
						|
/// the cleanuppad.
 | 
						|
static bool doesEHPadUnwindToCaller(const Instruction *EHPad) {
 | 
						|
  auto *CPI = dyn_cast<CleanupPadInst>(EHPad);
 | 
						|
  if (!CPI)
 | 
						|
    return EHPad->mayThrow();
 | 
						|
 | 
						|
  // This cleanup does not return or unwind, so we say it unwinds to caller.
 | 
						|
  if (CPI->use_empty())
 | 
						|
    return true;
 | 
						|
 | 
						|
  const Instruction *User = CPI->user_back();
 | 
						|
  if (auto *CRI = dyn_cast<CleanupReturnInst>(User))
 | 
						|
    return CRI->unwindsToCaller();
 | 
						|
  return cast<CleanupEndPadInst>(User)->unwindsToCaller();
 | 
						|
}
 | 
						|
 | 
						|
void llvm::calculateSEHStateNumbers(const Function *Fn,
 | 
						|
                                    WinEHFuncInfo &FuncInfo) {
 | 
						|
  // Don't compute state numbers twice.
 | 
						|
  if (!FuncInfo.SEHUnwindMap.empty())
 | 
						|
    return;
 | 
						|
 | 
						|
  for (const BasicBlock &BB : *Fn) {
 | 
						|
    if (!BB.isEHPad() || !doesEHPadUnwindToCaller(BB.getFirstNonPHI()))
 | 
						|
      continue;
 | 
						|
    calculateExplicitSEHStateNumbers(FuncInfo, BB, -1);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void llvm::calculateWinCXXEHStateNumbers(const Function *Fn,
 | 
						|
                                         WinEHFuncInfo &FuncInfo) {
 | 
						|
  // Return if it's already been done.
 | 
						|
  if (!FuncInfo.EHPadStateMap.empty())
 | 
						|
    return;
 | 
						|
 | 
						|
  for (const BasicBlock &BB : *Fn) {
 | 
						|
    if (!BB.isEHPad())
 | 
						|
      continue;
 | 
						|
    if (BB.isLandingPad())
 | 
						|
      report_fatal_error("MSVC C++ EH cannot use landingpads");
 | 
						|
    const Instruction *FirstNonPHI = BB.getFirstNonPHI();
 | 
						|
    if (!doesEHPadUnwindToCaller(FirstNonPHI))
 | 
						|
      continue;
 | 
						|
    calculateExplicitCXXStateNumbers(FuncInfo, BB, -1);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
static int addClrEHHandler(WinEHFuncInfo &FuncInfo, int ParentState,
 | 
						|
                           ClrHandlerType HandlerType, uint32_t TypeToken,
 | 
						|
                           const BasicBlock *Handler) {
 | 
						|
  ClrEHUnwindMapEntry Entry;
 | 
						|
  Entry.Parent = ParentState;
 | 
						|
  Entry.Handler = Handler;
 | 
						|
  Entry.HandlerType = HandlerType;
 | 
						|
  Entry.TypeToken = TypeToken;
 | 
						|
  FuncInfo.ClrEHUnwindMap.push_back(Entry);
 | 
						|
  return FuncInfo.ClrEHUnwindMap.size() - 1;
 | 
						|
}
 | 
						|
 | 
						|
void llvm::calculateClrEHStateNumbers(const Function *Fn,
 | 
						|
                                      WinEHFuncInfo &FuncInfo) {
 | 
						|
  // Return if it's already been done.
 | 
						|
  if (!FuncInfo.EHPadStateMap.empty())
 | 
						|
    return;
 | 
						|
 | 
						|
  SmallVector<std::pair<const Instruction *, int>, 8> Worklist;
 | 
						|
 | 
						|
  // Each pad needs to be able to refer to its parent, so scan the function
 | 
						|
  // looking for top-level handlers and seed the worklist with them.
 | 
						|
  for (const BasicBlock &BB : *Fn) {
 | 
						|
    if (!BB.isEHPad())
 | 
						|
      continue;
 | 
						|
    if (BB.isLandingPad())
 | 
						|
      report_fatal_error("CoreCLR EH cannot use landingpads");
 | 
						|
    const Instruction *FirstNonPHI = BB.getFirstNonPHI();
 | 
						|
    if (!doesEHPadUnwindToCaller(FirstNonPHI))
 | 
						|
      continue;
 | 
						|
    // queue this with sentinel parent state -1 to mean unwind to caller.
 | 
						|
    Worklist.emplace_back(FirstNonPHI, -1);
 | 
						|
  }
 | 
						|
 | 
						|
  while (!Worklist.empty()) {
 | 
						|
    const Instruction *Pad;
 | 
						|
    int ParentState;
 | 
						|
    std::tie(Pad, ParentState) = Worklist.pop_back_val();
 | 
						|
 | 
						|
    int PredState;
 | 
						|
    if (const CleanupEndPadInst *EndPad = dyn_cast<CleanupEndPadInst>(Pad)) {
 | 
						|
      FuncInfo.EHPadStateMap[EndPad] = ParentState;
 | 
						|
      // Queue the cleanuppad, in case it doesn't have a cleanupret.
 | 
						|
      Worklist.emplace_back(EndPad->getCleanupPad(), ParentState);
 | 
						|
      // Preds of the endpad should get the parent state.
 | 
						|
      PredState = ParentState;
 | 
						|
    } else if (const CleanupPadInst *Cleanup = dyn_cast<CleanupPadInst>(Pad)) {
 | 
						|
      // A cleanup can have multiple exits; don't re-process after the first.
 | 
						|
      if (FuncInfo.EHPadStateMap.count(Pad))
 | 
						|
        continue;
 | 
						|
      // CoreCLR personality uses arity to distinguish faults from finallies.
 | 
						|
      const BasicBlock *PadBlock = Cleanup->getParent();
 | 
						|
      ClrHandlerType HandlerType =
 | 
						|
          (Cleanup->getNumOperands() ? ClrHandlerType::Fault
 | 
						|
                                     : ClrHandlerType::Finally);
 | 
						|
      int NewState =
 | 
						|
          addClrEHHandler(FuncInfo, ParentState, HandlerType, 0, PadBlock);
 | 
						|
      FuncInfo.EHPadStateMap[Cleanup] = NewState;
 | 
						|
      // Propagate the new state to all preds of the cleanup
 | 
						|
      PredState = NewState;
 | 
						|
    } else if (const CatchEndPadInst *EndPad = dyn_cast<CatchEndPadInst>(Pad)) {
 | 
						|
      FuncInfo.EHPadStateMap[EndPad] = ParentState;
 | 
						|
      // Preds of the endpad should get the parent state.
 | 
						|
      PredState = ParentState;
 | 
						|
    } else if (const CatchPadInst *Catch = dyn_cast<CatchPadInst>(Pad)) {
 | 
						|
      const BasicBlock *PadBlock = Catch->getParent();
 | 
						|
      uint32_t TypeToken = static_cast<uint32_t>(
 | 
						|
          cast<ConstantInt>(Catch->getArgOperand(0))->getZExtValue());
 | 
						|
      int NewState = addClrEHHandler(FuncInfo, ParentState,
 | 
						|
                                     ClrHandlerType::Catch, TypeToken, PadBlock);
 | 
						|
      FuncInfo.EHPadStateMap[Catch] = NewState;
 | 
						|
      // Preds of the catch get its state
 | 
						|
      PredState = NewState;
 | 
						|
    } else {
 | 
						|
      llvm_unreachable("Unexpected EH pad");
 | 
						|
    }
 | 
						|
 | 
						|
    // Queue all predecessors with the given state
 | 
						|
    for (const BasicBlock *Pred : predecessors(Pad->getParent())) {
 | 
						|
      if ((Pred = getEHPadFromPredecessor(Pred)))
 | 
						|
        Worklist.emplace_back(Pred->getFirstNonPHI(), PredState);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void WinEHPrepare::replaceTerminatePadWithCleanup(Function &F) {
 | 
						|
  if (Personality != EHPersonality::MSVC_CXX)
 | 
						|
    return;
 | 
						|
  for (BasicBlock &BB : F) {
 | 
						|
    Instruction *First = BB.getFirstNonPHI();
 | 
						|
    auto *TPI = dyn_cast<TerminatePadInst>(First);
 | 
						|
    if (!TPI)
 | 
						|
      continue;
 | 
						|
 | 
						|
    if (TPI->getNumArgOperands() != 1)
 | 
						|
      report_fatal_error(
 | 
						|
          "Expected a unary terminatepad for MSVC C++ personalities!");
 | 
						|
 | 
						|
    auto *TerminateFn = dyn_cast<Function>(TPI->getArgOperand(0));
 | 
						|
    if (!TerminateFn)
 | 
						|
      report_fatal_error("Function operand expected in terminatepad for MSVC "
 | 
						|
                         "C++ personalities!");
 | 
						|
 | 
						|
    // Insert the cleanuppad instruction.
 | 
						|
    auto *CPI = CleanupPadInst::Create(
 | 
						|
        BB.getContext(), {}, Twine("terminatepad.for.", BB.getName()), &BB);
 | 
						|
 | 
						|
    // Insert the call to the terminate instruction.
 | 
						|
    auto *CallTerminate = CallInst::Create(TerminateFn, {}, &BB);
 | 
						|
    CallTerminate->setDoesNotThrow();
 | 
						|
    CallTerminate->setDoesNotReturn();
 | 
						|
    CallTerminate->setCallingConv(TerminateFn->getCallingConv());
 | 
						|
 | 
						|
    // Insert a new terminator for the cleanuppad using the same successor as
 | 
						|
    // the terminatepad.
 | 
						|
    CleanupReturnInst::Create(CPI, TPI->getUnwindDest(), &BB);
 | 
						|
 | 
						|
    // Let's remove the terminatepad now that we've inserted the new
 | 
						|
    // instructions.
 | 
						|
    TPI->eraseFromParent();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
colorFunclets(Function &F, SmallVectorImpl<BasicBlock *> &EntryBlocks,
 | 
						|
              std::map<BasicBlock *, std::set<BasicBlock *>> &BlockColors,
 | 
						|
              std::map<BasicBlock *, std::set<BasicBlock *>> &FuncletBlocks,
 | 
						|
              std::map<BasicBlock *, std::set<BasicBlock *>> &FuncletChildren) {
 | 
						|
  SmallVector<std::pair<BasicBlock *, BasicBlock *>, 16> Worklist;
 | 
						|
  BasicBlock *EntryBlock = &F.getEntryBlock();
 | 
						|
 | 
						|
  // Build up the color map, which maps each block to its set of 'colors'.
 | 
						|
  // For any block B, the "colors" of B are the set of funclets F (possibly
 | 
						|
  // including a root "funclet" representing the main function), such that
 | 
						|
  // F will need to directly contain B or a copy of B (where the term "directly
 | 
						|
  // contain" is used to distinguish from being "transitively contained" in
 | 
						|
  // a nested funclet).
 | 
						|
  // Use a CFG walk driven by a worklist of (block, color) pairs.  The "color"
 | 
						|
  // sets attached during this processing to a block which is the entry of some
 | 
						|
  // funclet F is actually the set of F's parents -- i.e. the union of colors
 | 
						|
  // of all predecessors of F's entry.  For all other blocks, the color sets
 | 
						|
  // are as defined above.  A post-pass fixes up the block color map to reflect
 | 
						|
  // the same sense of "color" for funclet entries as for other blocks.
 | 
						|
 | 
						|
  Worklist.push_back({EntryBlock, EntryBlock});
 | 
						|
 | 
						|
  while (!Worklist.empty()) {
 | 
						|
    BasicBlock *Visiting;
 | 
						|
    BasicBlock *Color;
 | 
						|
    std::tie(Visiting, Color) = Worklist.pop_back_val();
 | 
						|
    Instruction *VisitingHead = Visiting->getFirstNonPHI();
 | 
						|
    if (VisitingHead->isEHPad() && !isa<CatchEndPadInst>(VisitingHead) &&
 | 
						|
        !isa<CleanupEndPadInst>(VisitingHead)) {
 | 
						|
      // Mark this as a funclet head as a member of itself.
 | 
						|
      FuncletBlocks[Visiting].insert(Visiting);
 | 
						|
      // Queue exits (i.e. successors of rets/endpads) with the parent color.
 | 
						|
      // Skip any exits that are catchendpads, since the parent color must then
 | 
						|
      // represent one of the catches chained to that catchendpad, but the
 | 
						|
      // catchendpad should get the color of the common parent of all its
 | 
						|
      // chained catches (i.e. the grandparent color of the current pad).
 | 
						|
      // We don't need to worry abou catchendpads going unvisited, since the
 | 
						|
      // catches chained to them must have unwind edges to them by which we will
 | 
						|
      // visit them.
 | 
						|
      for (User *U : VisitingHead->users()) {
 | 
						|
        if (auto *Exit = dyn_cast<TerminatorInst>(U)) {
 | 
						|
          for (BasicBlock *Succ : successors(Exit->getParent()))
 | 
						|
            if (!isa<CatchEndPadInst>(*Succ->getFirstNonPHI()))
 | 
						|
              if (BlockColors[Succ].insert(Color).second)
 | 
						|
                Worklist.push_back({Succ, Color});
 | 
						|
        }
 | 
						|
      }
 | 
						|
      // Handle CatchPad specially since its successors need different colors.
 | 
						|
      if (CatchPadInst *CatchPad = dyn_cast<CatchPadInst>(VisitingHead)) {
 | 
						|
        // Visit the normal successor with the color of the new EH pad, and
 | 
						|
        // visit the unwind successor with the color of the parent.
 | 
						|
        BasicBlock *NormalSucc = CatchPad->getNormalDest();
 | 
						|
        if (BlockColors[NormalSucc].insert(Visiting).second) {
 | 
						|
          Worklist.push_back({NormalSucc, Visiting});
 | 
						|
        }
 | 
						|
        BasicBlock *UnwindSucc = CatchPad->getUnwindDest();
 | 
						|
        if (BlockColors[UnwindSucc].insert(Color).second) {
 | 
						|
          Worklist.push_back({UnwindSucc, Color});
 | 
						|
        }
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
      // Switch color to the current node, except for terminate pads which
 | 
						|
      // have no bodies and only unwind successors and so need their successors
 | 
						|
      // visited with the color of the parent.
 | 
						|
      if (!isa<TerminatePadInst>(VisitingHead))
 | 
						|
        Color = Visiting;
 | 
						|
    } else {
 | 
						|
      // Note that this is a member of the given color.
 | 
						|
      FuncletBlocks[Color].insert(Visiting);
 | 
						|
    }
 | 
						|
 | 
						|
    TerminatorInst *Terminator = Visiting->getTerminator();
 | 
						|
    if (isa<CleanupReturnInst>(Terminator) ||
 | 
						|
        isa<CatchReturnInst>(Terminator) ||
 | 
						|
        isa<CleanupEndPadInst>(Terminator)) {
 | 
						|
      // These blocks' successors have already been queued with the parent
 | 
						|
      // color.
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    for (BasicBlock *Succ : successors(Visiting)) {
 | 
						|
      if (isa<CatchEndPadInst>(Succ->getFirstNonPHI())) {
 | 
						|
        // The catchendpad needs to be visited with the parent's color, not
 | 
						|
        // the current color.  This will happen in the code above that visits
 | 
						|
        // any catchpad unwind successor with the parent color, so we can
 | 
						|
        // safely skip this successor here.
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
      if (BlockColors[Succ].insert(Color).second) {
 | 
						|
        Worklist.push_back({Succ, Color});
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // The processing above actually accumulated the parent set for this
 | 
						|
  // funclet into the color set for its entry; use the parent set to
 | 
						|
  // populate the children map, and reset the color set to include just
 | 
						|
  // the funclet itself (no instruction can target a funclet entry except on
 | 
						|
  // that transitions to the child funclet).
 | 
						|
  for (BasicBlock *FuncletEntry : EntryBlocks) {
 | 
						|
    std::set<BasicBlock *> &ColorMapItem = BlockColors[FuncletEntry];
 | 
						|
    for (BasicBlock *Parent : ColorMapItem)
 | 
						|
      FuncletChildren[Parent].insert(FuncletEntry);
 | 
						|
    ColorMapItem.clear();
 | 
						|
    ColorMapItem.insert(FuncletEntry);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void WinEHPrepare::colorFunclets(Function &F,
 | 
						|
                                 SmallVectorImpl<BasicBlock *> &EntryBlocks) {
 | 
						|
  ::colorFunclets(F, EntryBlocks, BlockColors, FuncletBlocks, FuncletChildren);
 | 
						|
}
 | 
						|
 | 
						|
void llvm::calculateCatchReturnSuccessorColors(const Function *Fn,
 | 
						|
                                               WinEHFuncInfo &FuncInfo) {
 | 
						|
  SmallVector<BasicBlock *, 4> EntryBlocks;
 | 
						|
  // colorFunclets needs the set of EntryBlocks, get them using
 | 
						|
  // findFuncletEntryPoints.
 | 
						|
  findFuncletEntryPoints(const_cast<Function &>(*Fn), EntryBlocks);
 | 
						|
 | 
						|
  std::map<BasicBlock *, std::set<BasicBlock *>> BlockColors;
 | 
						|
  std::map<BasicBlock *, std::set<BasicBlock *>> FuncletBlocks;
 | 
						|
  std::map<BasicBlock *, std::set<BasicBlock *>> FuncletChildren;
 | 
						|
  // Figure out which basic blocks belong to which funclets.
 | 
						|
  colorFunclets(const_cast<Function &>(*Fn), EntryBlocks, BlockColors,
 | 
						|
                FuncletBlocks, FuncletChildren);
 | 
						|
 | 
						|
  // We need to find the catchret successors.  To do this, we must first find
 | 
						|
  // all the catchpad funclets.
 | 
						|
  for (auto &Funclet : FuncletBlocks) {
 | 
						|
    // Figure out what kind of funclet we are looking at; We only care about
 | 
						|
    // catchpads.
 | 
						|
    BasicBlock *FuncletPadBB = Funclet.first;
 | 
						|
    Instruction *FirstNonPHI = FuncletPadBB->getFirstNonPHI();
 | 
						|
    auto *CatchPad = dyn_cast<CatchPadInst>(FirstNonPHI);
 | 
						|
    if (!CatchPad)
 | 
						|
      continue;
 | 
						|
 | 
						|
    // The users of a catchpad are always catchrets.
 | 
						|
    for (User *Exit : CatchPad->users()) {
 | 
						|
      auto *CatchReturn = dyn_cast<CatchReturnInst>(Exit);
 | 
						|
      if (!CatchReturn)
 | 
						|
        continue;
 | 
						|
      BasicBlock *CatchRetSuccessor = CatchReturn->getSuccessor();
 | 
						|
      std::set<BasicBlock *> &SuccessorColors = BlockColors[CatchRetSuccessor];
 | 
						|
      assert(SuccessorColors.size() == 1 && "Expected BB to be monochrome!");
 | 
						|
      BasicBlock *Color = *SuccessorColors.begin();
 | 
						|
      // Record the catchret successor's funclet membership.
 | 
						|
      FuncInfo.CatchRetSuccessorColorMap[CatchReturn] = Color;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void WinEHPrepare::demotePHIsOnFunclets(Function &F) {
 | 
						|
  // Strip PHI nodes off of EH pads.
 | 
						|
  SmallVector<PHINode *, 16> PHINodes;
 | 
						|
  for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE;) {
 | 
						|
    BasicBlock *BB = &*FI++;
 | 
						|
    if (!BB->isEHPad())
 | 
						|
      continue;
 | 
						|
    for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE;) {
 | 
						|
      Instruction *I = &*BI++;
 | 
						|
      auto *PN = dyn_cast<PHINode>(I);
 | 
						|
      // Stop at the first non-PHI.
 | 
						|
      if (!PN)
 | 
						|
        break;
 | 
						|
 | 
						|
      AllocaInst *SpillSlot = insertPHILoads(PN, F);
 | 
						|
      if (SpillSlot)
 | 
						|
        insertPHIStores(PN, SpillSlot);
 | 
						|
 | 
						|
      PHINodes.push_back(PN);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  for (auto *PN : PHINodes) {
 | 
						|
    // There may be lingering uses on other EH PHIs being removed
 | 
						|
    PN->replaceAllUsesWith(UndefValue::get(PN->getType()));
 | 
						|
    PN->eraseFromParent();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void WinEHPrepare::demoteUsesBetweenFunclets(Function &F) {
 | 
						|
  // Turn all inter-funclet uses of a Value into loads and stores.
 | 
						|
  for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE;) {
 | 
						|
    BasicBlock *BB = &*FI++;
 | 
						|
    std::set<BasicBlock *> &ColorsForBB = BlockColors[BB];
 | 
						|
    for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE;) {
 | 
						|
      Instruction *I = &*BI++;
 | 
						|
      // Funclets are permitted to use static allocas.
 | 
						|
      if (auto *AI = dyn_cast<AllocaInst>(I))
 | 
						|
        if (AI->isStaticAlloca())
 | 
						|
          continue;
 | 
						|
 | 
						|
      demoteNonlocalUses(I, ColorsForBB, F);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void WinEHPrepare::demoteArgumentUses(Function &F) {
 | 
						|
  // Also demote function parameters used in funclets.
 | 
						|
  std::set<BasicBlock *> &ColorsForEntry = BlockColors[&F.getEntryBlock()];
 | 
						|
  for (Argument &Arg : F.args())
 | 
						|
    demoteNonlocalUses(&Arg, ColorsForEntry, F);
 | 
						|
}
 | 
						|
 | 
						|
void WinEHPrepare::cloneCommonBlocks(
 | 
						|
    Function &F, SmallVectorImpl<BasicBlock *> &EntryBlocks) {
 | 
						|
  // We need to clone all blocks which belong to multiple funclets.  Values are
 | 
						|
  // remapped throughout the funclet to propogate both the new instructions
 | 
						|
  // *and* the new basic blocks themselves.
 | 
						|
  for (BasicBlock *FuncletPadBB : EntryBlocks) {
 | 
						|
    std::set<BasicBlock *> &BlocksInFunclet = FuncletBlocks[FuncletPadBB];
 | 
						|
 | 
						|
    std::map<BasicBlock *, BasicBlock *> Orig2Clone;
 | 
						|
    ValueToValueMapTy VMap;
 | 
						|
    for (BasicBlock *BB : BlocksInFunclet) {
 | 
						|
      std::set<BasicBlock *> &ColorsForBB = BlockColors[BB];
 | 
						|
      // We don't need to do anything if the block is monochromatic.
 | 
						|
      size_t NumColorsForBB = ColorsForBB.size();
 | 
						|
      if (NumColorsForBB == 1)
 | 
						|
        continue;
 | 
						|
 | 
						|
      // Create a new basic block and copy instructions into it!
 | 
						|
      BasicBlock *CBB =
 | 
						|
          CloneBasicBlock(BB, VMap, Twine(".for.", FuncletPadBB->getName()));
 | 
						|
      // Insert the clone immediately after the original to ensure determinism
 | 
						|
      // and to keep the same relative ordering of any funclet's blocks.
 | 
						|
      CBB->insertInto(&F, BB->getNextNode());
 | 
						|
 | 
						|
      // Add basic block mapping.
 | 
						|
      VMap[BB] = CBB;
 | 
						|
 | 
						|
      // Record delta operations that we need to perform to our color mappings.
 | 
						|
      Orig2Clone[BB] = CBB;
 | 
						|
    }
 | 
						|
 | 
						|
    // If nothing was cloned, we're done cloning in this funclet.
 | 
						|
    if (Orig2Clone.empty())
 | 
						|
      continue;
 | 
						|
 | 
						|
    // Update our color mappings to reflect that one block has lost a color and
 | 
						|
    // another has gained a color.
 | 
						|
    for (auto &BBMapping : Orig2Clone) {
 | 
						|
      BasicBlock *OldBlock = BBMapping.first;
 | 
						|
      BasicBlock *NewBlock = BBMapping.second;
 | 
						|
 | 
						|
      BlocksInFunclet.insert(NewBlock);
 | 
						|
      BlockColors[NewBlock].insert(FuncletPadBB);
 | 
						|
 | 
						|
      BlocksInFunclet.erase(OldBlock);
 | 
						|
      BlockColors[OldBlock].erase(FuncletPadBB);
 | 
						|
    }
 | 
						|
 | 
						|
    // Loop over all of the instructions in this funclet, fixing up operand
 | 
						|
    // references as we go.  This uses VMap to do all the hard work.
 | 
						|
    for (BasicBlock *BB : BlocksInFunclet)
 | 
						|
      // Loop over all instructions, fixing each one as we find it...
 | 
						|
      for (Instruction &I : *BB)
 | 
						|
        RemapInstruction(&I, VMap,
 | 
						|
                         RF_IgnoreMissingEntries | RF_NoModuleLevelChanges);
 | 
						|
 | 
						|
    // Check to see if SuccBB has PHI nodes. If so, we need to add entries to
 | 
						|
    // the PHI nodes for NewBB now.
 | 
						|
    for (auto &BBMapping : Orig2Clone) {
 | 
						|
      BasicBlock *OldBlock = BBMapping.first;
 | 
						|
      BasicBlock *NewBlock = BBMapping.second;
 | 
						|
      for (BasicBlock *SuccBB : successors(NewBlock)) {
 | 
						|
        for (Instruction &SuccI : *SuccBB) {
 | 
						|
          auto *SuccPN = dyn_cast<PHINode>(&SuccI);
 | 
						|
          if (!SuccPN)
 | 
						|
            break;
 | 
						|
 | 
						|
          // Ok, we have a PHI node.  Figure out what the incoming value was for
 | 
						|
          // the OldBlock.
 | 
						|
          int OldBlockIdx = SuccPN->getBasicBlockIndex(OldBlock);
 | 
						|
          if (OldBlockIdx == -1)
 | 
						|
            break;
 | 
						|
          Value *IV = SuccPN->getIncomingValue(OldBlockIdx);
 | 
						|
 | 
						|
          // Remap the value if necessary.
 | 
						|
          if (auto *Inst = dyn_cast<Instruction>(IV)) {
 | 
						|
            ValueToValueMapTy::iterator I = VMap.find(Inst);
 | 
						|
            if (I != VMap.end())
 | 
						|
              IV = I->second;
 | 
						|
          }
 | 
						|
 | 
						|
          SuccPN->addIncoming(IV, NewBlock);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    for (ValueToValueMapTy::value_type VT : VMap) {
 | 
						|
      // If there were values defined in BB that are used outside the funclet,
 | 
						|
      // then we now have to update all uses of the value to use either the
 | 
						|
      // original value, the cloned value, or some PHI derived value.  This can
 | 
						|
      // require arbitrary PHI insertion, of which we are prepared to do, clean
 | 
						|
      // these up now.
 | 
						|
      SmallVector<Use *, 16> UsesToRename;
 | 
						|
 | 
						|
      auto *OldI = dyn_cast<Instruction>(const_cast<Value *>(VT.first));
 | 
						|
      if (!OldI)
 | 
						|
        continue;
 | 
						|
      auto *NewI = cast<Instruction>(VT.second);
 | 
						|
      // Scan all uses of this instruction to see if it is used outside of its
 | 
						|
      // funclet, and if so, record them in UsesToRename.
 | 
						|
      for (Use &U : OldI->uses()) {
 | 
						|
        Instruction *UserI = cast<Instruction>(U.getUser());
 | 
						|
        BasicBlock *UserBB = UserI->getParent();
 | 
						|
        std::set<BasicBlock *> &ColorsForUserBB = BlockColors[UserBB];
 | 
						|
        assert(!ColorsForUserBB.empty());
 | 
						|
        if (ColorsForUserBB.size() > 1 ||
 | 
						|
            *ColorsForUserBB.begin() != FuncletPadBB)
 | 
						|
          UsesToRename.push_back(&U);
 | 
						|
      }
 | 
						|
 | 
						|
      // If there are no uses outside the block, we're done with this
 | 
						|
      // instruction.
 | 
						|
      if (UsesToRename.empty())
 | 
						|
        continue;
 | 
						|
 | 
						|
      // We found a use of OldI outside of the funclet.  Rename all uses of OldI
 | 
						|
      // that are outside its funclet to be uses of the appropriate PHI node
 | 
						|
      // etc.
 | 
						|
      SSAUpdater SSAUpdate;
 | 
						|
      SSAUpdate.Initialize(OldI->getType(), OldI->getName());
 | 
						|
      SSAUpdate.AddAvailableValue(OldI->getParent(), OldI);
 | 
						|
      SSAUpdate.AddAvailableValue(NewI->getParent(), NewI);
 | 
						|
 | 
						|
      while (!UsesToRename.empty())
 | 
						|
        SSAUpdate.RewriteUseAfterInsertions(*UsesToRename.pop_back_val());
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void WinEHPrepare::removeImplausibleTerminators(Function &F) {
 | 
						|
  // Remove implausible terminators and replace them with UnreachableInst.
 | 
						|
  for (auto &Funclet : FuncletBlocks) {
 | 
						|
    BasicBlock *FuncletPadBB = Funclet.first;
 | 
						|
    std::set<BasicBlock *> &BlocksInFunclet = Funclet.second;
 | 
						|
    Instruction *FirstNonPHI = FuncletPadBB->getFirstNonPHI();
 | 
						|
    auto *CatchPad = dyn_cast<CatchPadInst>(FirstNonPHI);
 | 
						|
    auto *CleanupPad = dyn_cast<CleanupPadInst>(FirstNonPHI);
 | 
						|
 | 
						|
    for (BasicBlock *BB : BlocksInFunclet) {
 | 
						|
      TerminatorInst *TI = BB->getTerminator();
 | 
						|
      // CatchPadInst and CleanupPadInst can't transfer control to a ReturnInst.
 | 
						|
      bool IsUnreachableRet = isa<ReturnInst>(TI) && (CatchPad || CleanupPad);
 | 
						|
      // The token consumed by a CatchReturnInst must match the funclet token.
 | 
						|
      bool IsUnreachableCatchret = false;
 | 
						|
      if (auto *CRI = dyn_cast<CatchReturnInst>(TI))
 | 
						|
        IsUnreachableCatchret = CRI->getCatchPad() != CatchPad;
 | 
						|
      // The token consumed by a CleanupReturnInst must match the funclet token.
 | 
						|
      bool IsUnreachableCleanupret = false;
 | 
						|
      if (auto *CRI = dyn_cast<CleanupReturnInst>(TI))
 | 
						|
        IsUnreachableCleanupret = CRI->getCleanupPad() != CleanupPad;
 | 
						|
      // The token consumed by a CleanupEndPadInst must match the funclet token.
 | 
						|
      bool IsUnreachableCleanupendpad = false;
 | 
						|
      if (auto *CEPI = dyn_cast<CleanupEndPadInst>(TI))
 | 
						|
        IsUnreachableCleanupendpad = CEPI->getCleanupPad() != CleanupPad;
 | 
						|
      if (IsUnreachableRet || IsUnreachableCatchret ||
 | 
						|
          IsUnreachableCleanupret || IsUnreachableCleanupendpad) {
 | 
						|
        // Loop through all of our successors and make sure they know that one
 | 
						|
        // of their predecessors is going away.
 | 
						|
        for (BasicBlock *SuccBB : TI->successors())
 | 
						|
          SuccBB->removePredecessor(BB);
 | 
						|
 | 
						|
        if (IsUnreachableCleanupendpad) {
 | 
						|
          // We can't simply replace a cleanupendpad with unreachable, because
 | 
						|
          // its predecessor edges are EH edges and unreachable is not an EH
 | 
						|
          // pad.  Change all predecessors to the "unwind to caller" form.
 | 
						|
          for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB);
 | 
						|
               PI != PE;) {
 | 
						|
            BasicBlock *Pred = *PI++;
 | 
						|
            removeUnwindEdge(Pred);
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        new UnreachableInst(BB->getContext(), TI);
 | 
						|
        TI->eraseFromParent();
 | 
						|
      }
 | 
						|
      // FIXME: Check for invokes/cleanuprets/cleanupendpads which unwind to
 | 
						|
      // implausible catchendpads (i.e. catchendpad not in immediate parent
 | 
						|
      // funclet).
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void WinEHPrepare::cleanupPreparedFunclets(Function &F) {
 | 
						|
  // Clean-up some of the mess we made by removing useles PHI nodes, trivial
 | 
						|
  // branches, etc.
 | 
						|
  for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE;) {
 | 
						|
    BasicBlock *BB = &*FI++;
 | 
						|
    SimplifyInstructionsInBlock(BB);
 | 
						|
    ConstantFoldTerminator(BB, /*DeleteDeadConditions=*/true);
 | 
						|
    MergeBlockIntoPredecessor(BB);
 | 
						|
  }
 | 
						|
 | 
						|
  // We might have some unreachable blocks after cleaning up some impossible
 | 
						|
  // control flow.
 | 
						|
  removeUnreachableBlocks(F);
 | 
						|
}
 | 
						|
 | 
						|
void WinEHPrepare::verifyPreparedFunclets(Function &F) {
 | 
						|
  // Recolor the CFG to verify that all is well.
 | 
						|
  for (BasicBlock &BB : F) {
 | 
						|
    size_t NumColors = BlockColors[&BB].size();
 | 
						|
    assert(NumColors == 1 && "Expected monochromatic BB!");
 | 
						|
    if (NumColors == 0)
 | 
						|
      report_fatal_error("Uncolored BB!");
 | 
						|
    if (NumColors > 1)
 | 
						|
      report_fatal_error("Multicolor BB!");
 | 
						|
    if (!DisableDemotion) {
 | 
						|
      bool EHPadHasPHI = BB.isEHPad() && isa<PHINode>(BB.begin());
 | 
						|
      assert(!EHPadHasPHI && "EH Pad still has a PHI!");
 | 
						|
      if (EHPadHasPHI)
 | 
						|
        report_fatal_error("EH Pad still has a PHI!");
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool WinEHPrepare::prepareExplicitEH(
 | 
						|
    Function &F, SmallVectorImpl<BasicBlock *> &EntryBlocks) {
 | 
						|
  replaceTerminatePadWithCleanup(F);
 | 
						|
 | 
						|
  // Determine which blocks are reachable from which funclet entries.
 | 
						|
  colorFunclets(F, EntryBlocks);
 | 
						|
 | 
						|
  if (!DisableDemotion) {
 | 
						|
    demotePHIsOnFunclets(F);
 | 
						|
 | 
						|
    demoteUsesBetweenFunclets(F);
 | 
						|
 | 
						|
    demoteArgumentUses(F);
 | 
						|
  }
 | 
						|
 | 
						|
  cloneCommonBlocks(F, EntryBlocks);
 | 
						|
 | 
						|
  if (!DisableCleanups) {
 | 
						|
    removeImplausibleTerminators(F);
 | 
						|
 | 
						|
    cleanupPreparedFunclets(F);
 | 
						|
  }
 | 
						|
 | 
						|
  verifyPreparedFunclets(F);
 | 
						|
 | 
						|
  BlockColors.clear();
 | 
						|
  FuncletBlocks.clear();
 | 
						|
  FuncletChildren.clear();
 | 
						|
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
// TODO: Share loads when one use dominates another, or when a catchpad exit
 | 
						|
// dominates uses (needs dominators).
 | 
						|
AllocaInst *WinEHPrepare::insertPHILoads(PHINode *PN, Function &F) {
 | 
						|
  BasicBlock *PHIBlock = PN->getParent();
 | 
						|
  AllocaInst *SpillSlot = nullptr;
 | 
						|
 | 
						|
  if (isa<CleanupPadInst>(PHIBlock->getFirstNonPHI())) {
 | 
						|
    // Insert a load in place of the PHI and replace all uses.
 | 
						|
    SpillSlot = new AllocaInst(PN->getType(), nullptr,
 | 
						|
                               Twine(PN->getName(), ".wineh.spillslot"),
 | 
						|
                               &F.getEntryBlock().front());
 | 
						|
    Value *V = new LoadInst(SpillSlot, Twine(PN->getName(), ".wineh.reload"),
 | 
						|
                            &*PHIBlock->getFirstInsertionPt());
 | 
						|
    PN->replaceAllUsesWith(V);
 | 
						|
    return SpillSlot;
 | 
						|
  }
 | 
						|
 | 
						|
  DenseMap<BasicBlock *, Value *> Loads;
 | 
						|
  for (Value::use_iterator UI = PN->use_begin(), UE = PN->use_end();
 | 
						|
       UI != UE;) {
 | 
						|
    Use &U = *UI++;
 | 
						|
    auto *UsingInst = cast<Instruction>(U.getUser());
 | 
						|
    BasicBlock *UsingBB = UsingInst->getParent();
 | 
						|
    if (UsingBB->isEHPad()) {
 | 
						|
      // Use is on an EH pad phi.  Leave it alone; we'll insert loads and
 | 
						|
      // stores for it separately.
 | 
						|
      assert(isa<PHINode>(UsingInst));
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    replaceUseWithLoad(PN, U, SpillSlot, Loads, F);
 | 
						|
  }
 | 
						|
  return SpillSlot;
 | 
						|
}
 | 
						|
 | 
						|
// TODO: improve store placement.  Inserting at def is probably good, but need
 | 
						|
// to be careful not to introduce interfering stores (needs liveness analysis).
 | 
						|
// TODO: identify related phi nodes that can share spill slots, and share them
 | 
						|
// (also needs liveness).
 | 
						|
void WinEHPrepare::insertPHIStores(PHINode *OriginalPHI,
 | 
						|
                                   AllocaInst *SpillSlot) {
 | 
						|
  // Use a worklist of (Block, Value) pairs -- the given Value needs to be
 | 
						|
  // stored to the spill slot by the end of the given Block.
 | 
						|
  SmallVector<std::pair<BasicBlock *, Value *>, 4> Worklist;
 | 
						|
 | 
						|
  Worklist.push_back({OriginalPHI->getParent(), OriginalPHI});
 | 
						|
 | 
						|
  while (!Worklist.empty()) {
 | 
						|
    BasicBlock *EHBlock;
 | 
						|
    Value *InVal;
 | 
						|
    std::tie(EHBlock, InVal) = Worklist.pop_back_val();
 | 
						|
 | 
						|
    PHINode *PN = dyn_cast<PHINode>(InVal);
 | 
						|
    if (PN && PN->getParent() == EHBlock) {
 | 
						|
      // The value is defined by another PHI we need to remove, with no room to
 | 
						|
      // insert a store after the PHI, so each predecessor needs to store its
 | 
						|
      // incoming value.
 | 
						|
      for (unsigned i = 0, e = PN->getNumIncomingValues(); i < e; ++i) {
 | 
						|
        Value *PredVal = PN->getIncomingValue(i);
 | 
						|
 | 
						|
        // Undef can safely be skipped.
 | 
						|
        if (isa<UndefValue>(PredVal))
 | 
						|
          continue;
 | 
						|
 | 
						|
        insertPHIStore(PN->getIncomingBlock(i), PredVal, SpillSlot, Worklist);
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      // We need to store InVal, which dominates EHBlock, but can't put a store
 | 
						|
      // in EHBlock, so need to put stores in each predecessor.
 | 
						|
      for (BasicBlock *PredBlock : predecessors(EHBlock)) {
 | 
						|
        insertPHIStore(PredBlock, InVal, SpillSlot, Worklist);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void WinEHPrepare::insertPHIStore(
 | 
						|
    BasicBlock *PredBlock, Value *PredVal, AllocaInst *SpillSlot,
 | 
						|
    SmallVectorImpl<std::pair<BasicBlock *, Value *>> &Worklist) {
 | 
						|
 | 
						|
  if (PredBlock->isEHPad() &&
 | 
						|
      !isa<CleanupPadInst>(PredBlock->getFirstNonPHI())) {
 | 
						|
    // Pred is unsplittable, so we need to queue it on the worklist.
 | 
						|
    Worklist.push_back({PredBlock, PredVal});
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  // Otherwise, insert the store at the end of the basic block.
 | 
						|
  new StoreInst(PredVal, SpillSlot, PredBlock->getTerminator());
 | 
						|
}
 | 
						|
 | 
						|
// TODO: Share loads for same-funclet uses (requires dominators if funclets
 | 
						|
// aren't properly nested).
 | 
						|
void WinEHPrepare::demoteNonlocalUses(Value *V,
 | 
						|
                                      std::set<BasicBlock *> &ColorsForBB,
 | 
						|
                                      Function &F) {
 | 
						|
  // Tokens can only be used non-locally due to control flow involving
 | 
						|
  // unreachable edges.  Don't try to demote the token usage, we'll simply
 | 
						|
  // delete the cloned user later.
 | 
						|
  if (isa<CatchPadInst>(V) || isa<CleanupPadInst>(V))
 | 
						|
    return;
 | 
						|
 | 
						|
  DenseMap<BasicBlock *, Value *> Loads;
 | 
						|
  AllocaInst *SpillSlot = nullptr;
 | 
						|
  for (Value::use_iterator UI = V->use_begin(), UE = V->use_end(); UI != UE;) {
 | 
						|
    Use &U = *UI++;
 | 
						|
    auto *UsingInst = cast<Instruction>(U.getUser());
 | 
						|
    BasicBlock *UsingBB = UsingInst->getParent();
 | 
						|
 | 
						|
    // Is the Use inside a block which is colored the same as the Def?
 | 
						|
    // If so, we don't need to escape the Def because we will clone
 | 
						|
    // ourselves our own private copy.
 | 
						|
    std::set<BasicBlock *> &ColorsForUsingBB = BlockColors[UsingBB];
 | 
						|
    if (ColorsForUsingBB == ColorsForBB)
 | 
						|
      continue;
 | 
						|
 | 
						|
    replaceUseWithLoad(V, U, SpillSlot, Loads, F);
 | 
						|
  }
 | 
						|
  if (SpillSlot) {
 | 
						|
    // Insert stores of the computed value into the stack slot.
 | 
						|
    // We have to be careful if I is an invoke instruction,
 | 
						|
    // because we can't insert the store AFTER the terminator instruction.
 | 
						|
    BasicBlock::iterator InsertPt;
 | 
						|
    if (isa<Argument>(V)) {
 | 
						|
      InsertPt = F.getEntryBlock().getTerminator()->getIterator();
 | 
						|
    } else if (isa<TerminatorInst>(V)) {
 | 
						|
      auto *II = cast<InvokeInst>(V);
 | 
						|
      // We cannot demote invoke instructions to the stack if their normal
 | 
						|
      // edge is critical. Therefore, split the critical edge and create a
 | 
						|
      // basic block into which the store can be inserted.
 | 
						|
      if (!II->getNormalDest()->getSinglePredecessor()) {
 | 
						|
        unsigned SuccNum =
 | 
						|
            GetSuccessorNumber(II->getParent(), II->getNormalDest());
 | 
						|
        assert(isCriticalEdge(II, SuccNum) && "Expected a critical edge!");
 | 
						|
        BasicBlock *NewBlock = SplitCriticalEdge(II, SuccNum);
 | 
						|
        assert(NewBlock && "Unable to split critical edge.");
 | 
						|
        // Update the color mapping for the newly split edge.
 | 
						|
        std::set<BasicBlock *> &ColorsForUsingBB = BlockColors[II->getParent()];
 | 
						|
        BlockColors[NewBlock] = ColorsForUsingBB;
 | 
						|
        for (BasicBlock *FuncletPad : ColorsForUsingBB)
 | 
						|
          FuncletBlocks[FuncletPad].insert(NewBlock);
 | 
						|
      }
 | 
						|
      InsertPt = II->getNormalDest()->getFirstInsertionPt();
 | 
						|
    } else {
 | 
						|
      InsertPt = cast<Instruction>(V)->getIterator();
 | 
						|
      ++InsertPt;
 | 
						|
      // Don't insert before PHI nodes or EH pad instrs.
 | 
						|
      for (; isa<PHINode>(InsertPt) || InsertPt->isEHPad(); ++InsertPt)
 | 
						|
        ;
 | 
						|
    }
 | 
						|
    new StoreInst(V, SpillSlot, &*InsertPt);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void WinEHPrepare::replaceUseWithLoad(Value *V, Use &U, AllocaInst *&SpillSlot,
 | 
						|
                                      DenseMap<BasicBlock *, Value *> &Loads,
 | 
						|
                                      Function &F) {
 | 
						|
  // Lazilly create the spill slot.
 | 
						|
  if (!SpillSlot)
 | 
						|
    SpillSlot = new AllocaInst(V->getType(), nullptr,
 | 
						|
                               Twine(V->getName(), ".wineh.spillslot"),
 | 
						|
                               &F.getEntryBlock().front());
 | 
						|
 | 
						|
  auto *UsingInst = cast<Instruction>(U.getUser());
 | 
						|
  if (auto *UsingPHI = dyn_cast<PHINode>(UsingInst)) {
 | 
						|
    // If this is a PHI node, we can't insert a load of the value before
 | 
						|
    // the use.  Instead insert the load in the predecessor block
 | 
						|
    // corresponding to the incoming value.
 | 
						|
    //
 | 
						|
    // Note that if there are multiple edges from a basic block to this
 | 
						|
    // PHI node that we cannot have multiple loads.  The problem is that
 | 
						|
    // the resulting PHI node will have multiple values (from each load)
 | 
						|
    // coming in from the same block, which is illegal SSA form.
 | 
						|
    // For this reason, we keep track of and reuse loads we insert.
 | 
						|
    BasicBlock *IncomingBlock = UsingPHI->getIncomingBlock(U);
 | 
						|
    if (auto *CatchRet =
 | 
						|
            dyn_cast<CatchReturnInst>(IncomingBlock->getTerminator())) {
 | 
						|
      // Putting a load above a catchret and use on the phi would still leave
 | 
						|
      // a cross-funclet def/use.  We need to split the edge, change the
 | 
						|
      // catchret to target the new block, and put the load there.
 | 
						|
      BasicBlock *PHIBlock = UsingInst->getParent();
 | 
						|
      BasicBlock *NewBlock = SplitEdge(IncomingBlock, PHIBlock);
 | 
						|
      // SplitEdge gives us:
 | 
						|
      //   IncomingBlock:
 | 
						|
      //     ...
 | 
						|
      //     br label %NewBlock
 | 
						|
      //   NewBlock:
 | 
						|
      //     catchret label %PHIBlock
 | 
						|
      // But we need:
 | 
						|
      //   IncomingBlock:
 | 
						|
      //     ...
 | 
						|
      //     catchret label %NewBlock
 | 
						|
      //   NewBlock:
 | 
						|
      //     br label %PHIBlock
 | 
						|
      // So move the terminators to each others' blocks and swap their
 | 
						|
      // successors.
 | 
						|
      BranchInst *Goto = cast<BranchInst>(IncomingBlock->getTerminator());
 | 
						|
      Goto->removeFromParent();
 | 
						|
      CatchRet->removeFromParent();
 | 
						|
      IncomingBlock->getInstList().push_back(CatchRet);
 | 
						|
      NewBlock->getInstList().push_back(Goto);
 | 
						|
      Goto->setSuccessor(0, PHIBlock);
 | 
						|
      CatchRet->setSuccessor(NewBlock);
 | 
						|
      // Update the color mapping for the newly split edge.
 | 
						|
      std::set<BasicBlock *> &ColorsForPHIBlock = BlockColors[PHIBlock];
 | 
						|
      BlockColors[NewBlock] = ColorsForPHIBlock;
 | 
						|
      for (BasicBlock *FuncletPad : ColorsForPHIBlock)
 | 
						|
        FuncletBlocks[FuncletPad].insert(NewBlock);
 | 
						|
      // Treat the new block as incoming for load insertion.
 | 
						|
      IncomingBlock = NewBlock;
 | 
						|
    }
 | 
						|
    Value *&Load = Loads[IncomingBlock];
 | 
						|
    // Insert the load into the predecessor block
 | 
						|
    if (!Load)
 | 
						|
      Load = new LoadInst(SpillSlot, Twine(V->getName(), ".wineh.reload"),
 | 
						|
                          /*Volatile=*/false, IncomingBlock->getTerminator());
 | 
						|
 | 
						|
    U.set(Load);
 | 
						|
  } else {
 | 
						|
    // Reload right before the old use.
 | 
						|
    auto *Load = new LoadInst(SpillSlot, Twine(V->getName(), ".wineh.reload"),
 | 
						|
                              /*Volatile=*/false, UsingInst);
 | 
						|
    U.set(Load);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void WinEHFuncInfo::addIPToStateRange(const BasicBlock *PadBB,
 | 
						|
                                      MCSymbol *InvokeBegin,
 | 
						|
                                      MCSymbol *InvokeEnd) {
 | 
						|
  assert(PadBB->isEHPad() && EHPadStateMap.count(PadBB->getFirstNonPHI()) &&
 | 
						|
         "should get EH pad BB with precomputed state");
 | 
						|
  InvokeToStateMap[InvokeBegin] =
 | 
						|
      std::make_pair(EHPadStateMap[PadBB->getFirstNonPHI()], InvokeEnd);
 | 
						|
}
 |