[StatepointLowering] Support of the gc.relocates for invoke statepoints.
[oota-llvm.git] / lib / CodeGen / SelectionDAG / FunctionLoweringInfo.cpp
index e2235fbc04499b1c2a050f6e0bdf61459c4934ce..37c58381ec21b43587a4a0837d206e267504902e 100644 (file)
@@ -82,24 +82,25 @@ 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;
+  SmallVector<std::unique_ptr<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 parseEHActions(const IntrinsicInst *II,
-                      SmallVectorImpl<ActionHandler *> &Actions);
   void createUnwindMapEntry(int ToState, ActionHandler *AH);
   void createTryBlockMapEntry(int TryLow, int TryHigh,
                               ArrayRef<CatchHandler *> Handlers);
-  void processCallSite(ArrayRef<ActionHandler *> Actions, ImmutableCallSite CS);
+  void processCallSite(MutableArrayRef<std::unique_ptr<ActionHandler>> Actions,
+                       ImmutableCallSite CS);
   void calculateStateNumbers(const Function &F);
 };
 }
@@ -204,10 +205,9 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf,
       // during the initial isel pass through the IR so that it is done
       // in a predictable order.
       if (const DbgDeclareInst *DI = dyn_cast<DbgDeclareInst>(I)) {
-        DIVariable DIVar(DI->getVariable());
-        assert((!DIVar || DIVar.isVariable()) &&
-          "Variable in DbgDeclareInst should be either null or a DIVariable.");
-        if (MMI.hasDebugInfo() && DIVar && DI->getDebugLoc()) {
+        assert(DI->getVariable() && "Missing variable");
+        assert(DI->getDebugLoc() && "Missing location");
+        if (MMI.hasDebugInfo()) {
           // Don't handle byval struct arguments or VLAs, for example.
           // Non-byval arguments are handled here (they refer to the stack
           // temporary alloca at this point).
@@ -274,43 +274,79 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf,
   }
 
   // Mark landing pad blocks.
-  for (BB = Fn->begin(); BB != EB; ++BB)
+  SmallVector<const LandingPadInst *, 4> LPads;
+  for (BB = Fn->begin(); BB != EB; ++BB) {
     if (const auto *Invoke = dyn_cast<InvokeInst>(BB->getTerminator()))
       MBBMap[Invoke->getSuccessor(1)]->setIsLandingPad();
+    if (BB->isLandingPad())
+      LPads.push_back(BB->getLandingPadInst());
+  }
+
+  // If this is an MSVC EH personality, we need to do a bit more work.
+  EHPersonality Personality = EHPersonality::Unknown;
+  if (!LPads.empty())
+    Personality = classifyEHPersonality(LPads.back()->getPersonalityFn());
+  if (!isMSVCEHPersonality(Personality))
+    return;
+
+  WinEHFuncInfo *EHInfo = nullptr;
+  if (Personality == EHPersonality::MSVC_Win64SEH) {
+    addSEHHandlersForLPads(LPads);
+  } else if (Personality == EHPersonality::MSVC_CXX) {
+    const Function *WinEHParentFn = MMI.getWinEHParent(&fn);
+    EHInfo = &MMI.getWinEHFuncInfo(WinEHParentFn);
+    if (EHInfo->LandingPadStateMap.empty()) {
+      WinEHNumbering Num(*EHInfo);
+      Num.calculateStateNumbers(*WinEHParentFn);
+      // Pop everything on the handler stack.
+      Num.processCallSite(None, ImmutableCallSite());
+    }
 
-  // Calculate EH numbers for WinEH.
-  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());
+    // Copy the state numbers to LandingPadInfo for the current function, which
+    // could be a handler or the parent.
+    for (const LandingPadInst *LP : LPads) {
+      MachineBasicBlock *LPadMBB = MBBMap[LP->getParent()];
+      MMI.addWinEHState(LPadMBB, EHInfo->LandingPadStateMap[LP]);
+    }
   }
 }
 
