//===-- BreakpointLocation.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/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/BreakpointID.h"
#include "lldb/Breakpoint/BreakpointResolver.h"
#include "lldb/Breakpoint/BreakpointResolverScripted.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Expression/UserExpression.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadSpec.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/ValueObject/ValueObject.h"

using namespace lldb;
using namespace lldb_private;

BreakpointLocation::BreakpointLocation(break_id_t loc_id, Breakpoint &owner,
                                       const Address &addr, lldb::tid_t tid,
                                       bool check_for_resolver)
    : m_address(addr), m_owner(owner), m_loc_id(loc_id) {
  if (check_for_resolver) {
    const Symbol *symbol = m_address.CalculateSymbolContextSymbol();
    if (symbol && symbol->IsIndirect()) {
      SetShouldResolveIndirectFunctions(true);
    }
  }

  SetThreadIDInternal(tid);
}

BreakpointLocation::BreakpointLocation(break_id_t loc_id, Breakpoint &owner)
    : m_owner(owner), m_loc_id(loc_id) {
  SetThreadIDInternal(LLDB_INVALID_THREAD_ID);
}

BreakpointLocation::~BreakpointLocation() {
  llvm::consumeError(ClearBreakpointSite());
}

lldb::addr_t BreakpointLocation::GetLoadAddress() const {
  return m_address.GetOpcodeLoadAddress(&m_owner.GetTarget());
}

const BreakpointOptions &BreakpointLocation::GetOptionsSpecifyingKind(
    BreakpointOptions::OptionKind kind) const {
  if (m_options_up && m_options_up->IsOptionSet(kind))
    return *m_options_up;
  return m_owner.GetOptions();
}

Address &BreakpointLocation::GetAddress() { return m_address; }

Breakpoint &BreakpointLocation::GetBreakpoint() { return m_owner; }

Target &BreakpointLocation::GetTarget() { return m_owner.GetTarget(); }

bool BreakpointLocation::IsEnabled() const {
  if (!m_owner.IsEnabled())
    return false;
  if (m_options_up != nullptr)
    return m_options_up->IsEnabled();
  return true;
}

llvm::Error BreakpointLocation::SetEnabled(bool enabled) {
  GetLocationOptions().SetEnabled(enabled);
  llvm::Error error = enabled ? ResolveBreakpointSite() : ClearBreakpointSite();
  SendBreakpointLocationChangedEvent(enabled ? eBreakpointEventTypeEnabled
                                             : eBreakpointEventTypeDisabled);
  return error;
}

bool BreakpointLocation::IsAutoContinue() const {
  if (m_options_up &&
      m_options_up->IsOptionSet(BreakpointOptions::eAutoContinue))
    return m_options_up->IsAutoContinue();
  return m_owner.IsAutoContinue();
}

void BreakpointLocation::SetAutoContinue(bool auto_continue) {
  GetLocationOptions().SetAutoContinue(auto_continue);
  SendBreakpointLocationChangedEvent(eBreakpointEventTypeAutoContinueChanged);
}

void BreakpointLocation::SetThreadID(lldb::tid_t thread_id) {
  SetThreadIDInternal(thread_id);
  SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
}

lldb::tid_t BreakpointLocation::GetThreadID() {
  const ThreadSpec *thread_spec =
      GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
          .GetThreadSpecNoCreate();
  if (thread_spec)
    return thread_spec->GetTID();
  return LLDB_INVALID_THREAD_ID;
}

void BreakpointLocation::SetThreadIndex(uint32_t index) {
  if (index != 0)
    GetLocationOptions().GetThreadSpec()->SetIndex(index);
  else {
    // If we're resetting this to an invalid thread id, then don't make an
    // options pointer just to do that.
    if (m_options_up != nullptr)
      m_options_up->GetThreadSpec()->SetIndex(index);
  }
  SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
}

uint32_t BreakpointLocation::GetThreadIndex() const {
  const ThreadSpec *thread_spec =
      GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
          .GetThreadSpecNoCreate();
  if (thread_spec)
    return thread_spec->GetIndex();
  return 0;
}

