37 using namespace llvm::PatternMatch;
39 #define DEBUG_TYPE "winehstate"
48 bool runOnFunction(
Function &Fn)
override;
50 bool doInitialization(
Module &M)
override;
52 bool doFinalization(
Module &M)
override;
56 const char *getPassName()
const override {
57 return "Windows 32-bit x86 EH state insertion";
61 void emitExceptionRegistrationRecord(
Function *
F);
64 void unlinkExceptionRegistration(
IRBuilder<> &Builder);
78 Type *getEHLinkRegistrationType();
79 Type *getSEHRegistrationType();
80 Type *getCXXEHRegistrationType();
83 Module *TheModule =
nullptr;
100 Type *RegNodeTy =
nullptr;
103 int StateFieldIndex = ~0U;
114 bool WinEHStatePass::doInitialization(
Module &M) {
122 bool WinEHStatePass::doFinalization(
Module &M) {
123 assert(TheModule == &M);
125 EHLinkRegistrationTy =
nullptr;
126 CXXEHRegistrationTy =
nullptr;
127 SEHRegistrationTy =
nullptr;
128 FrameEscape =
nullptr;
129 FrameRecover =
nullptr;
130 FrameAddress =
nullptr;
134 void WinEHStatePass::getAnalysisUsage(
AnalysisUsage &AU)
const {
140 bool WinEHStatePass::runOnFunction(
Function &
F) {
145 if (WinEHParentName != F.
getName() && !WinEHParentName.
empty())
162 F.
addFnAttr(
"no-frame-pointer-elim",
"true");
164 emitExceptionRegistrationRecord(&F);
166 auto *MMIPtr = getAnalysisIfAvailable<MachineModuleInfo>();
167 assert(MMIPtr &&
"MachineModuleInfo should always be available");
169 switch (Personality) {
176 PersonalityFn =
nullptr;
188 Type *WinEHStatePass::getEHLinkRegistrationType() {
189 if (EHLinkRegistrationTy)
190 return EHLinkRegistrationTy;
197 EHLinkRegistrationTy->setBody(FieldTys,
false);
198 return EHLinkRegistrationTy;
207 Type *WinEHStatePass::getCXXEHRegistrationType() {
208 if (CXXEHRegistrationTy)
209 return CXXEHRegistrationTy;
213 getEHLinkRegistrationType(),
216 CXXEHRegistrationTy =
218 return CXXEHRegistrationTy;
229 Type *WinEHStatePass::getSEHRegistrationType() {
230 if (SEHRegistrationTy)
231 return SEHRegistrationTy;
236 getEHLinkRegistrationType(),
241 return SEHRegistrationTy;
248 void WinEHStatePass::emitExceptionRegistrationRecord(
Function *F) {
252 StringRef PersonalityName = PersonalityFn->getName();
256 RegNodeTy = getCXXEHRegistrationType();
257 RegNode = Builder.CreateAlloca(RegNodeTy);
259 Value *
SP = Builder.CreateCall(
261 Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
264 insertStateNumberStore(RegNode, Builder.GetInsertPoint(), -1);
266 Function *Trampoline = generateLSDAInEAXThunk(F);
267 Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 1);
268 linkExceptionRegistration(Builder, Trampoline);
272 bool UseStackGuard = (PersonalityName ==
"_except_handler4");
273 RegNodeTy = getSEHRegistrationType();
274 RegNode = Builder.CreateAlloca(RegNodeTy);
276 Value *SP = Builder.CreateCall(
278 Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
281 insertStateNumberStore(RegNode, Builder.GetInsertPoint(),
282 UseStackGuard ? -2 : -1);
284 Value *FI8 = Builder.CreateBitCast(F, Int8PtrType);
285 Value *LSDA = Builder.CreateCall(
288 LSDA = Builder.CreatePtrToInt(LSDA, Int32Ty);
293 TheModule->getOrInsertGlobal(
"__security_cookie", Int32Ty);
294 Value *Val = Builder.CreateLoad(Int32Ty, Cookie);
295 LSDA = Builder.CreateXor(LSDA, Val);
297 Builder.CreateStore(LSDA, Builder.CreateStructGEP(RegNodeTy, RegNode, 3));
298 Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 2);
299 linkExceptionRegistration(Builder, PersonalityFn);
307 if (!isa<ReturnInst>(T))
309 Builder.SetInsertPoint(T);
310 unlinkExceptionRegistration(Builder);
331 Type *ArgTys[5] = {Int8PtrType, Int8PtrType, Int8PtrType, Int8PtrType,
346 Value *LSDA = emitEHLSDA(Builder, ParentFunc);
347 Value *CastPersonality =
350 Value *Args[5] = {LSDA, AI++, AI++, AI++, AI++};
360 void WinEHStatePass::linkExceptionRegistration(
IRBuilder<> &Builder,
365 Type *LinkTy = getEHLinkRegistrationType();
378 void WinEHStatePass::unlinkExceptionRegistration(
IRBuilder<> &Builder) {
380 if (
auto *
GEP = dyn_cast<GetElementPtrInst>(Link)) {
381 GEP = cast<GetElementPtrInst>(
GEP->clone());
385 Type *LinkTy = getEHLinkRegistrationType();
399 addCXXStateStoresToFunclet(RegNode, FuncInfo, F, -1);
402 int RegNodeEscapeIndex = escapeRegNode(F);
410 int BaseState =
P.second;
416 FrameRecover, {FI8, ParentFP, Builder.
getInt32(RegNodeEscapeIndex)});
418 Builder.
CreateBitCast(RecoveredRegNode, RegNodeTy->getPointerTo(0));
419 addCXXStateStoresToFunclet(RecoveredRegNode, FuncInfo, *Handler, BaseState);
426 int WinEHStatePass::escapeRegNode(
Function &F) {
439 Args.
append(Ops.begin(), Ops.end());
452 return Args.
size() - 1;
455 void WinEHStatePass::addCXXStateStoresToFunclet(
Value *ParentRegNode,
461 if (
auto *CI = dyn_cast<CallInst>(&
I)) {
464 if (CI->doesNotThrow())
466 insertStateNumberStore(ParentRegNode, CI, BaseState);
467 }
else if (
auto *II = dyn_cast<InvokeInst>(&
I)) {
473 insertStateNumberStore(ParentRegNode, II, State);
490 int RegNodeEscapeIndex = escapeRegNode(F);
497 for (
auto I = BB.begin(), E = BB.end();
I != E; ++
I) {
498 if (
auto *CI = dyn_cast<CallInst>(
I)) {
505 insertStateNumberStore(RegNode, CI, -1);
506 }
else if (
auto *II = dyn_cast<InvokeInst>(
I)) {
511 auto Iter = InsertionPair.first;
512 int &State = Iter->second;
513 bool Inserted = InsertionPair.second;
516 auto *EHActions = cast<IntrinsicInst>(LPI->
getNextNode());
519 assert(!ActionList.empty());
520 CurState += ActionList.size();
521 State += ActionList.size() - 1;
524 for (
auto &Handler : ActionList) {
525 if (
auto *CH = dyn_cast<CatchHandler>(Handler.get())) {
526 auto *BA = cast<BlockAddress>(
CH->getHandlerBlockOrFunc());
529 assert(Pred->isLandingPad() &&
530 "WinEHPrepare failed to split block");
532 ExceptBlocks.
insert(BA->getBasicBlock());
536 insertStateNumberStore(RegNode, II, State);
550 void WinEHStatePass::insertStateNumberStore(
Value *ParentRegNode,
iplist< Instruction >::iterator eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing basic block and deletes it...
void push_back(const T &Elt)
LoadInst * CreateLoad(Value *Ptr, const char *Name)
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
Force argument to be passed in register.
A Module instance is used to store all the information related to an LLVM module. ...
WinEHFuncInfo & getWinEHFuncInfo(const Function *F)
Intrinsic::ID getIntrinsicID() const
getIntrinsicID - Return the intrinsic ID of this intrinsic.
CallInst - This class represents a function call, abstracting a target machine's calling convention...
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
InstTy * Insert(InstTy *I, const Twine &Name="") const
Insert and return the specified instruction.
static Constant * getNullValue(Type *Ty)
StringRef getName() const
Return a constant reference to the value's name.
iterator begin()
Instruction iterator methods.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
NodeTy * getNextNode()
Get the next node, or 0 for the list tail.
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
StructType - Class to represent struct types.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
void addFnAttr(Attribute::AttrKind N)
Add function attributes to this function.
int EHRegNodeEscapeIndex
localescape index of the 32-bit EH registration node.
FunctionType - Class to represent function types.
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
FunctionType::get - This static method is the primary way of constructing a FunctionType.
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=None)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
void addAttribute(unsigned i, Attribute::AttrKind attr)
addAttribute - adds the attribute to the list of attributes.
static Constant * getBitCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
DenseMap< const LandingPadInst *, int > LandingPadStateMap
LandingPadInst - The landingpad instruction holds all of the information necessary to generate correc...
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.
ReturnInst * CreateRet(Value *V)
Create a 'ret <val>' instruction.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool hasPersonalityFn() const
Get the personality function associated with this 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.
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.
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)
CallInst * CreateCall(Value *Callee, ArrayRef< Value * > Args=None, const Twine &Name="")
PointerType * getPointerTo(unsigned AddrSpace=0)
getPointerTo - Return a pointer to the current type.
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)
void calculateWinCXXEHStateNumbers(const Function *ParentFn, WinEHFuncInfo &FuncInfo)
Analyze the IR in ParentFn and it's handlers to build WinEHFuncInfo, which describes the state number...
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
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:
const BasicBlock & getEntryBlock() const
Value * CreateStructGEP(Type *Ty, Value *Ptr, unsigned Idx, const Twine &Name="")
LLVM_ATTRIBUTE_UNUSED_RESULT std::enable_if< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
static StringRef getRealLinkageName(StringRef Name)
If special LLVM prefix that is used to inform the asm printer to not emit usual symbol prefix before ...
static IntegerType * getInt32Ty(LLVMContext &C)
Constant * getPersonalityFn() const
TerminatorInst * getTerminator()
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Rename collisions when linking (static functions).
iterator_range< op_iterator > arg_operands()
arg_operands - iteration adapter for range-for loops.
StringRef getValueAsString() const
Return the attribute's value as a string.
LLVM Value Representation.
static StructType * create(LLVMContext &Context, StringRef Name)
StructType::create - This creates an identified struct.
StringRef - Represent a constant reference to a string, i.e.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, const Twine &N="", Module *M=nullptr)
FunctionPass * createX86WinEHStatePass()
createX86WinEHStatePass - Return an IR pass that inserts EH registration stack objects and explicit E...
DenseMap< const Function *, int > HandlerBaseState
bool isMSVCEHPersonality(EHPersonality Pers)
Returns true if this is an MSVC personality function.
IntrinsicInst - A useful wrapper class for inspecting calls to intrinsic functions.
void parseEHActions(const IntrinsicInst *II, SmallVectorImpl< std::unique_ptr< ActionHandler >> &Actions)
MachineModuleInfo - This class contains meta information specific to a module.
AllocaInst - an instruction to allocate memory on the stack.
bool empty() const
empty - Check if the string is empty.