- DeleteContainerPointers(Actions);
- }
-}
-
-void WinEHNumbering::createUnwindMapEntry(int ToState, ActionHandler *AH) {
- WinEHUnwindMapEntry UME;
- UME.ToState = ToState;
- 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;
- assert(TBME.TryLow <= TBME.TryHigh);
- for (CatchHandler *CH : Handlers) {
- WinEHHandlerType HT;
- if (CH->getSelector()->isNullValue()) {
- HT.Adjectives = 0x40;
- HT.TypeDescriptor = nullptr;
- } else {
- 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());
- HT.CatchObjRecoverIdx = CH->getExceptionVarIndex();
- TBME.HandlerArray.push_back(HT);
- }
- FuncInfo.TryBlockMap.push_back(TBME);
-}
-
-static void print_name(const Value *V) {
-#ifndef NDEBUG
- if (!V) {
- DEBUG(dbgs() << "null");
- return;
- }
-
- if (const auto *F = dyn_cast<Function>(V))
- DEBUG(dbgs() << F->getName());
- else
- DEBUG(V->dump());
-#endif
-}
-
-void WinEHNumbering::processCallSite(ArrayRef<ActionHandler *> Actions,
- ImmutableCallSite CS) {
- int FirstMismatch = 0;
- for (int E = std::min(HandlerStack.size(), Actions.size()); FirstMismatch < E;
- ++FirstMismatch) {
- if (HandlerStack[FirstMismatch]->getHandlerBlockOrFunc() !=
- Actions[FirstMismatch]->getHandlerBlockOrFunc())
- break;
- 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;
- for (int I = HandlerStack.size() - 1; I >= FirstMismatch; --I) {
- if (auto *CH = dyn_cast<CatchHandler>(HandlerStack.back())) {
- PoppedCatches.push_back(CH);
- } else {
- // Delete cleanup handlers
- delete HandlerStack.back();
- }
- 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];
- 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) {
- // 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: ");
- print_name(CS ? CS.getCalledValue() : nullptr);
- DEBUG(dbgs() << '\n');
-}
-
-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) {
- for (const Instruction &I : BB) {
- const auto *CI = dyn_cast<CallInst>(&I);
- if (!CI || CI->doesNotThrow())
- continue;
- processCallSite(None, CI);
- }
- const auto *II = dyn_cast<InvokeInst>(BB.getTerminator());
- if (!II)
- continue;
- const LandingPadInst *LPI = II->getLandingPadInst();
- 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();