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