10b57cec5SDimitry Andric //===-- WinEHPrepare - Prepare exception handling for code generation ---===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This pass lowers LLVM IR exception handling into something closer to what the
100b57cec5SDimitry Andric // backend wants for functions using a personality function from a runtime
110b57cec5SDimitry Andric // provided by MSVC. Functions with other personality functions are left alone
120b57cec5SDimitry Andric // and may be prepared by other passes. In particular, all supported MSVC
130b57cec5SDimitry Andric // personality functions require cleanup code to be outlined, and the C++
140b57cec5SDimitry Andric // personality requires catch handler code to be outlined.
150b57cec5SDimitry Andric //
160b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
170b57cec5SDimitry Andric 
185f757f3fSDimitry Andric #include "llvm/CodeGen/WinEHPrepare.h"
190b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
200b57cec5SDimitry Andric #include "llvm/ADT/MapVector.h"
210b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/WinEHFuncInfo.h"
2581ad6265SDimitry Andric #include "llvm/IR/Constants.h"
2606c3fb27SDimitry Andric #include "llvm/IR/EHPersonalities.h"
2781ad6265SDimitry Andric #include "llvm/IR/Instructions.h"
280b57cec5SDimitry Andric #include "llvm/IR/Verifier.h"
29480093f4SDimitry Andric #include "llvm/InitializePasses.h"
300b57cec5SDimitry Andric #include "llvm/Pass.h"
31480093f4SDimitry Andric #include "llvm/Support/CommandLine.h"
320b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
330b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
3406c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
350b57cec5SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h"
360b57cec5SDimitry Andric #include "llvm/Transforms/Utils/Cloning.h"
37480093f4SDimitry Andric #include "llvm/Transforms/Utils/Local.h"
380b57cec5SDimitry Andric #include "llvm/Transforms/Utils/SSAUpdater.h"
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric using namespace llvm;
410b57cec5SDimitry Andric 
425f757f3fSDimitry Andric #define DEBUG_TYPE "win-eh-prepare"
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric static cl::opt<bool> DisableDemotion(
450b57cec5SDimitry Andric     "disable-demotion", cl::Hidden,
460b57cec5SDimitry Andric     cl::desc(
470b57cec5SDimitry Andric         "Clone multicolor basic blocks but do not demote cross scopes"),
480b57cec5SDimitry Andric     cl::init(false));
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric static cl::opt<bool> DisableCleanups(
510b57cec5SDimitry Andric     "disable-cleanups", cl::Hidden,
520b57cec5SDimitry Andric     cl::desc("Do not remove implausible terminators or other similar cleanups"),
530b57cec5SDimitry Andric     cl::init(false));
540b57cec5SDimitry Andric 
555f757f3fSDimitry Andric // TODO: Remove this option when we fully migrate to new pass manager
560b57cec5SDimitry Andric static cl::opt<bool> DemoteCatchSwitchPHIOnlyOpt(
570b57cec5SDimitry Andric     "demote-catchswitch-only", cl::Hidden,
580b57cec5SDimitry Andric     cl::desc("Demote catchswitch BBs only (for wasm EH)"), cl::init(false));
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric namespace {
610b57cec5SDimitry Andric 
625f757f3fSDimitry Andric class WinEHPrepareImpl {
630b57cec5SDimitry Andric public:
WinEHPrepareImpl(bool DemoteCatchSwitchPHIOnly)645f757f3fSDimitry Andric   WinEHPrepareImpl(bool DemoteCatchSwitchPHIOnly)
655f757f3fSDimitry Andric       : DemoteCatchSwitchPHIOnly(DemoteCatchSwitchPHIOnly) {}
660b57cec5SDimitry Andric 
675f757f3fSDimitry Andric   bool runOnFunction(Function &Fn);
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric private:
700b57cec5SDimitry Andric   void insertPHIStores(PHINode *OriginalPHI, AllocaInst *SpillSlot);
710b57cec5SDimitry Andric   void
720b57cec5SDimitry Andric   insertPHIStore(BasicBlock *PredBlock, Value *PredVal, AllocaInst *SpillSlot,
730b57cec5SDimitry Andric                  SmallVectorImpl<std::pair<BasicBlock *, Value *>> &Worklist);
740b57cec5SDimitry Andric   AllocaInst *insertPHILoads(PHINode *PN, Function &F);
750b57cec5SDimitry Andric   void replaceUseWithLoad(Value *V, Use &U, AllocaInst *&SpillSlot,
760b57cec5SDimitry Andric                           DenseMap<BasicBlock *, Value *> &Loads, Function &F);
770b57cec5SDimitry Andric   bool prepareExplicitEH(Function &F);
780b57cec5SDimitry Andric   void colorFunclets(Function &F);
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   void demotePHIsOnFunclets(Function &F, bool DemoteCatchSwitchPHIOnly);
810b57cec5SDimitry Andric   void cloneCommonBlocks(Function &F);
820b57cec5SDimitry Andric   void removeImplausibleInstructions(Function &F);
830b57cec5SDimitry Andric   void cleanupPreparedFunclets(Function &F);
840b57cec5SDimitry Andric   void verifyPreparedFunclets(Function &F);
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   bool DemoteCatchSwitchPHIOnly;
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric   // All fields are reset by runOnFunction.
890b57cec5SDimitry Andric   EHPersonality Personality = EHPersonality::Unknown;
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   const DataLayout *DL = nullptr;
920b57cec5SDimitry Andric   DenseMap<BasicBlock *, ColorVector> BlockColors;
930b57cec5SDimitry Andric   MapVector<BasicBlock *, std::vector<BasicBlock *>> FuncletBlocks;
940b57cec5SDimitry Andric };
950b57cec5SDimitry Andric 
965f757f3fSDimitry Andric class WinEHPrepare : public FunctionPass {
975f757f3fSDimitry Andric   bool DemoteCatchSwitchPHIOnly;
985f757f3fSDimitry Andric 
995f757f3fSDimitry Andric public:
1005f757f3fSDimitry Andric   static char ID; // Pass identification, replacement for typeid.
1015f757f3fSDimitry Andric 
WinEHPrepare(bool DemoteCatchSwitchPHIOnly=false)1025f757f3fSDimitry Andric   WinEHPrepare(bool DemoteCatchSwitchPHIOnly = false)
1035f757f3fSDimitry Andric       : FunctionPass(ID), DemoteCatchSwitchPHIOnly(DemoteCatchSwitchPHIOnly) {}
1045f757f3fSDimitry Andric 
getPassName() const1055f757f3fSDimitry Andric   StringRef getPassName() const override {
1065f757f3fSDimitry Andric     return "Windows exception handling preparation";
1075f757f3fSDimitry Andric   }
1085f757f3fSDimitry Andric 
runOnFunction(Function & Fn)1095f757f3fSDimitry Andric   bool runOnFunction(Function &Fn) override {
1105f757f3fSDimitry Andric     return WinEHPrepareImpl(DemoteCatchSwitchPHIOnly).runOnFunction(Fn);
1115f757f3fSDimitry Andric   }
1125f757f3fSDimitry Andric };
1135f757f3fSDimitry Andric 
1140b57cec5SDimitry Andric } // end anonymous namespace
1150b57cec5SDimitry Andric 
run(Function & F,FunctionAnalysisManager &)1165f757f3fSDimitry Andric PreservedAnalyses WinEHPreparePass::run(Function &F,
1175f757f3fSDimitry Andric                                         FunctionAnalysisManager &) {
1185f757f3fSDimitry Andric   bool Changed = WinEHPrepareImpl(DemoteCatchSwitchPHIOnly).runOnFunction(F);
1195f757f3fSDimitry Andric   return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
1205f757f3fSDimitry Andric }
1215f757f3fSDimitry Andric 
1220b57cec5SDimitry Andric char WinEHPrepare::ID = 0;
1235f757f3fSDimitry Andric INITIALIZE_PASS(WinEHPrepare, DEBUG_TYPE, "Prepare Windows exceptions", false,
1245f757f3fSDimitry Andric                 false)
1250b57cec5SDimitry Andric 
createWinEHPass(bool DemoteCatchSwitchPHIOnly)1260b57cec5SDimitry Andric FunctionPass *llvm::createWinEHPass(bool DemoteCatchSwitchPHIOnly) {
1270b57cec5SDimitry Andric   return new WinEHPrepare(DemoteCatchSwitchPHIOnly);
1280b57cec5SDimitry Andric }
1290b57cec5SDimitry Andric 
runOnFunction(Function & Fn)1305f757f3fSDimitry Andric bool WinEHPrepareImpl::runOnFunction(Function &Fn) {
1310b57cec5SDimitry Andric   if (!Fn.hasPersonalityFn())
1320b57cec5SDimitry Andric     return false;
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric   // Classify the personality to see what kind of preparation we need.
1350b57cec5SDimitry Andric   Personality = classifyEHPersonality(Fn.getPersonalityFn());
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   // Do nothing if this is not a scope-based personality.
1380b57cec5SDimitry Andric   if (!isScopedEHPersonality(Personality))
1390b57cec5SDimitry Andric     return false;
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   DL = &Fn.getParent()->getDataLayout();
1420b57cec5SDimitry Andric   return prepareExplicitEH(Fn);
1430b57cec5SDimitry Andric }
1440b57cec5SDimitry Andric 
addUnwindMapEntry(WinEHFuncInfo & FuncInfo,int ToState,const BasicBlock * BB)1450b57cec5SDimitry Andric static int addUnwindMapEntry(WinEHFuncInfo &FuncInfo, int ToState,
1460b57cec5SDimitry Andric                              const BasicBlock *BB) {
1470b57cec5SDimitry Andric   CxxUnwindMapEntry UME;
1480b57cec5SDimitry Andric   UME.ToState = ToState;
1490b57cec5SDimitry Andric   UME.Cleanup = BB;
1500b57cec5SDimitry Andric   FuncInfo.CxxUnwindMap.push_back(UME);
1510b57cec5SDimitry Andric   return FuncInfo.getLastStateNumber();
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric 
addTryBlockMapEntry(WinEHFuncInfo & FuncInfo,int TryLow,int TryHigh,int CatchHigh,ArrayRef<const CatchPadInst * > Handlers)1540b57cec5SDimitry Andric static void addTryBlockMapEntry(WinEHFuncInfo &FuncInfo, int TryLow,
1550b57cec5SDimitry Andric                                 int TryHigh, int CatchHigh,
1560b57cec5SDimitry Andric                                 ArrayRef<const CatchPadInst *> Handlers) {
1570b57cec5SDimitry Andric   WinEHTryBlockMapEntry TBME;
1580b57cec5SDimitry Andric   TBME.TryLow = TryLow;
1590b57cec5SDimitry Andric   TBME.TryHigh = TryHigh;
1600b57cec5SDimitry Andric   TBME.CatchHigh = CatchHigh;
1610b57cec5SDimitry Andric   assert(TBME.TryLow <= TBME.TryHigh);
1620b57cec5SDimitry Andric   for (const CatchPadInst *CPI : Handlers) {
1630b57cec5SDimitry Andric     WinEHHandlerType HT;
1640b57cec5SDimitry Andric     Constant *TypeInfo = cast<Constant>(CPI->getArgOperand(0));
1650b57cec5SDimitry Andric     if (TypeInfo->isNullValue())
1660b57cec5SDimitry Andric       HT.TypeDescriptor = nullptr;
1670b57cec5SDimitry Andric     else
1680b57cec5SDimitry Andric       HT.TypeDescriptor = cast<GlobalVariable>(TypeInfo->stripPointerCasts());
1690b57cec5SDimitry Andric     HT.Adjectives = cast<ConstantInt>(CPI->getArgOperand(1))->getZExtValue();
1700b57cec5SDimitry Andric     HT.Handler = CPI->getParent();
1710b57cec5SDimitry Andric     if (auto *AI =
1720b57cec5SDimitry Andric             dyn_cast<AllocaInst>(CPI->getArgOperand(2)->stripPointerCasts()))
1730b57cec5SDimitry Andric       HT.CatchObj.Alloca = AI;
1740b57cec5SDimitry Andric     else
1750b57cec5SDimitry Andric       HT.CatchObj.Alloca = nullptr;
1760b57cec5SDimitry Andric     TBME.HandlerArray.push_back(HT);
1770b57cec5SDimitry Andric   }
1780b57cec5SDimitry Andric   FuncInfo.TryBlockMap.push_back(TBME);
1790b57cec5SDimitry Andric }
1800b57cec5SDimitry Andric 
getCleanupRetUnwindDest(const CleanupPadInst * CleanupPad)1810b57cec5SDimitry Andric static BasicBlock *getCleanupRetUnwindDest(const CleanupPadInst *CleanupPad) {
1820b57cec5SDimitry Andric   for (const User *U : CleanupPad->users())
1830b57cec5SDimitry Andric     if (const auto *CRI = dyn_cast<CleanupReturnInst>(U))
1840b57cec5SDimitry Andric       return CRI->getUnwindDest();
1850b57cec5SDimitry Andric   return nullptr;
1860b57cec5SDimitry Andric }
1870b57cec5SDimitry Andric 
calculateStateNumbersForInvokes(const Function * Fn,WinEHFuncInfo & FuncInfo)1880b57cec5SDimitry Andric static void calculateStateNumbersForInvokes(const Function *Fn,
1890b57cec5SDimitry Andric                                             WinEHFuncInfo &FuncInfo) {
1900b57cec5SDimitry Andric   auto *F = const_cast<Function *>(Fn);
1910b57cec5SDimitry Andric   DenseMap<BasicBlock *, ColorVector> BlockColors = colorEHFunclets(*F);
1920b57cec5SDimitry Andric   for (BasicBlock &BB : *F) {
1930b57cec5SDimitry Andric     auto *II = dyn_cast<InvokeInst>(BB.getTerminator());
1940b57cec5SDimitry Andric     if (!II)
1950b57cec5SDimitry Andric       continue;
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric     auto &BBColors = BlockColors[&BB];
1980b57cec5SDimitry Andric     assert(BBColors.size() == 1 && "multi-color BB not removed by preparation");
1990b57cec5SDimitry Andric     BasicBlock *FuncletEntryBB = BBColors.front();
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric     BasicBlock *FuncletUnwindDest;
2020b57cec5SDimitry Andric     auto *FuncletPad =
2030b57cec5SDimitry Andric         dyn_cast<FuncletPadInst>(FuncletEntryBB->getFirstNonPHI());
2040b57cec5SDimitry Andric     assert(FuncletPad || FuncletEntryBB == &Fn->getEntryBlock());
2050b57cec5SDimitry Andric     if (!FuncletPad)
2060b57cec5SDimitry Andric       FuncletUnwindDest = nullptr;
2070b57cec5SDimitry Andric     else if (auto *CatchPad = dyn_cast<CatchPadInst>(FuncletPad))
2080b57cec5SDimitry Andric       FuncletUnwindDest = CatchPad->getCatchSwitch()->getUnwindDest();
2090b57cec5SDimitry Andric     else if (auto *CleanupPad = dyn_cast<CleanupPadInst>(FuncletPad))
2100b57cec5SDimitry Andric       FuncletUnwindDest = getCleanupRetUnwindDest(CleanupPad);
2110b57cec5SDimitry Andric     else
2120b57cec5SDimitry Andric       llvm_unreachable("unexpected funclet pad!");
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric     BasicBlock *InvokeUnwindDest = II->getUnwindDest();
2150b57cec5SDimitry Andric     int BaseState = -1;
2160b57cec5SDimitry Andric     if (FuncletUnwindDest == InvokeUnwindDest) {
2170b57cec5SDimitry Andric       auto BaseStateI = FuncInfo.FuncletBaseStateMap.find(FuncletPad);
2180b57cec5SDimitry Andric       if (BaseStateI != FuncInfo.FuncletBaseStateMap.end())
2190b57cec5SDimitry Andric         BaseState = BaseStateI->second;
2200b57cec5SDimitry Andric     }
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric     if (BaseState != -1) {
2230b57cec5SDimitry Andric       FuncInfo.InvokeStateMap[II] = BaseState;
2240b57cec5SDimitry Andric     } else {
2250b57cec5SDimitry Andric       Instruction *PadInst = InvokeUnwindDest->getFirstNonPHI();
2260b57cec5SDimitry Andric       assert(FuncInfo.EHPadStateMap.count(PadInst) && "EH Pad has no state!");
2270b57cec5SDimitry Andric       FuncInfo.InvokeStateMap[II] = FuncInfo.EHPadStateMap[PadInst];
2280b57cec5SDimitry Andric     }
2290b57cec5SDimitry Andric   }
2300b57cec5SDimitry Andric }
2310b57cec5SDimitry Andric 
23206c3fb27SDimitry Andric // See comments below for calculateSEHStateForAsynchEH().
23306c3fb27SDimitry Andric // State - incoming State of normal paths
23406c3fb27SDimitry Andric struct WorkItem {
23506c3fb27SDimitry Andric   const BasicBlock *Block;
23606c3fb27SDimitry Andric   int State;
WorkItemWorkItem23706c3fb27SDimitry Andric   WorkItem(const BasicBlock *BB, int St) {
23806c3fb27SDimitry Andric     Block = BB;
23906c3fb27SDimitry Andric     State = St;
24006c3fb27SDimitry Andric   }
24106c3fb27SDimitry Andric };
calculateCXXStateForAsynchEH(const BasicBlock * BB,int State,WinEHFuncInfo & EHInfo)24206c3fb27SDimitry Andric void llvm::calculateCXXStateForAsynchEH(const BasicBlock *BB, int State,
24306c3fb27SDimitry Andric                                         WinEHFuncInfo &EHInfo) {
24406c3fb27SDimitry Andric   SmallVector<struct WorkItem *, 8> WorkList;
24506c3fb27SDimitry Andric   struct WorkItem *WI = new WorkItem(BB, State);
24606c3fb27SDimitry Andric   WorkList.push_back(WI);
24706c3fb27SDimitry Andric 
24806c3fb27SDimitry Andric   while (!WorkList.empty()) {
24906c3fb27SDimitry Andric     WI = WorkList.pop_back_val();
25006c3fb27SDimitry Andric     const BasicBlock *BB = WI->Block;
25106c3fb27SDimitry Andric     int State = WI->State;
25206c3fb27SDimitry Andric     delete WI;
25306c3fb27SDimitry Andric     if (EHInfo.BlockToStateMap.count(BB) && EHInfo.BlockToStateMap[BB] <= State)
25406c3fb27SDimitry Andric       continue; // skip blocks already visited by lower State
25506c3fb27SDimitry Andric 
25606c3fb27SDimitry Andric     const llvm::Instruction *I = BB->getFirstNonPHI();
25706c3fb27SDimitry Andric     const llvm::Instruction *TI = BB->getTerminator();
25806c3fb27SDimitry Andric     if (I->isEHPad())
25906c3fb27SDimitry Andric       State = EHInfo.EHPadStateMap[I];
26006c3fb27SDimitry Andric     EHInfo.BlockToStateMap[BB] = State; // Record state, also flag visiting
26106c3fb27SDimitry Andric 
26206c3fb27SDimitry Andric     if ((isa<CleanupReturnInst>(TI) || isa<CatchReturnInst>(TI)) && State > 0) {
26306c3fb27SDimitry Andric       // Retrive the new State
26406c3fb27SDimitry Andric       State = EHInfo.CxxUnwindMap[State].ToState; // Retrive next State
26506c3fb27SDimitry Andric     } else if (isa<InvokeInst>(TI)) {
26606c3fb27SDimitry Andric       auto *Call = cast<CallBase>(TI);
26706c3fb27SDimitry Andric       const Function *Fn = Call->getCalledFunction();
26806c3fb27SDimitry Andric       if (Fn && Fn->isIntrinsic() &&
26906c3fb27SDimitry Andric           (Fn->getIntrinsicID() == Intrinsic::seh_scope_begin ||
27006c3fb27SDimitry Andric            Fn->getIntrinsicID() == Intrinsic::seh_try_begin))
27106c3fb27SDimitry Andric         // Retrive the new State from seh_scope_begin
27206c3fb27SDimitry Andric         State = EHInfo.InvokeStateMap[cast<InvokeInst>(TI)];
27306c3fb27SDimitry Andric       else if (Fn && Fn->isIntrinsic() &&
27406c3fb27SDimitry Andric                (Fn->getIntrinsicID() == Intrinsic::seh_scope_end ||
27506c3fb27SDimitry Andric                 Fn->getIntrinsicID() == Intrinsic::seh_try_end)) {
27606c3fb27SDimitry Andric         // In case of conditional ctor, let's retrieve State from Invoke
27706c3fb27SDimitry Andric         State = EHInfo.InvokeStateMap[cast<InvokeInst>(TI)];
27806c3fb27SDimitry Andric         // end of current state, retrive new state from UnwindMap
27906c3fb27SDimitry Andric         State = EHInfo.CxxUnwindMap[State].ToState;
28006c3fb27SDimitry Andric       }
28106c3fb27SDimitry Andric     }
28206c3fb27SDimitry Andric     // Continue push successors into worklist
28306c3fb27SDimitry Andric     for (auto *SuccBB : successors(BB)) {
28406c3fb27SDimitry Andric       WI = new WorkItem(SuccBB, State);
28506c3fb27SDimitry Andric       WorkList.push_back(WI);
28606c3fb27SDimitry Andric     }
28706c3fb27SDimitry Andric   }
28806c3fb27SDimitry Andric }
28906c3fb27SDimitry Andric 
29006c3fb27SDimitry Andric // The central theory of this routine is based on the following:
29106c3fb27SDimitry Andric //   A _try scope is always a SEME (Single Entry Multiple Exits) region
29206c3fb27SDimitry Andric //     as jumping into a _try is not allowed
29306c3fb27SDimitry Andric //   The single entry must start with a seh_try_begin() invoke with a
29406c3fb27SDimitry Andric //     correct State number that is the initial state of the SEME.
29506c3fb27SDimitry Andric //   Through control-flow, state number is propagated into all blocks.
29606c3fb27SDimitry Andric //   Side exits marked by seh_try_end() will unwind to parent state via
29706c3fb27SDimitry Andric //     existing SEHUnwindMap[].
29806c3fb27SDimitry Andric //   Side exits can ONLY jump into parent scopes (lower state number).
29906c3fb27SDimitry Andric //   Thus, when a block succeeds various states from its predecessors,
30006c3fb27SDimitry Andric //     the lowest State trumphs others.
30106c3fb27SDimitry Andric //   If some exits flow to unreachable, propagation on those paths terminate,
30206c3fb27SDimitry Andric //     not affecting remaining blocks.
calculateSEHStateForAsynchEH(const BasicBlock * BB,int State,WinEHFuncInfo & EHInfo)30306c3fb27SDimitry Andric void llvm::calculateSEHStateForAsynchEH(const BasicBlock *BB, int State,
30406c3fb27SDimitry Andric                                         WinEHFuncInfo &EHInfo) {
30506c3fb27SDimitry Andric   SmallVector<struct WorkItem *, 8> WorkList;
30606c3fb27SDimitry Andric   struct WorkItem *WI = new WorkItem(BB, State);
30706c3fb27SDimitry Andric   WorkList.push_back(WI);
30806c3fb27SDimitry Andric 
30906c3fb27SDimitry Andric   while (!WorkList.empty()) {
31006c3fb27SDimitry Andric     WI = WorkList.pop_back_val();
31106c3fb27SDimitry Andric     const BasicBlock *BB = WI->Block;
31206c3fb27SDimitry Andric     int State = WI->State;
31306c3fb27SDimitry Andric     delete WI;
31406c3fb27SDimitry Andric     if (EHInfo.BlockToStateMap.count(BB) && EHInfo.BlockToStateMap[BB] <= State)
31506c3fb27SDimitry Andric       continue; // skip blocks already visited by lower State
31606c3fb27SDimitry Andric 
31706c3fb27SDimitry Andric     const llvm::Instruction *I = BB->getFirstNonPHI();
31806c3fb27SDimitry Andric     const llvm::Instruction *TI = BB->getTerminator();
31906c3fb27SDimitry Andric     if (I->isEHPad())
32006c3fb27SDimitry Andric       State = EHInfo.EHPadStateMap[I];
32106c3fb27SDimitry Andric     EHInfo.BlockToStateMap[BB] = State; // Record state
32206c3fb27SDimitry Andric 
32306c3fb27SDimitry Andric     if (isa<CatchPadInst>(I) && isa<CatchReturnInst>(TI)) {
32406c3fb27SDimitry Andric       const Constant *FilterOrNull = cast<Constant>(
32506c3fb27SDimitry Andric           cast<CatchPadInst>(I)->getArgOperand(0)->stripPointerCasts());
32606c3fb27SDimitry Andric       const Function *Filter = dyn_cast<Function>(FilterOrNull);
3275f757f3fSDimitry Andric       if (!Filter || !Filter->getName().starts_with("__IsLocalUnwind"))
32806c3fb27SDimitry Andric         State = EHInfo.SEHUnwindMap[State].ToState; // Retrive next State
32906c3fb27SDimitry Andric     } else if ((isa<CleanupReturnInst>(TI) || isa<CatchReturnInst>(TI)) &&
33006c3fb27SDimitry Andric                State > 0) {
33106c3fb27SDimitry Andric       // Retrive the new State.
33206c3fb27SDimitry Andric       State = EHInfo.SEHUnwindMap[State].ToState; // Retrive next State
33306c3fb27SDimitry Andric     } else if (isa<InvokeInst>(TI)) {
33406c3fb27SDimitry Andric       auto *Call = cast<CallBase>(TI);
33506c3fb27SDimitry Andric       const Function *Fn = Call->getCalledFunction();
33606c3fb27SDimitry Andric       if (Fn && Fn->isIntrinsic() &&
33706c3fb27SDimitry Andric           Fn->getIntrinsicID() == Intrinsic::seh_try_begin)
33806c3fb27SDimitry Andric         // Retrive the new State from seh_try_begin
33906c3fb27SDimitry Andric         State = EHInfo.InvokeStateMap[cast<InvokeInst>(TI)];
34006c3fb27SDimitry Andric       else if (Fn && Fn->isIntrinsic() &&
34106c3fb27SDimitry Andric                Fn->getIntrinsicID() == Intrinsic::seh_try_end)
34206c3fb27SDimitry Andric         // end of current state, retrive new state from UnwindMap
34306c3fb27SDimitry Andric         State = EHInfo.SEHUnwindMap[State].ToState;
34406c3fb27SDimitry Andric     }
34506c3fb27SDimitry Andric     // Continue push successors into worklist
34606c3fb27SDimitry Andric     for (auto *SuccBB : successors(BB)) {
34706c3fb27SDimitry Andric       WI = new WorkItem(SuccBB, State);
34806c3fb27SDimitry Andric       WorkList.push_back(WI);
34906c3fb27SDimitry Andric     }
35006c3fb27SDimitry Andric   }
35106c3fb27SDimitry Andric }
35206c3fb27SDimitry Andric 
3530b57cec5SDimitry Andric // Given BB which ends in an unwind edge, return the EHPad that this BB belongs
3540b57cec5SDimitry Andric // to. If the unwind edge came from an invoke, return null.
getEHPadFromPredecessor(const BasicBlock * BB,Value * ParentPad)3550b57cec5SDimitry Andric static const BasicBlock *getEHPadFromPredecessor(const BasicBlock *BB,
3560b57cec5SDimitry Andric                                                  Value *ParentPad) {
3570b57cec5SDimitry Andric   const Instruction *TI = BB->getTerminator();
3580b57cec5SDimitry Andric   if (isa<InvokeInst>(TI))
3590b57cec5SDimitry Andric     return nullptr;
3600b57cec5SDimitry Andric   if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(TI)) {
3610b57cec5SDimitry Andric     if (CatchSwitch->getParentPad() != ParentPad)
3620b57cec5SDimitry Andric       return nullptr;
3630b57cec5SDimitry Andric     return BB;
3640b57cec5SDimitry Andric   }
3650b57cec5SDimitry Andric   assert(!TI->isEHPad() && "unexpected EHPad!");
3660b57cec5SDimitry Andric   auto *CleanupPad = cast<CleanupReturnInst>(TI)->getCleanupPad();
3670b57cec5SDimitry Andric   if (CleanupPad->getParentPad() != ParentPad)
3680b57cec5SDimitry Andric     return nullptr;
3690b57cec5SDimitry Andric   return CleanupPad->getParent();
3700b57cec5SDimitry Andric }
3710b57cec5SDimitry Andric 
3725ffd83dbSDimitry Andric // Starting from a EHPad, Backward walk through control-flow graph
3735ffd83dbSDimitry Andric // to produce two primary outputs:
3745ffd83dbSDimitry Andric //      FuncInfo.EHPadStateMap[] and FuncInfo.CxxUnwindMap[]
calculateCXXStateNumbers(WinEHFuncInfo & FuncInfo,const Instruction * FirstNonPHI,int ParentState)3750b57cec5SDimitry Andric static void calculateCXXStateNumbers(WinEHFuncInfo &FuncInfo,
3760b57cec5SDimitry Andric                                      const Instruction *FirstNonPHI,
3770b57cec5SDimitry Andric                                      int ParentState) {
3780b57cec5SDimitry Andric   const BasicBlock *BB = FirstNonPHI->getParent();
3790b57cec5SDimitry Andric   assert(BB->isEHPad() && "not a funclet!");
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric   if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(FirstNonPHI)) {
3820b57cec5SDimitry Andric     assert(FuncInfo.EHPadStateMap.count(CatchSwitch) == 0 &&
3830b57cec5SDimitry Andric            "shouldn't revist catch funclets!");
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric     SmallVector<const CatchPadInst *, 2> Handlers;
3860b57cec5SDimitry Andric     for (const BasicBlock *CatchPadBB : CatchSwitch->handlers()) {
3870b57cec5SDimitry Andric       auto *CatchPad = cast<CatchPadInst>(CatchPadBB->getFirstNonPHI());
3880b57cec5SDimitry Andric       Handlers.push_back(CatchPad);
3890b57cec5SDimitry Andric     }
3900b57cec5SDimitry Andric     int TryLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr);
3910b57cec5SDimitry Andric     FuncInfo.EHPadStateMap[CatchSwitch] = TryLow;
3920b57cec5SDimitry Andric     for (const BasicBlock *PredBlock : predecessors(BB))
3930b57cec5SDimitry Andric       if ((PredBlock = getEHPadFromPredecessor(PredBlock,
3940b57cec5SDimitry Andric                                                CatchSwitch->getParentPad())))
3950b57cec5SDimitry Andric         calculateCXXStateNumbers(FuncInfo, PredBlock->getFirstNonPHI(),
3960b57cec5SDimitry Andric                                  TryLow);
3970b57cec5SDimitry Andric     int CatchLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr);
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric     // catchpads are separate funclets in C++ EH due to the way rethrow works.
4000b57cec5SDimitry Andric     int TryHigh = CatchLow - 1;
4015ffd83dbSDimitry Andric 
4025ffd83dbSDimitry Andric     // MSVC FrameHandler3/4 on x64&Arm64 expect Catch Handlers in $tryMap$
4035ffd83dbSDimitry Andric     //  stored in pre-order (outer first, inner next), not post-order
4045ffd83dbSDimitry Andric     //  Add to map here.  Fix the CatchHigh after children are processed
4055ffd83dbSDimitry Andric     const Module *Mod = BB->getParent()->getParent();
4065ffd83dbSDimitry Andric     bool IsPreOrder = Triple(Mod->getTargetTriple()).isArch64Bit();
4075ffd83dbSDimitry Andric     if (IsPreOrder)
4085ffd83dbSDimitry Andric       addTryBlockMapEntry(FuncInfo, TryLow, TryHigh, CatchLow, Handlers);
4095ffd83dbSDimitry Andric     unsigned TBMEIdx = FuncInfo.TryBlockMap.size() - 1;
4105ffd83dbSDimitry Andric 
4110b57cec5SDimitry Andric     for (const auto *CatchPad : Handlers) {
4120b57cec5SDimitry Andric       FuncInfo.FuncletBaseStateMap[CatchPad] = CatchLow;
41306c3fb27SDimitry Andric       FuncInfo.EHPadStateMap[CatchPad] = CatchLow;
4140b57cec5SDimitry Andric       for (const User *U : CatchPad->users()) {
4150b57cec5SDimitry Andric         const auto *UserI = cast<Instruction>(U);
4160b57cec5SDimitry Andric         if (auto *InnerCatchSwitch = dyn_cast<CatchSwitchInst>(UserI)) {
4170b57cec5SDimitry Andric           BasicBlock *UnwindDest = InnerCatchSwitch->getUnwindDest();
4180b57cec5SDimitry Andric           if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest())
4190b57cec5SDimitry Andric             calculateCXXStateNumbers(FuncInfo, UserI, CatchLow);
4200b57cec5SDimitry Andric         }
4210b57cec5SDimitry Andric         if (auto *InnerCleanupPad = dyn_cast<CleanupPadInst>(UserI)) {
4220b57cec5SDimitry Andric           BasicBlock *UnwindDest = getCleanupRetUnwindDest(InnerCleanupPad);
4230b57cec5SDimitry Andric           // If a nested cleanup pad reports a null unwind destination and the
4240b57cec5SDimitry Andric           // enclosing catch pad doesn't it must be post-dominated by an
4250b57cec5SDimitry Andric           // unreachable instruction.
4260b57cec5SDimitry Andric           if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest())
4270b57cec5SDimitry Andric             calculateCXXStateNumbers(FuncInfo, UserI, CatchLow);
4280b57cec5SDimitry Andric         }
4290b57cec5SDimitry Andric       }
4300b57cec5SDimitry Andric     }
4310b57cec5SDimitry Andric     int CatchHigh = FuncInfo.getLastStateNumber();
4325ffd83dbSDimitry Andric     // Now child Catches are processed, update CatchHigh
4335ffd83dbSDimitry Andric     if (IsPreOrder)
4345ffd83dbSDimitry Andric       FuncInfo.TryBlockMap[TBMEIdx].CatchHigh = CatchHigh;
4355ffd83dbSDimitry Andric     else // PostOrder
4360b57cec5SDimitry Andric       addTryBlockMapEntry(FuncInfo, TryLow, TryHigh, CatchHigh, Handlers);
4375ffd83dbSDimitry Andric 
4380b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "TryLow[" << BB->getName() << "]: " << TryLow << '\n');
4390b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "TryHigh[" << BB->getName() << "]: " << TryHigh
4400b57cec5SDimitry Andric                       << '\n');
4410b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "CatchHigh[" << BB->getName() << "]: " << CatchHigh
4420b57cec5SDimitry Andric                       << '\n');
4430b57cec5SDimitry Andric   } else {
4440b57cec5SDimitry Andric     auto *CleanupPad = cast<CleanupPadInst>(FirstNonPHI);
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric     // It's possible for a cleanup to be visited twice: it might have multiple
4470b57cec5SDimitry Andric     // cleanupret instructions.
4480b57cec5SDimitry Andric     if (FuncInfo.EHPadStateMap.count(CleanupPad))
4490b57cec5SDimitry Andric       return;
4500b57cec5SDimitry Andric 
4510b57cec5SDimitry Andric     int CleanupState = addUnwindMapEntry(FuncInfo, ParentState, BB);
4520b57cec5SDimitry Andric     FuncInfo.EHPadStateMap[CleanupPad] = CleanupState;
4530b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Assigning state #" << CleanupState << " to BB "
4540b57cec5SDimitry Andric                       << BB->getName() << '\n');
4550b57cec5SDimitry Andric     for (const BasicBlock *PredBlock : predecessors(BB)) {
4560b57cec5SDimitry Andric       if ((PredBlock = getEHPadFromPredecessor(PredBlock,
4570b57cec5SDimitry Andric                                                CleanupPad->getParentPad()))) {
4580b57cec5SDimitry Andric         calculateCXXStateNumbers(FuncInfo, PredBlock->getFirstNonPHI(),
4590b57cec5SDimitry Andric                                  CleanupState);
4600b57cec5SDimitry Andric       }
4610b57cec5SDimitry Andric     }
4620b57cec5SDimitry Andric     for (const User *U : CleanupPad->users()) {
4630b57cec5SDimitry Andric       const auto *UserI = cast<Instruction>(U);
4640b57cec5SDimitry Andric       if (UserI->isEHPad())
4650b57cec5SDimitry Andric         report_fatal_error("Cleanup funclets for the MSVC++ personality cannot "
4660b57cec5SDimitry Andric                            "contain exceptional actions");
4670b57cec5SDimitry Andric     }
4680b57cec5SDimitry Andric   }
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric 
addSEHExcept(WinEHFuncInfo & FuncInfo,int ParentState,const Function * Filter,const BasicBlock * Handler)4710b57cec5SDimitry Andric static int addSEHExcept(WinEHFuncInfo &FuncInfo, int ParentState,
4720b57cec5SDimitry Andric                         const Function *Filter, const BasicBlock *Handler) {
4730b57cec5SDimitry Andric   SEHUnwindMapEntry Entry;
4740b57cec5SDimitry Andric   Entry.ToState = ParentState;
4750b57cec5SDimitry Andric   Entry.IsFinally = false;
4760b57cec5SDimitry Andric   Entry.Filter = Filter;
4770b57cec5SDimitry Andric   Entry.Handler = Handler;
4780b57cec5SDimitry Andric   FuncInfo.SEHUnwindMap.push_back(Entry);
4790b57cec5SDimitry Andric   return FuncInfo.SEHUnwindMap.size() - 1;
4800b57cec5SDimitry Andric }
4810b57cec5SDimitry Andric 
addSEHFinally(WinEHFuncInfo & FuncInfo,int ParentState,const BasicBlock * Handler)4820b57cec5SDimitry Andric static int addSEHFinally(WinEHFuncInfo &FuncInfo, int ParentState,
4830b57cec5SDimitry Andric                          const BasicBlock *Handler) {
4840b57cec5SDimitry Andric   SEHUnwindMapEntry Entry;
4850b57cec5SDimitry Andric   Entry.ToState = ParentState;
4860b57cec5SDimitry Andric   Entry.IsFinally = true;
4870b57cec5SDimitry Andric   Entry.Filter = nullptr;
4880b57cec5SDimitry Andric   Entry.Handler = Handler;
4890b57cec5SDimitry Andric   FuncInfo.SEHUnwindMap.push_back(Entry);
4900b57cec5SDimitry Andric   return FuncInfo.SEHUnwindMap.size() - 1;
4910b57cec5SDimitry Andric }
4920b57cec5SDimitry Andric 
4935ffd83dbSDimitry Andric // Starting from a EHPad, Backward walk through control-flow graph
4945ffd83dbSDimitry Andric // to produce two primary outputs:
4955ffd83dbSDimitry Andric //      FuncInfo.EHPadStateMap[] and FuncInfo.SEHUnwindMap[]
calculateSEHStateNumbers(WinEHFuncInfo & FuncInfo,const Instruction * FirstNonPHI,int ParentState)4960b57cec5SDimitry Andric static void calculateSEHStateNumbers(WinEHFuncInfo &FuncInfo,
4970b57cec5SDimitry Andric                                      const Instruction *FirstNonPHI,
4980b57cec5SDimitry Andric                                      int ParentState) {
4990b57cec5SDimitry Andric   const BasicBlock *BB = FirstNonPHI->getParent();
5000b57cec5SDimitry Andric   assert(BB->isEHPad() && "no a funclet!");
5010b57cec5SDimitry Andric 
5020b57cec5SDimitry Andric   if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(FirstNonPHI)) {
5030b57cec5SDimitry Andric     assert(FuncInfo.EHPadStateMap.count(CatchSwitch) == 0 &&
5040b57cec5SDimitry Andric            "shouldn't revist catch funclets!");
5050b57cec5SDimitry Andric 
5060b57cec5SDimitry Andric     // Extract the filter function and the __except basic block and create a
5070b57cec5SDimitry Andric     // state for them.
5080b57cec5SDimitry Andric     assert(CatchSwitch->getNumHandlers() == 1 &&
5090b57cec5SDimitry Andric            "SEH doesn't have multiple handlers per __try");
5100b57cec5SDimitry Andric     const auto *CatchPad =
5110b57cec5SDimitry Andric         cast<CatchPadInst>((*CatchSwitch->handler_begin())->getFirstNonPHI());
5120b57cec5SDimitry Andric     const BasicBlock *CatchPadBB = CatchPad->getParent();
5130b57cec5SDimitry Andric     const Constant *FilterOrNull =
5140b57cec5SDimitry Andric         cast<Constant>(CatchPad->getArgOperand(0)->stripPointerCasts());
5150b57cec5SDimitry Andric     const Function *Filter = dyn_cast<Function>(FilterOrNull);
5160b57cec5SDimitry Andric     assert((Filter || FilterOrNull->isNullValue()) &&
5170b57cec5SDimitry Andric            "unexpected filter value");
5180b57cec5SDimitry Andric     int TryState = addSEHExcept(FuncInfo, ParentState, Filter, CatchPadBB);
5190b57cec5SDimitry Andric 
5200b57cec5SDimitry Andric     // Everything in the __try block uses TryState as its parent state.
5210b57cec5SDimitry Andric     FuncInfo.EHPadStateMap[CatchSwitch] = TryState;
52206c3fb27SDimitry Andric     FuncInfo.EHPadStateMap[CatchPad] = TryState;
5230b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Assigning state #" << TryState << " to BB "
5240b57cec5SDimitry Andric                       << CatchPadBB->getName() << '\n');
5250b57cec5SDimitry Andric     for (const BasicBlock *PredBlock : predecessors(BB))
5260b57cec5SDimitry Andric       if ((PredBlock = getEHPadFromPredecessor(PredBlock,
5270b57cec5SDimitry Andric                                                CatchSwitch->getParentPad())))
5280b57cec5SDimitry Andric         calculateSEHStateNumbers(FuncInfo, PredBlock->getFirstNonPHI(),
5290b57cec5SDimitry Andric                                  TryState);
5300b57cec5SDimitry Andric 
5310b57cec5SDimitry Andric     // Everything in the __except block unwinds to ParentState, just like code
5320b57cec5SDimitry Andric     // outside the __try.
5330b57cec5SDimitry Andric     for (const User *U : CatchPad->users()) {
5340b57cec5SDimitry Andric       const auto *UserI = cast<Instruction>(U);
5350b57cec5SDimitry Andric       if (auto *InnerCatchSwitch = dyn_cast<CatchSwitchInst>(UserI)) {
5360b57cec5SDimitry Andric         BasicBlock *UnwindDest = InnerCatchSwitch->getUnwindDest();
5370b57cec5SDimitry Andric         if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest())
5380b57cec5SDimitry Andric           calculateSEHStateNumbers(FuncInfo, UserI, ParentState);
5390b57cec5SDimitry Andric       }
5400b57cec5SDimitry Andric       if (auto *InnerCleanupPad = dyn_cast<CleanupPadInst>(UserI)) {
5410b57cec5SDimitry Andric         BasicBlock *UnwindDest = getCleanupRetUnwindDest(InnerCleanupPad);
5420b57cec5SDimitry Andric         // If a nested cleanup pad reports a null unwind destination and the
5430b57cec5SDimitry Andric         // enclosing catch pad doesn't it must be post-dominated by an
5440b57cec5SDimitry Andric         // unreachable instruction.
5450b57cec5SDimitry Andric         if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest())
5460b57cec5SDimitry Andric           calculateSEHStateNumbers(FuncInfo, UserI, ParentState);
5470b57cec5SDimitry Andric       }
5480b57cec5SDimitry Andric     }
5490b57cec5SDimitry Andric   } else {
5500b57cec5SDimitry Andric     auto *CleanupPad = cast<CleanupPadInst>(FirstNonPHI);
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric     // It's possible for a cleanup to be visited twice: it might have multiple
5530b57cec5SDimitry Andric     // cleanupret instructions.
5540b57cec5SDimitry Andric     if (FuncInfo.EHPadStateMap.count(CleanupPad))
5550b57cec5SDimitry Andric       return;
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric     int CleanupState = addSEHFinally(FuncInfo, ParentState, BB);
5580b57cec5SDimitry Andric     FuncInfo.EHPadStateMap[CleanupPad] = CleanupState;
5590b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Assigning state #" << CleanupState << " to BB "
5600b57cec5SDimitry Andric                       << BB->getName() << '\n');
5610b57cec5SDimitry Andric     for (const BasicBlock *PredBlock : predecessors(BB))
5620b57cec5SDimitry Andric       if ((PredBlock =
5630b57cec5SDimitry Andric                getEHPadFromPredecessor(PredBlock, CleanupPad->getParentPad())))
5640b57cec5SDimitry Andric         calculateSEHStateNumbers(FuncInfo, PredBlock->getFirstNonPHI(),
5650b57cec5SDimitry Andric                                  CleanupState);
5660b57cec5SDimitry Andric     for (const User *U : CleanupPad->users()) {
5670b57cec5SDimitry Andric       const auto *UserI = cast<Instruction>(U);
5680b57cec5SDimitry Andric       if (UserI->isEHPad())
5690b57cec5SDimitry Andric         report_fatal_error("Cleanup funclets for the SEH personality cannot "
5700b57cec5SDimitry Andric                            "contain exceptional actions");
5710b57cec5SDimitry Andric     }
5720b57cec5SDimitry Andric   }
5730b57cec5SDimitry Andric }
5740b57cec5SDimitry Andric 
isTopLevelPadForMSVC(const Instruction * EHPad)5750b57cec5SDimitry Andric static bool isTopLevelPadForMSVC(const Instruction *EHPad) {
5760b57cec5SDimitry Andric   if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(EHPad))
5770b57cec5SDimitry Andric     return isa<ConstantTokenNone>(CatchSwitch->getParentPad()) &&
5780b57cec5SDimitry Andric            CatchSwitch->unwindsToCaller();
5790b57cec5SDimitry Andric   if (auto *CleanupPad = dyn_cast<CleanupPadInst>(EHPad))
5800b57cec5SDimitry Andric     return isa<ConstantTokenNone>(CleanupPad->getParentPad()) &&
5810b57cec5SDimitry Andric            getCleanupRetUnwindDest(CleanupPad) == nullptr;
5820b57cec5SDimitry Andric   if (isa<CatchPadInst>(EHPad))
5830b57cec5SDimitry Andric     return false;
5840b57cec5SDimitry Andric   llvm_unreachable("unexpected EHPad!");
5850b57cec5SDimitry Andric }
5860b57cec5SDimitry Andric 
calculateSEHStateNumbers(const Function * Fn,WinEHFuncInfo & FuncInfo)5870b57cec5SDimitry Andric void llvm::calculateSEHStateNumbers(const Function *Fn,
5880b57cec5SDimitry Andric                                     WinEHFuncInfo &FuncInfo) {
5890b57cec5SDimitry Andric   // Don't compute state numbers twice.
5900b57cec5SDimitry Andric   if (!FuncInfo.SEHUnwindMap.empty())
5910b57cec5SDimitry Andric     return;
5920b57cec5SDimitry Andric 
5930b57cec5SDimitry Andric   for (const BasicBlock &BB : *Fn) {
5940b57cec5SDimitry Andric     if (!BB.isEHPad())
5950b57cec5SDimitry Andric       continue;
5960b57cec5SDimitry Andric     const Instruction *FirstNonPHI = BB.getFirstNonPHI();
5970b57cec5SDimitry Andric     if (!isTopLevelPadForMSVC(FirstNonPHI))
5980b57cec5SDimitry Andric       continue;
5990b57cec5SDimitry Andric     ::calculateSEHStateNumbers(FuncInfo, FirstNonPHI, -1);
6000b57cec5SDimitry Andric   }
6010b57cec5SDimitry Andric 
6020b57cec5SDimitry Andric   calculateStateNumbersForInvokes(Fn, FuncInfo);
60306c3fb27SDimitry Andric 
60406c3fb27SDimitry Andric   bool IsEHa = Fn->getParent()->getModuleFlag("eh-asynch");
60506c3fb27SDimitry Andric   if (IsEHa) {
60606c3fb27SDimitry Andric     const BasicBlock *EntryBB = &(Fn->getEntryBlock());
60706c3fb27SDimitry Andric     calculateSEHStateForAsynchEH(EntryBB, -1, FuncInfo);
60806c3fb27SDimitry Andric   }
6090b57cec5SDimitry Andric }
6100b57cec5SDimitry Andric 
calculateWinCXXEHStateNumbers(const Function * Fn,WinEHFuncInfo & FuncInfo)6110b57cec5SDimitry Andric void llvm::calculateWinCXXEHStateNumbers(const Function *Fn,
6120b57cec5SDimitry Andric                                          WinEHFuncInfo &FuncInfo) {
6130b57cec5SDimitry Andric   // Return if it's already been done.
6140b57cec5SDimitry Andric   if (!FuncInfo.EHPadStateMap.empty())
6150b57cec5SDimitry Andric     return;
6160b57cec5SDimitry Andric 
6170b57cec5SDimitry Andric   for (const BasicBlock &BB : *Fn) {
6180b57cec5SDimitry Andric     if (!BB.isEHPad())
6190b57cec5SDimitry Andric       continue;
6200b57cec5SDimitry Andric     const Instruction *FirstNonPHI = BB.getFirstNonPHI();
6210b57cec5SDimitry Andric     if (!isTopLevelPadForMSVC(FirstNonPHI))
6220b57cec5SDimitry Andric       continue;
6230b57cec5SDimitry Andric     calculateCXXStateNumbers(FuncInfo, FirstNonPHI, -1);
6240b57cec5SDimitry Andric   }
6250b57cec5SDimitry Andric 
6260b57cec5SDimitry Andric   calculateStateNumbersForInvokes(Fn, FuncInfo);
62706c3fb27SDimitry Andric 
62806c3fb27SDimitry Andric   bool IsEHa = Fn->getParent()->getModuleFlag("eh-asynch");
62906c3fb27SDimitry Andric   if (IsEHa) {
63006c3fb27SDimitry Andric     const BasicBlock *EntryBB = &(Fn->getEntryBlock());
63106c3fb27SDimitry Andric     calculateCXXStateForAsynchEH(EntryBB, -1, FuncInfo);
63206c3fb27SDimitry Andric   }
6330b57cec5SDimitry Andric }
6340b57cec5SDimitry Andric 
addClrEHHandler(WinEHFuncInfo & FuncInfo,int HandlerParentState,int TryParentState,ClrHandlerType HandlerType,uint32_t TypeToken,const BasicBlock * Handler)6350b57cec5SDimitry Andric static int addClrEHHandler(WinEHFuncInfo &FuncInfo, int HandlerParentState,
6360b57cec5SDimitry Andric                            int TryParentState, ClrHandlerType HandlerType,
6370b57cec5SDimitry Andric                            uint32_t TypeToken, const BasicBlock *Handler) {
6380b57cec5SDimitry Andric   ClrEHUnwindMapEntry Entry;
6390b57cec5SDimitry Andric   Entry.HandlerParentState = HandlerParentState;
6400b57cec5SDimitry Andric   Entry.TryParentState = TryParentState;
6410b57cec5SDimitry Andric   Entry.Handler = Handler;
6420b57cec5SDimitry Andric   Entry.HandlerType = HandlerType;
6430b57cec5SDimitry Andric   Entry.TypeToken = TypeToken;
6440b57cec5SDimitry Andric   FuncInfo.ClrEHUnwindMap.push_back(Entry);
6450b57cec5SDimitry Andric   return FuncInfo.ClrEHUnwindMap.size() - 1;
6460b57cec5SDimitry Andric }
6470b57cec5SDimitry Andric 
calculateClrEHStateNumbers(const Function * Fn,WinEHFuncInfo & FuncInfo)6480b57cec5SDimitry Andric void llvm::calculateClrEHStateNumbers(const Function *Fn,
6490b57cec5SDimitry Andric                                       WinEHFuncInfo &FuncInfo) {
6500b57cec5SDimitry Andric   // Return if it's already been done.
6510b57cec5SDimitry Andric   if (!FuncInfo.EHPadStateMap.empty())
6520b57cec5SDimitry Andric     return;
6530b57cec5SDimitry Andric 
6540b57cec5SDimitry Andric   // This numbering assigns one state number to each catchpad and cleanuppad.
6550b57cec5SDimitry Andric   // It also computes two tree-like relations over states:
6560b57cec5SDimitry Andric   // 1) Each state has a "HandlerParentState", which is the state of the next
6570b57cec5SDimitry Andric   //    outer handler enclosing this state's handler (same as nearest ancestor
6580b57cec5SDimitry Andric   //    per the ParentPad linkage on EH pads, but skipping over catchswitches).
6590b57cec5SDimitry Andric   // 2) Each state has a "TryParentState", which:
6600b57cec5SDimitry Andric   //    a) for a catchpad that's not the last handler on its catchswitch, is
6610b57cec5SDimitry Andric   //       the state of the next catchpad on that catchswitch
6620b57cec5SDimitry Andric   //    b) for all other pads, is the state of the pad whose try region is the
6630b57cec5SDimitry Andric   //       next outer try region enclosing this state's try region.  The "try
6640b57cec5SDimitry Andric   //       regions are not present as such in the IR, but will be inferred
6650b57cec5SDimitry Andric   //       based on the placement of invokes and pads which reach each other
6660b57cec5SDimitry Andric   //       by exceptional exits
6670b57cec5SDimitry Andric   // Catchswitches do not get their own states, but each gets mapped to the
6680b57cec5SDimitry Andric   // state of its first catchpad.
6690b57cec5SDimitry Andric 
6700b57cec5SDimitry Andric   // Step one: walk down from outermost to innermost funclets, assigning each
6710b57cec5SDimitry Andric   // catchpad and cleanuppad a state number.  Add an entry to the
6720b57cec5SDimitry Andric   // ClrEHUnwindMap for each state, recording its HandlerParentState and
6730b57cec5SDimitry Andric   // handler attributes.  Record the TryParentState as well for each catchpad
6740b57cec5SDimitry Andric   // that's not the last on its catchswitch, but initialize all other entries'
6750b57cec5SDimitry Andric   // TryParentStates to a sentinel -1 value that the next pass will update.
6760b57cec5SDimitry Andric 
6770b57cec5SDimitry Andric   // Seed a worklist with pads that have no parent.
6780b57cec5SDimitry Andric   SmallVector<std::pair<const Instruction *, int>, 8> Worklist;
6790b57cec5SDimitry Andric   for (const BasicBlock &BB : *Fn) {
6800b57cec5SDimitry Andric     const Instruction *FirstNonPHI = BB.getFirstNonPHI();
6810b57cec5SDimitry Andric     const Value *ParentPad;
6820b57cec5SDimitry Andric     if (const auto *CPI = dyn_cast<CleanupPadInst>(FirstNonPHI))
6830b57cec5SDimitry Andric       ParentPad = CPI->getParentPad();
6840b57cec5SDimitry Andric     else if (const auto *CSI = dyn_cast<CatchSwitchInst>(FirstNonPHI))
6850b57cec5SDimitry Andric       ParentPad = CSI->getParentPad();
6860b57cec5SDimitry Andric     else
6870b57cec5SDimitry Andric       continue;
6880b57cec5SDimitry Andric     if (isa<ConstantTokenNone>(ParentPad))
6890b57cec5SDimitry Andric       Worklist.emplace_back(FirstNonPHI, -1);
6900b57cec5SDimitry Andric   }
6910b57cec5SDimitry Andric 
6920b57cec5SDimitry Andric   // Use the worklist to visit all pads, from outer to inner.  Record
6930b57cec5SDimitry Andric   // HandlerParentState for all pads.  Record TryParentState only for catchpads
6940b57cec5SDimitry Andric   // that aren't the last on their catchswitch (setting all other entries'
6950b57cec5SDimitry Andric   // TryParentStates to an initial value of -1).  This loop is also responsible
6960b57cec5SDimitry Andric   // for setting the EHPadStateMap entry for all catchpads, cleanuppads, and
6970b57cec5SDimitry Andric   // catchswitches.
6980b57cec5SDimitry Andric   while (!Worklist.empty()) {
6990b57cec5SDimitry Andric     const Instruction *Pad;
7000b57cec5SDimitry Andric     int HandlerParentState;
7010b57cec5SDimitry Andric     std::tie(Pad, HandlerParentState) = Worklist.pop_back_val();
7020b57cec5SDimitry Andric 
7030b57cec5SDimitry Andric     if (const auto *Cleanup = dyn_cast<CleanupPadInst>(Pad)) {
7040b57cec5SDimitry Andric       // Create the entry for this cleanup with the appropriate handler
7050b57cec5SDimitry Andric       // properties.  Finally and fault handlers are distinguished by arity.
7060b57cec5SDimitry Andric       ClrHandlerType HandlerType =
707bdd1243dSDimitry Andric           (Cleanup->arg_size() ? ClrHandlerType::Fault
7080b57cec5SDimitry Andric                                : ClrHandlerType::Finally);
7090b57cec5SDimitry Andric       int CleanupState = addClrEHHandler(FuncInfo, HandlerParentState, -1,
7100b57cec5SDimitry Andric                                          HandlerType, 0, Pad->getParent());
7110b57cec5SDimitry Andric       // Queue any child EH pads on the worklist.
7120b57cec5SDimitry Andric       for (const User *U : Cleanup->users())
7130b57cec5SDimitry Andric         if (const auto *I = dyn_cast<Instruction>(U))
7140b57cec5SDimitry Andric           if (I->isEHPad())
7150b57cec5SDimitry Andric             Worklist.emplace_back(I, CleanupState);
7160b57cec5SDimitry Andric       // Remember this pad's state.
7170b57cec5SDimitry Andric       FuncInfo.EHPadStateMap[Cleanup] = CleanupState;
7180b57cec5SDimitry Andric     } else {
7190b57cec5SDimitry Andric       // Walk the handlers of this catchswitch in reverse order since all but
7200b57cec5SDimitry Andric       // the last need to set the following one as its TryParentState.
7210b57cec5SDimitry Andric       const auto *CatchSwitch = cast<CatchSwitchInst>(Pad);
7220b57cec5SDimitry Andric       int CatchState = -1, FollowerState = -1;
7230b57cec5SDimitry Andric       SmallVector<const BasicBlock *, 4> CatchBlocks(CatchSwitch->handlers());
7240eae32dcSDimitry Andric       for (const BasicBlock *CatchBlock : llvm::reverse(CatchBlocks)) {
7250b57cec5SDimitry Andric         // Create the entry for this catch with the appropriate handler
7260b57cec5SDimitry Andric         // properties.
7270b57cec5SDimitry Andric         const auto *Catch = cast<CatchPadInst>(CatchBlock->getFirstNonPHI());
7280b57cec5SDimitry Andric         uint32_t TypeToken = static_cast<uint32_t>(
7290b57cec5SDimitry Andric             cast<ConstantInt>(Catch->getArgOperand(0))->getZExtValue());
7300b57cec5SDimitry Andric         CatchState =
7310b57cec5SDimitry Andric             addClrEHHandler(FuncInfo, HandlerParentState, FollowerState,
7320b57cec5SDimitry Andric                             ClrHandlerType::Catch, TypeToken, CatchBlock);
7330b57cec5SDimitry Andric         // Queue any child EH pads on the worklist.
7340b57cec5SDimitry Andric         for (const User *U : Catch->users())
7350b57cec5SDimitry Andric           if (const auto *I = dyn_cast<Instruction>(U))
7360b57cec5SDimitry Andric             if (I->isEHPad())
7370b57cec5SDimitry Andric               Worklist.emplace_back(I, CatchState);
7380b57cec5SDimitry Andric         // Remember this catch's state.
7390b57cec5SDimitry Andric         FuncInfo.EHPadStateMap[Catch] = CatchState;
7400eae32dcSDimitry Andric         FollowerState = CatchState;
7410b57cec5SDimitry Andric       }
7420b57cec5SDimitry Andric       // Associate the catchswitch with the state of its first catch.
7430b57cec5SDimitry Andric       assert(CatchSwitch->getNumHandlers());
7440b57cec5SDimitry Andric       FuncInfo.EHPadStateMap[CatchSwitch] = CatchState;
7450b57cec5SDimitry Andric     }
7460b57cec5SDimitry Andric   }
7470b57cec5SDimitry Andric 
7480b57cec5SDimitry Andric   // Step two: record the TryParentState of each state.  For cleanuppads that
7490b57cec5SDimitry Andric   // don't have cleanuprets, we may need to infer this from their child pads,
7500b57cec5SDimitry Andric   // so visit pads in descendant-most to ancestor-most order.
7510eae32dcSDimitry Andric   for (ClrEHUnwindMapEntry &Entry : llvm::reverse(FuncInfo.ClrEHUnwindMap)) {
7520b57cec5SDimitry Andric     const Instruction *Pad =
75306c3fb27SDimitry Andric         cast<const BasicBlock *>(Entry.Handler)->getFirstNonPHI();
7540b57cec5SDimitry Andric     // For most pads, the TryParentState is the state associated with the
7550b57cec5SDimitry Andric     // unwind dest of exceptional exits from it.
7560b57cec5SDimitry Andric     const BasicBlock *UnwindDest;
7570b57cec5SDimitry Andric     if (const auto *Catch = dyn_cast<CatchPadInst>(Pad)) {
7580b57cec5SDimitry Andric       // If a catch is not the last in its catchswitch, its TryParentState is
7590b57cec5SDimitry Andric       // the state associated with the next catch in the switch, even though
7600b57cec5SDimitry Andric       // that's not the unwind dest of exceptions escaping the catch.  Those
7610b57cec5SDimitry Andric       // cases were already assigned a TryParentState in the first pass, so
7620b57cec5SDimitry Andric       // skip them.
7630eae32dcSDimitry Andric       if (Entry.TryParentState != -1)
7640b57cec5SDimitry Andric         continue;
7650b57cec5SDimitry Andric       // Otherwise, get the unwind dest from the catchswitch.
7660b57cec5SDimitry Andric       UnwindDest = Catch->getCatchSwitch()->getUnwindDest();
7670b57cec5SDimitry Andric     } else {
7680b57cec5SDimitry Andric       const auto *Cleanup = cast<CleanupPadInst>(Pad);
7690b57cec5SDimitry Andric       UnwindDest = nullptr;
7700b57cec5SDimitry Andric       for (const User *U : Cleanup->users()) {
7710b57cec5SDimitry Andric         if (auto *CleanupRet = dyn_cast<CleanupReturnInst>(U)) {
7720b57cec5SDimitry Andric           // Common and unambiguous case -- cleanupret indicates cleanup's
7730b57cec5SDimitry Andric           // unwind dest.
7740b57cec5SDimitry Andric           UnwindDest = CleanupRet->getUnwindDest();
7750b57cec5SDimitry Andric           break;
7760b57cec5SDimitry Andric         }
7770b57cec5SDimitry Andric 
7780b57cec5SDimitry Andric         // Get an unwind dest for the user
7790b57cec5SDimitry Andric         const BasicBlock *UserUnwindDest = nullptr;
7800b57cec5SDimitry Andric         if (auto *Invoke = dyn_cast<InvokeInst>(U)) {
7810b57cec5SDimitry Andric           UserUnwindDest = Invoke->getUnwindDest();
7820b57cec5SDimitry Andric         } else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(U)) {
7830b57cec5SDimitry Andric           UserUnwindDest = CatchSwitch->getUnwindDest();
7840b57cec5SDimitry Andric         } else if (auto *ChildCleanup = dyn_cast<CleanupPadInst>(U)) {
7850b57cec5SDimitry Andric           int UserState = FuncInfo.EHPadStateMap[ChildCleanup];
7860b57cec5SDimitry Andric           int UserUnwindState =
7870b57cec5SDimitry Andric               FuncInfo.ClrEHUnwindMap[UserState].TryParentState;
7880b57cec5SDimitry Andric           if (UserUnwindState != -1)
78906c3fb27SDimitry Andric             UserUnwindDest = cast<const BasicBlock *>(
79006c3fb27SDimitry Andric                 FuncInfo.ClrEHUnwindMap[UserUnwindState].Handler);
7910b57cec5SDimitry Andric         }
7920b57cec5SDimitry Andric 
7930b57cec5SDimitry Andric         // Not having an unwind dest for this user might indicate that it
7940b57cec5SDimitry Andric         // doesn't unwind, so can't be taken as proof that the cleanup itself
7950b57cec5SDimitry Andric         // may unwind to caller (see e.g. SimplifyUnreachable and
7960b57cec5SDimitry Andric         // RemoveUnwindEdge).
7970b57cec5SDimitry Andric         if (!UserUnwindDest)
7980b57cec5SDimitry Andric           continue;
7990b57cec5SDimitry Andric 
8000b57cec5SDimitry Andric         // Now we have an unwind dest for the user, but we need to see if it
8010b57cec5SDimitry Andric         // unwinds all the way out of the cleanup or if it stays within it.
8020b57cec5SDimitry Andric         const Instruction *UserUnwindPad = UserUnwindDest->getFirstNonPHI();
8030b57cec5SDimitry Andric         const Value *UserUnwindParent;
8040b57cec5SDimitry Andric         if (auto *CSI = dyn_cast<CatchSwitchInst>(UserUnwindPad))
8050b57cec5SDimitry Andric           UserUnwindParent = CSI->getParentPad();
8060b57cec5SDimitry Andric         else
8070b57cec5SDimitry Andric           UserUnwindParent =
8080b57cec5SDimitry Andric               cast<CleanupPadInst>(UserUnwindPad)->getParentPad();
8090b57cec5SDimitry Andric 
8100b57cec5SDimitry Andric         // The unwind stays within the cleanup iff it targets a child of the
8110b57cec5SDimitry Andric         // cleanup.
8120b57cec5SDimitry Andric         if (UserUnwindParent == Cleanup)
8130b57cec5SDimitry Andric           continue;
8140b57cec5SDimitry Andric 
8150b57cec5SDimitry Andric         // This unwind exits the cleanup, so its dest is the cleanup's dest.
8160b57cec5SDimitry Andric         UnwindDest = UserUnwindDest;
8170b57cec5SDimitry Andric         break;
8180b57cec5SDimitry Andric       }
8190b57cec5SDimitry Andric     }
8200b57cec5SDimitry Andric 
8210b57cec5SDimitry Andric     // Record the state of the unwind dest as the TryParentState.
8220b57cec5SDimitry Andric     int UnwindDestState;
8230b57cec5SDimitry Andric 
8240b57cec5SDimitry Andric     // If UnwindDest is null at this point, either the pad in question can
8250b57cec5SDimitry Andric     // be exited by unwind to caller, or it cannot be exited by unwind.  In
8260b57cec5SDimitry Andric     // either case, reporting such cases as unwinding to caller is correct.
8270b57cec5SDimitry Andric     // This can lead to EH tables that "look strange" -- if this pad's is in
8280b57cec5SDimitry Andric     // a parent funclet which has other children that do unwind to an enclosing
8290b57cec5SDimitry Andric     // pad, the try region for this pad will be missing the "duplicate" EH
8300b57cec5SDimitry Andric     // clause entries that you'd expect to see covering the whole parent.  That
8310b57cec5SDimitry Andric     // should be benign, since the unwind never actually happens.  If it were
8320b57cec5SDimitry Andric     // an issue, we could add a subsequent pass that pushes unwind dests down
8330b57cec5SDimitry Andric     // from parents that have them to children that appear to unwind to caller.
8340b57cec5SDimitry Andric     if (!UnwindDest) {
8350b57cec5SDimitry Andric       UnwindDestState = -1;
8360b57cec5SDimitry Andric     } else {
8370b57cec5SDimitry Andric       UnwindDestState = FuncInfo.EHPadStateMap[UnwindDest->getFirstNonPHI()];
8380b57cec5SDimitry Andric     }
8390b57cec5SDimitry Andric 
8400eae32dcSDimitry Andric     Entry.TryParentState = UnwindDestState;
8410b57cec5SDimitry Andric   }
8420b57cec5SDimitry Andric 
8430b57cec5SDimitry Andric   // Step three: transfer information from pads to invokes.
8440b57cec5SDimitry Andric   calculateStateNumbersForInvokes(Fn, FuncInfo);
8450b57cec5SDimitry Andric }
8460b57cec5SDimitry Andric 
colorFunclets(Function & F)8475f757f3fSDimitry Andric void WinEHPrepareImpl::colorFunclets(Function &F) {
8480b57cec5SDimitry Andric   BlockColors = colorEHFunclets(F);
8490b57cec5SDimitry Andric 
8500b57cec5SDimitry Andric   // Invert the map from BB to colors to color to BBs.
8510b57cec5SDimitry Andric   for (BasicBlock &BB : F) {
8520b57cec5SDimitry Andric     ColorVector &Colors = BlockColors[&BB];
8530b57cec5SDimitry Andric     for (BasicBlock *Color : Colors)
8540b57cec5SDimitry Andric       FuncletBlocks[Color].push_back(&BB);
8550b57cec5SDimitry Andric   }
8560b57cec5SDimitry Andric }
8570b57cec5SDimitry Andric 
demotePHIsOnFunclets(Function & F,bool DemoteCatchSwitchPHIOnly)8585f757f3fSDimitry Andric void WinEHPrepareImpl::demotePHIsOnFunclets(Function &F,
8590b57cec5SDimitry Andric                                             bool DemoteCatchSwitchPHIOnly) {
8600b57cec5SDimitry Andric   // Strip PHI nodes off of EH pads.
8610b57cec5SDimitry Andric   SmallVector<PHINode *, 16> PHINodes;
862fe6060f1SDimitry Andric   for (BasicBlock &BB : make_early_inc_range(F)) {
863fe6060f1SDimitry Andric     if (!BB.isEHPad())
8640b57cec5SDimitry Andric       continue;
865fe6060f1SDimitry Andric     if (DemoteCatchSwitchPHIOnly && !isa<CatchSwitchInst>(BB.getFirstNonPHI()))
8660b57cec5SDimitry Andric       continue;
8670b57cec5SDimitry Andric 
868fe6060f1SDimitry Andric     for (Instruction &I : make_early_inc_range(BB)) {
869fe6060f1SDimitry Andric       auto *PN = dyn_cast<PHINode>(&I);
8700b57cec5SDimitry Andric       // Stop at the first non-PHI.
8710b57cec5SDimitry Andric       if (!PN)
8720b57cec5SDimitry Andric         break;
8730b57cec5SDimitry Andric 
8740b57cec5SDimitry Andric       AllocaInst *SpillSlot = insertPHILoads(PN, F);
8750b57cec5SDimitry Andric       if (SpillSlot)
8760b57cec5SDimitry Andric         insertPHIStores(PN, SpillSlot);
8770b57cec5SDimitry Andric 
8780b57cec5SDimitry Andric       PHINodes.push_back(PN);
8790b57cec5SDimitry Andric     }
8800b57cec5SDimitry Andric   }
8810b57cec5SDimitry Andric 
8820b57cec5SDimitry Andric   for (auto *PN : PHINodes) {
8830b57cec5SDimitry Andric     // There may be lingering uses on other EH PHIs being removed
884bdd1243dSDimitry Andric     PN->replaceAllUsesWith(PoisonValue::get(PN->getType()));
8850b57cec5SDimitry Andric     PN->eraseFromParent();
8860b57cec5SDimitry Andric   }
8870b57cec5SDimitry Andric }
8880b57cec5SDimitry Andric 
cloneCommonBlocks(Function & F)8895f757f3fSDimitry Andric void WinEHPrepareImpl::cloneCommonBlocks(Function &F) {
8900b57cec5SDimitry Andric   // We need to clone all blocks which belong to multiple funclets.  Values are
8910b57cec5SDimitry Andric   // remapped throughout the funclet to propagate both the new instructions
8920b57cec5SDimitry Andric   // *and* the new basic blocks themselves.
8930b57cec5SDimitry Andric   for (auto &Funclets : FuncletBlocks) {
8940b57cec5SDimitry Andric     BasicBlock *FuncletPadBB = Funclets.first;
8950b57cec5SDimitry Andric     std::vector<BasicBlock *> &BlocksInFunclet = Funclets.second;
8960b57cec5SDimitry Andric     Value *FuncletToken;
8970b57cec5SDimitry Andric     if (FuncletPadBB == &F.getEntryBlock())
8980b57cec5SDimitry Andric       FuncletToken = ConstantTokenNone::get(F.getContext());
8990b57cec5SDimitry Andric     else
9000b57cec5SDimitry Andric       FuncletToken = FuncletPadBB->getFirstNonPHI();
9010b57cec5SDimitry Andric 
9020b57cec5SDimitry Andric     std::vector<std::pair<BasicBlock *, BasicBlock *>> Orig2Clone;
9030b57cec5SDimitry Andric     ValueToValueMapTy VMap;
9040b57cec5SDimitry Andric     for (BasicBlock *BB : BlocksInFunclet) {
9050b57cec5SDimitry Andric       ColorVector &ColorsForBB = BlockColors[BB];
9060b57cec5SDimitry Andric       // We don't need to do anything if the block is monochromatic.
9070b57cec5SDimitry Andric       size_t NumColorsForBB = ColorsForBB.size();
9080b57cec5SDimitry Andric       if (NumColorsForBB == 1)
9090b57cec5SDimitry Andric         continue;
9100b57cec5SDimitry Andric 
9115f757f3fSDimitry Andric       DEBUG_WITH_TYPE("win-eh-prepare-coloring",
9120b57cec5SDimitry Andric                       dbgs() << "  Cloning block \'" << BB->getName()
9130b57cec5SDimitry Andric                              << "\' for funclet \'" << FuncletPadBB->getName()
9140b57cec5SDimitry Andric                              << "\'.\n");
9150b57cec5SDimitry Andric 
9160b57cec5SDimitry Andric       // Create a new basic block and copy instructions into it!
9170b57cec5SDimitry Andric       BasicBlock *CBB =
9180b57cec5SDimitry Andric           CloneBasicBlock(BB, VMap, Twine(".for.", FuncletPadBB->getName()));
9190b57cec5SDimitry Andric       // Insert the clone immediately after the original to ensure determinism
9200b57cec5SDimitry Andric       // and to keep the same relative ordering of any funclet's blocks.
9210b57cec5SDimitry Andric       CBB->insertInto(&F, BB->getNextNode());
9220b57cec5SDimitry Andric 
9230b57cec5SDimitry Andric       // Add basic block mapping.
9240b57cec5SDimitry Andric       VMap[BB] = CBB;
9250b57cec5SDimitry Andric 
9260b57cec5SDimitry Andric       // Record delta operations that we need to perform to our color mappings.
9270b57cec5SDimitry Andric       Orig2Clone.emplace_back(BB, CBB);
9280b57cec5SDimitry Andric     }
9290b57cec5SDimitry Andric 
9300b57cec5SDimitry Andric     // If nothing was cloned, we're done cloning in this funclet.
9310b57cec5SDimitry Andric     if (Orig2Clone.empty())
9320b57cec5SDimitry Andric       continue;
9330b57cec5SDimitry Andric 
9340b57cec5SDimitry Andric     // Update our color mappings to reflect that one block has lost a color and
9350b57cec5SDimitry Andric     // another has gained a color.
9360b57cec5SDimitry Andric     for (auto &BBMapping : Orig2Clone) {
9370b57cec5SDimitry Andric       BasicBlock *OldBlock = BBMapping.first;
9380b57cec5SDimitry Andric       BasicBlock *NewBlock = BBMapping.second;
9390b57cec5SDimitry Andric 
9400b57cec5SDimitry Andric       BlocksInFunclet.push_back(NewBlock);
9410b57cec5SDimitry Andric       ColorVector &NewColors = BlockColors[NewBlock];
9420b57cec5SDimitry Andric       assert(NewColors.empty() && "A new block should only have one color!");
9430b57cec5SDimitry Andric       NewColors.push_back(FuncletPadBB);
9440b57cec5SDimitry Andric 
9455f757f3fSDimitry Andric       DEBUG_WITH_TYPE("win-eh-prepare-coloring",
9460b57cec5SDimitry Andric                       dbgs() << "  Assigned color \'" << FuncletPadBB->getName()
9470b57cec5SDimitry Andric                              << "\' to block \'" << NewBlock->getName()
9480b57cec5SDimitry Andric                              << "\'.\n");
9490b57cec5SDimitry Andric 
9505f757f3fSDimitry Andric       llvm::erase(BlocksInFunclet, OldBlock);
9510b57cec5SDimitry Andric       ColorVector &OldColors = BlockColors[OldBlock];
9525f757f3fSDimitry Andric       llvm::erase(OldColors, FuncletPadBB);
9530b57cec5SDimitry Andric 
9545f757f3fSDimitry Andric       DEBUG_WITH_TYPE("win-eh-prepare-coloring",
9550b57cec5SDimitry Andric                       dbgs() << "  Removed color \'" << FuncletPadBB->getName()
9560b57cec5SDimitry Andric                              << "\' from block \'" << OldBlock->getName()
9570b57cec5SDimitry Andric                              << "\'.\n");
9580b57cec5SDimitry Andric     }
9590b57cec5SDimitry Andric 
9600b57cec5SDimitry Andric     // Loop over all of the instructions in this funclet, fixing up operand
9610b57cec5SDimitry Andric     // references as we go.  This uses VMap to do all the hard work.
9620b57cec5SDimitry Andric     for (BasicBlock *BB : BlocksInFunclet)
9630b57cec5SDimitry Andric       // Loop over all instructions, fixing each one as we find it...
9640b57cec5SDimitry Andric       for (Instruction &I : *BB)
9650b57cec5SDimitry Andric         RemapInstruction(&I, VMap,
9660b57cec5SDimitry Andric                          RF_IgnoreMissingLocals | RF_NoModuleLevelChanges);
9670b57cec5SDimitry Andric 
9680b57cec5SDimitry Andric     // Catchrets targeting cloned blocks need to be updated separately from
9690b57cec5SDimitry Andric     // the loop above because they are not in the current funclet.
9700b57cec5SDimitry Andric     SmallVector<CatchReturnInst *, 2> FixupCatchrets;
9710b57cec5SDimitry Andric     for (auto &BBMapping : Orig2Clone) {
9720b57cec5SDimitry Andric       BasicBlock *OldBlock = BBMapping.first;
9730b57cec5SDimitry Andric       BasicBlock *NewBlock = BBMapping.second;
9740b57cec5SDimitry Andric 
9750b57cec5SDimitry Andric       FixupCatchrets.clear();
9760b57cec5SDimitry Andric       for (BasicBlock *Pred : predecessors(OldBlock))
9770b57cec5SDimitry Andric         if (auto *CatchRet = dyn_cast<CatchReturnInst>(Pred->getTerminator()))
9780b57cec5SDimitry Andric           if (CatchRet->getCatchSwitchParentPad() == FuncletToken)
9790b57cec5SDimitry Andric             FixupCatchrets.push_back(CatchRet);
9800b57cec5SDimitry Andric 
9810b57cec5SDimitry Andric       for (CatchReturnInst *CatchRet : FixupCatchrets)
9820b57cec5SDimitry Andric         CatchRet->setSuccessor(NewBlock);
9830b57cec5SDimitry Andric     }
9840b57cec5SDimitry Andric 
9850b57cec5SDimitry Andric     auto UpdatePHIOnClonedBlock = [&](PHINode *PN, bool IsForOldBlock) {
9860b57cec5SDimitry Andric       unsigned NumPreds = PN->getNumIncomingValues();
9870b57cec5SDimitry Andric       for (unsigned PredIdx = 0, PredEnd = NumPreds; PredIdx != PredEnd;
9880b57cec5SDimitry Andric            ++PredIdx) {
9890b57cec5SDimitry Andric         BasicBlock *IncomingBlock = PN->getIncomingBlock(PredIdx);
9900b57cec5SDimitry Andric         bool EdgeTargetsFunclet;
9910b57cec5SDimitry Andric         if (auto *CRI =
9920b57cec5SDimitry Andric                 dyn_cast<CatchReturnInst>(IncomingBlock->getTerminator())) {
9930b57cec5SDimitry Andric           EdgeTargetsFunclet = (CRI->getCatchSwitchParentPad() == FuncletToken);
9940b57cec5SDimitry Andric         } else {
9950b57cec5SDimitry Andric           ColorVector &IncomingColors = BlockColors[IncomingBlock];
9960b57cec5SDimitry Andric           assert(!IncomingColors.empty() && "Block not colored!");
9970b57cec5SDimitry Andric           assert((IncomingColors.size() == 1 ||
998bdd1243dSDimitry Andric                   !llvm::is_contained(IncomingColors, FuncletPadBB)) &&
9990b57cec5SDimitry Andric                  "Cloning should leave this funclet's blocks monochromatic");
10000b57cec5SDimitry Andric           EdgeTargetsFunclet = (IncomingColors.front() == FuncletPadBB);
10010b57cec5SDimitry Andric         }
10020b57cec5SDimitry Andric         if (IsForOldBlock != EdgeTargetsFunclet)
10030b57cec5SDimitry Andric           continue;
10040b57cec5SDimitry Andric         PN->removeIncomingValue(IncomingBlock, /*DeletePHIIfEmpty=*/false);
10050b57cec5SDimitry Andric         // Revisit the next entry.
10060b57cec5SDimitry Andric         --PredIdx;
10070b57cec5SDimitry Andric         --PredEnd;
10080b57cec5SDimitry Andric       }
10090b57cec5SDimitry Andric     };
10100b57cec5SDimitry Andric 
10110b57cec5SDimitry Andric     for (auto &BBMapping : Orig2Clone) {
10120b57cec5SDimitry Andric       BasicBlock *OldBlock = BBMapping.first;
10130b57cec5SDimitry Andric       BasicBlock *NewBlock = BBMapping.second;
10140b57cec5SDimitry Andric       for (PHINode &OldPN : OldBlock->phis()) {
10150b57cec5SDimitry Andric         UpdatePHIOnClonedBlock(&OldPN, /*IsForOldBlock=*/true);
10160b57cec5SDimitry Andric       }
10170b57cec5SDimitry Andric       for (PHINode &NewPN : NewBlock->phis()) {
10180b57cec5SDimitry Andric         UpdatePHIOnClonedBlock(&NewPN, /*IsForOldBlock=*/false);
10190b57cec5SDimitry Andric       }
10200b57cec5SDimitry Andric     }
10210b57cec5SDimitry Andric 
10220b57cec5SDimitry Andric     // Check to see if SuccBB has PHI nodes. If so, we need to add entries to
10230b57cec5SDimitry Andric     // the PHI nodes for NewBB now.
10240b57cec5SDimitry Andric     for (auto &BBMapping : Orig2Clone) {
10250b57cec5SDimitry Andric       BasicBlock *OldBlock = BBMapping.first;
10260b57cec5SDimitry Andric       BasicBlock *NewBlock = BBMapping.second;
10270b57cec5SDimitry Andric       for (BasicBlock *SuccBB : successors(NewBlock)) {
10280b57cec5SDimitry Andric         for (PHINode &SuccPN : SuccBB->phis()) {
10290b57cec5SDimitry Andric           // Ok, we have a PHI node.  Figure out what the incoming value was for
10300b57cec5SDimitry Andric           // the OldBlock.
10310b57cec5SDimitry Andric           int OldBlockIdx = SuccPN.getBasicBlockIndex(OldBlock);
10320b57cec5SDimitry Andric           if (OldBlockIdx == -1)
10330b57cec5SDimitry Andric             break;
10340b57cec5SDimitry Andric           Value *IV = SuccPN.getIncomingValue(OldBlockIdx);
10350b57cec5SDimitry Andric 
10360b57cec5SDimitry Andric           // Remap the value if necessary.
10370b57cec5SDimitry Andric           if (auto *Inst = dyn_cast<Instruction>(IV)) {
10380b57cec5SDimitry Andric             ValueToValueMapTy::iterator I = VMap.find(Inst);
10390b57cec5SDimitry Andric             if (I != VMap.end())
10400b57cec5SDimitry Andric               IV = I->second;
10410b57cec5SDimitry Andric           }
10420b57cec5SDimitry Andric 
10430b57cec5SDimitry Andric           SuccPN.addIncoming(IV, NewBlock);
10440b57cec5SDimitry Andric         }
10450b57cec5SDimitry Andric       }
10460b57cec5SDimitry Andric     }
10470b57cec5SDimitry Andric 
10480b57cec5SDimitry Andric     for (ValueToValueMapTy::value_type VT : VMap) {
10490b57cec5SDimitry Andric       // If there were values defined in BB that are used outside the funclet,
10500b57cec5SDimitry Andric       // then we now have to update all uses of the value to use either the
10510b57cec5SDimitry Andric       // original value, the cloned value, or some PHI derived value.  This can
10520b57cec5SDimitry Andric       // require arbitrary PHI insertion, of which we are prepared to do, clean
10530b57cec5SDimitry Andric       // these up now.
10540b57cec5SDimitry Andric       SmallVector<Use *, 16> UsesToRename;
10550b57cec5SDimitry Andric 
10560b57cec5SDimitry Andric       auto *OldI = dyn_cast<Instruction>(const_cast<Value *>(VT.first));
10570b57cec5SDimitry Andric       if (!OldI)
10580b57cec5SDimitry Andric         continue;
10590b57cec5SDimitry Andric       auto *NewI = cast<Instruction>(VT.second);
10600b57cec5SDimitry Andric       // Scan all uses of this instruction to see if it is used outside of its
10610b57cec5SDimitry Andric       // funclet, and if so, record them in UsesToRename.
10620b57cec5SDimitry Andric       for (Use &U : OldI->uses()) {
10630b57cec5SDimitry Andric         Instruction *UserI = cast<Instruction>(U.getUser());
10640b57cec5SDimitry Andric         BasicBlock *UserBB = UserI->getParent();
10650b57cec5SDimitry Andric         ColorVector &ColorsForUserBB = BlockColors[UserBB];
10660b57cec5SDimitry Andric         assert(!ColorsForUserBB.empty());
10670b57cec5SDimitry Andric         if (ColorsForUserBB.size() > 1 ||
10680b57cec5SDimitry Andric             *ColorsForUserBB.begin() != FuncletPadBB)
10690b57cec5SDimitry Andric           UsesToRename.push_back(&U);
10700b57cec5SDimitry Andric       }
10710b57cec5SDimitry Andric 
10720b57cec5SDimitry Andric       // If there are no uses outside the block, we're done with this
10730b57cec5SDimitry Andric       // instruction.
10740b57cec5SDimitry Andric       if (UsesToRename.empty())
10750b57cec5SDimitry Andric         continue;
10760b57cec5SDimitry Andric 
10770b57cec5SDimitry Andric       // We found a use of OldI outside of the funclet.  Rename all uses of OldI
10780b57cec5SDimitry Andric       // that are outside its funclet to be uses of the appropriate PHI node
10790b57cec5SDimitry Andric       // etc.
10800b57cec5SDimitry Andric       SSAUpdater SSAUpdate;
10810b57cec5SDimitry Andric       SSAUpdate.Initialize(OldI->getType(), OldI->getName());
10820b57cec5SDimitry Andric       SSAUpdate.AddAvailableValue(OldI->getParent(), OldI);
10830b57cec5SDimitry Andric       SSAUpdate.AddAvailableValue(NewI->getParent(), NewI);
10840b57cec5SDimitry Andric 
10850b57cec5SDimitry Andric       while (!UsesToRename.empty())
10860b57cec5SDimitry Andric         SSAUpdate.RewriteUseAfterInsertions(*UsesToRename.pop_back_val());
10870b57cec5SDimitry Andric     }
10880b57cec5SDimitry Andric   }
10890b57cec5SDimitry Andric }
10900b57cec5SDimitry Andric 
removeImplausibleInstructions(Function & F)10915f757f3fSDimitry Andric void WinEHPrepareImpl::removeImplausibleInstructions(Function &F) {
10920b57cec5SDimitry Andric   // Remove implausible terminators and replace them with UnreachableInst.
10930b57cec5SDimitry Andric   for (auto &Funclet : FuncletBlocks) {
10940b57cec5SDimitry Andric     BasicBlock *FuncletPadBB = Funclet.first;
10950b57cec5SDimitry Andric     std::vector<BasicBlock *> &BlocksInFunclet = Funclet.second;
10960b57cec5SDimitry Andric     Instruction *FirstNonPHI = FuncletPadBB->getFirstNonPHI();
10970b57cec5SDimitry Andric     auto *FuncletPad = dyn_cast<FuncletPadInst>(FirstNonPHI);
10980b57cec5SDimitry Andric     auto *CatchPad = dyn_cast_or_null<CatchPadInst>(FuncletPad);
10990b57cec5SDimitry Andric     auto *CleanupPad = dyn_cast_or_null<CleanupPadInst>(FuncletPad);
11000b57cec5SDimitry Andric 
11010b57cec5SDimitry Andric     for (BasicBlock *BB : BlocksInFunclet) {
11020b57cec5SDimitry Andric       for (Instruction &I : *BB) {
11035ffd83dbSDimitry Andric         auto *CB = dyn_cast<CallBase>(&I);
11045ffd83dbSDimitry Andric         if (!CB)
11050b57cec5SDimitry Andric           continue;
11060b57cec5SDimitry Andric 
11070b57cec5SDimitry Andric         Value *FuncletBundleOperand = nullptr;
11085ffd83dbSDimitry Andric         if (auto BU = CB->getOperandBundle(LLVMContext::OB_funclet))
11090b57cec5SDimitry Andric           FuncletBundleOperand = BU->Inputs.front();
11100b57cec5SDimitry Andric 
11110b57cec5SDimitry Andric         if (FuncletBundleOperand == FuncletPad)
11120b57cec5SDimitry Andric           continue;
11130b57cec5SDimitry Andric 
11140b57cec5SDimitry Andric         // Skip call sites which are nounwind intrinsics or inline asm.
11150b57cec5SDimitry Andric         auto *CalledFn =
11165ffd83dbSDimitry Andric             dyn_cast<Function>(CB->getCalledOperand()->stripPointerCasts());
11175ffd83dbSDimitry Andric         if (CalledFn && ((CalledFn->isIntrinsic() && CB->doesNotThrow()) ||
11185ffd83dbSDimitry Andric                          CB->isInlineAsm()))
11190b57cec5SDimitry Andric           continue;
11200b57cec5SDimitry Andric 
11210b57cec5SDimitry Andric         // This call site was not part of this funclet, remove it.
11225ffd83dbSDimitry Andric         if (isa<InvokeInst>(CB)) {
11230b57cec5SDimitry Andric           // Remove the unwind edge if it was an invoke.
11240b57cec5SDimitry Andric           removeUnwindEdge(BB);
11250b57cec5SDimitry Andric           // Get a pointer to the new call.
11260b57cec5SDimitry Andric           BasicBlock::iterator CallI =
11270b57cec5SDimitry Andric               std::prev(BB->getTerminator()->getIterator());
11280b57cec5SDimitry Andric           auto *CI = cast<CallInst>(&*CallI);
1129fe6060f1SDimitry Andric           changeToUnreachable(CI);
11300b57cec5SDimitry Andric         } else {
1131fe6060f1SDimitry Andric           changeToUnreachable(&I);
11320b57cec5SDimitry Andric         }
11330b57cec5SDimitry Andric 
11340b57cec5SDimitry Andric         // There are no more instructions in the block (except for unreachable),
11350b57cec5SDimitry Andric         // we are done.
11360b57cec5SDimitry Andric         break;
11370b57cec5SDimitry Andric       }
11380b57cec5SDimitry Andric 
11390b57cec5SDimitry Andric       Instruction *TI = BB->getTerminator();
11400b57cec5SDimitry Andric       // CatchPadInst and CleanupPadInst can't transfer control to a ReturnInst.
11410b57cec5SDimitry Andric       bool IsUnreachableRet = isa<ReturnInst>(TI) && FuncletPad;
11420b57cec5SDimitry Andric       // The token consumed by a CatchReturnInst must match the funclet token.
11430b57cec5SDimitry Andric       bool IsUnreachableCatchret = false;
11440b57cec5SDimitry Andric       if (auto *CRI = dyn_cast<CatchReturnInst>(TI))
11450b57cec5SDimitry Andric         IsUnreachableCatchret = CRI->getCatchPad() != CatchPad;
11460b57cec5SDimitry Andric       // The token consumed by a CleanupReturnInst must match the funclet token.
11470b57cec5SDimitry Andric       bool IsUnreachableCleanupret = false;
11480b57cec5SDimitry Andric       if (auto *CRI = dyn_cast<CleanupReturnInst>(TI))
11490b57cec5SDimitry Andric         IsUnreachableCleanupret = CRI->getCleanupPad() != CleanupPad;
11500b57cec5SDimitry Andric       if (IsUnreachableRet || IsUnreachableCatchret ||
11510b57cec5SDimitry Andric           IsUnreachableCleanupret) {
1152fe6060f1SDimitry Andric         changeToUnreachable(TI);
11530b57cec5SDimitry Andric       } else if (isa<InvokeInst>(TI)) {
11540b57cec5SDimitry Andric         if (Personality == EHPersonality::MSVC_CXX && CleanupPad) {
11550b57cec5SDimitry Andric           // Invokes within a cleanuppad for the MSVC++ personality never
11560b57cec5SDimitry Andric           // transfer control to their unwind edge: the personality will
11570b57cec5SDimitry Andric           // terminate the program.
11580b57cec5SDimitry Andric           removeUnwindEdge(BB);
11590b57cec5SDimitry Andric         }
11600b57cec5SDimitry Andric       }
11610b57cec5SDimitry Andric     }
11620b57cec5SDimitry Andric   }
11630b57cec5SDimitry Andric }
11640b57cec5SDimitry Andric 
cleanupPreparedFunclets(Function & F)11655f757f3fSDimitry Andric void WinEHPrepareImpl::cleanupPreparedFunclets(Function &F) {
11660b57cec5SDimitry Andric   // Clean-up some of the mess we made by removing useles PHI nodes, trivial
11670b57cec5SDimitry Andric   // branches, etc.
1168fe6060f1SDimitry Andric   for (BasicBlock &BB : llvm::make_early_inc_range(F)) {
1169fe6060f1SDimitry Andric     SimplifyInstructionsInBlock(&BB);
1170fe6060f1SDimitry Andric     ConstantFoldTerminator(&BB, /*DeleteDeadConditions=*/true);
1171fe6060f1SDimitry Andric     MergeBlockIntoPredecessor(&BB);
11720b57cec5SDimitry Andric   }
11730b57cec5SDimitry Andric 
11740b57cec5SDimitry Andric   // We might have some unreachable blocks after cleaning up some impossible
11750b57cec5SDimitry Andric   // control flow.
11760b57cec5SDimitry Andric   removeUnreachableBlocks(F);
11770b57cec5SDimitry Andric }
11780b57cec5SDimitry Andric 
11790b57cec5SDimitry Andric #ifndef NDEBUG
verifyPreparedFunclets(Function & F)11805f757f3fSDimitry Andric void WinEHPrepareImpl::verifyPreparedFunclets(Function &F) {
11810b57cec5SDimitry Andric   for (BasicBlock &BB : F) {
11820b57cec5SDimitry Andric     size_t NumColors = BlockColors[&BB].size();
11830b57cec5SDimitry Andric     assert(NumColors == 1 && "Expected monochromatic BB!");
11840b57cec5SDimitry Andric     if (NumColors == 0)
11850b57cec5SDimitry Andric       report_fatal_error("Uncolored BB!");
11860b57cec5SDimitry Andric     if (NumColors > 1)
11870b57cec5SDimitry Andric       report_fatal_error("Multicolor BB!");
11880b57cec5SDimitry Andric     assert((DisableDemotion || !(BB.isEHPad() && isa<PHINode>(BB.begin()))) &&
11890b57cec5SDimitry Andric            "EH Pad still has a PHI!");
11900b57cec5SDimitry Andric   }
11910b57cec5SDimitry Andric }
11920b57cec5SDimitry Andric #endif
11930b57cec5SDimitry Andric 
prepareExplicitEH(Function & F)11945f757f3fSDimitry Andric bool WinEHPrepareImpl::prepareExplicitEH(Function &F) {
11950b57cec5SDimitry Andric   // Remove unreachable blocks.  It is not valuable to assign them a color and
11960b57cec5SDimitry Andric   // their existence can trick us into thinking values are alive when they are
11970b57cec5SDimitry Andric   // not.
11980b57cec5SDimitry Andric   removeUnreachableBlocks(F);
11990b57cec5SDimitry Andric 
12000b57cec5SDimitry Andric   // Determine which blocks are reachable from which funclet entries.
12010b57cec5SDimitry Andric   colorFunclets(F);
12020b57cec5SDimitry Andric 
12030b57cec5SDimitry Andric   cloneCommonBlocks(F);
12040b57cec5SDimitry Andric 
12050b57cec5SDimitry Andric   if (!DisableDemotion)
12060b57cec5SDimitry Andric     demotePHIsOnFunclets(F, DemoteCatchSwitchPHIOnly ||
12070b57cec5SDimitry Andric                                 DemoteCatchSwitchPHIOnlyOpt);
12080b57cec5SDimitry Andric 
12090b57cec5SDimitry Andric   if (!DisableCleanups) {
12105ffd83dbSDimitry Andric     assert(!verifyFunction(F, &dbgs()));
12110b57cec5SDimitry Andric     removeImplausibleInstructions(F);
12120b57cec5SDimitry Andric 
12135ffd83dbSDimitry Andric     assert(!verifyFunction(F, &dbgs()));
12140b57cec5SDimitry Andric     cleanupPreparedFunclets(F);
12150b57cec5SDimitry Andric   }
12160b57cec5SDimitry Andric 
12170b57cec5SDimitry Andric   LLVM_DEBUG(verifyPreparedFunclets(F));
12180b57cec5SDimitry Andric   // Recolor the CFG to verify that all is well.
12190b57cec5SDimitry Andric   LLVM_DEBUG(colorFunclets(F));
12200b57cec5SDimitry Andric   LLVM_DEBUG(verifyPreparedFunclets(F));
12210b57cec5SDimitry Andric 
12220b57cec5SDimitry Andric   return true;
12230b57cec5SDimitry Andric }
12240b57cec5SDimitry Andric 
12250b57cec5SDimitry Andric // TODO: Share loads when one use dominates another, or when a catchpad exit
12260b57cec5SDimitry Andric // dominates uses (needs dominators).
insertPHILoads(PHINode * PN,Function & F)12275f757f3fSDimitry Andric AllocaInst *WinEHPrepareImpl::insertPHILoads(PHINode *PN, Function &F) {
12280b57cec5SDimitry Andric   BasicBlock *PHIBlock = PN->getParent();
12290b57cec5SDimitry Andric   AllocaInst *SpillSlot = nullptr;
12300b57cec5SDimitry Andric   Instruction *EHPad = PHIBlock->getFirstNonPHI();
12310b57cec5SDimitry Andric 
12320b57cec5SDimitry Andric   if (!EHPad->isTerminator()) {
12330b57cec5SDimitry Andric     // If the EHPad isn't a terminator, then we can insert a load in this block
12340b57cec5SDimitry Andric     // that will dominate all uses.
12350b57cec5SDimitry Andric     SpillSlot = new AllocaInst(PN->getType(), DL->getAllocaAddrSpace(), nullptr,
12360b57cec5SDimitry Andric                                Twine(PN->getName(), ".wineh.spillslot"),
12370b57cec5SDimitry Andric                                &F.getEntryBlock().front());
12380b57cec5SDimitry Andric     Value *V = new LoadInst(PN->getType(), SpillSlot,
12390b57cec5SDimitry Andric                             Twine(PN->getName(), ".wineh.reload"),
12400b57cec5SDimitry Andric                             &*PHIBlock->getFirstInsertionPt());
12410b57cec5SDimitry Andric     PN->replaceAllUsesWith(V);
12420b57cec5SDimitry Andric     return SpillSlot;
12430b57cec5SDimitry Andric   }
12440b57cec5SDimitry Andric 
12450b57cec5SDimitry Andric   // Otherwise, we have a PHI on a terminator EHPad, and we give up and insert
12460b57cec5SDimitry Andric   // loads of the slot before every use.
12470b57cec5SDimitry Andric   DenseMap<BasicBlock *, Value *> Loads;
1248fe6060f1SDimitry Andric   for (Use &U : llvm::make_early_inc_range(PN->uses())) {
12490b57cec5SDimitry Andric     auto *UsingInst = cast<Instruction>(U.getUser());
12500b57cec5SDimitry Andric     if (isa<PHINode>(UsingInst) && UsingInst->getParent()->isEHPad()) {
12510b57cec5SDimitry Andric       // Use is on an EH pad phi.  Leave it alone; we'll insert loads and
12520b57cec5SDimitry Andric       // stores for it separately.
12530b57cec5SDimitry Andric       continue;
12540b57cec5SDimitry Andric     }
12550b57cec5SDimitry Andric     replaceUseWithLoad(PN, U, SpillSlot, Loads, F);
12560b57cec5SDimitry Andric   }
12570b57cec5SDimitry Andric   return SpillSlot;
12580b57cec5SDimitry Andric }
12590b57cec5SDimitry Andric 
12600b57cec5SDimitry Andric // TODO: improve store placement.  Inserting at def is probably good, but need
12610b57cec5SDimitry Andric // to be careful not to introduce interfering stores (needs liveness analysis).
12620b57cec5SDimitry Andric // TODO: identify related phi nodes that can share spill slots, and share them
12630b57cec5SDimitry Andric // (also needs liveness).
insertPHIStores(PHINode * OriginalPHI,AllocaInst * SpillSlot)12645f757f3fSDimitry Andric void WinEHPrepareImpl::insertPHIStores(PHINode *OriginalPHI,
12650b57cec5SDimitry Andric                                        AllocaInst *SpillSlot) {
12660b57cec5SDimitry Andric   // Use a worklist of (Block, Value) pairs -- the given Value needs to be
12670b57cec5SDimitry Andric   // stored to the spill slot by the end of the given Block.
12680b57cec5SDimitry Andric   SmallVector<std::pair<BasicBlock *, Value *>, 4> Worklist;
12690b57cec5SDimitry Andric 
12700b57cec5SDimitry Andric   Worklist.push_back({OriginalPHI->getParent(), OriginalPHI});
12710b57cec5SDimitry Andric 
12720b57cec5SDimitry Andric   while (!Worklist.empty()) {
12730b57cec5SDimitry Andric     BasicBlock *EHBlock;
12740b57cec5SDimitry Andric     Value *InVal;
12750b57cec5SDimitry Andric     std::tie(EHBlock, InVal) = Worklist.pop_back_val();
12760b57cec5SDimitry Andric 
12770b57cec5SDimitry Andric     PHINode *PN = dyn_cast<PHINode>(InVal);
12780b57cec5SDimitry Andric     if (PN && PN->getParent() == EHBlock) {
12790b57cec5SDimitry Andric       // The value is defined by another PHI we need to remove, with no room to
12800b57cec5SDimitry Andric       // insert a store after the PHI, so each predecessor needs to store its
12810b57cec5SDimitry Andric       // incoming value.
12820b57cec5SDimitry Andric       for (unsigned i = 0, e = PN->getNumIncomingValues(); i < e; ++i) {
12830b57cec5SDimitry Andric         Value *PredVal = PN->getIncomingValue(i);
12840b57cec5SDimitry Andric 
12850b57cec5SDimitry Andric         // Undef can safely be skipped.
12860b57cec5SDimitry Andric         if (isa<UndefValue>(PredVal))
12870b57cec5SDimitry Andric           continue;
12880b57cec5SDimitry Andric 
12890b57cec5SDimitry Andric         insertPHIStore(PN->getIncomingBlock(i), PredVal, SpillSlot, Worklist);
12900b57cec5SDimitry Andric       }
12910b57cec5SDimitry Andric     } else {
12920b57cec5SDimitry Andric       // We need to store InVal, which dominates EHBlock, but can't put a store
12930b57cec5SDimitry Andric       // in EHBlock, so need to put stores in each predecessor.
12940b57cec5SDimitry Andric       for (BasicBlock *PredBlock : predecessors(EHBlock)) {
12950b57cec5SDimitry Andric         insertPHIStore(PredBlock, InVal, SpillSlot, Worklist);
12960b57cec5SDimitry Andric       }
12970b57cec5SDimitry Andric     }
12980b57cec5SDimitry Andric   }
12990b57cec5SDimitry Andric }
13000b57cec5SDimitry Andric 
insertPHIStore(BasicBlock * PredBlock,Value * PredVal,AllocaInst * SpillSlot,SmallVectorImpl<std::pair<BasicBlock *,Value * >> & Worklist)13015f757f3fSDimitry Andric void WinEHPrepareImpl::insertPHIStore(
13020b57cec5SDimitry Andric     BasicBlock *PredBlock, Value *PredVal, AllocaInst *SpillSlot,
13030b57cec5SDimitry Andric     SmallVectorImpl<std::pair<BasicBlock *, Value *>> &Worklist) {
13040b57cec5SDimitry Andric 
13050b57cec5SDimitry Andric   if (PredBlock->isEHPad() && PredBlock->getFirstNonPHI()->isTerminator()) {
13060b57cec5SDimitry Andric     // Pred is unsplittable, so we need to queue it on the worklist.
13070b57cec5SDimitry Andric     Worklist.push_back({PredBlock, PredVal});
13080b57cec5SDimitry Andric     return;
13090b57cec5SDimitry Andric   }
13100b57cec5SDimitry Andric 
13110b57cec5SDimitry Andric   // Otherwise, insert the store at the end of the basic block.
13120b57cec5SDimitry Andric   new StoreInst(PredVal, SpillSlot, PredBlock->getTerminator());
13130b57cec5SDimitry Andric }
13140b57cec5SDimitry Andric 
replaceUseWithLoad(Value * V,Use & U,AllocaInst * & SpillSlot,DenseMap<BasicBlock *,Value * > & Loads,Function & F)13155f757f3fSDimitry Andric void WinEHPrepareImpl::replaceUseWithLoad(
13165f757f3fSDimitry Andric     Value *V, Use &U, AllocaInst *&SpillSlot,
13175f757f3fSDimitry Andric     DenseMap<BasicBlock *, Value *> &Loads, Function &F) {
13180b57cec5SDimitry Andric   // Lazilly create the spill slot.
13190b57cec5SDimitry Andric   if (!SpillSlot)
13200b57cec5SDimitry Andric     SpillSlot = new AllocaInst(V->getType(), DL->getAllocaAddrSpace(), nullptr,
13210b57cec5SDimitry Andric                                Twine(V->getName(), ".wineh.spillslot"),
13220b57cec5SDimitry Andric                                &F.getEntryBlock().front());
13230b57cec5SDimitry Andric 
13240b57cec5SDimitry Andric   auto *UsingInst = cast<Instruction>(U.getUser());
13250b57cec5SDimitry Andric   if (auto *UsingPHI = dyn_cast<PHINode>(UsingInst)) {
13260b57cec5SDimitry Andric     // If this is a PHI node, we can't insert a load of the value before
13270b57cec5SDimitry Andric     // the use.  Instead insert the load in the predecessor block
13280b57cec5SDimitry Andric     // corresponding to the incoming value.
13290b57cec5SDimitry Andric     //
13300b57cec5SDimitry Andric     // Note that if there are multiple edges from a basic block to this
13310b57cec5SDimitry Andric     // PHI node that we cannot have multiple loads.  The problem is that
13320b57cec5SDimitry Andric     // the resulting PHI node will have multiple values (from each load)
13330b57cec5SDimitry Andric     // coming in from the same block, which is illegal SSA form.
13340b57cec5SDimitry Andric     // For this reason, we keep track of and reuse loads we insert.
13350b57cec5SDimitry Andric     BasicBlock *IncomingBlock = UsingPHI->getIncomingBlock(U);
13360b57cec5SDimitry Andric     if (auto *CatchRet =
13370b57cec5SDimitry Andric             dyn_cast<CatchReturnInst>(IncomingBlock->getTerminator())) {
13380b57cec5SDimitry Andric       // Putting a load above a catchret and use on the phi would still leave
13390b57cec5SDimitry Andric       // a cross-funclet def/use.  We need to split the edge, change the
13400b57cec5SDimitry Andric       // catchret to target the new block, and put the load there.
13410b57cec5SDimitry Andric       BasicBlock *PHIBlock = UsingInst->getParent();
13420b57cec5SDimitry Andric       BasicBlock *NewBlock = SplitEdge(IncomingBlock, PHIBlock);
13430b57cec5SDimitry Andric       // SplitEdge gives us:
13440b57cec5SDimitry Andric       //   IncomingBlock:
13450b57cec5SDimitry Andric       //     ...
13460b57cec5SDimitry Andric       //     br label %NewBlock
13470b57cec5SDimitry Andric       //   NewBlock:
13480b57cec5SDimitry Andric       //     catchret label %PHIBlock
13490b57cec5SDimitry Andric       // But we need:
13500b57cec5SDimitry Andric       //   IncomingBlock:
13510b57cec5SDimitry Andric       //     ...
13520b57cec5SDimitry Andric       //     catchret label %NewBlock
13530b57cec5SDimitry Andric       //   NewBlock:
13540b57cec5SDimitry Andric       //     br label %PHIBlock
13550b57cec5SDimitry Andric       // So move the terminators to each others' blocks and swap their
13560b57cec5SDimitry Andric       // successors.
13570b57cec5SDimitry Andric       BranchInst *Goto = cast<BranchInst>(IncomingBlock->getTerminator());
13580b57cec5SDimitry Andric       Goto->removeFromParent();
13590b57cec5SDimitry Andric       CatchRet->removeFromParent();
1360bdd1243dSDimitry Andric       CatchRet->insertInto(IncomingBlock, IncomingBlock->end());
1361bdd1243dSDimitry Andric       Goto->insertInto(NewBlock, NewBlock->end());
13620b57cec5SDimitry Andric       Goto->setSuccessor(0, PHIBlock);
13630b57cec5SDimitry Andric       CatchRet->setSuccessor(NewBlock);
13640b57cec5SDimitry Andric       // Update the color mapping for the newly split edge.
13650b57cec5SDimitry Andric       // Grab a reference to the ColorVector to be inserted before getting the
13660b57cec5SDimitry Andric       // reference to the vector we are copying because inserting the new
13670b57cec5SDimitry Andric       // element in BlockColors might cause the map to be reallocated.
13680b57cec5SDimitry Andric       ColorVector &ColorsForNewBlock = BlockColors[NewBlock];
13690b57cec5SDimitry Andric       ColorVector &ColorsForPHIBlock = BlockColors[PHIBlock];
13700b57cec5SDimitry Andric       ColorsForNewBlock = ColorsForPHIBlock;
13710b57cec5SDimitry Andric       for (BasicBlock *FuncletPad : ColorsForPHIBlock)
13720b57cec5SDimitry Andric         FuncletBlocks[FuncletPad].push_back(NewBlock);
13730b57cec5SDimitry Andric       // Treat the new block as incoming for load insertion.
13740b57cec5SDimitry Andric       IncomingBlock = NewBlock;
13750b57cec5SDimitry Andric     }
13760b57cec5SDimitry Andric     Value *&Load = Loads[IncomingBlock];
13770b57cec5SDimitry Andric     // Insert the load into the predecessor block
13780b57cec5SDimitry Andric     if (!Load)
13790b57cec5SDimitry Andric       Load = new LoadInst(V->getType(), SpillSlot,
13800b57cec5SDimitry Andric                           Twine(V->getName(), ".wineh.reload"),
13810b57cec5SDimitry Andric                           /*isVolatile=*/false, IncomingBlock->getTerminator());
13820b57cec5SDimitry Andric 
13830b57cec5SDimitry Andric     U.set(Load);
13840b57cec5SDimitry Andric   } else {
13850b57cec5SDimitry Andric     // Reload right before the old use.
13860b57cec5SDimitry Andric     auto *Load = new LoadInst(V->getType(), SpillSlot,
13870b57cec5SDimitry Andric                               Twine(V->getName(), ".wineh.reload"),
13880b57cec5SDimitry Andric                               /*isVolatile=*/false, UsingInst);
13890b57cec5SDimitry Andric     U.set(Load);
13900b57cec5SDimitry Andric   }
13910b57cec5SDimitry Andric }
13920b57cec5SDimitry Andric 
addIPToStateRange(const InvokeInst * II,MCSymbol * InvokeBegin,MCSymbol * InvokeEnd)13930b57cec5SDimitry Andric void WinEHFuncInfo::addIPToStateRange(const InvokeInst *II,
13940b57cec5SDimitry Andric                                       MCSymbol *InvokeBegin,
13950b57cec5SDimitry Andric                                       MCSymbol *InvokeEnd) {
13960b57cec5SDimitry Andric   assert(InvokeStateMap.count(II) &&
13970b57cec5SDimitry Andric          "should get invoke with precomputed state");
13980b57cec5SDimitry Andric   LabelToStateMap[InvokeBegin] = std::make_pair(InvokeStateMap[II], InvokeEnd);
13990b57cec5SDimitry Andric }
14000b57cec5SDimitry Andric 
addIPToStateRange(int State,MCSymbol * InvokeBegin,MCSymbol * InvokeEnd)140106c3fb27SDimitry Andric void WinEHFuncInfo::addIPToStateRange(int State, MCSymbol* InvokeBegin,
140206c3fb27SDimitry Andric     MCSymbol* InvokeEnd) {
140306c3fb27SDimitry Andric     LabelToStateMap[InvokeBegin] = std::make_pair(State, InvokeEnd);
140406c3fb27SDimitry Andric }
140506c3fb27SDimitry Andric 
140681ad6265SDimitry Andric WinEHFuncInfo::WinEHFuncInfo() = default;
1407