|  | //===-- WinEHPrepare - Prepare exception handling for code generation ---===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // 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/WinEHPrepare.h" | 
|  | #include "llvm/ADT/DenseMap.h" | 
|  | #include "llvm/ADT/MapVector.h" | 
|  | #include "llvm/ADT/STLExtras.h" | 
|  | #include "llvm/CodeGen/MachineBasicBlock.h" | 
|  | #include "llvm/CodeGen/Passes.h" | 
|  | #include "llvm/CodeGen/WinEHFuncInfo.h" | 
|  | #include "llvm/IR/Constants.h" | 
|  | #include "llvm/IR/EHPersonalities.h" | 
|  | #include "llvm/IR/Instructions.h" | 
|  | #include "llvm/IR/Module.h" | 
|  | #include "llvm/IR/Verifier.h" | 
|  | #include "llvm/InitializePasses.h" | 
|  | #include "llvm/Pass.h" | 
|  | #include "llvm/Support/CommandLine.h" | 
|  | #include "llvm/Support/Debug.h" | 
|  | #include "llvm/Support/raw_ostream.h" | 
|  | #include "llvm/TargetParser/Triple.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 "win-eh-prepare" | 
|  |  | 
|  | static cl::opt<bool> DisableDemotion( | 
|  | "disable-demotion", cl::Hidden, | 
|  | cl::desc( | 
|  | "Clone multicolor basic blocks but do not demote cross scopes"), | 
|  | 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)); | 
|  |  | 
|  | // TODO: Remove this option when we fully migrate to new pass manager | 
|  | static cl::opt<bool> DemoteCatchSwitchPHIOnlyOpt( | 
|  | "demote-catchswitch-only", cl::Hidden, | 
|  | cl::desc("Demote catchswitch BBs only (for wasm EH)"), cl::init(false)); | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | class WinEHPrepareImpl { | 
|  | public: | 
|  | WinEHPrepareImpl(bool DemoteCatchSwitchPHIOnly) | 
|  | : DemoteCatchSwitchPHIOnly(DemoteCatchSwitchPHIOnly) {} | 
|  |  | 
|  | bool runOnFunction(Function &Fn); | 
|  |  | 
|  | 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); | 
|  | bool prepareExplicitEH(Function &F); | 
|  | void colorFunclets(Function &F); | 
|  |  | 
|  | bool demotePHIsOnFunclets(Function &F, bool DemoteCatchSwitchPHIOnly); | 
|  | bool cloneCommonBlocks(Function &F); | 
|  | bool removeImplausibleInstructions(Function &F); | 
|  | bool cleanupPreparedFunclets(Function &F); | 
|  | void verifyPreparedFunclets(Function &F); | 
|  |  | 
|  | bool DemoteCatchSwitchPHIOnly; | 
|  |  | 
|  | // All fields are reset by runOnFunction. | 
|  | EHPersonality Personality = EHPersonality::Unknown; | 
|  |  | 
|  | const DataLayout *DL = nullptr; | 
|  | DenseMap<BasicBlock *, ColorVector> BlockColors; | 
|  | MapVector<BasicBlock *, std::vector<BasicBlock *>> FuncletBlocks; | 
|  | }; | 
|  |  | 
|  | class WinEHPrepare : public FunctionPass { | 
|  | bool DemoteCatchSwitchPHIOnly; | 
|  |  | 
|  | public: | 
|  | static char ID; // Pass identification, replacement for typeid. | 
|  |  | 
|  | WinEHPrepare(bool DemoteCatchSwitchPHIOnly = false) | 
|  | : FunctionPass(ID), DemoteCatchSwitchPHIOnly(DemoteCatchSwitchPHIOnly) {} | 
|  |  | 
|  | StringRef getPassName() const override { | 
|  | return "Windows exception handling preparation"; | 
|  | } | 
|  |  | 
|  | bool runOnFunction(Function &Fn) override { | 
|  | return WinEHPrepareImpl(DemoteCatchSwitchPHIOnly).runOnFunction(Fn); | 
|  | } | 
|  | }; | 
|  |  | 
|  | } // end anonymous namespace | 
|  |  | 
|  | PreservedAnalyses WinEHPreparePass::run(Function &F, | 
|  | FunctionAnalysisManager &) { | 
|  | bool Changed = WinEHPrepareImpl(DemoteCatchSwitchPHIOnly).runOnFunction(F); | 
|  | return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all(); | 
|  | } | 
|  |  | 
|  | char WinEHPrepare::ID = 0; | 
|  | INITIALIZE_PASS(WinEHPrepare, DEBUG_TYPE, "Prepare Windows exceptions", false, | 
|  | false) | 
|  |  | 
|  | FunctionPass *llvm::createWinEHPass(bool DemoteCatchSwitchPHIOnly) { | 
|  | return new WinEHPrepare(DemoteCatchSwitchPHIOnly); | 
|  | } | 
|  |  | 
|  | bool WinEHPrepareImpl::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 scope-based personality. | 
|  | if (!isScopedEHPersonality(Personality)) | 
|  | return false; | 
|  |  | 
|  | DL = &Fn.getDataLayout(); | 
|  | return prepareExplicitEH(Fn); | 
|  | } | 
|  |  | 
|  | 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 (auto *AI = | 
|  | dyn_cast<AllocaInst>(CPI->getArgOperand(2)->stripPointerCasts())) | 
|  | HT.CatchObj.Alloca = AI; | 
|  | else | 
|  | HT.CatchObj.Alloca = nullptr; | 
|  | TBME.HandlerArray.push_back(HT); | 
|  | } | 
|  | FuncInfo.TryBlockMap.push_back(TBME); | 
|  | } | 
|  |  | 
|  | static BasicBlock *getCleanupRetUnwindDest(const CleanupPadInst *CleanupPad) { | 
|  | for (const User *U : CleanupPad->users()) | 
|  | if (const auto *CRI = dyn_cast<CleanupReturnInst>(U)) | 
|  | return CRI->getUnwindDest(); | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | static void calculateStateNumbersForInvokes(const Function *Fn, | 
|  | WinEHFuncInfo &FuncInfo) { | 
|  | auto *F = const_cast<Function *>(Fn); | 
|  | DenseMap<BasicBlock *, ColorVector> BlockColors = colorEHFunclets(*F); | 
|  | for (BasicBlock &BB : *F) { | 
|  | auto *II = dyn_cast<InvokeInst>(BB.getTerminator()); | 
|  | if (!II) | 
|  | continue; | 
|  |  | 
|  | auto &BBColors = BlockColors[&BB]; | 
|  | assert(BBColors.size() == 1 && "multi-color BB not removed by preparation"); | 
|  | BasicBlock *FuncletEntryBB = BBColors.front(); | 
|  |  | 
|  | BasicBlock *FuncletUnwindDest; | 
|  | auto *FuncletPad = | 
|  | dyn_cast<FuncletPadInst>(FuncletEntryBB->getFirstNonPHIIt()); | 
|  | assert(FuncletPad || FuncletEntryBB == &Fn->getEntryBlock()); | 
|  | if (!FuncletPad) | 
|  | FuncletUnwindDest = nullptr; | 
|  | else if (auto *CatchPad = dyn_cast<CatchPadInst>(FuncletPad)) | 
|  | FuncletUnwindDest = CatchPad->getCatchSwitch()->getUnwindDest(); | 
|  | else if (auto *CleanupPad = dyn_cast<CleanupPadInst>(FuncletPad)) | 
|  | FuncletUnwindDest = getCleanupRetUnwindDest(CleanupPad); | 
|  | else | 
|  | llvm_unreachable("unexpected funclet pad!"); | 
|  |  | 
|  | BasicBlock *InvokeUnwindDest = II->getUnwindDest(); | 
|  | int BaseState = -1; | 
|  | if (FuncletUnwindDest == InvokeUnwindDest) { | 
|  | auto BaseStateI = FuncInfo.FuncletBaseStateMap.find(FuncletPad); | 
|  | if (BaseStateI != FuncInfo.FuncletBaseStateMap.end()) | 
|  | BaseState = BaseStateI->second; | 
|  | } | 
|  |  | 
|  | if (BaseState != -1) { | 
|  | FuncInfo.InvokeStateMap[II] = BaseState; | 
|  | } else { | 
|  | Instruction *PadInst = &*InvokeUnwindDest->getFirstNonPHIIt(); | 
|  | assert(FuncInfo.EHPadStateMap.count(PadInst) && "EH Pad has no state!"); | 
|  | FuncInfo.InvokeStateMap[II] = FuncInfo.EHPadStateMap[PadInst]; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // See comments below for calculateSEHStateForAsynchEH(). | 
|  | // State - incoming State of normal paths | 
|  | struct WorkItem { | 
|  | const BasicBlock *Block; | 
|  | int State; | 
|  | WorkItem(const BasicBlock *BB, int St) { | 
|  | Block = BB; | 
|  | State = St; | 
|  | } | 
|  | }; | 
|  | void llvm::calculateCXXStateForAsynchEH(const BasicBlock *BB, int State, | 
|  | WinEHFuncInfo &EHInfo) { | 
|  | SmallVector<struct WorkItem *, 8> WorkList; | 
|  | struct WorkItem *WI = new WorkItem(BB, State); | 
|  | WorkList.push_back(WI); | 
|  |  | 
|  | while (!WorkList.empty()) { | 
|  | WI = WorkList.pop_back_val(); | 
|  | const BasicBlock *BB = WI->Block; | 
|  | int State = WI->State; | 
|  | delete WI; | 
|  | auto [StateIt, Inserted] = EHInfo.BlockToStateMap.try_emplace(BB); | 
|  | if (!Inserted && StateIt->second <= State) | 
|  | continue; // skip blocks already visited by lower State | 
|  |  | 
|  | BasicBlock::const_iterator It = BB->getFirstNonPHIIt(); | 
|  | const llvm::Instruction *TI = BB->getTerminator(); | 
|  | if (It->isEHPad()) | 
|  | State = EHInfo.EHPadStateMap[&*It]; | 
|  | StateIt->second = State; // Record state, also flag visiting | 
|  |  | 
|  | if ((isa<CleanupReturnInst>(TI) || isa<CatchReturnInst>(TI)) && State > 0) { | 
|  | // Retrive the new State | 
|  | State = EHInfo.CxxUnwindMap[State].ToState; // Retrive next State | 
|  | } else if (isa<InvokeInst>(TI)) { | 
|  | auto *Call = cast<CallBase>(TI); | 
|  | const Function *Fn = Call->getCalledFunction(); | 
|  | if (Fn && Fn->isIntrinsic() && | 
|  | (Fn->getIntrinsicID() == Intrinsic::seh_scope_begin || | 
|  | Fn->getIntrinsicID() == Intrinsic::seh_try_begin)) | 
|  | // Retrive the new State from seh_scope_begin | 
|  | State = EHInfo.InvokeStateMap[cast<InvokeInst>(TI)]; | 
|  | else if (Fn && Fn->isIntrinsic() && | 
|  | (Fn->getIntrinsicID() == Intrinsic::seh_scope_end || | 
|  | Fn->getIntrinsicID() == Intrinsic::seh_try_end)) { | 
|  | // In case of conditional ctor, let's retrieve State from Invoke | 
|  | State = EHInfo.InvokeStateMap[cast<InvokeInst>(TI)]; | 
|  | // end of current state, retrive new state from UnwindMap | 
|  | State = EHInfo.CxxUnwindMap[State].ToState; | 
|  | } | 
|  | } | 
|  | // Continue push successors into worklist | 
|  | for (auto *SuccBB : successors(BB)) { | 
|  | WI = new WorkItem(SuccBB, State); | 
|  | WorkList.push_back(WI); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // The central theory of this routine is based on the following: | 
|  | //   A _try scope is always a SEME (Single Entry Multiple Exits) region | 
|  | //     as jumping into a _try is not allowed | 
|  | //   The single entry must start with a seh_try_begin() invoke with a | 
|  | //     correct State number that is the initial state of the SEME. | 
|  | //   Through control-flow, state number is propagated into all blocks. | 
|  | //   Side exits marked by seh_try_end() will unwind to parent state via | 
|  | //     existing SEHUnwindMap[]. | 
|  | //   Side exits can ONLY jump into parent scopes (lower state number). | 
|  | //   Thus, when a block succeeds various states from its predecessors, | 
|  | //     the lowest State trumphs others. | 
|  | //   If some exits flow to unreachable, propagation on those paths terminate, | 
|  | //     not affecting remaining blocks. | 
|  | void llvm::calculateSEHStateForAsynchEH(const BasicBlock *BB, int State, | 
|  | WinEHFuncInfo &EHInfo) { | 
|  | SmallVector<struct WorkItem *, 8> WorkList; | 
|  | struct WorkItem *WI = new WorkItem(BB, State); | 
|  | WorkList.push_back(WI); | 
|  |  | 
|  | while (!WorkList.empty()) { | 
|  | WI = WorkList.pop_back_val(); | 
|  | const BasicBlock *BB = WI->Block; | 
|  | int State = WI->State; | 
|  | delete WI; | 
|  | if (auto It = EHInfo.BlockToStateMap.find(BB); | 
|  | It != EHInfo.BlockToStateMap.end() && It->second <= State) | 
|  | continue; // skip blocks already visited by lower State | 
|  |  | 
|  | BasicBlock::const_iterator It = BB->getFirstNonPHIIt(); | 
|  | const llvm::Instruction *TI = BB->getTerminator(); | 
|  | if (It->isEHPad()) | 
|  | State = EHInfo.EHPadStateMap[&*It]; | 
|  | EHInfo.BlockToStateMap[BB] = State; // Record state | 
|  |  | 
|  | if (isa<CatchPadInst>(It) && isa<CatchReturnInst>(TI)) { | 
|  | const Constant *FilterOrNull = cast<Constant>( | 
|  | cast<CatchPadInst>(It)->getArgOperand(0)->stripPointerCasts()); | 
|  | const Function *Filter = dyn_cast<Function>(FilterOrNull); | 
|  | if (!Filter || !Filter->getName().starts_with("__IsLocalUnwind")) | 
|  | State = EHInfo.SEHUnwindMap[State].ToState; // Retrive next State | 
|  | } else if ((isa<CleanupReturnInst>(TI) || isa<CatchReturnInst>(TI)) && | 
|  | State > 0) { | 
|  | // Retrive the new State. | 
|  | State = EHInfo.SEHUnwindMap[State].ToState; // Retrive next State | 
|  | } else if (isa<InvokeInst>(TI)) { | 
|  | auto *Call = cast<CallBase>(TI); | 
|  | const Function *Fn = Call->getCalledFunction(); | 
|  | if (Fn && Fn->isIntrinsic() && | 
|  | Fn->getIntrinsicID() == Intrinsic::seh_try_begin) | 
|  | // Retrive the new State from seh_try_begin | 
|  | State = EHInfo.InvokeStateMap[cast<InvokeInst>(TI)]; | 
|  | else if (Fn && Fn->isIntrinsic() && | 
|  | Fn->getIntrinsicID() == Intrinsic::seh_try_end) | 
|  | // end of current state, retrive new state from UnwindMap | 
|  | State = EHInfo.SEHUnwindMap[State].ToState; | 
|  | } | 
|  | // Continue push successors into worklist | 
|  | for (auto *SuccBB : successors(BB)) { | 
|  | WI = new WorkItem(SuccBB, State); | 
|  | WorkList.push_back(WI); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // 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, | 
|  | Value *ParentPad) { | 
|  | const Instruction *TI = BB->getTerminator(); | 
|  | if (isa<InvokeInst>(TI)) | 
|  | return nullptr; | 
|  | if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(TI)) { | 
|  | if (CatchSwitch->getParentPad() != ParentPad) | 
|  | return nullptr; | 
|  | return BB; | 
|  | } | 
|  | assert(!TI->isEHPad() && "unexpected EHPad!"); | 
|  | auto *CleanupPad = cast<CleanupReturnInst>(TI)->getCleanupPad(); | 
|  | if (CleanupPad->getParentPad() != ParentPad) | 
|  | return nullptr; | 
|  | return CleanupPad->getParent(); | 
|  | } | 
|  |  | 
|  | // Starting from a EHPad, Backward walk through control-flow graph | 
|  | // to produce two primary outputs: | 
|  | //      FuncInfo.EHPadStateMap[] and FuncInfo.CxxUnwindMap[] | 
|  | static void calculateCXXStateNumbers(WinEHFuncInfo &FuncInfo, | 
|  | const Instruction *FirstNonPHI, | 
|  | int ParentState) { | 
|  | const BasicBlock *BB = FirstNonPHI->getParent(); | 
|  | assert(BB->isEHPad() && "not a funclet!"); | 
|  |  | 
|  | if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(FirstNonPHI)) { | 
|  | assert(FuncInfo.EHPadStateMap.count(CatchSwitch) == 0 && | 
|  | "shouldn't revist catch funclets!"); | 
|  |  | 
|  | SmallVector<const CatchPadInst *, 2> Handlers; | 
|  | for (const BasicBlock *CatchPadBB : CatchSwitch->handlers()) { | 
|  | auto *CatchPad = cast<CatchPadInst>(CatchPadBB->getFirstNonPHIIt()); | 
|  | Handlers.push_back(CatchPad); | 
|  | } | 
|  | int TryLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr); | 
|  | FuncInfo.EHPadStateMap[CatchSwitch] = TryLow; | 
|  | for (const BasicBlock *PredBlock : predecessors(BB)) | 
|  | if ((PredBlock = getEHPadFromPredecessor(PredBlock, | 
|  | CatchSwitch->getParentPad()))) | 
|  | calculateCXXStateNumbers(FuncInfo, &*PredBlock->getFirstNonPHIIt(), | 
|  | TryLow); | 
|  | int CatchLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr); | 
|  |  | 
|  | // catchpads are separate funclets in C++ EH due to the way rethrow works. | 
|  | int TryHigh = CatchLow - 1; | 
|  |  | 
|  | // MSVC FrameHandler3/4 on x64&Arm64 expect Catch Handlers in $tryMap$ | 
|  | //  stored in pre-order (outer first, inner next), not post-order | 
|  | //  Add to map here.  Fix the CatchHigh after children are processed | 
|  | const Module *Mod = BB->getParent()->getParent(); | 
|  | bool IsPreOrder = Mod->getTargetTriple().isArch64Bit(); | 
|  | if (IsPreOrder) | 
|  | addTryBlockMapEntry(FuncInfo, TryLow, TryHigh, CatchLow, Handlers); | 
|  | unsigned TBMEIdx = FuncInfo.TryBlockMap.size() - 1; | 
|  |  | 
|  | for (const auto *CatchPad : Handlers) { | 
|  | FuncInfo.FuncletBaseStateMap[CatchPad] = CatchLow; | 
|  | FuncInfo.EHPadStateMap[CatchPad] = CatchLow; | 
|  | for (const User *U : CatchPad->users()) { | 
|  | const auto *UserI = cast<Instruction>(U); | 
|  | if (auto *InnerCatchSwitch = dyn_cast<CatchSwitchInst>(UserI)) { | 
|  | BasicBlock *UnwindDest = InnerCatchSwitch->getUnwindDest(); | 
|  | if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest()) | 
|  | calculateCXXStateNumbers(FuncInfo, UserI, CatchLow); | 
|  | } | 
|  | if (auto *InnerCleanupPad = dyn_cast<CleanupPadInst>(UserI)) { | 
|  | BasicBlock *UnwindDest = getCleanupRetUnwindDest(InnerCleanupPad); | 
|  | // If a nested cleanup pad reports a null unwind destination and the | 
|  | // enclosing catch pad doesn't it must be post-dominated by an | 
|  | // unreachable instruction. | 
|  | if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest()) | 
|  | calculateCXXStateNumbers(FuncInfo, UserI, CatchLow); | 
|  | } | 
|  | } | 
|  | } | 
|  | int CatchHigh = FuncInfo.getLastStateNumber(); | 
|  | // Now child Catches are processed, update CatchHigh | 
|  | if (IsPreOrder) | 
|  | FuncInfo.TryBlockMap[TBMEIdx].CatchHigh = CatchHigh; | 
|  | else // PostOrder | 
|  | addTryBlockMapEntry(FuncInfo, TryLow, TryHigh, CatchHigh, Handlers); | 
|  |  | 
|  | LLVM_DEBUG(dbgs() << "TryLow[" << BB->getName() << "]: " << TryLow << '\n'); | 
|  | LLVM_DEBUG(dbgs() << "TryHigh[" << BB->getName() << "]: " << TryHigh | 
|  | << '\n'); | 
|  | LLVM_DEBUG(dbgs() << "CatchHigh[" << BB->getName() << "]: " << CatchHigh | 
|  | << '\n'); | 
|  | } else { | 
|  | auto *CleanupPad = cast<CleanupPadInst>(FirstNonPHI); | 
|  |  | 
|  | // It's possible for a cleanup to be visited twice: it might have multiple | 
|  | // cleanupret instructions. | 
|  | auto [It, Inserted] = FuncInfo.EHPadStateMap.try_emplace(CleanupPad); | 
|  | if (!Inserted) | 
|  | return; | 
|  |  | 
|  | int CleanupState = addUnwindMapEntry(FuncInfo, ParentState, BB); | 
|  | It->second = CleanupState; | 
|  | LLVM_DEBUG(dbgs() << "Assigning state #" << CleanupState << " to BB " | 
|  | << BB->getName() << '\n'); | 
|  | for (const BasicBlock *PredBlock : predecessors(BB)) { | 
|  | if ((PredBlock = getEHPadFromPredecessor(PredBlock, | 
|  | CleanupPad->getParentPad()))) { | 
|  | calculateCXXStateNumbers(FuncInfo, &*PredBlock->getFirstNonPHIIt(), | 
|  | CleanupState); | 
|  | } | 
|  | } | 
|  | for (const User *U : CleanupPad->users()) { | 
|  | const auto *UserI = cast<Instruction>(U); | 
|  | if (UserI->isEHPad()) | 
|  | report_fatal_error("Cleanup funclets for the MSVC++ personality cannot " | 
|  | "contain exceptional actions"); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | 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; | 
|  | } | 
|  |  | 
|  | // Starting from a EHPad, Backward walk through control-flow graph | 
|  | // to produce two primary outputs: | 
|  | //      FuncInfo.EHPadStateMap[] and FuncInfo.SEHUnwindMap[] | 
|  | static void calculateSEHStateNumbers(WinEHFuncInfo &FuncInfo, | 
|  | const Instruction *FirstNonPHI, | 
|  | int ParentState) { | 
|  | const BasicBlock *BB = FirstNonPHI->getParent(); | 
|  | assert(BB->isEHPad() && "no a funclet!"); | 
|  |  | 
|  | if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(FirstNonPHI)) { | 
|  | assert(FuncInfo.EHPadStateMap.count(CatchSwitch) == 0 && | 
|  | "shouldn't revist catch funclets!"); | 
|  |  | 
|  | // Extract the filter function and the __except basic block and create a | 
|  | // state for them. | 
|  | assert(CatchSwitch->getNumHandlers() == 1 && | 
|  | "SEH doesn't have multiple handlers per __try"); | 
|  | const auto *CatchPad = | 
|  | cast<CatchPadInst>((*CatchSwitch->handler_begin())->getFirstNonPHIIt()); | 
|  | const BasicBlock *CatchPadBB = CatchPad->getParent(); | 
|  | const Constant *FilterOrNull = | 
|  | cast<Constant>(CatchPad->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[CatchSwitch] = TryState; | 
|  | FuncInfo.EHPadStateMap[CatchPad] = TryState; | 
|  | LLVM_DEBUG(dbgs() << "Assigning state #" << TryState << " to BB " | 
|  | << CatchPadBB->getName() << '\n'); | 
|  | for (const BasicBlock *PredBlock : predecessors(BB)) | 
|  | if ((PredBlock = getEHPadFromPredecessor(PredBlock, | 
|  | CatchSwitch->getParentPad()))) | 
|  | calculateSEHStateNumbers(FuncInfo, &*PredBlock->getFirstNonPHIIt(), | 
|  | TryState); | 
|  |  | 
|  | // Everything in the __except block unwinds to ParentState, just like code | 
|  | // outside the __try. | 
|  | for (const User *U : CatchPad->users()) { | 
|  | const auto *UserI = cast<Instruction>(U); | 
|  | if (auto *InnerCatchSwitch = dyn_cast<CatchSwitchInst>(UserI)) { | 
|  | BasicBlock *UnwindDest = InnerCatchSwitch->getUnwindDest(); | 
|  | if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest()) | 
|  | calculateSEHStateNumbers(FuncInfo, UserI, ParentState); | 
|  | } | 
|  | if (auto *InnerCleanupPad = dyn_cast<CleanupPadInst>(UserI)) { | 
|  | BasicBlock *UnwindDest = getCleanupRetUnwindDest(InnerCleanupPad); | 
|  | // If a nested cleanup pad reports a null unwind destination and the | 
|  | // enclosing catch pad doesn't it must be post-dominated by an | 
|  | // unreachable instruction. | 
|  | if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest()) | 
|  | calculateSEHStateNumbers(FuncInfo, UserI, ParentState); | 
|  | } | 
|  | } | 
|  | } else { | 
|  | auto *CleanupPad = cast<CleanupPadInst>(FirstNonPHI); | 
|  |  | 
|  | // It's possible for a cleanup to be visited twice: it might have multiple | 
|  | // cleanupret instructions. | 
|  | auto [It, Inserted] = FuncInfo.EHPadStateMap.try_emplace(CleanupPad); | 
|  | if (!Inserted) | 
|  | return; | 
|  |  | 
|  | int CleanupState = addSEHFinally(FuncInfo, ParentState, BB); | 
|  | It->second = CleanupState; | 
|  | LLVM_DEBUG(dbgs() << "Assigning state #" << CleanupState << " to BB " | 
|  | << BB->getName() << '\n'); | 
|  | for (const BasicBlock *PredBlock : predecessors(BB)) | 
|  | if ((PredBlock = | 
|  | getEHPadFromPredecessor(PredBlock, CleanupPad->getParentPad()))) | 
|  | calculateSEHStateNumbers(FuncInfo, &*PredBlock->getFirstNonPHIIt(), | 
|  | CleanupState); | 
|  | for (const User *U : CleanupPad->users()) { | 
|  | const auto *UserI = cast<Instruction>(U); | 
|  | if (UserI->isEHPad()) | 
|  | report_fatal_error("Cleanup funclets for the SEH personality cannot " | 
|  | "contain exceptional actions"); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | static bool isTopLevelPadForMSVC(const Instruction *EHPad) { | 
|  | if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(EHPad)) | 
|  | return isa<ConstantTokenNone>(CatchSwitch->getParentPad()) && | 
|  | CatchSwitch->unwindsToCaller(); | 
|  | if (auto *CleanupPad = dyn_cast<CleanupPadInst>(EHPad)) | 
|  | return isa<ConstantTokenNone>(CleanupPad->getParentPad()) && | 
|  | getCleanupRetUnwindDest(CleanupPad) == nullptr; | 
|  | if (isa<CatchPadInst>(EHPad)) | 
|  | return false; | 
|  | llvm_unreachable("unexpected EHPad!"); | 
|  | } | 
|  |  | 
|  | 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()) | 
|  | continue; | 
|  | const Instruction *FirstNonPHI = &*BB.getFirstNonPHIIt(); | 
|  | if (!isTopLevelPadForMSVC(FirstNonPHI)) | 
|  | continue; | 
|  | ::calculateSEHStateNumbers(FuncInfo, FirstNonPHI, -1); | 
|  | } | 
|  |  | 
|  | calculateStateNumbersForInvokes(Fn, FuncInfo); | 
|  |  | 
|  | bool IsEHa = Fn->getParent()->getModuleFlag("eh-asynch"); | 
|  | if (IsEHa) { | 
|  | const BasicBlock *EntryBB = &(Fn->getEntryBlock()); | 
|  | calculateSEHStateForAsynchEH(EntryBB, -1, FuncInfo); | 
|  | } | 
|  | } | 
|  |  | 
|  | 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; | 
|  | const Instruction *FirstNonPHI = &*BB.getFirstNonPHIIt(); | 
|  | if (!isTopLevelPadForMSVC(FirstNonPHI)) | 
|  | continue; | 
|  | calculateCXXStateNumbers(FuncInfo, FirstNonPHI, -1); | 
|  | } | 
|  |  | 
|  | calculateStateNumbersForInvokes(Fn, FuncInfo); | 
|  |  | 
|  | bool IsEHa = Fn->getParent()->getModuleFlag("eh-asynch"); | 
|  | if (IsEHa) { | 
|  | const BasicBlock *EntryBB = &(Fn->getEntryBlock()); | 
|  | calculateCXXStateForAsynchEH(EntryBB, -1, FuncInfo); | 
|  | } | 
|  | } | 
|  |  | 
|  | static int addClrEHHandler(WinEHFuncInfo &FuncInfo, int HandlerParentState, | 
|  | int TryParentState, ClrHandlerType HandlerType, | 
|  | uint32_t TypeToken, const BasicBlock *Handler) { | 
|  | ClrEHUnwindMapEntry Entry; | 
|  | Entry.HandlerParentState = HandlerParentState; | 
|  | Entry.TryParentState = TryParentState; | 
|  | 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; | 
|  |  | 
|  | // This numbering assigns one state number to each catchpad and cleanuppad. | 
|  | // It also computes two tree-like relations over states: | 
|  | // 1) Each state has a "HandlerParentState", which is the state of the next | 
|  | //    outer handler enclosing this state's handler (same as nearest ancestor | 
|  | //    per the ParentPad linkage on EH pads, but skipping over catchswitches). | 
|  | // 2) Each state has a "TryParentState", which: | 
|  | //    a) for a catchpad that's not the last handler on its catchswitch, is | 
|  | //       the state of the next catchpad on that catchswitch | 
|  | //    b) for all other pads, is the state of the pad whose try region is the | 
|  | //       next outer try region enclosing this state's try region.  The "try | 
|  | //       regions are not present as such in the IR, but will be inferred | 
|  | //       based on the placement of invokes and pads which reach each other | 
|  | //       by exceptional exits | 
|  | // Catchswitches do not get their own states, but each gets mapped to the | 
|  | // state of its first catchpad. | 
|  |  | 
|  | // Step one: walk down from outermost to innermost funclets, assigning each | 
|  | // catchpad and cleanuppad a state number.  Add an entry to the | 
|  | // ClrEHUnwindMap for each state, recording its HandlerParentState and | 
|  | // handler attributes.  Record the TryParentState as well for each catchpad | 
|  | // that's not the last on its catchswitch, but initialize all other entries' | 
|  | // TryParentStates to a sentinel -1 value that the next pass will update. | 
|  |  | 
|  | // Seed a worklist with pads that have no parent. | 
|  | SmallVector<std::pair<const Instruction *, int>, 8> Worklist; | 
|  | for (const BasicBlock &BB : *Fn) { | 
|  | const Instruction *FirstNonPHI = &*BB.getFirstNonPHIIt(); | 
|  | const Value *ParentPad; | 
|  | if (const auto *CPI = dyn_cast<CleanupPadInst>(FirstNonPHI)) | 
|  | ParentPad = CPI->getParentPad(); | 
|  | else if (const auto *CSI = dyn_cast<CatchSwitchInst>(FirstNonPHI)) | 
|  | ParentPad = CSI->getParentPad(); | 
|  | else | 
|  | continue; | 
|  | if (isa<ConstantTokenNone>(ParentPad)) | 
|  | Worklist.emplace_back(FirstNonPHI, -1); | 
|  | } | 
|  |  | 
|  | // Use the worklist to visit all pads, from outer to inner.  Record | 
|  | // HandlerParentState for all pads.  Record TryParentState only for catchpads | 
|  | // that aren't the last on their catchswitch (setting all other entries' | 
|  | // TryParentStates to an initial value of -1).  This loop is also responsible | 
|  | // for setting the EHPadStateMap entry for all catchpads, cleanuppads, and | 
|  | // catchswitches. | 
|  | while (!Worklist.empty()) { | 
|  | const Instruction *Pad; | 
|  | int HandlerParentState; | 
|  | std::tie(Pad, HandlerParentState) = Worklist.pop_back_val(); | 
|  |  | 
|  | if (const auto *Cleanup = dyn_cast<CleanupPadInst>(Pad)) { | 
|  | // Create the entry for this cleanup with the appropriate handler | 
|  | // properties.  Finally and fault handlers are distinguished by arity. | 
|  | ClrHandlerType HandlerType = | 
|  | (Cleanup->arg_size() ? ClrHandlerType::Fault | 
|  | : ClrHandlerType::Finally); | 
|  | int CleanupState = addClrEHHandler(FuncInfo, HandlerParentState, -1, | 
|  | HandlerType, 0, Pad->getParent()); | 
|  | // Queue any child EH pads on the worklist. | 
|  | for (const User *U : Cleanup->users()) | 
|  | if (const auto *I = dyn_cast<Instruction>(U)) | 
|  | if (I->isEHPad()) | 
|  | Worklist.emplace_back(I, CleanupState); | 
|  | // Remember this pad's state. | 
|  | FuncInfo.EHPadStateMap[Cleanup] = CleanupState; | 
|  | } else { | 
|  | // Walk the handlers of this catchswitch in reverse order since all but | 
|  | // the last need to set the following one as its TryParentState. | 
|  | const auto *CatchSwitch = cast<CatchSwitchInst>(Pad); | 
|  | int CatchState = -1, FollowerState = -1; | 
|  | SmallVector<const BasicBlock *, 4> CatchBlocks(CatchSwitch->handlers()); | 
|  | for (const BasicBlock *CatchBlock : llvm::reverse(CatchBlocks)) { | 
|  | // Create the entry for this catch with the appropriate handler | 
|  | // properties. | 
|  | const auto *Catch = cast<CatchPadInst>(CatchBlock->getFirstNonPHIIt()); | 
|  | uint32_t TypeToken = static_cast<uint32_t>( | 
|  | cast<ConstantInt>(Catch->getArgOperand(0))->getZExtValue()); | 
|  | CatchState = | 
|  | addClrEHHandler(FuncInfo, HandlerParentState, FollowerState, | 
|  | ClrHandlerType::Catch, TypeToken, CatchBlock); | 
|  | // Queue any child EH pads on the worklist. | 
|  | for (const User *U : Catch->users()) | 
|  | if (const auto *I = dyn_cast<Instruction>(U)) | 
|  | if (I->isEHPad()) | 
|  | Worklist.emplace_back(I, CatchState); | 
|  | // Remember this catch's state. | 
|  | FuncInfo.EHPadStateMap[Catch] = CatchState; | 
|  | FollowerState = CatchState; | 
|  | } | 
|  | // Associate the catchswitch with the state of its first catch. | 
|  | assert(CatchSwitch->getNumHandlers()); | 
|  | FuncInfo.EHPadStateMap[CatchSwitch] = CatchState; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Step two: record the TryParentState of each state.  For cleanuppads that | 
|  | // don't have cleanuprets, we may need to infer this from their child pads, | 
|  | // so visit pads in descendant-most to ancestor-most order. | 
|  | for (ClrEHUnwindMapEntry &Entry : llvm::reverse(FuncInfo.ClrEHUnwindMap)) { | 
|  | const Instruction *Pad = | 
|  | &*cast<const BasicBlock *>(Entry.Handler)->getFirstNonPHIIt(); | 
|  | // For most pads, the TryParentState is the state associated with the | 
|  | // unwind dest of exceptional exits from it. | 
|  | const BasicBlock *UnwindDest; | 
|  | if (const auto *Catch = dyn_cast<CatchPadInst>(Pad)) { | 
|  | // If a catch is not the last in its catchswitch, its TryParentState is | 
|  | // the state associated with the next catch in the switch, even though | 
|  | // that's not the unwind dest of exceptions escaping the catch.  Those | 
|  | // cases were already assigned a TryParentState in the first pass, so | 
|  | // skip them. | 
|  | if (Entry.TryParentState != -1) | 
|  | continue; | 
|  | // Otherwise, get the unwind dest from the catchswitch. | 
|  | UnwindDest = Catch->getCatchSwitch()->getUnwindDest(); | 
|  | } else { | 
|  | const auto *Cleanup = cast<CleanupPadInst>(Pad); | 
|  | UnwindDest = nullptr; | 
|  | for (const User *U : Cleanup->users()) { | 
|  | if (auto *CleanupRet = dyn_cast<CleanupReturnInst>(U)) { | 
|  | // Common and unambiguous case -- cleanupret indicates cleanup's | 
|  | // unwind dest. | 
|  | UnwindDest = CleanupRet->getUnwindDest(); | 
|  | break; | 
|  | } | 
|  |  | 
|  | // Get an unwind dest for the user | 
|  | const BasicBlock *UserUnwindDest = nullptr; | 
|  | if (auto *Invoke = dyn_cast<InvokeInst>(U)) { | 
|  | UserUnwindDest = Invoke->getUnwindDest(); | 
|  | } else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(U)) { | 
|  | UserUnwindDest = CatchSwitch->getUnwindDest(); | 
|  | } else if (auto *ChildCleanup = dyn_cast<CleanupPadInst>(U)) { | 
|  | int UserState = FuncInfo.EHPadStateMap[ChildCleanup]; | 
|  | int UserUnwindState = | 
|  | FuncInfo.ClrEHUnwindMap[UserState].TryParentState; | 
|  | if (UserUnwindState != -1) | 
|  | UserUnwindDest = cast<const BasicBlock *>( | 
|  | FuncInfo.ClrEHUnwindMap[UserUnwindState].Handler); | 
|  | } | 
|  |  | 
|  | // Not having an unwind dest for this user might indicate that it | 
|  | // doesn't unwind, so can't be taken as proof that the cleanup itself | 
|  | // may unwind to caller (see e.g. SimplifyUnreachable and | 
|  | // RemoveUnwindEdge). | 
|  | if (!UserUnwindDest) | 
|  | continue; | 
|  |  | 
|  | // Now we have an unwind dest for the user, but we need to see if it | 
|  | // unwinds all the way out of the cleanup or if it stays within it. | 
|  | const Instruction *UserUnwindPad = &*UserUnwindDest->getFirstNonPHIIt(); | 
|  | const Value *UserUnwindParent; | 
|  | if (auto *CSI = dyn_cast<CatchSwitchInst>(UserUnwindPad)) | 
|  | UserUnwindParent = CSI->getParentPad(); | 
|  | else | 
|  | UserUnwindParent = | 
|  | cast<CleanupPadInst>(UserUnwindPad)->getParentPad(); | 
|  |  | 
|  | // The unwind stays within the cleanup iff it targets a child of the | 
|  | // cleanup. | 
|  | if (UserUnwindParent == Cleanup) | 
|  | continue; | 
|  |  | 
|  | // This unwind exits the cleanup, so its dest is the cleanup's dest. | 
|  | UnwindDest = UserUnwindDest; | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Record the state of the unwind dest as the TryParentState. | 
|  | int UnwindDestState; | 
|  |  | 
|  | // If UnwindDest is null at this point, either the pad in question can | 
|  | // be exited by unwind to caller, or it cannot be exited by unwind.  In | 
|  | // either case, reporting such cases as unwinding to caller is correct. | 
|  | // This can lead to EH tables that "look strange" -- if this pad's is in | 
|  | // a parent funclet which has other children that do unwind to an enclosing | 
|  | // pad, the try region for this pad will be missing the "duplicate" EH | 
|  | // clause entries that you'd expect to see covering the whole parent.  That | 
|  | // should be benign, since the unwind never actually happens.  If it were | 
|  | // an issue, we could add a subsequent pass that pushes unwind dests down | 
|  | // from parents that have them to children that appear to unwind to caller. | 
|  | if (!UnwindDest) { | 
|  | UnwindDestState = -1; | 
|  | } else { | 
|  | UnwindDestState = | 
|  | FuncInfo.EHPadStateMap[&*UnwindDest->getFirstNonPHIIt()]; | 
|  | } | 
|  |  | 
|  | Entry.TryParentState = UnwindDestState; | 
|  | } | 
|  |  | 
|  | // Step three: transfer information from pads to invokes. | 
|  | calculateStateNumbersForInvokes(Fn, FuncInfo); | 
|  | } | 
|  |  | 
|  | void WinEHPrepareImpl::colorFunclets(Function &F) { | 
|  | BlockColors = colorEHFunclets(F); | 
|  |  | 
|  | // Invert the map from BB to colors to color to BBs. | 
|  | for (BasicBlock &BB : F) { | 
|  | ColorVector &Colors = BlockColors[&BB]; | 
|  | for (BasicBlock *Color : Colors) | 
|  | FuncletBlocks[Color].push_back(&BB); | 
|  | } | 
|  | } | 
|  |  | 
|  | bool WinEHPrepareImpl::demotePHIsOnFunclets(Function &F, | 
|  | bool DemoteCatchSwitchPHIOnly) { | 
|  | bool Changed = false; | 
|  |  | 
|  | // Strip PHI nodes off of EH pads. | 
|  | SmallVector<PHINode *, 16> PHINodes; | 
|  | for (BasicBlock &BB : make_early_inc_range(F)) { | 
|  | if (!BB.isEHPad()) | 
|  | continue; | 
|  |  | 
|  | for (Instruction &I : make_early_inc_range(BB)) { | 
|  | auto *PN = dyn_cast<PHINode>(&I); | 
|  | // Stop at the first non-PHI. | 
|  | if (!PN) | 
|  | break; | 
|  |  | 
|  | // If DemoteCatchSwitchPHIOnly is true, we only demote a PHI when | 
|  | // 1. The PHI is within a catchswitch BB | 
|  | // 2. The PHI has a catchswitch BB has one of its incoming blocks | 
|  | if (DemoteCatchSwitchPHIOnly) { | 
|  | bool IsCatchSwitchBB = isa<CatchSwitchInst>(BB.getFirstNonPHIIt()); | 
|  | bool HasIncomingCatchSwitchBB = false; | 
|  | for (unsigned I = 0, E = PN->getNumIncomingValues(); I < E; ++I) { | 
|  | if (isa<CatchSwitchInst>( | 
|  | PN->getIncomingBlock(I)->getFirstNonPHIIt())) { | 
|  | HasIncomingCatchSwitchBB = true; | 
|  | break; | 
|  | } | 
|  | } | 
|  | if (!IsCatchSwitchBB && !HasIncomingCatchSwitchBB) | 
|  | break; | 
|  | } | 
|  |  | 
|  | Changed = true; | 
|  |  | 
|  | 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(PoisonValue::get(PN->getType())); | 
|  | PN->eraseFromParent(); | 
|  | } | 
|  |  | 
|  | return Changed; | 
|  | } | 
|  |  | 
|  | bool WinEHPrepareImpl::cloneCommonBlocks(Function &F) { | 
|  | bool Changed = false; | 
|  |  | 
|  | // We need to clone all blocks which belong to multiple funclets.  Values are | 
|  | // remapped throughout the funclet to propagate both the new instructions | 
|  | // *and* the new basic blocks themselves. | 
|  | for (auto &Funclets : FuncletBlocks) { | 
|  | BasicBlock *FuncletPadBB = Funclets.first; | 
|  | std::vector<BasicBlock *> &BlocksInFunclet = Funclets.second; | 
|  | Value *FuncletToken; | 
|  | if (FuncletPadBB == &F.getEntryBlock()) | 
|  | FuncletToken = ConstantTokenNone::get(F.getContext()); | 
|  | else | 
|  | FuncletToken = &*FuncletPadBB->getFirstNonPHIIt(); | 
|  |  | 
|  | std::vector<std::pair<BasicBlock *, BasicBlock *>> Orig2Clone; | 
|  | ValueToValueMapTy VMap; | 
|  | for (BasicBlock *BB : BlocksInFunclet) { | 
|  | ColorVector &ColorsForBB = BlockColors[BB]; | 
|  | // We don't need to do anything if the block is monochromatic. | 
|  | size_t NumColorsForBB = ColorsForBB.size(); | 
|  | if (NumColorsForBB == 1) | 
|  | continue; | 
|  |  | 
|  | DEBUG_WITH_TYPE("win-eh-prepare-coloring", | 
|  | dbgs() << "  Cloning block \'" << BB->getName() | 
|  | << "\' for funclet \'" << FuncletPadBB->getName() | 
|  | << "\'.\n"); | 
|  |  | 
|  | // 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.emplace_back(BB, CBB); | 
|  | } | 
|  |  | 
|  | // If nothing was cloned, we're done cloning in this funclet. | 
|  | if (Orig2Clone.empty()) | 
|  | continue; | 
|  |  | 
|  | Changed = true; | 
|  |  | 
|  | // 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.push_back(NewBlock); | 
|  | ColorVector &NewColors = BlockColors[NewBlock]; | 
|  | assert(NewColors.empty() && "A new block should only have one color!"); | 
|  | NewColors.push_back(FuncletPadBB); | 
|  |  | 
|  | DEBUG_WITH_TYPE("win-eh-prepare-coloring", | 
|  | dbgs() << "  Assigned color \'" << FuncletPadBB->getName() | 
|  | << "\' to block \'" << NewBlock->getName() | 
|  | << "\'.\n"); | 
|  |  | 
|  | llvm::erase(BlocksInFunclet, OldBlock); | 
|  | ColorVector &OldColors = BlockColors[OldBlock]; | 
|  | llvm::erase(OldColors, FuncletPadBB); | 
|  |  | 
|  | DEBUG_WITH_TYPE("win-eh-prepare-coloring", | 
|  | dbgs() << "  Removed color \'" << FuncletPadBB->getName() | 
|  | << "\' from block \'" << OldBlock->getName() | 
|  | << "\'.\n"); | 
|  | } | 
|  |  | 
|  | // 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_IgnoreMissingLocals | RF_NoModuleLevelChanges); | 
|  |  | 
|  | // Catchrets targeting cloned blocks need to be updated separately from | 
|  | // the loop above because they are not in the current funclet. | 
|  | SmallVector<CatchReturnInst *, 2> FixupCatchrets; | 
|  | for (auto &BBMapping : Orig2Clone) { | 
|  | BasicBlock *OldBlock = BBMapping.first; | 
|  | BasicBlock *NewBlock = BBMapping.second; | 
|  |  | 
|  | FixupCatchrets.clear(); | 
|  | for (BasicBlock *Pred : predecessors(OldBlock)) | 
|  | if (auto *CatchRet = dyn_cast<CatchReturnInst>(Pred->getTerminator())) | 
|  | if (CatchRet->getCatchSwitchParentPad() == FuncletToken) | 
|  | FixupCatchrets.push_back(CatchRet); | 
|  |  | 
|  | for (CatchReturnInst *CatchRet : FixupCatchrets) | 
|  | CatchRet->setSuccessor(NewBlock); | 
|  | } | 
|  |  | 
|  | auto UpdatePHIOnClonedBlock = [&](PHINode *PN, bool IsForOldBlock) { | 
|  | unsigned NumPreds = PN->getNumIncomingValues(); | 
|  | for (unsigned PredIdx = 0, PredEnd = NumPreds; PredIdx != PredEnd; | 
|  | ++PredIdx) { | 
|  | BasicBlock *IncomingBlock = PN->getIncomingBlock(PredIdx); | 
|  | bool EdgeTargetsFunclet; | 
|  | if (auto *CRI = | 
|  | dyn_cast<CatchReturnInst>(IncomingBlock->getTerminator())) { | 
|  | EdgeTargetsFunclet = (CRI->getCatchSwitchParentPad() == FuncletToken); | 
|  | } else { | 
|  | ColorVector &IncomingColors = BlockColors[IncomingBlock]; | 
|  | assert(!IncomingColors.empty() && "Block not colored!"); | 
|  | assert((IncomingColors.size() == 1 || | 
|  | !llvm::is_contained(IncomingColors, FuncletPadBB)) && | 
|  | "Cloning should leave this funclet's blocks monochromatic"); | 
|  | EdgeTargetsFunclet = (IncomingColors.front() == FuncletPadBB); | 
|  | } | 
|  | if (IsForOldBlock != EdgeTargetsFunclet) | 
|  | continue; | 
|  | PN->removeIncomingValue(IncomingBlock, /*DeletePHIIfEmpty=*/false); | 
|  | // Revisit the next entry. | 
|  | --PredIdx; | 
|  | --PredEnd; | 
|  | } | 
|  | }; | 
|  |  | 
|  | for (auto &BBMapping : Orig2Clone) { | 
|  | BasicBlock *OldBlock = BBMapping.first; | 
|  | BasicBlock *NewBlock = BBMapping.second; | 
|  | for (PHINode &OldPN : OldBlock->phis()) { | 
|  | UpdatePHIOnClonedBlock(&OldPN, /*IsForOldBlock=*/true); | 
|  | } | 
|  | for (PHINode &NewPN : NewBlock->phis()) { | 
|  | UpdatePHIOnClonedBlock(&NewPN, /*IsForOldBlock=*/false); | 
|  | } | 
|  | } | 
|  |  | 
|  | // 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 (PHINode &SuccPN : SuccBB->phis()) { | 
|  | // 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(); | 
|  | ColorVector &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()); | 
|  | } | 
|  | } | 
|  |  | 
|  | return Changed; | 
|  | } | 
|  |  | 
|  | bool WinEHPrepareImpl::removeImplausibleInstructions(Function &F) { | 
|  | bool Changed = false; | 
|  |  | 
|  | // Remove implausible terminators and replace them with UnreachableInst. | 
|  | for (auto &Funclet : FuncletBlocks) { | 
|  | BasicBlock *FuncletPadBB = Funclet.first; | 
|  | std::vector<BasicBlock *> &BlocksInFunclet = Funclet.second; | 
|  | Instruction *FirstNonPHI = &*FuncletPadBB->getFirstNonPHIIt(); | 
|  | auto *FuncletPad = dyn_cast<FuncletPadInst>(FirstNonPHI); | 
|  | auto *CatchPad = dyn_cast_or_null<CatchPadInst>(FuncletPad); | 
|  | auto *CleanupPad = dyn_cast_or_null<CleanupPadInst>(FuncletPad); | 
|  |  | 
|  | for (BasicBlock *BB : BlocksInFunclet) { | 
|  | for (Instruction &I : *BB) { | 
|  | auto *CB = dyn_cast<CallBase>(&I); | 
|  | if (!CB) | 
|  | continue; | 
|  |  | 
|  | Value *FuncletBundleOperand = nullptr; | 
|  | if (auto BU = CB->getOperandBundle(LLVMContext::OB_funclet)) | 
|  | FuncletBundleOperand = BU->Inputs.front(); | 
|  |  | 
|  | if (FuncletBundleOperand == FuncletPad) | 
|  | continue; | 
|  |  | 
|  | // Skip call sites which are nounwind intrinsics or inline asm. | 
|  | auto *CalledFn = | 
|  | dyn_cast<Function>(CB->getCalledOperand()->stripPointerCasts()); | 
|  | if (CB->isInlineAsm() || | 
|  | (CalledFn && CalledFn->isIntrinsic() && CB->doesNotThrow())) | 
|  | continue; | 
|  |  | 
|  | Changed = true; | 
|  |  | 
|  | // This call site was not part of this funclet, remove it. | 
|  | if (isa<InvokeInst>(CB)) { | 
|  | // Remove the unwind edge if it was an invoke. | 
|  | removeUnwindEdge(BB); | 
|  | // Get a pointer to the new call. | 
|  | BasicBlock::iterator CallI = | 
|  | std::prev(BB->getTerminator()->getIterator()); | 
|  | auto *CI = cast<CallInst>(&*CallI); | 
|  | changeToUnreachable(CI); | 
|  | } else { | 
|  | changeToUnreachable(&I); | 
|  | } | 
|  |  | 
|  | // There are no more instructions in the block (except for unreachable), | 
|  | // we are done. | 
|  | break; | 
|  | } | 
|  |  | 
|  | Instruction *TI = BB->getTerminator(); | 
|  | // CatchPadInst and CleanupPadInst can't transfer control to a ReturnInst. | 
|  | bool IsUnreachableRet = isa<ReturnInst>(TI) && FuncletPad; | 
|  | // 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; | 
|  | if (IsUnreachableRet || IsUnreachableCatchret || | 
|  | IsUnreachableCleanupret) { | 
|  | Changed = true; | 
|  | changeToUnreachable(TI); | 
|  | } else if (isa<InvokeInst>(TI)) { | 
|  | if (Personality == EHPersonality::MSVC_CXX && CleanupPad) { | 
|  | Changed = true; | 
|  | // Invokes within a cleanuppad for the MSVC++ personality never | 
|  | // transfer control to their unwind edge: the personality will | 
|  | // terminate the program. | 
|  | removeUnwindEdge(BB); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | return Changed; | 
|  | } | 
|  |  | 
|  | bool WinEHPrepareImpl::cleanupPreparedFunclets(Function &F) { | 
|  | bool Changed = false; | 
|  |  | 
|  | // Clean-up some of the mess we made by removing useles PHI nodes, trivial | 
|  | // branches, etc. | 
|  | for (BasicBlock &BB : llvm::make_early_inc_range(F)) { | 
|  | Changed |= SimplifyInstructionsInBlock(&BB); | 
|  | Changed |= ConstantFoldTerminator(&BB, /*DeleteDeadConditions=*/true); | 
|  | Changed |= MergeBlockIntoPredecessor(&BB); | 
|  | } | 
|  |  | 
|  | // We might have some unreachable blocks after cleaning up some impossible | 
|  | // control flow. | 
|  | Changed |= removeUnreachableBlocks(F); | 
|  |  | 
|  | return Changed; | 
|  | } | 
|  |  | 
|  | #ifndef NDEBUG | 
|  | void WinEHPrepareImpl::verifyPreparedFunclets(Function &F) { | 
|  | 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!"); | 
|  | assert((DisableDemotion || !(BB.isEHPad() && isa<PHINode>(BB.begin()))) && | 
|  | "EH Pad still has a PHI!"); | 
|  | } | 
|  | } | 
|  | #endif | 
|  |  | 
|  | bool WinEHPrepareImpl::prepareExplicitEH(Function &F) { | 
|  | // 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. | 
|  | bool Changed = removeUnreachableBlocks(F); | 
|  |  | 
|  | // Determine which blocks are reachable from which funclet entries. | 
|  | colorFunclets(F); | 
|  |  | 
|  | Changed |= cloneCommonBlocks(F); | 
|  |  | 
|  | if (!DisableDemotion) | 
|  | Changed |= demotePHIsOnFunclets(F, DemoteCatchSwitchPHIOnly || | 
|  | DemoteCatchSwitchPHIOnlyOpt); | 
|  |  | 
|  | if (!DisableCleanups) { | 
|  | assert(!verifyFunction(F, &dbgs())); | 
|  | Changed |= removeImplausibleInstructions(F); | 
|  |  | 
|  | assert(!verifyFunction(F, &dbgs())); | 
|  | Changed |= cleanupPreparedFunclets(F); | 
|  | } | 
|  |  | 
|  | LLVM_DEBUG(verifyPreparedFunclets(F)); | 
|  | // Recolor the CFG to verify that all is well. | 
|  | LLVM_DEBUG(colorFunclets(F)); | 
|  | LLVM_DEBUG(verifyPreparedFunclets(F)); | 
|  |  | 
|  | return Changed; | 
|  | } | 
|  |  | 
|  | // TODO: Share loads when one use dominates another, or when a catchpad exit | 
|  | // dominates uses (needs dominators). | 
|  | AllocaInst *WinEHPrepareImpl::insertPHILoads(PHINode *PN, Function &F) { | 
|  | BasicBlock *PHIBlock = PN->getParent(); | 
|  | AllocaInst *SpillSlot = nullptr; | 
|  | Instruction *EHPad = &*PHIBlock->getFirstNonPHIIt(); | 
|  |  | 
|  | if (!EHPad->isTerminator()) { | 
|  | // If the EHPad isn't a terminator, then we can insert a load in this block | 
|  | // that will dominate all uses. | 
|  | SpillSlot = new AllocaInst(PN->getType(), DL->getAllocaAddrSpace(), nullptr, | 
|  | Twine(PN->getName(), ".wineh.spillslot"), | 
|  | F.getEntryBlock().begin()); | 
|  | Value *V = new LoadInst(PN->getType(), SpillSlot, | 
|  | Twine(PN->getName(), ".wineh.reload"), | 
|  | PHIBlock->getFirstInsertionPt()); | 
|  | PN->replaceAllUsesWith(V); | 
|  | return SpillSlot; | 
|  | } | 
|  |  | 
|  | // Otherwise, we have a PHI on a terminator EHPad, and we give up and insert | 
|  | // loads of the slot before every use. | 
|  | DenseMap<BasicBlock *, Value *> Loads; | 
|  | for (Use &U : llvm::make_early_inc_range(PN->uses())) { | 
|  | auto *UsingInst = cast<Instruction>(U.getUser()); | 
|  | if (isa<PHINode>(UsingInst) && UsingInst->getParent()->isEHPad()) { | 
|  | // Use is on an EH pad phi.  Leave it alone; we'll insert loads and | 
|  | // stores for it separately. | 
|  | 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 WinEHPrepareImpl::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 WinEHPrepareImpl::insertPHIStore( | 
|  | BasicBlock *PredBlock, Value *PredVal, AllocaInst *SpillSlot, | 
|  | SmallVectorImpl<std::pair<BasicBlock *, Value *>> &Worklist) { | 
|  |  | 
|  | if (PredBlock->isEHPad() && PredBlock->getFirstNonPHIIt()->isTerminator()) { | 
|  | // 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()->getIterator()); | 
|  | } | 
|  |  | 
|  | void WinEHPrepareImpl::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(), DL->getAllocaAddrSpace(), nullptr, | 
|  | Twine(V->getName(), ".wineh.spillslot"), | 
|  | F.getEntryBlock().begin()); | 
|  |  | 
|  | 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(); | 
|  | CatchRet->insertInto(IncomingBlock, IncomingBlock->end()); | 
|  | Goto->insertInto(NewBlock, NewBlock->end()); | 
|  | Goto->setSuccessor(0, PHIBlock); | 
|  | CatchRet->setSuccessor(NewBlock); | 
|  | // Update the color mapping for the newly split edge. | 
|  | // Grab a reference to the ColorVector to be inserted before getting the | 
|  | // reference to the vector we are copying because inserting the new | 
|  | // element in BlockColors might cause the map to be reallocated. | 
|  | ColorVector &ColorsForNewBlock = BlockColors[NewBlock]; | 
|  | ColorVector &ColorsForPHIBlock = BlockColors[PHIBlock]; | 
|  | ColorsForNewBlock = ColorsForPHIBlock; | 
|  | for (BasicBlock *FuncletPad : ColorsForPHIBlock) | 
|  | FuncletBlocks[FuncletPad].push_back(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( | 
|  | V->getType(), SpillSlot, Twine(V->getName(), ".wineh.reload"), | 
|  | /*isVolatile=*/false, IncomingBlock->getTerminator()->getIterator()); | 
|  |  | 
|  | U.set(Load); | 
|  | } else { | 
|  | // Reload right before the old use. | 
|  | auto *Load = new LoadInst(V->getType(), SpillSlot, | 
|  | Twine(V->getName(), ".wineh.reload"), | 
|  | /*isVolatile=*/false, UsingInst->getIterator()); | 
|  | U.set(Load); | 
|  | } | 
|  | } | 
|  |  | 
|  | void WinEHFuncInfo::addIPToStateRange(const InvokeInst *II, | 
|  | MCSymbol *InvokeBegin, | 
|  | MCSymbol *InvokeEnd) { | 
|  | assert(InvokeStateMap.count(II) && | 
|  | "should get invoke with precomputed state"); | 
|  | LabelToStateMap[InvokeBegin] = std::make_pair(InvokeStateMap[II], InvokeEnd); | 
|  | } | 
|  |  | 
|  | void WinEHFuncInfo::addIPToStateRange(int State, MCSymbol* InvokeBegin, | 
|  | MCSymbol* InvokeEnd) { | 
|  | LabelToStateMap[InvokeBegin] = std::make_pair(State, InvokeEnd); | 
|  | } | 
|  |  | 
|  | WinEHFuncInfo::WinEHFuncInfo() = default; |