diff options
author | Andrew Kaylor <andrew.kaylor@intel.com> | 2015-05-11 19:41:19 +0000 |
---|---|---|
committer | Andrew Kaylor <andrew.kaylor@intel.com> | 2015-05-11 19:41:19 +0000 |
commit | 762a6bea1f28c5a9375b639ceedc4d1e378a7c88 (patch) | |
tree | f130d7ef77262e4e1b1d2cd7c0667b81e64bba4c /llvm/lib/CodeGen | |
parent | ba2d52291568ffaf5d99921ecba69acf62fa38cf (diff) | |
download | bcm5719-llvm-762a6bea1f28c5a9375b639ceedc4d1e378a7c88.tar.gz bcm5719-llvm-762a6bea1f28c5a9375b639ceedc4d1e378a7c88.zip |
[WinEH] Update exception numbering to give handlers their own base state.
Differential Revision: http://reviews.llvm.org/D9512
llvm-svn: 237014
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp | 14 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp | 89 |
2 files changed, 87 insertions, 16 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp b/llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp index b89ca011648..72aa4214f9a 100644 --- a/llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp @@ -299,6 +299,17 @@ void Win64Exception::emitCXXFrameHandler3Table(const MachineFunction *MF) { // The parent function and the catch handlers contribute to the 'ip2state' // table. + + // Include ip2state entries for the beginning of the main function and + // for catch handler functions. + if (F == ParentF) { + FuncInfo.IPToStateList.push_back(std::make_pair(LastLabel, -1)); + LastEHState = -1; + } else if (FuncInfo.HandlerBaseState.count(F)) { + FuncInfo.IPToStateList.push_back(std::make_pair(LastLabel, + FuncInfo.HandlerBaseState[F])); + LastEHState = FuncInfo.HandlerBaseState[F]; + } for (const auto &MBB : *MF) { for (const auto &MI : MBB) { if (!MI.isEHLabel()) { @@ -323,7 +334,8 @@ void Win64Exception::emitCXXFrameHandler3Table(const MachineFunction *MF) { assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] && "Inconsistent landing pad map!"); - if (SawPotentiallyThrowing) { + // FIXME: Should this be using FuncInfo.HandlerBaseState? + if (SawPotentiallyThrowing && LastEHState != -1) { FuncInfo.IPToStateList.push_back(std::make_pair(LastLabel, -1)); SawPotentiallyThrowing = false; LastEHState = -1; diff --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp index fc5ca3ec586..3248ac71aa2 100644 --- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -82,16 +82,18 @@ static ISD::NodeType getPreferredExtendForValue(const Value *V) { namespace { struct WinEHNumbering { - WinEHNumbering(WinEHFuncInfo &FuncInfo) : FuncInfo(FuncInfo), NextState(0) {} + WinEHNumbering(WinEHFuncInfo &FuncInfo) : FuncInfo(FuncInfo), + CurrentBaseState(-1), NextState(0) {} WinEHFuncInfo &FuncInfo; + int CurrentBaseState; int NextState; SmallVector<ActionHandler *, 4> HandlerStack; SmallPtrSet<const Function *, 4> VisitedHandlers; int currentEHNumber() const { - return HandlerStack.empty() ? -1 : HandlerStack.back()->getEHState(); + return HandlerStack.empty() ? CurrentBaseState : HandlerStack.back()->getEHState(); } void createUnwindMapEntry(int ToState, ActionHandler *AH); @@ -401,17 +403,33 @@ static void print_name(const Value *V) { void WinEHNumbering::processCallSite(ArrayRef<ActionHandler *> Actions, ImmutableCallSite CS) { + DEBUG(dbgs() << "processCallSite (EH state = " << currentEHNumber() + << ") for: "); + print_name(CS ? CS.getCalledValue() : nullptr); + DEBUG(dbgs() << '\n'); + + DEBUG(dbgs() << "HandlerStack: \n"); + for (int I = 0, E = HandlerStack.size(); I < E; ++I) { + DEBUG(dbgs() << " "); + print_name(HandlerStack[I]->getHandlerBlockOrFunc()); + DEBUG(dbgs() << '\n'); + } + DEBUG(dbgs() << "Actions: \n"); + for (int I = 0, E = Actions.size(); I < E; ++I) { + DEBUG(dbgs() << " "); + print_name(Actions[I]->getHandlerBlockOrFunc()); + DEBUG(dbgs() << '\n'); + } int FirstMismatch = 0; for (int E = std::min(HandlerStack.size(), Actions.size()); FirstMismatch < E; ++FirstMismatch) { if (HandlerStack[FirstMismatch]->getHandlerBlockOrFunc() != Actions[FirstMismatch]->getHandlerBlockOrFunc()) break; + // Delete any actions that are already represented on the handler stack. delete Actions[FirstMismatch]; } - bool EnteringScope = (int)Actions.size() > FirstMismatch; - // Don't recurse while we are looping over the handler stack. Instead, defer // the numbering of the catch handlers until we are done popping. SmallVector<CatchHandler *, 4> PoppedCatches; @@ -425,46 +443,75 @@ void WinEHNumbering::processCallSite(ArrayRef<ActionHandler *> Actions, HandlerStack.pop_back(); } - // We need to create a new state number if we are exiting a try scope and we - // will not push any more actions. int TryHigh = NextState - 1; - if (!EnteringScope && !PoppedCatches.empty()) { - createUnwindMapEntry(currentEHNumber(), nullptr); - ++NextState; - } - int LastTryLowIdx = 0; for (int I = 0, E = PoppedCatches.size(); I != E; ++I) { CatchHandler *CH = PoppedCatches[I]; + DEBUG(dbgs() << "Popped handler with state " << CH->getEHState() << "\n"); if (I + 1 == E || CH->getEHState() != PoppedCatches[I + 1]->getEHState()) { int TryLow = CH->getEHState(); auto Handlers = makeArrayRef(&PoppedCatches[LastTryLowIdx], I - LastTryLowIdx + 1); + DEBUG(dbgs() << "createTryBlockMapEntry(" << TryLow << ", " << TryHigh); + for (int J = 0; J < Handlers.size(); ++J) { + DEBUG(dbgs() << ", "); + print_name(Handlers[J]->getHandlerBlockOrFunc()); + } + DEBUG(dbgs() << ")\n"); createTryBlockMapEntry(TryLow, TryHigh, Handlers); LastTryLowIdx = I + 1; } } for (CatchHandler *CH : PoppedCatches) { - if (auto *F = dyn_cast<Function>(CH->getHandlerBlockOrFunc())) + if (auto *F = dyn_cast<Function>(CH->getHandlerBlockOrFunc())) { + DEBUG(dbgs() << "Assigning base state " << NextState << " to "); + print_name(F); + DEBUG(dbgs() << '\n'); + FuncInfo.HandlerBaseState[F] = NextState; + DEBUG(dbgs() << "createUnwindMapEntry(" << currentEHNumber() + << ", null)\n"); + createUnwindMapEntry(currentEHNumber(), nullptr); + ++NextState; calculateStateNumbers(*F); + } delete CH; } + // The handler functions may have pushed actions onto the handler stack + // that we expected to push here. Compare the handler stack to our + // actions again to check for that possibility. + if (HandlerStack.size() > FirstMismatch) { + for (int E = std::min(HandlerStack.size(), Actions.size()); + FirstMismatch < E; ++FirstMismatch) { + if (HandlerStack[FirstMismatch]->getHandlerBlockOrFunc() != + Actions[FirstMismatch]->getHandlerBlockOrFunc()) + break; + delete Actions[FirstMismatch]; + } + } + + DEBUG(dbgs() << "Pushing actions for CallSite: "); + print_name(CS ? CS.getCalledValue() : nullptr); + DEBUG(dbgs() << '\n'); + bool LastActionWasCatch = false; for (size_t I = FirstMismatch; I != Actions.size(); ++I) { // We can reuse eh states when pushing two catches for the same invoke. bool CurrActionIsCatch = isa<CatchHandler>(Actions[I]); // FIXME: Reenable this optimization! if (CurrActionIsCatch && LastActionWasCatch && false) { + DEBUG(dbgs() << "setEHState for handler to " << currentEHNumber() + << "\n"); Actions[I]->setEHState(currentEHNumber()); } else { + DEBUG(dbgs() << "createUnwindMapEntry(" << currentEHNumber() << ", "); + print_name(Actions[I]->getHandlerBlockOrFunc()); + DEBUG(dbgs() << ")\n"); createUnwindMapEntry(currentEHNumber(), Actions[I]); + DEBUG(dbgs() << "setEHState for handler to " << NextState << "\n"); Actions[I]->setEHState(NextState); NextState++; - DEBUG(dbgs() << "Creating unwind map entry for: ("); - print_name(Actions[I]->getHandlerBlockOrFunc()); - DEBUG(dbgs() << ", " << currentEHNumber() << ")\n"); } HandlerStack.push_back(Actions[I]); LastActionWasCatch = CurrActionIsCatch; @@ -480,6 +527,11 @@ void WinEHNumbering::calculateStateNumbers(const Function &F) { if (!I.second) return; // We've already visited this handler, don't renumber it. + int OldBaseState = CurrentBaseState; + if (FuncInfo.HandlerBaseState.count(&F)) { + CurrentBaseState = FuncInfo.HandlerBaseState[&F]; + } + DEBUG(dbgs() << "Calculating state numbers for: " << F.getName() << '\n'); SmallVector<ActionHandler *, 4> ActionList; for (const BasicBlock &BB : F) { @@ -498,12 +550,19 @@ void WinEHNumbering::calculateStateNumbers(const Function &F) { continue; assert(ActionsCall->getIntrinsicID() == Intrinsic::eh_actions); parseEHActions(ActionsCall, ActionList); + if (ActionList.empty()) + continue; processCallSite(ActionList, II); ActionList.clear(); FuncInfo.LandingPadStateMap[LPI] = currentEHNumber(); + DEBUG(dbgs() << "Assigning state " << currentEHNumber() + << " to landing pad at " << LPI->getParent()->getName() + << '\n'); } FuncInfo.CatchHandlerMaxState[&F] = NextState - 1; + + CurrentBaseState = OldBaseState; } /// clear - Clear out all the function-specific state. This returns this |