LLVM 20.0.0git
X86WinEHState.cpp
Go to the documentation of this file.
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"
18#include "llvm/Analysis/CFG.h"
21#include "llvm/IR/CFG.h"
23#include "llvm/IR/Function.h"
24#include "llvm/IR/IRBuilder.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
41class WinEHStatePass : public FunctionPass {
42public:
43 static char ID; // Pass identification, replacement for typeid.
44
45 WinEHStatePass() : FunctionPass(ID) {}
46
47 bool runOnFunction(Function &Fn) override;
48
49 bool doInitialization(Module &M) override;
50
51 bool doFinalization(Module &M) override;
52
53 void getAnalysisUsage(AnalysisUsage &AU) const override;
54
55 StringRef getPassName() const override {
56 return "Windows 32-bit x86 EH state insertion";
57 }
58
59private:
60 void emitExceptionRegistrationRecord(Function *F);
61
62 void linkExceptionRegistration(IRBuilder<> &Builder, Function *Handler);
63 void unlinkExceptionRegistration(IRBuilder<> &Builder);
64 void addStateStores(Function &F, WinEHFuncInfo &FuncInfo);
65 void insertStateNumberStore(Instruction *IP, int State);
66
67 Value *emitEHLSDA(IRBuilder<> &Builder, Function *F);
68
69 Function *generateLSDAInEAXThunk(Function *ParentFunc);
70
71 bool isStateStoreNeeded(EHPersonality Personality, CallBase &Call);
72 void rewriteSetJmpCall(IRBuilder<> &Builder, Function &F, CallBase &Call,
73 Value *State);
74 int getBaseStateForBB(DenseMap<BasicBlock *, ColorVector> &BlockColors,
75 WinEHFuncInfo &FuncInfo, BasicBlock *BB);
76 int getStateForCall(DenseMap<BasicBlock *, ColorVector> &BlockColors,
77 WinEHFuncInfo &FuncInfo, CallBase &Call);
78
79 void updateEspForInAllocas(Function &F);
80
81 // Module-level type getters.
82 Type *getEHLinkRegistrationType();
83 Type *getSEHRegistrationType();
84 Type *getCXXEHRegistrationType();
85
86 // Per-module data.
87 Module *TheModule = nullptr;
88 StructType *EHLinkRegistrationTy = nullptr;
89 StructType *CXXEHRegistrationTy = nullptr;
90 StructType *SEHRegistrationTy = nullptr;
91 FunctionCallee SetJmp3 = nullptr;
92 FunctionCallee CxxLongjmpUnwind = nullptr;
93
94 // Per-function state
96 Function *PersonalityFn = nullptr;
97 bool UseStackGuard = false;
98 int ParentBaseState = 0;
99 FunctionCallee SehLongjmpUnwind = nullptr;
100 Constant *Cookie = nullptr;
101
102 /// The stack allocation containing all EH data, including the link in the
103 /// fs:00 chain and the current state.
104 AllocaInst *RegNode = nullptr;
105
106 // Struct type of RegNode. Used for GEPing.
107 Type *RegNodeTy = nullptr;
108
109 // The allocation containing the EH security guard.
110 AllocaInst *EHGuardNode = nullptr;
111
112 /// The index of the state field of RegNode.
113 int StateFieldIndex = ~0U;
114
115 /// The linked list node subobject inside of RegNode.
116 Value *Link = nullptr;
117};
118} // namespace
119
120FunctionPass *llvm::createX86WinEHStatePass() { return new WinEHStatePass(); }
121
122char WinEHStatePass::ID = 0;
123
124INITIALIZE_PASS(WinEHStatePass, "x86-winehstate",
125 "Insert stores for EH state numbers", false, false)
126
127bool WinEHStatePass::doInitialization(Module &M) {
128 TheModule = &M;
129 return false;
130}
131
132bool WinEHStatePass::doFinalization(Module &M) {
133 assert(TheModule == &M);
134 TheModule = nullptr;
135 EHLinkRegistrationTy = nullptr;
136 CXXEHRegistrationTy = nullptr;
137 SEHRegistrationTy = nullptr;
138 SetJmp3 = nullptr;
139 CxxLongjmpUnwind = nullptr;
140 SehLongjmpUnwind = nullptr;
141 Cookie = nullptr;
142 return false;
143}
144
145void WinEHStatePass::getAnalysisUsage(AnalysisUsage &AU) const {
146 // This pass should only insert a stack allocation, memory accesses, and
147 // localrecovers.
148 AU.setPreservesCFG();
149}
150
151bool WinEHStatePass::runOnFunction(Function &F) {
152 // Don't insert state stores or exception handler thunks for
153 // available_externally functions. The handler needs to reference the LSDA,
154 // which will not be emitted in this case.
155 if (F.hasAvailableExternallyLinkage())
156 return false;
157
158 // Check the personality. Do nothing if this personality doesn't use funclets.
159 if (!F.hasPersonalityFn())
160 return false;
161 PersonalityFn = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts());
162 if (!PersonalityFn)
163 return false;
164 Personality = classifyEHPersonality(PersonalityFn);
165 if (!isFuncletEHPersonality(Personality))
166 return false;
167
168 // Skip this function if there are no EH pads and we aren't using IR-level
169 // outlining.
170 bool HasPads = false;
171 for (BasicBlock &BB : F) {
172 if (BB.isEHPad()) {
173 HasPads = true;
174 break;
175 }
176 }
177 if (!HasPads)
178 return false;
179
180 Type *Int8PtrType = PointerType::getUnqual(TheModule->getContext());
181 SetJmp3 = TheModule->getOrInsertFunction(
182 "_setjmp3", FunctionType::get(
183 Type::getInt32Ty(TheModule->getContext()),
184 {Int8PtrType, Type::getInt32Ty(TheModule->getContext())},
185 /*isVarArg=*/true));
186
187 emitExceptionRegistrationRecord(&F);
188
189 // The state numbers calculated here in IR must agree with what we calculate
190 // later on for the MachineFunction. In particular, if an IR pass deletes an
191 // unreachable EH pad after this point before machine CFG construction, we
192 // will be in trouble. If this assumption is ever broken, we should turn the
193 // numbers into an immutable analysis pass.
194 WinEHFuncInfo FuncInfo;
195 addStateStores(F, FuncInfo);
196 updateEspForInAllocas(F);
197
198 // Reset per-function state.
199 PersonalityFn = nullptr;
200 Personality = EHPersonality::Unknown;
201 UseStackGuard = false;
202 RegNodeTy = nullptr;
203 RegNode = nullptr;
204 EHGuardNode = nullptr;
205
206 return true;
207}
208
209/// Get the common EH registration subobject:
210/// typedef _EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE)(
211/// _EXCEPTION_RECORD *, void *, _CONTEXT *, void *);
212/// struct EHRegistrationNode {
213/// EHRegistrationNode *Next;
214/// PEXCEPTION_ROUTINE Handler;
215/// };
216Type *WinEHStatePass::getEHLinkRegistrationType() {
217 if (EHLinkRegistrationTy)
218 return EHLinkRegistrationTy;
219 LLVMContext &Context = TheModule->getContext();
220 Type *FieldTys[] = {
221 PointerType::getUnqual(Context), // EHRegistrationNode *Next
222 PointerType::getUnqual(Context) // EXCEPTION_DISPOSITION (*Handler)(...)
223 };
224 EHLinkRegistrationTy = StructType::create(FieldTys, "EHRegistrationNode");
225 return EHLinkRegistrationTy;
226}
227
228/// The __CxxFrameHandler3 registration node:
229/// struct CXXExceptionRegistration {
230/// void *SavedESP;
231/// EHRegistrationNode SubRecord;
232/// int32_t TryLevel;
233/// };
234Type *WinEHStatePass::getCXXEHRegistrationType() {
235 if (CXXEHRegistrationTy)
236 return CXXEHRegistrationTy;
237 LLVMContext &Context = TheModule->getContext();
238 Type *FieldTys[] = {
239 PointerType::getUnqual(Context), // void *SavedESP
240 getEHLinkRegistrationType(), // EHRegistrationNode SubRecord
241 Type::getInt32Ty(Context) // int32_t TryLevel
242 };
243 CXXEHRegistrationTy =
244 StructType::create(FieldTys, "CXXExceptionRegistration");
245 return CXXEHRegistrationTy;
246}
247
248/// The _except_handler3/4 registration node:
249/// struct EH4ExceptionRegistration {
250/// void *SavedESP;
251/// _EXCEPTION_POINTERS *ExceptionPointers;
252/// EHRegistrationNode SubRecord;
253/// int32_t EncodedScopeTable;
254/// int32_t TryLevel;
255/// };
256Type *WinEHStatePass::getSEHRegistrationType() {
257 if (SEHRegistrationTy)
258 return SEHRegistrationTy;
259 LLVMContext &Context = TheModule->getContext();
260 Type *FieldTys[] = {
261 PointerType::getUnqual(Context), // void *SavedESP
262 PointerType::getUnqual(Context), // void *ExceptionPointers
263 getEHLinkRegistrationType(), // EHRegistrationNode SubRecord
264 Type::getInt32Ty(Context), // int32_t EncodedScopeTable
265 Type::getInt32Ty(Context) // int32_t TryLevel
266 };
267 SEHRegistrationTy = StructType::create(FieldTys, "SEHExceptionRegistration");
268 return SEHRegistrationTy;
269}
270
271// Emit an exception registration record. These are stack allocations with the
272// common subobject of two pointers: the previous registration record (the old
273// fs:00) and the personality function for the current frame. The data before
274// and after that is personality function specific.
275void WinEHStatePass::emitExceptionRegistrationRecord(Function *F) {
276 assert(Personality == EHPersonality::MSVC_CXX ||
277 Personality == EHPersonality::MSVC_X86SEH);
278
279 IRBuilder<> Builder(&F->getEntryBlock(), F->getEntryBlock().begin());
280 Type *Int8PtrType = Builder.getPtrTy();
281 Type *Int32Ty = Builder.getInt32Ty();
282 Type *VoidTy = Builder.getVoidTy();
283
284 if (Personality == EHPersonality::MSVC_CXX) {
285 RegNodeTy = getCXXEHRegistrationType();
286 RegNode = Builder.CreateAlloca(RegNodeTy);
287 // SavedESP = llvm.stacksave()
288 Value *SP = Builder.CreateStackSave();
289 Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
290 // TryLevel = -1
291 StateFieldIndex = 2;
292 ParentBaseState = -1;
293 insertStateNumberStore(&*Builder.GetInsertPoint(), ParentBaseState);
294 // Handler = __ehhandler$F
295 Function *Trampoline = generateLSDAInEAXThunk(F);
296 Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 1);
297 linkExceptionRegistration(Builder, Trampoline);
298
299 CxxLongjmpUnwind = TheModule->getOrInsertFunction(
300 "__CxxLongjmpUnwind",
301 FunctionType::get(VoidTy, Int8PtrType, /*isVarArg=*/false));
302 cast<Function>(CxxLongjmpUnwind.getCallee()->stripPointerCasts())
303 ->setCallingConv(CallingConv::X86_StdCall);
304 } else if (Personality == EHPersonality::MSVC_X86SEH) {
305 // If _except_handler4 is in use, some additional guard checks and prologue
306 // stuff is required.
307 StringRef PersonalityName = PersonalityFn->getName();
308 UseStackGuard = (PersonalityName == "_except_handler4");
309
310 // Allocate local structures.
311 RegNodeTy = getSEHRegistrationType();
312 RegNode = Builder.CreateAlloca(RegNodeTy);
313 if (UseStackGuard)
314 EHGuardNode = Builder.CreateAlloca(Int32Ty);
315
316 // SavedESP = llvm.stacksave()
317 Value *SP = Builder.CreateStackSave();
318 Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
319 // TryLevel = -2 / -1
320 StateFieldIndex = 4;
321 ParentBaseState = UseStackGuard ? -2 : -1;
322 insertStateNumberStore(&*Builder.GetInsertPoint(), ParentBaseState);
323 // ScopeTable = llvm.x86.seh.lsda(F)
324 Value *LSDA = emitEHLSDA(Builder, F);
325 LSDA = Builder.CreatePtrToInt(LSDA, Int32Ty);
326 // If using _except_handler4, xor the address of the table with
327 // __security_cookie.
328 if (UseStackGuard) {
329 Cookie = TheModule->getOrInsertGlobal("__security_cookie", Int32Ty);
330 Value *Val = Builder.CreateLoad(Int32Ty, Cookie, "cookie");
331 LSDA = Builder.CreateXor(LSDA, Val);
332 }
333 Builder.CreateStore(LSDA, Builder.CreateStructGEP(RegNodeTy, RegNode, 3));
334
335 // If using _except_handler4, the EHGuard contains: FramePtr xor Cookie.
336 if (UseStackGuard) {
337 Value *Val = Builder.CreateLoad(Int32Ty, Cookie);
338 Value *FrameAddr = Builder.CreateIntrinsic(
339 Intrinsic::frameaddress,
340 Builder.getPtrTy(TheModule->getDataLayout().getAllocaAddrSpace()),
341 Builder.getInt32(0), /*FMFSource=*/nullptr, "frameaddr");
342 Value *FrameAddrI32 = Builder.CreatePtrToInt(FrameAddr, Int32Ty);
343 FrameAddrI32 = Builder.CreateXor(FrameAddrI32, Val);
344 Builder.CreateStore(FrameAddrI32, EHGuardNode);
345 }
346
347 // Register the exception handler.
348 Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 2);
349 linkExceptionRegistration(Builder, PersonalityFn);
350
351 SehLongjmpUnwind = TheModule->getOrInsertFunction(
352 UseStackGuard ? "_seh_longjmp_unwind4" : "_seh_longjmp_unwind",
353 FunctionType::get(Type::getVoidTy(TheModule->getContext()), Int8PtrType,
354 /*isVarArg=*/false));
355 cast<Function>(SehLongjmpUnwind.getCallee()->stripPointerCasts())
356 ->setCallingConv(CallingConv::X86_StdCall);
357 } else {
358 llvm_unreachable("unexpected personality function");
359 }
360
361 // Insert an unlink before all returns.
362 for (BasicBlock &BB : *F) {
363 Instruction *T = BB.getTerminator();
364 if (!isa<ReturnInst>(T))
365 continue;
366
367 // If there is a musttail call, that's the de-facto terminator.
368 if (CallInst *CI = BB.getTerminatingMustTailCall())
369 T = CI;
370
371 Builder.SetInsertPoint(T);
372 unlinkExceptionRegistration(Builder);
373 }
374}
375
376Value *WinEHStatePass::emitEHLSDA(IRBuilder<> &Builder, Function *F) {
377 return Builder.CreateIntrinsic(Intrinsic::x86_seh_lsda, {}, F);
378}
379
380/// Generate a thunk that puts the LSDA of ParentFunc in EAX and then calls
381/// PersonalityFn, forwarding the parameters passed to PEXCEPTION_ROUTINE:
382/// typedef _EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE)(
383/// _EXCEPTION_RECORD *, void *, _CONTEXT *, void *);
384/// We essentially want this code:
385/// movl $lsda, %eax
386/// jmpl ___CxxFrameHandler3
387Function *WinEHStatePass::generateLSDAInEAXThunk(Function *ParentFunc) {
388 LLVMContext &Context = ParentFunc->getContext();
389 Type *Int32Ty = Type::getInt32Ty(Context);
390 Type *Int8PtrType = PointerType::getUnqual(Context);
391 Type *ArgTys[5] = {Int8PtrType, Int8PtrType, Int8PtrType, Int8PtrType,
392 Int8PtrType};
393 FunctionType *TrampolineTy =
394 FunctionType::get(Int32Ty, ArrayRef(&ArgTys[0], 4),
395 /*isVarArg=*/false);
396 FunctionType *TargetFuncTy =
397 FunctionType::get(Int32Ty, ArrayRef(&ArgTys[0], 5),
398 /*isVarArg=*/false);
399 Function *Trampoline = Function::Create(
400 TrampolineTy, GlobalValue::InternalLinkage,
401 Twine("__ehhandler$") +
403 TheModule);
404 if (auto *C = ParentFunc->getComdat())
405 Trampoline->setComdat(C);
406 BasicBlock *EntryBB = BasicBlock::Create(Context, "entry", Trampoline);
407 IRBuilder<> Builder(EntryBB);
408 Value *LSDA = emitEHLSDA(Builder, ParentFunc);
409 auto AI = Trampoline->arg_begin();
410 Value *Args[5] = {LSDA, &*AI++, &*AI++, &*AI++, &*AI++};
411 CallInst *Call = Builder.CreateCall(TargetFuncTy, PersonalityFn, Args);
412 // Can't use musttail due to prototype mismatch, but we can use tail.
413 Call->setTailCall(true);
414 // Set inreg so we pass it in EAX.
415 Call->addParamAttr(0, Attribute::InReg);
416 Builder.CreateRet(Call);
417 return Trampoline;
418}
419
420void WinEHStatePass::linkExceptionRegistration(IRBuilder<> &Builder,
421 Function *Handler) {
422 // Emit the .safeseh directive for this function.
423 Handler->addFnAttr("safeseh");
424
425 LLVMContext &C = Builder.getContext();
426 Type *LinkTy = getEHLinkRegistrationType();
427 // Handler = Handler
428 Builder.CreateStore(Handler, Builder.CreateStructGEP(LinkTy, Link, 1));
429 // Next = [fs:00]
430 Constant *FSZero = Constant::getNullValue(PointerType::get(C, X86AS::FS));
431 Value *Next = Builder.CreateLoad(PointerType::getUnqual(C), FSZero);
432 Builder.CreateStore(Next, Builder.CreateStructGEP(LinkTy, Link, 0));
433 // [fs:00] = Link
434 Builder.CreateStore(Link, FSZero);
435}
436
437void WinEHStatePass::unlinkExceptionRegistration(IRBuilder<> &Builder) {
438 // Clone Link into the current BB for better address mode folding.
439 if (auto *GEP = dyn_cast<GetElementPtrInst>(Link)) {
440 GEP = cast<GetElementPtrInst>(GEP->clone());
441 Builder.Insert(GEP);
442 Link = GEP;
443 }
444
445 LLVMContext &C = Builder.getContext();
446 Type *LinkTy = getEHLinkRegistrationType();
447 // [fs:00] = Link->Next
448 Value *Next = Builder.CreateLoad(PointerType::getUnqual(C),
449 Builder.CreateStructGEP(LinkTy, Link, 0));
450 Constant *FSZero = Constant::getNullValue(PointerType::get(C, X86AS::FS));
451 Builder.CreateStore(Next, FSZero);
452}
453
454// Calls to setjmp(p) are lowered to _setjmp3(p, 0) by the frontend.
455// The idea behind _setjmp3 is that it takes an optional number of personality
456// specific parameters to indicate how to restore the personality-specific frame
457// state when longjmp is initiated. Typically, the current TryLevel is saved.
458void WinEHStatePass::rewriteSetJmpCall(IRBuilder<> &Builder, Function &F,
459 CallBase &Call, Value *State) {
460 // Don't rewrite calls with a weird number of arguments.
461 if (Call.arg_size() != 2)
462 return;
463
465 Call.getOperandBundlesAsDefs(OpBundles);
466
467 SmallVector<Value *, 3> OptionalArgs;
468 if (Personality == EHPersonality::MSVC_CXX) {
469 OptionalArgs.push_back(CxxLongjmpUnwind.getCallee());
470 OptionalArgs.push_back(State);
471 OptionalArgs.push_back(emitEHLSDA(Builder, &F));
472 } else if (Personality == EHPersonality::MSVC_X86SEH) {
473 OptionalArgs.push_back(SehLongjmpUnwind.getCallee());
474 OptionalArgs.push_back(State);
475 if (UseStackGuard)
476 OptionalArgs.push_back(Cookie);
477 } else {
478 llvm_unreachable("unhandled personality!");
479 }
480
482 Args.push_back(
483 Builder.CreateBitCast(Call.getArgOperand(0), Builder.getPtrTy()));
484 Args.push_back(Builder.getInt32(OptionalArgs.size()));
485 Args.append(OptionalArgs.begin(), OptionalArgs.end());
486
487 CallBase *NewCall;
488 if (auto *CI = dyn_cast<CallInst>(&Call)) {
489 CallInst *NewCI = Builder.CreateCall(SetJmp3, Args, OpBundles);
490 NewCI->setTailCallKind(CI->getTailCallKind());
491 NewCall = NewCI;
492 } else {
493 auto *II = cast<InvokeInst>(&Call);
494 NewCall = Builder.CreateInvoke(SetJmp3, II->getNormalDest(),
495 II->getUnwindDest(), Args, OpBundles);
496 }
497 NewCall->setCallingConv(Call.getCallingConv());
498 NewCall->setAttributes(Call.getAttributes());
499 NewCall->setDebugLoc(Call.getDebugLoc());
500
501 NewCall->takeName(&Call);
502 Call.replaceAllUsesWith(NewCall);
503 Call.eraseFromParent();
504}
505
506// Figure out what state we should assign calls in this block.
507int WinEHStatePass::getBaseStateForBB(
509 BasicBlock *BB) {
510 int BaseState = ParentBaseState;
511 auto &BBColors = BlockColors[BB];
512
513 assert(BBColors.size() == 1 && "multi-color BB not removed by preparation");
514 BasicBlock *FuncletEntryBB = BBColors.front();
515 if (auto *FuncletPad =
516 dyn_cast<FuncletPadInst>(FuncletEntryBB->getFirstNonPHI())) {
517 auto BaseStateI = FuncInfo.FuncletBaseStateMap.find(FuncletPad);
518 if (BaseStateI != FuncInfo.FuncletBaseStateMap.end())
519 BaseState = BaseStateI->second;
520 }
521
522 return BaseState;
523}
524
525static bool isIntrinsic(const CallBase &Call, Intrinsic::ID ID) {
526 const Function *CF = Call.getCalledFunction();
527 return CF && CF->isIntrinsic() && CF->getIntrinsicID() == ID;
528}
529
530static bool isSehScopeEnd(const CallBase &Call) {
531 return isIntrinsic(Call, Intrinsic::seh_scope_end);
532}
533
534static bool isSehScopeBegin(const CallBase &Call) {
535 return isIntrinsic(Call, Intrinsic::seh_scope_begin);
536}
537
538// Calculate the state a call-site is in.
539int WinEHStatePass::getStateForCall(
541 CallBase &Call) {
542 if (auto *II = dyn_cast<InvokeInst>(&Call)) {
543 if (isSehScopeEnd(*II)) {
544 return getBaseStateForBB(BlockColors, FuncInfo, II->getNormalDest());
545 }
546
547 // Look up the state number of the EH pad this unwinds to.
548 assert(FuncInfo.InvokeStateMap.count(II) && "invoke has no state!");
549 return FuncInfo.InvokeStateMap[II];
550 }
551 // Possibly throwing call instructions have no actions to take after
552 // an unwind. Ensure they are in the -1 state.
553 return getBaseStateForBB(BlockColors, FuncInfo, Call.getParent());
554}
555
556// Calculate the intersection of all the FinalStates for a BasicBlock's
557// predecessors.
559 int ParentBaseState, BasicBlock *BB) {
560 // The entry block has no predecessors but we know that the prologue always
561 // sets us up with a fixed state.
562 if (&F.getEntryBlock() == BB)
563 return ParentBaseState;
564
565 // This is an EH Pad, conservatively report this basic block as overdefined.
566 if (BB->isEHPad())
567 return OverdefinedState;
568
569 int CommonState = OverdefinedState;
570 for (BasicBlock *PredBB : predecessors(BB)) {
571 // We didn't manage to get a state for one of these predecessors,
572 // conservatively report this basic block as overdefined.
573 auto PredEndState = FinalStates.find(PredBB);
574 if (PredEndState == FinalStates.end())
575 return OverdefinedState;
576
577 // This code is reachable via exceptional control flow,
578 // conservatively report this basic block as overdefined.
579 if (isa<CatchReturnInst>(PredBB->getTerminator()))
580 return OverdefinedState;
581
582 int PredState = PredEndState->second;
583 assert(PredState != OverdefinedState &&
584 "overdefined BBs shouldn't be in FinalStates");
585 if (CommonState == OverdefinedState)
586 CommonState = PredState;
587
588 // At least two predecessors have different FinalStates,
589 // conservatively report this basic block as overdefined.
590 if (CommonState != PredState)
591 return OverdefinedState;
592 }
593
594 return CommonState;
595}
596
597// Calculate the intersection of all the InitialStates for a BasicBlock's
598// successors.
600 int ParentBaseState, BasicBlock *BB) {
601 // This block rejoins normal control flow,
602 // conservatively report this basic block as overdefined.
603 if (isa<CatchReturnInst>(BB->getTerminator()))
604 return OverdefinedState;
605
606 int CommonState = OverdefinedState;
607 for (BasicBlock *SuccBB : successors(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 SuccStartState = InitialStates.find(SuccBB);
611 if (SuccStartState == InitialStates.end())
612 return OverdefinedState;
613
614 // This is an EH Pad, conservatively report this basic block as overdefined.
615 if (SuccBB->isEHPad())
616 return OverdefinedState;
617
618 int SuccState = SuccStartState->second;
619 assert(SuccState != OverdefinedState &&
620 "overdefined BBs shouldn't be in FinalStates");
621 if (CommonState == OverdefinedState)
622 CommonState = SuccState;
623
624 // At least two successors have different InitialStates,
625 // conservatively report this basic block as overdefined.
626 if (CommonState != SuccState)
627 return OverdefinedState;
628 }
629
630 return CommonState;
631}
632
633bool WinEHStatePass::isStateStoreNeeded(EHPersonality Personality,
634 CallBase &Call) {
635 if (isSehScopeBegin(Call) || isSehScopeEnd(Call)) {
636 return true;
637 }
638
639 // If the function touches memory, it needs a state store.
640 if (isAsynchronousEHPersonality(Personality))
641 return !Call.doesNotAccessMemory();
642
643 // If the function throws, it needs a state store.
644 return !Call.doesNotThrow();
645}
646
647void WinEHStatePass::addStateStores(Function &F, WinEHFuncInfo &FuncInfo) {
648 // Mark the registration node. The backend needs to know which alloca it is so
649 // that it can recover the original frame pointer.
650 IRBuilder<> Builder(RegNode->getNextNode());
651 Value *RegNodeI8 = Builder.CreateBitCast(RegNode, Builder.getPtrTy());
652 Builder.CreateIntrinsic(Intrinsic::x86_seh_ehregnode, {}, {RegNodeI8});
653
654 if (EHGuardNode) {
655 IRBuilder<> Builder(EHGuardNode->getNextNode());
656 Value *EHGuardNodeI8 =
657 Builder.CreateBitCast(EHGuardNode, Builder.getPtrTy());
658 Builder.CreateIntrinsic(Intrinsic::x86_seh_ehguard, {}, {EHGuardNodeI8});
659 }
660
661 // Calculate state numbers.
662 if (isAsynchronousEHPersonality(Personality))
663 calculateSEHStateNumbers(&F, FuncInfo);
664 else
666
667 // Iterate all the instructions and emit state number stores.
670
671 // InitialStates yields the state of the first call-site for a BasicBlock.
672 DenseMap<BasicBlock *, int> InitialStates;
673 // FinalStates yields the state of the last call-site for a BasicBlock.
674 DenseMap<BasicBlock *, int> FinalStates;
675 // Worklist used to revisit BasicBlocks with indeterminate
676 // Initial/Final-States.
677 std::deque<BasicBlock *> Worklist;
678 // Fill in InitialStates and FinalStates for BasicBlocks with call-sites.
679 for (BasicBlock *BB : RPOT) {
680 int InitialState = OverdefinedState;
681 int FinalState;
682 if (&F.getEntryBlock() == BB)
683 InitialState = FinalState = ParentBaseState;
684 for (Instruction &I : *BB) {
685 auto *Call = dyn_cast<CallBase>(&I);
686 if (!Call || !isStateStoreNeeded(Personality, *Call))
687 continue;
688
689 int State = getStateForCall(BlockColors, FuncInfo, *Call);
690 if (InitialState == OverdefinedState)
691 InitialState = State;
692 FinalState = State;
693 }
694 // No call-sites in this basic block? That's OK, we will come back to these
695 // in a later pass.
696 if (InitialState == OverdefinedState) {
697 Worklist.push_back(BB);
698 continue;
699 }
700 LLVM_DEBUG(dbgs() << "X86WinEHState: " << BB->getName()
701 << " InitialState=" << InitialState << '\n');
702 LLVM_DEBUG(dbgs() << "X86WinEHState: " << BB->getName()
703 << " FinalState=" << FinalState << '\n');
704 InitialStates.insert({BB, InitialState});
705 FinalStates.insert({BB, FinalState});
706 }
707
708 // Try to fill-in InitialStates and FinalStates which have no call-sites.
709 while (!Worklist.empty()) {
710 BasicBlock *BB = Worklist.front();
711 Worklist.pop_front();
712 // This BasicBlock has already been figured out, nothing more we can do.
713 if (InitialStates.count(BB) != 0)
714 continue;
715
716 int PredState = getPredState(FinalStates, F, ParentBaseState, BB);
717 if (PredState == OverdefinedState)
718 continue;
719
720 // We successfully inferred this BasicBlock's state via it's predecessors;
721 // enqueue it's successors to see if we can infer their states.
722 InitialStates.insert({BB, PredState});
723 FinalStates.insert({BB, PredState});
724 for (BasicBlock *SuccBB : successors(BB))
725 Worklist.push_back(SuccBB);
726 }
727
728 // Try to hoist stores from successors.
729 for (BasicBlock *BB : RPOT) {
730 int SuccState = getSuccState(InitialStates, F, ParentBaseState, BB);
731 if (SuccState == OverdefinedState)
732 continue;
733
734 // Update our FinalState to reflect the common InitialState of our
735 // successors.
736 FinalStates.insert({BB, SuccState});
737 }
738
739 // Finally, insert state stores before call-sites which transition us to a new
740 // state.
741 for (BasicBlock *BB : RPOT) {
742 auto &BBColors = BlockColors[BB];
743 BasicBlock *FuncletEntryBB = BBColors.front();
744 if (isa<CleanupPadInst>(FuncletEntryBB->getFirstNonPHI()))
745 continue;
746
747 int PrevState = getPredState(FinalStates, F, ParentBaseState, BB);
748 LLVM_DEBUG(dbgs() << "X86WinEHState: " << BB->getName()
749 << " PrevState=" << PrevState << '\n');
750
751 for (Instruction &I : *BB) {
752 auto *Call = dyn_cast<CallBase>(&I);
753 if (!Call || !isStateStoreNeeded(Personality, *Call))
754 continue;
755
756 int State = getStateForCall(BlockColors, FuncInfo, *Call);
757 if (State != PrevState)
758 insertStateNumberStore(&I, State);
759 PrevState = State;
760 }
761
762 // We might have hoisted a state store into this block, emit it now.
763 auto EndState = FinalStates.find(BB);
764 if (EndState != FinalStates.end())
765 if (EndState->second != PrevState)
766 insertStateNumberStore(BB->getTerminator(), EndState->second);
767 }
768
769 SmallVector<CallBase *, 1> SetJmp3Calls;
770 for (BasicBlock *BB : RPOT) {
771 for (Instruction &I : *BB) {
772 auto *Call = dyn_cast<CallBase>(&I);
773 if (!Call)
774 continue;
775 if (Call->getCalledOperand()->stripPointerCasts() !=
776 SetJmp3.getCallee()->stripPointerCasts())
777 continue;
778
779 SetJmp3Calls.push_back(Call);
780 }
781 }
782
783 for (CallBase *Call : SetJmp3Calls) {
784 auto &BBColors = BlockColors[Call->getParent()];
785 BasicBlock *FuncletEntryBB = BBColors.front();
786 bool InCleanup = isa<CleanupPadInst>(FuncletEntryBB->getFirstNonPHI());
787
788 IRBuilder<> Builder(Call);
789 Value *State;
790 if (InCleanup) {
791 Value *StateField = Builder.CreateStructGEP(RegNode->getAllocatedType(),
792 RegNode, StateFieldIndex);
793 State = Builder.CreateLoad(Builder.getInt32Ty(), StateField);
794 } else {
795 State = Builder.getInt32(getStateForCall(BlockColors, FuncInfo, *Call));
796 }
797 rewriteSetJmpCall(Builder, F, *Call, State);
798 }
799}
800
801void WinEHStatePass::insertStateNumberStore(Instruction *IP, int State) {
802 IRBuilder<> Builder(IP);
803 Value *StateField = Builder.CreateStructGEP(RegNode->getAllocatedType(),
804 RegNode, StateFieldIndex);
805 Builder.CreateStore(Builder.getInt32(State), StateField);
806}
807
808void WinEHStatePass::updateEspForInAllocas(Function &F) {
809 for (BasicBlock &BB : F) {
810 for (Instruction &I : BB) {
811 if (auto *Alloca = dyn_cast<AllocaInst>(&I)) {
812 if (Alloca->isStaticAlloca())
813 continue;
814 IRBuilder<> Builder(Alloca->getNextNonDebugInstruction());
815 // SavedESP = llvm.stacksave()
816 Value *SP = Builder.CreateStackSave();
817 Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
818 }
819
820 if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
821 if (II->getIntrinsicID() != Intrinsic::stackrestore)
822 continue;
823 IRBuilder<> Builder(II->getNextNonDebugInstruction());
824 // SavedESP = llvm.stacksave()
825 Value *SP = Builder.CreateStackSave();
826 Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
827 }
828 }
829 }
830}
#define LLVM_DEBUG(...)
Definition: Debug.h:106
Hexagon Common GEP
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static int getPredState(DenseMap< BasicBlock *, int > &FinalStates, Function &F, int ParentBaseState, BasicBlock *BB)
static bool isSehScopeEnd(const CallBase &Call)
static bool isSehScopeBegin(const CallBase &Call)
static bool isIntrinsic(const CallBase &Call, Intrinsic::ID ID)
static int getSuccState(DenseMap< BasicBlock *, int > &InitialStates, Function &F, int ParentBaseState, BasicBlock *BB)
an instruction to allocate memory on the stack
Definition: Instructions.h:63
Represent the analysis usage information of a pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:256
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
LLVM Basic Block Representation.
Definition: BasicBlock.h:61
const Instruction * getFirstNonPHI() const
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
Definition: BasicBlock.cpp:367
const Instruction & front() const
Definition: BasicBlock.h:471
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition: BasicBlock.h:212
bool isEHPad() const
Return true if this basic block is an exception handling block.
Definition: BasicBlock.h:675
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Definition: BasicBlock.h:239
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Definition: InstrTypes.h:1120
void setCallingConv(CallingConv::ID CC)
Definition: InstrTypes.h:1411
void setAttributes(AttributeList A)
Set the attributes for this call.
Definition: InstrTypes.h:1428
This class represents a function call, abstracting a target machine's calling convention.
void setTailCallKind(TailCallKind TCK)
This is an important base class in LLVM.
Definition: Constant.h:42
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
Definition: Constants.cpp:373
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:156
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition: DenseMap.h:152
iterator end()
Definition: DenseMap.h:84
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: DenseMap.h:211
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
Definition: DerivedTypes.h:170
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:310
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
Definition: Function.cpp:641
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition: Function.h:173
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
Definition: Function.h:251
arg_iterator arg_begin()
Definition: Function.h:868
bool isIntrinsic() const
isIntrinsic - Returns true if the function's name starts with "llvm.".
Definition: Function.h:256
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition: Function.cpp:369
void setComdat(Comdat *C)
Definition: Globals.cpp:212
const Comdat * getComdat() const
Definition: GlobalObject.h:128
static StringRef dropLLVMManglingEscape(StringRef Name)
If the given string begins with the GlobalValue name mangling escape character '\1',...
Definition: GlobalValue.h:567
@ InternalLinkage
Rename collisions when linking (static functions).
Definition: GlobalValue.h:59
CallInst * CreateStackSave(const Twine &Name="")
Create a call to llvm.stacksave.
Definition: IRBuilder.h:1068
CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, Instruction *FMFSource=nullptr, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
Definition: IRBuilder.cpp:890
InvokeInst * CreateInvoke(FunctionType *Ty, Value *Callee, BasicBlock *NormalDest, BasicBlock *UnwindDest, ArrayRef< Value * > Args, ArrayRef< OperandBundleDef > OpBundles, const Twine &Name="")
Create an invoke instruction.
Definition: IRBuilder.h:1182
Value * CreateStructGEP(Type *Ty, Value *Ptr, unsigned Idx, const Twine &Name="")
Definition: IRBuilder.h:1995
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Definition: IRBuilder.h:523
ReturnInst * CreateRet(Value *V)
Create a 'ret <val>' instruction.
Definition: IRBuilder.h:1119
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
Definition: IRBuilder.h:483
InstTy * Insert(InstTy *I, const Twine &Name="") const
Insert and return the specified instruction.
Definition: IRBuilder.h:142
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
Definition: IRBuilder.h:2155
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Definition: IRBuilder.h:1813
LLVMContext & getContext() const
Definition: IRBuilder.h:173
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Definition: IRBuilder.h:1826
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition: IRBuilder.h:2444
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
Definition: IRBuilder.h:566
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:2697
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
Definition: Instruction.h:472
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition: Pass.cpp:98
virtual bool doInitialization(Module &)
doInitialization - Virtual method overridden by subclasses to do any necessary initialization before ...
Definition: Pass.h:119
virtual bool doFinalization(Module &)
doFinalization - Virtual method overriden by subclasses to do any necessary clean up after all passes...
Definition: Pass.h:123
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
size_t size() const
Definition: SmallVector.h:78
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
Class to represent struct types.
Definition: DerivedTypes.h:218
static StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Definition: Type.cpp:612
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
static Type * getVoidTy(LLVMContext &C)
static IntegerType * getInt32Ty(LLVMContext &C)
LLVM Value Representation.
Definition: Value.h:74
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:309
void takeName(Value *V)
Transfer the name from V to this value.
Definition: Value.cpp:383
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ X86_StdCall
stdcall is mostly used by the Win32 API.
Definition: CallingConv.h:99
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ FS
Definition: X86.h:211
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
FunctionPass * createX86WinEHStatePass()
Return an IR pass that inserts EH registration stack objects and explicit EH state updates.
auto successors(const MachineBasicBlock *BB)
DenseMap< BasicBlock *, ColorVector > colorEHFunclets(Function &F)
If an EH funclet personality is in use (see isFuncletEHPersonality), this will recompute which blocks...
void calculateWinCXXEHStateNumbers(const Function *ParentFn, WinEHFuncInfo &FuncInfo)
Analyze the IR in ParentFn and it's handlers to build WinEHFuncInfo, which describes the state number...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
bool isFuncletEHPersonality(EHPersonality Pers)
Returns true if this is a personality function that invokes handler funclets (which must return to it...
void calculateSEHStateNumbers(const Function *ParentFn, WinEHFuncInfo &FuncInfo)
bool isAsynchronousEHPersonality(EHPersonality Pers)
Returns true if this personality function catches asynchronous exceptions.
auto predecessors(const MachineBasicBlock *BB)
DenseMap< const FuncletPadInst *, int > FuncletBaseStateMap
Definition: WinEHFuncInfo.h:92
DenseMap< const InvokeInst *, int > InvokeStateMap
Definition: WinEHFuncInfo.h:93