LLVM 23.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
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
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
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(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
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.
153}
154
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>(F.getPersonalityFn()->stripPointerCasts());
199 if (!PersonalityFn)
200 return false;
201 Personality = classifyEHPersonality(PersonalityFn);
202 if (!isFuncletEHPersonality(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(TheModule->getContext());
218 SetJmp3 = TheModule->getOrInsertFunction(
219 "_setjmp3", FunctionType::get(
220 Type::getInt32Ty(TheModule->getContext()),
221 {Int8PtrType, Type::getInt32Ty(TheModule->getContext())},
222 /*isVarArg=*/true));
223
224 emitExceptionRegistrationRecord(&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(Context), // EHRegistrationNode *Next
259 PointerType::getUnqual(Context) // EXCEPTION_DISPOSITION (*Handler)(...)
260 };
261 EHLinkRegistrationTy = StructType::create(FieldTys, "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(Context), // void *SavedESP
277 getEHLinkRegistrationType(), // EHRegistrationNode SubRecord
278 Type::getInt32Ty(Context) // int32_t TryLevel
279 };
280 CXXEHRegistrationTy =
281 StructType::create(FieldTys, "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(Context), // void *SavedESP
299 PointerType::getUnqual(Context), // void *ExceptionPointers
300 getEHLinkRegistrationType(), // EHRegistrationNode SubRecord
301 Type::getInt32Ty(Context), // int32_t EncodedScopeTable
302 Type::getInt32Ty(Context) // int32_t TryLevel
303 };
304 SEHRegistrationTy = StructType::create(FieldTys, "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(RegNodeTy);
324 // SavedESP = llvm.stacksave()
325 Value *SP = Builder.CreateStackSave();
326 Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
327 // TryLevel = -1
328 StateFieldIndex = 2;
329 ParentBaseState = -1;
330 insertStateNumberStore(&*Builder.GetInsertPoint(), ParentBaseState);
331 // Handler = __ehhandler$F
332 Function *Trampoline = generateLSDAInEAXThunk(F);
333 Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 1);
334 linkExceptionRegistration(Builder, Trampoline);
335
336 CxxLongjmpUnwind = TheModule->getOrInsertFunction(
337 "__CxxLongjmpUnwind",
338 FunctionType::get(VoidTy, Int8PtrType, /*isVarArg=*/false));
339 cast<Function>(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(RegNodeTy);
350 if (UseStackGuard)
351 EHGuardNode = Builder.CreateAlloca(Int32Ty);
352
353 // SavedESP = llvm.stacksave()
354 Value *SP = Builder.CreateStackSave();
355 Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
356 // TryLevel = -2 / -1
357 StateFieldIndex = 4;
358 ParentBaseState = UseStackGuard ? -2 : -1;
359 insertStateNumberStore(&*Builder.GetInsertPoint(), ParentBaseState);
360 // ScopeTable = llvm.x86.seh.lsda(F)
361 Value *LSDA = emitEHLSDA(Builder, F);
362 LSDA = Builder.CreatePtrToInt(LSDA, Int32Ty);
363 // If using _except_handler4, xor the address of the table with
364 // __security_cookie.
365 if (UseStackGuard) {
366 Cookie = TheModule->getOrInsertGlobal("__security_cookie", Int32Ty);
367 Value *Val = Builder.CreateLoad(Int32Ty, Cookie, "cookie");
368 LSDA = Builder.CreateXor(LSDA, Val);
369 }
370 Builder.CreateStore(LSDA, Builder.CreateStructGEP(RegNodeTy, RegNode, 3));
371
372 // If using _except_handler4, the EHGuard contains: FramePtr xor Cookie.
373 if (UseStackGuard) {
374 Value *Val = Builder.CreateLoad(Int32Ty, Cookie);
375 Value *FrameAddr = Builder.CreateIntrinsic(
376 Intrinsic::frameaddress,
377 Builder.getPtrTy(TheModule->getDataLayout().getAllocaAddrSpace()),
378 Builder.getInt32(0), /*FMFSource=*/nullptr, "frameaddr");
379 Value *FrameAddrI32 = Builder.CreatePtrToInt(FrameAddr, Int32Ty);
380 FrameAddrI32 = Builder.CreateXor(FrameAddrI32, Val);
381 Builder.CreateStore(FrameAddrI32, EHGuardNode);
382 }
383
384 // Register the exception handler.
385 Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 2);
386 linkExceptionRegistration(Builder, PersonalityFn);
387
388 SehLongjmpUnwind = TheModule->getOrInsertFunction(
389 UseStackGuard ? "_seh_longjmp_unwind4" : "_seh_longjmp_unwind",
390 FunctionType::get(Type::getVoidTy(TheModule->getContext()), Int8PtrType,
391 /*isVarArg=*/false));
392 cast<Function>(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>(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(Intrinsic::x86_seh_lsda, 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();
427 Type *Int8PtrType = PointerType::getUnqual(Context);
428 Type *ArgTys[5] = {Int8PtrType, Int8PtrType, Int8PtrType, Int8PtrType,
429 Int8PtrType};
430 FunctionType *TrampolineTy =
431 FunctionType::get(Int32Ty, ArrayRef(&ArgTys[0], 4),
432 /*isVarArg=*/false);
433 FunctionType *TargetFuncTy =
434 FunctionType::get(Int32Ty, ArrayRef(&ArgTys[0], 5),
435 /*isVarArg=*/false);
436 Function *Trampoline = Function::Create(
437 TrampolineTy, GlobalValue::InternalLinkage,
438 Twine("__ehhandler$") +
440 TheModule);
441 if (auto *C = ParentFunc->getComdat())
442 Trampoline->setComdat(C);
443 BasicBlock *EntryBB = BasicBlock::Create(Context, "entry", Trampoline);
444 IRBuilder<> Builder(EntryBB);
445 Value *LSDA = emitEHLSDA(Builder, ParentFunc);
446 auto AI = Trampoline->arg_begin();
447 Value *Args[5] = {LSDA, &*AI++, &*AI++, &*AI++, &*AI++};
448 CallInst *Call = Builder.CreateCall(TargetFuncTy, 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(0, Attribute::InReg);
453 Builder.CreateRet(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("safeseh");
461
462 LLVMContext &C = Builder.getContext();
463 Type *LinkTy = getEHLinkRegistrationType();
464 // Handler = Handler
465 Builder.CreateStore(Handler, Builder.CreateStructGEP(LinkTy, Link, 1));
466 // Next = [fs:00]
468 Value *Next = Builder.CreateLoad(PointerType::getUnqual(C), FSZero);
469 Builder.CreateStore(Next, Builder.CreateStructGEP(LinkTy, Link, 0));
470 // [fs:00] = Link
471 Builder.CreateStore(Link, 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>(Link)) {
477 GEP = cast<GetElementPtrInst>(GEP->clone());
478 Builder.Insert(GEP);
479 Link = GEP;
480 }
481
482 LLVMContext &C = Builder.getContext();
483 Type *LinkTy = getEHLinkRegistrationType();
484 // [fs:00] = Link->Next
486 Builder.CreateStructGEP(LinkTy, Link, 0));
488 Builder.CreateStore(Next, 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
502 Call.getOperandBundlesAsDefs(OpBundles);
503
504 SmallVector<Value *, 3> OptionalArgs;
505 if (Personality == EHPersonality::MSVC_CXX) {
506 OptionalArgs.push_back(CxxLongjmpUnwind.getCallee());
507 OptionalArgs.push_back(State);
508 OptionalArgs.push_back(emitEHLSDA(Builder, &F));
509 } else if (Personality == EHPersonality::MSVC_X86SEH) {
510 OptionalArgs.push_back(SehLongjmpUnwind.getCallee());
511 OptionalArgs.push_back(State);
512 if (UseStackGuard)
513 OptionalArgs.push_back(Cookie);
514 } else {
515 llvm_unreachable("unhandled personality!");
516 }
517
519 Args.push_back(
520 Builder.CreateBitCast(Call.getArgOperand(0), Builder.getPtrTy()));
521 Args.push_back(Builder.getInt32(OptionalArgs.size()));
522 Args.append(OptionalArgs.begin(), OptionalArgs.end());
523
524 CallBase *NewCall;
525 if (auto *CI = dyn_cast<CallInst>(&Call)) {
526 CallInst *NewCI = Builder.CreateCall(SetJmp3, Args, OpBundles);
527 NewCI->setTailCallKind(CI->getTailCallKind());
528 NewCall = NewCI;
529 } else {
530 auto *II = cast<InvokeInst>(&Call);
531 NewCall = Builder.CreateInvoke(SetJmp3, II->getNormalDest(),
532 II->getUnwindDest(), Args, OpBundles);
533 }
535 NewCall->setAttributes(Call.getAttributes());
536 NewCall->setDebugLoc(Call.getDebugLoc());
537
538 NewCall->takeName(&Call);
539 Call.replaceAllUsesWith(NewCall);
541}
542
543// Figure out what state we should assign calls in this block.
544int WinEHStateFnPassImpl::getBaseStateForBB(
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>(FuncletEntryBB->getFirstNonPHIIt())) {
554 auto BaseStateI = FuncInfo.FuncletBaseStateMap.find(FuncletPad);
555 if (BaseStateI != FuncInfo.FuncletBaseStateMap.end())
556 BaseState = BaseStateI->second;
557 }
558
559 return BaseState;
560}
561
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, Intrinsic::seh_scope_end);
569}
570
571static bool isSehScopeBegin(const CallBase &Call) {
572 return isIntrinsic(Call, Intrinsic::seh_scope_begin);
573}
574
575// Calculate the state a call-site is in.
576int WinEHStateFnPassImpl::getStateForCall(
578 CallBase &Call) {
579 if (auto *II = dyn_cast<InvokeInst>(&Call)) {
580 if (isSehScopeEnd(*II)) {
581 return getBaseStateForBB(BlockColors, FuncInfo, 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, Call.getParent());
591}
592
593// Calculate the intersection of all the FinalStates for a BasicBlock's
594// predecessors.
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(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>(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.
637 int ParentBaseState, BasicBlock *BB) {
638 // This block rejoins normal control flow,
639 // conservatively report this basic block as overdefined.
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(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) {
673 return true;
674 }
675
676 // If the function touches memory, it needs a state store.
677 if (isAsynchronousEHPersonality(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(RegNode, Builder.getPtrTy());
690 Builder.CreateIntrinsic(Intrinsic::x86_seh_ehregnode, {RegNodeI8});
691
692 if (EHGuardNode) {
693 IRBuilder<> Builder(EHGuardNode->getNextNode());
694 Value *EHGuardNodeI8 =
695 Builder.CreateBitCast(EHGuardNode, Builder.getPtrTy());
696 Builder.CreateIntrinsic(Intrinsic::x86_seh_ehguard, {EHGuardNodeI8});
697 }
698
699 // Calculate state numbers.
700 if (isAsynchronousEHPersonality(Personality))
701 calculateSEHStateNumbers(&F, FuncInfo);
702 else
704
705 // Iterate all the instructions and emit state number stores.
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>(&I);
724 if (!Call || !isStateStoreNeeded(Personality, *Call))
725 continue;
726
727 int State = getStateForCall(BlockColors, FuncInfo, *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(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({BB, InitialState});
743 FinalStates.insert({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(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({BB, PredState});
761 FinalStates.insert({BB, PredState});
762 for (BasicBlock *SuccBB : successors(BB))
763 Worklist.push_back(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({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>(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>(&I);
791 if (!Call || !isStateStoreNeeded(Personality, *Call))
792 continue;
793
794 int State = getStateForCall(BlockColors, FuncInfo, *Call);
795 if (State != PrevState)
796 insertStateNumberStore(&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(BB);
802 if (EndState != FinalStates.end())
803 if (EndState->second != PrevState)
804 insertStateNumberStore(BB->getTerminator(), 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>(&I);
811 if (!Call)
812 continue;
814 SetJmp3.getCallee()->stripPointerCasts())
815 continue;
816
817 SetJmp3Calls.push_back(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>(FuncletEntryBB->getFirstNonPHIIt());
825
826 IRBuilder<> Builder(Call);
827 Value *State;
828 if (InCleanup) {
829 Value *StateField =
830 Builder.CreateStructGEP(RegNodeTy, RegNode, StateFieldIndex);
831 State = Builder.CreateLoad(Builder.getInt32Ty(), StateField);
832 } else {
833 State = Builder.getInt32(getStateForCall(BlockColors, FuncInfo, *Call));
834 }
835 rewriteSetJmpCall(Builder, F, *Call, State);
836 }
837}
838
839void WinEHStateFnPassImpl::insertStateNumberStore(Instruction *IP, int State) {
840 IRBuilder<> Builder(IP);
841 Value *StateField =
842 Builder.CreateStructGEP(RegNodeTy, RegNode, StateFieldIndex);
843 Builder.CreateStore(Builder.getInt32(State), 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>(&I)) {
850 if (Alloca->isStaticAlloca())
851 continue;
852 IRBuilder<> Builder(Alloca->getNextNode());
853 // SavedESP = llvm.stacksave()
854 Value *SP = Builder.CreateStackSave();
855 Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
856 }
857
858 if (auto *II = dyn_cast<IntrinsicInst>(&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(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
865 }
866 }
867 }
868}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
arc branch finalize
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:54
#define I(x, y, z)
Definition MD5.cpp:57
#define T
uint64_t IntrinsicInst * II
ModuleAnalysisManager MAM
#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 void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, const llvm::StringTable &StandardNames, VectorLibrary VecLib)
Initialize the set of available library functions based on the specified target triple.
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
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:493
bool isEHPad() const
Return true if this basic block is an exception handling block.
Definition BasicBlock.h:713
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
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
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.
This class represents a function call, abstracting a target machine's calling convention.
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.
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:178
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:174
iterator end()
Definition DenseMap.h:81
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:241
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
Class to represent function types.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
Definition Function.cpp:639
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition Function.h:168
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
Definition Function.h:246
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:251
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:358
LLVM_ABI void setComdat(Comdat *C)
Definition Globals.cpp:215
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:1124
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:1238
Value * CreateStructGEP(Type *Ty, Value *Ptr, unsigned Idx, const Twine &Name="")
Definition IRBuilder.h:2018
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Definition IRBuilder.h:561
ReturnInst * CreateRet(Value *V)
Create a 'ret <val>' instruction.
Definition IRBuilder.h:1175
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:2176
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:1854
LLVMContext & getContext() const
Definition IRBuilder.h:203
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Definition IRBuilder.h:1867
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:2487
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
Definition IRBuilder.h:604
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2787
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.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Definition Analysis.h:151
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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:619
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:296
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Definition Type.cpp:280
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:553
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
Definition Value.cpp:708
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:403
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
const ParentTy * getParent() const
Definition ilist_node.h:34
CallInst * Call
Changed
#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
@ 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
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
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.
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:547
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)
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:559
auto predecessors(const MachineBasicBlock *BB)
FunctionPass * createX86WinEHStateLegacyPass()
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
DenseMap< const FuncletPadInst *, int > FuncletBaseStateMap
DenseMap< const InvokeInst *, int > InvokeStateMap