xref: /aosp_15_r20/external/llvm/lib/Target/X86/X86WinEHState.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- X86WinEHState - Insert EH state updates for win32 exceptions ------===//
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 // All functions using an MSVC EH personality use an explicitly updated state
11*9880d681SAndroid Build Coastguard Worker // number stored in an exception registration stack object. The registration
12*9880d681SAndroid Build Coastguard Worker // object is linked into a thread-local chain of registrations stored at fs:00.
13*9880d681SAndroid Build Coastguard Worker // This pass adds the registration object and EH state updates.
14*9880d681SAndroid Build Coastguard Worker //
15*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
16*9880d681SAndroid Build Coastguard Worker 
17*9880d681SAndroid Build Coastguard Worker #include "X86.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/PostOrderIterator.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/CFG.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/EHPersonalities.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineModuleInfo.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/WinEHFuncInfo.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/CallSite.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Instructions.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/IntrinsicInst.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/IRBuilder.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Module.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 <deque>
32*9880d681SAndroid Build Coastguard Worker 
33*9880d681SAndroid Build Coastguard Worker using namespace llvm;
34*9880d681SAndroid Build Coastguard Worker 
35*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "winehstate"
36*9880d681SAndroid Build Coastguard Worker 
37*9880d681SAndroid Build Coastguard Worker namespace llvm {
38*9880d681SAndroid Build Coastguard Worker void initializeWinEHStatePassPass(PassRegistry &);
39*9880d681SAndroid Build Coastguard Worker }
40*9880d681SAndroid Build Coastguard Worker 
41*9880d681SAndroid Build Coastguard Worker namespace {
42*9880d681SAndroid Build Coastguard Worker const int OverdefinedState = INT_MIN;
43*9880d681SAndroid Build Coastguard Worker 
44*9880d681SAndroid Build Coastguard Worker class WinEHStatePass : public FunctionPass {
45*9880d681SAndroid Build Coastguard Worker public:
46*9880d681SAndroid Build Coastguard Worker   static char ID; // Pass identification, replacement for typeid.
47*9880d681SAndroid Build Coastguard Worker 
WinEHStatePass()48*9880d681SAndroid Build Coastguard Worker   WinEHStatePass() : FunctionPass(ID) {
49*9880d681SAndroid Build Coastguard Worker     initializeWinEHStatePassPass(*PassRegistry::getPassRegistry());
50*9880d681SAndroid Build Coastguard Worker   }
51*9880d681SAndroid Build Coastguard Worker 
52*9880d681SAndroid Build Coastguard Worker   bool runOnFunction(Function &Fn) override;
53*9880d681SAndroid Build Coastguard Worker 
54*9880d681SAndroid Build Coastguard Worker   bool doInitialization(Module &M) override;
55*9880d681SAndroid Build Coastguard Worker 
56*9880d681SAndroid Build Coastguard Worker   bool doFinalization(Module &M) override;
57*9880d681SAndroid Build Coastguard Worker 
58*9880d681SAndroid Build Coastguard Worker   void getAnalysisUsage(AnalysisUsage &AU) const override;
59*9880d681SAndroid Build Coastguard Worker 
getPassName() const60*9880d681SAndroid Build Coastguard Worker   const char *getPassName() const override {
61*9880d681SAndroid Build Coastguard Worker     return "Windows 32-bit x86 EH state insertion";
62*9880d681SAndroid Build Coastguard Worker   }
63*9880d681SAndroid Build Coastguard Worker 
64*9880d681SAndroid Build Coastguard Worker private:
65*9880d681SAndroid Build Coastguard Worker   void emitExceptionRegistrationRecord(Function *F);
66*9880d681SAndroid Build Coastguard Worker 
67*9880d681SAndroid Build Coastguard Worker   void linkExceptionRegistration(IRBuilder<> &Builder, Function *Handler);
68*9880d681SAndroid Build Coastguard Worker   void unlinkExceptionRegistration(IRBuilder<> &Builder);
69*9880d681SAndroid Build Coastguard Worker   void addStateStores(Function &F, WinEHFuncInfo &FuncInfo);
70*9880d681SAndroid Build Coastguard Worker   void insertStateNumberStore(Instruction *IP, int State);
71*9880d681SAndroid Build Coastguard Worker 
72*9880d681SAndroid Build Coastguard Worker   Value *emitEHLSDA(IRBuilder<> &Builder, Function *F);
73*9880d681SAndroid Build Coastguard Worker 
74*9880d681SAndroid Build Coastguard Worker   Function *generateLSDAInEAXThunk(Function *ParentFunc);
75*9880d681SAndroid Build Coastguard Worker 
76*9880d681SAndroid Build Coastguard Worker   bool isStateStoreNeeded(EHPersonality Personality, CallSite CS);
77*9880d681SAndroid Build Coastguard Worker   void rewriteSetJmpCallSite(IRBuilder<> &Builder, Function &F, CallSite CS,
78*9880d681SAndroid Build Coastguard Worker                              Value *State);
79*9880d681SAndroid Build Coastguard Worker   int getBaseStateForBB(DenseMap<BasicBlock *, ColorVector> &BlockColors,
80*9880d681SAndroid Build Coastguard Worker                         WinEHFuncInfo &FuncInfo, BasicBlock *BB);
81*9880d681SAndroid Build Coastguard Worker   int getStateForCallSite(DenseMap<BasicBlock *, ColorVector> &BlockColors,
82*9880d681SAndroid Build Coastguard Worker                           WinEHFuncInfo &FuncInfo, CallSite CS);
83*9880d681SAndroid Build Coastguard Worker 
84*9880d681SAndroid Build Coastguard Worker   // Module-level type getters.
85*9880d681SAndroid Build Coastguard Worker   Type *getEHLinkRegistrationType();
86*9880d681SAndroid Build Coastguard Worker   Type *getSEHRegistrationType();
87*9880d681SAndroid Build Coastguard Worker   Type *getCXXEHRegistrationType();
88*9880d681SAndroid Build Coastguard Worker 
89*9880d681SAndroid Build Coastguard Worker   // Per-module data.
90*9880d681SAndroid Build Coastguard Worker   Module *TheModule = nullptr;
91*9880d681SAndroid Build Coastguard Worker   StructType *EHLinkRegistrationTy = nullptr;
92*9880d681SAndroid Build Coastguard Worker   StructType *CXXEHRegistrationTy = nullptr;
93*9880d681SAndroid Build Coastguard Worker   StructType *SEHRegistrationTy = nullptr;
94*9880d681SAndroid Build Coastguard Worker   Constant *SetJmp3 = nullptr;
95*9880d681SAndroid Build Coastguard Worker   Constant *CxxLongjmpUnwind = nullptr;
96*9880d681SAndroid Build Coastguard Worker 
97*9880d681SAndroid Build Coastguard Worker   // Per-function state
98*9880d681SAndroid Build Coastguard Worker   EHPersonality Personality = EHPersonality::Unknown;
99*9880d681SAndroid Build Coastguard Worker   Function *PersonalityFn = nullptr;
100*9880d681SAndroid Build Coastguard Worker   bool UseStackGuard = false;
101*9880d681SAndroid Build Coastguard Worker   int ParentBaseState;
102*9880d681SAndroid Build Coastguard Worker   Constant *SehLongjmpUnwind = nullptr;
103*9880d681SAndroid Build Coastguard Worker   Constant *Cookie = nullptr;
104*9880d681SAndroid Build Coastguard Worker 
105*9880d681SAndroid Build Coastguard Worker   /// The stack allocation containing all EH data, including the link in the
106*9880d681SAndroid Build Coastguard Worker   /// fs:00 chain and the current state.
107*9880d681SAndroid Build Coastguard Worker   AllocaInst *RegNode = nullptr;
108*9880d681SAndroid Build Coastguard Worker 
109*9880d681SAndroid Build Coastguard Worker   // The allocation containing the EH security guard.
110*9880d681SAndroid Build Coastguard Worker   AllocaInst *EHGuardNode = nullptr;
111*9880d681SAndroid Build Coastguard Worker 
112*9880d681SAndroid Build Coastguard Worker   /// The index of the state field of RegNode.
113*9880d681SAndroid Build Coastguard Worker   int StateFieldIndex = ~0U;
114*9880d681SAndroid Build Coastguard Worker 
115*9880d681SAndroid Build Coastguard Worker   /// The linked list node subobject inside of RegNode.
116*9880d681SAndroid Build Coastguard Worker   Value *Link = nullptr;
117*9880d681SAndroid Build Coastguard Worker };
118*9880d681SAndroid Build Coastguard Worker }
119*9880d681SAndroid Build Coastguard Worker 
createX86WinEHStatePass()120*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createX86WinEHStatePass() { return new WinEHStatePass(); }
121*9880d681SAndroid Build Coastguard Worker 
122*9880d681SAndroid Build Coastguard Worker char WinEHStatePass::ID = 0;
123*9880d681SAndroid Build Coastguard Worker 
124*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(WinEHStatePass, "x86-winehstate",
125*9880d681SAndroid Build Coastguard Worker                 "Insert stores for EH state numbers", false, false)
126*9880d681SAndroid Build Coastguard Worker 
doInitialization(Module & M)127*9880d681SAndroid Build Coastguard Worker bool WinEHStatePass::doInitialization(Module &M) {
128*9880d681SAndroid Build Coastguard Worker   TheModule = &M;
129*9880d681SAndroid Build Coastguard Worker   return false;
130*9880d681SAndroid Build Coastguard Worker }
131*9880d681SAndroid Build Coastguard Worker 
doFinalization(Module & M)132*9880d681SAndroid Build Coastguard Worker bool WinEHStatePass::doFinalization(Module &M) {
133*9880d681SAndroid Build Coastguard Worker   assert(TheModule == &M);
134*9880d681SAndroid Build Coastguard Worker   TheModule = nullptr;
135*9880d681SAndroid Build Coastguard Worker   EHLinkRegistrationTy = nullptr;
136*9880d681SAndroid Build Coastguard Worker   CXXEHRegistrationTy = nullptr;
137*9880d681SAndroid Build Coastguard Worker   SEHRegistrationTy = nullptr;
138*9880d681SAndroid Build Coastguard Worker   SetJmp3 = nullptr;
139*9880d681SAndroid Build Coastguard Worker   CxxLongjmpUnwind = nullptr;
140*9880d681SAndroid Build Coastguard Worker   SehLongjmpUnwind = nullptr;
141*9880d681SAndroid Build Coastguard Worker   Cookie = nullptr;
142*9880d681SAndroid Build Coastguard Worker   return false;
143*9880d681SAndroid Build Coastguard Worker }
144*9880d681SAndroid Build Coastguard Worker 
getAnalysisUsage(AnalysisUsage & AU) const145*9880d681SAndroid Build Coastguard Worker void WinEHStatePass::getAnalysisUsage(AnalysisUsage &AU) const {
146*9880d681SAndroid Build Coastguard Worker   // This pass should only insert a stack allocation, memory accesses, and
147*9880d681SAndroid Build Coastguard Worker   // localrecovers.
148*9880d681SAndroid Build Coastguard Worker   AU.setPreservesCFG();
149*9880d681SAndroid Build Coastguard Worker }
150*9880d681SAndroid Build Coastguard Worker 
runOnFunction(Function & F)151*9880d681SAndroid Build Coastguard Worker bool WinEHStatePass::runOnFunction(Function &F) {
152*9880d681SAndroid Build Coastguard Worker   // Check the personality. Do nothing if this personality doesn't use funclets.
153*9880d681SAndroid Build Coastguard Worker   if (!F.hasPersonalityFn())
154*9880d681SAndroid Build Coastguard Worker     return false;
155*9880d681SAndroid Build Coastguard Worker   PersonalityFn =
156*9880d681SAndroid Build Coastguard Worker       dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts());
157*9880d681SAndroid Build Coastguard Worker   if (!PersonalityFn)
158*9880d681SAndroid Build Coastguard Worker     return false;
159*9880d681SAndroid Build Coastguard Worker   Personality = classifyEHPersonality(PersonalityFn);
160*9880d681SAndroid Build Coastguard Worker   if (!isFuncletEHPersonality(Personality))
161*9880d681SAndroid Build Coastguard Worker     return false;
162*9880d681SAndroid Build Coastguard Worker 
163*9880d681SAndroid Build Coastguard Worker   // Skip this function if there are no EH pads and we aren't using IR-level
164*9880d681SAndroid Build Coastguard Worker   // outlining.
165*9880d681SAndroid Build Coastguard Worker   bool HasPads = false;
166*9880d681SAndroid Build Coastguard Worker   for (BasicBlock &BB : F) {
167*9880d681SAndroid Build Coastguard Worker     if (BB.isEHPad()) {
168*9880d681SAndroid Build Coastguard Worker       HasPads = true;
169*9880d681SAndroid Build Coastguard Worker       break;
170*9880d681SAndroid Build Coastguard Worker     }
171*9880d681SAndroid Build Coastguard Worker   }
172*9880d681SAndroid Build Coastguard Worker   if (!HasPads)
173*9880d681SAndroid Build Coastguard Worker     return false;
174*9880d681SAndroid Build Coastguard Worker 
175*9880d681SAndroid Build Coastguard Worker   Type *Int8PtrType = Type::getInt8PtrTy(TheModule->getContext());
176*9880d681SAndroid Build Coastguard Worker   SetJmp3 = TheModule->getOrInsertFunction(
177*9880d681SAndroid Build Coastguard Worker       "_setjmp3", FunctionType::get(
178*9880d681SAndroid Build Coastguard Worker                       Type::getInt32Ty(TheModule->getContext()),
179*9880d681SAndroid Build Coastguard Worker                       {Int8PtrType, Type::getInt32Ty(TheModule->getContext())},
180*9880d681SAndroid Build Coastguard Worker                       /*isVarArg=*/true));
181*9880d681SAndroid Build Coastguard Worker 
182*9880d681SAndroid Build Coastguard Worker   // Disable frame pointer elimination in this function.
183*9880d681SAndroid Build Coastguard Worker   // FIXME: Do the nested handlers need to keep the parent ebp in ebp, or can we
184*9880d681SAndroid Build Coastguard Worker   // use an arbitrary register?
185*9880d681SAndroid Build Coastguard Worker   F.addFnAttr("no-frame-pointer-elim", "true");
186*9880d681SAndroid Build Coastguard Worker 
187*9880d681SAndroid Build Coastguard Worker   emitExceptionRegistrationRecord(&F);
188*9880d681SAndroid Build Coastguard Worker 
189*9880d681SAndroid Build Coastguard Worker   // The state numbers calculated here in IR must agree with what we calculate
190*9880d681SAndroid Build Coastguard Worker   // later on for the MachineFunction. In particular, if an IR pass deletes an
191*9880d681SAndroid Build Coastguard Worker   // unreachable EH pad after this point before machine CFG construction, we
192*9880d681SAndroid Build Coastguard Worker   // will be in trouble. If this assumption is ever broken, we should turn the
193*9880d681SAndroid Build Coastguard Worker   // numbers into an immutable analysis pass.
194*9880d681SAndroid Build Coastguard Worker   WinEHFuncInfo FuncInfo;
195*9880d681SAndroid Build Coastguard Worker   addStateStores(F, FuncInfo);
196*9880d681SAndroid Build Coastguard Worker 
197*9880d681SAndroid Build Coastguard Worker   // Reset per-function state.
198*9880d681SAndroid Build Coastguard Worker   PersonalityFn = nullptr;
199*9880d681SAndroid Build Coastguard Worker   Personality = EHPersonality::Unknown;
200*9880d681SAndroid Build Coastguard Worker   UseStackGuard = false;
201*9880d681SAndroid Build Coastguard Worker   RegNode = nullptr;
202*9880d681SAndroid Build Coastguard Worker   EHGuardNode = nullptr;
203*9880d681SAndroid Build Coastguard Worker 
204*9880d681SAndroid Build Coastguard Worker   return true;
205*9880d681SAndroid Build Coastguard Worker }
206*9880d681SAndroid Build Coastguard Worker 
207*9880d681SAndroid Build Coastguard Worker /// Get the common EH registration subobject:
208*9880d681SAndroid Build Coastguard Worker ///   typedef _EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE)(
209*9880d681SAndroid Build Coastguard Worker ///       _EXCEPTION_RECORD *, void *, _CONTEXT *, void *);
210*9880d681SAndroid Build Coastguard Worker ///   struct EHRegistrationNode {
211*9880d681SAndroid Build Coastguard Worker ///     EHRegistrationNode *Next;
212*9880d681SAndroid Build Coastguard Worker ///     PEXCEPTION_ROUTINE Handler;
213*9880d681SAndroid Build Coastguard Worker ///   };
getEHLinkRegistrationType()214*9880d681SAndroid Build Coastguard Worker Type *WinEHStatePass::getEHLinkRegistrationType() {
215*9880d681SAndroid Build Coastguard Worker   if (EHLinkRegistrationTy)
216*9880d681SAndroid Build Coastguard Worker     return EHLinkRegistrationTy;
217*9880d681SAndroid Build Coastguard Worker   LLVMContext &Context = TheModule->getContext();
218*9880d681SAndroid Build Coastguard Worker   EHLinkRegistrationTy = StructType::create(Context, "EHRegistrationNode");
219*9880d681SAndroid Build Coastguard Worker   Type *FieldTys[] = {
220*9880d681SAndroid Build Coastguard Worker       EHLinkRegistrationTy->getPointerTo(0), // EHRegistrationNode *Next
221*9880d681SAndroid Build Coastguard Worker       Type::getInt8PtrTy(Context) // EXCEPTION_DISPOSITION (*Handler)(...)
222*9880d681SAndroid Build Coastguard Worker   };
223*9880d681SAndroid Build Coastguard Worker   EHLinkRegistrationTy->setBody(FieldTys, false);
224*9880d681SAndroid Build Coastguard Worker   return EHLinkRegistrationTy;
225*9880d681SAndroid Build Coastguard Worker }
226*9880d681SAndroid Build Coastguard Worker 
227*9880d681SAndroid Build Coastguard Worker /// The __CxxFrameHandler3 registration node:
228*9880d681SAndroid Build Coastguard Worker ///   struct CXXExceptionRegistration {
229*9880d681SAndroid Build Coastguard Worker ///     void *SavedESP;
230*9880d681SAndroid Build Coastguard Worker ///     EHRegistrationNode SubRecord;
231*9880d681SAndroid Build Coastguard Worker ///     int32_t TryLevel;
232*9880d681SAndroid Build Coastguard Worker ///   };
getCXXEHRegistrationType()233*9880d681SAndroid Build Coastguard Worker Type *WinEHStatePass::getCXXEHRegistrationType() {
234*9880d681SAndroid Build Coastguard Worker   if (CXXEHRegistrationTy)
235*9880d681SAndroid Build Coastguard Worker     return CXXEHRegistrationTy;
236*9880d681SAndroid Build Coastguard Worker   LLVMContext &Context = TheModule->getContext();
237*9880d681SAndroid Build Coastguard Worker   Type *FieldTys[] = {
238*9880d681SAndroid Build Coastguard Worker       Type::getInt8PtrTy(Context), // void *SavedESP
239*9880d681SAndroid Build Coastguard Worker       getEHLinkRegistrationType(), // EHRegistrationNode SubRecord
240*9880d681SAndroid Build Coastguard Worker       Type::getInt32Ty(Context)    // int32_t TryLevel
241*9880d681SAndroid Build Coastguard Worker   };
242*9880d681SAndroid Build Coastguard Worker   CXXEHRegistrationTy =
243*9880d681SAndroid Build Coastguard Worker       StructType::create(FieldTys, "CXXExceptionRegistration");
244*9880d681SAndroid Build Coastguard Worker   return CXXEHRegistrationTy;
245*9880d681SAndroid Build Coastguard Worker }
246*9880d681SAndroid Build Coastguard Worker 
247*9880d681SAndroid Build Coastguard Worker /// The _except_handler3/4 registration node:
248*9880d681SAndroid Build Coastguard Worker ///   struct EH4ExceptionRegistration {
249*9880d681SAndroid Build Coastguard Worker ///     void *SavedESP;
250*9880d681SAndroid Build Coastguard Worker ///     _EXCEPTION_POINTERS *ExceptionPointers;
251*9880d681SAndroid Build Coastguard Worker ///     EHRegistrationNode SubRecord;
252*9880d681SAndroid Build Coastguard Worker ///     int32_t EncodedScopeTable;
253*9880d681SAndroid Build Coastguard Worker ///     int32_t TryLevel;
254*9880d681SAndroid Build Coastguard Worker ///   };
getSEHRegistrationType()255*9880d681SAndroid Build Coastguard Worker Type *WinEHStatePass::getSEHRegistrationType() {
256*9880d681SAndroid Build Coastguard Worker   if (SEHRegistrationTy)
257*9880d681SAndroid Build Coastguard Worker     return SEHRegistrationTy;
258*9880d681SAndroid Build Coastguard Worker   LLVMContext &Context = TheModule->getContext();
259*9880d681SAndroid Build Coastguard Worker   Type *FieldTys[] = {
260*9880d681SAndroid Build Coastguard Worker       Type::getInt8PtrTy(Context), // void *SavedESP
261*9880d681SAndroid Build Coastguard Worker       Type::getInt8PtrTy(Context), // void *ExceptionPointers
262*9880d681SAndroid Build Coastguard Worker       getEHLinkRegistrationType(), // EHRegistrationNode SubRecord
263*9880d681SAndroid Build Coastguard Worker       Type::getInt32Ty(Context),   // int32_t EncodedScopeTable
264*9880d681SAndroid Build Coastguard Worker       Type::getInt32Ty(Context)    // int32_t TryLevel
265*9880d681SAndroid Build Coastguard Worker   };
266*9880d681SAndroid Build Coastguard Worker   SEHRegistrationTy = StructType::create(FieldTys, "SEHExceptionRegistration");
267*9880d681SAndroid Build Coastguard Worker   return SEHRegistrationTy;
268*9880d681SAndroid Build Coastguard Worker }
269*9880d681SAndroid Build Coastguard Worker 
270*9880d681SAndroid Build Coastguard Worker // Emit an exception registration record. These are stack allocations with the
271*9880d681SAndroid Build Coastguard Worker // common subobject of two pointers: the previous registration record (the old
272*9880d681SAndroid Build Coastguard Worker // fs:00) and the personality function for the current frame. The data before
273*9880d681SAndroid Build Coastguard Worker // and after that is personality function specific.
emitExceptionRegistrationRecord(Function * F)274*9880d681SAndroid Build Coastguard Worker void WinEHStatePass::emitExceptionRegistrationRecord(Function *F) {
275*9880d681SAndroid Build Coastguard Worker   assert(Personality == EHPersonality::MSVC_CXX ||
276*9880d681SAndroid Build Coastguard Worker          Personality == EHPersonality::MSVC_X86SEH);
277*9880d681SAndroid Build Coastguard Worker 
278*9880d681SAndroid Build Coastguard Worker   // Struct type of RegNode. Used for GEPing.
279*9880d681SAndroid Build Coastguard Worker   Type *RegNodeTy;
280*9880d681SAndroid Build Coastguard Worker 
281*9880d681SAndroid Build Coastguard Worker   IRBuilder<> Builder(&F->getEntryBlock(), F->getEntryBlock().begin());
282*9880d681SAndroid Build Coastguard Worker   Type *Int8PtrType = Builder.getInt8PtrTy();
283*9880d681SAndroid Build Coastguard Worker   Type *Int32Ty = Builder.getInt32Ty();
284*9880d681SAndroid Build Coastguard Worker   Type *VoidTy = Builder.getVoidTy();
285*9880d681SAndroid Build Coastguard Worker 
286*9880d681SAndroid Build Coastguard Worker   if (Personality == EHPersonality::MSVC_CXX) {
287*9880d681SAndroid Build Coastguard Worker     RegNodeTy = getCXXEHRegistrationType();
288*9880d681SAndroid Build Coastguard Worker     RegNode = Builder.CreateAlloca(RegNodeTy);
289*9880d681SAndroid Build Coastguard Worker     // SavedESP = llvm.stacksave()
290*9880d681SAndroid Build Coastguard Worker     Value *SP = Builder.CreateCall(
291*9880d681SAndroid Build Coastguard Worker         Intrinsic::getDeclaration(TheModule, Intrinsic::stacksave), {});
292*9880d681SAndroid Build Coastguard Worker     Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
293*9880d681SAndroid Build Coastguard Worker     // TryLevel = -1
294*9880d681SAndroid Build Coastguard Worker     StateFieldIndex = 2;
295*9880d681SAndroid Build Coastguard Worker     ParentBaseState = -1;
296*9880d681SAndroid Build Coastguard Worker     insertStateNumberStore(&*Builder.GetInsertPoint(), ParentBaseState);
297*9880d681SAndroid Build Coastguard Worker     // Handler = __ehhandler$F
298*9880d681SAndroid Build Coastguard Worker     Function *Trampoline = generateLSDAInEAXThunk(F);
299*9880d681SAndroid Build Coastguard Worker     Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 1);
300*9880d681SAndroid Build Coastguard Worker     linkExceptionRegistration(Builder, Trampoline);
301*9880d681SAndroid Build Coastguard Worker 
302*9880d681SAndroid Build Coastguard Worker     CxxLongjmpUnwind = TheModule->getOrInsertFunction(
303*9880d681SAndroid Build Coastguard Worker         "__CxxLongjmpUnwind",
304*9880d681SAndroid Build Coastguard Worker         FunctionType::get(VoidTy, Int8PtrType, /*isVarArg=*/false));
305*9880d681SAndroid Build Coastguard Worker     cast<Function>(CxxLongjmpUnwind->stripPointerCasts())
306*9880d681SAndroid Build Coastguard Worker         ->setCallingConv(CallingConv::X86_StdCall);
307*9880d681SAndroid Build Coastguard Worker   } else if (Personality == EHPersonality::MSVC_X86SEH) {
308*9880d681SAndroid Build Coastguard Worker     // If _except_handler4 is in use, some additional guard checks and prologue
309*9880d681SAndroid Build Coastguard Worker     // stuff is required.
310*9880d681SAndroid Build Coastguard Worker     StringRef PersonalityName = PersonalityFn->getName();
311*9880d681SAndroid Build Coastguard Worker     UseStackGuard = (PersonalityName == "_except_handler4");
312*9880d681SAndroid Build Coastguard Worker 
313*9880d681SAndroid Build Coastguard Worker     // Allocate local structures.
314*9880d681SAndroid Build Coastguard Worker     RegNodeTy = getSEHRegistrationType();
315*9880d681SAndroid Build Coastguard Worker     RegNode = Builder.CreateAlloca(RegNodeTy);
316*9880d681SAndroid Build Coastguard Worker     if (UseStackGuard)
317*9880d681SAndroid Build Coastguard Worker       EHGuardNode = Builder.CreateAlloca(Int32Ty);
318*9880d681SAndroid Build Coastguard Worker 
319*9880d681SAndroid Build Coastguard Worker     // SavedESP = llvm.stacksave()
320*9880d681SAndroid Build Coastguard Worker     Value *SP = Builder.CreateCall(
321*9880d681SAndroid Build Coastguard Worker         Intrinsic::getDeclaration(TheModule, Intrinsic::stacksave), {});
322*9880d681SAndroid Build Coastguard Worker     Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
323*9880d681SAndroid Build Coastguard Worker     // TryLevel = -2 / -1
324*9880d681SAndroid Build Coastguard Worker     StateFieldIndex = 4;
325*9880d681SAndroid Build Coastguard Worker     ParentBaseState = UseStackGuard ? -2 : -1;
326*9880d681SAndroid Build Coastguard Worker     insertStateNumberStore(&*Builder.GetInsertPoint(), ParentBaseState);
327*9880d681SAndroid Build Coastguard Worker     // ScopeTable = llvm.x86.seh.lsda(F)
328*9880d681SAndroid Build Coastguard Worker     Value *LSDA = emitEHLSDA(Builder, F);
329*9880d681SAndroid Build Coastguard Worker     LSDA = Builder.CreatePtrToInt(LSDA, Int32Ty);
330*9880d681SAndroid Build Coastguard Worker     // If using _except_handler4, xor the address of the table with
331*9880d681SAndroid Build Coastguard Worker     // __security_cookie.
332*9880d681SAndroid Build Coastguard Worker     if (UseStackGuard) {
333*9880d681SAndroid Build Coastguard Worker       Cookie = TheModule->getOrInsertGlobal("__security_cookie", Int32Ty);
334*9880d681SAndroid Build Coastguard Worker       Value *Val = Builder.CreateLoad(Int32Ty, Cookie, "cookie");
335*9880d681SAndroid Build Coastguard Worker       LSDA = Builder.CreateXor(LSDA, Val);
336*9880d681SAndroid Build Coastguard Worker     }
337*9880d681SAndroid Build Coastguard Worker     Builder.CreateStore(LSDA, Builder.CreateStructGEP(RegNodeTy, RegNode, 3));
338*9880d681SAndroid Build Coastguard Worker 
339*9880d681SAndroid Build Coastguard Worker     // If using _except_handler4, the EHGuard contains: FramePtr xor Cookie.
340*9880d681SAndroid Build Coastguard Worker     if (UseStackGuard) {
341*9880d681SAndroid Build Coastguard Worker       Value *Val = Builder.CreateLoad(Int32Ty, Cookie);
342*9880d681SAndroid Build Coastguard Worker       Value *FrameAddr = Builder.CreateCall(
343*9880d681SAndroid Build Coastguard Worker           Intrinsic::getDeclaration(TheModule, Intrinsic::frameaddress),
344*9880d681SAndroid Build Coastguard Worker           Builder.getInt32(0), "frameaddr");
345*9880d681SAndroid Build Coastguard Worker       Value *FrameAddrI32 = Builder.CreatePtrToInt(FrameAddr, Int32Ty);
346*9880d681SAndroid Build Coastguard Worker       FrameAddrI32 = Builder.CreateXor(FrameAddrI32, Val);
347*9880d681SAndroid Build Coastguard Worker       Builder.CreateStore(FrameAddrI32, EHGuardNode);
348*9880d681SAndroid Build Coastguard Worker     }
349*9880d681SAndroid Build Coastguard Worker 
350*9880d681SAndroid Build Coastguard Worker     // Register the exception handler.
351*9880d681SAndroid Build Coastguard Worker     Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 2);
352*9880d681SAndroid Build Coastguard Worker     linkExceptionRegistration(Builder, PersonalityFn);
353*9880d681SAndroid Build Coastguard Worker 
354*9880d681SAndroid Build Coastguard Worker     SehLongjmpUnwind = TheModule->getOrInsertFunction(
355*9880d681SAndroid Build Coastguard Worker         UseStackGuard ? "_seh_longjmp_unwind4" : "_seh_longjmp_unwind",
356*9880d681SAndroid Build Coastguard Worker         FunctionType::get(Type::getVoidTy(TheModule->getContext()), Int8PtrType,
357*9880d681SAndroid Build Coastguard Worker                           /*isVarArg=*/false));
358*9880d681SAndroid Build Coastguard Worker     cast<Function>(SehLongjmpUnwind->stripPointerCasts())
359*9880d681SAndroid Build Coastguard Worker         ->setCallingConv(CallingConv::X86_StdCall);
360*9880d681SAndroid Build Coastguard Worker   } else {
361*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("unexpected personality function");
362*9880d681SAndroid Build Coastguard Worker   }
363*9880d681SAndroid Build Coastguard Worker 
364*9880d681SAndroid Build Coastguard Worker   // Insert an unlink before all returns.
365*9880d681SAndroid Build Coastguard Worker   for (BasicBlock &BB : *F) {
366*9880d681SAndroid Build Coastguard Worker     TerminatorInst *T = BB.getTerminator();
367*9880d681SAndroid Build Coastguard Worker     if (!isa<ReturnInst>(T))
368*9880d681SAndroid Build Coastguard Worker       continue;
369*9880d681SAndroid Build Coastguard Worker     Builder.SetInsertPoint(T);
370*9880d681SAndroid Build Coastguard Worker     unlinkExceptionRegistration(Builder);
371*9880d681SAndroid Build Coastguard Worker   }
372*9880d681SAndroid Build Coastguard Worker }
373*9880d681SAndroid Build Coastguard Worker 
emitEHLSDA(IRBuilder<> & Builder,Function * F)374*9880d681SAndroid Build Coastguard Worker Value *WinEHStatePass::emitEHLSDA(IRBuilder<> &Builder, Function *F) {
375*9880d681SAndroid Build Coastguard Worker   Value *FI8 = Builder.CreateBitCast(F, Type::getInt8PtrTy(F->getContext()));
376*9880d681SAndroid Build Coastguard Worker   return Builder.CreateCall(
377*9880d681SAndroid Build Coastguard Worker       Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_lsda), FI8);
378*9880d681SAndroid Build Coastguard Worker }
379*9880d681SAndroid Build Coastguard Worker 
380*9880d681SAndroid Build Coastguard Worker /// Generate a thunk that puts the LSDA of ParentFunc in EAX and then calls
381*9880d681SAndroid Build Coastguard Worker /// PersonalityFn, forwarding the parameters passed to PEXCEPTION_ROUTINE:
382*9880d681SAndroid Build Coastguard Worker ///   typedef _EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE)(
383*9880d681SAndroid Build Coastguard Worker ///       _EXCEPTION_RECORD *, void *, _CONTEXT *, void *);
384*9880d681SAndroid Build Coastguard Worker /// We essentially want this code:
385*9880d681SAndroid Build Coastguard Worker ///   movl $lsda, %eax
386*9880d681SAndroid Build Coastguard Worker ///   jmpl ___CxxFrameHandler3
generateLSDAInEAXThunk(Function * ParentFunc)387*9880d681SAndroid Build Coastguard Worker Function *WinEHStatePass::generateLSDAInEAXThunk(Function *ParentFunc) {
388*9880d681SAndroid Build Coastguard Worker   LLVMContext &Context = ParentFunc->getContext();
389*9880d681SAndroid Build Coastguard Worker   Type *Int32Ty = Type::getInt32Ty(Context);
390*9880d681SAndroid Build Coastguard Worker   Type *Int8PtrType = Type::getInt8PtrTy(Context);
391*9880d681SAndroid Build Coastguard Worker   Type *ArgTys[5] = {Int8PtrType, Int8PtrType, Int8PtrType, Int8PtrType,
392*9880d681SAndroid Build Coastguard Worker                      Int8PtrType};
393*9880d681SAndroid Build Coastguard Worker   FunctionType *TrampolineTy =
394*9880d681SAndroid Build Coastguard Worker       FunctionType::get(Int32Ty, makeArrayRef(&ArgTys[0], 4),
395*9880d681SAndroid Build Coastguard Worker                         /*isVarArg=*/false);
396*9880d681SAndroid Build Coastguard Worker   FunctionType *TargetFuncTy =
397*9880d681SAndroid Build Coastguard Worker       FunctionType::get(Int32Ty, makeArrayRef(&ArgTys[0], 5),
398*9880d681SAndroid Build Coastguard Worker                         /*isVarArg=*/false);
399*9880d681SAndroid Build Coastguard Worker   Function *Trampoline =
400*9880d681SAndroid Build Coastguard Worker       Function::Create(TrampolineTy, GlobalValue::InternalLinkage,
401*9880d681SAndroid Build Coastguard Worker                        Twine("__ehhandler$") + GlobalValue::getRealLinkageName(
402*9880d681SAndroid Build Coastguard Worker                                                    ParentFunc->getName()),
403*9880d681SAndroid Build Coastguard Worker                        TheModule);
404*9880d681SAndroid Build Coastguard Worker   BasicBlock *EntryBB = BasicBlock::Create(Context, "entry", Trampoline);
405*9880d681SAndroid Build Coastguard Worker   IRBuilder<> Builder(EntryBB);
406*9880d681SAndroid Build Coastguard Worker   Value *LSDA = emitEHLSDA(Builder, ParentFunc);
407*9880d681SAndroid Build Coastguard Worker   Value *CastPersonality =
408*9880d681SAndroid Build Coastguard Worker       Builder.CreateBitCast(PersonalityFn, TargetFuncTy->getPointerTo());
409*9880d681SAndroid Build Coastguard Worker   auto AI = Trampoline->arg_begin();
410*9880d681SAndroid Build Coastguard Worker   Value *Args[5] = {LSDA, &*AI++, &*AI++, &*AI++, &*AI++};
411*9880d681SAndroid Build Coastguard Worker   CallInst *Call = Builder.CreateCall(CastPersonality, Args);
412*9880d681SAndroid Build Coastguard Worker   // Can't use musttail due to prototype mismatch, but we can use tail.
413*9880d681SAndroid Build Coastguard Worker   Call->setTailCall(true);
414*9880d681SAndroid Build Coastguard Worker   // Set inreg so we pass it in EAX.
415*9880d681SAndroid Build Coastguard Worker   Call->addAttribute(1, Attribute::InReg);
416*9880d681SAndroid Build Coastguard Worker   Builder.CreateRet(Call);
417*9880d681SAndroid Build Coastguard Worker   return Trampoline;
418*9880d681SAndroid Build Coastguard Worker }
419*9880d681SAndroid Build Coastguard Worker 
linkExceptionRegistration(IRBuilder<> & Builder,Function * Handler)420*9880d681SAndroid Build Coastguard Worker void WinEHStatePass::linkExceptionRegistration(IRBuilder<> &Builder,
421*9880d681SAndroid Build Coastguard Worker                                                Function *Handler) {
422*9880d681SAndroid Build Coastguard Worker   // Emit the .safeseh directive for this function.
423*9880d681SAndroid Build Coastguard Worker   Handler->addFnAttr("safeseh");
424*9880d681SAndroid Build Coastguard Worker 
425*9880d681SAndroid Build Coastguard Worker   Type *LinkTy = getEHLinkRegistrationType();
426*9880d681SAndroid Build Coastguard Worker   // Handler = Handler
427*9880d681SAndroid Build Coastguard Worker   Value *HandlerI8 = Builder.CreateBitCast(Handler, Builder.getInt8PtrTy());
428*9880d681SAndroid Build Coastguard Worker   Builder.CreateStore(HandlerI8, Builder.CreateStructGEP(LinkTy, Link, 1));
429*9880d681SAndroid Build Coastguard Worker   // Next = [fs:00]
430*9880d681SAndroid Build Coastguard Worker   Constant *FSZero =
431*9880d681SAndroid Build Coastguard Worker       Constant::getNullValue(LinkTy->getPointerTo()->getPointerTo(257));
432*9880d681SAndroid Build Coastguard Worker   Value *Next = Builder.CreateLoad(FSZero);
433*9880d681SAndroid Build Coastguard Worker   Builder.CreateStore(Next, Builder.CreateStructGEP(LinkTy, Link, 0));
434*9880d681SAndroid Build Coastguard Worker   // [fs:00] = Link
435*9880d681SAndroid Build Coastguard Worker   Builder.CreateStore(Link, FSZero);
436*9880d681SAndroid Build Coastguard Worker }
437*9880d681SAndroid Build Coastguard Worker 
unlinkExceptionRegistration(IRBuilder<> & Builder)438*9880d681SAndroid Build Coastguard Worker void WinEHStatePass::unlinkExceptionRegistration(IRBuilder<> &Builder) {
439*9880d681SAndroid Build Coastguard Worker   // Clone Link into the current BB for better address mode folding.
440*9880d681SAndroid Build Coastguard Worker   if (auto *GEP = dyn_cast<GetElementPtrInst>(Link)) {
441*9880d681SAndroid Build Coastguard Worker     GEP = cast<GetElementPtrInst>(GEP->clone());
442*9880d681SAndroid Build Coastguard Worker     Builder.Insert(GEP);
443*9880d681SAndroid Build Coastguard Worker     Link = GEP;
444*9880d681SAndroid Build Coastguard Worker   }
445*9880d681SAndroid Build Coastguard Worker   Type *LinkTy = getEHLinkRegistrationType();
446*9880d681SAndroid Build Coastguard Worker   // [fs:00] = Link->Next
447*9880d681SAndroid Build Coastguard Worker   Value *Next =
448*9880d681SAndroid Build Coastguard Worker       Builder.CreateLoad(Builder.CreateStructGEP(LinkTy, Link, 0));
449*9880d681SAndroid Build Coastguard Worker   Constant *FSZero =
450*9880d681SAndroid Build Coastguard Worker       Constant::getNullValue(LinkTy->getPointerTo()->getPointerTo(257));
451*9880d681SAndroid Build Coastguard Worker   Builder.CreateStore(Next, FSZero);
452*9880d681SAndroid Build Coastguard Worker }
453*9880d681SAndroid Build Coastguard Worker 
454*9880d681SAndroid Build Coastguard Worker // Calls to setjmp(p) are lowered to _setjmp3(p, 0) by the frontend.
455*9880d681SAndroid Build Coastguard Worker // The idea behind _setjmp3 is that it takes an optional number of personality
456*9880d681SAndroid Build Coastguard Worker // specific parameters to indicate how to restore the personality-specific frame
457*9880d681SAndroid Build Coastguard Worker // state when longjmp is initiated.  Typically, the current TryLevel is saved.
rewriteSetJmpCallSite(IRBuilder<> & Builder,Function & F,CallSite CS,Value * State)458*9880d681SAndroid Build Coastguard Worker void WinEHStatePass::rewriteSetJmpCallSite(IRBuilder<> &Builder, Function &F,
459*9880d681SAndroid Build Coastguard Worker                                            CallSite CS, Value *State) {
460*9880d681SAndroid Build Coastguard Worker   // Don't rewrite calls with a weird number of arguments.
461*9880d681SAndroid Build Coastguard Worker   if (CS.getNumArgOperands() != 2)
462*9880d681SAndroid Build Coastguard Worker     return;
463*9880d681SAndroid Build Coastguard Worker 
464*9880d681SAndroid Build Coastguard Worker   Instruction *Inst = CS.getInstruction();
465*9880d681SAndroid Build Coastguard Worker 
466*9880d681SAndroid Build Coastguard Worker   SmallVector<OperandBundleDef, 1> OpBundles;
467*9880d681SAndroid Build Coastguard Worker   CS.getOperandBundlesAsDefs(OpBundles);
468*9880d681SAndroid Build Coastguard Worker 
469*9880d681SAndroid Build Coastguard Worker   SmallVector<Value *, 3> OptionalArgs;
470*9880d681SAndroid Build Coastguard Worker   if (Personality == EHPersonality::MSVC_CXX) {
471*9880d681SAndroid Build Coastguard Worker     OptionalArgs.push_back(CxxLongjmpUnwind);
472*9880d681SAndroid Build Coastguard Worker     OptionalArgs.push_back(State);
473*9880d681SAndroid Build Coastguard Worker     OptionalArgs.push_back(emitEHLSDA(Builder, &F));
474*9880d681SAndroid Build Coastguard Worker   } else if (Personality == EHPersonality::MSVC_X86SEH) {
475*9880d681SAndroid Build Coastguard Worker     OptionalArgs.push_back(SehLongjmpUnwind);
476*9880d681SAndroid Build Coastguard Worker     OptionalArgs.push_back(State);
477*9880d681SAndroid Build Coastguard Worker     if (UseStackGuard)
478*9880d681SAndroid Build Coastguard Worker       OptionalArgs.push_back(Cookie);
479*9880d681SAndroid Build Coastguard Worker   } else {
480*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("unhandled personality!");
481*9880d681SAndroid Build Coastguard Worker   }
482*9880d681SAndroid Build Coastguard Worker 
483*9880d681SAndroid Build Coastguard Worker   SmallVector<Value *, 5> Args;
484*9880d681SAndroid Build Coastguard Worker   Args.push_back(
485*9880d681SAndroid Build Coastguard Worker       Builder.CreateBitCast(CS.getArgOperand(0), Builder.getInt8PtrTy()));
486*9880d681SAndroid Build Coastguard Worker   Args.push_back(Builder.getInt32(OptionalArgs.size()));
487*9880d681SAndroid Build Coastguard Worker   Args.append(OptionalArgs.begin(), OptionalArgs.end());
488*9880d681SAndroid Build Coastguard Worker 
489*9880d681SAndroid Build Coastguard Worker   CallSite NewCS;
490*9880d681SAndroid Build Coastguard Worker   if (CS.isCall()) {
491*9880d681SAndroid Build Coastguard Worker     auto *CI = cast<CallInst>(Inst);
492*9880d681SAndroid Build Coastguard Worker     CallInst *NewCI = Builder.CreateCall(SetJmp3, Args, OpBundles);
493*9880d681SAndroid Build Coastguard Worker     NewCI->setTailCallKind(CI->getTailCallKind());
494*9880d681SAndroid Build Coastguard Worker     NewCS = NewCI;
495*9880d681SAndroid Build Coastguard Worker   } else {
496*9880d681SAndroid Build Coastguard Worker     auto *II = cast<InvokeInst>(Inst);
497*9880d681SAndroid Build Coastguard Worker     NewCS = Builder.CreateInvoke(
498*9880d681SAndroid Build Coastguard Worker         SetJmp3, II->getNormalDest(), II->getUnwindDest(), Args, OpBundles);
499*9880d681SAndroid Build Coastguard Worker   }
500*9880d681SAndroid Build Coastguard Worker   NewCS.setCallingConv(CS.getCallingConv());
501*9880d681SAndroid Build Coastguard Worker   NewCS.setAttributes(CS.getAttributes());
502*9880d681SAndroid Build Coastguard Worker   NewCS->setDebugLoc(CS->getDebugLoc());
503*9880d681SAndroid Build Coastguard Worker 
504*9880d681SAndroid Build Coastguard Worker   Instruction *NewInst = NewCS.getInstruction();
505*9880d681SAndroid Build Coastguard Worker   NewInst->takeName(Inst);
506*9880d681SAndroid Build Coastguard Worker   Inst->replaceAllUsesWith(NewInst);
507*9880d681SAndroid Build Coastguard Worker   Inst->eraseFromParent();
508*9880d681SAndroid Build Coastguard Worker }
509*9880d681SAndroid Build Coastguard Worker 
510*9880d681SAndroid Build Coastguard Worker // Figure out what state we should assign calls in this block.
getBaseStateForBB(DenseMap<BasicBlock *,ColorVector> & BlockColors,WinEHFuncInfo & FuncInfo,BasicBlock * BB)511*9880d681SAndroid Build Coastguard Worker int WinEHStatePass::getBaseStateForBB(
512*9880d681SAndroid Build Coastguard Worker     DenseMap<BasicBlock *, ColorVector> &BlockColors, WinEHFuncInfo &FuncInfo,
513*9880d681SAndroid Build Coastguard Worker     BasicBlock *BB) {
514*9880d681SAndroid Build Coastguard Worker   int BaseState = ParentBaseState;
515*9880d681SAndroid Build Coastguard Worker   auto &BBColors = BlockColors[BB];
516*9880d681SAndroid Build Coastguard Worker 
517*9880d681SAndroid Build Coastguard Worker   assert(BBColors.size() == 1 && "multi-color BB not removed by preparation");
518*9880d681SAndroid Build Coastguard Worker   BasicBlock *FuncletEntryBB = BBColors.front();
519*9880d681SAndroid Build Coastguard Worker   if (auto *FuncletPad =
520*9880d681SAndroid Build Coastguard Worker           dyn_cast<FuncletPadInst>(FuncletEntryBB->getFirstNonPHI())) {
521*9880d681SAndroid Build Coastguard Worker     auto BaseStateI = FuncInfo.FuncletBaseStateMap.find(FuncletPad);
522*9880d681SAndroid Build Coastguard Worker     if (BaseStateI != FuncInfo.FuncletBaseStateMap.end())
523*9880d681SAndroid Build Coastguard Worker       BaseState = BaseStateI->second;
524*9880d681SAndroid Build Coastguard Worker   }
525*9880d681SAndroid Build Coastguard Worker 
526*9880d681SAndroid Build Coastguard Worker   return BaseState;
527*9880d681SAndroid Build Coastguard Worker }
528*9880d681SAndroid Build Coastguard Worker 
529*9880d681SAndroid Build Coastguard Worker // Calculate the state a call-site is in.
getStateForCallSite(DenseMap<BasicBlock *,ColorVector> & BlockColors,WinEHFuncInfo & FuncInfo,CallSite CS)530*9880d681SAndroid Build Coastguard Worker int WinEHStatePass::getStateForCallSite(
531*9880d681SAndroid Build Coastguard Worker     DenseMap<BasicBlock *, ColorVector> &BlockColors, WinEHFuncInfo &FuncInfo,
532*9880d681SAndroid Build Coastguard Worker     CallSite CS) {
533*9880d681SAndroid Build Coastguard Worker   if (auto *II = dyn_cast<InvokeInst>(CS.getInstruction())) {
534*9880d681SAndroid Build Coastguard Worker     // Look up the state number of the EH pad this unwinds to.
535*9880d681SAndroid Build Coastguard Worker     assert(FuncInfo.InvokeStateMap.count(II) && "invoke has no state!");
536*9880d681SAndroid Build Coastguard Worker     return FuncInfo.InvokeStateMap[II];
537*9880d681SAndroid Build Coastguard Worker   }
538*9880d681SAndroid Build Coastguard Worker   // Possibly throwing call instructions have no actions to take after
539*9880d681SAndroid Build Coastguard Worker   // an unwind. Ensure they are in the -1 state.
540*9880d681SAndroid Build Coastguard Worker   return getBaseStateForBB(BlockColors, FuncInfo, CS.getParent());
541*9880d681SAndroid Build Coastguard Worker }
542*9880d681SAndroid Build Coastguard Worker 
543*9880d681SAndroid Build Coastguard Worker // Calculate the intersection of all the FinalStates for a BasicBlock's
544*9880d681SAndroid Build Coastguard Worker // predecessors.
getPredState(DenseMap<BasicBlock *,int> & FinalStates,Function & F,int ParentBaseState,BasicBlock * BB)545*9880d681SAndroid Build Coastguard Worker static int getPredState(DenseMap<BasicBlock *, int> &FinalStates, Function &F,
546*9880d681SAndroid Build Coastguard Worker                         int ParentBaseState, BasicBlock *BB) {
547*9880d681SAndroid Build Coastguard Worker   // The entry block has no predecessors but we know that the prologue always
548*9880d681SAndroid Build Coastguard Worker   // sets us up with a fixed state.
549*9880d681SAndroid Build Coastguard Worker   if (&F.getEntryBlock() == BB)
550*9880d681SAndroid Build Coastguard Worker     return ParentBaseState;
551*9880d681SAndroid Build Coastguard Worker 
552*9880d681SAndroid Build Coastguard Worker   // This is an EH Pad, conservatively report this basic block as overdefined.
553*9880d681SAndroid Build Coastguard Worker   if (BB->isEHPad())
554*9880d681SAndroid Build Coastguard Worker     return OverdefinedState;
555*9880d681SAndroid Build Coastguard Worker 
556*9880d681SAndroid Build Coastguard Worker   int CommonState = OverdefinedState;
557*9880d681SAndroid Build Coastguard Worker   for (BasicBlock *PredBB : predecessors(BB)) {
558*9880d681SAndroid Build Coastguard Worker     // We didn't manage to get a state for one of these predecessors,
559*9880d681SAndroid Build Coastguard Worker     // conservatively report this basic block as overdefined.
560*9880d681SAndroid Build Coastguard Worker     auto PredEndState = FinalStates.find(PredBB);
561*9880d681SAndroid Build Coastguard Worker     if (PredEndState == FinalStates.end())
562*9880d681SAndroid Build Coastguard Worker       return OverdefinedState;
563*9880d681SAndroid Build Coastguard Worker 
564*9880d681SAndroid Build Coastguard Worker     // This code is reachable via exceptional control flow,
565*9880d681SAndroid Build Coastguard Worker     // conservatively report this basic block as overdefined.
566*9880d681SAndroid Build Coastguard Worker     if (isa<CatchReturnInst>(PredBB->getTerminator()))
567*9880d681SAndroid Build Coastguard Worker       return OverdefinedState;
568*9880d681SAndroid Build Coastguard Worker 
569*9880d681SAndroid Build Coastguard Worker     int PredState = PredEndState->second;
570*9880d681SAndroid Build Coastguard Worker     assert(PredState != OverdefinedState &&
571*9880d681SAndroid Build Coastguard Worker            "overdefined BBs shouldn't be in FinalStates");
572*9880d681SAndroid Build Coastguard Worker     if (CommonState == OverdefinedState)
573*9880d681SAndroid Build Coastguard Worker       CommonState = PredState;
574*9880d681SAndroid Build Coastguard Worker 
575*9880d681SAndroid Build Coastguard Worker     // At least two predecessors have different FinalStates,
576*9880d681SAndroid Build Coastguard Worker     // conservatively report this basic block as overdefined.
577*9880d681SAndroid Build Coastguard Worker     if (CommonState != PredState)
578*9880d681SAndroid Build Coastguard Worker       return OverdefinedState;
579*9880d681SAndroid Build Coastguard Worker   }
580*9880d681SAndroid Build Coastguard Worker 
581*9880d681SAndroid Build Coastguard Worker   return CommonState;
582*9880d681SAndroid Build Coastguard Worker }
583*9880d681SAndroid Build Coastguard Worker 
584*9880d681SAndroid Build Coastguard Worker // Calculate the intersection of all the InitialStates for a BasicBlock's
585*9880d681SAndroid Build Coastguard Worker // successors.
getSuccState(DenseMap<BasicBlock *,int> & InitialStates,Function & F,int ParentBaseState,BasicBlock * BB)586*9880d681SAndroid Build Coastguard Worker static int getSuccState(DenseMap<BasicBlock *, int> &InitialStates, Function &F,
587*9880d681SAndroid Build Coastguard Worker                         int ParentBaseState, BasicBlock *BB) {
588*9880d681SAndroid Build Coastguard Worker   // This block rejoins normal control flow,
589*9880d681SAndroid Build Coastguard Worker   // conservatively report this basic block as overdefined.
590*9880d681SAndroid Build Coastguard Worker   if (isa<CatchReturnInst>(BB->getTerminator()))
591*9880d681SAndroid Build Coastguard Worker     return OverdefinedState;
592*9880d681SAndroid Build Coastguard Worker 
593*9880d681SAndroid Build Coastguard Worker   int CommonState = OverdefinedState;
594*9880d681SAndroid Build Coastguard Worker   for (BasicBlock *SuccBB : successors(BB)) {
595*9880d681SAndroid Build Coastguard Worker     // We didn't manage to get a state for one of these predecessors,
596*9880d681SAndroid Build Coastguard Worker     // conservatively report this basic block as overdefined.
597*9880d681SAndroid Build Coastguard Worker     auto SuccStartState = InitialStates.find(SuccBB);
598*9880d681SAndroid Build Coastguard Worker     if (SuccStartState == InitialStates.end())
599*9880d681SAndroid Build Coastguard Worker       return OverdefinedState;
600*9880d681SAndroid Build Coastguard Worker 
601*9880d681SAndroid Build Coastguard Worker     // This is an EH Pad, conservatively report this basic block as overdefined.
602*9880d681SAndroid Build Coastguard Worker     if (SuccBB->isEHPad())
603*9880d681SAndroid Build Coastguard Worker       return OverdefinedState;
604*9880d681SAndroid Build Coastguard Worker 
605*9880d681SAndroid Build Coastguard Worker     int SuccState = SuccStartState->second;
606*9880d681SAndroid Build Coastguard Worker     assert(SuccState != OverdefinedState &&
607*9880d681SAndroid Build Coastguard Worker            "overdefined BBs shouldn't be in FinalStates");
608*9880d681SAndroid Build Coastguard Worker     if (CommonState == OverdefinedState)
609*9880d681SAndroid Build Coastguard Worker       CommonState = SuccState;
610*9880d681SAndroid Build Coastguard Worker 
611*9880d681SAndroid Build Coastguard Worker     // At least two successors have different InitialStates,
612*9880d681SAndroid Build Coastguard Worker     // conservatively report this basic block as overdefined.
613*9880d681SAndroid Build Coastguard Worker     if (CommonState != SuccState)
614*9880d681SAndroid Build Coastguard Worker       return OverdefinedState;
615*9880d681SAndroid Build Coastguard Worker   }
616*9880d681SAndroid Build Coastguard Worker 
617*9880d681SAndroid Build Coastguard Worker   return CommonState;
618*9880d681SAndroid Build Coastguard Worker }
619*9880d681SAndroid Build Coastguard Worker 
isStateStoreNeeded(EHPersonality Personality,CallSite CS)620*9880d681SAndroid Build Coastguard Worker bool WinEHStatePass::isStateStoreNeeded(EHPersonality Personality,
621*9880d681SAndroid Build Coastguard Worker                                         CallSite CS) {
622*9880d681SAndroid Build Coastguard Worker   if (!CS)
623*9880d681SAndroid Build Coastguard Worker     return false;
624*9880d681SAndroid Build Coastguard Worker 
625*9880d681SAndroid Build Coastguard Worker   // If the function touches memory, it needs a state store.
626*9880d681SAndroid Build Coastguard Worker   if (isAsynchronousEHPersonality(Personality))
627*9880d681SAndroid Build Coastguard Worker     return !CS.doesNotAccessMemory();
628*9880d681SAndroid Build Coastguard Worker 
629*9880d681SAndroid Build Coastguard Worker   // If the function throws, it needs a state store.
630*9880d681SAndroid Build Coastguard Worker   return !CS.doesNotThrow();
631*9880d681SAndroid Build Coastguard Worker }
632*9880d681SAndroid Build Coastguard Worker 
addStateStores(Function & F,WinEHFuncInfo & FuncInfo)633*9880d681SAndroid Build Coastguard Worker void WinEHStatePass::addStateStores(Function &F, WinEHFuncInfo &FuncInfo) {
634*9880d681SAndroid Build Coastguard Worker   // Mark the registration node. The backend needs to know which alloca it is so
635*9880d681SAndroid Build Coastguard Worker   // that it can recover the original frame pointer.
636*9880d681SAndroid Build Coastguard Worker   IRBuilder<> Builder(RegNode->getNextNode());
637*9880d681SAndroid Build Coastguard Worker   Value *RegNodeI8 = Builder.CreateBitCast(RegNode, Builder.getInt8PtrTy());
638*9880d681SAndroid Build Coastguard Worker   Builder.CreateCall(
639*9880d681SAndroid Build Coastguard Worker       Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_ehregnode),
640*9880d681SAndroid Build Coastguard Worker       {RegNodeI8});
641*9880d681SAndroid Build Coastguard Worker 
642*9880d681SAndroid Build Coastguard Worker   if (EHGuardNode) {
643*9880d681SAndroid Build Coastguard Worker     IRBuilder<> Builder(EHGuardNode->getNextNode());
644*9880d681SAndroid Build Coastguard Worker     Value *EHGuardNodeI8 =
645*9880d681SAndroid Build Coastguard Worker         Builder.CreateBitCast(EHGuardNode, Builder.getInt8PtrTy());
646*9880d681SAndroid Build Coastguard Worker     Builder.CreateCall(
647*9880d681SAndroid Build Coastguard Worker         Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_ehguard),
648*9880d681SAndroid Build Coastguard Worker         {EHGuardNodeI8});
649*9880d681SAndroid Build Coastguard Worker   }
650*9880d681SAndroid Build Coastguard Worker 
651*9880d681SAndroid Build Coastguard Worker   // Calculate state numbers.
652*9880d681SAndroid Build Coastguard Worker   if (isAsynchronousEHPersonality(Personality))
653*9880d681SAndroid Build Coastguard Worker     calculateSEHStateNumbers(&F, FuncInfo);
654*9880d681SAndroid Build Coastguard Worker   else
655*9880d681SAndroid Build Coastguard Worker     calculateWinCXXEHStateNumbers(&F, FuncInfo);
656*9880d681SAndroid Build Coastguard Worker 
657*9880d681SAndroid Build Coastguard Worker   // Iterate all the instructions and emit state number stores.
658*9880d681SAndroid Build Coastguard Worker   DenseMap<BasicBlock *, ColorVector> BlockColors = colorEHFunclets(F);
659*9880d681SAndroid Build Coastguard Worker   ReversePostOrderTraversal<Function *> RPOT(&F);
660*9880d681SAndroid Build Coastguard Worker 
661*9880d681SAndroid Build Coastguard Worker   // InitialStates yields the state of the first call-site for a BasicBlock.
662*9880d681SAndroid Build Coastguard Worker   DenseMap<BasicBlock *, int> InitialStates;
663*9880d681SAndroid Build Coastguard Worker   // FinalStates yields the state of the last call-site for a BasicBlock.
664*9880d681SAndroid Build Coastguard Worker   DenseMap<BasicBlock *, int> FinalStates;
665*9880d681SAndroid Build Coastguard Worker   // Worklist used to revisit BasicBlocks with indeterminate
666*9880d681SAndroid Build Coastguard Worker   // Initial/Final-States.
667*9880d681SAndroid Build Coastguard Worker   std::deque<BasicBlock *> Worklist;
668*9880d681SAndroid Build Coastguard Worker   // Fill in InitialStates and FinalStates for BasicBlocks with call-sites.
669*9880d681SAndroid Build Coastguard Worker   for (BasicBlock *BB : RPOT) {
670*9880d681SAndroid Build Coastguard Worker     int InitialState = OverdefinedState;
671*9880d681SAndroid Build Coastguard Worker     int FinalState;
672*9880d681SAndroid Build Coastguard Worker     if (&F.getEntryBlock() == BB)
673*9880d681SAndroid Build Coastguard Worker       InitialState = FinalState = ParentBaseState;
674*9880d681SAndroid Build Coastguard Worker     for (Instruction &I : *BB) {
675*9880d681SAndroid Build Coastguard Worker       CallSite CS(&I);
676*9880d681SAndroid Build Coastguard Worker       if (!isStateStoreNeeded(Personality, CS))
677*9880d681SAndroid Build Coastguard Worker         continue;
678*9880d681SAndroid Build Coastguard Worker 
679*9880d681SAndroid Build Coastguard Worker       int State = getStateForCallSite(BlockColors, FuncInfo, CS);
680*9880d681SAndroid Build Coastguard Worker       if (InitialState == OverdefinedState)
681*9880d681SAndroid Build Coastguard Worker         InitialState = State;
682*9880d681SAndroid Build Coastguard Worker       FinalState = State;
683*9880d681SAndroid Build Coastguard Worker     }
684*9880d681SAndroid Build Coastguard Worker     // No call-sites in this basic block? That's OK, we will come back to these
685*9880d681SAndroid Build Coastguard Worker     // in a later pass.
686*9880d681SAndroid Build Coastguard Worker     if (InitialState == OverdefinedState) {
687*9880d681SAndroid Build Coastguard Worker       Worklist.push_back(BB);
688*9880d681SAndroid Build Coastguard Worker       continue;
689*9880d681SAndroid Build Coastguard Worker     }
690*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << "X86WinEHState: " << BB->getName()
691*9880d681SAndroid Build Coastguard Worker                  << " InitialState=" << InitialState << '\n');
692*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << "X86WinEHState: " << BB->getName()
693*9880d681SAndroid Build Coastguard Worker                  << " FinalState=" << FinalState << '\n');
694*9880d681SAndroid Build Coastguard Worker     InitialStates.insert({BB, InitialState});
695*9880d681SAndroid Build Coastguard Worker     FinalStates.insert({BB, FinalState});
696*9880d681SAndroid Build Coastguard Worker   }
697*9880d681SAndroid Build Coastguard Worker 
698*9880d681SAndroid Build Coastguard Worker   // Try to fill-in InitialStates and FinalStates which have no call-sites.
699*9880d681SAndroid Build Coastguard Worker   while (!Worklist.empty()) {
700*9880d681SAndroid Build Coastguard Worker     BasicBlock *BB = Worklist.front();
701*9880d681SAndroid Build Coastguard Worker     Worklist.pop_front();
702*9880d681SAndroid Build Coastguard Worker     // This BasicBlock has already been figured out, nothing more we can do.
703*9880d681SAndroid Build Coastguard Worker     if (InitialStates.count(BB) != 0)
704*9880d681SAndroid Build Coastguard Worker       continue;
705*9880d681SAndroid Build Coastguard Worker 
706*9880d681SAndroid Build Coastguard Worker     int PredState = getPredState(FinalStates, F, ParentBaseState, BB);
707*9880d681SAndroid Build Coastguard Worker     if (PredState == OverdefinedState)
708*9880d681SAndroid Build Coastguard Worker       continue;
709*9880d681SAndroid Build Coastguard Worker 
710*9880d681SAndroid Build Coastguard Worker     // We successfully inferred this BasicBlock's state via it's predecessors;
711*9880d681SAndroid Build Coastguard Worker     // enqueue it's successors to see if we can infer their states.
712*9880d681SAndroid Build Coastguard Worker     InitialStates.insert({BB, PredState});
713*9880d681SAndroid Build Coastguard Worker     FinalStates.insert({BB, PredState});
714*9880d681SAndroid Build Coastguard Worker     for (BasicBlock *SuccBB : successors(BB))
715*9880d681SAndroid Build Coastguard Worker       Worklist.push_back(SuccBB);
716*9880d681SAndroid Build Coastguard Worker   }
717*9880d681SAndroid Build Coastguard Worker 
718*9880d681SAndroid Build Coastguard Worker   // Try to hoist stores from successors.
719*9880d681SAndroid Build Coastguard Worker   for (BasicBlock *BB : RPOT) {
720*9880d681SAndroid Build Coastguard Worker     int SuccState = getSuccState(InitialStates, F, ParentBaseState, BB);
721*9880d681SAndroid Build Coastguard Worker     if (SuccState == OverdefinedState)
722*9880d681SAndroid Build Coastguard Worker       continue;
723*9880d681SAndroid Build Coastguard Worker 
724*9880d681SAndroid Build Coastguard Worker     // Update our FinalState to reflect the common InitialState of our
725*9880d681SAndroid Build Coastguard Worker     // successors.
726*9880d681SAndroid Build Coastguard Worker     FinalStates.insert({BB, SuccState});
727*9880d681SAndroid Build Coastguard Worker   }
728*9880d681SAndroid Build Coastguard Worker 
729*9880d681SAndroid Build Coastguard Worker   // Finally, insert state stores before call-sites which transition us to a new
730*9880d681SAndroid Build Coastguard Worker   // state.
731*9880d681SAndroid Build Coastguard Worker   for (BasicBlock *BB : RPOT) {
732*9880d681SAndroid Build Coastguard Worker     auto &BBColors = BlockColors[BB];
733*9880d681SAndroid Build Coastguard Worker     BasicBlock *FuncletEntryBB = BBColors.front();
734*9880d681SAndroid Build Coastguard Worker     if (isa<CleanupPadInst>(FuncletEntryBB->getFirstNonPHI()))
735*9880d681SAndroid Build Coastguard Worker       continue;
736*9880d681SAndroid Build Coastguard Worker 
737*9880d681SAndroid Build Coastguard Worker     int PrevState = getPredState(FinalStates, F, ParentBaseState, BB);
738*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << "X86WinEHState: " << BB->getName()
739*9880d681SAndroid Build Coastguard Worker                  << " PrevState=" << PrevState << '\n');
740*9880d681SAndroid Build Coastguard Worker 
741*9880d681SAndroid Build Coastguard Worker     for (Instruction &I : *BB) {
742*9880d681SAndroid Build Coastguard Worker       CallSite CS(&I);
743*9880d681SAndroid Build Coastguard Worker       if (!isStateStoreNeeded(Personality, CS))
744*9880d681SAndroid Build Coastguard Worker         continue;
745*9880d681SAndroid Build Coastguard Worker 
746*9880d681SAndroid Build Coastguard Worker       int State = getStateForCallSite(BlockColors, FuncInfo, CS);
747*9880d681SAndroid Build Coastguard Worker       if (State != PrevState)
748*9880d681SAndroid Build Coastguard Worker         insertStateNumberStore(&I, State);
749*9880d681SAndroid Build Coastguard Worker       PrevState = State;
750*9880d681SAndroid Build Coastguard Worker     }
751*9880d681SAndroid Build Coastguard Worker 
752*9880d681SAndroid Build Coastguard Worker     // We might have hoisted a state store into this block, emit it now.
753*9880d681SAndroid Build Coastguard Worker     auto EndState = FinalStates.find(BB);
754*9880d681SAndroid Build Coastguard Worker     if (EndState != FinalStates.end())
755*9880d681SAndroid Build Coastguard Worker       if (EndState->second != PrevState)
756*9880d681SAndroid Build Coastguard Worker         insertStateNumberStore(BB->getTerminator(), EndState->second);
757*9880d681SAndroid Build Coastguard Worker   }
758*9880d681SAndroid Build Coastguard Worker 
759*9880d681SAndroid Build Coastguard Worker   SmallVector<CallSite, 1> SetJmp3CallSites;
760*9880d681SAndroid Build Coastguard Worker   for (BasicBlock *BB : RPOT) {
761*9880d681SAndroid Build Coastguard Worker     for (Instruction &I : *BB) {
762*9880d681SAndroid Build Coastguard Worker       CallSite CS(&I);
763*9880d681SAndroid Build Coastguard Worker       if (!CS)
764*9880d681SAndroid Build Coastguard Worker         continue;
765*9880d681SAndroid Build Coastguard Worker       if (CS.getCalledValue()->stripPointerCasts() !=
766*9880d681SAndroid Build Coastguard Worker           SetJmp3->stripPointerCasts())
767*9880d681SAndroid Build Coastguard Worker         continue;
768*9880d681SAndroid Build Coastguard Worker 
769*9880d681SAndroid Build Coastguard Worker       SetJmp3CallSites.push_back(CS);
770*9880d681SAndroid Build Coastguard Worker     }
771*9880d681SAndroid Build Coastguard Worker   }
772*9880d681SAndroid Build Coastguard Worker 
773*9880d681SAndroid Build Coastguard Worker   for (CallSite CS : SetJmp3CallSites) {
774*9880d681SAndroid Build Coastguard Worker     auto &BBColors = BlockColors[CS->getParent()];
775*9880d681SAndroid Build Coastguard Worker     BasicBlock *FuncletEntryBB = BBColors.front();
776*9880d681SAndroid Build Coastguard Worker     bool InCleanup = isa<CleanupPadInst>(FuncletEntryBB->getFirstNonPHI());
777*9880d681SAndroid Build Coastguard Worker 
778*9880d681SAndroid Build Coastguard Worker     IRBuilder<> Builder(CS.getInstruction());
779*9880d681SAndroid Build Coastguard Worker     Value *State;
780*9880d681SAndroid Build Coastguard Worker     if (InCleanup) {
781*9880d681SAndroid Build Coastguard Worker       Value *StateField =
782*9880d681SAndroid Build Coastguard Worker           Builder.CreateStructGEP(nullptr, RegNode, StateFieldIndex);
783*9880d681SAndroid Build Coastguard Worker       State = Builder.CreateLoad(StateField);
784*9880d681SAndroid Build Coastguard Worker     } else {
785*9880d681SAndroid Build Coastguard Worker       State = Builder.getInt32(getStateForCallSite(BlockColors, FuncInfo, CS));
786*9880d681SAndroid Build Coastguard Worker     }
787*9880d681SAndroid Build Coastguard Worker     rewriteSetJmpCallSite(Builder, F, CS, State);
788*9880d681SAndroid Build Coastguard Worker   }
789*9880d681SAndroid Build Coastguard Worker }
790*9880d681SAndroid Build Coastguard Worker 
insertStateNumberStore(Instruction * IP,int State)791*9880d681SAndroid Build Coastguard Worker void WinEHStatePass::insertStateNumberStore(Instruction *IP, int State) {
792*9880d681SAndroid Build Coastguard Worker   IRBuilder<> Builder(IP);
793*9880d681SAndroid Build Coastguard Worker   Value *StateField =
794*9880d681SAndroid Build Coastguard Worker       Builder.CreateStructGEP(nullptr, RegNode, StateFieldIndex);
795*9880d681SAndroid Build Coastguard Worker   Builder.CreateStore(Builder.getInt32(State), StateField);
796*9880d681SAndroid Build Coastguard Worker }
797