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