xref: /aosp_15_r20/external/llvm/lib/CodeGen/WinEHPrepare.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- WinEHPrepare - Prepare exception handling for code generation ---===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This pass lowers LLVM IR exception handling into something closer to what the
11*9880d681SAndroid Build Coastguard Worker // backend wants for functions using a personality function from a runtime
12*9880d681SAndroid Build Coastguard Worker // provided by MSVC. Functions with other personality functions are left alone
13*9880d681SAndroid Build Coastguard Worker // and may be prepared by other passes. In particular, all supported MSVC
14*9880d681SAndroid Build Coastguard Worker // personality functions require cleanup code to be outlined, and the C++
15*9880d681SAndroid Build Coastguard Worker // personality requires catch handler code to be outlined.
16*9880d681SAndroid Build Coastguard Worker //
17*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
18*9880d681SAndroid Build Coastguard Worker 
19*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/Passes.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/DenseMap.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/MapVector.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/STLExtras.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/CFG.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/EHPersonalities.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineBasicBlock.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/WinEHFuncInfo.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Verifier.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSymbol.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/Pass.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Utils/BasicBlockUtils.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Utils/Cloning.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Utils/Local.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Utils/SSAUpdater.h"
36*9880d681SAndroid Build Coastguard Worker 
37*9880d681SAndroid Build Coastguard Worker using namespace llvm;
38*9880d681SAndroid Build Coastguard Worker 
39*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "winehprepare"
40*9880d681SAndroid Build Coastguard Worker 
41*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> DisableDemotion(
42*9880d681SAndroid Build Coastguard Worker     "disable-demotion", cl::Hidden,
43*9880d681SAndroid Build Coastguard Worker     cl::desc(
44*9880d681SAndroid Build Coastguard Worker         "Clone multicolor basic blocks but do not demote cross funclet values"),
45*9880d681SAndroid Build Coastguard Worker     cl::init(false));
46*9880d681SAndroid Build Coastguard Worker 
47*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> DisableCleanups(
48*9880d681SAndroid Build Coastguard Worker     "disable-cleanups", cl::Hidden,
49*9880d681SAndroid Build Coastguard Worker     cl::desc("Do not remove implausible terminators or other similar cleanups"),
50*9880d681SAndroid Build Coastguard Worker     cl::init(false));
51*9880d681SAndroid Build Coastguard Worker 
52*9880d681SAndroid Build Coastguard Worker namespace {
53*9880d681SAndroid Build Coastguard Worker 
54*9880d681SAndroid Build Coastguard Worker class WinEHPrepare : public FunctionPass {
55*9880d681SAndroid Build Coastguard Worker public:
56*9880d681SAndroid Build Coastguard Worker   static char ID; // Pass identification, replacement for typeid.
WinEHPrepare(const TargetMachine * TM=nullptr)57*9880d681SAndroid Build Coastguard Worker   WinEHPrepare(const TargetMachine *TM = nullptr) : FunctionPass(ID) {}
58*9880d681SAndroid Build Coastguard Worker 
59*9880d681SAndroid Build Coastguard Worker   bool runOnFunction(Function &Fn) override;
60*9880d681SAndroid Build Coastguard Worker 
61*9880d681SAndroid Build Coastguard Worker   bool doFinalization(Module &M) override;
62*9880d681SAndroid Build Coastguard Worker 
63*9880d681SAndroid Build Coastguard Worker   void getAnalysisUsage(AnalysisUsage &AU) const override;
64*9880d681SAndroid Build Coastguard Worker 
getPassName() const65*9880d681SAndroid Build Coastguard Worker   const char *getPassName() const override {
66*9880d681SAndroid Build Coastguard Worker     return "Windows exception handling preparation";
67*9880d681SAndroid Build Coastguard Worker   }
68*9880d681SAndroid Build Coastguard Worker 
69*9880d681SAndroid Build Coastguard Worker private:
70*9880d681SAndroid Build Coastguard Worker   void insertPHIStores(PHINode *OriginalPHI, AllocaInst *SpillSlot);
71*9880d681SAndroid Build Coastguard Worker   void
72*9880d681SAndroid Build Coastguard Worker   insertPHIStore(BasicBlock *PredBlock, Value *PredVal, AllocaInst *SpillSlot,
73*9880d681SAndroid Build Coastguard Worker                  SmallVectorImpl<std::pair<BasicBlock *, Value *>> &Worklist);
74*9880d681SAndroid Build Coastguard Worker   AllocaInst *insertPHILoads(PHINode *PN, Function &F);
75*9880d681SAndroid Build Coastguard Worker   void replaceUseWithLoad(Value *V, Use &U, AllocaInst *&SpillSlot,
76*9880d681SAndroid Build Coastguard Worker                           DenseMap<BasicBlock *, Value *> &Loads, Function &F);
77*9880d681SAndroid Build Coastguard Worker   bool prepareExplicitEH(Function &F);
78*9880d681SAndroid Build Coastguard Worker   void colorFunclets(Function &F);
79*9880d681SAndroid Build Coastguard Worker 
80*9880d681SAndroid Build Coastguard Worker   void demotePHIsOnFunclets(Function &F);
81*9880d681SAndroid Build Coastguard Worker   void cloneCommonBlocks(Function &F);
82*9880d681SAndroid Build Coastguard Worker   void removeImplausibleInstructions(Function &F);
83*9880d681SAndroid Build Coastguard Worker   void cleanupPreparedFunclets(Function &F);
84*9880d681SAndroid Build Coastguard Worker   void verifyPreparedFunclets(Function &F);
85*9880d681SAndroid Build Coastguard Worker 
86*9880d681SAndroid Build Coastguard Worker   // All fields are reset by runOnFunction.
87*9880d681SAndroid Build Coastguard Worker   EHPersonality Personality = EHPersonality::Unknown;
88*9880d681SAndroid Build Coastguard Worker 
89*9880d681SAndroid Build Coastguard Worker   DenseMap<BasicBlock *, ColorVector> BlockColors;
90*9880d681SAndroid Build Coastguard Worker   MapVector<BasicBlock *, std::vector<BasicBlock *>> FuncletBlocks;
91*9880d681SAndroid Build Coastguard Worker };
92*9880d681SAndroid Build Coastguard Worker 
93*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
94*9880d681SAndroid Build Coastguard Worker 
95*9880d681SAndroid Build Coastguard Worker char WinEHPrepare::ID = 0;
96*9880d681SAndroid Build Coastguard Worker INITIALIZE_TM_PASS(WinEHPrepare, "winehprepare", "Prepare Windows exceptions",
97*9880d681SAndroid Build Coastguard Worker                    false, false)
98*9880d681SAndroid Build Coastguard Worker 
createWinEHPass(const TargetMachine * TM)99*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createWinEHPass(const TargetMachine *TM) {
100*9880d681SAndroid Build Coastguard Worker   return new WinEHPrepare(TM);
101*9880d681SAndroid Build Coastguard Worker }
102*9880d681SAndroid Build Coastguard Worker 
runOnFunction(Function & Fn)103*9880d681SAndroid Build Coastguard Worker bool WinEHPrepare::runOnFunction(Function &Fn) {
104*9880d681SAndroid Build Coastguard Worker   if (!Fn.hasPersonalityFn())
105*9880d681SAndroid Build Coastguard Worker     return false;
106*9880d681SAndroid Build Coastguard Worker 
107*9880d681SAndroid Build Coastguard Worker   // Classify the personality to see what kind of preparation we need.
108*9880d681SAndroid Build Coastguard Worker   Personality = classifyEHPersonality(Fn.getPersonalityFn());
109*9880d681SAndroid Build Coastguard Worker 
110*9880d681SAndroid Build Coastguard Worker   // Do nothing if this is not a funclet-based personality.
111*9880d681SAndroid Build Coastguard Worker   if (!isFuncletEHPersonality(Personality))
112*9880d681SAndroid Build Coastguard Worker     return false;
113*9880d681SAndroid Build Coastguard Worker 
114*9880d681SAndroid Build Coastguard Worker   return prepareExplicitEH(Fn);
115*9880d681SAndroid Build Coastguard Worker }
116*9880d681SAndroid Build Coastguard Worker 
doFinalization(Module & M)117*9880d681SAndroid Build Coastguard Worker bool WinEHPrepare::doFinalization(Module &M) { return false; }
118*9880d681SAndroid Build Coastguard Worker 
getAnalysisUsage(AnalysisUsage & AU) const119*9880d681SAndroid Build Coastguard Worker void WinEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const {}
120*9880d681SAndroid Build Coastguard Worker 
addUnwindMapEntry(WinEHFuncInfo & FuncInfo,int ToState,const BasicBlock * BB)121*9880d681SAndroid Build Coastguard Worker static int addUnwindMapEntry(WinEHFuncInfo &FuncInfo, int ToState,
122*9880d681SAndroid Build Coastguard Worker                              const BasicBlock *BB) {
123*9880d681SAndroid Build Coastguard Worker   CxxUnwindMapEntry UME;
124*9880d681SAndroid Build Coastguard Worker   UME.ToState = ToState;
125*9880d681SAndroid Build Coastguard Worker   UME.Cleanup = BB;
126*9880d681SAndroid Build Coastguard Worker   FuncInfo.CxxUnwindMap.push_back(UME);
127*9880d681SAndroid Build Coastguard Worker   return FuncInfo.getLastStateNumber();
128*9880d681SAndroid Build Coastguard Worker }
129*9880d681SAndroid Build Coastguard Worker 
addTryBlockMapEntry(WinEHFuncInfo & FuncInfo,int TryLow,int TryHigh,int CatchHigh,ArrayRef<const CatchPadInst * > Handlers)130*9880d681SAndroid Build Coastguard Worker static void addTryBlockMapEntry(WinEHFuncInfo &FuncInfo, int TryLow,
131*9880d681SAndroid Build Coastguard Worker                                 int TryHigh, int CatchHigh,
132*9880d681SAndroid Build Coastguard Worker                                 ArrayRef<const CatchPadInst *> Handlers) {
133*9880d681SAndroid Build Coastguard Worker   WinEHTryBlockMapEntry TBME;
134*9880d681SAndroid Build Coastguard Worker   TBME.TryLow = TryLow;
135*9880d681SAndroid Build Coastguard Worker   TBME.TryHigh = TryHigh;
136*9880d681SAndroid Build Coastguard Worker   TBME.CatchHigh = CatchHigh;
137*9880d681SAndroid Build Coastguard Worker   assert(TBME.TryLow <= TBME.TryHigh);
138*9880d681SAndroid Build Coastguard Worker   for (const CatchPadInst *CPI : Handlers) {
139*9880d681SAndroid Build Coastguard Worker     WinEHHandlerType HT;
140*9880d681SAndroid Build Coastguard Worker     Constant *TypeInfo = cast<Constant>(CPI->getArgOperand(0));
141*9880d681SAndroid Build Coastguard Worker     if (TypeInfo->isNullValue())
142*9880d681SAndroid Build Coastguard Worker       HT.TypeDescriptor = nullptr;
143*9880d681SAndroid Build Coastguard Worker     else
144*9880d681SAndroid Build Coastguard Worker       HT.TypeDescriptor = cast<GlobalVariable>(TypeInfo->stripPointerCasts());
145*9880d681SAndroid Build Coastguard Worker     HT.Adjectives = cast<ConstantInt>(CPI->getArgOperand(1))->getZExtValue();
146*9880d681SAndroid Build Coastguard Worker     HT.Handler = CPI->getParent();
147*9880d681SAndroid Build Coastguard Worker     if (auto *AI =
148*9880d681SAndroid Build Coastguard Worker             dyn_cast<AllocaInst>(CPI->getArgOperand(2)->stripPointerCasts()))
149*9880d681SAndroid Build Coastguard Worker       HT.CatchObj.Alloca = AI;
150*9880d681SAndroid Build Coastguard Worker     else
151*9880d681SAndroid Build Coastguard Worker       HT.CatchObj.Alloca = nullptr;
152*9880d681SAndroid Build Coastguard Worker     TBME.HandlerArray.push_back(HT);
153*9880d681SAndroid Build Coastguard Worker   }
154*9880d681SAndroid Build Coastguard Worker   FuncInfo.TryBlockMap.push_back(TBME);
155*9880d681SAndroid Build Coastguard Worker }
156*9880d681SAndroid Build Coastguard Worker 
getCleanupRetUnwindDest(const CleanupPadInst * CleanupPad)157*9880d681SAndroid Build Coastguard Worker static BasicBlock *getCleanupRetUnwindDest(const CleanupPadInst *CleanupPad) {
158*9880d681SAndroid Build Coastguard Worker   for (const User *U : CleanupPad->users())
159*9880d681SAndroid Build Coastguard Worker     if (const auto *CRI = dyn_cast<CleanupReturnInst>(U))
160*9880d681SAndroid Build Coastguard Worker       return CRI->getUnwindDest();
161*9880d681SAndroid Build Coastguard Worker   return nullptr;
162*9880d681SAndroid Build Coastguard Worker }
163*9880d681SAndroid Build Coastguard Worker 
calculateStateNumbersForInvokes(const Function * Fn,WinEHFuncInfo & FuncInfo)164*9880d681SAndroid Build Coastguard Worker static void calculateStateNumbersForInvokes(const Function *Fn,
165*9880d681SAndroid Build Coastguard Worker                                             WinEHFuncInfo &FuncInfo) {
166*9880d681SAndroid Build Coastguard Worker   auto *F = const_cast<Function *>(Fn);
167*9880d681SAndroid Build Coastguard Worker   DenseMap<BasicBlock *, ColorVector> BlockColors = colorEHFunclets(*F);
168*9880d681SAndroid Build Coastguard Worker   for (BasicBlock &BB : *F) {
169*9880d681SAndroid Build Coastguard Worker     auto *II = dyn_cast<InvokeInst>(BB.getTerminator());
170*9880d681SAndroid Build Coastguard Worker     if (!II)
171*9880d681SAndroid Build Coastguard Worker       continue;
172*9880d681SAndroid Build Coastguard Worker 
173*9880d681SAndroid Build Coastguard Worker     auto &BBColors = BlockColors[&BB];
174*9880d681SAndroid Build Coastguard Worker     assert(BBColors.size() == 1 && "multi-color BB not removed by preparation");
175*9880d681SAndroid Build Coastguard Worker     BasicBlock *FuncletEntryBB = BBColors.front();
176*9880d681SAndroid Build Coastguard Worker 
177*9880d681SAndroid Build Coastguard Worker     BasicBlock *FuncletUnwindDest;
178*9880d681SAndroid Build Coastguard Worker     auto *FuncletPad =
179*9880d681SAndroid Build Coastguard Worker         dyn_cast<FuncletPadInst>(FuncletEntryBB->getFirstNonPHI());
180*9880d681SAndroid Build Coastguard Worker     assert(FuncletPad || FuncletEntryBB == &Fn->getEntryBlock());
181*9880d681SAndroid Build Coastguard Worker     if (!FuncletPad)
182*9880d681SAndroid Build Coastguard Worker       FuncletUnwindDest = nullptr;
183*9880d681SAndroid Build Coastguard Worker     else if (auto *CatchPad = dyn_cast<CatchPadInst>(FuncletPad))
184*9880d681SAndroid Build Coastguard Worker       FuncletUnwindDest = CatchPad->getCatchSwitch()->getUnwindDest();
185*9880d681SAndroid Build Coastguard Worker     else if (auto *CleanupPad = dyn_cast<CleanupPadInst>(FuncletPad))
186*9880d681SAndroid Build Coastguard Worker       FuncletUnwindDest = getCleanupRetUnwindDest(CleanupPad);
187*9880d681SAndroid Build Coastguard Worker     else
188*9880d681SAndroid Build Coastguard Worker       llvm_unreachable("unexpected funclet pad!");
189*9880d681SAndroid Build Coastguard Worker 
190*9880d681SAndroid Build Coastguard Worker     BasicBlock *InvokeUnwindDest = II->getUnwindDest();
191*9880d681SAndroid Build Coastguard Worker     int BaseState = -1;
192*9880d681SAndroid Build Coastguard Worker     if (FuncletUnwindDest == InvokeUnwindDest) {
193*9880d681SAndroid Build Coastguard Worker       auto BaseStateI = FuncInfo.FuncletBaseStateMap.find(FuncletPad);
194*9880d681SAndroid Build Coastguard Worker       if (BaseStateI != FuncInfo.FuncletBaseStateMap.end())
195*9880d681SAndroid Build Coastguard Worker         BaseState = BaseStateI->second;
196*9880d681SAndroid Build Coastguard Worker     }
197*9880d681SAndroid Build Coastguard Worker 
198*9880d681SAndroid Build Coastguard Worker     if (BaseState != -1) {
199*9880d681SAndroid Build Coastguard Worker       FuncInfo.InvokeStateMap[II] = BaseState;
200*9880d681SAndroid Build Coastguard Worker     } else {
201*9880d681SAndroid Build Coastguard Worker       Instruction *PadInst = InvokeUnwindDest->getFirstNonPHI();
202*9880d681SAndroid Build Coastguard Worker       assert(FuncInfo.EHPadStateMap.count(PadInst) && "EH Pad has no state!");
203*9880d681SAndroid Build Coastguard Worker       FuncInfo.InvokeStateMap[II] = FuncInfo.EHPadStateMap[PadInst];
204*9880d681SAndroid Build Coastguard Worker     }
205*9880d681SAndroid Build Coastguard Worker   }
206*9880d681SAndroid Build Coastguard Worker }
207*9880d681SAndroid Build Coastguard Worker 
208*9880d681SAndroid Build Coastguard Worker // Given BB which ends in an unwind edge, return the EHPad that this BB belongs
209*9880d681SAndroid Build Coastguard Worker // to. If the unwind edge came from an invoke, return null.
getEHPadFromPredecessor(const BasicBlock * BB,Value * ParentPad)210*9880d681SAndroid Build Coastguard Worker static const BasicBlock *getEHPadFromPredecessor(const BasicBlock *BB,
211*9880d681SAndroid Build Coastguard Worker                                                  Value *ParentPad) {
212*9880d681SAndroid Build Coastguard Worker   const TerminatorInst *TI = BB->getTerminator();
213*9880d681SAndroid Build Coastguard Worker   if (isa<InvokeInst>(TI))
214*9880d681SAndroid Build Coastguard Worker     return nullptr;
215*9880d681SAndroid Build Coastguard Worker   if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(TI)) {
216*9880d681SAndroid Build Coastguard Worker     if (CatchSwitch->getParentPad() != ParentPad)
217*9880d681SAndroid Build Coastguard Worker       return nullptr;
218*9880d681SAndroid Build Coastguard Worker     return BB;
219*9880d681SAndroid Build Coastguard Worker   }
220*9880d681SAndroid Build Coastguard Worker   assert(!TI->isEHPad() && "unexpected EHPad!");
221*9880d681SAndroid Build Coastguard Worker   auto *CleanupPad = cast<CleanupReturnInst>(TI)->getCleanupPad();
222*9880d681SAndroid Build Coastguard Worker   if (CleanupPad->getParentPad() != ParentPad)
223*9880d681SAndroid Build Coastguard Worker     return nullptr;
224*9880d681SAndroid Build Coastguard Worker   return CleanupPad->getParent();
225*9880d681SAndroid Build Coastguard Worker }
226*9880d681SAndroid Build Coastguard Worker 
calculateCXXStateNumbers(WinEHFuncInfo & FuncInfo,const Instruction * FirstNonPHI,int ParentState)227*9880d681SAndroid Build Coastguard Worker static void calculateCXXStateNumbers(WinEHFuncInfo &FuncInfo,
228*9880d681SAndroid Build Coastguard Worker                                      const Instruction *FirstNonPHI,
229*9880d681SAndroid Build Coastguard Worker                                      int ParentState) {
230*9880d681SAndroid Build Coastguard Worker   const BasicBlock *BB = FirstNonPHI->getParent();
231*9880d681SAndroid Build Coastguard Worker   assert(BB->isEHPad() && "not a funclet!");
232*9880d681SAndroid Build Coastguard Worker 
233*9880d681SAndroid Build Coastguard Worker   if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(FirstNonPHI)) {
234*9880d681SAndroid Build Coastguard Worker     assert(FuncInfo.EHPadStateMap.count(CatchSwitch) == 0 &&
235*9880d681SAndroid Build Coastguard Worker            "shouldn't revist catch funclets!");
236*9880d681SAndroid Build Coastguard Worker 
237*9880d681SAndroid Build Coastguard Worker     SmallVector<const CatchPadInst *, 2> Handlers;
238*9880d681SAndroid Build Coastguard Worker     for (const BasicBlock *CatchPadBB : CatchSwitch->handlers()) {
239*9880d681SAndroid Build Coastguard Worker       auto *CatchPad = cast<CatchPadInst>(CatchPadBB->getFirstNonPHI());
240*9880d681SAndroid Build Coastguard Worker       Handlers.push_back(CatchPad);
241*9880d681SAndroid Build Coastguard Worker     }
242*9880d681SAndroid Build Coastguard Worker     int TryLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr);
243*9880d681SAndroid Build Coastguard Worker     FuncInfo.EHPadStateMap[CatchSwitch] = TryLow;
244*9880d681SAndroid Build Coastguard Worker     for (const BasicBlock *PredBlock : predecessors(BB))
245*9880d681SAndroid Build Coastguard Worker       if ((PredBlock = getEHPadFromPredecessor(PredBlock,
246*9880d681SAndroid Build Coastguard Worker                                                CatchSwitch->getParentPad())))
247*9880d681SAndroid Build Coastguard Worker         calculateCXXStateNumbers(FuncInfo, PredBlock->getFirstNonPHI(),
248*9880d681SAndroid Build Coastguard Worker                                  TryLow);
249*9880d681SAndroid Build Coastguard Worker     int CatchLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr);
250*9880d681SAndroid Build Coastguard Worker 
251*9880d681SAndroid Build Coastguard Worker     // catchpads are separate funclets in C++ EH due to the way rethrow works.
252*9880d681SAndroid Build Coastguard Worker     int TryHigh = CatchLow - 1;
253*9880d681SAndroid Build Coastguard Worker     for (const auto *CatchPad : Handlers) {
254*9880d681SAndroid Build Coastguard Worker       FuncInfo.FuncletBaseStateMap[CatchPad] = CatchLow;
255*9880d681SAndroid Build Coastguard Worker       for (const User *U : CatchPad->users()) {
256*9880d681SAndroid Build Coastguard Worker         const auto *UserI = cast<Instruction>(U);
257*9880d681SAndroid Build Coastguard Worker         if (auto *InnerCatchSwitch = dyn_cast<CatchSwitchInst>(UserI)) {
258*9880d681SAndroid Build Coastguard Worker           BasicBlock *UnwindDest = InnerCatchSwitch->getUnwindDest();
259*9880d681SAndroid Build Coastguard Worker           if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest())
260*9880d681SAndroid Build Coastguard Worker             calculateCXXStateNumbers(FuncInfo, UserI, CatchLow);
261*9880d681SAndroid Build Coastguard Worker         }
262*9880d681SAndroid Build Coastguard Worker         if (auto *InnerCleanupPad = dyn_cast<CleanupPadInst>(UserI)) {
263*9880d681SAndroid Build Coastguard Worker           BasicBlock *UnwindDest = getCleanupRetUnwindDest(InnerCleanupPad);
264*9880d681SAndroid Build Coastguard Worker           // If a nested cleanup pad reports a null unwind destination and the
265*9880d681SAndroid Build Coastguard Worker           // enclosing catch pad doesn't it must be post-dominated by an
266*9880d681SAndroid Build Coastguard Worker           // unreachable instruction.
267*9880d681SAndroid Build Coastguard Worker           if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest())
268*9880d681SAndroid Build Coastguard Worker             calculateCXXStateNumbers(FuncInfo, UserI, CatchLow);
269*9880d681SAndroid Build Coastguard Worker         }
270*9880d681SAndroid Build Coastguard Worker       }
271*9880d681SAndroid Build Coastguard Worker     }
272*9880d681SAndroid Build Coastguard Worker     int CatchHigh = FuncInfo.getLastStateNumber();
273*9880d681SAndroid Build Coastguard Worker     addTryBlockMapEntry(FuncInfo, TryLow, TryHigh, CatchHigh, Handlers);
274*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << "TryLow[" << BB->getName() << "]: " << TryLow << '\n');
275*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << "TryHigh[" << BB->getName() << "]: " << TryHigh << '\n');
276*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << "CatchHigh[" << BB->getName() << "]: " << CatchHigh
277*9880d681SAndroid Build Coastguard Worker                  << '\n');
278*9880d681SAndroid Build Coastguard Worker   } else {
279*9880d681SAndroid Build Coastguard Worker     auto *CleanupPad = cast<CleanupPadInst>(FirstNonPHI);
280*9880d681SAndroid Build Coastguard Worker 
281*9880d681SAndroid Build Coastguard Worker     // It's possible for a cleanup to be visited twice: it might have multiple
282*9880d681SAndroid Build Coastguard Worker     // cleanupret instructions.
283*9880d681SAndroid Build Coastguard Worker     if (FuncInfo.EHPadStateMap.count(CleanupPad))
284*9880d681SAndroid Build Coastguard Worker       return;
285*9880d681SAndroid Build Coastguard Worker 
286*9880d681SAndroid Build Coastguard Worker     int CleanupState = addUnwindMapEntry(FuncInfo, ParentState, BB);
287*9880d681SAndroid Build Coastguard Worker     FuncInfo.EHPadStateMap[CleanupPad] = CleanupState;
288*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << "Assigning state #" << CleanupState << " to BB "
289*9880d681SAndroid Build Coastguard Worker                  << BB->getName() << '\n');
290*9880d681SAndroid Build Coastguard Worker     for (const BasicBlock *PredBlock : predecessors(BB)) {
291*9880d681SAndroid Build Coastguard Worker       if ((PredBlock = getEHPadFromPredecessor(PredBlock,
292*9880d681SAndroid Build Coastguard Worker                                                CleanupPad->getParentPad()))) {
293*9880d681SAndroid Build Coastguard Worker         calculateCXXStateNumbers(FuncInfo, PredBlock->getFirstNonPHI(),
294*9880d681SAndroid Build Coastguard Worker                                  CleanupState);
295*9880d681SAndroid Build Coastguard Worker       }
296*9880d681SAndroid Build Coastguard Worker     }
297*9880d681SAndroid Build Coastguard Worker     for (const User *U : CleanupPad->users()) {
298*9880d681SAndroid Build Coastguard Worker       const auto *UserI = cast<Instruction>(U);
299*9880d681SAndroid Build Coastguard Worker       if (UserI->isEHPad())
300*9880d681SAndroid Build Coastguard Worker         report_fatal_error("Cleanup funclets for the MSVC++ personality cannot "
301*9880d681SAndroid Build Coastguard Worker                            "contain exceptional actions");
302*9880d681SAndroid Build Coastguard Worker     }
303*9880d681SAndroid Build Coastguard Worker   }
304*9880d681SAndroid Build Coastguard Worker }
305*9880d681SAndroid Build Coastguard Worker 
addSEHExcept(WinEHFuncInfo & FuncInfo,int ParentState,const Function * Filter,const BasicBlock * Handler)306*9880d681SAndroid Build Coastguard Worker static int addSEHExcept(WinEHFuncInfo &FuncInfo, int ParentState,
307*9880d681SAndroid Build Coastguard Worker                         const Function *Filter, const BasicBlock *Handler) {
308*9880d681SAndroid Build Coastguard Worker   SEHUnwindMapEntry Entry;
309*9880d681SAndroid Build Coastguard Worker   Entry.ToState = ParentState;
310*9880d681SAndroid Build Coastguard Worker   Entry.IsFinally = false;
311*9880d681SAndroid Build Coastguard Worker   Entry.Filter = Filter;
312*9880d681SAndroid Build Coastguard Worker   Entry.Handler = Handler;
313*9880d681SAndroid Build Coastguard Worker   FuncInfo.SEHUnwindMap.push_back(Entry);
314*9880d681SAndroid Build Coastguard Worker   return FuncInfo.SEHUnwindMap.size() - 1;
315*9880d681SAndroid Build Coastguard Worker }
316*9880d681SAndroid Build Coastguard Worker 
addSEHFinally(WinEHFuncInfo & FuncInfo,int ParentState,const BasicBlock * Handler)317*9880d681SAndroid Build Coastguard Worker static int addSEHFinally(WinEHFuncInfo &FuncInfo, int ParentState,
318*9880d681SAndroid Build Coastguard Worker                          const BasicBlock *Handler) {
319*9880d681SAndroid Build Coastguard Worker   SEHUnwindMapEntry Entry;
320*9880d681SAndroid Build Coastguard Worker   Entry.ToState = ParentState;
321*9880d681SAndroid Build Coastguard Worker   Entry.IsFinally = true;
322*9880d681SAndroid Build Coastguard Worker   Entry.Filter = nullptr;
323*9880d681SAndroid Build Coastguard Worker   Entry.Handler = Handler;
324*9880d681SAndroid Build Coastguard Worker   FuncInfo.SEHUnwindMap.push_back(Entry);
325*9880d681SAndroid Build Coastguard Worker   return FuncInfo.SEHUnwindMap.size() - 1;
326*9880d681SAndroid Build Coastguard Worker }
327*9880d681SAndroid Build Coastguard Worker 
calculateSEHStateNumbers(WinEHFuncInfo & FuncInfo,const Instruction * FirstNonPHI,int ParentState)328*9880d681SAndroid Build Coastguard Worker static void calculateSEHStateNumbers(WinEHFuncInfo &FuncInfo,
329*9880d681SAndroid Build Coastguard Worker                                      const Instruction *FirstNonPHI,
330*9880d681SAndroid Build Coastguard Worker                                      int ParentState) {
331*9880d681SAndroid Build Coastguard Worker   const BasicBlock *BB = FirstNonPHI->getParent();
332*9880d681SAndroid Build Coastguard Worker   assert(BB->isEHPad() && "no a funclet!");
333*9880d681SAndroid Build Coastguard Worker 
334*9880d681SAndroid Build Coastguard Worker   if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(FirstNonPHI)) {
335*9880d681SAndroid Build Coastguard Worker     assert(FuncInfo.EHPadStateMap.count(CatchSwitch) == 0 &&
336*9880d681SAndroid Build Coastguard Worker            "shouldn't revist catch funclets!");
337*9880d681SAndroid Build Coastguard Worker 
338*9880d681SAndroid Build Coastguard Worker     // Extract the filter function and the __except basic block and create a
339*9880d681SAndroid Build Coastguard Worker     // state for them.
340*9880d681SAndroid Build Coastguard Worker     assert(CatchSwitch->getNumHandlers() == 1 &&
341*9880d681SAndroid Build Coastguard Worker            "SEH doesn't have multiple handlers per __try");
342*9880d681SAndroid Build Coastguard Worker     const auto *CatchPad =
343*9880d681SAndroid Build Coastguard Worker         cast<CatchPadInst>((*CatchSwitch->handler_begin())->getFirstNonPHI());
344*9880d681SAndroid Build Coastguard Worker     const BasicBlock *CatchPadBB = CatchPad->getParent();
345*9880d681SAndroid Build Coastguard Worker     const Constant *FilterOrNull =
346*9880d681SAndroid Build Coastguard Worker         cast<Constant>(CatchPad->getArgOperand(0)->stripPointerCasts());
347*9880d681SAndroid Build Coastguard Worker     const Function *Filter = dyn_cast<Function>(FilterOrNull);
348*9880d681SAndroid Build Coastguard Worker     assert((Filter || FilterOrNull->isNullValue()) &&
349*9880d681SAndroid Build Coastguard Worker            "unexpected filter value");
350*9880d681SAndroid Build Coastguard Worker     int TryState = addSEHExcept(FuncInfo, ParentState, Filter, CatchPadBB);
351*9880d681SAndroid Build Coastguard Worker 
352*9880d681SAndroid Build Coastguard Worker     // Everything in the __try block uses TryState as its parent state.
353*9880d681SAndroid Build Coastguard Worker     FuncInfo.EHPadStateMap[CatchSwitch] = TryState;
354*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << "Assigning state #" << TryState << " to BB "
355*9880d681SAndroid Build Coastguard Worker                  << CatchPadBB->getName() << '\n');
356*9880d681SAndroid Build Coastguard Worker     for (const BasicBlock *PredBlock : predecessors(BB))
357*9880d681SAndroid Build Coastguard Worker       if ((PredBlock = getEHPadFromPredecessor(PredBlock,
358*9880d681SAndroid Build Coastguard Worker                                                CatchSwitch->getParentPad())))
359*9880d681SAndroid Build Coastguard Worker         calculateSEHStateNumbers(FuncInfo, PredBlock->getFirstNonPHI(),
360*9880d681SAndroid Build Coastguard Worker                                  TryState);
361*9880d681SAndroid Build Coastguard Worker 
362*9880d681SAndroid Build Coastguard Worker     // Everything in the __except block unwinds to ParentState, just like code
363*9880d681SAndroid Build Coastguard Worker     // outside the __try.
364*9880d681SAndroid Build Coastguard Worker     for (const User *U : CatchPad->users()) {
365*9880d681SAndroid Build Coastguard Worker       const auto *UserI = cast<Instruction>(U);
366*9880d681SAndroid Build Coastguard Worker       if (auto *InnerCatchSwitch = dyn_cast<CatchSwitchInst>(UserI)) {
367*9880d681SAndroid Build Coastguard Worker         BasicBlock *UnwindDest = InnerCatchSwitch->getUnwindDest();
368*9880d681SAndroid Build Coastguard Worker         if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest())
369*9880d681SAndroid Build Coastguard Worker           calculateSEHStateNumbers(FuncInfo, UserI, ParentState);
370*9880d681SAndroid Build Coastguard Worker       }
371*9880d681SAndroid Build Coastguard Worker       if (auto *InnerCleanupPad = dyn_cast<CleanupPadInst>(UserI)) {
372*9880d681SAndroid Build Coastguard Worker         BasicBlock *UnwindDest = getCleanupRetUnwindDest(InnerCleanupPad);
373*9880d681SAndroid Build Coastguard Worker         // If a nested cleanup pad reports a null unwind destination and the
374*9880d681SAndroid Build Coastguard Worker         // enclosing catch pad doesn't it must be post-dominated by an
375*9880d681SAndroid Build Coastguard Worker         // unreachable instruction.
376*9880d681SAndroid Build Coastguard Worker         if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest())
377*9880d681SAndroid Build Coastguard Worker           calculateSEHStateNumbers(FuncInfo, UserI, ParentState);
378*9880d681SAndroid Build Coastguard Worker       }
379*9880d681SAndroid Build Coastguard Worker     }
380*9880d681SAndroid Build Coastguard Worker   } else {
381*9880d681SAndroid Build Coastguard Worker     auto *CleanupPad = cast<CleanupPadInst>(FirstNonPHI);
382*9880d681SAndroid Build Coastguard Worker 
383*9880d681SAndroid Build Coastguard Worker     // It's possible for a cleanup to be visited twice: it might have multiple
384*9880d681SAndroid Build Coastguard Worker     // cleanupret instructions.
385*9880d681SAndroid Build Coastguard Worker     if (FuncInfo.EHPadStateMap.count(CleanupPad))
386*9880d681SAndroid Build Coastguard Worker       return;
387*9880d681SAndroid Build Coastguard Worker 
388*9880d681SAndroid Build Coastguard Worker     int CleanupState = addSEHFinally(FuncInfo, ParentState, BB);
389*9880d681SAndroid Build Coastguard Worker     FuncInfo.EHPadStateMap[CleanupPad] = CleanupState;
390*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << "Assigning state #" << CleanupState << " to BB "
391*9880d681SAndroid Build Coastguard Worker                  << BB->getName() << '\n');
392*9880d681SAndroid Build Coastguard Worker     for (const BasicBlock *PredBlock : predecessors(BB))
393*9880d681SAndroid Build Coastguard Worker       if ((PredBlock =
394*9880d681SAndroid Build Coastguard Worker                getEHPadFromPredecessor(PredBlock, CleanupPad->getParentPad())))
395*9880d681SAndroid Build Coastguard Worker         calculateSEHStateNumbers(FuncInfo, PredBlock->getFirstNonPHI(),
396*9880d681SAndroid Build Coastguard Worker                                  CleanupState);
397*9880d681SAndroid Build Coastguard Worker     for (const User *U : CleanupPad->users()) {
398*9880d681SAndroid Build Coastguard Worker       const auto *UserI = cast<Instruction>(U);
399*9880d681SAndroid Build Coastguard Worker       if (UserI->isEHPad())
400*9880d681SAndroid Build Coastguard Worker         report_fatal_error("Cleanup funclets for the SEH personality cannot "
401*9880d681SAndroid Build Coastguard Worker                            "contain exceptional actions");
402*9880d681SAndroid Build Coastguard Worker     }
403*9880d681SAndroid Build Coastguard Worker   }
404*9880d681SAndroid Build Coastguard Worker }
405*9880d681SAndroid Build Coastguard Worker 
isTopLevelPadForMSVC(const Instruction * EHPad)406*9880d681SAndroid Build Coastguard Worker static bool isTopLevelPadForMSVC(const Instruction *EHPad) {
407*9880d681SAndroid Build Coastguard Worker   if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(EHPad))
408*9880d681SAndroid Build Coastguard Worker     return isa<ConstantTokenNone>(CatchSwitch->getParentPad()) &&
409*9880d681SAndroid Build Coastguard Worker            CatchSwitch->unwindsToCaller();
410*9880d681SAndroid Build Coastguard Worker   if (auto *CleanupPad = dyn_cast<CleanupPadInst>(EHPad))
411*9880d681SAndroid Build Coastguard Worker     return isa<ConstantTokenNone>(CleanupPad->getParentPad()) &&
412*9880d681SAndroid Build Coastguard Worker            getCleanupRetUnwindDest(CleanupPad) == nullptr;
413*9880d681SAndroid Build Coastguard Worker   if (isa<CatchPadInst>(EHPad))
414*9880d681SAndroid Build Coastguard Worker     return false;
415*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("unexpected EHPad!");
416*9880d681SAndroid Build Coastguard Worker }
417*9880d681SAndroid Build Coastguard Worker 
calculateSEHStateNumbers(const Function * Fn,WinEHFuncInfo & FuncInfo)418*9880d681SAndroid Build Coastguard Worker void llvm::calculateSEHStateNumbers(const Function *Fn,
419*9880d681SAndroid Build Coastguard Worker                                     WinEHFuncInfo &FuncInfo) {
420*9880d681SAndroid Build Coastguard Worker   // Don't compute state numbers twice.
421*9880d681SAndroid Build Coastguard Worker   if (!FuncInfo.SEHUnwindMap.empty())
422*9880d681SAndroid Build Coastguard Worker     return;
423*9880d681SAndroid Build Coastguard Worker 
424*9880d681SAndroid Build Coastguard Worker   for (const BasicBlock &BB : *Fn) {
425*9880d681SAndroid Build Coastguard Worker     if (!BB.isEHPad())
426*9880d681SAndroid Build Coastguard Worker       continue;
427*9880d681SAndroid Build Coastguard Worker     const Instruction *FirstNonPHI = BB.getFirstNonPHI();
428*9880d681SAndroid Build Coastguard Worker     if (!isTopLevelPadForMSVC(FirstNonPHI))
429*9880d681SAndroid Build Coastguard Worker       continue;
430*9880d681SAndroid Build Coastguard Worker     ::calculateSEHStateNumbers(FuncInfo, FirstNonPHI, -1);
431*9880d681SAndroid Build Coastguard Worker   }
432*9880d681SAndroid Build Coastguard Worker 
433*9880d681SAndroid Build Coastguard Worker   calculateStateNumbersForInvokes(Fn, FuncInfo);
434*9880d681SAndroid Build Coastguard Worker }
435*9880d681SAndroid Build Coastguard Worker 
calculateWinCXXEHStateNumbers(const Function * Fn,WinEHFuncInfo & FuncInfo)436*9880d681SAndroid Build Coastguard Worker void llvm::calculateWinCXXEHStateNumbers(const Function *Fn,
437*9880d681SAndroid Build Coastguard Worker                                          WinEHFuncInfo &FuncInfo) {
438*9880d681SAndroid Build Coastguard Worker   // Return if it's already been done.
439*9880d681SAndroid Build Coastguard Worker   if (!FuncInfo.EHPadStateMap.empty())
440*9880d681SAndroid Build Coastguard Worker     return;
441*9880d681SAndroid Build Coastguard Worker 
442*9880d681SAndroid Build Coastguard Worker   for (const BasicBlock &BB : *Fn) {
443*9880d681SAndroid Build Coastguard Worker     if (!BB.isEHPad())
444*9880d681SAndroid Build Coastguard Worker       continue;
445*9880d681SAndroid Build Coastguard Worker     const Instruction *FirstNonPHI = BB.getFirstNonPHI();
446*9880d681SAndroid Build Coastguard Worker     if (!isTopLevelPadForMSVC(FirstNonPHI))
447*9880d681SAndroid Build Coastguard Worker       continue;
448*9880d681SAndroid Build Coastguard Worker     calculateCXXStateNumbers(FuncInfo, FirstNonPHI, -1);
449*9880d681SAndroid Build Coastguard Worker   }
450*9880d681SAndroid Build Coastguard Worker 
451*9880d681SAndroid Build Coastguard Worker   calculateStateNumbersForInvokes(Fn, FuncInfo);
452*9880d681SAndroid Build Coastguard Worker }
453*9880d681SAndroid Build Coastguard Worker 
addClrEHHandler(WinEHFuncInfo & FuncInfo,int HandlerParentState,int TryParentState,ClrHandlerType HandlerType,uint32_t TypeToken,const BasicBlock * Handler)454*9880d681SAndroid Build Coastguard Worker static int addClrEHHandler(WinEHFuncInfo &FuncInfo, int HandlerParentState,
455*9880d681SAndroid Build Coastguard Worker                            int TryParentState, ClrHandlerType HandlerType,
456*9880d681SAndroid Build Coastguard Worker                            uint32_t TypeToken, const BasicBlock *Handler) {
457*9880d681SAndroid Build Coastguard Worker   ClrEHUnwindMapEntry Entry;
458*9880d681SAndroid Build Coastguard Worker   Entry.HandlerParentState = HandlerParentState;
459*9880d681SAndroid Build Coastguard Worker   Entry.TryParentState = TryParentState;
460*9880d681SAndroid Build Coastguard Worker   Entry.Handler = Handler;
461*9880d681SAndroid Build Coastguard Worker   Entry.HandlerType = HandlerType;
462*9880d681SAndroid Build Coastguard Worker   Entry.TypeToken = TypeToken;
463*9880d681SAndroid Build Coastguard Worker   FuncInfo.ClrEHUnwindMap.push_back(Entry);
464*9880d681SAndroid Build Coastguard Worker   return FuncInfo.ClrEHUnwindMap.size() - 1;
465*9880d681SAndroid Build Coastguard Worker }
466*9880d681SAndroid Build Coastguard Worker 
calculateClrEHStateNumbers(const Function * Fn,WinEHFuncInfo & FuncInfo)467*9880d681SAndroid Build Coastguard Worker void llvm::calculateClrEHStateNumbers(const Function *Fn,
468*9880d681SAndroid Build Coastguard Worker                                       WinEHFuncInfo &FuncInfo) {
469*9880d681SAndroid Build Coastguard Worker   // Return if it's already been done.
470*9880d681SAndroid Build Coastguard Worker   if (!FuncInfo.EHPadStateMap.empty())
471*9880d681SAndroid Build Coastguard Worker     return;
472*9880d681SAndroid Build Coastguard Worker 
473*9880d681SAndroid Build Coastguard Worker   // This numbering assigns one state number to each catchpad and cleanuppad.
474*9880d681SAndroid Build Coastguard Worker   // It also computes two tree-like relations over states:
475*9880d681SAndroid Build Coastguard Worker   // 1) Each state has a "HandlerParentState", which is the state of the next
476*9880d681SAndroid Build Coastguard Worker   //    outer handler enclosing this state's handler (same as nearest ancestor
477*9880d681SAndroid Build Coastguard Worker   //    per the ParentPad linkage on EH pads, but skipping over catchswitches).
478*9880d681SAndroid Build Coastguard Worker   // 2) Each state has a "TryParentState", which:
479*9880d681SAndroid Build Coastguard Worker   //    a) for a catchpad that's not the last handler on its catchswitch, is
480*9880d681SAndroid Build Coastguard Worker   //       the state of the next catchpad on that catchswitch
481*9880d681SAndroid Build Coastguard Worker   //    b) for all other pads, is the state of the pad whose try region is the
482*9880d681SAndroid Build Coastguard Worker   //       next outer try region enclosing this state's try region.  The "try
483*9880d681SAndroid Build Coastguard Worker   //       regions are not present as such in the IR, but will be inferred
484*9880d681SAndroid Build Coastguard Worker   //       based on the placement of invokes and pads which reach each other
485*9880d681SAndroid Build Coastguard Worker   //       by exceptional exits
486*9880d681SAndroid Build Coastguard Worker   // Catchswitches do not get their own states, but each gets mapped to the
487*9880d681SAndroid Build Coastguard Worker   // state of its first catchpad.
488*9880d681SAndroid Build Coastguard Worker 
489*9880d681SAndroid Build Coastguard Worker   // Step one: walk down from outermost to innermost funclets, assigning each
490*9880d681SAndroid Build Coastguard Worker   // catchpad and cleanuppad a state number.  Add an entry to the
491*9880d681SAndroid Build Coastguard Worker   // ClrEHUnwindMap for each state, recording its HandlerParentState and
492*9880d681SAndroid Build Coastguard Worker   // handler attributes.  Record the TryParentState as well for each catchpad
493*9880d681SAndroid Build Coastguard Worker   // that's not the last on its catchswitch, but initialize all other entries'
494*9880d681SAndroid Build Coastguard Worker   // TryParentStates to a sentinel -1 value that the next pass will update.
495*9880d681SAndroid Build Coastguard Worker 
496*9880d681SAndroid Build Coastguard Worker   // Seed a worklist with pads that have no parent.
497*9880d681SAndroid Build Coastguard Worker   SmallVector<std::pair<const Instruction *, int>, 8> Worklist;
498*9880d681SAndroid Build Coastguard Worker   for (const BasicBlock &BB : *Fn) {
499*9880d681SAndroid Build Coastguard Worker     const Instruction *FirstNonPHI = BB.getFirstNonPHI();
500*9880d681SAndroid Build Coastguard Worker     const Value *ParentPad;
501*9880d681SAndroid Build Coastguard Worker     if (const auto *CPI = dyn_cast<CleanupPadInst>(FirstNonPHI))
502*9880d681SAndroid Build Coastguard Worker       ParentPad = CPI->getParentPad();
503*9880d681SAndroid Build Coastguard Worker     else if (const auto *CSI = dyn_cast<CatchSwitchInst>(FirstNonPHI))
504*9880d681SAndroid Build Coastguard Worker       ParentPad = CSI->getParentPad();
505*9880d681SAndroid Build Coastguard Worker     else
506*9880d681SAndroid Build Coastguard Worker       continue;
507*9880d681SAndroid Build Coastguard Worker     if (isa<ConstantTokenNone>(ParentPad))
508*9880d681SAndroid Build Coastguard Worker       Worklist.emplace_back(FirstNonPHI, -1);
509*9880d681SAndroid Build Coastguard Worker   }
510*9880d681SAndroid Build Coastguard Worker 
511*9880d681SAndroid Build Coastguard Worker   // Use the worklist to visit all pads, from outer to inner.  Record
512*9880d681SAndroid Build Coastguard Worker   // HandlerParentState for all pads.  Record TryParentState only for catchpads
513*9880d681SAndroid Build Coastguard Worker   // that aren't the last on their catchswitch (setting all other entries'
514*9880d681SAndroid Build Coastguard Worker   // TryParentStates to an initial value of -1).  This loop is also responsible
515*9880d681SAndroid Build Coastguard Worker   // for setting the EHPadStateMap entry for all catchpads, cleanuppads, and
516*9880d681SAndroid Build Coastguard Worker   // catchswitches.
517*9880d681SAndroid Build Coastguard Worker   while (!Worklist.empty()) {
518*9880d681SAndroid Build Coastguard Worker     const Instruction *Pad;
519*9880d681SAndroid Build Coastguard Worker     int HandlerParentState;
520*9880d681SAndroid Build Coastguard Worker     std::tie(Pad, HandlerParentState) = Worklist.pop_back_val();
521*9880d681SAndroid Build Coastguard Worker 
522*9880d681SAndroid Build Coastguard Worker     if (const auto *Cleanup = dyn_cast<CleanupPadInst>(Pad)) {
523*9880d681SAndroid Build Coastguard Worker       // Create the entry for this cleanup with the appropriate handler
524*9880d681SAndroid Build Coastguard Worker       // properties.  Finaly and fault handlers are distinguished by arity.
525*9880d681SAndroid Build Coastguard Worker       ClrHandlerType HandlerType =
526*9880d681SAndroid Build Coastguard Worker           (Cleanup->getNumArgOperands() ? ClrHandlerType::Fault
527*9880d681SAndroid Build Coastguard Worker                                         : ClrHandlerType::Finally);
528*9880d681SAndroid Build Coastguard Worker       int CleanupState = addClrEHHandler(FuncInfo, HandlerParentState, -1,
529*9880d681SAndroid Build Coastguard Worker                                          HandlerType, 0, Pad->getParent());
530*9880d681SAndroid Build Coastguard Worker       // Queue any child EH pads on the worklist.
531*9880d681SAndroid Build Coastguard Worker       for (const User *U : Cleanup->users())
532*9880d681SAndroid Build Coastguard Worker         if (const auto *I = dyn_cast<Instruction>(U))
533*9880d681SAndroid Build Coastguard Worker           if (I->isEHPad())
534*9880d681SAndroid Build Coastguard Worker             Worklist.emplace_back(I, CleanupState);
535*9880d681SAndroid Build Coastguard Worker       // Remember this pad's state.
536*9880d681SAndroid Build Coastguard Worker       FuncInfo.EHPadStateMap[Cleanup] = CleanupState;
537*9880d681SAndroid Build Coastguard Worker     } else {
538*9880d681SAndroid Build Coastguard Worker       // Walk the handlers of this catchswitch in reverse order since all but
539*9880d681SAndroid Build Coastguard Worker       // the last need to set the following one as its TryParentState.
540*9880d681SAndroid Build Coastguard Worker       const auto *CatchSwitch = cast<CatchSwitchInst>(Pad);
541*9880d681SAndroid Build Coastguard Worker       int CatchState = -1, FollowerState = -1;
542*9880d681SAndroid Build Coastguard Worker       SmallVector<const BasicBlock *, 4> CatchBlocks(CatchSwitch->handlers());
543*9880d681SAndroid Build Coastguard Worker       for (auto CBI = CatchBlocks.rbegin(), CBE = CatchBlocks.rend();
544*9880d681SAndroid Build Coastguard Worker            CBI != CBE; ++CBI, FollowerState = CatchState) {
545*9880d681SAndroid Build Coastguard Worker         const BasicBlock *CatchBlock = *CBI;
546*9880d681SAndroid Build Coastguard Worker         // Create the entry for this catch with the appropriate handler
547*9880d681SAndroid Build Coastguard Worker         // properties.
548*9880d681SAndroid Build Coastguard Worker         const auto *Catch = cast<CatchPadInst>(CatchBlock->getFirstNonPHI());
549*9880d681SAndroid Build Coastguard Worker         uint32_t TypeToken = static_cast<uint32_t>(
550*9880d681SAndroid Build Coastguard Worker             cast<ConstantInt>(Catch->getArgOperand(0))->getZExtValue());
551*9880d681SAndroid Build Coastguard Worker         CatchState =
552*9880d681SAndroid Build Coastguard Worker             addClrEHHandler(FuncInfo, HandlerParentState, FollowerState,
553*9880d681SAndroid Build Coastguard Worker                             ClrHandlerType::Catch, TypeToken, CatchBlock);
554*9880d681SAndroid Build Coastguard Worker         // Queue any child EH pads on the worklist.
555*9880d681SAndroid Build Coastguard Worker         for (const User *U : Catch->users())
556*9880d681SAndroid Build Coastguard Worker           if (const auto *I = dyn_cast<Instruction>(U))
557*9880d681SAndroid Build Coastguard Worker             if (I->isEHPad())
558*9880d681SAndroid Build Coastguard Worker               Worklist.emplace_back(I, CatchState);
559*9880d681SAndroid Build Coastguard Worker         // Remember this catch's state.
560*9880d681SAndroid Build Coastguard Worker         FuncInfo.EHPadStateMap[Catch] = CatchState;
561*9880d681SAndroid Build Coastguard Worker       }
562*9880d681SAndroid Build Coastguard Worker       // Associate the catchswitch with the state of its first catch.
563*9880d681SAndroid Build Coastguard Worker       assert(CatchSwitch->getNumHandlers());
564*9880d681SAndroid Build Coastguard Worker       FuncInfo.EHPadStateMap[CatchSwitch] = CatchState;
565*9880d681SAndroid Build Coastguard Worker     }
566*9880d681SAndroid Build Coastguard Worker   }
567*9880d681SAndroid Build Coastguard Worker 
568*9880d681SAndroid Build Coastguard Worker   // Step two: record the TryParentState of each state.  For cleanuppads that
569*9880d681SAndroid Build Coastguard Worker   // don't have cleanuprets, we may need to infer this from their child pads,
570*9880d681SAndroid Build Coastguard Worker   // so visit pads in descendant-most to ancestor-most order.
571*9880d681SAndroid Build Coastguard Worker   for (auto Entry = FuncInfo.ClrEHUnwindMap.rbegin(),
572*9880d681SAndroid Build Coastguard Worker             End = FuncInfo.ClrEHUnwindMap.rend();
573*9880d681SAndroid Build Coastguard Worker        Entry != End; ++Entry) {
574*9880d681SAndroid Build Coastguard Worker     const Instruction *Pad =
575*9880d681SAndroid Build Coastguard Worker         Entry->Handler.get<const BasicBlock *>()->getFirstNonPHI();
576*9880d681SAndroid Build Coastguard Worker     // For most pads, the TryParentState is the state associated with the
577*9880d681SAndroid Build Coastguard Worker     // unwind dest of exceptional exits from it.
578*9880d681SAndroid Build Coastguard Worker     const BasicBlock *UnwindDest;
579*9880d681SAndroid Build Coastguard Worker     if (const auto *Catch = dyn_cast<CatchPadInst>(Pad)) {
580*9880d681SAndroid Build Coastguard Worker       // If a catch is not the last in its catchswitch, its TryParentState is
581*9880d681SAndroid Build Coastguard Worker       // the state associated with the next catch in the switch, even though
582*9880d681SAndroid Build Coastguard Worker       // that's not the unwind dest of exceptions escaping the catch.  Those
583*9880d681SAndroid Build Coastguard Worker       // cases were already assigned a TryParentState in the first pass, so
584*9880d681SAndroid Build Coastguard Worker       // skip them.
585*9880d681SAndroid Build Coastguard Worker       if (Entry->TryParentState != -1)
586*9880d681SAndroid Build Coastguard Worker         continue;
587*9880d681SAndroid Build Coastguard Worker       // Otherwise, get the unwind dest from the catchswitch.
588*9880d681SAndroid Build Coastguard Worker       UnwindDest = Catch->getCatchSwitch()->getUnwindDest();
589*9880d681SAndroid Build Coastguard Worker     } else {
590*9880d681SAndroid Build Coastguard Worker       const auto *Cleanup = cast<CleanupPadInst>(Pad);
591*9880d681SAndroid Build Coastguard Worker       UnwindDest = nullptr;
592*9880d681SAndroid Build Coastguard Worker       for (const User *U : Cleanup->users()) {
593*9880d681SAndroid Build Coastguard Worker         if (auto *CleanupRet = dyn_cast<CleanupReturnInst>(U)) {
594*9880d681SAndroid Build Coastguard Worker           // Common and unambiguous case -- cleanupret indicates cleanup's
595*9880d681SAndroid Build Coastguard Worker           // unwind dest.
596*9880d681SAndroid Build Coastguard Worker           UnwindDest = CleanupRet->getUnwindDest();
597*9880d681SAndroid Build Coastguard Worker           break;
598*9880d681SAndroid Build Coastguard Worker         }
599*9880d681SAndroid Build Coastguard Worker 
600*9880d681SAndroid Build Coastguard Worker         // Get an unwind dest for the user
601*9880d681SAndroid Build Coastguard Worker         const BasicBlock *UserUnwindDest = nullptr;
602*9880d681SAndroid Build Coastguard Worker         if (auto *Invoke = dyn_cast<InvokeInst>(U)) {
603*9880d681SAndroid Build Coastguard Worker           UserUnwindDest = Invoke->getUnwindDest();
604*9880d681SAndroid Build Coastguard Worker         } else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(U)) {
605*9880d681SAndroid Build Coastguard Worker           UserUnwindDest = CatchSwitch->getUnwindDest();
606*9880d681SAndroid Build Coastguard Worker         } else if (auto *ChildCleanup = dyn_cast<CleanupPadInst>(U)) {
607*9880d681SAndroid Build Coastguard Worker           int UserState = FuncInfo.EHPadStateMap[ChildCleanup];
608*9880d681SAndroid Build Coastguard Worker           int UserUnwindState =
609*9880d681SAndroid Build Coastguard Worker               FuncInfo.ClrEHUnwindMap[UserState].TryParentState;
610*9880d681SAndroid Build Coastguard Worker           if (UserUnwindState != -1)
611*9880d681SAndroid Build Coastguard Worker             UserUnwindDest = FuncInfo.ClrEHUnwindMap[UserUnwindState]
612*9880d681SAndroid Build Coastguard Worker                                  .Handler.get<const BasicBlock *>();
613*9880d681SAndroid Build Coastguard Worker         }
614*9880d681SAndroid Build Coastguard Worker 
615*9880d681SAndroid Build Coastguard Worker         // Not having an unwind dest for this user might indicate that it
616*9880d681SAndroid Build Coastguard Worker         // doesn't unwind, so can't be taken as proof that the cleanup itself
617*9880d681SAndroid Build Coastguard Worker         // may unwind to caller (see e.g. SimplifyUnreachable and
618*9880d681SAndroid Build Coastguard Worker         // RemoveUnwindEdge).
619*9880d681SAndroid Build Coastguard Worker         if (!UserUnwindDest)
620*9880d681SAndroid Build Coastguard Worker           continue;
621*9880d681SAndroid Build Coastguard Worker 
622*9880d681SAndroid Build Coastguard Worker         // Now we have an unwind dest for the user, but we need to see if it
623*9880d681SAndroid Build Coastguard Worker         // unwinds all the way out of the cleanup or if it stays within it.
624*9880d681SAndroid Build Coastguard Worker         const Instruction *UserUnwindPad = UserUnwindDest->getFirstNonPHI();
625*9880d681SAndroid Build Coastguard Worker         const Value *UserUnwindParent;
626*9880d681SAndroid Build Coastguard Worker         if (auto *CSI = dyn_cast<CatchSwitchInst>(UserUnwindPad))
627*9880d681SAndroid Build Coastguard Worker           UserUnwindParent = CSI->getParentPad();
628*9880d681SAndroid Build Coastguard Worker         else
629*9880d681SAndroid Build Coastguard Worker           UserUnwindParent =
630*9880d681SAndroid Build Coastguard Worker               cast<CleanupPadInst>(UserUnwindPad)->getParentPad();
631*9880d681SAndroid Build Coastguard Worker 
632*9880d681SAndroid Build Coastguard Worker         // The unwind stays within the cleanup iff it targets a child of the
633*9880d681SAndroid Build Coastguard Worker         // cleanup.
634*9880d681SAndroid Build Coastguard Worker         if (UserUnwindParent == Cleanup)
635*9880d681SAndroid Build Coastguard Worker           continue;
636*9880d681SAndroid Build Coastguard Worker 
637*9880d681SAndroid Build Coastguard Worker         // This unwind exits the cleanup, so its dest is the cleanup's dest.
638*9880d681SAndroid Build Coastguard Worker         UnwindDest = UserUnwindDest;
639*9880d681SAndroid Build Coastguard Worker         break;
640*9880d681SAndroid Build Coastguard Worker       }
641*9880d681SAndroid Build Coastguard Worker     }
642*9880d681SAndroid Build Coastguard Worker 
643*9880d681SAndroid Build Coastguard Worker     // Record the state of the unwind dest as the TryParentState.
644*9880d681SAndroid Build Coastguard Worker     int UnwindDestState;
645*9880d681SAndroid Build Coastguard Worker 
646*9880d681SAndroid Build Coastguard Worker     // If UnwindDest is null at this point, either the pad in question can
647*9880d681SAndroid Build Coastguard Worker     // be exited by unwind to caller, or it cannot be exited by unwind.  In
648*9880d681SAndroid Build Coastguard Worker     // either case, reporting such cases as unwinding to caller is correct.
649*9880d681SAndroid Build Coastguard Worker     // This can lead to EH tables that "look strange" -- if this pad's is in
650*9880d681SAndroid Build Coastguard Worker     // a parent funclet which has other children that do unwind to an enclosing
651*9880d681SAndroid Build Coastguard Worker     // pad, the try region for this pad will be missing the "duplicate" EH
652*9880d681SAndroid Build Coastguard Worker     // clause entries that you'd expect to see covering the whole parent.  That
653*9880d681SAndroid Build Coastguard Worker     // should be benign, since the unwind never actually happens.  If it were
654*9880d681SAndroid Build Coastguard Worker     // an issue, we could add a subsequent pass that pushes unwind dests down
655*9880d681SAndroid Build Coastguard Worker     // from parents that have them to children that appear to unwind to caller.
656*9880d681SAndroid Build Coastguard Worker     if (!UnwindDest) {
657*9880d681SAndroid Build Coastguard Worker       UnwindDestState = -1;
658*9880d681SAndroid Build Coastguard Worker     } else {
659*9880d681SAndroid Build Coastguard Worker       UnwindDestState = FuncInfo.EHPadStateMap[UnwindDest->getFirstNonPHI()];
660*9880d681SAndroid Build Coastguard Worker     }
661*9880d681SAndroid Build Coastguard Worker 
662*9880d681SAndroid Build Coastguard Worker     Entry->TryParentState = UnwindDestState;
663*9880d681SAndroid Build Coastguard Worker   }
664*9880d681SAndroid Build Coastguard Worker 
665*9880d681SAndroid Build Coastguard Worker   // Step three: transfer information from pads to invokes.
666*9880d681SAndroid Build Coastguard Worker   calculateStateNumbersForInvokes(Fn, FuncInfo);
667*9880d681SAndroid Build Coastguard Worker }
668*9880d681SAndroid Build Coastguard Worker 
colorFunclets(Function & F)669*9880d681SAndroid Build Coastguard Worker void WinEHPrepare::colorFunclets(Function &F) {
670*9880d681SAndroid Build Coastguard Worker   BlockColors = colorEHFunclets(F);
671*9880d681SAndroid Build Coastguard Worker 
672*9880d681SAndroid Build Coastguard Worker   // Invert the map from BB to colors to color to BBs.
673*9880d681SAndroid Build Coastguard Worker   for (BasicBlock &BB : F) {
674*9880d681SAndroid Build Coastguard Worker     ColorVector &Colors = BlockColors[&BB];
675*9880d681SAndroid Build Coastguard Worker     for (BasicBlock *Color : Colors)
676*9880d681SAndroid Build Coastguard Worker       FuncletBlocks[Color].push_back(&BB);
677*9880d681SAndroid Build Coastguard Worker   }
678*9880d681SAndroid Build Coastguard Worker }
679*9880d681SAndroid Build Coastguard Worker 
demotePHIsOnFunclets(Function & F)680*9880d681SAndroid Build Coastguard Worker void WinEHPrepare::demotePHIsOnFunclets(Function &F) {
681*9880d681SAndroid Build Coastguard Worker   // Strip PHI nodes off of EH pads.
682*9880d681SAndroid Build Coastguard Worker   SmallVector<PHINode *, 16> PHINodes;
683*9880d681SAndroid Build Coastguard Worker   for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE;) {
684*9880d681SAndroid Build Coastguard Worker     BasicBlock *BB = &*FI++;
685*9880d681SAndroid Build Coastguard Worker     if (!BB->isEHPad())
686*9880d681SAndroid Build Coastguard Worker       continue;
687*9880d681SAndroid Build Coastguard Worker     for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE;) {
688*9880d681SAndroid Build Coastguard Worker       Instruction *I = &*BI++;
689*9880d681SAndroid Build Coastguard Worker       auto *PN = dyn_cast<PHINode>(I);
690*9880d681SAndroid Build Coastguard Worker       // Stop at the first non-PHI.
691*9880d681SAndroid Build Coastguard Worker       if (!PN)
692*9880d681SAndroid Build Coastguard Worker         break;
693*9880d681SAndroid Build Coastguard Worker 
694*9880d681SAndroid Build Coastguard Worker       AllocaInst *SpillSlot = insertPHILoads(PN, F);
695*9880d681SAndroid Build Coastguard Worker       if (SpillSlot)
696*9880d681SAndroid Build Coastguard Worker         insertPHIStores(PN, SpillSlot);
697*9880d681SAndroid Build Coastguard Worker 
698*9880d681SAndroid Build Coastguard Worker       PHINodes.push_back(PN);
699*9880d681SAndroid Build Coastguard Worker     }
700*9880d681SAndroid Build Coastguard Worker   }
701*9880d681SAndroid Build Coastguard Worker 
702*9880d681SAndroid Build Coastguard Worker   for (auto *PN : PHINodes) {
703*9880d681SAndroid Build Coastguard Worker     // There may be lingering uses on other EH PHIs being removed
704*9880d681SAndroid Build Coastguard Worker     PN->replaceAllUsesWith(UndefValue::get(PN->getType()));
705*9880d681SAndroid Build Coastguard Worker     PN->eraseFromParent();
706*9880d681SAndroid Build Coastguard Worker   }
707*9880d681SAndroid Build Coastguard Worker }
708*9880d681SAndroid Build Coastguard Worker 
cloneCommonBlocks(Function & F)709*9880d681SAndroid Build Coastguard Worker void WinEHPrepare::cloneCommonBlocks(Function &F) {
710*9880d681SAndroid Build Coastguard Worker   // We need to clone all blocks which belong to multiple funclets.  Values are
711*9880d681SAndroid Build Coastguard Worker   // remapped throughout the funclet to propogate both the new instructions
712*9880d681SAndroid Build Coastguard Worker   // *and* the new basic blocks themselves.
713*9880d681SAndroid Build Coastguard Worker   for (auto &Funclets : FuncletBlocks) {
714*9880d681SAndroid Build Coastguard Worker     BasicBlock *FuncletPadBB = Funclets.first;
715*9880d681SAndroid Build Coastguard Worker     std::vector<BasicBlock *> &BlocksInFunclet = Funclets.second;
716*9880d681SAndroid Build Coastguard Worker     Value *FuncletToken;
717*9880d681SAndroid Build Coastguard Worker     if (FuncletPadBB == &F.getEntryBlock())
718*9880d681SAndroid Build Coastguard Worker       FuncletToken = ConstantTokenNone::get(F.getContext());
719*9880d681SAndroid Build Coastguard Worker     else
720*9880d681SAndroid Build Coastguard Worker       FuncletToken = FuncletPadBB->getFirstNonPHI();
721*9880d681SAndroid Build Coastguard Worker 
722*9880d681SAndroid Build Coastguard Worker     std::vector<std::pair<BasicBlock *, BasicBlock *>> Orig2Clone;
723*9880d681SAndroid Build Coastguard Worker     ValueToValueMapTy VMap;
724*9880d681SAndroid Build Coastguard Worker     for (BasicBlock *BB : BlocksInFunclet) {
725*9880d681SAndroid Build Coastguard Worker       ColorVector &ColorsForBB = BlockColors[BB];
726*9880d681SAndroid Build Coastguard Worker       // We don't need to do anything if the block is monochromatic.
727*9880d681SAndroid Build Coastguard Worker       size_t NumColorsForBB = ColorsForBB.size();
728*9880d681SAndroid Build Coastguard Worker       if (NumColorsForBB == 1)
729*9880d681SAndroid Build Coastguard Worker         continue;
730*9880d681SAndroid Build Coastguard Worker 
731*9880d681SAndroid Build Coastguard Worker       DEBUG_WITH_TYPE("winehprepare-coloring",
732*9880d681SAndroid Build Coastguard Worker                       dbgs() << "  Cloning block \'" << BB->getName()
733*9880d681SAndroid Build Coastguard Worker                               << "\' for funclet \'" << FuncletPadBB->getName()
734*9880d681SAndroid Build Coastguard Worker                               << "\'.\n");
735*9880d681SAndroid Build Coastguard Worker 
736*9880d681SAndroid Build Coastguard Worker       // Create a new basic block and copy instructions into it!
737*9880d681SAndroid Build Coastguard Worker       BasicBlock *CBB =
738*9880d681SAndroid Build Coastguard Worker           CloneBasicBlock(BB, VMap, Twine(".for.", FuncletPadBB->getName()));
739*9880d681SAndroid Build Coastguard Worker       // Insert the clone immediately after the original to ensure determinism
740*9880d681SAndroid Build Coastguard Worker       // and to keep the same relative ordering of any funclet's blocks.
741*9880d681SAndroid Build Coastguard Worker       CBB->insertInto(&F, BB->getNextNode());
742*9880d681SAndroid Build Coastguard Worker 
743*9880d681SAndroid Build Coastguard Worker       // Add basic block mapping.
744*9880d681SAndroid Build Coastguard Worker       VMap[BB] = CBB;
745*9880d681SAndroid Build Coastguard Worker 
746*9880d681SAndroid Build Coastguard Worker       // Record delta operations that we need to perform to our color mappings.
747*9880d681SAndroid Build Coastguard Worker       Orig2Clone.emplace_back(BB, CBB);
748*9880d681SAndroid Build Coastguard Worker     }
749*9880d681SAndroid Build Coastguard Worker 
750*9880d681SAndroid Build Coastguard Worker     // If nothing was cloned, we're done cloning in this funclet.
751*9880d681SAndroid Build Coastguard Worker     if (Orig2Clone.empty())
752*9880d681SAndroid Build Coastguard Worker       continue;
753*9880d681SAndroid Build Coastguard Worker 
754*9880d681SAndroid Build Coastguard Worker     // Update our color mappings to reflect that one block has lost a color and
755*9880d681SAndroid Build Coastguard Worker     // another has gained a color.
756*9880d681SAndroid Build Coastguard Worker     for (auto &BBMapping : Orig2Clone) {
757*9880d681SAndroid Build Coastguard Worker       BasicBlock *OldBlock = BBMapping.first;
758*9880d681SAndroid Build Coastguard Worker       BasicBlock *NewBlock = BBMapping.second;
759*9880d681SAndroid Build Coastguard Worker 
760*9880d681SAndroid Build Coastguard Worker       BlocksInFunclet.push_back(NewBlock);
761*9880d681SAndroid Build Coastguard Worker       ColorVector &NewColors = BlockColors[NewBlock];
762*9880d681SAndroid Build Coastguard Worker       assert(NewColors.empty() && "A new block should only have one color!");
763*9880d681SAndroid Build Coastguard Worker       NewColors.push_back(FuncletPadBB);
764*9880d681SAndroid Build Coastguard Worker 
765*9880d681SAndroid Build Coastguard Worker       DEBUG_WITH_TYPE("winehprepare-coloring",
766*9880d681SAndroid Build Coastguard Worker                       dbgs() << "  Assigned color \'" << FuncletPadBB->getName()
767*9880d681SAndroid Build Coastguard Worker                               << "\' to block \'" << NewBlock->getName()
768*9880d681SAndroid Build Coastguard Worker                               << "\'.\n");
769*9880d681SAndroid Build Coastguard Worker 
770*9880d681SAndroid Build Coastguard Worker       BlocksInFunclet.erase(
771*9880d681SAndroid Build Coastguard Worker           std::remove(BlocksInFunclet.begin(), BlocksInFunclet.end(), OldBlock),
772*9880d681SAndroid Build Coastguard Worker           BlocksInFunclet.end());
773*9880d681SAndroid Build Coastguard Worker       ColorVector &OldColors = BlockColors[OldBlock];
774*9880d681SAndroid Build Coastguard Worker       OldColors.erase(
775*9880d681SAndroid Build Coastguard Worker           std::remove(OldColors.begin(), OldColors.end(), FuncletPadBB),
776*9880d681SAndroid Build Coastguard Worker           OldColors.end());
777*9880d681SAndroid Build Coastguard Worker 
778*9880d681SAndroid Build Coastguard Worker       DEBUG_WITH_TYPE("winehprepare-coloring",
779*9880d681SAndroid Build Coastguard Worker                       dbgs() << "  Removed color \'" << FuncletPadBB->getName()
780*9880d681SAndroid Build Coastguard Worker                               << "\' from block \'" << OldBlock->getName()
781*9880d681SAndroid Build Coastguard Worker                               << "\'.\n");
782*9880d681SAndroid Build Coastguard Worker     }
783*9880d681SAndroid Build Coastguard Worker 
784*9880d681SAndroid Build Coastguard Worker     // Loop over all of the instructions in this funclet, fixing up operand
785*9880d681SAndroid Build Coastguard Worker     // references as we go.  This uses VMap to do all the hard work.
786*9880d681SAndroid Build Coastguard Worker     for (BasicBlock *BB : BlocksInFunclet)
787*9880d681SAndroid Build Coastguard Worker       // Loop over all instructions, fixing each one as we find it...
788*9880d681SAndroid Build Coastguard Worker       for (Instruction &I : *BB)
789*9880d681SAndroid Build Coastguard Worker         RemapInstruction(&I, VMap,
790*9880d681SAndroid Build Coastguard Worker                          RF_IgnoreMissingLocals | RF_NoModuleLevelChanges);
791*9880d681SAndroid Build Coastguard Worker 
792*9880d681SAndroid Build Coastguard Worker     // Catchrets targeting cloned blocks need to be updated separately from
793*9880d681SAndroid Build Coastguard Worker     // the loop above because they are not in the current funclet.
794*9880d681SAndroid Build Coastguard Worker     SmallVector<CatchReturnInst *, 2> FixupCatchrets;
795*9880d681SAndroid Build Coastguard Worker     for (auto &BBMapping : Orig2Clone) {
796*9880d681SAndroid Build Coastguard Worker       BasicBlock *OldBlock = BBMapping.first;
797*9880d681SAndroid Build Coastguard Worker       BasicBlock *NewBlock = BBMapping.second;
798*9880d681SAndroid Build Coastguard Worker 
799*9880d681SAndroid Build Coastguard Worker       FixupCatchrets.clear();
800*9880d681SAndroid Build Coastguard Worker       for (BasicBlock *Pred : predecessors(OldBlock))
801*9880d681SAndroid Build Coastguard Worker         if (auto *CatchRet = dyn_cast<CatchReturnInst>(Pred->getTerminator()))
802*9880d681SAndroid Build Coastguard Worker           if (CatchRet->getCatchSwitchParentPad() == FuncletToken)
803*9880d681SAndroid Build Coastguard Worker             FixupCatchrets.push_back(CatchRet);
804*9880d681SAndroid Build Coastguard Worker 
805*9880d681SAndroid Build Coastguard Worker       for (CatchReturnInst *CatchRet : FixupCatchrets)
806*9880d681SAndroid Build Coastguard Worker         CatchRet->setSuccessor(NewBlock);
807*9880d681SAndroid Build Coastguard Worker     }
808*9880d681SAndroid Build Coastguard Worker 
809*9880d681SAndroid Build Coastguard Worker     auto UpdatePHIOnClonedBlock = [&](PHINode *PN, bool IsForOldBlock) {
810*9880d681SAndroid Build Coastguard Worker       unsigned NumPreds = PN->getNumIncomingValues();
811*9880d681SAndroid Build Coastguard Worker       for (unsigned PredIdx = 0, PredEnd = NumPreds; PredIdx != PredEnd;
812*9880d681SAndroid Build Coastguard Worker            ++PredIdx) {
813*9880d681SAndroid Build Coastguard Worker         BasicBlock *IncomingBlock = PN->getIncomingBlock(PredIdx);
814*9880d681SAndroid Build Coastguard Worker         bool EdgeTargetsFunclet;
815*9880d681SAndroid Build Coastguard Worker         if (auto *CRI =
816*9880d681SAndroid Build Coastguard Worker                 dyn_cast<CatchReturnInst>(IncomingBlock->getTerminator())) {
817*9880d681SAndroid Build Coastguard Worker           EdgeTargetsFunclet = (CRI->getCatchSwitchParentPad() == FuncletToken);
818*9880d681SAndroid Build Coastguard Worker         } else {
819*9880d681SAndroid Build Coastguard Worker           ColorVector &IncomingColors = BlockColors[IncomingBlock];
820*9880d681SAndroid Build Coastguard Worker           assert(!IncomingColors.empty() && "Block not colored!");
821*9880d681SAndroid Build Coastguard Worker           assert((IncomingColors.size() == 1 ||
822*9880d681SAndroid Build Coastguard Worker                   llvm::all_of(IncomingColors,
823*9880d681SAndroid Build Coastguard Worker                                [&](BasicBlock *Color) {
824*9880d681SAndroid Build Coastguard Worker                                  return Color != FuncletPadBB;
825*9880d681SAndroid Build Coastguard Worker                                })) &&
826*9880d681SAndroid Build Coastguard Worker                  "Cloning should leave this funclet's blocks monochromatic");
827*9880d681SAndroid Build Coastguard Worker           EdgeTargetsFunclet = (IncomingColors.front() == FuncletPadBB);
828*9880d681SAndroid Build Coastguard Worker         }
829*9880d681SAndroid Build Coastguard Worker         if (IsForOldBlock != EdgeTargetsFunclet)
830*9880d681SAndroid Build Coastguard Worker           continue;
831*9880d681SAndroid Build Coastguard Worker         PN->removeIncomingValue(IncomingBlock, /*DeletePHIIfEmpty=*/false);
832*9880d681SAndroid Build Coastguard Worker         // Revisit the next entry.
833*9880d681SAndroid Build Coastguard Worker         --PredIdx;
834*9880d681SAndroid Build Coastguard Worker         --PredEnd;
835*9880d681SAndroid Build Coastguard Worker       }
836*9880d681SAndroid Build Coastguard Worker     };
837*9880d681SAndroid Build Coastguard Worker 
838*9880d681SAndroid Build Coastguard Worker     for (auto &BBMapping : Orig2Clone) {
839*9880d681SAndroid Build Coastguard Worker       BasicBlock *OldBlock = BBMapping.first;
840*9880d681SAndroid Build Coastguard Worker       BasicBlock *NewBlock = BBMapping.second;
841*9880d681SAndroid Build Coastguard Worker       for (Instruction &OldI : *OldBlock) {
842*9880d681SAndroid Build Coastguard Worker         auto *OldPN = dyn_cast<PHINode>(&OldI);
843*9880d681SAndroid Build Coastguard Worker         if (!OldPN)
844*9880d681SAndroid Build Coastguard Worker           break;
845*9880d681SAndroid Build Coastguard Worker         UpdatePHIOnClonedBlock(OldPN, /*IsForOldBlock=*/true);
846*9880d681SAndroid Build Coastguard Worker       }
847*9880d681SAndroid Build Coastguard Worker       for (Instruction &NewI : *NewBlock) {
848*9880d681SAndroid Build Coastguard Worker         auto *NewPN = dyn_cast<PHINode>(&NewI);
849*9880d681SAndroid Build Coastguard Worker         if (!NewPN)
850*9880d681SAndroid Build Coastguard Worker           break;
851*9880d681SAndroid Build Coastguard Worker         UpdatePHIOnClonedBlock(NewPN, /*IsForOldBlock=*/false);
852*9880d681SAndroid Build Coastguard Worker       }
853*9880d681SAndroid Build Coastguard Worker     }
854*9880d681SAndroid Build Coastguard Worker 
855*9880d681SAndroid Build Coastguard Worker     // Check to see if SuccBB has PHI nodes. If so, we need to add entries to
856*9880d681SAndroid Build Coastguard Worker     // the PHI nodes for NewBB now.
857*9880d681SAndroid Build Coastguard Worker     for (auto &BBMapping : Orig2Clone) {
858*9880d681SAndroid Build Coastguard Worker       BasicBlock *OldBlock = BBMapping.first;
859*9880d681SAndroid Build Coastguard Worker       BasicBlock *NewBlock = BBMapping.second;
860*9880d681SAndroid Build Coastguard Worker       for (BasicBlock *SuccBB : successors(NewBlock)) {
861*9880d681SAndroid Build Coastguard Worker         for (Instruction &SuccI : *SuccBB) {
862*9880d681SAndroid Build Coastguard Worker           auto *SuccPN = dyn_cast<PHINode>(&SuccI);
863*9880d681SAndroid Build Coastguard Worker           if (!SuccPN)
864*9880d681SAndroid Build Coastguard Worker             break;
865*9880d681SAndroid Build Coastguard Worker 
866*9880d681SAndroid Build Coastguard Worker           // Ok, we have a PHI node.  Figure out what the incoming value was for
867*9880d681SAndroid Build Coastguard Worker           // the OldBlock.
868*9880d681SAndroid Build Coastguard Worker           int OldBlockIdx = SuccPN->getBasicBlockIndex(OldBlock);
869*9880d681SAndroid Build Coastguard Worker           if (OldBlockIdx == -1)
870*9880d681SAndroid Build Coastguard Worker             break;
871*9880d681SAndroid Build Coastguard Worker           Value *IV = SuccPN->getIncomingValue(OldBlockIdx);
872*9880d681SAndroid Build Coastguard Worker 
873*9880d681SAndroid Build Coastguard Worker           // Remap the value if necessary.
874*9880d681SAndroid Build Coastguard Worker           if (auto *Inst = dyn_cast<Instruction>(IV)) {
875*9880d681SAndroid Build Coastguard Worker             ValueToValueMapTy::iterator I = VMap.find(Inst);
876*9880d681SAndroid Build Coastguard Worker             if (I != VMap.end())
877*9880d681SAndroid Build Coastguard Worker               IV = I->second;
878*9880d681SAndroid Build Coastguard Worker           }
879*9880d681SAndroid Build Coastguard Worker 
880*9880d681SAndroid Build Coastguard Worker           SuccPN->addIncoming(IV, NewBlock);
881*9880d681SAndroid Build Coastguard Worker         }
882*9880d681SAndroid Build Coastguard Worker       }
883*9880d681SAndroid Build Coastguard Worker     }
884*9880d681SAndroid Build Coastguard Worker 
885*9880d681SAndroid Build Coastguard Worker     for (ValueToValueMapTy::value_type VT : VMap) {
886*9880d681SAndroid Build Coastguard Worker       // If there were values defined in BB that are used outside the funclet,
887*9880d681SAndroid Build Coastguard Worker       // then we now have to update all uses of the value to use either the
888*9880d681SAndroid Build Coastguard Worker       // original value, the cloned value, or some PHI derived value.  This can
889*9880d681SAndroid Build Coastguard Worker       // require arbitrary PHI insertion, of which we are prepared to do, clean
890*9880d681SAndroid Build Coastguard Worker       // these up now.
891*9880d681SAndroid Build Coastguard Worker       SmallVector<Use *, 16> UsesToRename;
892*9880d681SAndroid Build Coastguard Worker 
893*9880d681SAndroid Build Coastguard Worker       auto *OldI = dyn_cast<Instruction>(const_cast<Value *>(VT.first));
894*9880d681SAndroid Build Coastguard Worker       if (!OldI)
895*9880d681SAndroid Build Coastguard Worker         continue;
896*9880d681SAndroid Build Coastguard Worker       auto *NewI = cast<Instruction>(VT.second);
897*9880d681SAndroid Build Coastguard Worker       // Scan all uses of this instruction to see if it is used outside of its
898*9880d681SAndroid Build Coastguard Worker       // funclet, and if so, record them in UsesToRename.
899*9880d681SAndroid Build Coastguard Worker       for (Use &U : OldI->uses()) {
900*9880d681SAndroid Build Coastguard Worker         Instruction *UserI = cast<Instruction>(U.getUser());
901*9880d681SAndroid Build Coastguard Worker         BasicBlock *UserBB = UserI->getParent();
902*9880d681SAndroid Build Coastguard Worker         ColorVector &ColorsForUserBB = BlockColors[UserBB];
903*9880d681SAndroid Build Coastguard Worker         assert(!ColorsForUserBB.empty());
904*9880d681SAndroid Build Coastguard Worker         if (ColorsForUserBB.size() > 1 ||
905*9880d681SAndroid Build Coastguard Worker             *ColorsForUserBB.begin() != FuncletPadBB)
906*9880d681SAndroid Build Coastguard Worker           UsesToRename.push_back(&U);
907*9880d681SAndroid Build Coastguard Worker       }
908*9880d681SAndroid Build Coastguard Worker 
909*9880d681SAndroid Build Coastguard Worker       // If there are no uses outside the block, we're done with this
910*9880d681SAndroid Build Coastguard Worker       // instruction.
911*9880d681SAndroid Build Coastguard Worker       if (UsesToRename.empty())
912*9880d681SAndroid Build Coastguard Worker         continue;
913*9880d681SAndroid Build Coastguard Worker 
914*9880d681SAndroid Build Coastguard Worker       // We found a use of OldI outside of the funclet.  Rename all uses of OldI
915*9880d681SAndroid Build Coastguard Worker       // that are outside its funclet to be uses of the appropriate PHI node
916*9880d681SAndroid Build Coastguard Worker       // etc.
917*9880d681SAndroid Build Coastguard Worker       SSAUpdater SSAUpdate;
918*9880d681SAndroid Build Coastguard Worker       SSAUpdate.Initialize(OldI->getType(), OldI->getName());
919*9880d681SAndroid Build Coastguard Worker       SSAUpdate.AddAvailableValue(OldI->getParent(), OldI);
920*9880d681SAndroid Build Coastguard Worker       SSAUpdate.AddAvailableValue(NewI->getParent(), NewI);
921*9880d681SAndroid Build Coastguard Worker 
922*9880d681SAndroid Build Coastguard Worker       while (!UsesToRename.empty())
923*9880d681SAndroid Build Coastguard Worker         SSAUpdate.RewriteUseAfterInsertions(*UsesToRename.pop_back_val());
924*9880d681SAndroid Build Coastguard Worker     }
925*9880d681SAndroid Build Coastguard Worker   }
926*9880d681SAndroid Build Coastguard Worker }
927*9880d681SAndroid Build Coastguard Worker 
removeImplausibleInstructions(Function & F)928*9880d681SAndroid Build Coastguard Worker void WinEHPrepare::removeImplausibleInstructions(Function &F) {
929*9880d681SAndroid Build Coastguard Worker   // Remove implausible terminators and replace them with UnreachableInst.
930*9880d681SAndroid Build Coastguard Worker   for (auto &Funclet : FuncletBlocks) {
931*9880d681SAndroid Build Coastguard Worker     BasicBlock *FuncletPadBB = Funclet.first;
932*9880d681SAndroid Build Coastguard Worker     std::vector<BasicBlock *> &BlocksInFunclet = Funclet.second;
933*9880d681SAndroid Build Coastguard Worker     Instruction *FirstNonPHI = FuncletPadBB->getFirstNonPHI();
934*9880d681SAndroid Build Coastguard Worker     auto *FuncletPad = dyn_cast<FuncletPadInst>(FirstNonPHI);
935*9880d681SAndroid Build Coastguard Worker     auto *CatchPad = dyn_cast_or_null<CatchPadInst>(FuncletPad);
936*9880d681SAndroid Build Coastguard Worker     auto *CleanupPad = dyn_cast_or_null<CleanupPadInst>(FuncletPad);
937*9880d681SAndroid Build Coastguard Worker 
938*9880d681SAndroid Build Coastguard Worker     for (BasicBlock *BB : BlocksInFunclet) {
939*9880d681SAndroid Build Coastguard Worker       for (Instruction &I : *BB) {
940*9880d681SAndroid Build Coastguard Worker         CallSite CS(&I);
941*9880d681SAndroid Build Coastguard Worker         if (!CS)
942*9880d681SAndroid Build Coastguard Worker           continue;
943*9880d681SAndroid Build Coastguard Worker 
944*9880d681SAndroid Build Coastguard Worker         Value *FuncletBundleOperand = nullptr;
945*9880d681SAndroid Build Coastguard Worker         if (auto BU = CS.getOperandBundle(LLVMContext::OB_funclet))
946*9880d681SAndroid Build Coastguard Worker           FuncletBundleOperand = BU->Inputs.front();
947*9880d681SAndroid Build Coastguard Worker 
948*9880d681SAndroid Build Coastguard Worker         if (FuncletBundleOperand == FuncletPad)
949*9880d681SAndroid Build Coastguard Worker           continue;
950*9880d681SAndroid Build Coastguard Worker 
951*9880d681SAndroid Build Coastguard Worker         // Skip call sites which are nounwind intrinsics or inline asm.
952*9880d681SAndroid Build Coastguard Worker         auto *CalledFn =
953*9880d681SAndroid Build Coastguard Worker             dyn_cast<Function>(CS.getCalledValue()->stripPointerCasts());
954*9880d681SAndroid Build Coastguard Worker         if (CalledFn && ((CalledFn->isIntrinsic() && CS.doesNotThrow()) ||
955*9880d681SAndroid Build Coastguard Worker                          CS.isInlineAsm()))
956*9880d681SAndroid Build Coastguard Worker           continue;
957*9880d681SAndroid Build Coastguard Worker 
958*9880d681SAndroid Build Coastguard Worker         // This call site was not part of this funclet, remove it.
959*9880d681SAndroid Build Coastguard Worker         if (CS.isInvoke()) {
960*9880d681SAndroid Build Coastguard Worker           // Remove the unwind edge if it was an invoke.
961*9880d681SAndroid Build Coastguard Worker           removeUnwindEdge(BB);
962*9880d681SAndroid Build Coastguard Worker           // Get a pointer to the new call.
963*9880d681SAndroid Build Coastguard Worker           BasicBlock::iterator CallI =
964*9880d681SAndroid Build Coastguard Worker               std::prev(BB->getTerminator()->getIterator());
965*9880d681SAndroid Build Coastguard Worker           auto *CI = cast<CallInst>(&*CallI);
966*9880d681SAndroid Build Coastguard Worker           changeToUnreachable(CI, /*UseLLVMTrap=*/false);
967*9880d681SAndroid Build Coastguard Worker         } else {
968*9880d681SAndroid Build Coastguard Worker           changeToUnreachable(&I, /*UseLLVMTrap=*/false);
969*9880d681SAndroid Build Coastguard Worker         }
970*9880d681SAndroid Build Coastguard Worker 
971*9880d681SAndroid Build Coastguard Worker         // There are no more instructions in the block (except for unreachable),
972*9880d681SAndroid Build Coastguard Worker         // we are done.
973*9880d681SAndroid Build Coastguard Worker         break;
974*9880d681SAndroid Build Coastguard Worker       }
975*9880d681SAndroid Build Coastguard Worker 
976*9880d681SAndroid Build Coastguard Worker       TerminatorInst *TI = BB->getTerminator();
977*9880d681SAndroid Build Coastguard Worker       // CatchPadInst and CleanupPadInst can't transfer control to a ReturnInst.
978*9880d681SAndroid Build Coastguard Worker       bool IsUnreachableRet = isa<ReturnInst>(TI) && FuncletPad;
979*9880d681SAndroid Build Coastguard Worker       // The token consumed by a CatchReturnInst must match the funclet token.
980*9880d681SAndroid Build Coastguard Worker       bool IsUnreachableCatchret = false;
981*9880d681SAndroid Build Coastguard Worker       if (auto *CRI = dyn_cast<CatchReturnInst>(TI))
982*9880d681SAndroid Build Coastguard Worker         IsUnreachableCatchret = CRI->getCatchPad() != CatchPad;
983*9880d681SAndroid Build Coastguard Worker       // The token consumed by a CleanupReturnInst must match the funclet token.
984*9880d681SAndroid Build Coastguard Worker       bool IsUnreachableCleanupret = false;
985*9880d681SAndroid Build Coastguard Worker       if (auto *CRI = dyn_cast<CleanupReturnInst>(TI))
986*9880d681SAndroid Build Coastguard Worker         IsUnreachableCleanupret = CRI->getCleanupPad() != CleanupPad;
987*9880d681SAndroid Build Coastguard Worker       if (IsUnreachableRet || IsUnreachableCatchret ||
988*9880d681SAndroid Build Coastguard Worker           IsUnreachableCleanupret) {
989*9880d681SAndroid Build Coastguard Worker         changeToUnreachable(TI, /*UseLLVMTrap=*/false);
990*9880d681SAndroid Build Coastguard Worker       } else if (isa<InvokeInst>(TI)) {
991*9880d681SAndroid Build Coastguard Worker         if (Personality == EHPersonality::MSVC_CXX && CleanupPad) {
992*9880d681SAndroid Build Coastguard Worker           // Invokes within a cleanuppad for the MSVC++ personality never
993*9880d681SAndroid Build Coastguard Worker           // transfer control to their unwind edge: the personality will
994*9880d681SAndroid Build Coastguard Worker           // terminate the program.
995*9880d681SAndroid Build Coastguard Worker           removeUnwindEdge(BB);
996*9880d681SAndroid Build Coastguard Worker         }
997*9880d681SAndroid Build Coastguard Worker       }
998*9880d681SAndroid Build Coastguard Worker     }
999*9880d681SAndroid Build Coastguard Worker   }
1000*9880d681SAndroid Build Coastguard Worker }
1001*9880d681SAndroid Build Coastguard Worker 
cleanupPreparedFunclets(Function & F)1002*9880d681SAndroid Build Coastguard Worker void WinEHPrepare::cleanupPreparedFunclets(Function &F) {
1003*9880d681SAndroid Build Coastguard Worker   // Clean-up some of the mess we made by removing useles PHI nodes, trivial
1004*9880d681SAndroid Build Coastguard Worker   // branches, etc.
1005*9880d681SAndroid Build Coastguard Worker   for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE;) {
1006*9880d681SAndroid Build Coastguard Worker     BasicBlock *BB = &*FI++;
1007*9880d681SAndroid Build Coastguard Worker     SimplifyInstructionsInBlock(BB);
1008*9880d681SAndroid Build Coastguard Worker     ConstantFoldTerminator(BB, /*DeleteDeadConditions=*/true);
1009*9880d681SAndroid Build Coastguard Worker     MergeBlockIntoPredecessor(BB);
1010*9880d681SAndroid Build Coastguard Worker   }
1011*9880d681SAndroid Build Coastguard Worker 
1012*9880d681SAndroid Build Coastguard Worker   // We might have some unreachable blocks after cleaning up some impossible
1013*9880d681SAndroid Build Coastguard Worker   // control flow.
1014*9880d681SAndroid Build Coastguard Worker   removeUnreachableBlocks(F);
1015*9880d681SAndroid Build Coastguard Worker }
1016*9880d681SAndroid Build Coastguard Worker 
verifyPreparedFunclets(Function & F)1017*9880d681SAndroid Build Coastguard Worker void WinEHPrepare::verifyPreparedFunclets(Function &F) {
1018*9880d681SAndroid Build Coastguard Worker   for (BasicBlock &BB : F) {
1019*9880d681SAndroid Build Coastguard Worker     size_t NumColors = BlockColors[&BB].size();
1020*9880d681SAndroid Build Coastguard Worker     assert(NumColors == 1 && "Expected monochromatic BB!");
1021*9880d681SAndroid Build Coastguard Worker     if (NumColors == 0)
1022*9880d681SAndroid Build Coastguard Worker       report_fatal_error("Uncolored BB!");
1023*9880d681SAndroid Build Coastguard Worker     if (NumColors > 1)
1024*9880d681SAndroid Build Coastguard Worker       report_fatal_error("Multicolor BB!");
1025*9880d681SAndroid Build Coastguard Worker     assert((DisableDemotion || !(BB.isEHPad() && isa<PHINode>(BB.begin()))) &&
1026*9880d681SAndroid Build Coastguard Worker            "EH Pad still has a PHI!");
1027*9880d681SAndroid Build Coastguard Worker   }
1028*9880d681SAndroid Build Coastguard Worker }
1029*9880d681SAndroid Build Coastguard Worker 
prepareExplicitEH(Function & F)1030*9880d681SAndroid Build Coastguard Worker bool WinEHPrepare::prepareExplicitEH(Function &F) {
1031*9880d681SAndroid Build Coastguard Worker   // Remove unreachable blocks.  It is not valuable to assign them a color and
1032*9880d681SAndroid Build Coastguard Worker   // their existence can trick us into thinking values are alive when they are
1033*9880d681SAndroid Build Coastguard Worker   // not.
1034*9880d681SAndroid Build Coastguard Worker   removeUnreachableBlocks(F);
1035*9880d681SAndroid Build Coastguard Worker 
1036*9880d681SAndroid Build Coastguard Worker   // Determine which blocks are reachable from which funclet entries.
1037*9880d681SAndroid Build Coastguard Worker   colorFunclets(F);
1038*9880d681SAndroid Build Coastguard Worker 
1039*9880d681SAndroid Build Coastguard Worker   cloneCommonBlocks(F);
1040*9880d681SAndroid Build Coastguard Worker 
1041*9880d681SAndroid Build Coastguard Worker   if (!DisableDemotion)
1042*9880d681SAndroid Build Coastguard Worker     demotePHIsOnFunclets(F);
1043*9880d681SAndroid Build Coastguard Worker 
1044*9880d681SAndroid Build Coastguard Worker   if (!DisableCleanups) {
1045*9880d681SAndroid Build Coastguard Worker     DEBUG(verifyFunction(F));
1046*9880d681SAndroid Build Coastguard Worker     removeImplausibleInstructions(F);
1047*9880d681SAndroid Build Coastguard Worker 
1048*9880d681SAndroid Build Coastguard Worker     DEBUG(verifyFunction(F));
1049*9880d681SAndroid Build Coastguard Worker     cleanupPreparedFunclets(F);
1050*9880d681SAndroid Build Coastguard Worker   }
1051*9880d681SAndroid Build Coastguard Worker 
1052*9880d681SAndroid Build Coastguard Worker   DEBUG(verifyPreparedFunclets(F));
1053*9880d681SAndroid Build Coastguard Worker   // Recolor the CFG to verify that all is well.
1054*9880d681SAndroid Build Coastguard Worker   DEBUG(colorFunclets(F));
1055*9880d681SAndroid Build Coastguard Worker   DEBUG(verifyPreparedFunclets(F));
1056*9880d681SAndroid Build Coastguard Worker 
1057*9880d681SAndroid Build Coastguard Worker   BlockColors.clear();
1058*9880d681SAndroid Build Coastguard Worker   FuncletBlocks.clear();
1059*9880d681SAndroid Build Coastguard Worker 
1060*9880d681SAndroid Build Coastguard Worker   return true;
1061*9880d681SAndroid Build Coastguard Worker }
1062*9880d681SAndroid Build Coastguard Worker 
1063*9880d681SAndroid Build Coastguard Worker // TODO: Share loads when one use dominates another, or when a catchpad exit
1064*9880d681SAndroid Build Coastguard Worker // dominates uses (needs dominators).
insertPHILoads(PHINode * PN,Function & F)1065*9880d681SAndroid Build Coastguard Worker AllocaInst *WinEHPrepare::insertPHILoads(PHINode *PN, Function &F) {
1066*9880d681SAndroid Build Coastguard Worker   BasicBlock *PHIBlock = PN->getParent();
1067*9880d681SAndroid Build Coastguard Worker   AllocaInst *SpillSlot = nullptr;
1068*9880d681SAndroid Build Coastguard Worker   Instruction *EHPad = PHIBlock->getFirstNonPHI();
1069*9880d681SAndroid Build Coastguard Worker 
1070*9880d681SAndroid Build Coastguard Worker   if (!isa<TerminatorInst>(EHPad)) {
1071*9880d681SAndroid Build Coastguard Worker     // If the EHPad isn't a terminator, then we can insert a load in this block
1072*9880d681SAndroid Build Coastguard Worker     // that will dominate all uses.
1073*9880d681SAndroid Build Coastguard Worker     SpillSlot = new AllocaInst(PN->getType(), nullptr,
1074*9880d681SAndroid Build Coastguard Worker                                Twine(PN->getName(), ".wineh.spillslot"),
1075*9880d681SAndroid Build Coastguard Worker                                &F.getEntryBlock().front());
1076*9880d681SAndroid Build Coastguard Worker     Value *V = new LoadInst(SpillSlot, Twine(PN->getName(), ".wineh.reload"),
1077*9880d681SAndroid Build Coastguard Worker                             &*PHIBlock->getFirstInsertionPt());
1078*9880d681SAndroid Build Coastguard Worker     PN->replaceAllUsesWith(V);
1079*9880d681SAndroid Build Coastguard Worker     return SpillSlot;
1080*9880d681SAndroid Build Coastguard Worker   }
1081*9880d681SAndroid Build Coastguard Worker 
1082*9880d681SAndroid Build Coastguard Worker   // Otherwise, we have a PHI on a terminator EHPad, and we give up and insert
1083*9880d681SAndroid Build Coastguard Worker   // loads of the slot before every use.
1084*9880d681SAndroid Build Coastguard Worker   DenseMap<BasicBlock *, Value *> Loads;
1085*9880d681SAndroid Build Coastguard Worker   for (Value::use_iterator UI = PN->use_begin(), UE = PN->use_end();
1086*9880d681SAndroid Build Coastguard Worker        UI != UE;) {
1087*9880d681SAndroid Build Coastguard Worker     Use &U = *UI++;
1088*9880d681SAndroid Build Coastguard Worker     auto *UsingInst = cast<Instruction>(U.getUser());
1089*9880d681SAndroid Build Coastguard Worker     if (isa<PHINode>(UsingInst) && UsingInst->getParent()->isEHPad()) {
1090*9880d681SAndroid Build Coastguard Worker       // Use is on an EH pad phi.  Leave it alone; we'll insert loads and
1091*9880d681SAndroid Build Coastguard Worker       // stores for it separately.
1092*9880d681SAndroid Build Coastguard Worker       continue;
1093*9880d681SAndroid Build Coastguard Worker     }
1094*9880d681SAndroid Build Coastguard Worker     replaceUseWithLoad(PN, U, SpillSlot, Loads, F);
1095*9880d681SAndroid Build Coastguard Worker   }
1096*9880d681SAndroid Build Coastguard Worker   return SpillSlot;
1097*9880d681SAndroid Build Coastguard Worker }
1098*9880d681SAndroid Build Coastguard Worker 
1099*9880d681SAndroid Build Coastguard Worker // TODO: improve store placement.  Inserting at def is probably good, but need
1100*9880d681SAndroid Build Coastguard Worker // to be careful not to introduce interfering stores (needs liveness analysis).
1101*9880d681SAndroid Build Coastguard Worker // TODO: identify related phi nodes that can share spill slots, and share them
1102*9880d681SAndroid Build Coastguard Worker // (also needs liveness).
insertPHIStores(PHINode * OriginalPHI,AllocaInst * SpillSlot)1103*9880d681SAndroid Build Coastguard Worker void WinEHPrepare::insertPHIStores(PHINode *OriginalPHI,
1104*9880d681SAndroid Build Coastguard Worker                                    AllocaInst *SpillSlot) {
1105*9880d681SAndroid Build Coastguard Worker   // Use a worklist of (Block, Value) pairs -- the given Value needs to be
1106*9880d681SAndroid Build Coastguard Worker   // stored to the spill slot by the end of the given Block.
1107*9880d681SAndroid Build Coastguard Worker   SmallVector<std::pair<BasicBlock *, Value *>, 4> Worklist;
1108*9880d681SAndroid Build Coastguard Worker 
1109*9880d681SAndroid Build Coastguard Worker   Worklist.push_back({OriginalPHI->getParent(), OriginalPHI});
1110*9880d681SAndroid Build Coastguard Worker 
1111*9880d681SAndroid Build Coastguard Worker   while (!Worklist.empty()) {
1112*9880d681SAndroid Build Coastguard Worker     BasicBlock *EHBlock;
1113*9880d681SAndroid Build Coastguard Worker     Value *InVal;
1114*9880d681SAndroid Build Coastguard Worker     std::tie(EHBlock, InVal) = Worklist.pop_back_val();
1115*9880d681SAndroid Build Coastguard Worker 
1116*9880d681SAndroid Build Coastguard Worker     PHINode *PN = dyn_cast<PHINode>(InVal);
1117*9880d681SAndroid Build Coastguard Worker     if (PN && PN->getParent() == EHBlock) {
1118*9880d681SAndroid Build Coastguard Worker       // The value is defined by another PHI we need to remove, with no room to
1119*9880d681SAndroid Build Coastguard Worker       // insert a store after the PHI, so each predecessor needs to store its
1120*9880d681SAndroid Build Coastguard Worker       // incoming value.
1121*9880d681SAndroid Build Coastguard Worker       for (unsigned i = 0, e = PN->getNumIncomingValues(); i < e; ++i) {
1122*9880d681SAndroid Build Coastguard Worker         Value *PredVal = PN->getIncomingValue(i);
1123*9880d681SAndroid Build Coastguard Worker 
1124*9880d681SAndroid Build Coastguard Worker         // Undef can safely be skipped.
1125*9880d681SAndroid Build Coastguard Worker         if (isa<UndefValue>(PredVal))
1126*9880d681SAndroid Build Coastguard Worker           continue;
1127*9880d681SAndroid Build Coastguard Worker 
1128*9880d681SAndroid Build Coastguard Worker         insertPHIStore(PN->getIncomingBlock(i), PredVal, SpillSlot, Worklist);
1129*9880d681SAndroid Build Coastguard Worker       }
1130*9880d681SAndroid Build Coastguard Worker     } else {
1131*9880d681SAndroid Build Coastguard Worker       // We need to store InVal, which dominates EHBlock, but can't put a store
1132*9880d681SAndroid Build Coastguard Worker       // in EHBlock, so need to put stores in each predecessor.
1133*9880d681SAndroid Build Coastguard Worker       for (BasicBlock *PredBlock : predecessors(EHBlock)) {
1134*9880d681SAndroid Build Coastguard Worker         insertPHIStore(PredBlock, InVal, SpillSlot, Worklist);
1135*9880d681SAndroid Build Coastguard Worker       }
1136*9880d681SAndroid Build Coastguard Worker     }
1137*9880d681SAndroid Build Coastguard Worker   }
1138*9880d681SAndroid Build Coastguard Worker }
1139*9880d681SAndroid Build Coastguard Worker 
insertPHIStore(BasicBlock * PredBlock,Value * PredVal,AllocaInst * SpillSlot,SmallVectorImpl<std::pair<BasicBlock *,Value * >> & Worklist)1140*9880d681SAndroid Build Coastguard Worker void WinEHPrepare::insertPHIStore(
1141*9880d681SAndroid Build Coastguard Worker     BasicBlock *PredBlock, Value *PredVal, AllocaInst *SpillSlot,
1142*9880d681SAndroid Build Coastguard Worker     SmallVectorImpl<std::pair<BasicBlock *, Value *>> &Worklist) {
1143*9880d681SAndroid Build Coastguard Worker 
1144*9880d681SAndroid Build Coastguard Worker   if (PredBlock->isEHPad() &&
1145*9880d681SAndroid Build Coastguard Worker       isa<TerminatorInst>(PredBlock->getFirstNonPHI())) {
1146*9880d681SAndroid Build Coastguard Worker     // Pred is unsplittable, so we need to queue it on the worklist.
1147*9880d681SAndroid Build Coastguard Worker     Worklist.push_back({PredBlock, PredVal});
1148*9880d681SAndroid Build Coastguard Worker     return;
1149*9880d681SAndroid Build Coastguard Worker   }
1150*9880d681SAndroid Build Coastguard Worker 
1151*9880d681SAndroid Build Coastguard Worker   // Otherwise, insert the store at the end of the basic block.
1152*9880d681SAndroid Build Coastguard Worker   new StoreInst(PredVal, SpillSlot, PredBlock->getTerminator());
1153*9880d681SAndroid Build Coastguard Worker }
1154*9880d681SAndroid Build Coastguard Worker 
replaceUseWithLoad(Value * V,Use & U,AllocaInst * & SpillSlot,DenseMap<BasicBlock *,Value * > & Loads,Function & F)1155*9880d681SAndroid Build Coastguard Worker void WinEHPrepare::replaceUseWithLoad(Value *V, Use &U, AllocaInst *&SpillSlot,
1156*9880d681SAndroid Build Coastguard Worker                                       DenseMap<BasicBlock *, Value *> &Loads,
1157*9880d681SAndroid Build Coastguard Worker                                       Function &F) {
1158*9880d681SAndroid Build Coastguard Worker   // Lazilly create the spill slot.
1159*9880d681SAndroid Build Coastguard Worker   if (!SpillSlot)
1160*9880d681SAndroid Build Coastguard Worker     SpillSlot = new AllocaInst(V->getType(), nullptr,
1161*9880d681SAndroid Build Coastguard Worker                                Twine(V->getName(), ".wineh.spillslot"),
1162*9880d681SAndroid Build Coastguard Worker                                &F.getEntryBlock().front());
1163*9880d681SAndroid Build Coastguard Worker 
1164*9880d681SAndroid Build Coastguard Worker   auto *UsingInst = cast<Instruction>(U.getUser());
1165*9880d681SAndroid Build Coastguard Worker   if (auto *UsingPHI = dyn_cast<PHINode>(UsingInst)) {
1166*9880d681SAndroid Build Coastguard Worker     // If this is a PHI node, we can't insert a load of the value before
1167*9880d681SAndroid Build Coastguard Worker     // the use.  Instead insert the load in the predecessor block
1168*9880d681SAndroid Build Coastguard Worker     // corresponding to the incoming value.
1169*9880d681SAndroid Build Coastguard Worker     //
1170*9880d681SAndroid Build Coastguard Worker     // Note that if there are multiple edges from a basic block to this
1171*9880d681SAndroid Build Coastguard Worker     // PHI node that we cannot have multiple loads.  The problem is that
1172*9880d681SAndroid Build Coastguard Worker     // the resulting PHI node will have multiple values (from each load)
1173*9880d681SAndroid Build Coastguard Worker     // coming in from the same block, which is illegal SSA form.
1174*9880d681SAndroid Build Coastguard Worker     // For this reason, we keep track of and reuse loads we insert.
1175*9880d681SAndroid Build Coastguard Worker     BasicBlock *IncomingBlock = UsingPHI->getIncomingBlock(U);
1176*9880d681SAndroid Build Coastguard Worker     if (auto *CatchRet =
1177*9880d681SAndroid Build Coastguard Worker             dyn_cast<CatchReturnInst>(IncomingBlock->getTerminator())) {
1178*9880d681SAndroid Build Coastguard Worker       // Putting a load above a catchret and use on the phi would still leave
1179*9880d681SAndroid Build Coastguard Worker       // a cross-funclet def/use.  We need to split the edge, change the
1180*9880d681SAndroid Build Coastguard Worker       // catchret to target the new block, and put the load there.
1181*9880d681SAndroid Build Coastguard Worker       BasicBlock *PHIBlock = UsingInst->getParent();
1182*9880d681SAndroid Build Coastguard Worker       BasicBlock *NewBlock = SplitEdge(IncomingBlock, PHIBlock);
1183*9880d681SAndroid Build Coastguard Worker       // SplitEdge gives us:
1184*9880d681SAndroid Build Coastguard Worker       //   IncomingBlock:
1185*9880d681SAndroid Build Coastguard Worker       //     ...
1186*9880d681SAndroid Build Coastguard Worker       //     br label %NewBlock
1187*9880d681SAndroid Build Coastguard Worker       //   NewBlock:
1188*9880d681SAndroid Build Coastguard Worker       //     catchret label %PHIBlock
1189*9880d681SAndroid Build Coastguard Worker       // But we need:
1190*9880d681SAndroid Build Coastguard Worker       //   IncomingBlock:
1191*9880d681SAndroid Build Coastguard Worker       //     ...
1192*9880d681SAndroid Build Coastguard Worker       //     catchret label %NewBlock
1193*9880d681SAndroid Build Coastguard Worker       //   NewBlock:
1194*9880d681SAndroid Build Coastguard Worker       //     br label %PHIBlock
1195*9880d681SAndroid Build Coastguard Worker       // So move the terminators to each others' blocks and swap their
1196*9880d681SAndroid Build Coastguard Worker       // successors.
1197*9880d681SAndroid Build Coastguard Worker       BranchInst *Goto = cast<BranchInst>(IncomingBlock->getTerminator());
1198*9880d681SAndroid Build Coastguard Worker       Goto->removeFromParent();
1199*9880d681SAndroid Build Coastguard Worker       CatchRet->removeFromParent();
1200*9880d681SAndroid Build Coastguard Worker       IncomingBlock->getInstList().push_back(CatchRet);
1201*9880d681SAndroid Build Coastguard Worker       NewBlock->getInstList().push_back(Goto);
1202*9880d681SAndroid Build Coastguard Worker       Goto->setSuccessor(0, PHIBlock);
1203*9880d681SAndroid Build Coastguard Worker       CatchRet->setSuccessor(NewBlock);
1204*9880d681SAndroid Build Coastguard Worker       // Update the color mapping for the newly split edge.
1205*9880d681SAndroid Build Coastguard Worker       ColorVector &ColorsForPHIBlock = BlockColors[PHIBlock];
1206*9880d681SAndroid Build Coastguard Worker       BlockColors[NewBlock] = ColorsForPHIBlock;
1207*9880d681SAndroid Build Coastguard Worker       for (BasicBlock *FuncletPad : ColorsForPHIBlock)
1208*9880d681SAndroid Build Coastguard Worker         FuncletBlocks[FuncletPad].push_back(NewBlock);
1209*9880d681SAndroid Build Coastguard Worker       // Treat the new block as incoming for load insertion.
1210*9880d681SAndroid Build Coastguard Worker       IncomingBlock = NewBlock;
1211*9880d681SAndroid Build Coastguard Worker     }
1212*9880d681SAndroid Build Coastguard Worker     Value *&Load = Loads[IncomingBlock];
1213*9880d681SAndroid Build Coastguard Worker     // Insert the load into the predecessor block
1214*9880d681SAndroid Build Coastguard Worker     if (!Load)
1215*9880d681SAndroid Build Coastguard Worker       Load = new LoadInst(SpillSlot, Twine(V->getName(), ".wineh.reload"),
1216*9880d681SAndroid Build Coastguard Worker                           /*Volatile=*/false, IncomingBlock->getTerminator());
1217*9880d681SAndroid Build Coastguard Worker 
1218*9880d681SAndroid Build Coastguard Worker     U.set(Load);
1219*9880d681SAndroid Build Coastguard Worker   } else {
1220*9880d681SAndroid Build Coastguard Worker     // Reload right before the old use.
1221*9880d681SAndroid Build Coastguard Worker     auto *Load = new LoadInst(SpillSlot, Twine(V->getName(), ".wineh.reload"),
1222*9880d681SAndroid Build Coastguard Worker                               /*Volatile=*/false, UsingInst);
1223*9880d681SAndroid Build Coastguard Worker     U.set(Load);
1224*9880d681SAndroid Build Coastguard Worker   }
1225*9880d681SAndroid Build Coastguard Worker }
1226*9880d681SAndroid Build Coastguard Worker 
addIPToStateRange(const InvokeInst * II,MCSymbol * InvokeBegin,MCSymbol * InvokeEnd)1227*9880d681SAndroid Build Coastguard Worker void WinEHFuncInfo::addIPToStateRange(const InvokeInst *II,
1228*9880d681SAndroid Build Coastguard Worker                                       MCSymbol *InvokeBegin,
1229*9880d681SAndroid Build Coastguard Worker                                       MCSymbol *InvokeEnd) {
1230*9880d681SAndroid Build Coastguard Worker   assert(InvokeStateMap.count(II) &&
1231*9880d681SAndroid Build Coastguard Worker          "should get invoke with precomputed state");
1232*9880d681SAndroid Build Coastguard Worker   LabelToStateMap[InvokeBegin] = std::make_pair(InvokeStateMap[II], InvokeEnd);
1233*9880d681SAndroid Build Coastguard Worker }
1234*9880d681SAndroid Build Coastguard Worker 
WinEHFuncInfo()1235*9880d681SAndroid Build Coastguard Worker WinEHFuncInfo::WinEHFuncInfo() {}
1236