void BreakpointLocation::SetThreadName(const char *thread_name) {
  if (thread_name != nullptr)
    GetLocationOptions().GetThreadSpec()->SetName(thread_name);
  else {
    // If we're resetting this to an invalid thread id, then don't make an
    // options pointer just to do that.
    if (m_options_up != nullptr)
      m_options_up->GetThreadSpec()->SetName(thread_name);
  }
  SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
}

const char *BreakpointLocation::GetThreadName() const {
  const ThreadSpec *thread_spec =
      GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
          .GetThreadSpecNoCreate();
  if (thread_spec)
    return thread_spec->GetName();
  return nullptr;
}

void BreakpointLocation::SetQueueName(const char *queue_name) {
  if (queue_name != nullptr)
    GetLocationOptions().GetThreadSpec()->SetQueueName(queue_name);
  else {
    // If we're resetting this to an invalid thread id, then don't make an
    // options pointer just to do that.
    if (m_options_up != nullptr)
      m_options_up->GetThreadSpec()->SetQueueName(queue_name);
  }
  SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
}

const char *BreakpointLocation::GetQueueName() const {
  const ThreadSpec *thread_spec =
      GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
          .GetThreadSpecNoCreate();
  if (thread_spec)
    return thread_spec->GetQueueName();
  return nullptr;
}

bool BreakpointLocation::InvokeCallback(StoppointCallbackContext *context) {
  if (m_options_up != nullptr && m_options_up->HasCallback())
    return m_options_up->InvokeCallback(context, m_owner.GetID(), GetID());
  return m_owner.InvokeCallback(context, GetID());
}

bool BreakpointLocation::IsCallbackSynchronous() {
  if (m_options_up != nullptr && m_options_up->HasCallback())
    return m_options_up->IsCallbackSynchronous();
  return m_owner.GetOptions().IsCallbackSynchronous();
}

void BreakpointLocation::SetCallback(BreakpointHitCallback callback,
                                     void *baton, bool is_synchronous) {
  // The default "Baton" class will keep a copy of "baton" and won't free or
  // delete it when it goes out of scope.
  GetLocationOptions().SetCallback(
      callback, std::make_shared<UntypedBaton>(baton), is_synchronous);
  SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged);
}

void BreakpointLocation::SetCallback(BreakpointHitCallback callback,
                                     const BatonSP &baton_sp,
                                     bool is_synchronous) {
  GetLocationOptions().SetCallback(callback, baton_sp, is_synchronous);
  SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged);
}

void BreakpointLocation::ClearCallback() {
  GetLocationOptions().ClearCallback();
}

void BreakpointLocation::SetCondition(StopCondition condition) {
  GetLocationOptions().SetCondition(std::move(condition));
  SendBreakpointLocationChangedEvent(eBreakpointEventTypeConditionChanged);
}

const StopCondition &BreakpointLocation::GetCondition() const {
  return GetOptionsSpecifyingKind(BreakpointOptions::eCondition).GetCondition();
}

bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx,
                                           Status &error) {
  Log *log = GetLog(LLDBLog::Breakpoints);

  std::lock_guard<std::mutex> guard(m_condition_mutex);

  StopCondition condition = GetCondition();

  if (!condition) {
    m_user_expression_sp.reset();
    return false;
  }

  error.Clear();

  DiagnosticManager diagnostics;

  if (condition.GetHash() != m_condition_hash || !m_user_expression_sp ||
      !m_user_expression_sp->IsParseCacheable() ||
      !m_user_expression_sp->MatchesContext(exe_ctx)) {
    LanguageType language = condition.GetLanguage();
    if (language == lldb::eLanguageTypeUnknown) {
      // See if we can figure out the language from the frame, otherwise use the
      // default language:
      if (CompileUnit *comp_unit =
              m_address.CalculateSymbolContextCompileUnit())
        language = comp_unit->GetLanguage();
    }

    m_user_expression_sp.reset(GetTarget().GetUserExpressionForLanguage(
        condition.GetText(), llvm::StringRef(), SourceLanguage{language},
        Expression::eResultTypeAny, EvaluateExpressionOptions(), nullptr,
        error));
    if (error.Fail()) {
      LLDB_LOGF(log, "Error getting condition expression: %s.",
                error.AsCString());
      m_user_expression_sp.reset();
      return true;
    }

    if (!m_user_expression_sp->Parse(diagnostics, exe_ctx,
                                     eExecutionPolicyOnlyWhenNeeded, true,
                                     false)) {
      error = Status::FromError(
          diagnostics.GetAsError(lldb::eExpressionParseError,
                                 "Couldn't parse conditional expression:"));

      m_user_expression_sp.reset();
      return true;
    }

    m_condition_hash = condition.GetHash();
  }

  // We need to make sure the user sees any parse errors in their condition, so
  // we'll hook the constructor errors up to the debugger's Async I/O.

  ValueObjectSP result_value_sp;

  EvaluateExpressionOptions options;
  options.SetUnwindOnError(true);
  options.SetIgnoreBreakpoints(true);
  options.SetTryAllThreads(true);
  options.SetSuppressPersistentResult(
      true); // Don't generate a user variable for condition expressions.

  Status expr_error;

  diagnostics.Clear();

  ExpressionVariableSP result_variable_sp;

  ExpressionResults result_code = m_user_expression_sp->Execute(
      diagnostics, exe_ctx, options, m_user_expression_sp, result_variable_sp);

  bool ret;

  if (result_code == eExpressionCompleted) {
    if (!result_variable_sp) {
      error = Status::FromErrorString("Expression did not return a result");
      return false;
    }

    result_value_sp = result_variable_sp->GetValueObject();

    if (result_value_sp) {
      ret = result_value_sp->IsLogicalTrue(error);
      if (log) {
        if (error.Success()) {
          LLDB_LOGF(log, "Condition successfully evaluated, result is %s.\n",
                    ret ? "true" : "false");
        } else {
          error = Status::FromErrorString(
              "Failed to get an integer result from the expression");
          ret = false;
        }
      }
    } else {
      ret = false;
      error = Status::FromErrorString(
          "Failed to get any result from the expression");
    }
  } else {
    ret = false;
    error = Status::FromError(diagnostics.GetAsError(
        lldb::eExpressionParseError, "Couldn't execute expression:"));
  }

  return ret;
}

uint32_t BreakpointLocation::GetIgnoreCount() const {
  return GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
      .GetIgnoreCount();
}

void BreakpointLocation::SetIgnoreCount(uint32_t n) {
  GetLocationOptions().SetIgnoreCount(n);
  SendBreakpointLocationChangedEvent(eBreakpointEventTypeIgnoreChanged);
}

void BreakpointLocation::DecrementIgnoreCount() {
  if (m_options_up != nullptr) {
    uint32_t loc_ignore = m_options_up->GetIgnoreCount();
    if (loc_ignore != 0)
      m_options_up->SetIgnoreCount(loc_ignore - 1);
  }
}

bool BreakpointLocation::IgnoreCountShouldStop() {
  uint32_t owner_ignore = GetBreakpoint().GetIgnoreCount();
  uint32_t loc_ignore = 0;
  if (m_options_up != nullptr)
    loc_ignore = m_options_up->GetIgnoreCount();

  if (loc_ignore != 0 || owner_ignore != 0) {
    m_owner.DecrementIgnoreCount();
    DecrementIgnoreCount(); // Have to decrement our owners' ignore count,
                            // since it won't get a chance to.
    return false;
  }
  return true;
}

BreakpointOptions &BreakpointLocation::GetLocationOptions() {
  // If we make the copy we don't copy the callbacks because that is
  // potentially expensive and we don't want to do that for the simple case
  // where someone is just disabling the location.
  if (m_options_up == nullptr)
    m_options_up = std::make_unique<BreakpointOptions>(false);

  return *m_options_up;
}

