//===-- ThreadPlanShouldStopHere.cpp --------------------------------------===//
//
// 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/ThreadPlanShouldStopHere.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/Language.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"

using namespace lldb;
using namespace lldb_private;

// ThreadPlanShouldStopHere constructor
ThreadPlanShouldStopHere::ThreadPlanShouldStopHere(ThreadPlan *owner)
    : m_callbacks(), m_baton(nullptr), m_owner(owner),
      m_flags(ThreadPlanShouldStopHere::eNone) {
  m_callbacks.should_stop_here_callback =
      ThreadPlanShouldStopHere::DefaultShouldStopHereCallback;
  m_callbacks.step_from_here_callback =
      ThreadPlanShouldStopHere::DefaultStepFromHereCallback;
}

ThreadPlanShouldStopHere::ThreadPlanShouldStopHere(
    ThreadPlan *owner, const ThreadPlanShouldStopHereCallbacks *callbacks,
    void *baton)
    : m_callbacks(), m_baton(), m_owner(owner),
      m_flags(ThreadPlanShouldStopHere::eNone) {
  SetShouldStopHereCallbacks(callbacks, baton);
}

ThreadPlanShouldStopHere::~ThreadPlanShouldStopHere() = default;

bool ThreadPlanShouldStopHere::InvokeShouldStopHereCallback(
    FrameComparison operation, Status &status) {
  bool should_stop_here = true;
  if (m_callbacks.should_stop_here_callback) {
    should_stop_here = m_callbacks.should_stop_here_callback(
        m_owner, m_flags, operation, status, m_baton);
    Log *log = GetLog(LLDBLog::Step);
    if (log) {
      lldb::addr_t current_addr =
          m_owner->GetThread().GetRegisterContext()->GetPC(0);

      LLDB_LOGF(log, "ShouldStopHere callback returned %u from 0x%" PRIx64 ".",
                should_stop_here, current_addr);
    }
  }

  return should_stop_here;
}

bool ThreadPlanShouldStopHere::DefaultShouldStopHereCallback(
    ThreadPlan *current_plan, Flags &flags, FrameComparison operation,
    Status &status, void *baton) {
  bool should_stop_here = true;
  StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
  if (!frame)
    return true;

  Log *log = GetLog(LLDBLog::Step);

  if ((operation == eFrameCompareOlder && flags.Test(eStepOutAvoidNoDebug)) ||
      (operation == eFrameCompareYounger && flags.Test(eStepInAvoidNoDebug)) ||
      (operation == eFrameCompareSameParent &&
       flags.Test(eStepInAvoidNoDebug))) {
    if (!frame->HasDebugInformation()) {
      LLDB_LOGF(log, "Stepping out of frame with no debug info");

      should_stop_here = false;
    }
  }

  // Check whether the frame we are in is a language runtime thunk, only for
  // step out:
  if (operation == eFrameCompareOlder) {
    if (const Symbol *symbol =
            frame->GetSymbolContext(eSymbolContextSymbol).symbol) {
      ProcessSP process_sp(current_plan->GetThread().GetProcess());
      for (auto *runtime : process_sp->GetLanguageRuntimes()) {
        if (runtime->IsSymbolARuntimeThunk(*symbol) &&
            flags.Test(ThreadPlanShouldStopHere::eStepOutPastThunks)) {
          LLDB_LOGF(
              log, "Stepping out past a language thunk %s for: %s",
              frame->GetFunctionName(),
              Language::GetNameForLanguageType(runtime->GetLanguageType()));
          should_stop_here = false;
          break;
        }
      }
    }
  }
  // Source line stepping plans should always avoid code with line number 0.
  // But trampoline plans should not; it's easier to reason about if they
  // leave that up to the source line plan that's driving them.
  // FIXME: At present the ShouldStop and the StepFromHere calculate this
  // independently.  If this ever becomes expensive (this one isn't) we can
  // try to have this set a state that the StepFromHere can use.
  if (frame && flags.Test(ThreadPlanShouldStopHere::eStepPastLine0)) {
    SymbolContext sc;
    sc = frame->GetSymbolContext(eSymbolContextLineEntry);
    if (sc.line_entry.line == 0)
      should_stop_here = false;
  }

  return should_stop_here;
}

