diff options
Diffstat (limited to 'lib/Target/X86/X86WinEHState.cpp')
-rw-r--r-- | lib/Target/X86/X86WinEHState.cpp | 464 |
1 files changed, 402 insertions, 62 deletions
diff --git a/lib/Target/X86/X86WinEHState.cpp b/lib/Target/X86/X86WinEHState.cpp index dce94a9e9ef78..99387edef99a9 100644 --- a/lib/Target/X86/X86WinEHState.cpp +++ b/lib/Target/X86/X86WinEHState.cpp @@ -15,33 +15,32 @@ //===----------------------------------------------------------------------===// #include "X86.h" +#include "llvm/ADT/PostOrderIterator.h" #include "llvm/Analysis/CFG.h" #include "llvm/Analysis/EHPersonalities.h" #include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/WinEHFuncInfo.h" -#include "llvm/IR/Dominators.h" +#include "llvm/IR/CallSite.h" #include "llvm/IR/Function.h" -#include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/IRBuilder.h" #include "llvm/IR/Module.h" -#include "llvm/IR/PatternMatch.h" #include "llvm/Pass.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Transforms/Utils/BasicBlockUtils.h" -#include "llvm/Transforms/Utils/Cloning.h" -#include "llvm/Transforms/Utils/Local.h" +#include <deque> using namespace llvm; -using namespace llvm::PatternMatch; #define DEBUG_TYPE "winehstate" -namespace llvm { void initializeWinEHStatePassPass(PassRegistry &); } +namespace llvm { +void initializeWinEHStatePassPass(PassRegistry &); +} namespace { +const int OverdefinedState = INT_MIN; + class WinEHStatePass : public FunctionPass { public: static char ID; // Pass identification, replacement for typeid. @@ -68,12 +67,20 @@ private: void linkExceptionRegistration(IRBuilder<> &Builder, Function *Handler); void unlinkExceptionRegistration(IRBuilder<> &Builder); void addStateStores(Function &F, WinEHFuncInfo &FuncInfo); - void insertStateNumberStore(Value *ParentRegNode, Instruction *IP, int State); + void insertStateNumberStore(Instruction *IP, int State); Value *emitEHLSDA(IRBuilder<> &Builder, Function *F); Function *generateLSDAInEAXThunk(Function *ParentFunc); + bool isStateStoreNeeded(EHPersonality Personality, CallSite CS); + void rewriteSetJmpCallSite(IRBuilder<> &Builder, Function &F, CallSite CS, + Value *State); + int getBaseStateForBB(DenseMap<BasicBlock *, ColorVector> &BlockColors, + WinEHFuncInfo &FuncInfo, BasicBlock *BB); + int getStateForCallSite(DenseMap<BasicBlock *, ColorVector> &BlockColors, + WinEHFuncInfo &FuncInfo, CallSite CS); + // Module-level type getters. Type *getEHLinkRegistrationType(); Type *getSEHRegistrationType(); @@ -84,20 +91,23 @@ private: StructType *EHLinkRegistrationTy = nullptr; StructType *CXXEHRegistrationTy = nullptr; StructType *SEHRegistrationTy = nullptr; - Function *FrameRecover = nullptr; - Function *FrameAddress = nullptr; - Function *FrameEscape = nullptr; + Constant *SetJmp3 = nullptr; + Constant *CxxLongjmpUnwind = nullptr; // Per-function state EHPersonality Personality = EHPersonality::Unknown; Function *PersonalityFn = nullptr; + bool UseStackGuard = false; + int ParentBaseState; + Constant *SehLongjmpUnwind = nullptr; + Constant *Cookie = nullptr; /// The stack allocation containing all EH data, including the link in the /// fs:00 chain and the current state. AllocaInst *RegNode = nullptr; - /// Struct type of RegNode. Used for GEPing. - Type *RegNodeTy = nullptr; + // The allocation containing the EH security guard. + AllocaInst *EHGuardNode = nullptr; /// The index of the state field of RegNode. int StateFieldIndex = ~0U; @@ -116,9 +126,6 @@ INITIALIZE_PASS(WinEHStatePass, "x86-winehstate", bool WinEHStatePass::doInitialization(Module &M) { TheModule = &M; - FrameEscape = Intrinsic::getDeclaration(TheModule, Intrinsic::localescape); - FrameRecover = Intrinsic::getDeclaration(TheModule, Intrinsic::localrecover); - FrameAddress = Intrinsic::getDeclaration(TheModule, Intrinsic::frameaddress); return false; } @@ -128,9 +135,10 @@ bool WinEHStatePass::doFinalization(Module &M) { EHLinkRegistrationTy = nullptr; CXXEHRegistrationTy = nullptr; SEHRegistrationTy = nullptr; - FrameEscape = nullptr; - FrameRecover = nullptr; - FrameAddress = nullptr; + SetJmp3 = nullptr; + CxxLongjmpUnwind = nullptr; + SehLongjmpUnwind = nullptr; + Cookie = nullptr; return false; } @@ -164,6 +172,13 @@ bool WinEHStatePass::runOnFunction(Function &F) { if (!HasPads) return false; + Type *Int8PtrType = Type::getInt8PtrTy(TheModule->getContext()); + SetJmp3 = TheModule->getOrInsertFunction( + "_setjmp3", FunctionType::get( + Type::getInt32Ty(TheModule->getContext()), + {Int8PtrType, Type::getInt32Ty(TheModule->getContext())}, + /*isVarArg=*/true)); + // Disable frame pointer elimination in this function. // FIXME: Do the nested handlers need to keep the parent ebp in ebp, or can we // use an arbitrary register? @@ -182,6 +197,10 @@ bool WinEHStatePass::runOnFunction(Function &F) { // Reset per-function state. PersonalityFn = nullptr; Personality = EHPersonality::Unknown; + UseStackGuard = false; + RegNode = nullptr; + EHGuardNode = nullptr; + return true; } @@ -256,9 +275,14 @@ void WinEHStatePass::emitExceptionRegistrationRecord(Function *F) { assert(Personality == EHPersonality::MSVC_CXX || Personality == EHPersonality::MSVC_X86SEH); - StringRef PersonalityName = PersonalityFn->getName(); + // Struct type of RegNode. Used for GEPing. + Type *RegNodeTy; + IRBuilder<> Builder(&F->getEntryBlock(), F->getEntryBlock().begin()); Type *Int8PtrType = Builder.getInt8PtrTy(); + Type *Int32Ty = Builder.getInt32Ty(); + Type *VoidTy = Builder.getVoidTy(); + if (Personality == EHPersonality::MSVC_CXX) { RegNodeTy = getCXXEHRegistrationType(); RegNode = Builder.CreateAlloca(RegNodeTy); @@ -268,42 +292,71 @@ void WinEHStatePass::emitExceptionRegistrationRecord(Function *F) { Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0)); // TryLevel = -1 StateFieldIndex = 2; - insertStateNumberStore(RegNode, &*Builder.GetInsertPoint(), -1); + ParentBaseState = -1; + insertStateNumberStore(&*Builder.GetInsertPoint(), ParentBaseState); // Handler = __ehhandler$F Function *Trampoline = generateLSDAInEAXThunk(F); Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 1); linkExceptionRegistration(Builder, Trampoline); + + CxxLongjmpUnwind = TheModule->getOrInsertFunction( + "__CxxLongjmpUnwind", + FunctionType::get(VoidTy, Int8PtrType, /*isVarArg=*/false)); + cast<Function>(CxxLongjmpUnwind->stripPointerCasts()) + ->setCallingConv(CallingConv::X86_StdCall); } else if (Personality == EHPersonality::MSVC_X86SEH) { // If _except_handler4 is in use, some additional guard checks and prologue // stuff is required. - bool UseStackGuard = (PersonalityName == "_except_handler4"); + StringRef PersonalityName = PersonalityFn->getName(); + UseStackGuard = (PersonalityName == "_except_handler4"); + + // Allocate local structures. RegNodeTy = getSEHRegistrationType(); RegNode = Builder.CreateAlloca(RegNodeTy); + if (UseStackGuard) + EHGuardNode = Builder.CreateAlloca(Int32Ty); + // SavedESP = llvm.stacksave() Value *SP = Builder.CreateCall( Intrinsic::getDeclaration(TheModule, Intrinsic::stacksave), {}); Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0)); // TryLevel = -2 / -1 StateFieldIndex = 4; - insertStateNumberStore(RegNode, &*Builder.GetInsertPoint(), - UseStackGuard ? -2 : -1); + ParentBaseState = UseStackGuard ? -2 : -1; + insertStateNumberStore(&*Builder.GetInsertPoint(), ParentBaseState); // ScopeTable = llvm.x86.seh.lsda(F) - Value *FI8 = Builder.CreateBitCast(F, Int8PtrType); - Value *LSDA = Builder.CreateCall( - Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_lsda), FI8); - Type *Int32Ty = Type::getInt32Ty(TheModule->getContext()); + Value *LSDA = emitEHLSDA(Builder, F); LSDA = Builder.CreatePtrToInt(LSDA, Int32Ty); // If using _except_handler4, xor the address of the table with // __security_cookie. if (UseStackGuard) { - Value *Cookie = - TheModule->getOrInsertGlobal("__security_cookie", Int32Ty); - Value *Val = Builder.CreateLoad(Int32Ty, Cookie); + Cookie = TheModule->getOrInsertGlobal("__security_cookie", Int32Ty); + Value *Val = Builder.CreateLoad(Int32Ty, Cookie, "cookie"); LSDA = Builder.CreateXor(LSDA, Val); } Builder.CreateStore(LSDA, Builder.CreateStructGEP(RegNodeTy, RegNode, 3)); + + // If using _except_handler4, the EHGuard contains: FramePtr xor Cookie. + if (UseStackGuard) { + Value *Val = Builder.CreateLoad(Int32Ty, Cookie); + Value *FrameAddr = Builder.CreateCall( + Intrinsic::getDeclaration(TheModule, Intrinsic::frameaddress), + Builder.getInt32(0), "frameaddr"); + Value *FrameAddrI32 = Builder.CreatePtrToInt(FrameAddr, Int32Ty); + FrameAddrI32 = Builder.CreateXor(FrameAddrI32, Val); + Builder.CreateStore(FrameAddrI32, EHGuardNode); + } + + // Register the exception handler. Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 2); linkExceptionRegistration(Builder, PersonalityFn); + + SehLongjmpUnwind = TheModule->getOrInsertFunction( + UseStackGuard ? "_seh_longjmp_unwind4" : "_seh_longjmp_unwind", + FunctionType::get(Type::getVoidTy(TheModule->getContext()), Int8PtrType, + /*isVarArg=*/false)); + cast<Function>(SehLongjmpUnwind->stripPointerCasts()) + ->setCallingConv(CallingConv::X86_StdCall); } else { llvm_unreachable("unexpected personality function"); } @@ -398,15 +451,203 @@ void WinEHStatePass::unlinkExceptionRegistration(IRBuilder<> &Builder) { Builder.CreateStore(Next, FSZero); } +// Calls to setjmp(p) are lowered to _setjmp3(p, 0) by the frontend. +// The idea behind _setjmp3 is that it takes an optional number of personality +// specific parameters to indicate how to restore the personality-specific frame +// state when longjmp is initiated. Typically, the current TryLevel is saved. +void WinEHStatePass::rewriteSetJmpCallSite(IRBuilder<> &Builder, Function &F, + CallSite CS, Value *State) { + // Don't rewrite calls with a weird number of arguments. + if (CS.getNumArgOperands() != 2) + return; + + Instruction *Inst = CS.getInstruction(); + + SmallVector<OperandBundleDef, 1> OpBundles; + CS.getOperandBundlesAsDefs(OpBundles); + + SmallVector<Value *, 3> OptionalArgs; + if (Personality == EHPersonality::MSVC_CXX) { + OptionalArgs.push_back(CxxLongjmpUnwind); + OptionalArgs.push_back(State); + OptionalArgs.push_back(emitEHLSDA(Builder, &F)); + } else if (Personality == EHPersonality::MSVC_X86SEH) { + OptionalArgs.push_back(SehLongjmpUnwind); + OptionalArgs.push_back(State); + if (UseStackGuard) + OptionalArgs.push_back(Cookie); + } else { + llvm_unreachable("unhandled personality!"); + } + + SmallVector<Value *, 5> Args; + Args.push_back( + Builder.CreateBitCast(CS.getArgOperand(0), Builder.getInt8PtrTy())); + Args.push_back(Builder.getInt32(OptionalArgs.size())); + Args.append(OptionalArgs.begin(), OptionalArgs.end()); + + CallSite NewCS; + if (CS.isCall()) { + auto *CI = cast<CallInst>(Inst); + CallInst *NewCI = Builder.CreateCall(SetJmp3, Args, OpBundles); + NewCI->setTailCallKind(CI->getTailCallKind()); + NewCS = NewCI; + } else { + auto *II = cast<InvokeInst>(Inst); + NewCS = Builder.CreateInvoke( + SetJmp3, II->getNormalDest(), II->getUnwindDest(), Args, OpBundles); + } + NewCS.setCallingConv(CS.getCallingConv()); + NewCS.setAttributes(CS.getAttributes()); + NewCS->setDebugLoc(CS->getDebugLoc()); + + Instruction *NewInst = NewCS.getInstruction(); + NewInst->takeName(Inst); + Inst->replaceAllUsesWith(NewInst); + Inst->eraseFromParent(); +} + +// Figure out what state we should assign calls in this block. +int WinEHStatePass::getBaseStateForBB( + DenseMap<BasicBlock *, ColorVector> &BlockColors, WinEHFuncInfo &FuncInfo, + BasicBlock *BB) { + int BaseState = ParentBaseState; + auto &BBColors = BlockColors[BB]; + + assert(BBColors.size() == 1 && "multi-color BB not removed by preparation"); + BasicBlock *FuncletEntryBB = BBColors.front(); + if (auto *FuncletPad = + dyn_cast<FuncletPadInst>(FuncletEntryBB->getFirstNonPHI())) { + auto BaseStateI = FuncInfo.FuncletBaseStateMap.find(FuncletPad); + if (BaseStateI != FuncInfo.FuncletBaseStateMap.end()) + BaseState = BaseStateI->second; + } + + return BaseState; +} + +// Calculate the state a call-site is in. +int WinEHStatePass::getStateForCallSite( + DenseMap<BasicBlock *, ColorVector> &BlockColors, WinEHFuncInfo &FuncInfo, + CallSite CS) { + if (auto *II = dyn_cast<InvokeInst>(CS.getInstruction())) { + // Look up the state number of the EH pad this unwinds to. + assert(FuncInfo.InvokeStateMap.count(II) && "invoke has no state!"); + return FuncInfo.InvokeStateMap[II]; + } + // Possibly throwing call instructions have no actions to take after + // an unwind. Ensure they are in the -1 state. + return getBaseStateForBB(BlockColors, FuncInfo, CS.getParent()); +} + +// Calculate the intersection of all the FinalStates for a BasicBlock's +// predecessors. +static int getPredState(DenseMap<BasicBlock *, int> &FinalStates, Function &F, + int ParentBaseState, BasicBlock *BB) { + // The entry block has no predecessors but we know that the prologue always + // sets us up with a fixed state. + if (&F.getEntryBlock() == BB) + return ParentBaseState; + + // This is an EH Pad, conservatively report this basic block as overdefined. + if (BB->isEHPad()) + return OverdefinedState; + + int CommonState = OverdefinedState; + for (BasicBlock *PredBB : predecessors(BB)) { + // We didn't manage to get a state for one of these predecessors, + // conservatively report this basic block as overdefined. + auto PredEndState = FinalStates.find(PredBB); + if (PredEndState == FinalStates.end()) + return OverdefinedState; + + // This code is reachable via exceptional control flow, + // conservatively report this basic block as overdefined. + if (isa<CatchReturnInst>(PredBB->getTerminator())) + return OverdefinedState; + + int PredState = PredEndState->second; + assert(PredState != OverdefinedState && + "overdefined BBs shouldn't be in FinalStates"); + if (CommonState == OverdefinedState) + CommonState = PredState; + + // At least two predecessors have different FinalStates, + // conservatively report this basic block as overdefined. + if (CommonState != PredState) + return OverdefinedState; + } + + return CommonState; +} + +// Calculate the intersection of all the InitialStates for a BasicBlock's +// successors. +static int getSuccState(DenseMap<BasicBlock *, int> &InitialStates, Function &F, + int ParentBaseState, BasicBlock *BB) { + // This block rejoins normal control flow, + // conservatively report this basic block as overdefined. + if (isa<CatchReturnInst>(BB->getTerminator())) + return OverdefinedState; + + int CommonState = OverdefinedState; + for (BasicBlock *SuccBB : successors(BB)) { + // We didn't manage to get a state for one of these predecessors, + // conservatively report this basic block as overdefined. + auto SuccStartState = InitialStates.find(SuccBB); + if (SuccStartState == InitialStates.end()) + return OverdefinedState; + + // This is an EH Pad, conservatively report this basic block as overdefined. + if (SuccBB->isEHPad()) + return OverdefinedState; + + int SuccState = SuccStartState->second; + assert(SuccState != OverdefinedState && + "overdefined BBs shouldn't be in FinalStates"); + if (CommonState == OverdefinedState) + CommonState = SuccState; + + // At least two successors have different InitialStates, + // conservatively report this basic block as overdefined. + if (CommonState != SuccState) + return OverdefinedState; + } + + return CommonState; +} + +bool WinEHStatePass::isStateStoreNeeded(EHPersonality Personality, + CallSite CS) { + if (!CS) + return false; + + // If the function touches memory, it needs a state store. + if (isAsynchronousEHPersonality(Personality)) + return !CS.doesNotAccessMemory(); + + // If the function throws, it needs a state store. + return !CS.doesNotThrow(); +} + void WinEHStatePass::addStateStores(Function &F, WinEHFuncInfo &FuncInfo) { // Mark the registration node. The backend needs to know which alloca it is so // that it can recover the original frame pointer. - IRBuilder<> Builder(RegNode->getParent(), std::next(RegNode->getIterator())); + IRBuilder<> Builder(RegNode->getNextNode()); Value *RegNodeI8 = Builder.CreateBitCast(RegNode, Builder.getInt8PtrTy()); Builder.CreateCall( Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_ehregnode), {RegNodeI8}); + if (EHGuardNode) { + IRBuilder<> Builder(EHGuardNode->getNextNode()); + Value *EHGuardNodeI8 = + Builder.CreateBitCast(EHGuardNode, Builder.getInt8PtrTy()); + Builder.CreateCall( + Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_ehguard), + {EHGuardNodeI8}); + } + // Calculate state numbers. if (isAsynchronousEHPersonality(Personality)) calculateSEHStateNumbers(&F, FuncInfo); @@ -415,42 +656,141 @@ void WinEHStatePass::addStateStores(Function &F, WinEHFuncInfo &FuncInfo) { // Iterate all the instructions and emit state number stores. DenseMap<BasicBlock *, ColorVector> BlockColors = colorEHFunclets(F); - for (BasicBlock &BB : F) { - // Figure out what state we should assign calls in this block. - int BaseState = -1; - auto &BBColors = BlockColors[&BB]; + ReversePostOrderTraversal<Function *> RPOT(&F); + + // InitialStates yields the state of the first call-site for a BasicBlock. + DenseMap<BasicBlock *, int> InitialStates; + // FinalStates yields the state of the last call-site for a BasicBlock. + DenseMap<BasicBlock *, int> FinalStates; + // Worklist used to revisit BasicBlocks with indeterminate + // Initial/Final-States. + std::deque<BasicBlock *> Worklist; + // Fill in InitialStates and FinalStates for BasicBlocks with call-sites. + for (BasicBlock *BB : RPOT) { + int InitialState = OverdefinedState; + int FinalState; + if (&F.getEntryBlock() == BB) + InitialState = FinalState = ParentBaseState; + for (Instruction &I : *BB) { + CallSite CS(&I); + if (!isStateStoreNeeded(Personality, CS)) + continue; + + int State = getStateForCallSite(BlockColors, FuncInfo, CS); + if (InitialState == OverdefinedState) + InitialState = State; + FinalState = State; + } + // No call-sites in this basic block? That's OK, we will come back to these + // in a later pass. + if (InitialState == OverdefinedState) { + Worklist.push_back(BB); + continue; + } + DEBUG(dbgs() << "X86WinEHState: " << BB->getName() + << " InitialState=" << InitialState << '\n'); + DEBUG(dbgs() << "X86WinEHState: " << BB->getName() + << " FinalState=" << FinalState << '\n'); + InitialStates.insert({BB, InitialState}); + FinalStates.insert({BB, FinalState}); + } - assert(BBColors.size() == 1 && - "multi-color BB not removed by preparation"); + // Try to fill-in InitialStates and FinalStates which have no call-sites. + while (!Worklist.empty()) { + BasicBlock *BB = Worklist.front(); + Worklist.pop_front(); + // This BasicBlock has already been figured out, nothing more we can do. + if (InitialStates.count(BB) != 0) + continue; + + int PredState = getPredState(FinalStates, F, ParentBaseState, BB); + if (PredState == OverdefinedState) + continue; + + // We successfully inferred this BasicBlock's state via it's predecessors; + // enqueue it's successors to see if we can infer their states. + InitialStates.insert({BB, PredState}); + FinalStates.insert({BB, PredState}); + for (BasicBlock *SuccBB : successors(BB)) + Worklist.push_back(SuccBB); + } + + // Try to hoist stores from successors. + for (BasicBlock *BB : RPOT) { + int SuccState = getSuccState(InitialStates, F, ParentBaseState, BB); + if (SuccState == OverdefinedState) + continue; + + // Update our FinalState to reflect the common InitialState of our + // successors. + FinalStates.insert({BB, SuccState}); + } + + // Finally, insert state stores before call-sites which transition us to a new + // state. + for (BasicBlock *BB : RPOT) { + auto &BBColors = BlockColors[BB]; BasicBlock *FuncletEntryBB = BBColors.front(); - if (auto *FuncletPad = - dyn_cast<FuncletPadInst>(FuncletEntryBB->getFirstNonPHI())) { - auto BaseStateI = FuncInfo.FuncletBaseStateMap.find(FuncletPad); - if (BaseStateI != FuncInfo.FuncletBaseStateMap.end()) - BaseState = BaseStateI->second; + if (isa<CleanupPadInst>(FuncletEntryBB->getFirstNonPHI())) + continue; + + int PrevState = getPredState(FinalStates, F, ParentBaseState, BB); + DEBUG(dbgs() << "X86WinEHState: " << BB->getName() + << " PrevState=" << PrevState << '\n'); + + for (Instruction &I : *BB) { + CallSite CS(&I); + if (!isStateStoreNeeded(Personality, CS)) + continue; + + int State = getStateForCallSite(BlockColors, FuncInfo, CS); + if (State != PrevState) + insertStateNumberStore(&I, State); + PrevState = State; } - for (Instruction &I : BB) { - if (auto *CI = dyn_cast<CallInst>(&I)) { - // Possibly throwing call instructions have no actions to take after - // an unwind. Ensure they are in the -1 state. - if (CI->doesNotThrow()) - continue; - insertStateNumberStore(RegNode, CI, BaseState); - } else if (auto *II = dyn_cast<InvokeInst>(&I)) { - // Look up the state number of the landingpad this unwinds to. - assert(FuncInfo.InvokeStateMap.count(II) && "invoke has no state!"); - int State = FuncInfo.InvokeStateMap[II]; - insertStateNumberStore(RegNode, II, State); - } + // We might have hoisted a state store into this block, emit it now. + auto EndState = FinalStates.find(BB); + if (EndState != FinalStates.end()) + if (EndState->second != PrevState) + insertStateNumberStore(BB->getTerminator(), EndState->second); + } + + SmallVector<CallSite, 1> SetJmp3CallSites; + for (BasicBlock *BB : RPOT) { + for (Instruction &I : *BB) { + CallSite CS(&I); + if (!CS) + continue; + if (CS.getCalledValue()->stripPointerCasts() != + SetJmp3->stripPointerCasts()) + continue; + + SetJmp3CallSites.push_back(CS); + } + } + + for (CallSite CS : SetJmp3CallSites) { + auto &BBColors = BlockColors[CS->getParent()]; + BasicBlock *FuncletEntryBB = BBColors.front(); + bool InCleanup = isa<CleanupPadInst>(FuncletEntryBB->getFirstNonPHI()); + + IRBuilder<> Builder(CS.getInstruction()); + Value *State; + if (InCleanup) { + Value *StateField = + Builder.CreateStructGEP(nullptr, RegNode, StateFieldIndex); + State = Builder.CreateLoad(StateField); + } else { + State = Builder.getInt32(getStateForCallSite(BlockColors, FuncInfo, CS)); } + rewriteSetJmpCallSite(Builder, F, CS, State); } } -void WinEHStatePass::insertStateNumberStore(Value *ParentRegNode, - Instruction *IP, int State) { +void WinEHStatePass::insertStateNumberStore(Instruction *IP, int State) { IRBuilder<> Builder(IP); Value *StateField = - Builder.CreateStructGEP(RegNodeTy, ParentRegNode, StateFieldIndex); + Builder.CreateStructGEP(nullptr, RegNode, StateFieldIndex); Builder.CreateStore(Builder.getInt32(State), StateField); } |