bool BreakpointLocation::ValidForThisThread(Thread &thread) {
  return thread.MatchesSpec(
      GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
          .GetThreadSpecNoCreate());
}

BreakpointLocationSP
BreakpointLocation::WasHit(StoppointCallbackContext *context) {
  // Only the BreakpointResolverScripted provides WasHit.
  BreakpointResolverSP resolver_sp = GetBreakpoint().GetResolver();
  BreakpointResolverScripted *scripted =
      llvm::dyn_cast<BreakpointResolverScripted>(resolver_sp.get());
  if (!scripted)
    return shared_from_this();

  StackFrameSP frame_sp = context->exe_ctx_ref.GetFrameSP();
  if (!frame_sp)
    return shared_from_this();

  BreakpointLocationSP return_loc_sp =
      scripted->WasHit(frame_sp, shared_from_this());
  // If this is a facade location, then we won't have bumped its hit count
  // while processing the original location hit.  Do so here.  We don't need
  // to bump the breakpoint's hit count, however, since hitting the real
  // location would have already done that.
  // Also we have to check the enabled state here, since we would never have
  // gotten here with a real location...
  if (return_loc_sp && return_loc_sp->IsFacade()) {
    if (return_loc_sp->IsEnabled())
      return_loc_sp->m_hit_counter.Increment();
    else
      return {};
  }
  return return_loc_sp;
}

// RETURNS - true if we should stop at this breakpoint, false if we
// should continue.  Note, we don't check the thread spec for the breakpoint
// here, since if the breakpoint is not for this thread, then the event won't
// even get reported, so the check is redundant.

bool BreakpointLocation::ShouldStop(StoppointCallbackContext *context,
                                    lldb::BreakpointLocationSP &facade_loc_sp) {
  bool should_stop = true;
  Log *log = GetLog(LLDBLog::Breakpoints);

  // Do this first, if a location is disabled, it shouldn't increment its hit
  // count.
  if (!IsEnabled())
    return false;

  // Next check WasHit:
  BreakpointLocationSP loc_hit_sp = WasHit(context);

  if (!loc_hit_sp) {
    // We bump the hit counts in StopInfoBreakpoint::ShouldStopSynchronous,
    // before we call into each location's ShouldStop.  So we need to undo
    // that here.
    UndoBumpHitCount();
    return false;
  }

  // If the location hit was not us, it was a facade location, in which case
  // we should use the facade location's callbacks, etc.  Those will all be
  // run in the asynchronous phase, so for now we just have to record the fact
  // that we should treat this as a facade hit.  This is strictly an out
  // parameter, so clear it if this isn't a facade hit.
  if (loc_hit_sp.get() != this)
    facade_loc_sp = loc_hit_sp;
  else
    facade_loc_sp.reset();

  // We only run synchronous callbacks in ShouldStop:
  context->is_synchronous = true;
  should_stop = InvokeCallback(context);

  if (log) {
    StreamString s;
    GetDescription(&s, lldb::eDescriptionLevelVerbose);
    LLDB_LOGF(log, "Hit breakpoint location: %s, %s.\n", s.GetData(),
              should_stop ? "stopping" : "continuing");
    if (facade_loc_sp) {
      s.Clear();
      facade_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
      LLDB_LOGF(log, "Attributing to facade location: %s.\n", s.GetData());
    }
  }

  return should_stop;
}

void BreakpointLocation::BumpHitCount() {
  if (IsEnabled()) {
    // Step our hit count, and also step the hit count of the owner.
    m_hit_counter.Increment();
    m_owner.m_hit_counter.Increment();
  }
}

void BreakpointLocation::UndoBumpHitCount() {
  if (IsEnabled()) {
    // Step our hit count, and also step the hit count of the owner.
    m_hit_counter.Decrement();
    m_owner.m_hit_counter.Decrement();
  }
}

