1 //===-- X86WinEHState - Insert EH state updates for win32 exceptions ------===//
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
7 //===----------------------------------------------------------------------===//
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.
14 //===----------------------------------------------------------------------===//
17 #include "llvm/ADT/PostOrderIterator.h"
18 #include "llvm/Analysis/CFG.h"
19 #include "llvm/Analysis/EHPersonalities.h"
20 #include "llvm/CodeGen/MachineModuleInfo.h"
21 #include "llvm/CodeGen/WinEHFuncInfo.h"
22 #include "llvm/IR/CallSite.h"
23 #include "llvm/IR/Function.h"
24 #include "llvm/IR/IRBuilder.h"
25 #include "llvm/IR/Instructions.h"
26 #include "llvm/IR/IntrinsicInst.h"
27 #include "llvm/IR/Module.h"
28 #include "llvm/Pass.h"
29 #include "llvm/Support/Debug.h"
34 #define DEBUG_TYPE "winehstate"
37 const int OverdefinedState
= INT_MIN
;
39 class WinEHStatePass
: public FunctionPass
{
41 static char ID
; // Pass identification, replacement for typeid.
43 WinEHStatePass() : FunctionPass(ID
) { }
45 bool runOnFunction(Function
&Fn
) override
;
47 bool doInitialization(Module
&M
) override
;
49 bool doFinalization(Module
&M
) override
;
51 void getAnalysisUsage(AnalysisUsage
&AU
) const override
;
53 StringRef
getPassName() const override
{
54 return "Windows 32-bit x86 EH state insertion";
58 void emitExceptionRegistrationRecord(Function
*F
);
60 void linkExceptionRegistration(IRBuilder
<> &Builder
, Function
*Handler
);
61 void unlinkExceptionRegistration(IRBuilder
<> &Builder
);
62 void addStateStores(Function
&F
, WinEHFuncInfo
&FuncInfo
);
63 void insertStateNumberStore(Instruction
*IP
, int State
);
65 Value
*emitEHLSDA(IRBuilder
<> &Builder
, Function
*F
);
67 Function
*generateLSDAInEAXThunk(Function
*ParentFunc
);
69 bool isStateStoreNeeded(EHPersonality Personality
, CallSite CS
);
70 void rewriteSetJmpCallSite(IRBuilder
<> &Builder
, Function
&F
, CallSite CS
,
72 int getBaseStateForBB(DenseMap
<BasicBlock
*, ColorVector
> &BlockColors
,
73 WinEHFuncInfo
&FuncInfo
, BasicBlock
*BB
);
74 int getStateForCallSite(DenseMap
<BasicBlock
*, ColorVector
> &BlockColors
,
75 WinEHFuncInfo
&FuncInfo
, CallSite CS
);
77 // Module-level type getters.
78 Type
*getEHLinkRegistrationType();
79 Type
*getSEHRegistrationType();
80 Type
*getCXXEHRegistrationType();
83 Module
*TheModule
= nullptr;
84 StructType
*EHLinkRegistrationTy
= nullptr;
85 StructType
*CXXEHRegistrationTy
= nullptr;
86 StructType
*SEHRegistrationTy
= nullptr;
87 FunctionCallee SetJmp3
= nullptr;
88 FunctionCallee CxxLongjmpUnwind
= nullptr;
91 EHPersonality Personality
= EHPersonality::Unknown
;
92 Function
*PersonalityFn
= nullptr;
93 bool UseStackGuard
= false;
95 FunctionCallee SehLongjmpUnwind
= nullptr;
96 Constant
*Cookie
= nullptr;
98 /// The stack allocation containing all EH data, including the link in the
99 /// fs:00 chain and the current state.
100 AllocaInst
*RegNode
= nullptr;
102 // The allocation containing the EH security guard.
103 AllocaInst
*EHGuardNode
= nullptr;
105 /// The index of the state field of RegNode.
106 int StateFieldIndex
= ~0U;
108 /// The linked list node subobject inside of RegNode.
109 Value
*Link
= nullptr;
113 FunctionPass
*llvm::createX86WinEHStatePass() { return new WinEHStatePass(); }
115 char WinEHStatePass::ID
= 0;
117 INITIALIZE_PASS(WinEHStatePass
, "x86-winehstate",
118 "Insert stores for EH state numbers", false, false)
120 bool WinEHStatePass::doInitialization(Module
&M
) {
125 bool WinEHStatePass::doFinalization(Module
&M
) {
126 assert(TheModule
== &M
);
128 EHLinkRegistrationTy
= nullptr;
129 CXXEHRegistrationTy
= nullptr;
130 SEHRegistrationTy
= nullptr;
132 CxxLongjmpUnwind
= nullptr;
133 SehLongjmpUnwind
= nullptr;
138 void WinEHStatePass::getAnalysisUsage(AnalysisUsage
&AU
) const {
139 // This pass should only insert a stack allocation, memory accesses, and
141 AU
.setPreservesCFG();
144 bool WinEHStatePass::runOnFunction(Function
&F
) {
145 // Don't insert state stores or exception handler thunks for
146 // available_externally functions. The handler needs to reference the LSDA,
147 // which will not be emitted in this case.
148 if (F
.hasAvailableExternallyLinkage())
151 // Check the personality. Do nothing if this personality doesn't use funclets.
152 if (!F
.hasPersonalityFn())
155 dyn_cast
<Function
>(F
.getPersonalityFn()->stripPointerCasts());
158 Personality
= classifyEHPersonality(PersonalityFn
);
159 if (!isFuncletEHPersonality(Personality
))
162 // Skip this function if there are no EH pads and we aren't using IR-level
164 bool HasPads
= false;
165 for (BasicBlock
&BB
: F
) {
174 Type
*Int8PtrType
= Type::getInt8PtrTy(TheModule
->getContext());
175 SetJmp3
= TheModule
->getOrInsertFunction(
176 "_setjmp3", FunctionType::get(
177 Type::getInt32Ty(TheModule
->getContext()),
178 {Int8PtrType
, Type::getInt32Ty(TheModule
->getContext())},
181 // Disable frame pointer elimination in this function.
182 // FIXME: Do the nested handlers need to keep the parent ebp in ebp, or can we
183 // use an arbitrary register?
184 F
.addFnAttr("no-frame-pointer-elim", "true");
186 emitExceptionRegistrationRecord(&F
);
188 // The state numbers calculated here in IR must agree with what we calculate
189 // later on for the MachineFunction. In particular, if an IR pass deletes an
190 // unreachable EH pad after this point before machine CFG construction, we
191 // will be in trouble. If this assumption is ever broken, we should turn the
192 // numbers into an immutable analysis pass.
193 WinEHFuncInfo FuncInfo
;
194 addStateStores(F
, FuncInfo
);
196 // Reset per-function state.
197 PersonalityFn
= nullptr;
198 Personality
= EHPersonality::Unknown
;
199 UseStackGuard
= false;
201 EHGuardNode
= nullptr;
206 /// Get the common EH registration subobject:
207 /// typedef _EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE)(
208 /// _EXCEPTION_RECORD *, void *, _CONTEXT *, void *);
209 /// struct EHRegistrationNode {
210 /// EHRegistrationNode *Next;
211 /// PEXCEPTION_ROUTINE Handler;
213 Type
*WinEHStatePass::getEHLinkRegistrationType() {
214 if (EHLinkRegistrationTy
)
215 return EHLinkRegistrationTy
;
216 LLVMContext
&Context
= TheModule
->getContext();
217 EHLinkRegistrationTy
= StructType::create(Context
, "EHRegistrationNode");
219 EHLinkRegistrationTy
->getPointerTo(0), // EHRegistrationNode *Next
220 Type::getInt8PtrTy(Context
) // EXCEPTION_DISPOSITION (*Handler)(...)
222 EHLinkRegistrationTy
->setBody(FieldTys
, false);
223 return EHLinkRegistrationTy
;
226 /// The __CxxFrameHandler3 registration node:
227 /// struct CXXExceptionRegistration {
229 /// EHRegistrationNode SubRecord;
230 /// int32_t TryLevel;
232 Type
*WinEHStatePass::getCXXEHRegistrationType() {
233 if (CXXEHRegistrationTy
)
234 return CXXEHRegistrationTy
;
235 LLVMContext
&Context
= TheModule
->getContext();
237 Type::getInt8PtrTy(Context
), // void *SavedESP
238 getEHLinkRegistrationType(), // EHRegistrationNode SubRecord
239 Type::getInt32Ty(Context
) // int32_t TryLevel
241 CXXEHRegistrationTy
=
242 StructType::create(FieldTys
, "CXXExceptionRegistration");
243 return CXXEHRegistrationTy
;
246 /// The _except_handler3/4 registration node:
247 /// struct EH4ExceptionRegistration {
249 /// _EXCEPTION_POINTERS *ExceptionPointers;
250 /// EHRegistrationNode SubRecord;
251 /// int32_t EncodedScopeTable;
252 /// int32_t TryLevel;
254 Type
*WinEHStatePass::getSEHRegistrationType() {
255 if (SEHRegistrationTy
)
256 return SEHRegistrationTy
;
257 LLVMContext
&Context
= TheModule
->getContext();
259 Type::getInt8PtrTy(Context
), // void *SavedESP
260 Type::getInt8PtrTy(Context
), // void *ExceptionPointers
261 getEHLinkRegistrationType(), // EHRegistrationNode SubRecord
262 Type::getInt32Ty(Context
), // int32_t EncodedScopeTable
263 Type::getInt32Ty(Context
) // int32_t TryLevel
265 SEHRegistrationTy
= StructType::create(FieldTys
, "SEHExceptionRegistration");
266 return SEHRegistrationTy
;
269 // Emit an exception registration record. These are stack allocations with the
270 // common subobject of two pointers: the previous registration record (the old
271 // fs:00) and the personality function for the current frame. The data before
272 // and after that is personality function specific.
273 void WinEHStatePass::emitExceptionRegistrationRecord(Function
*F
) {
274 assert(Personality
== EHPersonality::MSVC_CXX
||
275 Personality
== EHPersonality::MSVC_X86SEH
);
277 // Struct type of RegNode. Used for GEPing.
280 IRBuilder
<> Builder(&F
->getEntryBlock(), F
->getEntryBlock().begin());
281 Type
*Int8PtrType
= Builder
.getInt8PtrTy();
282 Type
*Int32Ty
= Builder
.getInt32Ty();
283 Type
*VoidTy
= Builder
.getVoidTy();
285 if (Personality
== EHPersonality::MSVC_CXX
) {
286 RegNodeTy
= getCXXEHRegistrationType();
287 RegNode
= Builder
.CreateAlloca(RegNodeTy
);
288 // SavedESP = llvm.stacksave()
289 Value
*SP
= Builder
.CreateCall(
290 Intrinsic::getDeclaration(TheModule
, Intrinsic::stacksave
), {});
291 Builder
.CreateStore(SP
, Builder
.CreateStructGEP(RegNodeTy
, RegNode
, 0));
294 ParentBaseState
= -1;
295 insertStateNumberStore(&*Builder
.GetInsertPoint(), ParentBaseState
);
296 // Handler = __ehhandler$F
297 Function
*Trampoline
= generateLSDAInEAXThunk(F
);
298 Link
= Builder
.CreateStructGEP(RegNodeTy
, RegNode
, 1);
299 linkExceptionRegistration(Builder
, Trampoline
);
301 CxxLongjmpUnwind
= TheModule
->getOrInsertFunction(
302 "__CxxLongjmpUnwind",
303 FunctionType::get(VoidTy
, Int8PtrType
, /*isVarArg=*/false));
304 cast
<Function
>(CxxLongjmpUnwind
.getCallee()->stripPointerCasts())
305 ->setCallingConv(CallingConv::X86_StdCall
);
306 } else if (Personality
== EHPersonality::MSVC_X86SEH
) {
307 // If _except_handler4 is in use, some additional guard checks and prologue
308 // stuff is required.
309 StringRef PersonalityName
= PersonalityFn
->getName();
310 UseStackGuard
= (PersonalityName
== "_except_handler4");
312 // Allocate local structures.
313 RegNodeTy
= getSEHRegistrationType();
314 RegNode
= Builder
.CreateAlloca(RegNodeTy
);
316 EHGuardNode
= Builder
.CreateAlloca(Int32Ty
);
318 // SavedESP = llvm.stacksave()
319 Value
*SP
= Builder
.CreateCall(
320 Intrinsic::getDeclaration(TheModule
, Intrinsic::stacksave
), {});
321 Builder
.CreateStore(SP
, Builder
.CreateStructGEP(RegNodeTy
, RegNode
, 0));
322 // TryLevel = -2 / -1
324 ParentBaseState
= UseStackGuard
? -2 : -1;
325 insertStateNumberStore(&*Builder
.GetInsertPoint(), ParentBaseState
);
326 // ScopeTable = llvm.x86.seh.lsda(F)
327 Value
*LSDA
= emitEHLSDA(Builder
, F
);
328 LSDA
= Builder
.CreatePtrToInt(LSDA
, Int32Ty
);
329 // If using _except_handler4, xor the address of the table with
330 // __security_cookie.
332 Cookie
= TheModule
->getOrInsertGlobal("__security_cookie", Int32Ty
);
333 Value
*Val
= Builder
.CreateLoad(Int32Ty
, Cookie
, "cookie");
334 LSDA
= Builder
.CreateXor(LSDA
, Val
);
336 Builder
.CreateStore(LSDA
, Builder
.CreateStructGEP(RegNodeTy
, RegNode
, 3));
338 // If using _except_handler4, the EHGuard contains: FramePtr xor Cookie.
340 Value
*Val
= Builder
.CreateLoad(Int32Ty
, Cookie
);
341 Value
*FrameAddr
= Builder
.CreateCall(
342 Intrinsic::getDeclaration(
343 TheModule
, Intrinsic::frameaddress
,
344 Builder
.getInt8PtrTy(
345 TheModule
->getDataLayout().getAllocaAddrSpace())),
346 Builder
.getInt32(0), "frameaddr");
347 Value
*FrameAddrI32
= Builder
.CreatePtrToInt(FrameAddr
, Int32Ty
);
348 FrameAddrI32
= Builder
.CreateXor(FrameAddrI32
, Val
);
349 Builder
.CreateStore(FrameAddrI32
, EHGuardNode
);
352 // Register the exception handler.
353 Link
= Builder
.CreateStructGEP(RegNodeTy
, RegNode
, 2);
354 linkExceptionRegistration(Builder
, PersonalityFn
);
356 SehLongjmpUnwind
= TheModule
->getOrInsertFunction(
357 UseStackGuard
? "_seh_longjmp_unwind4" : "_seh_longjmp_unwind",
358 FunctionType::get(Type::getVoidTy(TheModule
->getContext()), Int8PtrType
,
359 /*isVarArg=*/false));
360 cast
<Function
>(SehLongjmpUnwind
.getCallee()->stripPointerCasts())
361 ->setCallingConv(CallingConv::X86_StdCall
);
363 llvm_unreachable("unexpected personality function");
366 // Insert an unlink before all returns.
367 for (BasicBlock
&BB
: *F
) {
368 Instruction
*T
= BB
.getTerminator();
369 if (!isa
<ReturnInst
>(T
))
371 Builder
.SetInsertPoint(T
);
372 unlinkExceptionRegistration(Builder
);
376 Value
*WinEHStatePass::emitEHLSDA(IRBuilder
<> &Builder
, Function
*F
) {
377 Value
*FI8
= Builder
.CreateBitCast(F
, Type::getInt8PtrTy(F
->getContext()));
378 return Builder
.CreateCall(
379 Intrinsic::getDeclaration(TheModule
, Intrinsic::x86_seh_lsda
), FI8
);
382 /// Generate a thunk that puts the LSDA of ParentFunc in EAX and then calls
383 /// PersonalityFn, forwarding the parameters passed to PEXCEPTION_ROUTINE:
384 /// typedef _EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE)(
385 /// _EXCEPTION_RECORD *, void *, _CONTEXT *, void *);
386 /// We essentially want this code:
388 /// jmpl ___CxxFrameHandler3
389 Function
*WinEHStatePass::generateLSDAInEAXThunk(Function
*ParentFunc
) {
390 LLVMContext
&Context
= ParentFunc
->getContext();
391 Type
*Int32Ty
= Type::getInt32Ty(Context
);
392 Type
*Int8PtrType
= Type::getInt8PtrTy(Context
);
393 Type
*ArgTys
[5] = {Int8PtrType
, Int8PtrType
, Int8PtrType
, Int8PtrType
,
395 FunctionType
*TrampolineTy
=
396 FunctionType::get(Int32Ty
, makeArrayRef(&ArgTys
[0], 4),
398 FunctionType
*TargetFuncTy
=
399 FunctionType::get(Int32Ty
, makeArrayRef(&ArgTys
[0], 5),
401 Function
*Trampoline
=
402 Function::Create(TrampolineTy
, GlobalValue::InternalLinkage
,
403 Twine("__ehhandler$") + GlobalValue::dropLLVMManglingEscape(
404 ParentFunc
->getName()),
406 if (auto *C
= ParentFunc
->getComdat())
407 Trampoline
->setComdat(C
);
408 BasicBlock
*EntryBB
= BasicBlock::Create(Context
, "entry", Trampoline
);
409 IRBuilder
<> Builder(EntryBB
);
410 Value
*LSDA
= emitEHLSDA(Builder
, ParentFunc
);
411 Value
*CastPersonality
=
412 Builder
.CreateBitCast(PersonalityFn
, TargetFuncTy
->getPointerTo());
413 auto AI
= Trampoline
->arg_begin();
414 Value
*Args
[5] = {LSDA
, &*AI
++, &*AI
++, &*AI
++, &*AI
++};
415 CallInst
*Call
= Builder
.CreateCall(TargetFuncTy
, CastPersonality
, Args
);
416 // Can't use musttail due to prototype mismatch, but we can use tail.
417 Call
->setTailCall(true);
418 // Set inreg so we pass it in EAX.
419 Call
->addParamAttr(0, Attribute::InReg
);
420 Builder
.CreateRet(Call
);
424 void WinEHStatePass::linkExceptionRegistration(IRBuilder
<> &Builder
,
426 // Emit the .safeseh directive for this function.
427 Handler
->addFnAttr("safeseh");
429 Type
*LinkTy
= getEHLinkRegistrationType();
431 Value
*HandlerI8
= Builder
.CreateBitCast(Handler
, Builder
.getInt8PtrTy());
432 Builder
.CreateStore(HandlerI8
, Builder
.CreateStructGEP(LinkTy
, Link
, 1));
435 Constant::getNullValue(LinkTy
->getPointerTo()->getPointerTo(257));
436 Value
*Next
= Builder
.CreateLoad(LinkTy
->getPointerTo(), FSZero
);
437 Builder
.CreateStore(Next
, Builder
.CreateStructGEP(LinkTy
, Link
, 0));
439 Builder
.CreateStore(Link
, FSZero
);
442 void WinEHStatePass::unlinkExceptionRegistration(IRBuilder
<> &Builder
) {
443 // Clone Link into the current BB for better address mode folding.
444 if (auto *GEP
= dyn_cast
<GetElementPtrInst
>(Link
)) {
445 GEP
= cast
<GetElementPtrInst
>(GEP
->clone());
449 Type
*LinkTy
= getEHLinkRegistrationType();
450 // [fs:00] = Link->Next
451 Value
*Next
= Builder
.CreateLoad(LinkTy
->getPointerTo(),
452 Builder
.CreateStructGEP(LinkTy
, Link
, 0));
454 Constant::getNullValue(LinkTy
->getPointerTo()->getPointerTo(257));
455 Builder
.CreateStore(Next
, FSZero
);
458 // Calls to setjmp(p) are lowered to _setjmp3(p, 0) by the frontend.
459 // The idea behind _setjmp3 is that it takes an optional number of personality
460 // specific parameters to indicate how to restore the personality-specific frame
461 // state when longjmp is initiated. Typically, the current TryLevel is saved.
462 void WinEHStatePass::rewriteSetJmpCallSite(IRBuilder
<> &Builder
, Function
&F
,
463 CallSite CS
, Value
*State
) {
464 // Don't rewrite calls with a weird number of arguments.
465 if (CS
.getNumArgOperands() != 2)
468 Instruction
*Inst
= CS
.getInstruction();
470 SmallVector
<OperandBundleDef
, 1> OpBundles
;
471 CS
.getOperandBundlesAsDefs(OpBundles
);
473 SmallVector
<Value
*, 3> OptionalArgs
;
474 if (Personality
== EHPersonality::MSVC_CXX
) {
475 OptionalArgs
.push_back(CxxLongjmpUnwind
.getCallee());
476 OptionalArgs
.push_back(State
);
477 OptionalArgs
.push_back(emitEHLSDA(Builder
, &F
));
478 } else if (Personality
== EHPersonality::MSVC_X86SEH
) {
479 OptionalArgs
.push_back(SehLongjmpUnwind
.getCallee());
480 OptionalArgs
.push_back(State
);
482 OptionalArgs
.push_back(Cookie
);
484 llvm_unreachable("unhandled personality!");
487 SmallVector
<Value
*, 5> Args
;
489 Builder
.CreateBitCast(CS
.getArgOperand(0), Builder
.getInt8PtrTy()));
490 Args
.push_back(Builder
.getInt32(OptionalArgs
.size()));
491 Args
.append(OptionalArgs
.begin(), OptionalArgs
.end());
495 auto *CI
= cast
<CallInst
>(Inst
);
496 CallInst
*NewCI
= Builder
.CreateCall(SetJmp3
, Args
, OpBundles
);
497 NewCI
->setTailCallKind(CI
->getTailCallKind());
500 auto *II
= cast
<InvokeInst
>(Inst
);
501 NewCS
= Builder
.CreateInvoke(
502 SetJmp3
, II
->getNormalDest(), II
->getUnwindDest(), Args
, OpBundles
);
504 NewCS
.setCallingConv(CS
.getCallingConv());
505 NewCS
.setAttributes(CS
.getAttributes());
506 NewCS
->setDebugLoc(CS
->getDebugLoc());
508 Instruction
*NewInst
= NewCS
.getInstruction();
509 NewInst
->takeName(Inst
);
510 Inst
->replaceAllUsesWith(NewInst
);
511 Inst
->eraseFromParent();
514 // Figure out what state we should assign calls in this block.
515 int WinEHStatePass::getBaseStateForBB(
516 DenseMap
<BasicBlock
*, ColorVector
> &BlockColors
, WinEHFuncInfo
&FuncInfo
,
518 int BaseState
= ParentBaseState
;
519 auto &BBColors
= BlockColors
[BB
];
521 assert(BBColors
.size() == 1 && "multi-color BB not removed by preparation");
522 BasicBlock
*FuncletEntryBB
= BBColors
.front();
523 if (auto *FuncletPad
=
524 dyn_cast
<FuncletPadInst
>(FuncletEntryBB
->getFirstNonPHI())) {
525 auto BaseStateI
= FuncInfo
.FuncletBaseStateMap
.find(FuncletPad
);
526 if (BaseStateI
!= FuncInfo
.FuncletBaseStateMap
.end())
527 BaseState
= BaseStateI
->second
;
533 // Calculate the state a call-site is in.
534 int WinEHStatePass::getStateForCallSite(
535 DenseMap
<BasicBlock
*, ColorVector
> &BlockColors
, WinEHFuncInfo
&FuncInfo
,
537 if (auto *II
= dyn_cast
<InvokeInst
>(CS
.getInstruction())) {
538 // Look up the state number of the EH pad this unwinds to.
539 assert(FuncInfo
.InvokeStateMap
.count(II
) && "invoke has no state!");
540 return FuncInfo
.InvokeStateMap
[II
];
542 // Possibly throwing call instructions have no actions to take after
543 // an unwind. Ensure they are in the -1 state.
544 return getBaseStateForBB(BlockColors
, FuncInfo
, CS
.getParent());
547 // Calculate the intersection of all the FinalStates for a BasicBlock's
549 static int getPredState(DenseMap
<BasicBlock
*, int> &FinalStates
, Function
&F
,
550 int ParentBaseState
, BasicBlock
*BB
) {
551 // The entry block has no predecessors but we know that the prologue always
552 // sets us up with a fixed state.
553 if (&F
.getEntryBlock() == BB
)
554 return ParentBaseState
;
556 // This is an EH Pad, conservatively report this basic block as overdefined.
558 return OverdefinedState
;
560 int CommonState
= OverdefinedState
;
561 for (BasicBlock
*PredBB
: predecessors(BB
)) {
562 // We didn't manage to get a state for one of these predecessors,
563 // conservatively report this basic block as overdefined.
564 auto PredEndState
= FinalStates
.find(PredBB
);
565 if (PredEndState
== FinalStates
.end())
566 return OverdefinedState
;
568 // This code is reachable via exceptional control flow,
569 // conservatively report this basic block as overdefined.
570 if (isa
<CatchReturnInst
>(PredBB
->getTerminator()))
571 return OverdefinedState
;
573 int PredState
= PredEndState
->second
;
574 assert(PredState
!= OverdefinedState
&&
575 "overdefined BBs shouldn't be in FinalStates");
576 if (CommonState
== OverdefinedState
)
577 CommonState
= PredState
;
579 // At least two predecessors have different FinalStates,
580 // conservatively report this basic block as overdefined.
581 if (CommonState
!= PredState
)
582 return OverdefinedState
;
588 // Calculate the intersection of all the InitialStates for a BasicBlock's
590 static int getSuccState(DenseMap
<BasicBlock
*, int> &InitialStates
, Function
&F
,
591 int ParentBaseState
, BasicBlock
*BB
) {
592 // This block rejoins normal control flow,
593 // conservatively report this basic block as overdefined.
594 if (isa
<CatchReturnInst
>(BB
->getTerminator()))
595 return OverdefinedState
;
597 int CommonState
= OverdefinedState
;
598 for (BasicBlock
*SuccBB
: successors(BB
)) {
599 // We didn't manage to get a state for one of these predecessors,
600 // conservatively report this basic block as overdefined.
601 auto SuccStartState
= InitialStates
.find(SuccBB
);
602 if (SuccStartState
== InitialStates
.end())
603 return OverdefinedState
;
605 // This is an EH Pad, conservatively report this basic block as overdefined.
606 if (SuccBB
->isEHPad())
607 return OverdefinedState
;
609 int SuccState
= SuccStartState
->second
;
610 assert(SuccState
!= OverdefinedState
&&
611 "overdefined BBs shouldn't be in FinalStates");
612 if (CommonState
== OverdefinedState
)
613 CommonState
= SuccState
;
615 // At least two successors have different InitialStates,
616 // conservatively report this basic block as overdefined.
617 if (CommonState
!= SuccState
)
618 return OverdefinedState
;
624 bool WinEHStatePass::isStateStoreNeeded(EHPersonality Personality
,
629 // If the function touches memory, it needs a state store.
630 if (isAsynchronousEHPersonality(Personality
))
631 return !CS
.doesNotAccessMemory();
633 // If the function throws, it needs a state store.
634 return !CS
.doesNotThrow();
637 void WinEHStatePass::addStateStores(Function
&F
, WinEHFuncInfo
&FuncInfo
) {
638 // Mark the registration node. The backend needs to know which alloca it is so
639 // that it can recover the original frame pointer.
640 IRBuilder
<> Builder(RegNode
->getNextNode());
641 Value
*RegNodeI8
= Builder
.CreateBitCast(RegNode
, Builder
.getInt8PtrTy());
643 Intrinsic::getDeclaration(TheModule
, Intrinsic::x86_seh_ehregnode
),
647 IRBuilder
<> Builder(EHGuardNode
->getNextNode());
648 Value
*EHGuardNodeI8
=
649 Builder
.CreateBitCast(EHGuardNode
, Builder
.getInt8PtrTy());
651 Intrinsic::getDeclaration(TheModule
, Intrinsic::x86_seh_ehguard
),
655 // Calculate state numbers.
656 if (isAsynchronousEHPersonality(Personality
))
657 calculateSEHStateNumbers(&F
, FuncInfo
);
659 calculateWinCXXEHStateNumbers(&F
, FuncInfo
);
661 // Iterate all the instructions and emit state number stores.
662 DenseMap
<BasicBlock
*, ColorVector
> BlockColors
= colorEHFunclets(F
);
663 ReversePostOrderTraversal
<Function
*> RPOT(&F
);
665 // InitialStates yields the state of the first call-site for a BasicBlock.
666 DenseMap
<BasicBlock
*, int> InitialStates
;
667 // FinalStates yields the state of the last call-site for a BasicBlock.
668 DenseMap
<BasicBlock
*, int> FinalStates
;
669 // Worklist used to revisit BasicBlocks with indeterminate
670 // Initial/Final-States.
671 std::deque
<BasicBlock
*> Worklist
;
672 // Fill in InitialStates and FinalStates for BasicBlocks with call-sites.
673 for (BasicBlock
*BB
: RPOT
) {
674 int InitialState
= OverdefinedState
;
676 if (&F
.getEntryBlock() == BB
)
677 InitialState
= FinalState
= ParentBaseState
;
678 for (Instruction
&I
: *BB
) {
680 if (!isStateStoreNeeded(Personality
, CS
))
683 int State
= getStateForCallSite(BlockColors
, FuncInfo
, CS
);
684 if (InitialState
== OverdefinedState
)
685 InitialState
= State
;
688 // No call-sites in this basic block? That's OK, we will come back to these
690 if (InitialState
== OverdefinedState
) {
691 Worklist
.push_back(BB
);
694 LLVM_DEBUG(dbgs() << "X86WinEHState: " << BB
->getName()
695 << " InitialState=" << InitialState
<< '\n');
696 LLVM_DEBUG(dbgs() << "X86WinEHState: " << BB
->getName()
697 << " FinalState=" << FinalState
<< '\n');
698 InitialStates
.insert({BB
, InitialState
});
699 FinalStates
.insert({BB
, FinalState
});
702 // Try to fill-in InitialStates and FinalStates which have no call-sites.
703 while (!Worklist
.empty()) {
704 BasicBlock
*BB
= Worklist
.front();
705 Worklist
.pop_front();
706 // This BasicBlock has already been figured out, nothing more we can do.
707 if (InitialStates
.count(BB
) != 0)
710 int PredState
= getPredState(FinalStates
, F
, ParentBaseState
, BB
);
711 if (PredState
== OverdefinedState
)
714 // We successfully inferred this BasicBlock's state via it's predecessors;
715 // enqueue it's successors to see if we can infer their states.
716 InitialStates
.insert({BB
, PredState
});
717 FinalStates
.insert({BB
, PredState
});
718 for (BasicBlock
*SuccBB
: successors(BB
))
719 Worklist
.push_back(SuccBB
);
722 // Try to hoist stores from successors.
723 for (BasicBlock
*BB
: RPOT
) {
724 int SuccState
= getSuccState(InitialStates
, F
, ParentBaseState
, BB
);
725 if (SuccState
== OverdefinedState
)
728 // Update our FinalState to reflect the common InitialState of our
730 FinalStates
.insert({BB
, SuccState
});
733 // Finally, insert state stores before call-sites which transition us to a new
735 for (BasicBlock
*BB
: RPOT
) {
736 auto &BBColors
= BlockColors
[BB
];
737 BasicBlock
*FuncletEntryBB
= BBColors
.front();
738 if (isa
<CleanupPadInst
>(FuncletEntryBB
->getFirstNonPHI()))
741 int PrevState
= getPredState(FinalStates
, F
, ParentBaseState
, BB
);
742 LLVM_DEBUG(dbgs() << "X86WinEHState: " << BB
->getName()
743 << " PrevState=" << PrevState
<< '\n');
745 for (Instruction
&I
: *BB
) {
747 if (!isStateStoreNeeded(Personality
, CS
))
750 int State
= getStateForCallSite(BlockColors
, FuncInfo
, CS
);
751 if (State
!= PrevState
)
752 insertStateNumberStore(&I
, State
);
756 // We might have hoisted a state store into this block, emit it now.
757 auto EndState
= FinalStates
.find(BB
);
758 if (EndState
!= FinalStates
.end())
759 if (EndState
->second
!= PrevState
)
760 insertStateNumberStore(BB
->getTerminator(), EndState
->second
);
763 SmallVector
<CallSite
, 1> SetJmp3CallSites
;
764 for (BasicBlock
*BB
: RPOT
) {
765 for (Instruction
&I
: *BB
) {
769 if (CS
.getCalledValue()->stripPointerCasts() !=
770 SetJmp3
.getCallee()->stripPointerCasts())
773 SetJmp3CallSites
.push_back(CS
);
777 for (CallSite CS
: SetJmp3CallSites
) {
778 auto &BBColors
= BlockColors
[CS
->getParent()];
779 BasicBlock
*FuncletEntryBB
= BBColors
.front();
780 bool InCleanup
= isa
<CleanupPadInst
>(FuncletEntryBB
->getFirstNonPHI());
782 IRBuilder
<> Builder(CS
.getInstruction());
785 Value
*StateField
= Builder
.CreateStructGEP(RegNode
->getAllocatedType(),
786 RegNode
, StateFieldIndex
);
787 State
= Builder
.CreateLoad(Builder
.getInt32Ty(), StateField
);
789 State
= Builder
.getInt32(getStateForCallSite(BlockColors
, FuncInfo
, CS
));
791 rewriteSetJmpCallSite(Builder
, F
, CS
, State
);
795 void WinEHStatePass::insertStateNumberStore(Instruction
*IP
, int State
) {
796 IRBuilder
<> Builder(IP
);
797 Value
*StateField
= Builder
.CreateStructGEP(RegNode
->getAllocatedType(),
798 RegNode
, StateFieldIndex
);
799 Builder
.CreateStore(Builder
.getInt32(State
), StateField
);