//===-- ThreadPlanStack.cpp -------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Target/ThreadPlanStack.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Utility/Log.h"

using namespace lldb;
using namespace lldb_private;

static void PrintPlanElement(Stream &s, const ThreadPlanSP &plan,
                             lldb::DescriptionLevel desc_level,
                             int32_t elem_idx) {
  s.IndentMore();
  s.Indent();
  s.Printf("Element %d: ", elem_idx);
  plan->GetDescription(&s, desc_level);
  s.EOL();
  s.IndentLess();
}

ThreadPlanStack::ThreadPlanStack(const Thread &thread, bool make_null) {
  if (make_null) {
    // The ThreadPlanNull doesn't do anything to the Thread, so this is actually
    // still a const operation.
    m_plans.push_back(
        ThreadPlanSP(new ThreadPlanNull(const_cast<Thread &>(thread))));
  }
}

void ThreadPlanStack::DumpThreadPlans(Stream &s,
                                      lldb::DescriptionLevel desc_level,
                                      bool include_internal) const {
  s.IndentMore();
  PrintOneStack(s, "Active plan stack", m_plans, desc_level, include_internal);
  PrintOneStack(s, "Completed plan stack", m_completed_plans, desc_level,
                include_internal);
  PrintOneStack(s, "Discarded plan stack", m_discarded_plans, desc_level,
                include_internal);
  s.IndentLess();
}

void ThreadPlanStack::PrintOneStack(Stream &s, llvm::StringRef stack_name,
                                    const PlanStack &stack,
                                    lldb::DescriptionLevel desc_level,
                                    bool include_internal) const {
  // If the stack is empty, just exit:
  if (stack.empty())
    return;

  // Make sure there are public completed plans:
  bool any_public = false;
  if (!include_internal) {
    for (auto plan : stack) {
      if (!plan->GetPrivate()) {
        any_public = true;
        break;
      }
    }
  }

  if (include_internal || any_public) {
    int print_idx = 0;
    s.Indent();
    s << stack_name << ":\n";
    for (auto plan : stack) {
      if (!include_internal && plan->GetPrivate())
        continue;
      PrintPlanElement(s, plan, desc_level, print_idx++);
    }
  }
}

size_t ThreadPlanStack::CheckpointCompletedPlans() {
  m_completed_plan_checkpoint++;
  m_completed_plan_store.insert(
      std::make_pair(m_completed_plan_checkpoint, m_completed_plans));
  return m_completed_plan_checkpoint;
}

void ThreadPlanStack::RestoreCompletedPlanCheckpoint(size_t checkpoint) {
  auto result = m_completed_plan_store.find(checkpoint);
  assert(result != m_completed_plan_store.end() &&
         "Asked for a checkpoint that didn't exist");
  m_completed_plans.swap((*result).second);
  m_completed_plan_store.erase(result);
}

void ThreadPlanStack::DiscardCompletedPlanCheckpoint(size_t checkpoint) {
  m_completed_plan_store.erase(checkpoint);
}

void ThreadPlanStack::ThreadDestroyed(Thread *thread) {
  // Tell the plan stacks that this thread is going away:
  for (ThreadPlanSP plan : m_plans)
    plan->ThreadDestroyed();

  for (ThreadPlanSP plan : m_discarded_plans)
    plan->ThreadDestroyed();

  for (ThreadPlanSP plan : m_completed_plans)
    plan->ThreadDestroyed();

  // Now clear the current plan stacks:
  m_plans.clear();
  m_discarded_plans.clear();
  m_completed_plans.clear();

  // Push a ThreadPlanNull on the plan stack.  That way we can continue
  // assuming that the plan stack is never empty, but if somebody errantly asks
  // questions of a destroyed thread without checking first whether it is
  // destroyed, they won't crash.
  if (thread != nullptr) {
    lldb::ThreadPlanSP null_plan_sp(new ThreadPlanNull(*thread));
    m_plans.push_back(null_plan_sp);
  }
}