bool BreakpointLocation::IsResolved() const {

  bool has_site = m_bp_site_sp.get() != nullptr;
  // Facade locations are currently always considered resolved.
  return has_site || IsFacade();
}

lldb::BreakpointSiteSP BreakpointLocation::GetBreakpointSite() const {
  return m_bp_site_sp;
}

llvm::Error BreakpointLocation::ResolveBreakpointSite() {
  // This might be a facade location, which doesn't have an address.
  // In that case, don't attempt to make a site.
  if (m_bp_site_sp || IsFacade())
    return llvm::Error::success();

  Process *process = m_owner.GetTarget().GetProcessSP().get();
  if (process == nullptr)
    return llvm::createStringError("no process");

  lldb::break_id_t new_id =
      process->CreateBreakpointSite(shared_from_this(), m_owner.IsHardware());

  if (new_id == LLDB_INVALID_BREAK_ID)
    return llvm::createStringError(
        llvm::formatv("Failed to add breakpoint site at {0:x}",
                      m_address.GetOpcodeLoadAddress(&m_owner.GetTarget())));

  if (!IsResolved())
    return llvm::createStringError(
        "breakpoint site created but location is still unresolved");

  return llvm::Error::success();
}

bool BreakpointLocation::SetBreakpointSite(BreakpointSiteSP &bp_site_sp) {
  m_bp_site_sp = bp_site_sp;
  SendBreakpointLocationChangedEvent(eBreakpointEventTypeLocationsResolved);
  return true;
}

llvm::Error BreakpointLocation::ClearBreakpointSite() {
  if (!m_bp_site_sp) {
    // This might be a Facade Location, which don't have sites or addresses
    if (IsFacade())
      return llvm::Error::success();
    return llvm::createStringError("no breakpoint site to clear");
  }

  // If the process exists, get it to remove the owner, it will remove the
  // physical implementation of the breakpoint as well if there are no more
  // owners.  Otherwise just remove this owner.
  if (ProcessSP process_sp = m_owner.GetTarget().GetProcessSP())
    process_sp->RemoveConstituentFromBreakpointSite(GetBreakpoint().GetID(),
                                                    GetID(), m_bp_site_sp);
  else
    m_bp_site_sp->RemoveConstituent(GetBreakpoint().GetID(), GetID());

  m_bp_site_sp.reset();
  return llvm::Error::success();
}

