diff options
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp')
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp | 135 |
1 files changed, 105 insertions, 30 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp index c00b11893bf..e2235fbc044 100644 --- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -88,6 +88,7 @@ struct WinEHNumbering { int NextState; SmallVector<ActionHandler *, 4> HandlerStack; + SmallPtrSet<const Function *, 4> VisitedHandlers; int currentEHNumber() const { return HandlerStack.empty() ? -1 : HandlerStack.back()->getEHState(); @@ -96,7 +97,9 @@ struct WinEHNumbering { void parseEHActions(const IntrinsicInst *II, SmallVectorImpl<ActionHandler *> &Actions); void createUnwindMapEntry(int ToState, ActionHandler *AH); - void proccessCallSite(ArrayRef<ActionHandler *> Actions, ImmutableCallSite CS); + void createTryBlockMapEntry(int TryLow, int TryHigh, + ArrayRef<CatchHandler *> Handlers); + void processCallSite(ArrayRef<ActionHandler *> Actions, ImmutableCallSite CS); void calculateStateNumbers(const Function &F); }; } @@ -276,8 +279,12 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf, MBBMap[Invoke->getSuccessor(1)]->setIsLandingPad(); // Calculate EH numbers for WinEH. - if (fn.getFnAttribute("wineh-parent").getValueAsString() == fn.getName()) - WinEHNumbering(MMI.getWinEHFuncInfo(&fn)).calculateStateNumbers(fn); + if (fn.getFnAttribute("wineh-parent").getValueAsString() == fn.getName()) { + WinEHNumbering Num(MMI.getWinEHFuncInfo(&fn)); + Num.calculateStateNumbers(fn); + // Pop everything on the handler stack. + Num.processCallSite(None, ImmutableCallSite()); + } } void WinEHNumbering::parseEHActions(const IntrinsicInst *II, @@ -309,13 +316,42 @@ void WinEHNumbering::parseEHActions(const IntrinsicInst *II, void WinEHNumbering::createUnwindMapEntry(int ToState, ActionHandler *AH) { WinEHUnwindMapEntry UME; UME.ToState = ToState; - if (auto *CH = dyn_cast<CleanupHandler>(AH)) + if (auto *CH = dyn_cast_or_null<CleanupHandler>(AH)) UME.Cleanup = cast<Function>(CH->getHandlerBlockOrFunc()); else UME.Cleanup = nullptr; FuncInfo.UnwindMap.push_back(UME); } +void WinEHNumbering::createTryBlockMapEntry(int TryLow, int TryHigh, + ArrayRef<CatchHandler *> Handlers) { + WinEHTryBlockMapEntry TBME; + TBME.TryLow = TryLow; + TBME.TryHigh = TryHigh; + // FIXME: This should be revisited when we want to throw inside a catch + // handler. + TBME.CatchHigh = INT_MAX; + assert(TBME.TryLow <= TBME.TryHigh); + assert(TBME.CatchHigh > TBME.TryHigh); + for (CatchHandler *CH : Handlers) { + WinEHHandlerType HT; + auto *GV = cast<GlobalVariable>(CH->getSelector()->stripPointerCasts()); + // Selectors are always pointers to GlobalVariables with 'struct' type. + // The struct has two fields, adjectives and a type descriptor. + auto *CS = cast<ConstantStruct>(GV->getInitializer()); + HT.Adjectives = + cast<ConstantInt>(CS->getAggregateElement(0U))->getZExtValue(); + HT.TypeDescriptor = cast<GlobalVariable>( + CS->getAggregateElement(1)->stripPointerCasts()); + HT.Handler = cast<Function>(CH->getHandlerBlockOrFunc()); + // FIXME: We don't support catching objects yet! + HT.CatchObjIdx = INT_MAX; + HT.CatchObjOffset = 0; + TBME.HandlerArray.push_back(HT); + } + FuncInfo.TryBlockMap.push_back(TBME); +} + static void print_name(const Value *V) { #ifndef NDEBUG if (!V) { @@ -330,10 +366,8 @@ static void print_name(const Value *V) { #endif } -void WinEHNumbering::proccessCallSite(ArrayRef<ActionHandler *> Actions, - ImmutableCallSite CS) { - // float, int - // float, double, int +void WinEHNumbering::processCallSite(ArrayRef<ActionHandler *> Actions, + ImmutableCallSite CS) { int FirstMismatch = 0; for (int E = std::min(HandlerStack.size(), Actions.size()); FirstMismatch < E; ++FirstMismatch) { @@ -343,28 +377,65 @@ void WinEHNumbering::proccessCallSite(ArrayRef<ActionHandler *> Actions, delete Actions[FirstMismatch]; } + bool EnteringScope = (int)Actions.size() > FirstMismatch; + bool ExitingScope = (int)HandlerStack.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<const Function *, 4> UnnumberedHandlers; + SmallVector<CatchHandler *, 4> PoppedCatches; for (int I = HandlerStack.size() - 1; I >= FirstMismatch; --I) { - if (auto *CH = dyn_cast<CatchHandler>(HandlerStack.back())) - if (const auto *F = dyn_cast<Function>(CH->getHandlerBlockOrFunc())) - UnnumberedHandlers.push_back(F); - // Pop the handlers off of the stack. - delete HandlerStack.back(); + if (auto *CH = dyn_cast<CatchHandler>(HandlerStack.back())) { + PoppedCatches.push_back(CH); + } else { + // Delete cleanup handlers + delete HandlerStack.back(); + } HandlerStack.pop_back(); } - for (const Function *F : UnnumberedHandlers) - calculateStateNumbers(*F); + // 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 (ExitingScope && !EnteringScope && !PoppedCatches.empty()) { + createUnwindMapEntry(currentEHNumber(), nullptr); + ++NextState; + } + + int LastTryLowIdx = 0; + for (int I = 0, E = PoppedCatches.size(); I != E; ++I) { + CatchHandler *CH = PoppedCatches[I]; + if (I + 1 == E || CH->getEHState() != PoppedCatches[I + 1]->getEHState()) { + int TryLow = CH->getEHState(); + auto Handlers = + makeArrayRef(&PoppedCatches[LastTryLowIdx], I - LastTryLowIdx + 1); + createTryBlockMapEntry(TryLow, TryHigh, Handlers); + LastTryLowIdx = I + 1; + } + } + for (CatchHandler *CH : PoppedCatches) { + if (auto *F = dyn_cast<Function>(CH->getHandlerBlockOrFunc())) + calculateStateNumbers(*F); + delete CH; + } + + bool LastActionWasCatch = false; for (size_t I = FirstMismatch; I != Actions.size(); ++I) { - createUnwindMapEntry(currentEHNumber(), Actions[I]); - Actions[I]->setEHState(NextState++); - DEBUG(dbgs() << "Creating unwind map entry for: ("); - print_name(Actions[I]->getHandlerBlockOrFunc()); - DEBUG(dbgs() << ", " << currentEHNumber() << ")\n"); + // 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) { + Actions[I]->setEHState(currentEHNumber()); + } else { + createUnwindMapEntry(currentEHNumber(), Actions[I]); + 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; } DEBUG(dbgs() << "In EHState " << currentEHNumber() << " for CallSite: "); @@ -373,6 +444,10 @@ void WinEHNumbering::proccessCallSite(ArrayRef<ActionHandler *> Actions, } void WinEHNumbering::calculateStateNumbers(const Function &F) { + auto I = VisitedHandlers.insert(&F); + if (!I.second) + return; // We've already visited this handler, don't renumber it. + DEBUG(dbgs() << "Calculating state numbers for: " << F.getName() << '\n'); SmallVector<ActionHandler *, 4> ActionList; for (const BasicBlock &BB : F) { @@ -380,21 +455,21 @@ void WinEHNumbering::calculateStateNumbers(const Function &F) { const auto *CI = dyn_cast<CallInst>(&I); if (!CI || CI->doesNotThrow()) continue; - proccessCallSite(None, CI); + processCallSite(None, CI); } const auto *II = dyn_cast<InvokeInst>(BB.getTerminator()); if (!II) continue; const LandingPadInst *LPI = II->getLandingPadInst(); - if (auto *ActionsCall = dyn_cast<IntrinsicInst>(LPI->getNextNode())) { - assert(ActionsCall->getIntrinsicID() == Intrinsic::eh_actions); - parseEHActions(ActionsCall, ActionList); - proccessCallSite(ActionList, II); - ActionList.clear(); - FuncInfo.LandingPadStateMap[LPI] = currentEHNumber(); - } + auto *ActionsCall = dyn_cast<IntrinsicInst>(LPI->getNextNode()); + if (!ActionsCall) + continue; + assert(ActionsCall->getIntrinsicID() == Intrinsic::eh_actions); + parseEHActions(ActionsCall, ActionList); + processCallSite(ActionList, II); + ActionList.clear(); + FuncInfo.LandingPadStateMap[LPI] = currentEHNumber(); } - proccessCallSite(None, ImmutableCallSite()); } /// clear - Clear out all the function-specific state. This returns this |