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