void ThreadPlanStack::PushPlan(lldb::ThreadPlanSP new_plan_sp) {
  // If the thread plan doesn't already have a tracer, give it its parent's
  // tracer:
  // The first plan has to be a base plan:
  assert((m_plans.size() > 0 || new_plan_sp->IsBasePlan()) &&
         "Zeroth plan must be a base plan");

  if (!new_plan_sp->GetThreadPlanTracer()) {
    assert(!m_plans.empty());
    new_plan_sp->SetThreadPlanTracer(m_plans.back()->GetThreadPlanTracer());
  }
  m_plans.push_back(new_plan_sp);
  new_plan_sp->DidPush();
}

lldb::ThreadPlanSP ThreadPlanStack::PopPlan() {
  assert(m_plans.size() > 1 && "Can't pop the base thread plan");

  lldb::ThreadPlanSP plan_sp = std::move(m_plans.back());
  m_completed_plans.push_back(plan_sp);
  plan_sp->WillPop();
  m_plans.pop_back();
  return plan_sp;
}

lldb::ThreadPlanSP ThreadPlanStack::DiscardPlan() {
  assert(m_plans.size() > 1 && "Can't discard the base thread plan");

  lldb::ThreadPlanSP plan_sp = std::move(m_plans.back());
  m_discarded_plans.push_back(plan_sp);
  plan_sp->WillPop();
  m_plans.pop_back();
  return plan_sp;
}

// If the input plan is nullptr, discard all plans.  Otherwise make sure this
// plan is in the stack, and if so discard up to and including it.
void ThreadPlanStack::DiscardPlansUpToPlan(ThreadPlan *up_to_plan_ptr) {
  int stack_size = m_plans.size();

  if (up_to_plan_ptr == nullptr) {
    for (int i = stack_size - 1; i > 0; i--)
      DiscardPlan();
    return;
  }

  bool found_it = false;
  for (int i = stack_size - 1; i > 0; i--) {
    if (m_plans[i].get() == up_to_plan_ptr) {
      found_it = true;
      break;
    }
  }

  if (found_it) {
    bool last_one = false;
    for (int i = stack_size - 1; i > 0 && !last_one; i--) {
      if (GetCurrentPlan().get() == up_to_plan_ptr)
        last_one = true;
      DiscardPlan();
    }
  }
}

void ThreadPlanStack::DiscardAllPlans() {
  int stack_size = m_plans.size();
  for (int i = stack_size - 1; i > 0; i--) {
    DiscardPlan();
  }
  return;
}

void ThreadPlanStack::DiscardConsultingMasterPlans() {
  while (true) {
    int master_plan_idx;
    bool discard = true;

    // Find the first master plan, see if it wants discarding, and if yes
    // discard up to it.
    for (master_plan_idx = m_plans.size() - 1; master_plan_idx >= 0;
         master_plan_idx--) {
      if (m_plans[master_plan_idx]->IsMasterPlan()) {
        discard = m_plans[master_plan_idx]->OkayToDiscard();
        break;
      }
    }

    // If the master plan doesn't want to get discarded, then we're done.
    if (!discard)
      return;

    // First pop all the dependent plans:
    for (int i = m_plans.size() - 1; i > master_plan_idx; i--) {
      DiscardPlan();
    }

    // Now discard the master plan itself.
    // The bottom-most plan never gets discarded.  "OkayToDiscard" for it
    // means discard it's dependent plans, but not it...
    if (master_plan_idx > 0) {
      DiscardPlan();
    }
  }
}

lldb::ThreadPlanSP ThreadPlanStack::GetCurrentPlan() const {
  assert(m_plans.size() != 0 && "There will always be a base plan.");
  return m_plans.back();
}

lldb::ThreadPlanSP ThreadPlanStack::GetCompletedPlan(bool skip_private) const {
  if (m_completed_plans.empty())
    return {};

  if (!skip_private)
    return m_completed_plans.back();

  for (int i = m_completed_plans.size() - 1; i >= 0; i--) {
    lldb::ThreadPlanSP completed_plan_sp;
    completed_plan_sp = m_completed_plans[i];
    if (!completed_plan_sp->GetPrivate())
      return completed_plan_sp;
  }
  return {};
}