void BreakpointLocation::GetDescription(Stream *s,
                                        lldb::DescriptionLevel level) {
  SymbolContext sc;

  // If this is a scripted breakpoint, give it a chance to describe its
  // locations:
  std::optional<std::string> scripted_opt;
  BreakpointResolverSP resolver_sp = GetBreakpoint().GetResolver();
  BreakpointResolverScripted *scripted =
      llvm::dyn_cast<BreakpointResolverScripted>(resolver_sp.get());
  if (scripted)
    scripted_opt = scripted->GetLocationDescription(shared_from_this(), level);

  bool is_scripted_desc = scripted_opt.has_value();

  // If the description level is "initial" then the breakpoint is printing out
  // our initial state, and we should let it decide how it wants to print our
  // label.
  if (level != eDescriptionLevelInitial) {
    s->Indent();
    BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
  }

  if (level == lldb::eDescriptionLevelBrief)
    return;

  if (level != eDescriptionLevelInitial)
    s->PutCString(": ");

  if (level == lldb::eDescriptionLevelVerbose)
    s->IndentMore();

  if (is_scripted_desc) {
    s->PutCString(scripted_opt->c_str());
  } else if (m_address.IsSectionOffset()) {
    m_address.CalculateSymbolContext(&sc);

    if (level == lldb::eDescriptionLevelFull ||
        level == eDescriptionLevelInitial) {
      if (IsReExported())
        s->PutCString("re-exported target = ");
      else
        s->PutCString("where = ");

      // If there's a preferred line entry for printing, use that.
      bool show_function_info = true;
      if (auto preferred = GetPreferredLineEntry()) {
        sc.line_entry = *preferred;
        // FIXME: We're going to get the function name wrong when the preferred
        // line entry is not the lowest one.  For now, just leave the function
        // out in this case, but we really should also figure out how to easily
        // fake the function name here.
        show_function_info = false;
      }
      sc.DumpStopContext(s, m_owner.GetTarget().GetProcessSP().get(), m_address,
                         false, true, false, show_function_info,
                         show_function_info, show_function_info);
    } else {
      if (sc.module_sp) {
        s->EOL();
        s->Indent("module = ");
        sc.module_sp->GetFileSpec().Dump(s->AsRawOstream());
      }

      if (sc.comp_unit != nullptr) {
        s->EOL();
        s->Indent("compile unit = ");
        s->PutCString(sc.comp_unit->GetPrimaryFile().GetFilename());

        if (sc.function != nullptr) {
          s->EOL();
          s->Indent("function = ");
          s->PutCString(sc.function->GetName().AsCString("<unknown>"));
          if (ConstString mangled_name =
                  sc.function->GetMangled().GetMangledName()) {
            s->EOL();
            s->Indent("mangled function = ");
            s->PutCString(mangled_name);
          }
        }

        if (sc.line_entry.line > 0) {
          s->EOL();
          s->Indent("location = ");
          if (auto preferred = GetPreferredLineEntry())
            preferred->DumpStopContext(s, true);
          else
            sc.line_entry.DumpStopContext(s, true);
        }

      } else {
        // If we don't have a comp unit, see if we have a symbol we can print.
        if (sc.symbol) {
          s->EOL();
          if (IsReExported())
            s->Indent("re-exported target = ");
          else
            s->Indent("symbol = ");
          s->PutCString(sc.symbol->GetName().AsCString("<unknown>"));
        }
      }
    }
  }

  if (level == lldb::eDescriptionLevelVerbose) {
    s->EOL();
    s->Indent();
  }

  if (!is_scripted_desc) {
    if (m_address.IsSectionOffset() &&
        (level == eDescriptionLevelFull || level == eDescriptionLevelInitial))
      s->PutCString(", ");
    s->PutCString("address = ");

    ExecutionContextScope *exe_scope = nullptr;
    Target *target = &m_owner.GetTarget();
    if (target)
      exe_scope = target->GetProcessSP().get();
    if (exe_scope == nullptr)
      exe_scope = target;

    if (level == eDescriptionLevelInitial)
      m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,
                     Address::DumpStyleFileAddress);
    else
      m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,
                     Address::DumpStyleModuleWithFileAddress);

    if (IsIndirect() && m_bp_site_sp) {
      Address resolved_address;
      resolved_address.SetLoadAddress(m_bp_site_sp->GetLoadAddress(), target);
      const Symbol *resolved_symbol =
          resolved_address.CalculateSymbolContextSymbol();
      if (resolved_symbol) {
        if (level == eDescriptionLevelFull || level == eDescriptionLevelInitial)
          s->PutCString(", ");
        else if (level == lldb::eDescriptionLevelVerbose) {
          s->EOL();
          s->Indent();
        }
        s->Printf("indirect target = %s",
                  resolved_symbol->GetName().GetCString());
      }
    }
  }

  // FIXME: scripted breakpoint are currently always resolved.  Does this seem
  // right? If they don't add any scripted locations, we shouldn't consider them
  // resolved.
  bool is_resolved = is_scripted_desc || IsResolved();
  // A scripted breakpoint might be resolved but not have a site.  Be sure to
  // check for that.
  bool is_hardware = !is_scripted_desc && IsResolved() && m_bp_site_sp &&
                     m_bp_site_sp->IsHardware();

  if (level == lldb::eDescriptionLevelVerbose) {
    s->EOL();
    s->Indent();
    s->Printf("resolved = %s\n", is_resolved ? "true" : "false");
    s->Indent();
    s->Printf("hardware = %s\n", is_hardware ? "true" : "false");
    s->Indent();
    s->Printf("hit count = %-4u\n", GetHitCount());

    if (m_options_up) {
      s->Indent();
      m_options_up->GetDescription(s, level);
      s->EOL();
    }
    s->IndentLess();
  } else if (level != eDescriptionLevelInitial) {
    s->Printf(", %sresolved, %shit count = %u ", (is_resolved ? "" : "un"),
              (is_hardware ? "hardware, " : ""), GetHitCount());
    if (m_options_up) {
      m_options_up->GetDescription(s, level);
    }
  }
}

