blob: 8a5aa40bc7f20b644df557e74fb90062f668d4e9 [file] [log] [blame]
Reid Kleckner0738a9c2015-05-05 17:44:16 +00001//===-- 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"
Reid Klecknerfe4d4912015-05-28 22:00:24 +000019#include "llvm/CodeGen/MachineModuleInfo.h"
Reid Kleckner0738a9c2015-05-05 17:44:16 +000020#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
36using namespace llvm;
37using namespace llvm::PatternMatch;
38
39#define DEBUG_TYPE "winehstate"
40
David Majnemer0ad363e2015-08-18 19:07:12 +000041namespace llvm { void initializeWinEHStatePassPass(PassRegistry &); }
42
Reid Kleckner0738a9c2015-05-05 17:44:16 +000043namespace {
44class WinEHStatePass : public FunctionPass {
45public:
46 static char ID; // Pass identification, replacement for typeid.
47
David Majnemer0ad363e2015-08-18 19:07:12 +000048 WinEHStatePass() : FunctionPass(ID) {
49 initializeWinEHStatePassPass(*PassRegistry::getPassRegistry());
50 }
Reid Kleckner0738a9c2015-05-05 17:44:16 +000051
52 bool runOnFunction(Function &Fn) override;
53
54 bool doInitialization(Module &M) override;
55
56 bool doFinalization(Module &M) override;
57
58 void getAnalysisUsage(AnalysisUsage &AU) const override;
59
60 const char *getPassName() const override {
61 return "Windows 32-bit x86 EH state insertion";
62 }
63
64private:
65 void emitExceptionRegistrationRecord(Function *F);
66
Reid Kleckner2bc93ca2015-06-10 01:02:30 +000067 void linkExceptionRegistration(IRBuilder<> &Builder, Function *Handler);
Reid Klecknerfe4d4912015-05-28 22:00:24 +000068 void unlinkExceptionRegistration(IRBuilder<> &Builder);
Reid Klecknerc20276d2015-11-17 21:10:25 +000069 void addStateStores(Function &F, WinEHFuncInfo &FuncInfo);
Reid Klecknerfe4d4912015-05-28 22:00:24 +000070 void insertStateNumberStore(Value *ParentRegNode, Instruction *IP, int State);
Reid Kleckner0738a9c2015-05-05 17:44:16 +000071
Reid Kleckner2632f0d2015-05-20 23:08:04 +000072 Value *emitEHLSDA(IRBuilder<> &Builder, Function *F);
73
74 Function *generateLSDAInEAXThunk(Function *ParentFunc);
75
Reid Kleckner0738a9c2015-05-05 17:44:16 +000076 // Module-level type getters.
Reid Klecknere6531a552015-05-29 22:57:46 +000077 Type *getEHLinkRegistrationType();
78 Type *getSEHRegistrationType();
79 Type *getCXXEHRegistrationType();
Reid Kleckner0738a9c2015-05-05 17:44:16 +000080
81 // Per-module data.
82 Module *TheModule = nullptr;
Reid Klecknere6531a552015-05-29 22:57:46 +000083 StructType *EHLinkRegistrationTy = nullptr;
84 StructType *CXXEHRegistrationTy = nullptr;
85 StructType *SEHRegistrationTy = nullptr;
Reid Klecknerb7403332015-06-08 22:43:32 +000086 Function *FrameRecover = nullptr;
87 Function *FrameAddress = nullptr;
88 Function *FrameEscape = nullptr;
Reid Kleckner94b704c2015-09-09 21:10:03 +000089 Function *RestoreFrame = nullptr;
Reid Kleckner0738a9c2015-05-05 17:44:16 +000090
91 // Per-function state
92 EHPersonality Personality = EHPersonality::Unknown;
93 Function *PersonalityFn = nullptr;
Reid Klecknerfe4d4912015-05-28 22:00:24 +000094
95 /// The stack allocation containing all EH data, including the link in the
96 /// fs:00 chain and the current state.
97 AllocaInst *RegNode = nullptr;
98
99 /// Struct type of RegNode. Used for GEPing.
100 Type *RegNodeTy = nullptr;
101
102 /// The index of the state field of RegNode.
103 int StateFieldIndex = ~0U;
104
105 /// The linked list node subobject inside of RegNode.
106 Value *Link = nullptr;
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000107};
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000108}
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000109
110FunctionPass *llvm::createX86WinEHStatePass() { return new WinEHStatePass(); }
111
112char WinEHStatePass::ID = 0;
113
David Majnemer0ad363e2015-08-18 19:07:12 +0000114INITIALIZE_PASS(WinEHStatePass, "x86-winehstate",
115 "Insert stores for EH state numbers", false, false)
116
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000117bool WinEHStatePass::doInitialization(Module &M) {
118 TheModule = &M;
Reid Kleckner60381792015-07-07 22:25:32 +0000119 FrameEscape = Intrinsic::getDeclaration(TheModule, Intrinsic::localescape);
120 FrameRecover = Intrinsic::getDeclaration(TheModule, Intrinsic::localrecover);
Reid Klecknerb7403332015-06-08 22:43:32 +0000121 FrameAddress = Intrinsic::getDeclaration(TheModule, Intrinsic::frameaddress);
Reid Kleckner94b704c2015-09-09 21:10:03 +0000122 RestoreFrame =
123 Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_restoreframe);
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000124 return false;
125}
126
127bool WinEHStatePass::doFinalization(Module &M) {
128 assert(TheModule == &M);
129 TheModule = nullptr;
Reid Klecknere6531a552015-05-29 22:57:46 +0000130 EHLinkRegistrationTy = nullptr;
131 CXXEHRegistrationTy = nullptr;
132 SEHRegistrationTy = nullptr;
Reid Klecknerb7403332015-06-08 22:43:32 +0000133 FrameEscape = nullptr;
134 FrameRecover = nullptr;
135 FrameAddress = nullptr;
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000136 return false;
137}
138
139void WinEHStatePass::getAnalysisUsage(AnalysisUsage &AU) const {
140 // This pass should only insert a stack allocation, memory accesses, and
Reid Kleckner60381792015-07-07 22:25:32 +0000141 // localrecovers.
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000142 AU.setPreservesCFG();
143}
144
145bool WinEHStatePass::runOnFunction(Function &F) {
Joseph Tremoulet2afea542015-10-06 20:28:16 +0000146 // Check the personality. Do nothing if this personality doesn't use funclets.
David Majnemer7fddecc2015-06-17 20:52:32 +0000147 if (!F.hasPersonalityFn())
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000148 return false;
149 PersonalityFn =
David Majnemer7fddecc2015-06-17 20:52:32 +0000150 dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts());
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000151 if (!PersonalityFn)
152 return false;
153 Personality = classifyEHPersonality(PersonalityFn);
Joseph Tremoulet2afea542015-10-06 20:28:16 +0000154 if (!isFuncletEHPersonality(Personality))
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000155 return false;
156
Reid Kleckner84ebff42015-09-16 17:19:44 +0000157 // Skip this function if there are no EH pads and we aren't using IR-level
158 // outlining.
David Majnemerbfa5b982015-10-10 00:04:29 +0000159 bool HasPads = false;
160 for (BasicBlock &BB : F) {
161 if (BB.isEHPad()) {
162 HasPads = true;
163 break;
Reid Kleckner84ebff42015-09-16 17:19:44 +0000164 }
Reid Kleckner84ebff42015-09-16 17:19:44 +0000165 }
David Majnemerbfa5b982015-10-10 00:04:29 +0000166 if (!HasPads)
167 return false;
Reid Kleckner84ebff42015-09-16 17:19:44 +0000168
Reid Kleckner173a7252015-05-29 21:58:11 +0000169 // Disable frame pointer elimination in this function.
170 // FIXME: Do the nested handlers need to keep the parent ebp in ebp, or can we
171 // use an arbitrary register?
172 F.addFnAttr("no-frame-pointer-elim", "true");
173
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000174 emitExceptionRegistrationRecord(&F);
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000175
Reid Klecknerc20276d2015-11-17 21:10:25 +0000176 // The state numbers calculated here in IR must agree with what we calculate
177 // later on for the MachineFunction. In particular, if an IR pass deletes an
178 // unreachable EH pad after this point before machine CFG construction, we
179 // will be in trouble. If this assumption is ever broken, we should turn the
180 // numbers into an immutable analysis pass.
181 WinEHFuncInfo FuncInfo;
182 addStateStores(F, FuncInfo);
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000183
184 // Reset per-function state.
185 PersonalityFn = nullptr;
186 Personality = EHPersonality::Unknown;
187 return true;
188}
189
190/// Get the common EH registration subobject:
Reid Kleckner2632f0d2015-05-20 23:08:04 +0000191/// typedef _EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE)(
192/// _EXCEPTION_RECORD *, void *, _CONTEXT *, void *);
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000193/// struct EHRegistrationNode {
194/// EHRegistrationNode *Next;
Reid Kleckner2632f0d2015-05-20 23:08:04 +0000195/// PEXCEPTION_ROUTINE Handler;
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000196/// };
Reid Klecknere6531a552015-05-29 22:57:46 +0000197Type *WinEHStatePass::getEHLinkRegistrationType() {
198 if (EHLinkRegistrationTy)
199 return EHLinkRegistrationTy;
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000200 LLVMContext &Context = TheModule->getContext();
Reid Klecknere6531a552015-05-29 22:57:46 +0000201 EHLinkRegistrationTy = StructType::create(Context, "EHRegistrationNode");
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000202 Type *FieldTys[] = {
Reid Klecknere6531a552015-05-29 22:57:46 +0000203 EHLinkRegistrationTy->getPointerTo(0), // EHRegistrationNode *Next
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000204 Type::getInt8PtrTy(Context) // EXCEPTION_DISPOSITION (*Handler)(...)
205 };
Reid Klecknere6531a552015-05-29 22:57:46 +0000206 EHLinkRegistrationTy->setBody(FieldTys, false);
207 return EHLinkRegistrationTy;
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000208}
209
210/// The __CxxFrameHandler3 registration node:
211/// struct CXXExceptionRegistration {
212/// void *SavedESP;
213/// EHRegistrationNode SubRecord;
214/// int32_t TryLevel;
215/// };
Reid Klecknere6531a552015-05-29 22:57:46 +0000216Type *WinEHStatePass::getCXXEHRegistrationType() {
217 if (CXXEHRegistrationTy)
218 return CXXEHRegistrationTy;
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000219 LLVMContext &Context = TheModule->getContext();
220 Type *FieldTys[] = {
221 Type::getInt8PtrTy(Context), // void *SavedESP
Reid Klecknere6531a552015-05-29 22:57:46 +0000222 getEHLinkRegistrationType(), // EHRegistrationNode SubRecord
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000223 Type::getInt32Ty(Context) // int32_t TryLevel
224 };
Reid Klecknere6531a552015-05-29 22:57:46 +0000225 CXXEHRegistrationTy =
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000226 StructType::create(FieldTys, "CXXExceptionRegistration");
Reid Klecknere6531a552015-05-29 22:57:46 +0000227 return CXXEHRegistrationTy;
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000228}
229
Reid Klecknere6531a552015-05-29 22:57:46 +0000230/// The _except_handler3/4 registration node:
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000231/// struct EH4ExceptionRegistration {
232/// void *SavedESP;
233/// _EXCEPTION_POINTERS *ExceptionPointers;
234/// EHRegistrationNode SubRecord;
235/// int32_t EncodedScopeTable;
236/// int32_t TryLevel;
237/// };
Reid Klecknere6531a552015-05-29 22:57:46 +0000238Type *WinEHStatePass::getSEHRegistrationType() {
239 if (SEHRegistrationTy)
240 return SEHRegistrationTy;
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000241 LLVMContext &Context = TheModule->getContext();
242 Type *FieldTys[] = {
243 Type::getInt8PtrTy(Context), // void *SavedESP
244 Type::getInt8PtrTy(Context), // void *ExceptionPointers
Reid Klecknere6531a552015-05-29 22:57:46 +0000245 getEHLinkRegistrationType(), // EHRegistrationNode SubRecord
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000246 Type::getInt32Ty(Context), // int32_t EncodedScopeTable
247 Type::getInt32Ty(Context) // int32_t TryLevel
248 };
Reid Klecknere6531a552015-05-29 22:57:46 +0000249 SEHRegistrationTy = StructType::create(FieldTys, "SEHExceptionRegistration");
250 return SEHRegistrationTy;
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000251}
252
253// Emit an exception registration record. These are stack allocations with the
254// common subobject of two pointers: the previous registration record (the old
255// fs:00) and the personality function for the current frame. The data before
256// and after that is personality function specific.
257void WinEHStatePass::emitExceptionRegistrationRecord(Function *F) {
258 assert(Personality == EHPersonality::MSVC_CXX ||
259 Personality == EHPersonality::MSVC_X86SEH);
260
261 StringRef PersonalityName = PersonalityFn->getName();
262 IRBuilder<> Builder(&F->getEntryBlock(), F->getEntryBlock().begin());
263 Type *Int8PtrType = Builder.getInt8PtrTy();
Reid Klecknere6531a552015-05-29 22:57:46 +0000264 if (Personality == EHPersonality::MSVC_CXX) {
265 RegNodeTy = getCXXEHRegistrationType();
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000266 RegNode = Builder.CreateAlloca(RegNodeTy);
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000267 // SavedESP = llvm.stacksave()
268 Value *SP = Builder.CreateCall(
David Blaikieff6409d2015-05-18 22:13:54 +0000269 Intrinsic::getDeclaration(TheModule, Intrinsic::stacksave), {});
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000270 Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
271 // TryLevel = -1
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000272 StateFieldIndex = 2;
Duncan P. N. Exon Smithd77de642015-10-19 21:48:29 +0000273 insertStateNumberStore(RegNode, &*Builder.GetInsertPoint(), -1);
Reid Kleckner2632f0d2015-05-20 23:08:04 +0000274 // Handler = __ehhandler$F
275 Function *Trampoline = generateLSDAInEAXThunk(F);
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000276 Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 1);
277 linkExceptionRegistration(Builder, Trampoline);
Reid Klecknere6531a552015-05-29 22:57:46 +0000278 } else if (Personality == EHPersonality::MSVC_X86SEH) {
279 // If _except_handler4 is in use, some additional guard checks and prologue
280 // stuff is required.
281 bool UseStackGuard = (PersonalityName == "_except_handler4");
282 RegNodeTy = getSEHRegistrationType();
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000283 RegNode = Builder.CreateAlloca(RegNodeTy);
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000284 // SavedESP = llvm.stacksave()
285 Value *SP = Builder.CreateCall(
David Blaikieff6409d2015-05-18 22:13:54 +0000286 Intrinsic::getDeclaration(TheModule, Intrinsic::stacksave), {});
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000287 Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
Reid Klecknere6531a552015-05-29 22:57:46 +0000288 // TryLevel = -2 / -1
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000289 StateFieldIndex = 4;
Duncan P. N. Exon Smithd77de642015-10-19 21:48:29 +0000290 insertStateNumberStore(RegNode, &*Builder.GetInsertPoint(),
Reid Klecknere6531a552015-05-29 22:57:46 +0000291 UseStackGuard ? -2 : -1);
Reid Kleckner2632f0d2015-05-20 23:08:04 +0000292 // ScopeTable = llvm.x86.seh.lsda(F)
293 Value *FI8 = Builder.CreateBitCast(F, Int8PtrType);
294 Value *LSDA = Builder.CreateCall(
295 Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_lsda), FI8);
Reid Klecknere6531a552015-05-29 22:57:46 +0000296 Type *Int32Ty = Type::getInt32Ty(TheModule->getContext());
297 LSDA = Builder.CreatePtrToInt(LSDA, Int32Ty);
298 // If using _except_handler4, xor the address of the table with
299 // __security_cookie.
300 if (UseStackGuard) {
301 Value *Cookie =
302 TheModule->getOrInsertGlobal("__security_cookie", Int32Ty);
303 Value *Val = Builder.CreateLoad(Int32Ty, Cookie);
304 LSDA = Builder.CreateXor(LSDA, Val);
305 }
306 Builder.CreateStore(LSDA, Builder.CreateStructGEP(RegNodeTy, RegNode, 3));
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000307 Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 2);
308 linkExceptionRegistration(Builder, PersonalityFn);
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000309 } else {
310 llvm_unreachable("unexpected personality function");
311 }
312
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000313 // Insert an unlink before all returns.
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000314 for (BasicBlock &BB : *F) {
315 TerminatorInst *T = BB.getTerminator();
316 if (!isa<ReturnInst>(T))
317 continue;
318 Builder.SetInsertPoint(T);
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000319 unlinkExceptionRegistration(Builder);
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000320 }
321}
322
Reid Kleckner2632f0d2015-05-20 23:08:04 +0000323Value *WinEHStatePass::emitEHLSDA(IRBuilder<> &Builder, Function *F) {
324 Value *FI8 = Builder.CreateBitCast(F, Type::getInt8PtrTy(F->getContext()));
325 return Builder.CreateCall(
326 Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_lsda), FI8);
327}
328
329/// Generate a thunk that puts the LSDA of ParentFunc in EAX and then calls
330/// PersonalityFn, forwarding the parameters passed to PEXCEPTION_ROUTINE:
331/// typedef _EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE)(
332/// _EXCEPTION_RECORD *, void *, _CONTEXT *, void *);
333/// We essentially want this code:
334/// movl $lsda, %eax
335/// jmpl ___CxxFrameHandler3
336Function *WinEHStatePass::generateLSDAInEAXThunk(Function *ParentFunc) {
337 LLVMContext &Context = ParentFunc->getContext();
338 Type *Int32Ty = Type::getInt32Ty(Context);
339 Type *Int8PtrType = Type::getInt8PtrTy(Context);
340 Type *ArgTys[5] = {Int8PtrType, Int8PtrType, Int8PtrType, Int8PtrType,
341 Int8PtrType};
342 FunctionType *TrampolineTy =
343 FunctionType::get(Int32Ty, makeArrayRef(&ArgTys[0], 4),
344 /*isVarArg=*/false);
345 FunctionType *TargetFuncTy =
346 FunctionType::get(Int32Ty, makeArrayRef(&ArgTys[0], 5),
347 /*isVarArg=*/false);
Reid Kleckner5f4dd922015-07-13 17:55:14 +0000348 Function *Trampoline =
349 Function::Create(TrampolineTy, GlobalValue::InternalLinkage,
350 Twine("__ehhandler$") + GlobalValue::getRealLinkageName(
351 ParentFunc->getName()),
352 TheModule);
Reid Kleckner2632f0d2015-05-20 23:08:04 +0000353 BasicBlock *EntryBB = BasicBlock::Create(Context, "entry", Trampoline);
354 IRBuilder<> Builder(EntryBB);
355 Value *LSDA = emitEHLSDA(Builder, ParentFunc);
356 Value *CastPersonality =
357 Builder.CreateBitCast(PersonalityFn, TargetFuncTy->getPointerTo());
358 auto AI = Trampoline->arg_begin();
Duncan P. N. Exon Smithd77de642015-10-19 21:48:29 +0000359 Value *Args[5] = {LSDA, &*AI++, &*AI++, &*AI++, &*AI++};
Reid Kleckner2632f0d2015-05-20 23:08:04 +0000360 CallInst *Call = Builder.CreateCall(CastPersonality, Args);
361 // Can't use musttail due to prototype mismatch, but we can use tail.
362 Call->setTailCall(true);
363 // Set inreg so we pass it in EAX.
364 Call->addAttribute(1, Attribute::InReg);
365 Builder.CreateRet(Call);
366 return Trampoline;
367}
368
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000369void WinEHStatePass::linkExceptionRegistration(IRBuilder<> &Builder,
Reid Kleckner2bc93ca2015-06-10 01:02:30 +0000370 Function *Handler) {
371 // Emit the .safeseh directive for this function.
372 Handler->addFnAttr("safeseh");
373
Reid Klecknere6531a552015-05-29 22:57:46 +0000374 Type *LinkTy = getEHLinkRegistrationType();
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000375 // Handler = Handler
Reid Kleckner2bc93ca2015-06-10 01:02:30 +0000376 Value *HandlerI8 = Builder.CreateBitCast(Handler, Builder.getInt8PtrTy());
377 Builder.CreateStore(HandlerI8, Builder.CreateStructGEP(LinkTy, Link, 1));
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000378 // Next = [fs:00]
379 Constant *FSZero =
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000380 Constant::getNullValue(LinkTy->getPointerTo()->getPointerTo(257));
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000381 Value *Next = Builder.CreateLoad(FSZero);
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000382 Builder.CreateStore(Next, Builder.CreateStructGEP(LinkTy, Link, 0));
383 // [fs:00] = Link
384 Builder.CreateStore(Link, FSZero);
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000385}
386
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000387void WinEHStatePass::unlinkExceptionRegistration(IRBuilder<> &Builder) {
388 // Clone Link into the current BB for better address mode folding.
389 if (auto *GEP = dyn_cast<GetElementPtrInst>(Link)) {
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000390 GEP = cast<GetElementPtrInst>(GEP->clone());
391 Builder.Insert(GEP);
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000392 Link = GEP;
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000393 }
Reid Klecknere6531a552015-05-29 22:57:46 +0000394 Type *LinkTy = getEHLinkRegistrationType();
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000395 // [fs:00] = Link->Next
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000396 Value *Next =
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000397 Builder.CreateLoad(Builder.CreateStructGEP(LinkTy, Link, 0));
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000398 Constant *FSZero =
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000399 Constant::getNullValue(LinkTy->getPointerTo()->getPointerTo(257));
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000400 Builder.CreateStore(Next, FSZero);
401}
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000402
Reid Klecknerc20276d2015-11-17 21:10:25 +0000403void WinEHStatePass::addStateStores(Function &F, WinEHFuncInfo &FuncInfo) {
404 // Mark the registration node. The backend needs to know which alloca it is so
405 // that it can recover the original frame pointer.
406 IRBuilder<> Builder(RegNode->getParent(), std::next(RegNode->getIterator()));
407 Value *RegNodeI8 = Builder.CreateBitCast(RegNode, Builder.getInt8PtrTy());
408 Builder.CreateCall(
409 Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_ehregnode),
410 {RegNodeI8});
Reid Kleckner14e77352015-10-09 23:34:53 +0000411
Reid Klecknerc20276d2015-11-17 21:10:25 +0000412 // Calculate state numbers.
413 if (isAsynchronousEHPersonality(Personality))
414 calculateSEHStateNumbers(&F, FuncInfo);
415 else
416 calculateWinCXXEHStateNumbers(&F, FuncInfo);
Reid Kleckner14e77352015-10-09 23:34:53 +0000417
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000418 // Iterate all the instructions and emit state number stores.
419 for (BasicBlock &BB : F) {
420 for (Instruction &I : BB) {
421 if (auto *CI = dyn_cast<CallInst>(&I)) {
422 // Possibly throwing call instructions have no actions to take after
423 // an unwind. Ensure they are in the -1 state.
424 if (CI->doesNotThrow())
425 continue;
Reid Klecknerc20276d2015-11-17 21:10:25 +0000426 insertStateNumberStore(RegNode, CI, -1);
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000427 } else if (auto *II = dyn_cast<InvokeInst>(&I)) {
428 // Look up the state number of the landingpad this unwinds to.
David Majnemer0ad363e2015-08-18 19:07:12 +0000429 Instruction *PadInst = II->getUnwindDest()->getFirstNonPHI();
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000430 // FIXME: Why does this assertion fail?
David Majnemer0ad363e2015-08-18 19:07:12 +0000431 //assert(FuncInfo.EHPadStateMap.count(PadInst) && "EH Pad has no state!");
432 int State = FuncInfo.EHPadStateMap[PadInst];
Reid Klecknerc20276d2015-11-17 21:10:25 +0000433 insertStateNumberStore(RegNode, II, State);
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000434 }
435 }
436 }
437}
438
439void WinEHStatePass::insertStateNumberStore(Value *ParentRegNode,
440 Instruction *IP, int State) {
441 IRBuilder<> Builder(IP);
442 Value *StateField =
443 Builder.CreateStructGEP(RegNodeTy, ParentRegNode, StateFieldIndex);
444 Builder.CreateStore(Builder.getInt32(State), StateField);
445}