summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
authorAndrew Kaylor <andrew.kaylor@intel.com>2015-05-11 19:41:19 +0000
committerAndrew Kaylor <andrew.kaylor@intel.com>2015-05-11 19:41:19 +0000
commit762a6bea1f28c5a9375b639ceedc4d1e378a7c88 (patch)
treef130d7ef77262e4e1b1d2cd7c0667b81e64bba4c /llvm/lib/CodeGen
parentba2d52291568ffaf5d99921ecba69acf62fa38cf (diff)
downloadbcm5719-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.cpp14
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp89
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
OpenPOWER on IntegriCloud