LLVM 22.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 }
498 NewCall->setAttributes(Call.getAttributes());
499 NewCall->setDebugLoc(Call.getDebugLoc());
500
501 NewCall->takeName(&Call);
502 Call.replaceAllUsesWith(NewCall);
504}
505
506// Figure out what state we should assign calls in this block.
507int WinEHStatePass::getBaseStateForBB(
508 DenseMap<BasicBlock *, ColorVector> &BlockColors, WinEHFuncInfo &FuncInfo,
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->getFirstNonPHIIt())) {
517 auto BaseStateI = FuncInfo.FuncletBaseStateMap.find(FuncletPad);
518 if (BaseStateI != FuncInfo.FuncletBaseStateMap.end())
519 BaseState = BaseStateI->second;
520 }
521
522 return BaseState;
523}
524
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(
540 DenseMap<BasicBlock *, ColorVector> &BlockColors, WinEHFuncInfo &FuncInfo,
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.
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) {
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.
668 DenseMap<BasicBlock *, ColorVector> BlockColors = colorEHFunclets(F);
669 ReversePostOrderTraversal<Function *> RPOT(&F);
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->getFirstNonPHIIt()))
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;
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->getFirstNonPHIIt());
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->getNextNode());
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->getNextNode());
824 // SavedESP = llvm.stacksave()
825 Value *SP = Builder.CreateStackSave();
826 Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
827 }
828 }
829 }
830}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool runOnFunction(Function &F, bool PostInlining)
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
#define T
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
#define LLVM_DEBUG(...)
Definition Debug.h:114
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
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
Represent the analysis usage information of a pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition Pass.cpp:270
LLVM Basic Block Representation.
Definition BasicBlock.h:62
LLVM_ABI InstListType::const_iterator getFirstNonPHIIt() const
Returns an iterator to the first instruction in this block that is not a PHINode instruction.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
const Instruction & front() const
Definition BasicBlock.h:482
bool isEHPad() const
Return true if this basic block is an exception handling block.
Definition BasicBlock.h:707
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:233
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
void setCallingConv(CallingConv::ID CC)
LLVM_ABI void getOperandBundlesAsDefs(SmallVectorImpl< OperandBundleDef > &Defs) const
Return the list of operand bundles attached to this instruction as a vector of OperandBundleDefs.
bool doesNotAccessMemory(unsigned OpNo) const
CallingConv::ID getCallingConv() const
Value * getCalledOperand() const
void setAttributes(AttributeList A)
Set the attributes for this call.
bool doesNotThrow() const
Determine if the call cannot unwind.
Value * getArgOperand(unsigned i) const
unsigned arg_size() const
AttributeList getAttributes() const
Return the attributes for this call.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
void setTailCallKind(TailCallKind TCK)
void setTailCall(bool IsTc=true)
This is an important base class in LLVM.
Definition Constant.h:43
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
unsigned getAllocaAddrSpace() const
Definition DataLayout.h:239
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:165
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:161
iterator end()
Definition DenseMap.h:81
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:214
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
Definition Function.cpp:637
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition Function.h:166
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
Definition Function.h:244
arg_iterator arg_begin()
Definition Function.h:866
bool isIntrinsic() const
isIntrinsic - Returns true if the function's name starts with "llvm.".
Definition Function.h:249
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:359
LLVM_ABI void setComdat(Comdat *C)
Definition Globals.cpp:214
const Comdat * getComdat() const
static StringRef dropLLVMManglingEscape(StringRef Name)
If the given string begins with the GlobalValue name mangling escape character '\1',...
@ InternalLinkage
Rename collisions when linking (static functions).
Definition GlobalValue.h:60
CallInst * CreateStackSave(const Twine &Name="")
Create a call to llvm.stacksave.
Definition IRBuilder.h:1121
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:1235
Value * CreateStructGEP(Type *Ty, Value *Ptr, unsigned Idx, const Twine &Name="")
Definition IRBuilder.h:2029
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Definition IRBuilder.h:562
ReturnInst * CreateRet(Value *V)
Create a 'ret <val>' instruction.
Definition IRBuilder.h:1172
LLVM_ABI CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
Definition IRBuilder.h:522
InstTy * Insert(InstTy *I, const Twine &Name="") const
Insert and return the specified instruction.
Definition IRBuilder.h:172
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2204
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:1847
LLVMContext & getContext() const
Definition IRBuilder.h:203
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Definition IRBuilder.h:1860
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:2508
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
Definition IRBuilder.h:605
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2780
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
LLVMContext & getContext() const
Get the global data context.
Definition Module.h:285
FunctionCallee getOrInsertFunction(StringRef Name, FunctionType *T, AttributeList AttributeList)
Look up the specified function in the module symbol table.
Definition Module.cpp:206
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
Definition Module.h:278
GlobalVariable * getOrInsertGlobal(StringRef Name, Type *Ty, function_ref< GlobalVariable *()> CreateGlobalCallback)
Look up the specified global in the module symbol table.
Definition Module.cpp:257
void push_back(const T &Elt)
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
Class to represent struct types.
static LLVM_ABI StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Definition Type.cpp:620
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
LLVM Value Representation.
Definition Value.h:75
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:546
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
Definition Value.cpp:701
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:322
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Definition Value.cpp:396
const ParentTy * getParent() const
Definition ilist_node.h:34
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
Definition ilist_node.h:348
CallInst * Call
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:81
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
This is an optimization pass for GlobalISel generic memory operations.
FunctionPass * createX86WinEHStatePass()
Return an IR pass that inserts EH registration stack objects and explicit EH state updates.
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:649
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
Definition InstrProf.h:296
auto successors(const MachineBasicBlock *BB)
LLVM_ABI 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...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
LLVM_ABI EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:548
bool isFuncletEHPersonality(EHPersonality Pers)
Returns true if this is a personality function that invokes handler funclets (which must return to it...
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
void calculateSEHStateNumbers(const Function *ParentFn, WinEHFuncInfo &FuncInfo)
FunctionAddr VTableAddr Next
Definition InstrProf.h:141
ArrayRef(const T &OneElt) -> ArrayRef< T >
bool isAsynchronousEHPersonality(EHPersonality Pers)
Returns true if this personality function catches asynchronous exceptions.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:565
auto predecessors(const MachineBasicBlock *BB)
DenseMap< const FuncletPadInst *, int > FuncletBaseStateMap
DenseMap< const InvokeInst *, int > InvokeStateMap