lldb::ThreadPlanSP ThreadPlanStack::GetPlanByIndex(uint32_t plan_idx,
                                                   bool skip_private) const {
  uint32_t idx = 0;

  for (lldb::ThreadPlanSP plan_sp : m_plans) {
    if (skip_private && plan_sp->GetPrivate())
      continue;
    if (idx == plan_idx)
      return plan_sp;
    idx++;
  }
  return {};
}

lldb::ValueObjectSP ThreadPlanStack::GetReturnValueObject() const {
  if (m_completed_plans.empty())
    return {};

  for (int i = m_completed_plans.size() - 1; i >= 0; i--) {
    lldb::ValueObjectSP return_valobj_sp;
    return_valobj_sp = m_completed_plans[i]->GetReturnValueObject();
    if (return_valobj_sp)
      return return_valobj_sp;
  }
  return {};
}

lldb::ExpressionVariableSP ThreadPlanStack::GetExpressionVariable() const {
  if (m_completed_plans.empty())
    return {};

  for (int i = m_completed_plans.size() - 1; i >= 0; i--) {
    lldb::ExpressionVariableSP expression_variable_sp;
    expression_variable_sp = m_completed_plans[i]->GetExpressionVariable();
    if (expression_variable_sp)
      return expression_variable_sp;
  }
  return {};
}
bool ThreadPlanStack::AnyPlans() const {
  // There is always a base plan...
  return m_plans.size() > 1;
}

bool ThreadPlanStack::AnyCompletedPlans() const {
  return !m_completed_plans.empty();
}

bool ThreadPlanStack::AnyDiscardedPlans() const {
  return !m_discarded_plans.empty();
}

bool ThreadPlanStack::IsPlanDone(ThreadPlan *in_plan) const {
  for (auto plan : m_completed_plans) {
    if (plan.get() == in_plan)
      return true;
  }
  return false;
}

bool ThreadPlanStack::WasPlanDiscarded(ThreadPlan *in_plan) const {
  for (auto plan : m_discarded_plans) {
    if (plan.get() == in_plan)
      return true;
  }
  return false;
}

ThreadPlan *ThreadPlanStack::GetPreviousPlan(ThreadPlan *current_plan) const {
  if (current_plan == nullptr)
    return nullptr;

  // Look first in the completed plans, if the plan is here and there is
  // a completed plan above it, return that.
  int stack_size = m_completed_plans.size();
  for (int i = stack_size - 1; i > 0; i--) {
    if (current_plan == m_completed_plans[i].get())
      return m_completed_plans[i - 1].get();
  }

  // If this is the first completed plan, the previous one is the
  // bottom of the regular plan stack.
  if (stack_size > 0 && m_completed_plans[0].get() == current_plan) {
    return GetCurrentPlan().get();
  }

  // Otherwise look for it in the regular plans.
  stack_size = m_plans.size();
  for (int i = stack_size - 1; i > 0; i--) {
    if (current_plan == m_plans[i].get())
      return m_plans[i - 1].get();
  }
  return nullptr;
}

ThreadPlan *ThreadPlanStack::GetInnermostExpression() const {
  int stack_size = m_plans.size();

  for (int i = stack_size - 1; i > 0; i--) {
    if (m_plans[i]->GetKind() == ThreadPlan::eKindCallFunction)
      return m_plans[i].get();
  }
  return nullptr;
}

void ThreadPlanStack::ClearThreadCache() {
  for (lldb::ThreadPlanSP thread_plan_sp : m_plans)
    thread_plan_sp->ClearThreadCache();
}

void ThreadPlanStack::WillResume() {
  m_completed_plans.clear();
  m_discarded_plans.clear();
}

