35 #define DEBUG_TYPE "winehstate"
42 const int OverdefinedState = INT_MIN;
52 bool runOnFunction(
Function &Fn)
override;
54 bool doInitialization(
Module &M)
override;
56 bool doFinalization(
Module &M)
override;
61 return "Windows 32-bit x86 EH state insertion";
65 void emitExceptionRegistrationRecord(
Function *
F);
68 void unlinkExceptionRegistration(
IRBuilder<> &Builder);
70 void insertStateNumberStore(
Instruction *IP,
int State);
85 Type *getEHLinkRegistrationType();
86 Type *getSEHRegistrationType();
87 Type *getCXXEHRegistrationType();
90 Module *TheModule =
nullptr;
95 Constant *CxxLongjmpUnwind =
nullptr;
100 bool UseStackGuard =
false;
102 Constant *SehLongjmpUnwind =
nullptr;
113 int StateFieldIndex = ~0U;
125 "Insert stores for EH state numbers",
false,
false)
127 bool WinEHStatePass::doInitialization(
Module &M) {
132 bool WinEHStatePass::doFinalization(
Module &M) {
135 EHLinkRegistrationTy =
nullptr;
136 CXXEHRegistrationTy =
nullptr;
137 SEHRegistrationTy =
nullptr;
139 CxxLongjmpUnwind =
nullptr;
140 SehLongjmpUnwind =
nullptr;
145 void WinEHStatePass::getAnalysisUsage(
AnalysisUsage &AU)
const {
151 bool WinEHStatePass::runOnFunction(
Function &
F) {
165 bool HasPads =
false;
176 SetJmp3 = TheModule->getOrInsertFunction(
185 F.addFnAttr(
"no-frame-pointer-elim",
"true");
187 emitExceptionRegistrationRecord(&F);
195 addStateStores(F, FuncInfo);
198 PersonalityFn =
nullptr;
200 UseStackGuard =
false;
202 EHGuardNode =
nullptr;
214 Type *WinEHStatePass::getEHLinkRegistrationType() {
215 if (EHLinkRegistrationTy)
216 return EHLinkRegistrationTy;
223 EHLinkRegistrationTy->setBody(FieldTys,
false);
224 return EHLinkRegistrationTy;
233 Type *WinEHStatePass::getCXXEHRegistrationType() {
234 if (CXXEHRegistrationTy)
235 return CXXEHRegistrationTy;
239 getEHLinkRegistrationType(),
242 CXXEHRegistrationTy =
244 return CXXEHRegistrationTy;
255 Type *WinEHStatePass::getSEHRegistrationType() {
256 if (SEHRegistrationTy)
257 return SEHRegistrationTy;
262 getEHLinkRegistrationType(),
267 return SEHRegistrationTy;
274 void WinEHStatePass::emitExceptionRegistrationRecord(
Function *F) {
287 RegNodeTy = getCXXEHRegistrationType();
288 RegNode = Builder.CreateAlloca(RegNodeTy);
290 Value *
SP = Builder.CreateCall(
292 Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
295 ParentBaseState = -1;
296 insertStateNumberStore(&*Builder.GetInsertPoint(), ParentBaseState);
298 Function *Trampoline = generateLSDAInEAXThunk(F);
299 Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 1);
300 linkExceptionRegistration(Builder, Trampoline);
302 CxxLongjmpUnwind = TheModule->getOrInsertFunction(
303 "__CxxLongjmpUnwind",
305 cast<Function>(CxxLongjmpUnwind->stripPointerCasts())
310 StringRef PersonalityName = PersonalityFn->getName();
311 UseStackGuard = (PersonalityName ==
"_except_handler4");
314 RegNodeTy = getSEHRegistrationType();
315 RegNode = Builder.CreateAlloca(RegNodeTy);
317 EHGuardNode = Builder.CreateAlloca(Int32Ty);
320 Value *SP = Builder.CreateCall(
322 Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
325 ParentBaseState = UseStackGuard ? -2 : -1;
326 insertStateNumberStore(&*Builder.GetInsertPoint(), ParentBaseState);
328 Value *LSDA = emitEHLSDA(Builder, F);
329 LSDA = Builder.CreatePtrToInt(LSDA, Int32Ty);
333 Cookie = TheModule->getOrInsertGlobal(
"__security_cookie", Int32Ty);
334 Value *Val = Builder.CreateLoad(Int32Ty, Cookie,
"cookie");
335 LSDA = Builder.CreateXor(LSDA, Val);
337 Builder.CreateStore(LSDA, Builder.CreateStructGEP(RegNodeTy, RegNode, 3));
341 Value *Val = Builder.CreateLoad(Int32Ty, Cookie);
342 Value *FrameAddr = Builder.CreateCall(
344 Builder.getInt32(0),
"frameaddr");
345 Value *FrameAddrI32 = Builder.CreatePtrToInt(FrameAddr, Int32Ty);
346 FrameAddrI32 = Builder.CreateXor(FrameAddrI32, Val);
347 Builder.CreateStore(FrameAddrI32, EHGuardNode);
351 Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 2);
352 linkExceptionRegistration(Builder, PersonalityFn);
354 SehLongjmpUnwind = TheModule->getOrInsertFunction(
355 UseStackGuard ?
"_seh_longjmp_unwind4" :
"_seh_longjmp_unwind",
358 cast<Function>(SehLongjmpUnwind->stripPointerCasts())
367 if (!isa<ReturnInst>(T))
369 Builder.SetInsertPoint(T);
370 unlinkExceptionRegistration(Builder);
391 Type *ArgTys[5] = {Int8PtrType, Int8PtrType, Int8PtrType, Int8PtrType,
406 Value *LSDA = emitEHLSDA(Builder, ParentFunc);
407 Value *CastPersonality =
410 Value *
Args[5] = {LSDA, &*AI++, &*AI++, &*AI++, &*AI++};
420 void WinEHStatePass::linkExceptionRegistration(
IRBuilder<> &Builder,
425 Type *LinkTy = getEHLinkRegistrationType();
438 void WinEHStatePass::unlinkExceptionRegistration(
IRBuilder<> &Builder) {
440 if (
auto *
GEP = dyn_cast<GetElementPtrInst>(
Link)) {
441 GEP = cast<GetElementPtrInst>(
GEP->clone());
445 Type *LinkTy = getEHLinkRegistrationType();
471 OptionalArgs.
push_back(CxxLongjmpUnwind);
473 OptionalArgs.
push_back(emitEHLSDA(Builder, &F));
475 OptionalArgs.
push_back(SehLongjmpUnwind);
491 auto *CI = cast<CallInst>(Inst);
496 auto *II = cast<InvokeInst>(Inst);
498 SetJmp3, II->getNormalDest(), II->getUnwindDest(),
Args, OpBundles);
502 NewCS->setDebugLoc(CS->getDebugLoc());
511 int WinEHStatePass::getBaseStateForBB(
514 int BaseState = ParentBaseState;
515 auto &BBColors = BlockColors[BB];
517 assert(BBColors.size() == 1 &&
"multi-color BB not removed by preparation");
519 if (
auto *FuncletPad =
520 dyn_cast<FuncletPadInst>(FuncletEntryBB->getFirstNonPHI())) {
523 BaseState = BaseStateI->second;
530 int WinEHStatePass::getStateForCallSite(
540 return getBaseStateForBB(BlockColors, FuncInfo, CS.
getParent());
550 return ParentBaseState;
554 return OverdefinedState;
556 int CommonState = OverdefinedState;
560 auto PredEndState = FinalStates.
find(PredBB);
561 if (PredEndState == FinalStates.
end())
562 return OverdefinedState;
566 if (isa<CatchReturnInst>(PredBB->getTerminator()))
567 return OverdefinedState;
569 int PredState = PredEndState->second;
570 assert(PredState != OverdefinedState &&
571 "overdefined BBs shouldn't be in FinalStates");
572 if (CommonState == OverdefinedState)
573 CommonState = PredState;
577 if (CommonState != PredState)
578 return OverdefinedState;
591 return OverdefinedState;
593 int CommonState = OverdefinedState;
597 auto SuccStartState = InitialStates.
find(SuccBB);
598 if (SuccStartState == InitialStates.
end())
599 return OverdefinedState;
602 if (SuccBB->isEHPad())
603 return OverdefinedState;
605 int SuccState = SuccStartState->second;
606 assert(SuccState != OverdefinedState &&
607 "overdefined BBs shouldn't be in FinalStates");
608 if (CommonState == OverdefinedState)
609 CommonState = SuccState;
613 if (CommonState != SuccState)
614 return OverdefinedState;
620 bool WinEHStatePass::isStateStoreNeeded(
EHPersonality Personality,
644 Value *EHGuardNodeI8 =
667 std::deque<BasicBlock *> Worklist;
670 int InitialState = OverdefinedState;
673 InitialState = FinalState = ParentBaseState;
676 if (!isStateStoreNeeded(Personality, CS))
679 int State = getStateForCallSite(BlockColors, FuncInfo, CS);
680 if (InitialState == OverdefinedState)
681 InitialState = State;
686 if (InitialState == OverdefinedState) {
687 Worklist.push_back(BB);
690 DEBUG(
dbgs() <<
"X86WinEHState: " << BB->getName()
691 <<
" InitialState=" << InitialState <<
'\n');
692 DEBUG(
dbgs() <<
"X86WinEHState: " << BB->getName()
693 <<
" FinalState=" << FinalState <<
'\n');
694 InitialStates.
insert({BB, InitialState});
695 FinalStates.
insert({BB, FinalState});
699 while (!Worklist.empty()) {
701 Worklist.pop_front();
703 if (InitialStates.
count(BB) != 0)
706 int PredState =
getPredState(FinalStates, F, ParentBaseState, BB);
707 if (PredState == OverdefinedState)
712 InitialStates.
insert({BB, PredState});
713 FinalStates.
insert({BB, PredState});
715 Worklist.push_back(SuccBB);
720 int SuccState =
getSuccState(InitialStates, F, ParentBaseState, BB);
721 if (SuccState == OverdefinedState)
726 FinalStates.
insert({BB, SuccState});
732 auto &BBColors = BlockColors[BB];
737 int PrevState =
getPredState(FinalStates, F, ParentBaseState, BB);
739 <<
" PrevState=" << PrevState <<
'\n');
743 if (!isStateStoreNeeded(Personality, CS))
746 int State = getStateForCallSite(BlockColors, FuncInfo, CS);
747 if (State != PrevState)
748 insertStateNumberStore(&
I, State);
753 auto EndState = FinalStates.
find(BB);
754 if (EndState != FinalStates.
end())
755 if (EndState->second != PrevState)
756 insertStateNumberStore(BB->getTerminator(), EndState->second);
773 for (
CallSite CS : SetJmp3CallSites) {
774 auto &BBColors = BlockColors[CS->
getParent()];
776 bool InCleanup = isa<CleanupPadInst>(FuncletEntryBB->
getFirstNonPHI());
785 State = Builder.
getInt32(getStateForCallSite(BlockColors, FuncInfo, CS));
787 rewriteSetJmpCallSite(Builder, F, CS, State);
791 void WinEHStatePass::insertStateNumberStore(
Instruction *IP,
int State) {
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
void push_back(const T &Elt)
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
void getOperandBundlesAsDefs(SmallVectorImpl< OperandBundleDef > &Defs) const
A Module instance is used to store all the information related to an LLVM module. ...
DenseMap< const FuncletPadInst *, int > FuncletBaseStateMap
BBTy * getParent() const
Get the basic block containing the call site.
This class represents a function call, abstracting a target machine's calling convention.
InvokeInst * CreateInvoke(Value *Callee, BasicBlock *NormalDest, BasicBlock *UnwindDest, ArrayRef< Value * > Args=None, const Twine &Name="")
Create an invoke instruction.
bool isEHPad() const
Return true if this basic block is an exception handling block.
const Instruction & front() const
static int getPredState(DenseMap< BasicBlock *, int > &FinalStates, Function &F, int ParentBaseState, BasicBlock *BB)
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
StringRef getName() const
Return a constant reference to the value's name.
iterator begin()
Instruction iterator methods.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
void calculateSEHStateNumbers(const Function *ParentFn, WinEHFuncInfo &FuncInfo)
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
Class to represent struct types.
ValTy * getCalledValue() const
getCalledValue - Return the pointer to function that is being called.
Instruction * getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
ReturnInst * CreateRet(Value *V)
Create a 'ret <val>' instruction.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
bool isCall() const
isCall - true if a CallInst is enclosed.
Constant * getPersonalityFn() const
Get the personality function associated with this function.
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Class to represent function types.
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
CallingConv::ID getCallingConv() const
getCallingConv/setCallingConv - get or set the calling convention of the call.
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
InstTy * Insert(InstTy *I, const Twine &Name="") const
Insert and return the specified instruction.
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=None)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
void takeName(Value *V)
Transfer the name from V to this value.
LoadInst * CreateLoad(Value *Ptr, const char *Name)
Subclasses of this class are all able to terminate a basic block.
Constant * stripPointerCasts()
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
This is an important class for using LLVM in a threaded context.
This is an important base class in LLVM.
X86_StdCall - stdcall is the calling conventions mostly used by the Win32 API.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
bool hasPersonalityFn() const
Check whether this function has a personality function.
EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
Represent the analysis usage information of a pass.
static Type * getVoidTy(LLVMContext &C)
FunctionPass class - This class is used to implement most global optimizations.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
DenseMap< const InvokeInst *, int > InvokeStateMap
void setTailCallKind(TailCallKind TCK)
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
void setTailCall(bool isTC=true)
PointerType * getInt8PtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer to an 8-bit integer value.
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool doesNotAccessMemory() const
Determine if the call does not access memory.
AttributeSet getAttributes() const
getAttributes/setAttributes - get or set the parameter attributes of the call.
void calculateWinCXXEHStateNumbers(const Function *ParentFn, WinEHFuncInfo &FuncInfo)
Analyze the IR in ParentFn and it's handlers to build WinEHFuncInfo, which describes the state number...
InstrTy * getInstruction() const
bool isFuncletEHPersonality(EHPersonality Pers)
Returns true if this is a personality function that invokes handler funclets (which must return to it...
static int getSuccState(DenseMap< BasicBlock *, int > &InitialStates, Function &F, int ParentBaseState, BasicBlock *BB)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Module.h This file contains the declarations for the Module class.
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
Value * stripPointerCasts()
Strip off pointer casts, all-zero GEPs, and aliases.
pred_range predecessors(BasicBlock *BB)
void setPreservesCFG()
This function should be called by the pass, iff they do not:
const BasicBlock & getEntryBlock() const
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
size_type count(const KeyT &Val) const
Return 1 if the specified key is in the map, 0 otherwise.
unsigned getNumArgOperands() const
INITIALIZE_PASS(WinEHStatePass,"x86-winehstate","Insert stores for EH state numbers", false, false) bool WinEHStatePass
static StringRef getRealLinkageName(StringRef Name)
If special LLVM prefix that is used to inform the asm printer to not emit usual symbol prefix before ...
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
static IntegerType * getInt32Ty(LLVMContext &C)
TerminatorInst * getTerminator()
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
CallInst * CreateCall(Value *Callee, ArrayRef< Value * > Args=None, const Twine &Name="", MDNode *FPMathTag=nullptr)
iterator find(const KeyT &Val)
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Rename collisions when linking (static functions).
void initializeWinEHStatePassPass(PassRegistry &)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool isAsynchronousEHPersonality(EHPersonality Pers)
Returns true if this personality function catches asynchronous exceptions.
LLVM Value Representation.
succ_range successors(BasicBlock *BB)
static StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
ValTy * getArgOperand(unsigned i) const
void setCallingConv(CallingConv::ID CC)
Value * CreateStructGEP(Type *Ty, Value *Ptr, unsigned Idx, const Twine &Name="")
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
StringRef - Represent a constant reference to a string, i.e.
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, const Twine &N="", Module *M=nullptr)
void addAttribute(unsigned i, Attribute::AttrKind Kind)
adds the attribute to the list of attributes.
FunctionPass * createX86WinEHStatePass()
Return an IR pass that inserts EH registration stack objects and explicit EH state updates...
DenseMap< BasicBlock *, ColorVector > colorEHFunclets(Function &F)
If an EH funclet personality is in use (see isFuncletEHPersonality), this will recompute which blocks...
bool doesNotThrow() const
Determine if the call cannot unwind.
an instruction to allocate memory on the stack