diff options
author | Reid Kleckner <reid@kleckner.net> | 2015-06-09 21:42:19 +0000 |
---|---|---|
committer | Reid Kleckner <reid@kleckner.net> | 2015-06-09 21:42:19 +0000 |
commit | f12c030f4879e2bf2caca21976f5de9ba8c48bdd (patch) | |
tree | 21b2e4664e29273f3905ed81222e87a61abeec1c /llvm/lib/Target/X86/X86WinEHState.cpp | |
parent | cf90acc1041fea47db7d862a21b24534b5df21b0 (diff) | |
download | bcm5719-llvm-f12c030f4879e2bf2caca21976f5de9ba8c48bdd.tar.gz bcm5719-llvm-f12c030f4879e2bf2caca21976f5de9ba8c48bdd.zip |
[WinEH] Add 32-bit SEH state table emission prototype
This gets all the handler info through to the asm printer and we can
look at the .xdata tables now. I've convinced one small catch-all test
case to work, but other than that, it would be a stretch to say this is
functional.
The state numbering algorithm avoids doing any scope reconstruction as
we do for C++ to simplify the implementation.
llvm-svn: 239433
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); |