void ThreadPlanStackMap::Update(ThreadList &current_threads,
                                bool delete_missing,
                                bool check_for_new) {

  // Now find all the new threads and add them to the map:
  if (check_for_new) {
    for (auto thread : current_threads.Threads()) {
      lldb::tid_t cur_tid = thread->GetID();
      if (!Find(cur_tid)) {
        AddThread(*thread.get());
        thread->QueueFundamentalPlan(true);
      }
    }
  }

  // If we aren't reaping missing threads at this point,
  // we are done.
  if (!delete_missing)
    return;
  // Otherwise scan for absent TID's.
  std::vector<lldb::tid_t> missing_threads;
  // If we are going to delete plans from the plan stack,
  // then scan for absent TID's:
  for (auto thread_plans : m_plans_list) {
    lldb::tid_t cur_tid = thread_plans.first;
    ThreadSP thread_sp = current_threads.FindThreadByID(cur_tid);
    if (!thread_sp)
      missing_threads.push_back(cur_tid);
  }
  for (lldb::tid_t tid : missing_threads) {
    RemoveTID(tid);
  }
}

void ThreadPlanStackMap::DumpPlans(Stream &strm,
                                   lldb::DescriptionLevel desc_level,
                                   bool internal, bool condense_if_trivial,
                                   bool skip_unreported) {
  for (auto elem : m_plans_list) {
    lldb::tid_t tid = elem.first;
    uint32_t index_id = 0;
    ThreadSP thread_sp = m_process.GetThreadList().FindThreadByID(tid);

    if (skip_unreported) {
      if (!thread_sp)
        continue;
    }
    if (thread_sp)
      index_id = thread_sp->GetIndexID();

    if (condense_if_trivial) {
      if (!elem.second.AnyPlans() && !elem.second.AnyCompletedPlans() &&
          !elem.second.AnyDiscardedPlans()) {
        strm.Printf("thread #%u: tid = 0x%4.4" PRIx64 "\n", index_id, tid);
        strm.IndentMore();
        strm.Indent();
        strm.Printf("No active thread plans\n");
        strm.IndentLess();
        return;
      }
    }

    strm.Indent();
    strm.Printf("thread #%u: tid = 0x%4.4" PRIx64 ":\n", index_id, tid);

    elem.second.DumpThreadPlans(strm, desc_level, internal);
  }
}

bool ThreadPlanStackMap::DumpPlansForTID(Stream &strm, lldb::tid_t tid,
                                         lldb::DescriptionLevel desc_level,
                                         bool internal,
                                         bool condense_if_trivial,
                                         bool skip_unreported) {
  uint32_t index_id = 0;
  ThreadSP thread_sp = m_process.GetThreadList().FindThreadByID(tid);

  if (skip_unreported) {
    if (!thread_sp) {
      strm.Format("Unknown TID: {0}", tid);
      return false;
    }
  }

  if (thread_sp)
    index_id = thread_sp->GetIndexID();
  ThreadPlanStack *stack = Find(tid);
  if (!stack) {
    strm.Format("Unknown TID: {0}\n", tid);
    return false;
  }

  if (condense_if_trivial) {
    if (!stack->AnyPlans() && !stack->AnyCompletedPlans() &&
        !stack->AnyDiscardedPlans()) {
      strm.Printf("thread #%u: tid = 0x%4.4" PRIx64 "\n", index_id, tid);
      strm.IndentMore();
      strm.Indent();
      strm.Printf("No active thread plans\n");
      strm.IndentLess();
      return true;
    }
  }

  strm.Indent();
  strm.Printf("thread #%u: tid = 0x%4.4" PRIx64 ":\n", index_id, tid);

  stack->DumpThreadPlans(strm, desc_level, internal);
  return true;
}

bool ThreadPlanStackMap::PrunePlansForTID(lldb::tid_t tid) {
  // We only remove the plans for unreported TID's.
  ThreadSP thread_sp = m_process.GetThreadList().FindThreadByID(tid);
  if (thread_sp)
    return false;

  return RemoveTID(tid);
}
