xref: /openbsd-src/gnu/llvm/llvm/lib/CodeGen/WinEHPrepare.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===-- WinEHPrepare - Prepare exception handling for code generation ---===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This pass lowers LLVM IR exception handling into something closer to what the
1009467b48Spatrick // backend wants for functions using a personality function from a runtime
1109467b48Spatrick // provided by MSVC. Functions with other personality functions are left alone
1209467b48Spatrick // and may be prepared by other passes. In particular, all supported MSVC
1309467b48Spatrick // personality functions require cleanup code to be outlined, and the C++
1409467b48Spatrick // personality requires catch handler code to be outlined.
1509467b48Spatrick //
1609467b48Spatrick //===----------------------------------------------------------------------===//
1709467b48Spatrick 
1809467b48Spatrick #include "llvm/ADT/DenseMap.h"
1909467b48Spatrick #include "llvm/ADT/MapVector.h"
2009467b48Spatrick #include "llvm/ADT/STLExtras.h"
21097a140dSpatrick #include "llvm/ADT/Triple.h"
2209467b48Spatrick #include "llvm/Analysis/EHPersonalities.h"
2309467b48Spatrick #include "llvm/CodeGen/MachineBasicBlock.h"
2409467b48Spatrick #include "llvm/CodeGen/Passes.h"
2509467b48Spatrick #include "llvm/CodeGen/WinEHFuncInfo.h"
26*d415bd75Srobert #include "llvm/IR/Constants.h"
27*d415bd75Srobert #include "llvm/IR/Instructions.h"
2809467b48Spatrick #include "llvm/IR/Verifier.h"
2909467b48Spatrick #include "llvm/InitializePasses.h"
3009467b48Spatrick #include "llvm/Pass.h"
3109467b48Spatrick #include "llvm/Support/CommandLine.h"
3209467b48Spatrick #include "llvm/Support/Debug.h"
3309467b48Spatrick #include "llvm/Support/raw_ostream.h"
3409467b48Spatrick #include "llvm/Transforms/Utils/BasicBlockUtils.h"
3509467b48Spatrick #include "llvm/Transforms/Utils/Cloning.h"
3609467b48Spatrick #include "llvm/Transforms/Utils/Local.h"
3709467b48Spatrick #include "llvm/Transforms/Utils/SSAUpdater.h"
3809467b48Spatrick 
3909467b48Spatrick using namespace llvm;
4009467b48Spatrick 
4109467b48Spatrick #define DEBUG_TYPE "winehprepare"
4209467b48Spatrick 
4309467b48Spatrick static cl::opt<bool> DisableDemotion(
4409467b48Spatrick     "disable-demotion", cl::Hidden,
4509467b48Spatrick     cl::desc(
4609467b48Spatrick         "Clone multicolor basic blocks but do not demote cross scopes"),
4709467b48Spatrick     cl::init(false));
4809467b48Spatrick 
4909467b48Spatrick static cl::opt<bool> DisableCleanups(
5009467b48Spatrick     "disable-cleanups", cl::Hidden,
5109467b48Spatrick     cl::desc("Do not remove implausible terminators or other similar cleanups"),
5209467b48Spatrick     cl::init(false));
5309467b48Spatrick 
5409467b48Spatrick static cl::opt<bool> DemoteCatchSwitchPHIOnlyOpt(
5509467b48Spatrick     "demote-catchswitch-only", cl::Hidden,
5609467b48Spatrick     cl::desc("Demote catchswitch BBs only (for wasm EH)"), cl::init(false));
5709467b48Spatrick 
5809467b48Spatrick namespace {
5909467b48Spatrick 
6009467b48Spatrick class WinEHPrepare : public FunctionPass {
6109467b48Spatrick public:
6209467b48Spatrick   static char ID; // Pass identification, replacement for typeid.
WinEHPrepare(bool DemoteCatchSwitchPHIOnly=false)6309467b48Spatrick   WinEHPrepare(bool DemoteCatchSwitchPHIOnly = false)
6409467b48Spatrick       : FunctionPass(ID), DemoteCatchSwitchPHIOnly(DemoteCatchSwitchPHIOnly) {}
6509467b48Spatrick 
6609467b48Spatrick   bool runOnFunction(Function &Fn) override;
6709467b48Spatrick 
6809467b48Spatrick   bool doFinalization(Module &M) override;
6909467b48Spatrick 
7009467b48Spatrick   void getAnalysisUsage(AnalysisUsage &AU) const override;
7109467b48Spatrick 
getPassName() const7209467b48Spatrick   StringRef getPassName() const override {
7309467b48Spatrick     return "Windows exception handling preparation";
7409467b48Spatrick   }
7509467b48Spatrick 
7609467b48Spatrick private:
7709467b48Spatrick   void insertPHIStores(PHINode *OriginalPHI, AllocaInst *SpillSlot);
7809467b48Spatrick   void
7909467b48Spatrick   insertPHIStore(BasicBlock *PredBlock, Value *PredVal, AllocaInst *SpillSlot,
8009467b48Spatrick                  SmallVectorImpl<std::pair<BasicBlock *, Value *>> &Worklist);
8109467b48Spatrick   AllocaInst *insertPHILoads(PHINode *PN, Function &F);
8209467b48Spatrick   void replaceUseWithLoad(Value *V, Use &U, AllocaInst *&SpillSlot,
8309467b48Spatrick                           DenseMap<BasicBlock *, Value *> &Loads, Function &F);
8409467b48Spatrick   bool prepareExplicitEH(Function &F);
8509467b48Spatrick   void colorFunclets(Function &F);
8609467b48Spatrick 
8709467b48Spatrick   void demotePHIsOnFunclets(Function &F, bool DemoteCatchSwitchPHIOnly);
8809467b48Spatrick   void cloneCommonBlocks(Function &F);
8909467b48Spatrick   void removeImplausibleInstructions(Function &F);
9009467b48Spatrick   void cleanupPreparedFunclets(Function &F);
9109467b48Spatrick   void verifyPreparedFunclets(Function &F);
9209467b48Spatrick 
9309467b48Spatrick   bool DemoteCatchSwitchPHIOnly;
9409467b48Spatrick 
9509467b48Spatrick   // All fields are reset by runOnFunction.
9609467b48Spatrick   EHPersonality Personality = EHPersonality::Unknown;
9709467b48Spatrick 
9809467b48Spatrick   const DataLayout *DL = nullptr;
9909467b48Spatrick   DenseMap<BasicBlock *, ColorVector> BlockColors;
10009467b48Spatrick   MapVector<BasicBlock *, std::vector<BasicBlock *>> FuncletBlocks;
10109467b48Spatrick };
10209467b48Spatrick 
10309467b48Spatrick } // end anonymous namespace
10409467b48Spatrick 
10509467b48Spatrick char WinEHPrepare::ID = 0;
10609467b48Spatrick INITIALIZE_PASS(WinEHPrepare, DEBUG_TYPE, "Prepare Windows exceptions",
10709467b48Spatrick                 false, false)
10809467b48Spatrick 
createWinEHPass(bool DemoteCatchSwitchPHIOnly)10909467b48Spatrick FunctionPass *llvm::createWinEHPass(bool DemoteCatchSwitchPHIOnly) {
11009467b48Spatrick   return new WinEHPrepare(DemoteCatchSwitchPHIOnly);
11109467b48Spatrick }
11209467b48Spatrick 
runOnFunction(Function & Fn)11309467b48Spatrick bool WinEHPrepare::runOnFunction(Function &Fn) {
11409467b48Spatrick   if (!Fn.hasPersonalityFn())
11509467b48Spatrick     return false;
11609467b48Spatrick 
11709467b48Spatrick   // Classify the personality to see what kind of preparation we need.
11809467b48Spatrick   Personality = classifyEHPersonality(Fn.getPersonalityFn());
11909467b48Spatrick 
12009467b48Spatrick   // Do nothing if this is not a scope-based personality.
12109467b48Spatrick   if (!isScopedEHPersonality(Personality))
12209467b48Spatrick     return false;
12309467b48Spatrick 
12409467b48Spatrick   DL = &Fn.getParent()->getDataLayout();
12509467b48Spatrick   return prepareExplicitEH(Fn);
12609467b48Spatrick }
12709467b48Spatrick 
doFinalization(Module & M)12809467b48Spatrick bool WinEHPrepare::doFinalization(Module &M) { return false; }
12909467b48Spatrick 
getAnalysisUsage(AnalysisUsage & AU) const13009467b48Spatrick void WinEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const {}
13109467b48Spatrick 
addUnwindMapEntry(WinEHFuncInfo & FuncInfo,int ToState,const BasicBlock * BB)13209467b48Spatrick static int addUnwindMapEntry(WinEHFuncInfo &FuncInfo, int ToState,
13309467b48Spatrick                              const BasicBlock *BB) {
13409467b48Spatrick   CxxUnwindMapEntry UME;
13509467b48Spatrick   UME.ToState = ToState;
13609467b48Spatrick   UME.Cleanup = BB;
13709467b48Spatrick   FuncInfo.CxxUnwindMap.push_back(UME);
13809467b48Spatrick   return FuncInfo.getLastStateNumber();
13909467b48Spatrick }
14009467b48Spatrick 
addTryBlockMapEntry(WinEHFuncInfo & FuncInfo,int TryLow,int TryHigh,int CatchHigh,ArrayRef<const CatchPadInst * > Handlers)14109467b48Spatrick static void addTryBlockMapEntry(WinEHFuncInfo &FuncInfo, int TryLow,
14209467b48Spatrick                                 int TryHigh, int CatchHigh,
14309467b48Spatrick                                 ArrayRef<const CatchPadInst *> Handlers) {
14409467b48Spatrick   WinEHTryBlockMapEntry TBME;
14509467b48Spatrick   TBME.TryLow = TryLow;
14609467b48Spatrick   TBME.TryHigh = TryHigh;
14709467b48Spatrick   TBME.CatchHigh = CatchHigh;
14809467b48Spatrick   assert(TBME.TryLow <= TBME.TryHigh);
14909467b48Spatrick   for (const CatchPadInst *CPI : Handlers) {
15009467b48Spatrick     WinEHHandlerType HT;
15109467b48Spatrick     Constant *TypeInfo = cast<Constant>(CPI->getArgOperand(0));
15209467b48Spatrick     if (TypeInfo->isNullValue())
15309467b48Spatrick       HT.TypeDescriptor = nullptr;
15409467b48Spatrick     else
15509467b48Spatrick       HT.TypeDescriptor = cast<GlobalVariable>(TypeInfo->stripPointerCasts());
15609467b48Spatrick     HT.Adjectives = cast<ConstantInt>(CPI->getArgOperand(1))->getZExtValue();
15709467b48Spatrick     HT.Handler = CPI->getParent();
15809467b48Spatrick     if (auto *AI =
15909467b48Spatrick             dyn_cast<AllocaInst>(CPI->getArgOperand(2)->stripPointerCasts()))
16009467b48Spatrick       HT.CatchObj.Alloca = AI;
16109467b48Spatrick     else
16209467b48Spatrick       HT.CatchObj.Alloca = nullptr;
16309467b48Spatrick     TBME.HandlerArray.push_back(HT);
16409467b48Spatrick   }
16509467b48Spatrick   FuncInfo.TryBlockMap.push_back(TBME);
16609467b48Spatrick }
16709467b48Spatrick 
getCleanupRetUnwindDest(const CleanupPadInst * CleanupPad)16809467b48Spatrick static BasicBlock *getCleanupRetUnwindDest(const CleanupPadInst *CleanupPad) {
16909467b48Spatrick   for (const User *U : CleanupPad->users())
17009467b48Spatrick     if (const auto *CRI = dyn_cast<CleanupReturnInst>(U))
17109467b48Spatrick       return CRI->getUnwindDest();
17209467b48Spatrick   return nullptr;
17309467b48Spatrick }
17409467b48Spatrick 
calculateStateNumbersForInvokes(const Function * Fn,WinEHFuncInfo & FuncInfo)17509467b48Spatrick static void calculateStateNumbersForInvokes(const Function *Fn,
17609467b48Spatrick                                             WinEHFuncInfo &FuncInfo) {
17709467b48Spatrick   auto *F = const_cast<Function *>(Fn);
17809467b48Spatrick   DenseMap<BasicBlock *, ColorVector> BlockColors = colorEHFunclets(*F);
17909467b48Spatrick   for (BasicBlock &BB : *F) {
18009467b48Spatrick     auto *II = dyn_cast<InvokeInst>(BB.getTerminator());
18109467b48Spatrick     if (!II)
18209467b48Spatrick       continue;
18309467b48Spatrick 
18409467b48Spatrick     auto &BBColors = BlockColors[&BB];
18509467b48Spatrick     assert(BBColors.size() == 1 && "multi-color BB not removed by preparation");
18609467b48Spatrick     BasicBlock *FuncletEntryBB = BBColors.front();
18709467b48Spatrick 
18809467b48Spatrick     BasicBlock *FuncletUnwindDest;
18909467b48Spatrick     auto *FuncletPad =
19009467b48Spatrick         dyn_cast<FuncletPadInst>(FuncletEntryBB->getFirstNonPHI());
19109467b48Spatrick     assert(FuncletPad || FuncletEntryBB == &Fn->getEntryBlock());
19209467b48Spatrick     if (!FuncletPad)
19309467b48Spatrick       FuncletUnwindDest = nullptr;
19409467b48Spatrick     else if (auto *CatchPad = dyn_cast<CatchPadInst>(FuncletPad))
19509467b48Spatrick       FuncletUnwindDest = CatchPad->getCatchSwitch()->getUnwindDest();
19609467b48Spatrick     else if (auto *CleanupPad = dyn_cast<CleanupPadInst>(FuncletPad))
19709467b48Spatrick       FuncletUnwindDest = getCleanupRetUnwindDest(CleanupPad);
19809467b48Spatrick     else
19909467b48Spatrick       llvm_unreachable("unexpected funclet pad!");
20009467b48Spatrick 
20109467b48Spatrick     BasicBlock *InvokeUnwindDest = II->getUnwindDest();
20209467b48Spatrick     int BaseState = -1;
20309467b48Spatrick     if (FuncletUnwindDest == InvokeUnwindDest) {
20409467b48Spatrick       auto BaseStateI = FuncInfo.FuncletBaseStateMap.find(FuncletPad);
20509467b48Spatrick       if (BaseStateI != FuncInfo.FuncletBaseStateMap.end())
20609467b48Spatrick         BaseState = BaseStateI->second;
20709467b48Spatrick     }
20809467b48Spatrick 
20909467b48Spatrick     if (BaseState != -1) {
21009467b48Spatrick       FuncInfo.InvokeStateMap[II] = BaseState;
21109467b48Spatrick     } else {
21209467b48Spatrick       Instruction *PadInst = InvokeUnwindDest->getFirstNonPHI();
21309467b48Spatrick       assert(FuncInfo.EHPadStateMap.count(PadInst) && "EH Pad has no state!");
21409467b48Spatrick       FuncInfo.InvokeStateMap[II] = FuncInfo.EHPadStateMap[PadInst];
21509467b48Spatrick     }
21609467b48Spatrick   }
21709467b48Spatrick }
21809467b48Spatrick 
21909467b48Spatrick // Given BB which ends in an unwind edge, return the EHPad that this BB belongs
22009467b48Spatrick // to. If the unwind edge came from an invoke, return null.
getEHPadFromPredecessor(const BasicBlock * BB,Value * ParentPad)22109467b48Spatrick static const BasicBlock *getEHPadFromPredecessor(const BasicBlock *BB,
22209467b48Spatrick                                                  Value *ParentPad) {
22309467b48Spatrick   const Instruction *TI = BB->getTerminator();
22409467b48Spatrick   if (isa<InvokeInst>(TI))
22509467b48Spatrick     return nullptr;
22609467b48Spatrick   if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(TI)) {
22709467b48Spatrick     if (CatchSwitch->getParentPad() != ParentPad)
22809467b48Spatrick       return nullptr;
22909467b48Spatrick     return BB;
23009467b48Spatrick   }
23109467b48Spatrick   assert(!TI->isEHPad() && "unexpected EHPad!");
23209467b48Spatrick   auto *CleanupPad = cast<CleanupReturnInst>(TI)->getCleanupPad();
23309467b48Spatrick   if (CleanupPad->getParentPad() != ParentPad)
23409467b48Spatrick     return nullptr;
23509467b48Spatrick   return CleanupPad->getParent();
23609467b48Spatrick }
23709467b48Spatrick 
238097a140dSpatrick // Starting from a EHPad, Backward walk through control-flow graph
239097a140dSpatrick // to produce two primary outputs:
240097a140dSpatrick //      FuncInfo.EHPadStateMap[] and FuncInfo.CxxUnwindMap[]
calculateCXXStateNumbers(WinEHFuncInfo & FuncInfo,const Instruction * FirstNonPHI,int ParentState)24109467b48Spatrick static void calculateCXXStateNumbers(WinEHFuncInfo &FuncInfo,
24209467b48Spatrick                                      const Instruction *FirstNonPHI,
24309467b48Spatrick                                      int ParentState) {
24409467b48Spatrick   const BasicBlock *BB = FirstNonPHI->getParent();
24509467b48Spatrick   assert(BB->isEHPad() && "not a funclet!");
24609467b48Spatrick 
24709467b48Spatrick   if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(FirstNonPHI)) {
24809467b48Spatrick     assert(FuncInfo.EHPadStateMap.count(CatchSwitch) == 0 &&
24909467b48Spatrick            "shouldn't revist catch funclets!");
25009467b48Spatrick 
25109467b48Spatrick     SmallVector<const CatchPadInst *, 2> Handlers;
25209467b48Spatrick     for (const BasicBlock *CatchPadBB : CatchSwitch->handlers()) {
25309467b48Spatrick       auto *CatchPad = cast<CatchPadInst>(CatchPadBB->getFirstNonPHI());
25409467b48Spatrick       Handlers.push_back(CatchPad);
25509467b48Spatrick     }
25609467b48Spatrick     int TryLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr);
25709467b48Spatrick     FuncInfo.EHPadStateMap[CatchSwitch] = TryLow;
25809467b48Spatrick     for (const BasicBlock *PredBlock : predecessors(BB))
25909467b48Spatrick       if ((PredBlock = getEHPadFromPredecessor(PredBlock,
26009467b48Spatrick                                                CatchSwitch->getParentPad())))
26109467b48Spatrick         calculateCXXStateNumbers(FuncInfo, PredBlock->getFirstNonPHI(),
26209467b48Spatrick                                  TryLow);
26309467b48Spatrick     int CatchLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr);
26409467b48Spatrick 
26509467b48Spatrick     // catchpads are separate funclets in C++ EH due to the way rethrow works.
26609467b48Spatrick     int TryHigh = CatchLow - 1;
267097a140dSpatrick 
268097a140dSpatrick     // MSVC FrameHandler3/4 on x64&Arm64 expect Catch Handlers in $tryMap$
269097a140dSpatrick     //  stored in pre-order (outer first, inner next), not post-order
270097a140dSpatrick     //  Add to map here.  Fix the CatchHigh after children are processed
271097a140dSpatrick     const Module *Mod = BB->getParent()->getParent();
272097a140dSpatrick     bool IsPreOrder = Triple(Mod->getTargetTriple()).isArch64Bit();
273097a140dSpatrick     if (IsPreOrder)
274097a140dSpatrick       addTryBlockMapEntry(FuncInfo, TryLow, TryHigh, CatchLow, Handlers);
275097a140dSpatrick     unsigned TBMEIdx = FuncInfo.TryBlockMap.size() - 1;
276097a140dSpatrick 
27709467b48Spatrick     for (const auto *CatchPad : Handlers) {
27809467b48Spatrick       FuncInfo.FuncletBaseStateMap[CatchPad] = CatchLow;
27909467b48Spatrick       for (const User *U : CatchPad->users()) {
28009467b48Spatrick         const auto *UserI = cast<Instruction>(U);
28109467b48Spatrick         if (auto *InnerCatchSwitch = dyn_cast<CatchSwitchInst>(UserI)) {
28209467b48Spatrick           BasicBlock *UnwindDest = InnerCatchSwitch->getUnwindDest();
28309467b48Spatrick           if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest())
28409467b48Spatrick             calculateCXXStateNumbers(FuncInfo, UserI, CatchLow);
28509467b48Spatrick         }
28609467b48Spatrick         if (auto *InnerCleanupPad = dyn_cast<CleanupPadInst>(UserI)) {
28709467b48Spatrick           BasicBlock *UnwindDest = getCleanupRetUnwindDest(InnerCleanupPad);
28809467b48Spatrick           // If a nested cleanup pad reports a null unwind destination and the
28909467b48Spatrick           // enclosing catch pad doesn't it must be post-dominated by an
29009467b48Spatrick           // unreachable instruction.
29109467b48Spatrick           if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest())
29209467b48Spatrick             calculateCXXStateNumbers(FuncInfo, UserI, CatchLow);
29309467b48Spatrick         }
29409467b48Spatrick       }
29509467b48Spatrick     }
29609467b48Spatrick     int CatchHigh = FuncInfo.getLastStateNumber();
297097a140dSpatrick     // Now child Catches are processed, update CatchHigh
298097a140dSpatrick     if (IsPreOrder)
299097a140dSpatrick       FuncInfo.TryBlockMap[TBMEIdx].CatchHigh = CatchHigh;
300097a140dSpatrick     else // PostOrder
30109467b48Spatrick       addTryBlockMapEntry(FuncInfo, TryLow, TryHigh, CatchHigh, Handlers);
302097a140dSpatrick 
30309467b48Spatrick     LLVM_DEBUG(dbgs() << "TryLow[" << BB->getName() << "]: " << TryLow << '\n');
30409467b48Spatrick     LLVM_DEBUG(dbgs() << "TryHigh[" << BB->getName() << "]: " << TryHigh
30509467b48Spatrick                       << '\n');
30609467b48Spatrick     LLVM_DEBUG(dbgs() << "CatchHigh[" << BB->getName() << "]: " << CatchHigh
30709467b48Spatrick                       << '\n');
30809467b48Spatrick   } else {
30909467b48Spatrick     auto *CleanupPad = cast<CleanupPadInst>(FirstNonPHI);
31009467b48Spatrick 
31109467b48Spatrick     // It's possible for a cleanup to be visited twice: it might have multiple
31209467b48Spatrick     // cleanupret instructions.
31309467b48Spatrick     if (FuncInfo.EHPadStateMap.count(CleanupPad))
31409467b48Spatrick       return;
31509467b48Spatrick 
31609467b48Spatrick     int CleanupState = addUnwindMapEntry(FuncInfo, ParentState, BB);
31709467b48Spatrick     FuncInfo.EHPadStateMap[CleanupPad] = CleanupState;
31809467b48Spatrick     LLVM_DEBUG(dbgs() << "Assigning state #" << CleanupState << " to BB "
31909467b48Spatrick                       << BB->getName() << '\n');
32009467b48Spatrick     for (const BasicBlock *PredBlock : predecessors(BB)) {
32109467b48Spatrick       if ((PredBlock = getEHPadFromPredecessor(PredBlock,
32209467b48Spatrick                                                CleanupPad->getParentPad()))) {
32309467b48Spatrick         calculateCXXStateNumbers(FuncInfo, PredBlock->getFirstNonPHI(),
32409467b48Spatrick                                  CleanupState);
32509467b48Spatrick       }
32609467b48Spatrick     }
32709467b48Spatrick     for (const User *U : CleanupPad->users()) {
32809467b48Spatrick       const auto *UserI = cast<Instruction>(U);
32909467b48Spatrick       if (UserI->isEHPad())
33009467b48Spatrick         report_fatal_error("Cleanup funclets for the MSVC++ personality cannot "
33109467b48Spatrick                            "contain exceptional actions");
33209467b48Spatrick     }
33309467b48Spatrick   }
33409467b48Spatrick }
33509467b48Spatrick 
addSEHExcept(WinEHFuncInfo & FuncInfo,int ParentState,const Function * Filter,const BasicBlock * Handler)33609467b48Spatrick static int addSEHExcept(WinEHFuncInfo &FuncInfo, int ParentState,
33709467b48Spatrick                         const Function *Filter, const BasicBlock *Handler) {
33809467b48Spatrick   SEHUnwindMapEntry Entry;
33909467b48Spatrick   Entry.ToState = ParentState;
34009467b48Spatrick   Entry.IsFinally = false;
34109467b48Spatrick   Entry.Filter = Filter;
34209467b48Spatrick   Entry.Handler = Handler;
34309467b48Spatrick   FuncInfo.SEHUnwindMap.push_back(Entry);
34409467b48Spatrick   return FuncInfo.SEHUnwindMap.size() - 1;
34509467b48Spatrick }
34609467b48Spatrick 
addSEHFinally(WinEHFuncInfo & FuncInfo,int ParentState,const BasicBlock * Handler)34709467b48Spatrick static int addSEHFinally(WinEHFuncInfo &FuncInfo, int ParentState,
34809467b48Spatrick                          const BasicBlock *Handler) {
34909467b48Spatrick   SEHUnwindMapEntry Entry;
35009467b48Spatrick   Entry.ToState = ParentState;
35109467b48Spatrick   Entry.IsFinally = true;
35209467b48Spatrick   Entry.Filter = nullptr;
35309467b48Spatrick   Entry.Handler = Handler;
35409467b48Spatrick   FuncInfo.SEHUnwindMap.push_back(Entry);
35509467b48Spatrick   return FuncInfo.SEHUnwindMap.size() - 1;
35609467b48Spatrick }
35709467b48Spatrick 
358097a140dSpatrick // Starting from a EHPad, Backward walk through control-flow graph
359097a140dSpatrick // to produce two primary outputs:
360097a140dSpatrick //      FuncInfo.EHPadStateMap[] and FuncInfo.SEHUnwindMap[]
calculateSEHStateNumbers(WinEHFuncInfo & FuncInfo,const Instruction * FirstNonPHI,int ParentState)36109467b48Spatrick static void calculateSEHStateNumbers(WinEHFuncInfo &FuncInfo,
36209467b48Spatrick                                      const Instruction *FirstNonPHI,
36309467b48Spatrick                                      int ParentState) {
36409467b48Spatrick   const BasicBlock *BB = FirstNonPHI->getParent();
36509467b48Spatrick   assert(BB->isEHPad() && "no a funclet!");
36609467b48Spatrick 
36709467b48Spatrick   if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(FirstNonPHI)) {
36809467b48Spatrick     assert(FuncInfo.EHPadStateMap.count(CatchSwitch) == 0 &&
36909467b48Spatrick            "shouldn't revist catch funclets!");
37009467b48Spatrick 
37109467b48Spatrick     // Extract the filter function and the __except basic block and create a
37209467b48Spatrick     // state for them.
37309467b48Spatrick     assert(CatchSwitch->getNumHandlers() == 1 &&
37409467b48Spatrick            "SEH doesn't have multiple handlers per __try");
37509467b48Spatrick     const auto *CatchPad =
37609467b48Spatrick         cast<CatchPadInst>((*CatchSwitch->handler_begin())->getFirstNonPHI());
37709467b48Spatrick     const BasicBlock *CatchPadBB = CatchPad->getParent();
37809467b48Spatrick     const Constant *FilterOrNull =
37909467b48Spatrick         cast<Constant>(CatchPad->getArgOperand(0)->stripPointerCasts());
38009467b48Spatrick     const Function *Filter = dyn_cast<Function>(FilterOrNull);
38109467b48Spatrick     assert((Filter || FilterOrNull->isNullValue()) &&
38209467b48Spatrick            "unexpected filter value");
38309467b48Spatrick     int TryState = addSEHExcept(FuncInfo, ParentState, Filter, CatchPadBB);
38409467b48Spatrick 
38509467b48Spatrick     // Everything in the __try block uses TryState as its parent state.
38609467b48Spatrick     FuncInfo.EHPadStateMap[CatchSwitch] = TryState;
38709467b48Spatrick     LLVM_DEBUG(dbgs() << "Assigning state #" << TryState << " to BB "
38809467b48Spatrick                       << CatchPadBB->getName() << '\n');
38909467b48Spatrick     for (const BasicBlock *PredBlock : predecessors(BB))
39009467b48Spatrick       if ((PredBlock = getEHPadFromPredecessor(PredBlock,
39109467b48Spatrick                                                CatchSwitch->getParentPad())))
39209467b48Spatrick         calculateSEHStateNumbers(FuncInfo, PredBlock->getFirstNonPHI(),
39309467b48Spatrick                                  TryState);
39409467b48Spatrick 
39509467b48Spatrick     // Everything in the __except block unwinds to ParentState, just like code
39609467b48Spatrick     // outside the __try.
39709467b48Spatrick     for (const User *U : CatchPad->users()) {
39809467b48Spatrick       const auto *UserI = cast<Instruction>(U);
39909467b48Spatrick       if (auto *InnerCatchSwitch = dyn_cast<CatchSwitchInst>(UserI)) {
40009467b48Spatrick         BasicBlock *UnwindDest = InnerCatchSwitch->getUnwindDest();
40109467b48Spatrick         if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest())
40209467b48Spatrick           calculateSEHStateNumbers(FuncInfo, UserI, ParentState);
40309467b48Spatrick       }
40409467b48Spatrick       if (auto *InnerCleanupPad = dyn_cast<CleanupPadInst>(UserI)) {
40509467b48Spatrick         BasicBlock *UnwindDest = getCleanupRetUnwindDest(InnerCleanupPad);
40609467b48Spatrick         // If a nested cleanup pad reports a null unwind destination and the
40709467b48Spatrick         // enclosing catch pad doesn't it must be post-dominated by an
40809467b48Spatrick         // unreachable instruction.
40909467b48Spatrick         if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest())
41009467b48Spatrick           calculateSEHStateNumbers(FuncInfo, UserI, ParentState);
41109467b48Spatrick       }
41209467b48Spatrick     }
41309467b48Spatrick   } else {
41409467b48Spatrick     auto *CleanupPad = cast<CleanupPadInst>(FirstNonPHI);
41509467b48Spatrick 
41609467b48Spatrick     // It's possible for a cleanup to be visited twice: it might have multiple
41709467b48Spatrick     // cleanupret instructions.
41809467b48Spatrick     if (FuncInfo.EHPadStateMap.count(CleanupPad))
41909467b48Spatrick       return;
42009467b48Spatrick 
42109467b48Spatrick     int CleanupState = addSEHFinally(FuncInfo, ParentState, BB);
42209467b48Spatrick     FuncInfo.EHPadStateMap[CleanupPad] = CleanupState;
42309467b48Spatrick     LLVM_DEBUG(dbgs() << "Assigning state #" << CleanupState << " to BB "
42409467b48Spatrick                       << BB->getName() << '\n');
42509467b48Spatrick     for (const BasicBlock *PredBlock : predecessors(BB))
42609467b48Spatrick       if ((PredBlock =
42709467b48Spatrick                getEHPadFromPredecessor(PredBlock, CleanupPad->getParentPad())))
42809467b48Spatrick         calculateSEHStateNumbers(FuncInfo, PredBlock->getFirstNonPHI(),
42909467b48Spatrick                                  CleanupState);
43009467b48Spatrick     for (const User *U : CleanupPad->users()) {
43109467b48Spatrick       const auto *UserI = cast<Instruction>(U);
43209467b48Spatrick       if (UserI->isEHPad())
43309467b48Spatrick         report_fatal_error("Cleanup funclets for the SEH personality cannot "
43409467b48Spatrick                            "contain exceptional actions");
43509467b48Spatrick     }
43609467b48Spatrick   }
43709467b48Spatrick }
43809467b48Spatrick 
isTopLevelPadForMSVC(const Instruction * EHPad)43909467b48Spatrick static bool isTopLevelPadForMSVC(const Instruction *EHPad) {
44009467b48Spatrick   if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(EHPad))
44109467b48Spatrick     return isa<ConstantTokenNone>(CatchSwitch->getParentPad()) &&
44209467b48Spatrick            CatchSwitch->unwindsToCaller();
44309467b48Spatrick   if (auto *CleanupPad = dyn_cast<CleanupPadInst>(EHPad))
44409467b48Spatrick     return isa<ConstantTokenNone>(CleanupPad->getParentPad()) &&
44509467b48Spatrick            getCleanupRetUnwindDest(CleanupPad) == nullptr;
44609467b48Spatrick   if (isa<CatchPadInst>(EHPad))
44709467b48Spatrick     return false;
44809467b48Spatrick   llvm_unreachable("unexpected EHPad!");
44909467b48Spatrick }
45009467b48Spatrick 
calculateSEHStateNumbers(const Function * Fn,WinEHFuncInfo & FuncInfo)45109467b48Spatrick void llvm::calculateSEHStateNumbers(const Function *Fn,
45209467b48Spatrick                                     WinEHFuncInfo &FuncInfo) {
45309467b48Spatrick   // Don't compute state numbers twice.
45409467b48Spatrick   if (!FuncInfo.SEHUnwindMap.empty())
45509467b48Spatrick     return;
45609467b48Spatrick 
45709467b48Spatrick   for (const BasicBlock &BB : *Fn) {
45809467b48Spatrick     if (!BB.isEHPad())
45909467b48Spatrick       continue;
46009467b48Spatrick     const Instruction *FirstNonPHI = BB.getFirstNonPHI();
46109467b48Spatrick     if (!isTopLevelPadForMSVC(FirstNonPHI))
46209467b48Spatrick       continue;
46309467b48Spatrick     ::calculateSEHStateNumbers(FuncInfo, FirstNonPHI, -1);
46409467b48Spatrick   }
46509467b48Spatrick 
46609467b48Spatrick   calculateStateNumbersForInvokes(Fn, FuncInfo);
46709467b48Spatrick }
46809467b48Spatrick 
calculateWinCXXEHStateNumbers(const Function * Fn,WinEHFuncInfo & FuncInfo)46909467b48Spatrick void llvm::calculateWinCXXEHStateNumbers(const Function *Fn,
47009467b48Spatrick                                          WinEHFuncInfo &FuncInfo) {
47109467b48Spatrick   // Return if it's already been done.
47209467b48Spatrick   if (!FuncInfo.EHPadStateMap.empty())
47309467b48Spatrick     return;
47409467b48Spatrick 
47509467b48Spatrick   for (const BasicBlock &BB : *Fn) {
47609467b48Spatrick     if (!BB.isEHPad())
47709467b48Spatrick       continue;
47809467b48Spatrick     const Instruction *FirstNonPHI = BB.getFirstNonPHI();
47909467b48Spatrick     if (!isTopLevelPadForMSVC(FirstNonPHI))
48009467b48Spatrick       continue;
48109467b48Spatrick     calculateCXXStateNumbers(FuncInfo, FirstNonPHI, -1);
48209467b48Spatrick   }
48309467b48Spatrick 
48409467b48Spatrick   calculateStateNumbersForInvokes(Fn, FuncInfo);
48509467b48Spatrick }
48609467b48Spatrick 
addClrEHHandler(WinEHFuncInfo & FuncInfo,int HandlerParentState,int TryParentState,ClrHandlerType HandlerType,uint32_t TypeToken,const BasicBlock * Handler)48709467b48Spatrick static int addClrEHHandler(WinEHFuncInfo &FuncInfo, int HandlerParentState,
48809467b48Spatrick                            int TryParentState, ClrHandlerType HandlerType,
48909467b48Spatrick                            uint32_t TypeToken, const BasicBlock *Handler) {
49009467b48Spatrick   ClrEHUnwindMapEntry Entry;
49109467b48Spatrick   Entry.HandlerParentState = HandlerParentState;
49209467b48Spatrick   Entry.TryParentState = TryParentState;
49309467b48Spatrick   Entry.Handler = Handler;
49409467b48Spatrick   Entry.HandlerType = HandlerType;
49509467b48Spatrick   Entry.TypeToken = TypeToken;
49609467b48Spatrick   FuncInfo.ClrEHUnwindMap.push_back(Entry);
49709467b48Spatrick   return FuncInfo.ClrEHUnwindMap.size() - 1;
49809467b48Spatrick }
49909467b48Spatrick 
calculateClrEHStateNumbers(const Function * Fn,WinEHFuncInfo & FuncInfo)50009467b48Spatrick void llvm::calculateClrEHStateNumbers(const Function *Fn,
50109467b48Spatrick                                       WinEHFuncInfo &FuncInfo) {
50209467b48Spatrick   // Return if it's already been done.
50309467b48Spatrick   if (!FuncInfo.EHPadStateMap.empty())
50409467b48Spatrick     return;
50509467b48Spatrick 
50609467b48Spatrick   // This numbering assigns one state number to each catchpad and cleanuppad.
50709467b48Spatrick   // It also computes two tree-like relations over states:
50809467b48Spatrick   // 1) Each state has a "HandlerParentState", which is the state of the next
50909467b48Spatrick   //    outer handler enclosing this state's handler (same as nearest ancestor
51009467b48Spatrick   //    per the ParentPad linkage on EH pads, but skipping over catchswitches).
51109467b48Spatrick   // 2) Each state has a "TryParentState", which:
51209467b48Spatrick   //    a) for a catchpad that's not the last handler on its catchswitch, is
51309467b48Spatrick   //       the state of the next catchpad on that catchswitch
51409467b48Spatrick   //    b) for all other pads, is the state of the pad whose try region is the
51509467b48Spatrick   //       next outer try region enclosing this state's try region.  The "try
51609467b48Spatrick   //       regions are not present as such in the IR, but will be inferred
51709467b48Spatrick   //       based on the placement of invokes and pads which reach each other
51809467b48Spatrick   //       by exceptional exits
51909467b48Spatrick   // Catchswitches do not get their own states, but each gets mapped to the
52009467b48Spatrick   // state of its first catchpad.
52109467b48Spatrick 
52209467b48Spatrick   // Step one: walk down from outermost to innermost funclets, assigning each
52309467b48Spatrick   // catchpad and cleanuppad a state number.  Add an entry to the
52409467b48Spatrick   // ClrEHUnwindMap for each state, recording its HandlerParentState and
52509467b48Spatrick   // handler attributes.  Record the TryParentState as well for each catchpad
52609467b48Spatrick   // that's not the last on its catchswitch, but initialize all other entries'
52709467b48Spatrick   // TryParentStates to a sentinel -1 value that the next pass will update.
52809467b48Spatrick 
52909467b48Spatrick   // Seed a worklist with pads that have no parent.
53009467b48Spatrick   SmallVector<std::pair<const Instruction *, int>, 8> Worklist;
53109467b48Spatrick   for (const BasicBlock &BB : *Fn) {
53209467b48Spatrick     const Instruction *FirstNonPHI = BB.getFirstNonPHI();
53309467b48Spatrick     const Value *ParentPad;
53409467b48Spatrick     if (const auto *CPI = dyn_cast<CleanupPadInst>(FirstNonPHI))
53509467b48Spatrick       ParentPad = CPI->getParentPad();
53609467b48Spatrick     else if (const auto *CSI = dyn_cast<CatchSwitchInst>(FirstNonPHI))
53709467b48Spatrick       ParentPad = CSI->getParentPad();
53809467b48Spatrick     else
53909467b48Spatrick       continue;
54009467b48Spatrick     if (isa<ConstantTokenNone>(ParentPad))
54109467b48Spatrick       Worklist.emplace_back(FirstNonPHI, -1);
54209467b48Spatrick   }
54309467b48Spatrick 
54409467b48Spatrick   // Use the worklist to visit all pads, from outer to inner.  Record
54509467b48Spatrick   // HandlerParentState for all pads.  Record TryParentState only for catchpads
54609467b48Spatrick   // that aren't the last on their catchswitch (setting all other entries'
54709467b48Spatrick   // TryParentStates to an initial value of -1).  This loop is also responsible
54809467b48Spatrick   // for setting the EHPadStateMap entry for all catchpads, cleanuppads, and
54909467b48Spatrick   // catchswitches.
55009467b48Spatrick   while (!Worklist.empty()) {
55109467b48Spatrick     const Instruction *Pad;
55209467b48Spatrick     int HandlerParentState;
55309467b48Spatrick     std::tie(Pad, HandlerParentState) = Worklist.pop_back_val();
55409467b48Spatrick 
55509467b48Spatrick     if (const auto *Cleanup = dyn_cast<CleanupPadInst>(Pad)) {
55609467b48Spatrick       // Create the entry for this cleanup with the appropriate handler
55709467b48Spatrick       // properties.  Finally and fault handlers are distinguished by arity.
55809467b48Spatrick       ClrHandlerType HandlerType =
559*d415bd75Srobert           (Cleanup->arg_size() ? ClrHandlerType::Fault
56009467b48Spatrick                                : ClrHandlerType::Finally);
56109467b48Spatrick       int CleanupState = addClrEHHandler(FuncInfo, HandlerParentState, -1,
56209467b48Spatrick                                          HandlerType, 0, Pad->getParent());
56309467b48Spatrick       // Queue any child EH pads on the worklist.
56409467b48Spatrick       for (const User *U : Cleanup->users())
56509467b48Spatrick         if (const auto *I = dyn_cast<Instruction>(U))
56609467b48Spatrick           if (I->isEHPad())
56709467b48Spatrick             Worklist.emplace_back(I, CleanupState);
56809467b48Spatrick       // Remember this pad's state.
56909467b48Spatrick       FuncInfo.EHPadStateMap[Cleanup] = CleanupState;
57009467b48Spatrick     } else {
57109467b48Spatrick       // Walk the handlers of this catchswitch in reverse order since all but
57209467b48Spatrick       // the last need to set the following one as its TryParentState.
57309467b48Spatrick       const auto *CatchSwitch = cast<CatchSwitchInst>(Pad);
57409467b48Spatrick       int CatchState = -1, FollowerState = -1;
57509467b48Spatrick       SmallVector<const BasicBlock *, 4> CatchBlocks(CatchSwitch->handlers());
576*d415bd75Srobert       for (const BasicBlock *CatchBlock : llvm::reverse(CatchBlocks)) {
57709467b48Spatrick         // Create the entry for this catch with the appropriate handler
57809467b48Spatrick         // properties.
57909467b48Spatrick         const auto *Catch = cast<CatchPadInst>(CatchBlock->getFirstNonPHI());
58009467b48Spatrick         uint32_t TypeToken = static_cast<uint32_t>(
58109467b48Spatrick             cast<ConstantInt>(Catch->getArgOperand(0))->getZExtValue());
58209467b48Spatrick         CatchState =
58309467b48Spatrick             addClrEHHandler(FuncInfo, HandlerParentState, FollowerState,
58409467b48Spatrick                             ClrHandlerType::Catch, TypeToken, CatchBlock);
58509467b48Spatrick         // Queue any child EH pads on the worklist.
58609467b48Spatrick         for (const User *U : Catch->users())
58709467b48Spatrick           if (const auto *I = dyn_cast<Instruction>(U))
58809467b48Spatrick             if (I->isEHPad())
58909467b48Spatrick               Worklist.emplace_back(I, CatchState);
59009467b48Spatrick         // Remember this catch's state.
59109467b48Spatrick         FuncInfo.EHPadStateMap[Catch] = CatchState;
592*d415bd75Srobert         FollowerState = CatchState;
59309467b48Spatrick       }
59409467b48Spatrick       // Associate the catchswitch with the state of its first catch.
59509467b48Spatrick       assert(CatchSwitch->getNumHandlers());
59609467b48Spatrick       FuncInfo.EHPadStateMap[CatchSwitch] = CatchState;
59709467b48Spatrick     }
59809467b48Spatrick   }
59909467b48Spatrick 
60009467b48Spatrick   // Step two: record the TryParentState of each state.  For cleanuppads that
60109467b48Spatrick   // don't have cleanuprets, we may need to infer this from their child pads,
60209467b48Spatrick   // so visit pads in descendant-most to ancestor-most order.
603*d415bd75Srobert   for (ClrEHUnwindMapEntry &Entry : llvm::reverse(FuncInfo.ClrEHUnwindMap)) {
60409467b48Spatrick     const Instruction *Pad =
605*d415bd75Srobert         Entry.Handler.get<const BasicBlock *>()->getFirstNonPHI();
60609467b48Spatrick     // For most pads, the TryParentState is the state associated with the
60709467b48Spatrick     // unwind dest of exceptional exits from it.
60809467b48Spatrick     const BasicBlock *UnwindDest;
60909467b48Spatrick     if (const auto *Catch = dyn_cast<CatchPadInst>(Pad)) {
61009467b48Spatrick       // If a catch is not the last in its catchswitch, its TryParentState is
61109467b48Spatrick       // the state associated with the next catch in the switch, even though
61209467b48Spatrick       // that's not the unwind dest of exceptions escaping the catch.  Those
61309467b48Spatrick       // cases were already assigned a TryParentState in the first pass, so
61409467b48Spatrick       // skip them.
615*d415bd75Srobert       if (Entry.TryParentState != -1)
61609467b48Spatrick         continue;
61709467b48Spatrick       // Otherwise, get the unwind dest from the catchswitch.
61809467b48Spatrick       UnwindDest = Catch->getCatchSwitch()->getUnwindDest();
61909467b48Spatrick     } else {
62009467b48Spatrick       const auto *Cleanup = cast<CleanupPadInst>(Pad);
62109467b48Spatrick       UnwindDest = nullptr;
62209467b48Spatrick       for (const User *U : Cleanup->users()) {
62309467b48Spatrick         if (auto *CleanupRet = dyn_cast<CleanupReturnInst>(U)) {
62409467b48Spatrick           // Common and unambiguous case -- cleanupret indicates cleanup's
62509467b48Spatrick           // unwind dest.
62609467b48Spatrick           UnwindDest = CleanupRet->getUnwindDest();
62709467b48Spatrick           break;
62809467b48Spatrick         }
62909467b48Spatrick 
63009467b48Spatrick         // Get an unwind dest for the user
63109467b48Spatrick         const BasicBlock *UserUnwindDest = nullptr;
63209467b48Spatrick         if (auto *Invoke = dyn_cast<InvokeInst>(U)) {
63309467b48Spatrick           UserUnwindDest = Invoke->getUnwindDest();
63409467b48Spatrick         } else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(U)) {
63509467b48Spatrick           UserUnwindDest = CatchSwitch->getUnwindDest();
63609467b48Spatrick         } else if (auto *ChildCleanup = dyn_cast<CleanupPadInst>(U)) {
63709467b48Spatrick           int UserState = FuncInfo.EHPadStateMap[ChildCleanup];
63809467b48Spatrick           int UserUnwindState =
63909467b48Spatrick               FuncInfo.ClrEHUnwindMap[UserState].TryParentState;
64009467b48Spatrick           if (UserUnwindState != -1)
64109467b48Spatrick             UserUnwindDest = FuncInfo.ClrEHUnwindMap[UserUnwindState]
64209467b48Spatrick                                  .Handler.get<const BasicBlock *>();
64309467b48Spatrick         }
64409467b48Spatrick 
64509467b48Spatrick         // Not having an unwind dest for this user might indicate that it
64609467b48Spatrick         // doesn't unwind, so can't be taken as proof that the cleanup itself
64709467b48Spatrick         // may unwind to caller (see e.g. SimplifyUnreachable and
64809467b48Spatrick         // RemoveUnwindEdge).
64909467b48Spatrick         if (!UserUnwindDest)
65009467b48Spatrick           continue;
65109467b48Spatrick 
65209467b48Spatrick         // Now we have an unwind dest for the user, but we need to see if it
65309467b48Spatrick         // unwinds all the way out of the cleanup or if it stays within it.
65409467b48Spatrick         const Instruction *UserUnwindPad = UserUnwindDest->getFirstNonPHI();
65509467b48Spatrick         const Value *UserUnwindParent;
65609467b48Spatrick         if (auto *CSI = dyn_cast<CatchSwitchInst>(UserUnwindPad))
65709467b48Spatrick           UserUnwindParent = CSI->getParentPad();
65809467b48Spatrick         else
65909467b48Spatrick           UserUnwindParent =
66009467b48Spatrick               cast<CleanupPadInst>(UserUnwindPad)->getParentPad();
66109467b48Spatrick 
66209467b48Spatrick         // The unwind stays within the cleanup iff it targets a child of the
66309467b48Spatrick         // cleanup.
66409467b48Spatrick         if (UserUnwindParent == Cleanup)
66509467b48Spatrick           continue;
66609467b48Spatrick 
66709467b48Spatrick         // This unwind exits the cleanup, so its dest is the cleanup's dest.
66809467b48Spatrick         UnwindDest = UserUnwindDest;
66909467b48Spatrick         break;
67009467b48Spatrick       }
67109467b48Spatrick     }
67209467b48Spatrick 
67309467b48Spatrick     // Record the state of the unwind dest as the TryParentState.
67409467b48Spatrick     int UnwindDestState;
67509467b48Spatrick 
67609467b48Spatrick     // If UnwindDest is null at this point, either the pad in question can
67709467b48Spatrick     // be exited by unwind to caller, or it cannot be exited by unwind.  In
67809467b48Spatrick     // either case, reporting such cases as unwinding to caller is correct.
67909467b48Spatrick     // This can lead to EH tables that "look strange" -- if this pad's is in
68009467b48Spatrick     // a parent funclet which has other children that do unwind to an enclosing
68109467b48Spatrick     // pad, the try region for this pad will be missing the "duplicate" EH
68209467b48Spatrick     // clause entries that you'd expect to see covering the whole parent.  That
68309467b48Spatrick     // should be benign, since the unwind never actually happens.  If it were
68409467b48Spatrick     // an issue, we could add a subsequent pass that pushes unwind dests down
68509467b48Spatrick     // from parents that have them to children that appear to unwind to caller.
68609467b48Spatrick     if (!UnwindDest) {
68709467b48Spatrick       UnwindDestState = -1;
68809467b48Spatrick     } else {
68909467b48Spatrick       UnwindDestState = FuncInfo.EHPadStateMap[UnwindDest->getFirstNonPHI()];
69009467b48Spatrick     }
69109467b48Spatrick 
692*d415bd75Srobert     Entry.TryParentState = UnwindDestState;
69309467b48Spatrick   }
69409467b48Spatrick 
69509467b48Spatrick   // Step three: transfer information from pads to invokes.
69609467b48Spatrick   calculateStateNumbersForInvokes(Fn, FuncInfo);
69709467b48Spatrick }
69809467b48Spatrick 
colorFunclets(Function & F)69909467b48Spatrick void WinEHPrepare::colorFunclets(Function &F) {
70009467b48Spatrick   BlockColors = colorEHFunclets(F);
70109467b48Spatrick 
70209467b48Spatrick   // Invert the map from BB to colors to color to BBs.
70309467b48Spatrick   for (BasicBlock &BB : F) {
70409467b48Spatrick     ColorVector &Colors = BlockColors[&BB];
70509467b48Spatrick     for (BasicBlock *Color : Colors)
70609467b48Spatrick       FuncletBlocks[Color].push_back(&BB);
70709467b48Spatrick   }
70809467b48Spatrick }
70909467b48Spatrick 
demotePHIsOnFunclets(Function & F,bool DemoteCatchSwitchPHIOnly)71009467b48Spatrick void WinEHPrepare::demotePHIsOnFunclets(Function &F,
71109467b48Spatrick                                         bool DemoteCatchSwitchPHIOnly) {
71209467b48Spatrick   // Strip PHI nodes off of EH pads.
71309467b48Spatrick   SmallVector<PHINode *, 16> PHINodes;
71473471bf0Spatrick   for (BasicBlock &BB : make_early_inc_range(F)) {
71573471bf0Spatrick     if (!BB.isEHPad())
71609467b48Spatrick       continue;
71773471bf0Spatrick     if (DemoteCatchSwitchPHIOnly && !isa<CatchSwitchInst>(BB.getFirstNonPHI()))
71809467b48Spatrick       continue;
71909467b48Spatrick 
72073471bf0Spatrick     for (Instruction &I : make_early_inc_range(BB)) {
72173471bf0Spatrick       auto *PN = dyn_cast<PHINode>(&I);
72209467b48Spatrick       // Stop at the first non-PHI.
72309467b48Spatrick       if (!PN)
72409467b48Spatrick         break;
72509467b48Spatrick 
72609467b48Spatrick       AllocaInst *SpillSlot = insertPHILoads(PN, F);
72709467b48Spatrick       if (SpillSlot)
72809467b48Spatrick         insertPHIStores(PN, SpillSlot);
72909467b48Spatrick 
73009467b48Spatrick       PHINodes.push_back(PN);
73109467b48Spatrick     }
73209467b48Spatrick   }
73309467b48Spatrick 
73409467b48Spatrick   for (auto *PN : PHINodes) {
73509467b48Spatrick     // There may be lingering uses on other EH PHIs being removed
736*d415bd75Srobert     PN->replaceAllUsesWith(PoisonValue::get(PN->getType()));
73709467b48Spatrick     PN->eraseFromParent();
73809467b48Spatrick   }
73909467b48Spatrick }
74009467b48Spatrick 
cloneCommonBlocks(Function & F)74109467b48Spatrick void WinEHPrepare::cloneCommonBlocks(Function &F) {
74209467b48Spatrick   // We need to clone all blocks which belong to multiple funclets.  Values are
74309467b48Spatrick   // remapped throughout the funclet to propagate both the new instructions
74409467b48Spatrick   // *and* the new basic blocks themselves.
74509467b48Spatrick   for (auto &Funclets : FuncletBlocks) {
74609467b48Spatrick     BasicBlock *FuncletPadBB = Funclets.first;
74709467b48Spatrick     std::vector<BasicBlock *> &BlocksInFunclet = Funclets.second;
74809467b48Spatrick     Value *FuncletToken;
74909467b48Spatrick     if (FuncletPadBB == &F.getEntryBlock())
75009467b48Spatrick       FuncletToken = ConstantTokenNone::get(F.getContext());
75109467b48Spatrick     else
75209467b48Spatrick       FuncletToken = FuncletPadBB->getFirstNonPHI();
75309467b48Spatrick 
75409467b48Spatrick     std::vector<std::pair<BasicBlock *, BasicBlock *>> Orig2Clone;
75509467b48Spatrick     ValueToValueMapTy VMap;
75609467b48Spatrick     for (BasicBlock *BB : BlocksInFunclet) {
75709467b48Spatrick       ColorVector &ColorsForBB = BlockColors[BB];
75809467b48Spatrick       // We don't need to do anything if the block is monochromatic.
75909467b48Spatrick       size_t NumColorsForBB = ColorsForBB.size();
76009467b48Spatrick       if (NumColorsForBB == 1)
76109467b48Spatrick         continue;
76209467b48Spatrick 
76309467b48Spatrick       DEBUG_WITH_TYPE("winehprepare-coloring",
76409467b48Spatrick                       dbgs() << "  Cloning block \'" << BB->getName()
76509467b48Spatrick                               << "\' for funclet \'" << FuncletPadBB->getName()
76609467b48Spatrick                               << "\'.\n");
76709467b48Spatrick 
76809467b48Spatrick       // Create a new basic block and copy instructions into it!
76909467b48Spatrick       BasicBlock *CBB =
77009467b48Spatrick           CloneBasicBlock(BB, VMap, Twine(".for.", FuncletPadBB->getName()));
77109467b48Spatrick       // Insert the clone immediately after the original to ensure determinism
77209467b48Spatrick       // and to keep the same relative ordering of any funclet's blocks.
77309467b48Spatrick       CBB->insertInto(&F, BB->getNextNode());
77409467b48Spatrick 
77509467b48Spatrick       // Add basic block mapping.
77609467b48Spatrick       VMap[BB] = CBB;
77709467b48Spatrick 
77809467b48Spatrick       // Record delta operations that we need to perform to our color mappings.
77909467b48Spatrick       Orig2Clone.emplace_back(BB, CBB);
78009467b48Spatrick     }
78109467b48Spatrick 
78209467b48Spatrick     // If nothing was cloned, we're done cloning in this funclet.
78309467b48Spatrick     if (Orig2Clone.empty())
78409467b48Spatrick       continue;
78509467b48Spatrick 
78609467b48Spatrick     // Update our color mappings to reflect that one block has lost a color and
78709467b48Spatrick     // another has gained a color.
78809467b48Spatrick     for (auto &BBMapping : Orig2Clone) {
78909467b48Spatrick       BasicBlock *OldBlock = BBMapping.first;
79009467b48Spatrick       BasicBlock *NewBlock = BBMapping.second;
79109467b48Spatrick 
79209467b48Spatrick       BlocksInFunclet.push_back(NewBlock);
79309467b48Spatrick       ColorVector &NewColors = BlockColors[NewBlock];
79409467b48Spatrick       assert(NewColors.empty() && "A new block should only have one color!");
79509467b48Spatrick       NewColors.push_back(FuncletPadBB);
79609467b48Spatrick 
79709467b48Spatrick       DEBUG_WITH_TYPE("winehprepare-coloring",
79809467b48Spatrick                       dbgs() << "  Assigned color \'" << FuncletPadBB->getName()
79909467b48Spatrick                               << "\' to block \'" << NewBlock->getName()
80009467b48Spatrick                               << "\'.\n");
80109467b48Spatrick 
80273471bf0Spatrick       llvm::erase_value(BlocksInFunclet, OldBlock);
80309467b48Spatrick       ColorVector &OldColors = BlockColors[OldBlock];
80473471bf0Spatrick       llvm::erase_value(OldColors, FuncletPadBB);
80509467b48Spatrick 
80609467b48Spatrick       DEBUG_WITH_TYPE("winehprepare-coloring",
80709467b48Spatrick                       dbgs() << "  Removed color \'" << FuncletPadBB->getName()
80809467b48Spatrick                               << "\' from block \'" << OldBlock->getName()
80909467b48Spatrick                               << "\'.\n");
81009467b48Spatrick     }
81109467b48Spatrick 
81209467b48Spatrick     // Loop over all of the instructions in this funclet, fixing up operand
81309467b48Spatrick     // references as we go.  This uses VMap to do all the hard work.
81409467b48Spatrick     for (BasicBlock *BB : BlocksInFunclet)
81509467b48Spatrick       // Loop over all instructions, fixing each one as we find it...
81609467b48Spatrick       for (Instruction &I : *BB)
81709467b48Spatrick         RemapInstruction(&I, VMap,
81809467b48Spatrick                          RF_IgnoreMissingLocals | RF_NoModuleLevelChanges);
81909467b48Spatrick 
82009467b48Spatrick     // Catchrets targeting cloned blocks need to be updated separately from
82109467b48Spatrick     // the loop above because they are not in the current funclet.
82209467b48Spatrick     SmallVector<CatchReturnInst *, 2> FixupCatchrets;
82309467b48Spatrick     for (auto &BBMapping : Orig2Clone) {
82409467b48Spatrick       BasicBlock *OldBlock = BBMapping.first;
82509467b48Spatrick       BasicBlock *NewBlock = BBMapping.second;
82609467b48Spatrick 
82709467b48Spatrick       FixupCatchrets.clear();
82809467b48Spatrick       for (BasicBlock *Pred : predecessors(OldBlock))
82909467b48Spatrick         if (auto *CatchRet = dyn_cast<CatchReturnInst>(Pred->getTerminator()))
83009467b48Spatrick           if (CatchRet->getCatchSwitchParentPad() == FuncletToken)
83109467b48Spatrick             FixupCatchrets.push_back(CatchRet);
83209467b48Spatrick 
83309467b48Spatrick       for (CatchReturnInst *CatchRet : FixupCatchrets)
83409467b48Spatrick         CatchRet->setSuccessor(NewBlock);
83509467b48Spatrick     }
83609467b48Spatrick 
83709467b48Spatrick     auto UpdatePHIOnClonedBlock = [&](PHINode *PN, bool IsForOldBlock) {
83809467b48Spatrick       unsigned NumPreds = PN->getNumIncomingValues();
83909467b48Spatrick       for (unsigned PredIdx = 0, PredEnd = NumPreds; PredIdx != PredEnd;
84009467b48Spatrick            ++PredIdx) {
84109467b48Spatrick         BasicBlock *IncomingBlock = PN->getIncomingBlock(PredIdx);
84209467b48Spatrick         bool EdgeTargetsFunclet;
84309467b48Spatrick         if (auto *CRI =
84409467b48Spatrick                 dyn_cast<CatchReturnInst>(IncomingBlock->getTerminator())) {
84509467b48Spatrick           EdgeTargetsFunclet = (CRI->getCatchSwitchParentPad() == FuncletToken);
84609467b48Spatrick         } else {
84709467b48Spatrick           ColorVector &IncomingColors = BlockColors[IncomingBlock];
84809467b48Spatrick           assert(!IncomingColors.empty() && "Block not colored!");
84909467b48Spatrick           assert((IncomingColors.size() == 1 ||
850*d415bd75Srobert                   !llvm::is_contained(IncomingColors, FuncletPadBB)) &&
85109467b48Spatrick                  "Cloning should leave this funclet's blocks monochromatic");
85209467b48Spatrick           EdgeTargetsFunclet = (IncomingColors.front() == FuncletPadBB);
85309467b48Spatrick         }
85409467b48Spatrick         if (IsForOldBlock != EdgeTargetsFunclet)
85509467b48Spatrick           continue;
85609467b48Spatrick         PN->removeIncomingValue(IncomingBlock, /*DeletePHIIfEmpty=*/false);
85709467b48Spatrick         // Revisit the next entry.
85809467b48Spatrick         --PredIdx;
85909467b48Spatrick         --PredEnd;
86009467b48Spatrick       }
86109467b48Spatrick     };
86209467b48Spatrick 
86309467b48Spatrick     for (auto &BBMapping : Orig2Clone) {
86409467b48Spatrick       BasicBlock *OldBlock = BBMapping.first;
86509467b48Spatrick       BasicBlock *NewBlock = BBMapping.second;
86609467b48Spatrick       for (PHINode &OldPN : OldBlock->phis()) {
86709467b48Spatrick         UpdatePHIOnClonedBlock(&OldPN, /*IsForOldBlock=*/true);
86809467b48Spatrick       }
86909467b48Spatrick       for (PHINode &NewPN : NewBlock->phis()) {
87009467b48Spatrick         UpdatePHIOnClonedBlock(&NewPN, /*IsForOldBlock=*/false);
87109467b48Spatrick       }
87209467b48Spatrick     }
87309467b48Spatrick 
87409467b48Spatrick     // Check to see if SuccBB has PHI nodes. If so, we need to add entries to
87509467b48Spatrick     // the PHI nodes for NewBB now.
87609467b48Spatrick     for (auto &BBMapping : Orig2Clone) {
87709467b48Spatrick       BasicBlock *OldBlock = BBMapping.first;
87809467b48Spatrick       BasicBlock *NewBlock = BBMapping.second;
87909467b48Spatrick       for (BasicBlock *SuccBB : successors(NewBlock)) {
88009467b48Spatrick         for (PHINode &SuccPN : SuccBB->phis()) {
88109467b48Spatrick           // Ok, we have a PHI node.  Figure out what the incoming value was for
88209467b48Spatrick           // the OldBlock.
88309467b48Spatrick           int OldBlockIdx = SuccPN.getBasicBlockIndex(OldBlock);
88409467b48Spatrick           if (OldBlockIdx == -1)
88509467b48Spatrick             break;
88609467b48Spatrick           Value *IV = SuccPN.getIncomingValue(OldBlockIdx);
88709467b48Spatrick 
88809467b48Spatrick           // Remap the value if necessary.
88909467b48Spatrick           if (auto *Inst = dyn_cast<Instruction>(IV)) {
89009467b48Spatrick             ValueToValueMapTy::iterator I = VMap.find(Inst);
89109467b48Spatrick             if (I != VMap.end())
89209467b48Spatrick               IV = I->second;
89309467b48Spatrick           }
89409467b48Spatrick 
89509467b48Spatrick           SuccPN.addIncoming(IV, NewBlock);
89609467b48Spatrick         }
89709467b48Spatrick       }
89809467b48Spatrick     }
89909467b48Spatrick 
90009467b48Spatrick     for (ValueToValueMapTy::value_type VT : VMap) {
90109467b48Spatrick       // If there were values defined in BB that are used outside the funclet,
90209467b48Spatrick       // then we now have to update all uses of the value to use either the
90309467b48Spatrick       // original value, the cloned value, or some PHI derived value.  This can
90409467b48Spatrick       // require arbitrary PHI insertion, of which we are prepared to do, clean
90509467b48Spatrick       // these up now.
90609467b48Spatrick       SmallVector<Use *, 16> UsesToRename;
90709467b48Spatrick 
90809467b48Spatrick       auto *OldI = dyn_cast<Instruction>(const_cast<Value *>(VT.first));
90909467b48Spatrick       if (!OldI)
91009467b48Spatrick         continue;
91109467b48Spatrick       auto *NewI = cast<Instruction>(VT.second);
91209467b48Spatrick       // Scan all uses of this instruction to see if it is used outside of its
91309467b48Spatrick       // funclet, and if so, record them in UsesToRename.
91409467b48Spatrick       for (Use &U : OldI->uses()) {
91509467b48Spatrick         Instruction *UserI = cast<Instruction>(U.getUser());
91609467b48Spatrick         BasicBlock *UserBB = UserI->getParent();
91709467b48Spatrick         ColorVector &ColorsForUserBB = BlockColors[UserBB];
91809467b48Spatrick         assert(!ColorsForUserBB.empty());
91909467b48Spatrick         if (ColorsForUserBB.size() > 1 ||
92009467b48Spatrick             *ColorsForUserBB.begin() != FuncletPadBB)
92109467b48Spatrick           UsesToRename.push_back(&U);
92209467b48Spatrick       }
92309467b48Spatrick 
92409467b48Spatrick       // If there are no uses outside the block, we're done with this
92509467b48Spatrick       // instruction.
92609467b48Spatrick       if (UsesToRename.empty())
92709467b48Spatrick         continue;
92809467b48Spatrick 
92909467b48Spatrick       // We found a use of OldI outside of the funclet.  Rename all uses of OldI
93009467b48Spatrick       // that are outside its funclet to be uses of the appropriate PHI node
93109467b48Spatrick       // etc.
93209467b48Spatrick       SSAUpdater SSAUpdate;
93309467b48Spatrick       SSAUpdate.Initialize(OldI->getType(), OldI->getName());
93409467b48Spatrick       SSAUpdate.AddAvailableValue(OldI->getParent(), OldI);
93509467b48Spatrick       SSAUpdate.AddAvailableValue(NewI->getParent(), NewI);
93609467b48Spatrick 
93709467b48Spatrick       while (!UsesToRename.empty())
93809467b48Spatrick         SSAUpdate.RewriteUseAfterInsertions(*UsesToRename.pop_back_val());
93909467b48Spatrick     }
94009467b48Spatrick   }
94109467b48Spatrick }
94209467b48Spatrick 
removeImplausibleInstructions(Function & F)94309467b48Spatrick void WinEHPrepare::removeImplausibleInstructions(Function &F) {
94409467b48Spatrick   // Remove implausible terminators and replace them with UnreachableInst.
94509467b48Spatrick   for (auto &Funclet : FuncletBlocks) {
94609467b48Spatrick     BasicBlock *FuncletPadBB = Funclet.first;
94709467b48Spatrick     std::vector<BasicBlock *> &BlocksInFunclet = Funclet.second;
94809467b48Spatrick     Instruction *FirstNonPHI = FuncletPadBB->getFirstNonPHI();
94909467b48Spatrick     auto *FuncletPad = dyn_cast<FuncletPadInst>(FirstNonPHI);
95009467b48Spatrick     auto *CatchPad = dyn_cast_or_null<CatchPadInst>(FuncletPad);
95109467b48Spatrick     auto *CleanupPad = dyn_cast_or_null<CleanupPadInst>(FuncletPad);
95209467b48Spatrick 
95309467b48Spatrick     for (BasicBlock *BB : BlocksInFunclet) {
95409467b48Spatrick       for (Instruction &I : *BB) {
955097a140dSpatrick         auto *CB = dyn_cast<CallBase>(&I);
956097a140dSpatrick         if (!CB)
95709467b48Spatrick           continue;
95809467b48Spatrick 
95909467b48Spatrick         Value *FuncletBundleOperand = nullptr;
960097a140dSpatrick         if (auto BU = CB->getOperandBundle(LLVMContext::OB_funclet))
96109467b48Spatrick           FuncletBundleOperand = BU->Inputs.front();
96209467b48Spatrick 
96309467b48Spatrick         if (FuncletBundleOperand == FuncletPad)
96409467b48Spatrick           continue;
96509467b48Spatrick 
96609467b48Spatrick         // Skip call sites which are nounwind intrinsics or inline asm.
96709467b48Spatrick         auto *CalledFn =
968097a140dSpatrick             dyn_cast<Function>(CB->getCalledOperand()->stripPointerCasts());
969097a140dSpatrick         if (CalledFn && ((CalledFn->isIntrinsic() && CB->doesNotThrow()) ||
970097a140dSpatrick                          CB->isInlineAsm()))
97109467b48Spatrick           continue;
97209467b48Spatrick 
97309467b48Spatrick         // This call site was not part of this funclet, remove it.
974097a140dSpatrick         if (isa<InvokeInst>(CB)) {
97509467b48Spatrick           // Remove the unwind edge if it was an invoke.
97609467b48Spatrick           removeUnwindEdge(BB);
97709467b48Spatrick           // Get a pointer to the new call.
97809467b48Spatrick           BasicBlock::iterator CallI =
97909467b48Spatrick               std::prev(BB->getTerminator()->getIterator());
98009467b48Spatrick           auto *CI = cast<CallInst>(&*CallI);
98173471bf0Spatrick           changeToUnreachable(CI);
98209467b48Spatrick         } else {
98373471bf0Spatrick           changeToUnreachable(&I);
98409467b48Spatrick         }
98509467b48Spatrick 
98609467b48Spatrick         // There are no more instructions in the block (except for unreachable),
98709467b48Spatrick         // we are done.
98809467b48Spatrick         break;
98909467b48Spatrick       }
99009467b48Spatrick 
99109467b48Spatrick       Instruction *TI = BB->getTerminator();
99209467b48Spatrick       // CatchPadInst and CleanupPadInst can't transfer control to a ReturnInst.
99309467b48Spatrick       bool IsUnreachableRet = isa<ReturnInst>(TI) && FuncletPad;
99409467b48Spatrick       // The token consumed by a CatchReturnInst must match the funclet token.
99509467b48Spatrick       bool IsUnreachableCatchret = false;
99609467b48Spatrick       if (auto *CRI = dyn_cast<CatchReturnInst>(TI))
99709467b48Spatrick         IsUnreachableCatchret = CRI->getCatchPad() != CatchPad;
99809467b48Spatrick       // The token consumed by a CleanupReturnInst must match the funclet token.
99909467b48Spatrick       bool IsUnreachableCleanupret = false;
100009467b48Spatrick       if (auto *CRI = dyn_cast<CleanupReturnInst>(TI))
100109467b48Spatrick         IsUnreachableCleanupret = CRI->getCleanupPad() != CleanupPad;
100209467b48Spatrick       if (IsUnreachableRet || IsUnreachableCatchret ||
100309467b48Spatrick           IsUnreachableCleanupret) {
100473471bf0Spatrick         changeToUnreachable(TI);
100509467b48Spatrick       } else if (isa<InvokeInst>(TI)) {
100609467b48Spatrick         if (Personality == EHPersonality::MSVC_CXX && CleanupPad) {
100709467b48Spatrick           // Invokes within a cleanuppad for the MSVC++ personality never
100809467b48Spatrick           // transfer control to their unwind edge: the personality will
100909467b48Spatrick           // terminate the program.
101009467b48Spatrick           removeUnwindEdge(BB);
101109467b48Spatrick         }
101209467b48Spatrick       }
101309467b48Spatrick     }
101409467b48Spatrick   }
101509467b48Spatrick }
101609467b48Spatrick 
cleanupPreparedFunclets(Function & F)101709467b48Spatrick void WinEHPrepare::cleanupPreparedFunclets(Function &F) {
101809467b48Spatrick   // Clean-up some of the mess we made by removing useles PHI nodes, trivial
101909467b48Spatrick   // branches, etc.
102073471bf0Spatrick   for (BasicBlock &BB : llvm::make_early_inc_range(F)) {
102173471bf0Spatrick     SimplifyInstructionsInBlock(&BB);
102273471bf0Spatrick     ConstantFoldTerminator(&BB, /*DeleteDeadConditions=*/true);
102373471bf0Spatrick     MergeBlockIntoPredecessor(&BB);
102409467b48Spatrick   }
102509467b48Spatrick 
102609467b48Spatrick   // We might have some unreachable blocks after cleaning up some impossible
102709467b48Spatrick   // control flow.
102809467b48Spatrick   removeUnreachableBlocks(F);
102909467b48Spatrick }
103009467b48Spatrick 
103109467b48Spatrick #ifndef NDEBUG
verifyPreparedFunclets(Function & F)103209467b48Spatrick void WinEHPrepare::verifyPreparedFunclets(Function &F) {
103309467b48Spatrick   for (BasicBlock &BB : F) {
103409467b48Spatrick     size_t NumColors = BlockColors[&BB].size();
103509467b48Spatrick     assert(NumColors == 1 && "Expected monochromatic BB!");
103609467b48Spatrick     if (NumColors == 0)
103709467b48Spatrick       report_fatal_error("Uncolored BB!");
103809467b48Spatrick     if (NumColors > 1)
103909467b48Spatrick       report_fatal_error("Multicolor BB!");
104009467b48Spatrick     assert((DisableDemotion || !(BB.isEHPad() && isa<PHINode>(BB.begin()))) &&
104109467b48Spatrick            "EH Pad still has a PHI!");
104209467b48Spatrick   }
104309467b48Spatrick }
104409467b48Spatrick #endif
104509467b48Spatrick 
prepareExplicitEH(Function & F)104609467b48Spatrick bool WinEHPrepare::prepareExplicitEH(Function &F) {
104709467b48Spatrick   // Remove unreachable blocks.  It is not valuable to assign them a color and
104809467b48Spatrick   // their existence can trick us into thinking values are alive when they are
104909467b48Spatrick   // not.
105009467b48Spatrick   removeUnreachableBlocks(F);
105109467b48Spatrick 
105209467b48Spatrick   // Determine which blocks are reachable from which funclet entries.
105309467b48Spatrick   colorFunclets(F);
105409467b48Spatrick 
105509467b48Spatrick   cloneCommonBlocks(F);
105609467b48Spatrick 
105709467b48Spatrick   if (!DisableDemotion)
105809467b48Spatrick     demotePHIsOnFunclets(F, DemoteCatchSwitchPHIOnly ||
105909467b48Spatrick                                 DemoteCatchSwitchPHIOnlyOpt);
106009467b48Spatrick 
106109467b48Spatrick   if (!DisableCleanups) {
1062097a140dSpatrick     assert(!verifyFunction(F, &dbgs()));
106309467b48Spatrick     removeImplausibleInstructions(F);
106409467b48Spatrick 
1065097a140dSpatrick     assert(!verifyFunction(F, &dbgs()));
106609467b48Spatrick     cleanupPreparedFunclets(F);
106709467b48Spatrick   }
106809467b48Spatrick 
106909467b48Spatrick   LLVM_DEBUG(verifyPreparedFunclets(F));
107009467b48Spatrick   // Recolor the CFG to verify that all is well.
107109467b48Spatrick   LLVM_DEBUG(colorFunclets(F));
107209467b48Spatrick   LLVM_DEBUG(verifyPreparedFunclets(F));
107309467b48Spatrick 
107409467b48Spatrick   BlockColors.clear();
107509467b48Spatrick   FuncletBlocks.clear();
107609467b48Spatrick 
107709467b48Spatrick   return true;
107809467b48Spatrick }
107909467b48Spatrick 
108009467b48Spatrick // TODO: Share loads when one use dominates another, or when a catchpad exit
108109467b48Spatrick // dominates uses (needs dominators).
insertPHILoads(PHINode * PN,Function & F)108209467b48Spatrick AllocaInst *WinEHPrepare::insertPHILoads(PHINode *PN, Function &F) {
108309467b48Spatrick   BasicBlock *PHIBlock = PN->getParent();
108409467b48Spatrick   AllocaInst *SpillSlot = nullptr;
108509467b48Spatrick   Instruction *EHPad = PHIBlock->getFirstNonPHI();
108609467b48Spatrick 
108709467b48Spatrick   if (!EHPad->isTerminator()) {
108809467b48Spatrick     // If the EHPad isn't a terminator, then we can insert a load in this block
108909467b48Spatrick     // that will dominate all uses.
109009467b48Spatrick     SpillSlot = new AllocaInst(PN->getType(), DL->getAllocaAddrSpace(), nullptr,
109109467b48Spatrick                                Twine(PN->getName(), ".wineh.spillslot"),
109209467b48Spatrick                                &F.getEntryBlock().front());
109309467b48Spatrick     Value *V = new LoadInst(PN->getType(), SpillSlot,
109409467b48Spatrick                             Twine(PN->getName(), ".wineh.reload"),
109509467b48Spatrick                             &*PHIBlock->getFirstInsertionPt());
109609467b48Spatrick     PN->replaceAllUsesWith(V);
109709467b48Spatrick     return SpillSlot;
109809467b48Spatrick   }
109909467b48Spatrick 
110009467b48Spatrick   // Otherwise, we have a PHI on a terminator EHPad, and we give up and insert
110109467b48Spatrick   // loads of the slot before every use.
110209467b48Spatrick   DenseMap<BasicBlock *, Value *> Loads;
110373471bf0Spatrick   for (Use &U : llvm::make_early_inc_range(PN->uses())) {
110409467b48Spatrick     auto *UsingInst = cast<Instruction>(U.getUser());
110509467b48Spatrick     if (isa<PHINode>(UsingInst) && UsingInst->getParent()->isEHPad()) {
110609467b48Spatrick       // Use is on an EH pad phi.  Leave it alone; we'll insert loads and
110709467b48Spatrick       // stores for it separately.
110809467b48Spatrick       continue;
110909467b48Spatrick     }
111009467b48Spatrick     replaceUseWithLoad(PN, U, SpillSlot, Loads, F);
111109467b48Spatrick   }
111209467b48Spatrick   return SpillSlot;
111309467b48Spatrick }
111409467b48Spatrick 
111509467b48Spatrick // TODO: improve store placement.  Inserting at def is probably good, but need
111609467b48Spatrick // to be careful not to introduce interfering stores (needs liveness analysis).
111709467b48Spatrick // TODO: identify related phi nodes that can share spill slots, and share them
111809467b48Spatrick // (also needs liveness).
insertPHIStores(PHINode * OriginalPHI,AllocaInst * SpillSlot)111909467b48Spatrick void WinEHPrepare::insertPHIStores(PHINode *OriginalPHI,
112009467b48Spatrick                                    AllocaInst *SpillSlot) {
112109467b48Spatrick   // Use a worklist of (Block, Value) pairs -- the given Value needs to be
112209467b48Spatrick   // stored to the spill slot by the end of the given Block.
112309467b48Spatrick   SmallVector<std::pair<BasicBlock *, Value *>, 4> Worklist;
112409467b48Spatrick 
112509467b48Spatrick   Worklist.push_back({OriginalPHI->getParent(), OriginalPHI});
112609467b48Spatrick 
112709467b48Spatrick   while (!Worklist.empty()) {
112809467b48Spatrick     BasicBlock *EHBlock;
112909467b48Spatrick     Value *InVal;
113009467b48Spatrick     std::tie(EHBlock, InVal) = Worklist.pop_back_val();
113109467b48Spatrick 
113209467b48Spatrick     PHINode *PN = dyn_cast<PHINode>(InVal);
113309467b48Spatrick     if (PN && PN->getParent() == EHBlock) {
113409467b48Spatrick       // The value is defined by another PHI we need to remove, with no room to
113509467b48Spatrick       // insert a store after the PHI, so each predecessor needs to store its
113609467b48Spatrick       // incoming value.
113709467b48Spatrick       for (unsigned i = 0, e = PN->getNumIncomingValues(); i < e; ++i) {
113809467b48Spatrick         Value *PredVal = PN->getIncomingValue(i);
113909467b48Spatrick 
114009467b48Spatrick         // Undef can safely be skipped.
114109467b48Spatrick         if (isa<UndefValue>(PredVal))
114209467b48Spatrick           continue;
114309467b48Spatrick 
114409467b48Spatrick         insertPHIStore(PN->getIncomingBlock(i), PredVal, SpillSlot, Worklist);
114509467b48Spatrick       }
114609467b48Spatrick     } else {
114709467b48Spatrick       // We need to store InVal, which dominates EHBlock, but can't put a store
114809467b48Spatrick       // in EHBlock, so need to put stores in each predecessor.
114909467b48Spatrick       for (BasicBlock *PredBlock : predecessors(EHBlock)) {
115009467b48Spatrick         insertPHIStore(PredBlock, InVal, SpillSlot, Worklist);
115109467b48Spatrick       }
115209467b48Spatrick     }
115309467b48Spatrick   }
115409467b48Spatrick }
115509467b48Spatrick 
insertPHIStore(BasicBlock * PredBlock,Value * PredVal,AllocaInst * SpillSlot,SmallVectorImpl<std::pair<BasicBlock *,Value * >> & Worklist)115609467b48Spatrick void WinEHPrepare::insertPHIStore(
115709467b48Spatrick     BasicBlock *PredBlock, Value *PredVal, AllocaInst *SpillSlot,
115809467b48Spatrick     SmallVectorImpl<std::pair<BasicBlock *, Value *>> &Worklist) {
115909467b48Spatrick 
116009467b48Spatrick   if (PredBlock->isEHPad() && PredBlock->getFirstNonPHI()->isTerminator()) {
116109467b48Spatrick     // Pred is unsplittable, so we need to queue it on the worklist.
116209467b48Spatrick     Worklist.push_back({PredBlock, PredVal});
116309467b48Spatrick     return;
116409467b48Spatrick   }
116509467b48Spatrick 
116609467b48Spatrick   // Otherwise, insert the store at the end of the basic block.
116709467b48Spatrick   new StoreInst(PredVal, SpillSlot, PredBlock->getTerminator());
116809467b48Spatrick }
116909467b48Spatrick 
replaceUseWithLoad(Value * V,Use & U,AllocaInst * & SpillSlot,DenseMap<BasicBlock *,Value * > & Loads,Function & F)117009467b48Spatrick void WinEHPrepare::replaceUseWithLoad(Value *V, Use &U, AllocaInst *&SpillSlot,
117109467b48Spatrick                                       DenseMap<BasicBlock *, Value *> &Loads,
117209467b48Spatrick                                       Function &F) {
117309467b48Spatrick   // Lazilly create the spill slot.
117409467b48Spatrick   if (!SpillSlot)
117509467b48Spatrick     SpillSlot = new AllocaInst(V->getType(), DL->getAllocaAddrSpace(), nullptr,
117609467b48Spatrick                                Twine(V->getName(), ".wineh.spillslot"),
117709467b48Spatrick                                &F.getEntryBlock().front());
117809467b48Spatrick 
117909467b48Spatrick   auto *UsingInst = cast<Instruction>(U.getUser());
118009467b48Spatrick   if (auto *UsingPHI = dyn_cast<PHINode>(UsingInst)) {
118109467b48Spatrick     // If this is a PHI node, we can't insert a load of the value before
118209467b48Spatrick     // the use.  Instead insert the load in the predecessor block
118309467b48Spatrick     // corresponding to the incoming value.
118409467b48Spatrick     //
118509467b48Spatrick     // Note that if there are multiple edges from a basic block to this
118609467b48Spatrick     // PHI node that we cannot have multiple loads.  The problem is that
118709467b48Spatrick     // the resulting PHI node will have multiple values (from each load)
118809467b48Spatrick     // coming in from the same block, which is illegal SSA form.
118909467b48Spatrick     // For this reason, we keep track of and reuse loads we insert.
119009467b48Spatrick     BasicBlock *IncomingBlock = UsingPHI->getIncomingBlock(U);
119109467b48Spatrick     if (auto *CatchRet =
119209467b48Spatrick             dyn_cast<CatchReturnInst>(IncomingBlock->getTerminator())) {
119309467b48Spatrick       // Putting a load above a catchret and use on the phi would still leave
119409467b48Spatrick       // a cross-funclet def/use.  We need to split the edge, change the
119509467b48Spatrick       // catchret to target the new block, and put the load there.
119609467b48Spatrick       BasicBlock *PHIBlock = UsingInst->getParent();
119709467b48Spatrick       BasicBlock *NewBlock = SplitEdge(IncomingBlock, PHIBlock);
119809467b48Spatrick       // SplitEdge gives us:
119909467b48Spatrick       //   IncomingBlock:
120009467b48Spatrick       //     ...
120109467b48Spatrick       //     br label %NewBlock
120209467b48Spatrick       //   NewBlock:
120309467b48Spatrick       //     catchret label %PHIBlock
120409467b48Spatrick       // But we need:
120509467b48Spatrick       //   IncomingBlock:
120609467b48Spatrick       //     ...
120709467b48Spatrick       //     catchret label %NewBlock
120809467b48Spatrick       //   NewBlock:
120909467b48Spatrick       //     br label %PHIBlock
121009467b48Spatrick       // So move the terminators to each others' blocks and swap their
121109467b48Spatrick       // successors.
121209467b48Spatrick       BranchInst *Goto = cast<BranchInst>(IncomingBlock->getTerminator());
121309467b48Spatrick       Goto->removeFromParent();
121409467b48Spatrick       CatchRet->removeFromParent();
1215*d415bd75Srobert       CatchRet->insertInto(IncomingBlock, IncomingBlock->end());
1216*d415bd75Srobert       Goto->insertInto(NewBlock, NewBlock->end());
121709467b48Spatrick       Goto->setSuccessor(0, PHIBlock);
121809467b48Spatrick       CatchRet->setSuccessor(NewBlock);
121909467b48Spatrick       // Update the color mapping for the newly split edge.
122009467b48Spatrick       // Grab a reference to the ColorVector to be inserted before getting the
122109467b48Spatrick       // reference to the vector we are copying because inserting the new
122209467b48Spatrick       // element in BlockColors might cause the map to be reallocated.
122309467b48Spatrick       ColorVector &ColorsForNewBlock = BlockColors[NewBlock];
122409467b48Spatrick       ColorVector &ColorsForPHIBlock = BlockColors[PHIBlock];
122509467b48Spatrick       ColorsForNewBlock = ColorsForPHIBlock;
122609467b48Spatrick       for (BasicBlock *FuncletPad : ColorsForPHIBlock)
122709467b48Spatrick         FuncletBlocks[FuncletPad].push_back(NewBlock);
122809467b48Spatrick       // Treat the new block as incoming for load insertion.
122909467b48Spatrick       IncomingBlock = NewBlock;
123009467b48Spatrick     }
123109467b48Spatrick     Value *&Load = Loads[IncomingBlock];
123209467b48Spatrick     // Insert the load into the predecessor block
123309467b48Spatrick     if (!Load)
123409467b48Spatrick       Load = new LoadInst(V->getType(), SpillSlot,
123509467b48Spatrick                           Twine(V->getName(), ".wineh.reload"),
123609467b48Spatrick                           /*isVolatile=*/false, IncomingBlock->getTerminator());
123709467b48Spatrick 
123809467b48Spatrick     U.set(Load);
123909467b48Spatrick   } else {
124009467b48Spatrick     // Reload right before the old use.
124109467b48Spatrick     auto *Load = new LoadInst(V->getType(), SpillSlot,
124209467b48Spatrick                               Twine(V->getName(), ".wineh.reload"),
124309467b48Spatrick                               /*isVolatile=*/false, UsingInst);
124409467b48Spatrick     U.set(Load);
124509467b48Spatrick   }
124609467b48Spatrick }
124709467b48Spatrick 
addIPToStateRange(const InvokeInst * II,MCSymbol * InvokeBegin,MCSymbol * InvokeEnd)124809467b48Spatrick void WinEHFuncInfo::addIPToStateRange(const InvokeInst *II,
124909467b48Spatrick                                       MCSymbol *InvokeBegin,
125009467b48Spatrick                                       MCSymbol *InvokeEnd) {
125109467b48Spatrick   assert(InvokeStateMap.count(II) &&
125209467b48Spatrick          "should get invoke with precomputed state");
125309467b48Spatrick   LabelToStateMap[InvokeBegin] = std::make_pair(InvokeStateMap[II], InvokeEnd);
125409467b48Spatrick }
125509467b48Spatrick 
1256*d415bd75Srobert WinEHFuncInfo::WinEHFuncInfo() = default;
1257