ThreadPlanSP ThreadPlanShouldStopHere::DefaultStepFromHereCallback(
    ThreadPlan *current_plan, Flags &flags, FrameComparison operation,
    Status &status, void *baton) {
  const bool stop_others = false;
  const size_t frame_index = 0;
  ThreadPlanSP return_plan_sp;
  // If we are stepping through code at line number 0, then we need to step
  // over this range.  Otherwise we will step out.
  Log *log = GetLog(LLDBLog::Step);

  StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
  if (!frame)
    return return_plan_sp;
  SymbolContext sc;
  sc = frame->GetSymbolContext(eSymbolContextLineEntry | eSymbolContextSymbol);

  if (sc.line_entry.line == 0) {
    AddressRange range = sc.line_entry.range;
    bool just_step_out = false;
    if (sc.symbol) {
      ProcessSP process_sp(current_plan->GetThread().GetProcess());

      // If this is a runtime thunk, step through it, rather than stepping out
      // because it's marked line 0.
      bool is_thunk = false;
      for (auto *runtime : process_sp->GetLanguageRuntimes()) {
        if (runtime->IsSymbolARuntimeThunk(*sc.symbol) &&
            flags.Test(ThreadPlanShouldStopHere::eStepOutPastThunks)) {
          LLDB_LOGF(
              log, "Stepping out past a language thunk %s for: %s",
              frame->GetFunctionName(),
              Language::GetNameForLanguageType(runtime->GetLanguageType()));
          is_thunk = true;
          break;
        }
      }

      // If the whole function is marked line 0 just step out, that's easier &
      // faster than continuing to step through it.
      // FIXME: This assumes that the function is a single line range.  It could
      // be a series of contiguous line 0 ranges.  Check for that too.
      if (!is_thunk && sc.symbol->ValueIsAddress()) {
        Address symbol_end = sc.symbol->GetAddress();
        symbol_end.Slide(sc.symbol->GetByteSize() - 1);
        if (range.ContainsFileAddress(sc.symbol->GetAddress()) &&
            range.ContainsFileAddress(symbol_end)) {
          LLDB_LOGF(log, "Stopped in a function with only line 0 lines, just "
                         "stepping out.");
          just_step_out = true;
        }
      }
    }
    if (!just_step_out) {
      LLDB_LOGF(log, "ThreadPlanShouldStopHere::DefaultStepFromHereCallback "
                     "Queueing StepInRange plan to step through line 0 code.");

      return_plan_sp = current_plan->GetThread().QueueThreadPlanForStepInRange(
          false, range, sc, llvm::StringRef(), eOnlyDuringStepping, status,
          eLazyBoolCalculate, eLazyBoolNo);
    }
  }

  if (!return_plan_sp)
    return_plan_sp =
        current_plan->GetThread().QueueThreadPlanForStepOutNoShouldStop(
            false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion,
            frame_index, status, true);
  return return_plan_sp;
}

ThreadPlanSP ThreadPlanShouldStopHere::QueueStepOutFromHerePlan(
    lldb_private::Flags &flags, lldb::FrameComparison operation,
    Status &status) {
  ThreadPlanSP return_plan_sp;
  if (m_callbacks.step_from_here_callback) {
    return_plan_sp = m_callbacks.step_from_here_callback(
        m_owner, flags, operation, status, m_baton);
  }
  return return_plan_sp;
}

lldb::ThreadPlanSP ThreadPlanShouldStopHere::CheckShouldStopHereAndQueueStepOut(
    lldb::FrameComparison operation, Status &status) {
  if (!InvokeShouldStopHereCallback(operation, status))
    return QueueStepOutFromHerePlan(m_flags, operation, status);
  else
    return ThreadPlanSP();
}
