27 #include "llvm/IR/IntrinsicsX86.h" 35 #define DEBUG_TYPE "winehstate" 38 const int OverdefinedState = INT_MIN;
48 bool doInitialization(
Module &M)
override;
50 bool doFinalization(
Module &M)
override;
55 return "Windows 32-bit x86 EH state insertion";
59 void emitExceptionRegistrationRecord(
Function *
F);
64 void insertStateNumberStore(
Instruction *IP,
int State);
79 Type *getEHLinkRegistrationType();
80 Type *getSEHRegistrationType();
81 Type *getCXXEHRegistrationType();
84 Module *TheModule =
nullptr;
94 bool UseStackGuard =
false;
95 int ParentBaseState = 0;
107 int StateFieldIndex = ~0U;
119 "Insert stores for EH state numbers",
false,
false)
121 bool WinEHStatePass::doInitialization(
Module &M) {
126 bool WinEHStatePass::doFinalization(
Module &M) {
129 EHLinkRegistrationTy =
nullptr;
130 CXXEHRegistrationTy =
nullptr;
131 SEHRegistrationTy =
nullptr;
133 CxxLongjmpUnwind =
nullptr;
134 SehLongjmpUnwind =
nullptr;
139 void WinEHStatePass::getAnalysisUsage(
AnalysisUsage &AU)
const {
149 if (
F.hasAvailableExternallyLinkage())
153 if (!
F.hasPersonalityFn())
156 dyn_cast<Function>(
F.getPersonalityFn()->stripPointerCasts());
165 bool HasPads =
false;
176 SetJmp3 = TheModule->getOrInsertFunction(
182 emitExceptionRegistrationRecord(&
F);
190 addStateStores(
F, FuncInfo);
193 PersonalityFn =
nullptr;
195 UseStackGuard =
false;
197 EHGuardNode =
nullptr;
209 Type *WinEHStatePass::getEHLinkRegistrationType() {
210 if (EHLinkRegistrationTy)
211 return EHLinkRegistrationTy;
218 EHLinkRegistrationTy->setBody(FieldTys,
false);
219 return EHLinkRegistrationTy;
228 Type *WinEHStatePass::getCXXEHRegistrationType() {
229 if (CXXEHRegistrationTy)
230 return CXXEHRegistrationTy;
234 getEHLinkRegistrationType(),
237 CXXEHRegistrationTy =
239 return CXXEHRegistrationTy;
250 Type *WinEHStatePass::getSEHRegistrationType() {
251 if (SEHRegistrationTy)
252 return SEHRegistrationTy;
257 getEHLinkRegistrationType(),
262 return SEHRegistrationTy;
269 void WinEHStatePass::emitExceptionRegistrationRecord(
Function *
F) {
282 RegNodeTy = getCXXEHRegistrationType();
283 RegNode =
Builder.CreateAlloca(RegNodeTy);
287 Builder.CreateStore(SP,
Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
290 ParentBaseState = -1;
291 insertStateNumberStore(&*
Builder.GetInsertPoint(), ParentBaseState);
293 Function *Trampoline = generateLSDAInEAXThunk(
F);
294 Link =
Builder.CreateStructGEP(RegNodeTy, RegNode, 1);
295 linkExceptionRegistration(
Builder, Trampoline);
297 CxxLongjmpUnwind = TheModule->getOrInsertFunction(
298 "__CxxLongjmpUnwind",
300 cast<Function>(CxxLongjmpUnwind.getCallee()->stripPointerCasts())
305 StringRef PersonalityName = PersonalityFn->getName();
306 UseStackGuard = (PersonalityName ==
"_except_handler4");
309 RegNodeTy = getSEHRegistrationType();
310 RegNode =
Builder.CreateAlloca(RegNodeTy);
317 Builder.CreateStore(SP,
Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
320 ParentBaseState = UseStackGuard ? -2 : -1;
321 insertStateNumberStore(&*
Builder.GetInsertPoint(), ParentBaseState);
328 Cookie = TheModule->getOrInsertGlobal(
"__security_cookie",
Int32Ty);
330 LSDA =
Builder.CreateXor(LSDA, Val);
332 Builder.CreateStore(LSDA,
Builder.CreateStructGEP(RegNodeTy, RegNode, 3));
339 TheModule, Intrinsic::frameaddress,
341 TheModule->getDataLayout().getAllocaAddrSpace())),
342 Builder.getInt32(0),
"frameaddr");
344 FrameAddrI32 =
Builder.CreateXor(FrameAddrI32, Val);
345 Builder.CreateStore(FrameAddrI32, EHGuardNode);
349 Link =
Builder.CreateStructGEP(RegNodeTy, RegNode, 2);
350 linkExceptionRegistration(
Builder, PersonalityFn);
352 SehLongjmpUnwind = TheModule->getOrInsertFunction(
353 UseStackGuard ?
"_seh_longjmp_unwind4" :
"_seh_longjmp_unwind",
356 cast<Function>(SehLongjmpUnwind.getCallee()->stripPointerCasts())
365 if (!isa<ReturnInst>(
T))
368 unlinkExceptionRegistration(
Builder);
389 Type *ArgTys[5] = {Int8PtrType, Int8PtrType, Int8PtrType, Int8PtrType,
407 Value *CastPersonality =
410 Value *
Args[5] = {LSDA, &*AI++, &*AI++, &*AI++, &*AI++};
413 Call->setTailCall(
true);
415 Call->addParamAttr(0, Attribute::InReg);
425 Type *LinkTy = getEHLinkRegistrationType();
440 if (
auto *
GEP = dyn_cast<GetElementPtrInst>(
Link)) {
441 GEP = cast<GetElementPtrInst>(
GEP->clone());
445 Type *LinkTy = getEHLinkRegistrationType();
451 Builder.CreateStore(Next, FSZero);
461 if (
Call.getNumArgOperands() != 2)
465 Call.getOperandBundlesAsDefs(OpBundles);
469 OptionalArgs.
push_back(CxxLongjmpUnwind.getCallee());
473 OptionalArgs.
push_back(SehLongjmpUnwind.getCallee());
488 if (
auto *CI = dyn_cast<CallInst>(&Call)) {
493 auto *II = cast<InvokeInst>(&Call);
494 NewCall =
Builder.CreateInvoke(
495 SetJmp3, II->getNormalDest(), II->getUnwindDest(),
Args, OpBundles);
502 Call.replaceAllUsesWith(NewCall);
503 Call.eraseFromParent();
507 int WinEHStatePass::getBaseStateForBB(
510 int BaseState = ParentBaseState;
511 auto &BBColors = BlockColors[BB];
513 assert(BBColors.size() == 1 &&
"multi-color BB not removed by preparation");
515 if (
auto *FuncletPad =
516 dyn_cast<FuncletPadInst>(FuncletEntryBB->getFirstNonPHI())) {
519 BaseState = BaseStateI->second;
526 int WinEHStatePass::getStateForCall(
529 if (
auto *II = dyn_cast<InvokeInst>(&Call)) {
536 return getBaseStateForBB(BlockColors, FuncInfo,
Call.getParent());
545 if (&
F.getEntryBlock() == BB)
546 return ParentBaseState;
550 return OverdefinedState;
552 int CommonState = OverdefinedState;
556 auto PredEndState = FinalStates.
find(PredBB);
557 if (PredEndState == FinalStates.
end())
558 return OverdefinedState;
562 if (isa<CatchReturnInst>(PredBB->getTerminator()))
563 return OverdefinedState;
565 int PredState = PredEndState->second;
566 assert(PredState != OverdefinedState &&
567 "overdefined BBs shouldn't be in FinalStates");
568 if (CommonState == OverdefinedState)
569 CommonState = PredState;
573 if (CommonState != PredState)
574 return OverdefinedState;
587 return OverdefinedState;
589 int CommonState = OverdefinedState;
593 auto SuccStartState = InitialStates.
find(SuccBB);
594 if (SuccStartState == InitialStates.
end())
595 return OverdefinedState;
598 if (SuccBB->isEHPad())
599 return OverdefinedState;
601 int SuccState = SuccStartState->second;
602 assert(SuccState != OverdefinedState &&
603 "overdefined BBs shouldn't be in FinalStates");
604 if (CommonState == OverdefinedState)
605 CommonState = SuccState;
609 if (CommonState != SuccState)
610 return OverdefinedState;
616 bool WinEHStatePass::isStateStoreNeeded(
EHPersonality Personality,
620 return !
Call.doesNotAccessMemory();
623 return !
Call.doesNotThrow();
637 Value *EHGuardNodeI8 =
660 std::deque<BasicBlock *> Worklist;
663 int InitialState = OverdefinedState;
665 if (&
F.getEntryBlock() == BB)
666 InitialState = FinalState = ParentBaseState;
668 auto *
Call = dyn_cast<CallBase>(&
I);
669 if (!Call || !isStateStoreNeeded(Personality, *Call))
672 int State = getStateForCall(BlockColors, FuncInfo, *Call);
673 if (InitialState == OverdefinedState)
674 InitialState = State;
679 if (InitialState == OverdefinedState) {
680 Worklist.push_back(BB);
684 <<
" InitialState=" << InitialState <<
'\n');
686 <<
" FinalState=" << FinalState <<
'\n');
687 InitialStates.
insert({BB, InitialState});
688 FinalStates.
insert({BB, FinalState});
692 while (!Worklist.empty()) {
694 Worklist.pop_front();
696 if (InitialStates.
count(BB) != 0)
699 int PredState =
getPredState(FinalStates,
F, ParentBaseState, BB);
700 if (PredState == OverdefinedState)
705 InitialStates.
insert({BB, PredState});
706 FinalStates.
insert({BB, PredState});
708 Worklist.push_back(SuccBB);
713 int SuccState =
getSuccState(InitialStates,
F, ParentBaseState, BB);
714 if (SuccState == OverdefinedState)
719 FinalStates.
insert({BB, SuccState});
725 auto &BBColors = BlockColors[BB];
730 int PrevState =
getPredState(FinalStates,
F, ParentBaseState, BB);
732 <<
" PrevState=" << PrevState <<
'\n');
735 auto *
Call = dyn_cast<CallBase>(&
I);
736 if (!Call || !isStateStoreNeeded(Personality, *Call))
739 int State = getStateForCall(BlockColors, FuncInfo, *Call);
740 if (State != PrevState)
741 insertStateNumberStore(&
I, State);
746 auto EndState = FinalStates.
find(BB);
747 if (EndState != FinalStates.
end())
748 if (EndState->second != PrevState)
749 insertStateNumberStore(BB->getTerminator(), EndState->second);
755 auto *
Call = dyn_cast<CallBase>(&
I);
758 if (
Call->getCalledOperand()->stripPointerCasts() !=
759 SetJmp3.getCallee()->stripPointerCasts())
766 for (
CallBase *Call : SetJmp3Calls) {
767 auto &BBColors = BlockColors[
Call->getParent()];
769 bool InCleanup = isa<CleanupPadInst>(FuncletEntryBB->
getFirstNonPHI());
774 Value *StateField =
Builder.CreateStructGEP(RegNode->getAllocatedType(),
775 RegNode, StateFieldIndex);
778 State =
Builder.getInt32(getStateForCall(BlockColors, FuncInfo, *Call));
780 rewriteSetJmpCall(
Builder,
F, *Call, State);
784 void WinEHStatePass::insertStateNumberStore(
Instruction *IP,
int State) {
786 Value *StateField =
Builder.CreateStructGEP(RegNode->getAllocatedType(),
787 RegNode, StateFieldIndex);
This class represents lattice values for constants.
A Module instance is used to store all the information related to an LLVM module.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
void push_back(const T &Elt)
DenseMap< const FuncletPadInst *, int > FuncletBaseStateMap
This class represents a function call, abstracting a target machine's calling convention.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
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.
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.
Class to represent function types.
void setComdat(Comdat *C)
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
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.
void takeName(Value *V)
Transfer the name from V to this value.
iterator find(const_arg_type_t< KeyT > Val)
X86_StdCall - stdcall is the calling conventions mostly used by the Win32 API.
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.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this 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.
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)
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)
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void calculateWinCXXEHStateNumbers(const Function *ParentFn, WinEHFuncInfo &FuncInfo)
Analyze the IR in ParentFn and it's handlers to build WinEHFuncInfo, which describes the state number...
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.
pred_range predecessors(BasicBlock *BB)
void setPreservesCFG()
This function should be called by the pass, iff they do not:
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',...
const Comdat * getComdat() const
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
static IntegerType * getInt32Ty(LLVMContext &C)
StringRef getName() const
Return a constant reference to the value's name.
void setAttributes(AttributeList A)
Set the parameter attributes for this call.
Rename collisions when linking (static functions).
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
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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.
succ_range successors(Instruction *I)
static StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
StringRef - Represent a constant reference to a string, i.e.
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