diff options
Diffstat (limited to 'llvm/lib/Target/X86/X86WinEHState.cpp')
-rw-r--r-- | llvm/lib/Target/X86/X86WinEHState.cpp | 79 |
1 files changed, 77 insertions, 2 deletions
diff --git a/llvm/lib/Target/X86/X86WinEHState.cpp b/llvm/lib/Target/X86/X86WinEHState.cpp index ce69ea72199..0c4aabab880 100644 --- a/llvm/lib/Target/X86/X86WinEHState.cpp +++ b/llvm/lib/Target/X86/X86WinEHState.cpp @@ -63,9 +63,12 @@ private: void linkExceptionRegistration(IRBuilder<> &Builder, Value *Handler); void unlinkExceptionRegistration(IRBuilder<> &Builder); void addCXXStateStores(Function &F, MachineModuleInfo &MMI); + void addSEHStateStores(Function &F, MachineModuleInfo &MMI); void addCXXStateStoresToFunclet(Value *ParentRegNode, WinEHFuncInfo &FuncInfo, Function &F, int BaseState); void insertStateNumberStore(Value *ParentRegNode, Instruction *IP, int State); + iplist<Instruction>::iterator + rewriteExceptionInfoIntrinsics(IntrinsicInst *Intrin); Value *emitEHLSDA(IRBuilder<> &Builder, Function *F); @@ -171,8 +174,10 @@ bool WinEHStatePass::runOnFunction(Function &F) { auto *MMIPtr = getAnalysisIfAvailable<MachineModuleInfo>(); assert(MMIPtr && "MachineModuleInfo should always be available"); MachineModuleInfo &MMI = *MMIPtr; - if (Personality == EHPersonality::MSVC_CXX) { - addCXXStateStores(F, MMI); + switch (Personality) { + default: llvm_unreachable("unexpected personality function"); + case EHPersonality::MSVC_CXX: addCXXStateStores(F, MMI); break; + case EHPersonality::MSVC_X86SEH: addSEHStateStores(F, MMI); break; } // Reset per-function state. @@ -472,6 +477,76 @@ void WinEHStatePass::addCXXStateStoresToFunclet(Value *ParentRegNode, } } +/// Assign every distinct landingpad a unique state number for SEH. Unlike C++ +/// EH, we can use this very simple algorithm while C++ EH cannot because catch +/// handlers aren't outlined and the runtime doesn't have to figure out which +/// catch handler frame to unwind to. +/// FIXME: __finally blocks are outlined, so this approach may break down there. +void WinEHStatePass::addSEHStateStores(Function &F, MachineModuleInfo &MMI) { + WinEHFuncInfo &FuncInfo = MMI.getWinEHFuncInfo(&F); + + // Iterate all the instructions and emit state number stores. + int CurState = 0; + for (BasicBlock &BB : F) { + for (auto I = BB.begin(), E = BB.end(); I != E; ++I) { + if (auto *CI = dyn_cast<CallInst>(I)) { + auto *Intrin = dyn_cast<IntrinsicInst>(CI); + if (Intrin) { + I = rewriteExceptionInfoIntrinsics(Intrin); + // Calls that "don't throw" are considered to be able to throw asynch + // exceptions, but intrinsics cannot. + continue; + } + insertStateNumberStore(RegNode, CI, -1); + } else if (auto *II = dyn_cast<InvokeInst>(I)) { + // Look up the state number of the landingpad this unwinds to. + LandingPadInst *LPI = II->getUnwindDest()->getLandingPadInst(); + auto InsertionPair = + FuncInfo.LandingPadStateMap.insert(std::make_pair(LPI, 0)); + auto Iter = InsertionPair.first; + int &State = Iter->second; + bool Inserted = InsertionPair.second; + if (Inserted) { + // Each action consumes a state number. + auto *EHActions = cast<IntrinsicInst>(LPI->getNextNode()); + SmallVector<std::unique_ptr<ActionHandler>, 4> ActionList; + parseEHActions(EHActions, ActionList); + assert(!ActionList.empty()); + CurState += ActionList.size(); + State += ActionList.size() - 1; + } + insertStateNumberStore(RegNode, II, State); + } + } + } +} + +/// Rewrite llvm.eh.exceptioncode and llvm.eh.exceptioninfo to memory loads in +/// IR. +iplist<Instruction>::iterator +WinEHStatePass::rewriteExceptionInfoIntrinsics(IntrinsicInst *Intrin) { + Intrinsic::ID ID = Intrin->getIntrinsicID(); + if (ID != Intrinsic::eh_exceptioncode && ID != Intrinsic::eh_exceptioninfo) + return Intrin; + + // RegNode->ExceptionPointers + IRBuilder<> Builder(Intrin); + Value *Ptrs = + Builder.CreateLoad(Builder.CreateStructGEP(RegNodeTy, RegNode, 1)); + Value *Res; + if (ID == Intrinsic::eh_exceptioncode) { + // Ptrs->ExceptionRecord->Code + Ptrs = Builder.CreateBitCast( + Ptrs, Builder.getInt32Ty()->getPointerTo()->getPointerTo()); + Value *Rec = Builder.CreateLoad(Ptrs); + Res = Builder.CreateLoad(Rec); + } else { + Res = Ptrs; + } + Intrin->replaceAllUsesWith(Res); + return Intrin->eraseFromParent(); +} + void WinEHStatePass::insertStateNumberStore(Value *ParentRegNode, Instruction *IP, int State) { IRBuilder<> Builder(IP); |