[WinEH] Cache declarations of frame intrinsics
[oota-llvm.git] / lib / Target / X86 / X86WinEHState.cpp
1 //===-- X86WinEHState - Insert EH state updates for win32 exceptions ------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // All functions using an MSVC EH personality use an explicitly updated state
11 // number stored in an exception registration stack object. The registration
12 // object is linked into a thread-local chain of registrations stored at fs:00.
13 // This pass adds the registration object and EH state updates.
14 //
15 //===----------------------------------------------------------------------===//
16
17 #include "X86.h"
18 #include "llvm/Analysis/LibCallSemantics.h"
19 #include "llvm/CodeGen/MachineModuleInfo.h"
20 #include "llvm/CodeGen/Passes.h"
21 #include "llvm/CodeGen/WinEHFuncInfo.h"
22 #include "llvm/IR/Dominators.h"
23 #include "llvm/IR/Function.h"
24 #include "llvm/IR/IRBuilder.h"
25 #include "llvm/IR/Instructions.h"
26 #include "llvm/IR/IntrinsicInst.h"
27 #include "llvm/IR/Module.h"
28 #include "llvm/IR/PatternMatch.h"
29 #include "llvm/Pass.h"
30 #include "llvm/Support/Debug.h"
31 #include "llvm/Support/raw_ostream.h"
32 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
33 #include "llvm/Transforms/Utils/Cloning.h"
34 #include "llvm/Transforms/Utils/Local.h"
35
36 using namespace llvm;
37 using namespace llvm::PatternMatch;
38
39 #define DEBUG_TYPE "winehstate"
40
41 namespace {
42 class WinEHStatePass : public FunctionPass {
43 public:
44   static char ID; // Pass identification, replacement for typeid.
45
46   WinEHStatePass() : FunctionPass(ID) {}
47
48   bool runOnFunction(Function &Fn) override;
49
50   bool doInitialization(Module &M) override;
51
52   bool doFinalization(Module &M) override;
53
54   void getAnalysisUsage(AnalysisUsage &AU) const override;
55
56   const char *getPassName() const override {
57     return "Windows 32-bit x86 EH state insertion";
58   }
59
60 private:
61   void emitExceptionRegistrationRecord(Function *F);
62
63   void linkExceptionRegistration(IRBuilder<> &Builder, Value *Handler);
64   void unlinkExceptionRegistration(IRBuilder<> &Builder);
65   void addCXXStateStores(Function &F, MachineModuleInfo &MMI);
66   void addCXXStateStoresToFunclet(Value *ParentRegNode, WinEHFuncInfo &FuncInfo,
67                                   Function &F, int BaseState);
68   void insertStateNumberStore(Value *ParentRegNode, Instruction *IP, int State);
69
70   Value *emitEHLSDA(IRBuilder<> &Builder, Function *F);
71
72   Function *generateLSDAInEAXThunk(Function *ParentFunc);
73
74   int escapeRegNode(Function &F);
75
76   // Module-level type getters.
77   Type *getEHLinkRegistrationType();
78   Type *getSEHRegistrationType();
79   Type *getCXXEHRegistrationType();
80
81   // Per-module data.
82   Module *TheModule = nullptr;
83   StructType *EHLinkRegistrationTy = nullptr;
84   StructType *CXXEHRegistrationTy = nullptr;
85   StructType *SEHRegistrationTy = nullptr;
86   Function *FrameRecover = nullptr;
87   Function *FrameAddress = nullptr;
88   Function *FrameEscape = nullptr;
89
90   // Per-function state
91   EHPersonality Personality = EHPersonality::Unknown;
92   Function *PersonalityFn = nullptr;
93
94   /// The stack allocation containing all EH data, including the link in the
95   /// fs:00 chain and the current state.
96   AllocaInst *RegNode = nullptr;
97
98   /// Struct type of RegNode. Used for GEPing.
99   Type *RegNodeTy = nullptr;
100
101   /// The index of the state field of RegNode.
102   int StateFieldIndex = ~0U;
103
104   /// The linked list node subobject inside of RegNode.
105   Value *Link = nullptr;
106 };
107 }
108
109 FunctionPass *llvm::createX86WinEHStatePass() { return new WinEHStatePass(); }
110
111 char WinEHStatePass::ID = 0;
112
113 bool WinEHStatePass::doInitialization(Module &M) {
114   TheModule = &M;
115   FrameEscape = Intrinsic::getDeclaration(TheModule, Intrinsic::frameescape);
116   FrameRecover = Intrinsic::getDeclaration(TheModule, Intrinsic::framerecover);
117   FrameAddress = Intrinsic::getDeclaration(TheModule, Intrinsic::frameaddress);
118   return false;
119 }
120
121 bool WinEHStatePass::doFinalization(Module &M) {
122   assert(TheModule == &M);
123   TheModule = nullptr;
124   EHLinkRegistrationTy = nullptr;
125   CXXEHRegistrationTy = nullptr;
126   SEHRegistrationTy = nullptr;
127   FrameEscape = nullptr;
128   FrameRecover = nullptr;
129   FrameAddress = nullptr;
130   return false;
131 }
132
133 void WinEHStatePass::getAnalysisUsage(AnalysisUsage &AU) const {
134   // This pass should only insert a stack allocation, memory accesses, and
135   // framerecovers.
136   AU.setPreservesCFG();
137 }
138
139 bool WinEHStatePass::runOnFunction(Function &F) {
140   // If this is an outlined handler, don't do anything. We'll do state insertion
141   // for it in the parent.
142   StringRef WinEHParentName =
143       F.getFnAttribute("wineh-parent").getValueAsString();
144   if (WinEHParentName != F.getName() && !WinEHParentName.empty())
145     return false;
146
147   // Check the personality. Do nothing if this is not an MSVC personality.
148   LandingPadInst *LP = nullptr;
149   for (BasicBlock &BB : F) {
150     LP = BB.getLandingPadInst();
151     if (LP)
152       break;
153   }
154   if (!LP)
155     return false;
156   PersonalityFn =
157       dyn_cast<Function>(LP->getPersonalityFn()->stripPointerCasts());
158   if (!PersonalityFn)
159     return false;
160   Personality = classifyEHPersonality(PersonalityFn);
161   if (!isMSVCEHPersonality(Personality))
162     return false;
163
164   // Disable frame pointer elimination in this function.
165   // FIXME: Do the nested handlers need to keep the parent ebp in ebp, or can we
166   // use an arbitrary register?
167   F.addFnAttr("no-frame-pointer-elim", "true");
168
169   emitExceptionRegistrationRecord(&F);
170
171   auto *MMIPtr = getAnalysisIfAvailable<MachineModuleInfo>();
172   assert(MMIPtr && "MachineModuleInfo should always be available");
173   MachineModuleInfo &MMI = *MMIPtr;
174   if (Personality == EHPersonality::MSVC_CXX) {
175     addCXXStateStores(F, MMI);
176   }
177
178   // Reset per-function state.
179   PersonalityFn = nullptr;
180   Personality = EHPersonality::Unknown;
181   return true;
182 }
183
184 /// Get the common EH registration subobject:
185 ///   typedef _EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE)(
186 ///       _EXCEPTION_RECORD *, void *, _CONTEXT *, void *);
187 ///   struct EHRegistrationNode {
188 ///     EHRegistrationNode *Next;
189 ///     PEXCEPTION_ROUTINE Handler;
190 ///   };
191 Type *WinEHStatePass::getEHLinkRegistrationType() {
192   if (EHLinkRegistrationTy)
193     return EHLinkRegistrationTy;
194   LLVMContext &Context = TheModule->getContext();
195   EHLinkRegistrationTy = StructType::create(Context, "EHRegistrationNode");
196   Type *FieldTys[] = {
197       EHLinkRegistrationTy->getPointerTo(0), // EHRegistrationNode *Next
198       Type::getInt8PtrTy(Context) // EXCEPTION_DISPOSITION (*Handler)(...)
199   };
200   EHLinkRegistrationTy->setBody(FieldTys, false);
201   return EHLinkRegistrationTy;
202 }
203
204 /// The __CxxFrameHandler3 registration node:
205 ///   struct CXXExceptionRegistration {
206 ///     void *SavedESP;
207 ///     EHRegistrationNode SubRecord;
208 ///     int32_t TryLevel;
209 ///   };
210 Type *WinEHStatePass::getCXXEHRegistrationType() {
211   if (CXXEHRegistrationTy)
212     return CXXEHRegistrationTy;
213   LLVMContext &Context = TheModule->getContext();
214   Type *FieldTys[] = {
215       Type::getInt8PtrTy(Context), // void *SavedESP
216       getEHLinkRegistrationType(), // EHRegistrationNode SubRecord
217       Type::getInt32Ty(Context)    // int32_t TryLevel
218   };
219   CXXEHRegistrationTy =
220       StructType::create(FieldTys, "CXXExceptionRegistration");
221   return CXXEHRegistrationTy;
222 }
223
224 /// The _except_handler3/4 registration node:
225 ///   struct EH4ExceptionRegistration {
226 ///     void *SavedESP;
227 ///     _EXCEPTION_POINTERS *ExceptionPointers;
228 ///     EHRegistrationNode SubRecord;
229 ///     int32_t EncodedScopeTable;
230 ///     int32_t TryLevel;
231 ///   };
232 Type *WinEHStatePass::getSEHRegistrationType() {
233   if (SEHRegistrationTy)
234     return SEHRegistrationTy;
235   LLVMContext &Context = TheModule->getContext();
236   Type *FieldTys[] = {
237       Type::getInt8PtrTy(Context), // void *SavedESP
238       Type::getInt8PtrTy(Context), // void *ExceptionPointers
239       getEHLinkRegistrationType(), // EHRegistrationNode SubRecord
240       Type::getInt32Ty(Context),   // int32_t EncodedScopeTable
241       Type::getInt32Ty(Context)    // int32_t TryLevel
242   };
243   SEHRegistrationTy = StructType::create(FieldTys, "SEHExceptionRegistration");
244   return SEHRegistrationTy;
245 }
246
247 // Emit an exception registration record. These are stack allocations with the
248 // common subobject of two pointers: the previous registration record (the old
249 // fs:00) and the personality function for the current frame. The data before
250 // and after that is personality function specific.
251 void WinEHStatePass::emitExceptionRegistrationRecord(Function *F) {
252   assert(Personality == EHPersonality::MSVC_CXX ||
253          Personality == EHPersonality::MSVC_X86SEH);
254
255   StringRef PersonalityName = PersonalityFn->getName();
256   IRBuilder<> Builder(&F->getEntryBlock(), F->getEntryBlock().begin());
257   Type *Int8PtrType = Builder.getInt8PtrTy();
258   if (Personality == EHPersonality::MSVC_CXX) {
259     RegNodeTy = getCXXEHRegistrationType();
260     RegNode = Builder.CreateAlloca(RegNodeTy);
261     // FIXME: We can skip this in -GS- mode, when we figure that out.
262     // SavedESP = llvm.stacksave()
263     Value *SP = Builder.CreateCall(
264         Intrinsic::getDeclaration(TheModule, Intrinsic::stacksave), {});
265     Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
266     // TryLevel = -1
267     StateFieldIndex = 2;
268     insertStateNumberStore(RegNode, Builder.GetInsertPoint(), -1);
269     // Handler = __ehhandler$F
270     Function *Trampoline = generateLSDAInEAXThunk(F);
271     Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 1);
272     linkExceptionRegistration(Builder, Trampoline);
273   } else if (Personality == EHPersonality::MSVC_X86SEH) {
274     // If _except_handler4 is in use, some additional guard checks and prologue
275     // stuff is required.
276     bool UseStackGuard = (PersonalityName == "_except_handler4");
277     RegNodeTy = getSEHRegistrationType();
278     RegNode = Builder.CreateAlloca(RegNodeTy);
279     // SavedESP = llvm.stacksave()
280     Value *SP = Builder.CreateCall(
281         Intrinsic::getDeclaration(TheModule, Intrinsic::stacksave), {});
282     Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
283     // TryLevel = -2 / -1
284     StateFieldIndex = 4;
285     insertStateNumberStore(RegNode, Builder.GetInsertPoint(),
286                            UseStackGuard ? -2 : -1);
287     // ScopeTable = llvm.x86.seh.lsda(F)
288     Value *FI8 = Builder.CreateBitCast(F, Int8PtrType);
289     Value *LSDA = Builder.CreateCall(
290         Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_lsda), FI8);
291     Type *Int32Ty = Type::getInt32Ty(TheModule->getContext());
292     LSDA = Builder.CreatePtrToInt(LSDA, Int32Ty);
293     // If using _except_handler4, xor the address of the table with
294     // __security_cookie.
295     if (UseStackGuard) {
296       Value *Cookie =
297           TheModule->getOrInsertGlobal("__security_cookie", Int32Ty);
298       Value *Val = Builder.CreateLoad(Int32Ty, Cookie);
299       LSDA = Builder.CreateXor(LSDA, Val);
300     }
301     Builder.CreateStore(LSDA, Builder.CreateStructGEP(RegNodeTy, RegNode, 3));
302     Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 2);
303     linkExceptionRegistration(Builder, PersonalityFn);
304   } else {
305     llvm_unreachable("unexpected personality function");
306   }
307
308   // Insert an unlink before all returns.
309   for (BasicBlock &BB : *F) {
310     TerminatorInst *T = BB.getTerminator();
311     if (!isa<ReturnInst>(T))
312       continue;
313     Builder.SetInsertPoint(T);
314     unlinkExceptionRegistration(Builder);
315   }
316 }
317
318 Value *WinEHStatePass::emitEHLSDA(IRBuilder<> &Builder, Function *F) {
319   Value *FI8 = Builder.CreateBitCast(F, Type::getInt8PtrTy(F->getContext()));
320   return Builder.CreateCall(
321       Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_lsda), FI8);
322 }
323
324 /// Generate a thunk that puts the LSDA of ParentFunc in EAX and then calls
325 /// PersonalityFn, forwarding the parameters passed to PEXCEPTION_ROUTINE:
326 ///   typedef _EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE)(
327 ///       _EXCEPTION_RECORD *, void *, _CONTEXT *, void *);
328 /// We essentially want this code:
329 ///   movl $lsda, %eax
330 ///   jmpl ___CxxFrameHandler3
331 Function *WinEHStatePass::generateLSDAInEAXThunk(Function *ParentFunc) {
332   LLVMContext &Context = ParentFunc->getContext();
333   Type *Int32Ty = Type::getInt32Ty(Context);
334   Type *Int8PtrType = Type::getInt8PtrTy(Context);
335   Type *ArgTys[5] = {Int8PtrType, Int8PtrType, Int8PtrType, Int8PtrType,
336                      Int8PtrType};
337   FunctionType *TrampolineTy =
338       FunctionType::get(Int32Ty, makeArrayRef(&ArgTys[0], 4),
339                         /*isVarArg=*/false);
340   FunctionType *TargetFuncTy =
341       FunctionType::get(Int32Ty, makeArrayRef(&ArgTys[0], 5),
342                         /*isVarArg=*/false);
343   Function *Trampoline = Function::Create(
344       TrampolineTy, GlobalValue::InternalLinkage,
345       Twine("__ehhandler$") + ParentFunc->getName(), TheModule);
346   BasicBlock *EntryBB = BasicBlock::Create(Context, "entry", Trampoline);
347   IRBuilder<> Builder(EntryBB);
348   Value *LSDA = emitEHLSDA(Builder, ParentFunc);
349   Value *CastPersonality =
350       Builder.CreateBitCast(PersonalityFn, TargetFuncTy->getPointerTo());
351   auto AI = Trampoline->arg_begin();
352   Value *Args[5] = {LSDA, AI++, AI++, AI++, AI++};
353   CallInst *Call = Builder.CreateCall(CastPersonality, Args);
354   // Can't use musttail due to prototype mismatch, but we can use tail.
355   Call->setTailCall(true);
356   // Set inreg so we pass it in EAX.
357   Call->addAttribute(1, Attribute::InReg);
358   Builder.CreateRet(Call);
359   return Trampoline;
360 }
361
362 void WinEHStatePass::linkExceptionRegistration(IRBuilder<> &Builder,
363                                                Value *Handler) {
364   Type *LinkTy = getEHLinkRegistrationType();
365   // Handler = Handler
366   Handler = Builder.CreateBitCast(Handler, Builder.getInt8PtrTy());
367   Builder.CreateStore(Handler, Builder.CreateStructGEP(LinkTy, Link, 1));
368   // Next = [fs:00]
369   Constant *FSZero =
370       Constant::getNullValue(LinkTy->getPointerTo()->getPointerTo(257));
371   Value *Next = Builder.CreateLoad(FSZero);
372   Builder.CreateStore(Next, Builder.CreateStructGEP(LinkTy, Link, 0));
373   // [fs:00] = Link
374   Builder.CreateStore(Link, FSZero);
375 }
376
377 void WinEHStatePass::unlinkExceptionRegistration(IRBuilder<> &Builder) {
378   // Clone Link into the current BB for better address mode folding.
379   if (auto *GEP = dyn_cast<GetElementPtrInst>(Link)) {
380     GEP = cast<GetElementPtrInst>(GEP->clone());
381     Builder.Insert(GEP);
382     Link = GEP;
383   }
384   Type *LinkTy = getEHLinkRegistrationType();
385   // [fs:00] = Link->Next
386   Value *Next =
387       Builder.CreateLoad(Builder.CreateStructGEP(LinkTy, Link, 0));
388   Constant *FSZero =
389       Constant::getNullValue(LinkTy->getPointerTo()->getPointerTo(257));
390   Builder.CreateStore(Next, FSZero);
391 }
392
393 void WinEHStatePass::addCXXStateStores(Function &F, MachineModuleInfo &MMI) {
394   WinEHFuncInfo &FuncInfo = MMI.getWinEHFuncInfo(&F);
395   calculateWinCXXEHStateNumbers(&F, FuncInfo);
396
397   // The base state for the parent is -1.
398   addCXXStateStoresToFunclet(RegNode, FuncInfo, F, -1);
399
400   // Set up RegNodeEscapeIndex
401   int RegNodeEscapeIndex = escapeRegNode(F);
402
403   // Only insert stores in catch handlers.
404   Constant *FI8 =
405       ConstantExpr::getBitCast(&F, Type::getInt8PtrTy(TheModule->getContext()));
406   for (auto P : FuncInfo.HandlerBaseState) {
407     Function *Handler = const_cast<Function *>(P.first);
408     int BaseState = P.second;
409     IRBuilder<> Builder(&Handler->getEntryBlock(),
410                         Handler->getEntryBlock().begin());
411     // FIXME: Find and reuse such a call if present.
412     Value *ParentFP = Builder.CreateCall(FrameAddress, {Builder.getInt32(1)});
413     Value *RecoveredRegNode = Builder.CreateCall(
414         FrameRecover, {FI8, ParentFP, Builder.getInt32(RegNodeEscapeIndex)});
415     RecoveredRegNode =
416         Builder.CreateBitCast(RecoveredRegNode, RegNodeTy->getPointerTo(0));
417     addCXXStateStoresToFunclet(RecoveredRegNode, FuncInfo, *Handler, BaseState);
418   }
419 }
420
421 /// Escape RegNode so that we can access it from child handlers. Find the call
422 /// to frameescape, if any, in the entry block and append RegNode to the list
423 /// of arguments.
424 int WinEHStatePass::escapeRegNode(Function &F) {
425   // Find the call to frameescape and extract its arguments.
426   IntrinsicInst *EscapeCall = nullptr;
427   for (Instruction &I : F.getEntryBlock()) {
428     IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I);
429     if (II && II->getIntrinsicID() == Intrinsic::frameescape) {
430       EscapeCall = II;
431       break;
432     }
433   }
434   SmallVector<Value *, 8> Args;
435   if (EscapeCall) {
436     auto Ops = EscapeCall->arg_operands();
437     Args.append(Ops.begin(), Ops.end());
438   }
439   Args.push_back(RegNode);
440
441   // Replace the call (if it exists) with new one. Otherwise, insert at the end
442   // of the entry block.
443   IRBuilder<> Builder(&F.getEntryBlock(),
444                       EscapeCall ? EscapeCall : F.getEntryBlock().end());
445   Builder.CreateCall(FrameEscape, Args);
446   if (EscapeCall)
447     EscapeCall->eraseFromParent();
448   return Args.size() - 1;
449 }
450
451 void WinEHStatePass::addCXXStateStoresToFunclet(Value *ParentRegNode,
452                                                 WinEHFuncInfo &FuncInfo,
453                                                 Function &F, int BaseState) {
454   // Iterate all the instructions and emit state number stores.
455   for (BasicBlock &BB : F) {
456     for (Instruction &I : BB) {
457       if (auto *CI = dyn_cast<CallInst>(&I)) {
458         // Possibly throwing call instructions have no actions to take after
459         // an unwind. Ensure they are in the -1 state.
460         if (CI->doesNotThrow())
461           continue;
462         insertStateNumberStore(ParentRegNode, CI, BaseState);
463       } else if (auto *II = dyn_cast<InvokeInst>(&I)) {
464         // Look up the state number of the landingpad this unwinds to.
465         LandingPadInst *LPI = II->getUnwindDest()->getLandingPadInst();
466         // FIXME: Why does this assertion fail?
467         //assert(FuncInfo.LandingPadStateMap.count(LPI) && "LP has no state!");
468         int State = FuncInfo.LandingPadStateMap[LPI];
469         insertStateNumberStore(ParentRegNode, II, State);
470       }
471     }
472   }
473 }
474
475 void WinEHStatePass::insertStateNumberStore(Value *ParentRegNode,
476                                             Instruction *IP, int State) {
477   IRBuilder<> Builder(IP);
478   Value *StateField =
479       Builder.CreateStructGEP(RegNodeTy, ParentRegNode, StateFieldIndex);
480   Builder.CreateStore(Builder.getInt32(State), StateField);
481 }