35 #define DEBUG_TYPE "winehstate" 38 const int OverdefinedState = INT_MIN;
50 bool doInitialization(
Module &M)
override;
52 bool doFinalization(
Module &M)
override;
57 return "Windows 32-bit x86 EH state insertion";
61 void emitExceptionRegistrationRecord(
Function *
F);
64 void unlinkExceptionRegistration(
IRBuilder<> &Builder);
66 void insertStateNumberStore(
Instruction *IP,
int State);
81 Type *getEHLinkRegistrationType();
82 Type *getSEHRegistrationType();
83 Type *getCXXEHRegistrationType();
86 Module *TheModule =
nullptr;
91 Constant *CxxLongjmpUnwind =
nullptr;
96 bool UseStackGuard =
false;
98 Constant *SehLongjmpUnwind =
nullptr;
109 int StateFieldIndex = ~0U;
121 "Insert stores for EH state numbers",
false,
false)
123 bool WinEHStatePass::doInitialization(
Module &M) {
128 bool WinEHStatePass::doFinalization(
Module &M) {
131 EHLinkRegistrationTy =
nullptr;
132 CXXEHRegistrationTy =
nullptr;
133 SEHRegistrationTy =
nullptr;
135 CxxLongjmpUnwind =
nullptr;
136 SehLongjmpUnwind =
nullptr;
141 void WinEHStatePass::getAnalysisUsage(
AnalysisUsage &AU)
const {
167 bool HasPads =
false;
178 SetJmp3 = TheModule->getOrInsertFunction(
187 F.addFnAttr(
"no-frame-pointer-elim",
"true");
189 emitExceptionRegistrationRecord(&F);
197 addStateStores(F, FuncInfo);
200 PersonalityFn =
nullptr;
202 UseStackGuard =
false;
204 EHGuardNode =
nullptr;
216 Type *WinEHStatePass::getEHLinkRegistrationType() {
217 if (EHLinkRegistrationTy)
218 return EHLinkRegistrationTy;
225 EHLinkRegistrationTy->setBody(FieldTys,
false);
226 return EHLinkRegistrationTy;
235 Type *WinEHStatePass::getCXXEHRegistrationType() {
236 if (CXXEHRegistrationTy)
237 return CXXEHRegistrationTy;
241 getEHLinkRegistrationType(),
244 CXXEHRegistrationTy =
246 return CXXEHRegistrationTy;
257 Type *WinEHStatePass::getSEHRegistrationType() {
258 if (SEHRegistrationTy)
259 return SEHRegistrationTy;
264 getEHLinkRegistrationType(),
269 return SEHRegistrationTy;
276 void WinEHStatePass::emitExceptionRegistrationRecord(
Function *F) {
289 RegNodeTy = getCXXEHRegistrationType();
290 RegNode = Builder.CreateAlloca(RegNodeTy);
292 Value *
SP = Builder.CreateCall(
294 Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
297 ParentBaseState = -1;
298 insertStateNumberStore(&*Builder.GetInsertPoint(), ParentBaseState);
300 Function *Trampoline = generateLSDAInEAXThunk(F);
301 Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 1);
302 linkExceptionRegistration(Builder, Trampoline);
304 CxxLongjmpUnwind = TheModule->getOrInsertFunction(
305 "__CxxLongjmpUnwind",
307 cast<Function>(CxxLongjmpUnwind->stripPointerCasts())
312 StringRef PersonalityName = PersonalityFn->getName();
313 UseStackGuard = (PersonalityName ==
"_except_handler4");
316 RegNodeTy = getSEHRegistrationType();
317 RegNode = Builder.CreateAlloca(RegNodeTy);
319 EHGuardNode = Builder.CreateAlloca(Int32Ty);
322 Value *
SP = Builder.CreateCall(
324 Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
327 ParentBaseState = UseStackGuard ? -2 : -1;
328 insertStateNumberStore(&*Builder.GetInsertPoint(), ParentBaseState);
330 Value *LSDA = emitEHLSDA(Builder, F);
331 LSDA = Builder.CreatePtrToInt(LSDA, Int32Ty);
335 Cookie = TheModule->getOrInsertGlobal(
"__security_cookie", Int32Ty);
336 Value *Val = Builder.CreateLoad(Int32Ty, Cookie,
"cookie");
337 LSDA = Builder.CreateXor(LSDA, Val);
339 Builder.CreateStore(LSDA, Builder.CreateStructGEP(RegNodeTy, RegNode, 3));
343 Value *Val = Builder.CreateLoad(Int32Ty, Cookie);
344 Value *FrameAddr = Builder.CreateCall(
346 Builder.getInt32(0),
"frameaddr");
347 Value *FrameAddrI32 = Builder.CreatePtrToInt(FrameAddr, Int32Ty);
348 FrameAddrI32 = Builder.CreateXor(FrameAddrI32, Val);
349 Builder.CreateStore(FrameAddrI32, EHGuardNode);
353 Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 2);
354 linkExceptionRegistration(Builder, PersonalityFn);
356 SehLongjmpUnwind = TheModule->getOrInsertFunction(
357 UseStackGuard ?
"_seh_longjmp_unwind4" :
"_seh_longjmp_unwind",
360 cast<Function>(SehLongjmpUnwind->stripPointerCasts())
369 if (!isa<ReturnInst>(T))
371 Builder.SetInsertPoint(T);
372 unlinkExceptionRegistration(Builder);
393 Type *ArgTys[5] = {Int8PtrType, Int8PtrType, Int8PtrType, Int8PtrType,
410 Value *LSDA = emitEHLSDA(Builder, ParentFunc);
411 Value *CastPersonality =
414 Value *
Args[5] = {LSDA, &*AI++, &*AI++, &*AI++, &*AI++};
424 void WinEHStatePass::linkExceptionRegistration(
IRBuilder<> &Builder,
429 Type *LinkTy = getEHLinkRegistrationType();
442 void WinEHStatePass::unlinkExceptionRegistration(
IRBuilder<> &Builder) {
444 if (
auto *
GEP = dyn_cast<GetElementPtrInst>(
Link)) {
445 GEP = cast<GetElementPtrInst>(
GEP->clone());
449 Type *LinkTy = getEHLinkRegistrationType();
475 OptionalArgs.
push_back(CxxLongjmpUnwind);
477 OptionalArgs.
push_back(emitEHLSDA(Builder, &F));
479 OptionalArgs.
push_back(SehLongjmpUnwind);
495 auto *CI = cast<CallInst>(Inst);
500 auto *II = cast<InvokeInst>(Inst);
502 SetJmp3, II->getNormalDest(), II->getUnwindDest(),
Args, OpBundles);
506 NewCS->setDebugLoc(CS->getDebugLoc());
515 int WinEHStatePass::getBaseStateForBB(
518 int BaseState = ParentBaseState;
519 auto &BBColors = BlockColors[BB];
521 assert(BBColors.size() == 1 &&
"multi-color BB not removed by preparation");
523 if (
auto *FuncletPad =
524 dyn_cast<FuncletPadInst>(FuncletEntryBB->getFirstNonPHI())) {
527 BaseState = BaseStateI->second;
534 int WinEHStatePass::getStateForCallSite(
544 return getBaseStateForBB(BlockColors, FuncInfo, CS.
getParent());
554 return ParentBaseState;
558 return OverdefinedState;
560 int CommonState = OverdefinedState;
564 auto PredEndState = FinalStates.
find(PredBB);
565 if (PredEndState == FinalStates.
end())
566 return OverdefinedState;
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;
581 if (CommonState != PredState)
582 return OverdefinedState;
595 return OverdefinedState;
597 int CommonState = OverdefinedState;
601 auto SuccStartState = InitialStates.
find(SuccBB);
602 if (SuccStartState == InitialStates.
end())
603 return OverdefinedState;
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;
617 if (CommonState != SuccState)
618 return OverdefinedState;
624 bool WinEHStatePass::isStateStoreNeeded(
EHPersonality Personality,
648 Value *EHGuardNodeI8 =
671 std::deque<BasicBlock *> Worklist;
674 int InitialState = OverdefinedState;
677 InitialState = FinalState = ParentBaseState;
680 if (!isStateStoreNeeded(Personality, CS))
683 int State = getStateForCallSite(BlockColors, FuncInfo, CS);
684 if (InitialState == OverdefinedState)
685 InitialState = State;
690 if (InitialState == OverdefinedState) {
691 Worklist.push_back(BB);
695 <<
" InitialState=" << InitialState <<
'\n');
697 <<
" FinalState=" << FinalState <<
'\n');
698 InitialStates.
insert({BB, InitialState});
699 FinalStates.
insert({BB, FinalState});
703 while (!Worklist.empty()) {
705 Worklist.pop_front();
707 if (InitialStates.
count(BB) != 0)
710 int PredState =
getPredState(FinalStates, F, ParentBaseState, BB);
711 if (PredState == OverdefinedState)
716 InitialStates.
insert({BB, PredState});
717 FinalStates.
insert({BB, PredState});
719 Worklist.push_back(SuccBB);
724 int SuccState =
getSuccState(InitialStates, F, ParentBaseState, BB);
725 if (SuccState == OverdefinedState)
730 FinalStates.
insert({BB, SuccState});
736 auto &BBColors = BlockColors[BB];
741 int PrevState =
getPredState(FinalStates, F, ParentBaseState, BB);
743 <<
" PrevState=" << PrevState <<
'\n');
747 if (!isStateStoreNeeded(Personality, CS))
750 int State = getStateForCallSite(BlockColors, FuncInfo, CS);
751 if (State != PrevState)
752 insertStateNumberStore(&
I, State);
757 auto EndState = FinalStates.
find(BB);
758 if (EndState != FinalStates.
end())
759 if (EndState->second != PrevState)
760 insertStateNumberStore(BB->getTerminator(), EndState->second);
773 SetJmp3CallSites.push_back(CS);
777 for (
CallSite CS : SetJmp3CallSites) {
778 auto &BBColors = BlockColors[CS->
getParent()];
780 bool InCleanup = isa<CleanupPadInst>(FuncletEntryBB->
getFirstNonPHI());
789 State = Builder.
getInt32(getStateForCallSite(BlockColors, FuncInfo, CS));
791 rewriteSetJmpCallSite(Builder, F, CS, State);
795 void WinEHStatePass::insertStateNumberStore(
Instruction *IP,
int State) {
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
CallingConv::ID getCallingConv() const
Get the calling convention of the call.
This class represents lattice values for constants.
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
A Module instance is used to store all the information related to an LLVM module. ...
void push_back(const T &Elt)
DenseMap< const FuncletPadInst *, int > FuncletBaseStateMap
This class represents a function call, abstracting a target machine's calling convention.
bool hasAvailableExternallyLinkage() const
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...
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.
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.
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
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...
InstrTy * getInstruction() const
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
ValTy * getCalledValue() const
Return the pointer to function that is being called.
Class to represent function types.
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
ValTy * getArgOperand(unsigned i) const
void setComdat(Comdat *C)
bool hasPersonalityFn() const
Check whether this function has a personality function.
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.
Function * getDeclaration(Module *M, ID id, ArrayRef< Type *> Tys=None)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
bool isCall() const
Return true if a CallInst is enclosed.
iterator find(const_arg_type_t< KeyT > Val)
const BasicBlock & getEntryBlock() const
void setAttributes(AttributeList PAL)
Set the parameter attributes of the call.
static bool runOnFunction(Function &F, bool PostInlining)
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
const Instruction * getFirstNonPHI() const
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
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.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
const Instruction & front() const
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)
void setCallingConv(CallingConv::ID CC)
Set the calling convention of the call.
FunctionPass class - This class is used to implement most global optimizations.
static FunctionType * get(Type *Result, ArrayRef< Type *> Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
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)
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
void setTailCall(bool isTC=true)
const Constant * stripPointerCasts() const
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs, and aliases.
unsigned getNumArgOperands() const
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.
InvokeInst * CreateInvoke(FunctionType *Ty, Value *Callee, BasicBlock *NormalDest, BasicBlock *UnwindDest, ArrayRef< Value *> Args, ArrayRef< OperandBundleDef > OpBundles, const Twine &Name="")
Create an invoke instruction.
void calculateWinCXXEHStateNumbers(const Function *ParentFn, WinEHFuncInfo &FuncInfo)
Analyze the IR in ParentFn and it's handlers to build WinEHFuncInfo, which describes the state number...
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
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.
pred_range predecessors(BasicBlock *BB)
void setPreservesCFG()
This function should be called by the pass, iff they do not:
BBTy * getParent() const
Get the basic block containing the call site.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static StringRef dropLLVMManglingEscape(StringRef Name)
If the given string begins with the GlobalValue name mangling escape character '\1', drop it.
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
bool doesNotAccessMemory() const
Determine if the call does not access memory.
const Comdat * getComdat() const
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
static IntegerType * getInt32Ty(LLVMContext &C)
void getOperandBundlesAsDefs(SmallVectorImpl< OperandBundleDef > &Defs) const
StringRef getName() const
Return a constant reference to the value's name.
bool doesNotThrow() const
Determine if the call cannot unwind.
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).
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value *> Args=None, const Twine &Name="", MDNode *FPMathTag=nullptr)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
INITIALIZE_PASS(WinEHStatePass, "x86-winehstate", "Insert stores for EH state numbers", false, false) bool WinEHStatePass
void initializeWinEHStatePassPass(PassRegistry &)
InstTy * Insert(InstTy *I, const Twine &Name="") const
Insert and return the specified instruction.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
X86_StdCall - stdcall is the calling conventions mostly used by the Win32 API.
bool isAsynchronousEHPersonality(EHPersonality Pers)
Returns true if this personality function catches asynchronous exceptions.
bool isEHPad() const
Return true if this basic block is an exception handling block.
LLVM Value Representation.
Constant * getPersonalityFn() const
Get the personality function associated with this function.
succ_range successors(Instruction *I)
static StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Value * CreateStructGEP(Type *Ty, Value *Ptr, unsigned Idx, const Twine &Name="")
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
StringRef - Represent a constant reference to a string, i.e.
AttributeList getAttributes() const
Get the parameter attributes of the call.
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...
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
an instruction to allocate memory on the stack