blob: e0a476f0f3e7bf2966be3625440967aa42ccb44c [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"
David Majnemer70497c62015-12-02 23:06:39 +000018#include "llvm/Analysis/EHPersonalities.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/WinEHFuncInfo.h"
Reid Kleckner0738a9c2015-05-05 17:44:16 +000021#include "llvm/IR/Instructions.h"
22#include "llvm/IR/IntrinsicInst.h"
David Majnemerefb41742016-02-01 04:28:59 +000023#include "llvm/IR/IRBuilder.h"
Reid Kleckner0738a9c2015-05-05 17:44:16 +000024#include "llvm/IR/Module.h"
Reid Kleckner0738a9c2015-05-05 17:44:16 +000025#include "llvm/Pass.h"
Reid Kleckner0738a9c2015-05-05 17:44:16 +000026
27using namespace llvm;
Reid Kleckner0738a9c2015-05-05 17:44:16 +000028
29#define DEBUG_TYPE "winehstate"
30
David Majnemerefb41742016-02-01 04:28:59 +000031namespace llvm {
32void initializeWinEHStatePassPass(PassRegistry &);
33}
David Majnemer0ad363e2015-08-18 19:07:12 +000034
Reid Kleckner0738a9c2015-05-05 17:44:16 +000035namespace {
36class WinEHStatePass : public FunctionPass {
37public:
38 static char ID; // Pass identification, replacement for typeid.
39
David Majnemer0ad363e2015-08-18 19:07:12 +000040 WinEHStatePass() : FunctionPass(ID) {
41 initializeWinEHStatePassPass(*PassRegistry::getPassRegistry());
42 }
Reid Kleckner0738a9c2015-05-05 17:44:16 +000043
44 bool runOnFunction(Function &Fn) override;
45
46 bool doInitialization(Module &M) override;
47
48 bool doFinalization(Module &M) override;
49
50 void getAnalysisUsage(AnalysisUsage &AU) const override;
51
52 const char *getPassName() const override {
53 return "Windows 32-bit x86 EH state insertion";
54 }
55
56private:
57 void emitExceptionRegistrationRecord(Function *F);
58
Reid Kleckner2bc93ca2015-06-10 01:02:30 +000059 void linkExceptionRegistration(IRBuilder<> &Builder, Function *Handler);
Reid Klecknerfe4d4912015-05-28 22:00:24 +000060 void unlinkExceptionRegistration(IRBuilder<> &Builder);
Reid Klecknerc20276d2015-11-17 21:10:25 +000061 void addStateStores(Function &F, WinEHFuncInfo &FuncInfo);
David Majnemerefb41742016-02-01 04:28:59 +000062 void insertStateNumberStore(Instruction *IP, int State);
Reid Kleckner0738a9c2015-05-05 17:44:16 +000063
Reid Kleckner2632f0d2015-05-20 23:08:04 +000064 Value *emitEHLSDA(IRBuilder<> &Builder, Function *F);
65
66 Function *generateLSDAInEAXThunk(Function *ParentFunc);
67
Reid Kleckner0738a9c2015-05-05 17:44:16 +000068 // Module-level type getters.
Reid Klecknere6531a552015-05-29 22:57:46 +000069 Type *getEHLinkRegistrationType();
70 Type *getSEHRegistrationType();
71 Type *getCXXEHRegistrationType();
Reid Kleckner0738a9c2015-05-05 17:44:16 +000072
73 // Per-module data.
74 Module *TheModule = nullptr;
Reid Klecknere6531a552015-05-29 22:57:46 +000075 StructType *EHLinkRegistrationTy = nullptr;
76 StructType *CXXEHRegistrationTy = nullptr;
77 StructType *SEHRegistrationTy = nullptr;
Reid Klecknerb7403332015-06-08 22:43:32 +000078 Function *FrameRecover = nullptr;
79 Function *FrameAddress = nullptr;
80 Function *FrameEscape = nullptr;
Reid Kleckner0738a9c2015-05-05 17:44:16 +000081
82 // Per-function state
83 EHPersonality Personality = EHPersonality::Unknown;
84 Function *PersonalityFn = nullptr;
Reid Klecknerfe4d4912015-05-28 22:00:24 +000085
86 /// The stack allocation containing all EH data, including the link in the
87 /// fs:00 chain and the current state.
88 AllocaInst *RegNode = nullptr;
89
Reid Klecknerfe4d4912015-05-28 22:00:24 +000090 /// The index of the state field of RegNode.
91 int StateFieldIndex = ~0U;
92
93 /// The linked list node subobject inside of RegNode.
94 Value *Link = nullptr;
Reid Kleckner0738a9c2015-05-05 17:44:16 +000095};
Alexander Kornienkof00654e2015-06-23 09:49:53 +000096}
Reid Kleckner0738a9c2015-05-05 17:44:16 +000097
98FunctionPass *llvm::createX86WinEHStatePass() { return new WinEHStatePass(); }
99
100char WinEHStatePass::ID = 0;
101
David Majnemer0ad363e2015-08-18 19:07:12 +0000102INITIALIZE_PASS(WinEHStatePass, "x86-winehstate",
103 "Insert stores for EH state numbers", false, false)
104
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000105bool WinEHStatePass::doInitialization(Module &M) {
106 TheModule = &M;
Reid Kleckner60381792015-07-07 22:25:32 +0000107 FrameEscape = Intrinsic::getDeclaration(TheModule, Intrinsic::localescape);
108 FrameRecover = Intrinsic::getDeclaration(TheModule, Intrinsic::localrecover);
Reid Klecknerb7403332015-06-08 22:43:32 +0000109 FrameAddress = Intrinsic::getDeclaration(TheModule, Intrinsic::frameaddress);
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000110 return false;
111}
112
113bool WinEHStatePass::doFinalization(Module &M) {
114 assert(TheModule == &M);
115 TheModule = nullptr;
Reid Klecknere6531a552015-05-29 22:57:46 +0000116 EHLinkRegistrationTy = nullptr;
117 CXXEHRegistrationTy = nullptr;
118 SEHRegistrationTy = nullptr;
Reid Klecknerb7403332015-06-08 22:43:32 +0000119 FrameEscape = nullptr;
120 FrameRecover = nullptr;
121 FrameAddress = nullptr;
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000122 return false;
123}
124
125void WinEHStatePass::getAnalysisUsage(AnalysisUsage &AU) const {
126 // This pass should only insert a stack allocation, memory accesses, and
Reid Kleckner60381792015-07-07 22:25:32 +0000127 // localrecovers.
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000128 AU.setPreservesCFG();
129}
130
131bool WinEHStatePass::runOnFunction(Function &F) {
Joseph Tremoulet2afea542015-10-06 20:28:16 +0000132 // Check the personality. Do nothing if this personality doesn't use funclets.
David Majnemer7fddecc2015-06-17 20:52:32 +0000133 if (!F.hasPersonalityFn())
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000134 return false;
135 PersonalityFn =
David Majnemer7fddecc2015-06-17 20:52:32 +0000136 dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts());
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000137 if (!PersonalityFn)
138 return false;
139 Personality = classifyEHPersonality(PersonalityFn);
Joseph Tremoulet2afea542015-10-06 20:28:16 +0000140 if (!isFuncletEHPersonality(Personality))
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000141 return false;
142
Reid Kleckner84ebff42015-09-16 17:19:44 +0000143 // Skip this function if there are no EH pads and we aren't using IR-level
144 // outlining.
David Majnemerbfa5b982015-10-10 00:04:29 +0000145 bool HasPads = false;
146 for (BasicBlock &BB : F) {
147 if (BB.isEHPad()) {
148 HasPads = true;
149 break;
Reid Kleckner84ebff42015-09-16 17:19:44 +0000150 }
Reid Kleckner84ebff42015-09-16 17:19:44 +0000151 }
David Majnemerbfa5b982015-10-10 00:04:29 +0000152 if (!HasPads)
153 return false;
Reid Kleckner84ebff42015-09-16 17:19:44 +0000154
Reid Kleckner173a7252015-05-29 21:58:11 +0000155 // Disable frame pointer elimination in this function.
156 // FIXME: Do the nested handlers need to keep the parent ebp in ebp, or can we
157 // use an arbitrary register?
158 F.addFnAttr("no-frame-pointer-elim", "true");
159
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000160 emitExceptionRegistrationRecord(&F);
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000161
Reid Klecknerc20276d2015-11-17 21:10:25 +0000162 // The state numbers calculated here in IR must agree with what we calculate
163 // later on for the MachineFunction. In particular, if an IR pass deletes an
164 // unreachable EH pad after this point before machine CFG construction, we
165 // will be in trouble. If this assumption is ever broken, we should turn the
166 // numbers into an immutable analysis pass.
167 WinEHFuncInfo FuncInfo;
168 addStateStores(F, FuncInfo);
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000169
170 // Reset per-function state.
171 PersonalityFn = nullptr;
172 Personality = EHPersonality::Unknown;
173 return true;
174}
175
176/// Get the common EH registration subobject:
Reid Kleckner2632f0d2015-05-20 23:08:04 +0000177/// typedef _EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE)(
178/// _EXCEPTION_RECORD *, void *, _CONTEXT *, void *);
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000179/// struct EHRegistrationNode {
180/// EHRegistrationNode *Next;
Reid Kleckner2632f0d2015-05-20 23:08:04 +0000181/// PEXCEPTION_ROUTINE Handler;
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000182/// };
Reid Klecknere6531a552015-05-29 22:57:46 +0000183Type *WinEHStatePass::getEHLinkRegistrationType() {
184 if (EHLinkRegistrationTy)
185 return EHLinkRegistrationTy;
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000186 LLVMContext &Context = TheModule->getContext();
Reid Klecknere6531a552015-05-29 22:57:46 +0000187 EHLinkRegistrationTy = StructType::create(Context, "EHRegistrationNode");
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000188 Type *FieldTys[] = {
Reid Klecknere6531a552015-05-29 22:57:46 +0000189 EHLinkRegistrationTy->getPointerTo(0), // EHRegistrationNode *Next
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000190 Type::getInt8PtrTy(Context) // EXCEPTION_DISPOSITION (*Handler)(...)
191 };
Reid Klecknere6531a552015-05-29 22:57:46 +0000192 EHLinkRegistrationTy->setBody(FieldTys, false);
193 return EHLinkRegistrationTy;
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000194}
195
196/// The __CxxFrameHandler3 registration node:
197/// struct CXXExceptionRegistration {
198/// void *SavedESP;
199/// EHRegistrationNode SubRecord;
200/// int32_t TryLevel;
201/// };
Reid Klecknere6531a552015-05-29 22:57:46 +0000202Type *WinEHStatePass::getCXXEHRegistrationType() {
203 if (CXXEHRegistrationTy)
204 return CXXEHRegistrationTy;
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000205 LLVMContext &Context = TheModule->getContext();
206 Type *FieldTys[] = {
207 Type::getInt8PtrTy(Context), // void *SavedESP
Reid Klecknere6531a552015-05-29 22:57:46 +0000208 getEHLinkRegistrationType(), // EHRegistrationNode SubRecord
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000209 Type::getInt32Ty(Context) // int32_t TryLevel
210 };
Reid Klecknere6531a552015-05-29 22:57:46 +0000211 CXXEHRegistrationTy =
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000212 StructType::create(FieldTys, "CXXExceptionRegistration");
Reid Klecknere6531a552015-05-29 22:57:46 +0000213 return CXXEHRegistrationTy;
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000214}
215
Reid Klecknere6531a552015-05-29 22:57:46 +0000216/// The _except_handler3/4 registration node:
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000217/// struct EH4ExceptionRegistration {
218/// void *SavedESP;
219/// _EXCEPTION_POINTERS *ExceptionPointers;
220/// EHRegistrationNode SubRecord;
221/// int32_t EncodedScopeTable;
222/// int32_t TryLevel;
223/// };
Reid Klecknere6531a552015-05-29 22:57:46 +0000224Type *WinEHStatePass::getSEHRegistrationType() {
225 if (SEHRegistrationTy)
226 return SEHRegistrationTy;
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000227 LLVMContext &Context = TheModule->getContext();
228 Type *FieldTys[] = {
229 Type::getInt8PtrTy(Context), // void *SavedESP
230 Type::getInt8PtrTy(Context), // void *ExceptionPointers
Reid Klecknere6531a552015-05-29 22:57:46 +0000231 getEHLinkRegistrationType(), // EHRegistrationNode SubRecord
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000232 Type::getInt32Ty(Context), // int32_t EncodedScopeTable
233 Type::getInt32Ty(Context) // int32_t TryLevel
234 };
Reid Klecknere6531a552015-05-29 22:57:46 +0000235 SEHRegistrationTy = StructType::create(FieldTys, "SEHExceptionRegistration");
236 return SEHRegistrationTy;
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000237}
238
239// Emit an exception registration record. These are stack allocations with the
240// common subobject of two pointers: the previous registration record (the old
241// fs:00) and the personality function for the current frame. The data before
242// and after that is personality function specific.
243void WinEHStatePass::emitExceptionRegistrationRecord(Function *F) {
244 assert(Personality == EHPersonality::MSVC_CXX ||
245 Personality == EHPersonality::MSVC_X86SEH);
246
David Majnemerefb41742016-02-01 04:28:59 +0000247 // Struct type of RegNode. Used for GEPing.
248 Type *RegNodeTy;
249
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000250 StringRef PersonalityName = PersonalityFn->getName();
251 IRBuilder<> Builder(&F->getEntryBlock(), F->getEntryBlock().begin());
252 Type *Int8PtrType = Builder.getInt8PtrTy();
Reid Klecknere6531a552015-05-29 22:57:46 +0000253 if (Personality == EHPersonality::MSVC_CXX) {
254 RegNodeTy = getCXXEHRegistrationType();
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000255 RegNode = Builder.CreateAlloca(RegNodeTy);
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000256 // SavedESP = llvm.stacksave()
257 Value *SP = Builder.CreateCall(
David Blaikieff6409d2015-05-18 22:13:54 +0000258 Intrinsic::getDeclaration(TheModule, Intrinsic::stacksave), {});
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000259 Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
260 // TryLevel = -1
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000261 StateFieldIndex = 2;
David Majnemerefb41742016-02-01 04:28:59 +0000262 insertStateNumberStore(&*Builder.GetInsertPoint(), -1);
Reid Kleckner2632f0d2015-05-20 23:08:04 +0000263 // Handler = __ehhandler$F
264 Function *Trampoline = generateLSDAInEAXThunk(F);
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000265 Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 1);
266 linkExceptionRegistration(Builder, Trampoline);
Reid Klecknere6531a552015-05-29 22:57:46 +0000267 } else if (Personality == EHPersonality::MSVC_X86SEH) {
268 // If _except_handler4 is in use, some additional guard checks and prologue
269 // stuff is required.
270 bool UseStackGuard = (PersonalityName == "_except_handler4");
271 RegNodeTy = getSEHRegistrationType();
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000272 RegNode = Builder.CreateAlloca(RegNodeTy);
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000273 // SavedESP = llvm.stacksave()
274 Value *SP = Builder.CreateCall(
David Blaikieff6409d2015-05-18 22:13:54 +0000275 Intrinsic::getDeclaration(TheModule, Intrinsic::stacksave), {});
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000276 Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
Reid Klecknere6531a552015-05-29 22:57:46 +0000277 // TryLevel = -2 / -1
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000278 StateFieldIndex = 4;
David Majnemerefb41742016-02-01 04:28:59 +0000279 insertStateNumberStore(&*Builder.GetInsertPoint(), UseStackGuard ? -2 : -1);
Reid Kleckner2632f0d2015-05-20 23:08:04 +0000280 // ScopeTable = llvm.x86.seh.lsda(F)
281 Value *FI8 = Builder.CreateBitCast(F, Int8PtrType);
282 Value *LSDA = Builder.CreateCall(
283 Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_lsda), FI8);
Reid Klecknere6531a552015-05-29 22:57:46 +0000284 Type *Int32Ty = Type::getInt32Ty(TheModule->getContext());
285 LSDA = Builder.CreatePtrToInt(LSDA, Int32Ty);
286 // If using _except_handler4, xor the address of the table with
287 // __security_cookie.
288 if (UseStackGuard) {
289 Value *Cookie =
290 TheModule->getOrInsertGlobal("__security_cookie", Int32Ty);
291 Value *Val = Builder.CreateLoad(Int32Ty, Cookie);
292 LSDA = Builder.CreateXor(LSDA, Val);
293 }
294 Builder.CreateStore(LSDA, Builder.CreateStructGEP(RegNodeTy, RegNode, 3));
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000295 Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 2);
296 linkExceptionRegistration(Builder, PersonalityFn);
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000297 } else {
298 llvm_unreachable("unexpected personality function");
299 }
300
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000301 // Insert an unlink before all returns.
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000302 for (BasicBlock &BB : *F) {
303 TerminatorInst *T = BB.getTerminator();
304 if (!isa<ReturnInst>(T))
305 continue;
306 Builder.SetInsertPoint(T);
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000307 unlinkExceptionRegistration(Builder);
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000308 }
309}
310
Reid Kleckner2632f0d2015-05-20 23:08:04 +0000311Value *WinEHStatePass::emitEHLSDA(IRBuilder<> &Builder, Function *F) {
312 Value *FI8 = Builder.CreateBitCast(F, Type::getInt8PtrTy(F->getContext()));
313 return Builder.CreateCall(
314 Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_lsda), FI8);
315}
316
317/// Generate a thunk that puts the LSDA of ParentFunc in EAX and then calls
318/// PersonalityFn, forwarding the parameters passed to PEXCEPTION_ROUTINE:
319/// typedef _EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE)(
320/// _EXCEPTION_RECORD *, void *, _CONTEXT *, void *);
321/// We essentially want this code:
322/// movl $lsda, %eax
323/// jmpl ___CxxFrameHandler3
324Function *WinEHStatePass::generateLSDAInEAXThunk(Function *ParentFunc) {
325 LLVMContext &Context = ParentFunc->getContext();
326 Type *Int32Ty = Type::getInt32Ty(Context);
327 Type *Int8PtrType = Type::getInt8PtrTy(Context);
328 Type *ArgTys[5] = {Int8PtrType, Int8PtrType, Int8PtrType, Int8PtrType,
329 Int8PtrType};
330 FunctionType *TrampolineTy =
331 FunctionType::get(Int32Ty, makeArrayRef(&ArgTys[0], 4),
332 /*isVarArg=*/false);
333 FunctionType *TargetFuncTy =
334 FunctionType::get(Int32Ty, makeArrayRef(&ArgTys[0], 5),
335 /*isVarArg=*/false);
Reid Kleckner5f4dd922015-07-13 17:55:14 +0000336 Function *Trampoline =
337 Function::Create(TrampolineTy, GlobalValue::InternalLinkage,
338 Twine("__ehhandler$") + GlobalValue::getRealLinkageName(
339 ParentFunc->getName()),
340 TheModule);
Reid Kleckner2632f0d2015-05-20 23:08:04 +0000341 BasicBlock *EntryBB = BasicBlock::Create(Context, "entry", Trampoline);
342 IRBuilder<> Builder(EntryBB);
343 Value *LSDA = emitEHLSDA(Builder, ParentFunc);
344 Value *CastPersonality =
345 Builder.CreateBitCast(PersonalityFn, TargetFuncTy->getPointerTo());
346 auto AI = Trampoline->arg_begin();
Duncan P. N. Exon Smithd77de642015-10-19 21:48:29 +0000347 Value *Args[5] = {LSDA, &*AI++, &*AI++, &*AI++, &*AI++};
Reid Kleckner2632f0d2015-05-20 23:08:04 +0000348 CallInst *Call = Builder.CreateCall(CastPersonality, Args);
349 // Can't use musttail due to prototype mismatch, but we can use tail.
350 Call->setTailCall(true);
351 // Set inreg so we pass it in EAX.
352 Call->addAttribute(1, Attribute::InReg);
353 Builder.CreateRet(Call);
354 return Trampoline;
355}
356
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000357void WinEHStatePass::linkExceptionRegistration(IRBuilder<> &Builder,
Reid Kleckner2bc93ca2015-06-10 01:02:30 +0000358 Function *Handler) {
359 // Emit the .safeseh directive for this function.
360 Handler->addFnAttr("safeseh");
361
Reid Klecknere6531a552015-05-29 22:57:46 +0000362 Type *LinkTy = getEHLinkRegistrationType();
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000363 // Handler = Handler
Reid Kleckner2bc93ca2015-06-10 01:02:30 +0000364 Value *HandlerI8 = Builder.CreateBitCast(Handler, Builder.getInt8PtrTy());
365 Builder.CreateStore(HandlerI8, Builder.CreateStructGEP(LinkTy, Link, 1));
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000366 // Next = [fs:00]
367 Constant *FSZero =
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000368 Constant::getNullValue(LinkTy->getPointerTo()->getPointerTo(257));
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000369 Value *Next = Builder.CreateLoad(FSZero);
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000370 Builder.CreateStore(Next, Builder.CreateStructGEP(LinkTy, Link, 0));
371 // [fs:00] = Link
372 Builder.CreateStore(Link, FSZero);
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000373}
374
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000375void WinEHStatePass::unlinkExceptionRegistration(IRBuilder<> &Builder) {
376 // Clone Link into the current BB for better address mode folding.
377 if (auto *GEP = dyn_cast<GetElementPtrInst>(Link)) {
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000378 GEP = cast<GetElementPtrInst>(GEP->clone());
379 Builder.Insert(GEP);
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000380 Link = GEP;
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000381 }
Reid Klecknere6531a552015-05-29 22:57:46 +0000382 Type *LinkTy = getEHLinkRegistrationType();
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000383 // [fs:00] = Link->Next
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000384 Value *Next =
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000385 Builder.CreateLoad(Builder.CreateStructGEP(LinkTy, Link, 0));
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000386 Constant *FSZero =
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000387 Constant::getNullValue(LinkTy->getPointerTo()->getPointerTo(257));
Reid Kleckner0738a9c2015-05-05 17:44:16 +0000388 Builder.CreateStore(Next, FSZero);
389}
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000390
Reid Klecknerc20276d2015-11-17 21:10:25 +0000391void WinEHStatePass::addStateStores(Function &F, WinEHFuncInfo &FuncInfo) {
392 // Mark the registration node. The backend needs to know which alloca it is so
393 // that it can recover the original frame pointer.
394 IRBuilder<> Builder(RegNode->getParent(), std::next(RegNode->getIterator()));
395 Value *RegNodeI8 = Builder.CreateBitCast(RegNode, Builder.getInt8PtrTy());
396 Builder.CreateCall(
397 Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_ehregnode),
398 {RegNodeI8});
Reid Kleckner14e77352015-10-09 23:34:53 +0000399
Reid Klecknerc20276d2015-11-17 21:10:25 +0000400 // Calculate state numbers.
401 if (isAsynchronousEHPersonality(Personality))
402 calculateSEHStateNumbers(&F, FuncInfo);
403 else
404 calculateWinCXXEHStateNumbers(&F, FuncInfo);
Reid Kleckner14e77352015-10-09 23:34:53 +0000405
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000406 // Iterate all the instructions and emit state number stores.
David Majnemer8a1c45d2015-12-12 05:38:55 +0000407 DenseMap<BasicBlock *, ColorVector> BlockColors = colorEHFunclets(F);
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000408 for (BasicBlock &BB : F) {
David Majnemer8a1c45d2015-12-12 05:38:55 +0000409 // Figure out what state we should assign calls in this block.
410 int BaseState = -1;
411 auto &BBColors = BlockColors[&BB];
412
413 assert(BBColors.size() == 1 &&
414 "multi-color BB not removed by preparation");
415 BasicBlock *FuncletEntryBB = BBColors.front();
416 if (auto *FuncletPad =
417 dyn_cast<FuncletPadInst>(FuncletEntryBB->getFirstNonPHI())) {
David Majnemerf2bb7102016-01-29 05:33:15 +0000418 // We do not support nesting funclets within cleanuppads.
419 if (isa<CleanupPadInst>(FuncletPad))
420 continue;
421
David Majnemer8a1c45d2015-12-12 05:38:55 +0000422 auto BaseStateI = FuncInfo.FuncletBaseStateMap.find(FuncletPad);
423 if (BaseStateI != FuncInfo.FuncletBaseStateMap.end())
424 BaseState = BaseStateI->second;
425 }
426
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000427 for (Instruction &I : BB) {
428 if (auto *CI = dyn_cast<CallInst>(&I)) {
429 // Possibly throwing call instructions have no actions to take after
430 // an unwind. Ensure they are in the -1 state.
431 if (CI->doesNotThrow())
432 continue;
David Majnemerefb41742016-02-01 04:28:59 +0000433 insertStateNumberStore(CI, BaseState);
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000434 } else if (auto *II = dyn_cast<InvokeInst>(&I)) {
435 // Look up the state number of the landingpad this unwinds to.
David Majnemer8a1c45d2015-12-12 05:38:55 +0000436 assert(FuncInfo.InvokeStateMap.count(II) && "invoke has no state!");
437 int State = FuncInfo.InvokeStateMap[II];
David Majnemerefb41742016-02-01 04:28:59 +0000438 insertStateNumberStore(II, State);
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000439 }
440 }
441 }
442}
443
David Majnemerefb41742016-02-01 04:28:59 +0000444void WinEHStatePass::insertStateNumberStore(Instruction *IP, int State) {
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000445 IRBuilder<> Builder(IP);
446 Value *StateField =
David Majnemerefb41742016-02-01 04:28:59 +0000447 Builder.CreateStructGEP(nullptr, RegNode, StateFieldIndex);
Reid Klecknerfe4d4912015-05-28 22:00:24 +0000448 Builder.CreateStore(Builder.getInt32(State), StateField);
449}