void BreakpointLocation::Dump(Stream *s) const {
  if (s == nullptr)
    return;

  bool is_resolved = IsResolved();
  bool is_hardware = is_resolved && m_bp_site_sp->IsHardware();

  lldb::tid_t tid = GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
                        .GetThreadSpecNoCreate()
                        ->GetTID();
  s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64
            "  load addr = 0x%8.8" PRIx64 "  state = %s  type = %s breakpoint  "
            "hit_count = %-4u  ignore_count = %-4u",
            GetID(), tid,
            (uint64_t)m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()),
            (m_options_up ? m_options_up->IsEnabled() : m_owner.IsEnabled())
                ? "enabled "
                : "disabled",
            is_hardware ? "hardware" : "software", GetHitCount(),
            GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
                .GetIgnoreCount());
}

void BreakpointLocation::SendBreakpointLocationChangedEvent(
    lldb::BreakpointEventType eventKind) {
  if (!m_owner.IsInternal()) {
    auto data_sp = std::make_shared<Breakpoint::BreakpointEventData>(
        eventKind, m_owner.shared_from_this());
    data_sp->GetBreakpointLocationCollection().Add(shared_from_this());
    m_owner.GetTarget().NotifyBreakpointChanged(m_owner, data_sp);
  }
}

std::optional<uint32_t> BreakpointLocation::GetSuggestedStackFrameIndex() {
  auto preferred_opt = GetPreferredLineEntry();
  if (!preferred_opt)
    return {};
  LineEntry preferred = *preferred_opt;
  SymbolContext sc;
  if (!m_address.CalculateSymbolContext(&sc))
    return {};
  // Don't return anything special if frame 0 is the preferred line entry.
  // We not really telling the stack frame list to do anything special in that
  // case.
  if (!LineEntry::Compare(sc.line_entry, preferred))
    return {};

  if (!sc.block)
    return {};

  // Blocks have their line info in Declaration form, so make one here:
  Declaration preferred_decl(preferred.GetFile(), preferred.line,
                             preferred.column);

  uint32_t depth = 0;
  Block *inlined_block = sc.block->GetContainingInlinedBlock();
  while (inlined_block) {
    // If we've moved to a block that this isn't the start of, that's not
    // our inlining info or call site, so we can stop here.
    Address start_address;
    if (!inlined_block->GetStartAddress(start_address) ||
        start_address != m_address)
      return {};

    const InlineFunctionInfo *info = inlined_block->GetInlinedFunctionInfo();
    if (info) {
      if (preferred_decl == info->GetDeclaration())
        return depth;
      if (preferred_decl == info->GetCallSite())
        return depth + 1;
    }
    inlined_block = inlined_block->GetInlinedParent();
    depth++;
  }
  return {};
}

void BreakpointLocation::SwapLocation(BreakpointLocationSP swap_from) {
  m_address = swap_from->m_address;
  m_should_resolve_indirect_functions =
      swap_from->m_should_resolve_indirect_functions;
  m_is_reexported = swap_from->m_is_reexported;
  m_is_indirect = swap_from->m_is_indirect;
  m_user_expression_sp.reset();
}

void BreakpointLocation::SetThreadIDInternal(lldb::tid_t thread_id) {
  if (thread_id != LLDB_INVALID_THREAD_ID) {
    GetLocationOptions().SetThreadID(thread_id);
  } else {
    // If we're resetting this to an invalid thread id, then don't make an
    // options pointer just to do that.
    if (m_options_up != nullptr)
      m_options_up->SetThreadID(thread_id);
  }
}