-void WinEHNumbering::parseEHActions(const IntrinsicInst *II,
-                                    SmallVectorImpl<ActionHandler *> &Actions) {
-  for (unsigned I = 0, E = II->getNumArgOperands(); I != E;) {
-    uint64_t ActionKind =
-        cast<ConstantInt>(II->getArgOperand(I))->getZExtValue();
-    if (ActionKind == /*catch=*/1) {
-      auto *Selector = cast<Constant>(II->getArgOperand(I + 1));
-      Value *CatchObject = II->getArgOperand(I + 2);
-      Constant *Handler = cast<Constant>(II->getArgOperand(I + 3));
-      I += 4;
-      auto *CH = new CatchHandler(/*BB=*/nullptr, Selector, /*NextBB=*/nullptr);
-      CH->setExceptionVar(CatchObject);
-      CH->setHandlerBlockOrFunc(Handler);
-      Actions.push_back(CH);
-    } else {
-      assert(ActionKind == 0 && "expected a cleanup or a catch action!");
-      Constant *Handler = cast<Constant>(II->getArgOperand(I + 1));
-      I += 2;
-      auto *CH = new CleanupHandler(/*BB=*/nullptr);
-      CH->setHandlerBlockOrFunc(Handler);
-      Actions.push_back(CH);
+void FunctionLoweringInfo::addSEHHandlersForLPads(
+    ArrayRef<const LandingPadInst *> LPads) {
+  MachineModuleInfo &MMI = MF->getMMI();
+
+  // Iterate over all landing pads with llvm.eh.actions calls.
+  for (const LandingPadInst *LP : LPads) {
+    const IntrinsicInst *ActionsCall =
+        dyn_cast<IntrinsicInst>(LP->getNextNode());
+    if (!ActionsCall ||
+        ActionsCall->getIntrinsicID() != Intrinsic::eh_actions)
+      continue;
+
+    // Parse the llvm.eh.actions call we found.
+    MachineBasicBlock *LPadMBB = MBBMap[LP->getParent()];
+    SmallVector<std::unique_ptr<ActionHandler>, 4> Actions;
+    parseEHActions(ActionsCall, Actions);
+
+    // Iterate EH actions from most to least precedence, which means
+    // iterating in reverse.
+    for (auto I = Actions.rbegin(), E = Actions.rend(); I != E; ++I) {
+      ActionHandler *Action = I->get();
+      if (auto *CH = dyn_cast<CatchHandler>(Action)) {
+        const auto *Filter =
+            dyn_cast<Function>(CH->getSelector()->stripPointerCasts());
+        assert((Filter || CH->getSelector()->isNullValue()) &&
+               "expected function or catch-all");
+        const auto *RecoverBA =
+            cast<BlockAddress>(CH->getHandlerBlockOrFunc());
+        MMI.addSEHCatchHandler(LPadMBB, Filter, RecoverBA);
+      } else {
+        assert(isa<CleanupHandler>(Action));
+        const auto *Fini = cast<Function>(Action->getHandlerBlockOrFunc());
+        MMI.addSEHCleanupHandler(LPadMBB, Fini);
+      }
     }
   }
-  std::reverse(Actions.begin(), Actions.end());
 }
 
 void WinEHNumbering::createUnwindMapEntry(int ToState, ActionHandler *AH) {
@@ -328,25 +364,24 @@ void WinEHNumbering::createTryBlockMapEntry(int TryLow, int TryHigh,
   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());
+    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());
-    // FIXME: We don't support catching objects yet!
-    HT.CatchObjIdx = INT_MAX;
-    HT.CatchObjOffset = 0;
+    HT.CatchObjRecoverIdx = CH->getExceptionVarIndex();
     TBME.HandlerArray.push_back(HT);
   }
   FuncInfo.TryBlockMap.push_back(TBME);
@@ -366,75 +401,113 @@ static void print_name(const Value *V) {
 #endif
 }
 
-void WinEHNumbering::processCallSite(ArrayRef<ActionHandler *> Actions,
-                                     ImmutableCallSite CS) {
+void WinEHNumbering::processCallSite(
+    MutableArrayRef<std::unique_ptr<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 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<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();
+    std::unique_ptr<ActionHandler> Handler = HandlerStack.pop_back_val();
+    if (isa<CatchHandler>(Handler.get()))
+      PoppedCatches.push_back(cast<CatchHandler>(Handler.release()));
   }
 
-  // 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];
+    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 (size_t 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() > (size_t)FirstMismatch) {
+    for (int E = std::min(HandlerStack.size(), Actions.size());
+         FirstMismatch < E; ++FirstMismatch) {
+      if (HandlerStack[FirstMismatch]->getHandlerBlockOrFunc() !=
+          Actions[FirstMismatch]->getHandlerBlockOrFunc())
+        break;
+    }
+  }
+
+  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]);
+    bool CurrActionIsCatch = isa<CatchHandler>(Actions[I].get());
     // FIXME: Reenable this optimization!
     if (CurrActionIsCatch && LastActionWasCatch && false) {
+      DEBUG(dbgs() << "setEHState for handler to " << currentEHNumber()
+                   << "\n");
       Actions[I]->setEHState(currentEHNumber());
     } else {
-      createUnwindMapEntry(currentEHNumber(), Actions[I]);
+      DEBUG(dbgs() << "createUnwindMapEntry(" << currentEHNumber() << ", ");
+      print_name(Actions[I]->getHandlerBlockOrFunc());
+      DEBUG(dbgs() << ")\n");
+      createUnwindMapEntry(currentEHNumber(), Actions[I].get());
+      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]);
+    HandlerStack.push_back(std::move(Actions[I]));
     LastActionWasCatch = CurrActionIsCatch;
   }
 
@@ -448,8 +521,13 @@ 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;
+  SmallVector<std::unique_ptr<ActionHandler>, 4> ActionList;
   for (const BasicBlock &BB : F) {
     for (const Instruction &I : BB) {
       const auto *CI = dyn_cast<CallInst>(&I);
@@ -466,10 +544,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
@@ -492,6 +579,7 @@ void FunctionLoweringInfo::clear() {
   ByValArgFrameIndexMap.clear();
   RegFixups.clear();
   StatepointStackSlots.clear();
+  StatepointRelocatedValues.clear();
   PreferredExtendType.clear();
 }
 
@@ -678,8 +766,7 @@ void llvm::ComputeUsesVAFloatArgument(const CallInst &I,
   if (FT->isVarArg() && !MMI->usesVAFloatArgument()) {
     for (unsigned i = 0, e = I.getNumArgOperands(); i != e; ++i) {
       Type* T = I.getArgOperand(i)->getType();
-      for (po_iterator<Type*> i = po_begin(T), e = po_end(T);
-           i != e; ++i) {
+      for (auto i : post_order(T)) {
         if (i->isFloatingPointTy()) {
           MMI->setUsesVAFloatArgument(true);
           return;