//===-- SBThread.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/API/SBThread.h"
#include "Utils.h"
#include "lldb/API/SBAddress.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBFormat.h"
#include "lldb/API/SBFrame.h"
#include "lldb/API/SBFrameList.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBStructuredData.h"
#include "lldb/API/SBSymbolContext.h"
#include "lldb/API/SBThreadCollection.h"
#include "lldb/API/SBThreadPlan.h"
#include "lldb/API/SBValue.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Queue.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanStepInRange.h"
#include "lldb/Target/ThreadPlanStepInstruction.h"
#include "lldb/Target/ThreadPlanStepOut.h"
#include "lldb/Target/ThreadPlanStepRange.h"
#include "lldb/Utility/Instrumentation.h"
#include "lldb/Utility/State.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/ValueObject/ValueObject.h"
#include "lldb/lldb-enumerations.h"

#include <memory>

using namespace lldb;
using namespace lldb_private;

const char *SBThread::GetBroadcasterClassName() {
  LLDB_INSTRUMENT();

  return ConstString(Thread::GetStaticBroadcasterClass()).AsCString(nullptr);
}

// Constructors
SBThread::SBThread() : m_opaque_sp(new ExecutionContextRef()) {
  LLDB_INSTRUMENT_VA(this);
}

SBThread::SBThread(const ThreadSP &lldb_object_sp)
    : m_opaque_sp(new ExecutionContextRef(lldb_object_sp)) {
  LLDB_INSTRUMENT_VA(this, lldb_object_sp);
}

SBThread::SBThread(const SBThread &rhs) {
  LLDB_INSTRUMENT_VA(this, rhs);

  m_opaque_sp = clone(rhs.m_opaque_sp);
}

// Assignment operator

const lldb::SBThread &SBThread::operator=(const SBThread &rhs) {
  LLDB_INSTRUMENT_VA(this, rhs);

  if (this != &rhs)
    m_opaque_sp = clone(rhs.m_opaque_sp);
  return *this;
}

// Destructor
SBThread::~SBThread() = default;

lldb::SBQueue SBThread::GetQueue() const {
  LLDB_INSTRUMENT_VA(this);

  SBQueue sb_queue;
  QueueSP queue_sp;
  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBQueue();
  }

  if (exe_ctx->HasThreadScope()) {
    queue_sp = exe_ctx->GetThreadPtr()->GetQueue();
    if (queue_sp) {
      sb_queue.SetQueue(queue_sp);
    }
  }

  return sb_queue;
}

bool SBThread::IsValid() const {
  LLDB_INSTRUMENT_VA(this);
  return this->operator bool();
}
SBThread::operator bool() const {
  LLDB_INSTRUMENT_VA(this);
  if (!m_opaque_sp)
    return false;

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return false;
  }

  return m_opaque_sp->GetThreadSP().get() != nullptr;
}

void SBThread::Clear() {
  LLDB_INSTRUMENT_VA(this);

  m_opaque_sp->Clear();
}

StopReason SBThread::GetStopReason() {
  LLDB_INSTRUMENT_VA(this);

  StopReason reason = eStopReasonInvalid;
  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return reason;
  }

  if (exe_ctx->HasThreadScope())
    return exe_ctx->GetThreadPtr()->GetStopReason();

  return reason;
}

size_t SBThread::GetStopReasonDataCount() {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (exe_ctx) {
    if (exe_ctx->HasThreadScope()) {
      StopInfoSP stop_info_sp = exe_ctx->GetThreadPtr()->GetStopInfo();
      if (stop_info_sp)
        return stop_info_sp->GetStopReasonDataCount();
    }
  } else {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return 0;
  }
  return 0;
}

uint64_t SBThread::GetStopReasonDataAtIndex(uint32_t idx) {
  LLDB_INSTRUMENT_VA(this, idx);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (exe_ctx) {
    if (exe_ctx->HasThreadScope()) {
      Thread *thread = exe_ctx->GetThreadPtr();
      StopInfoSP stop_info_sp = thread->GetStopInfo();
      if (stop_info_sp)
        return stop_info_sp->GetStopReasonDataAtIndex(idx);
    }
  } else {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return 0;
  }
  return 0;
}

bool SBThread::GetStopReasonExtendedInfoAsJSON(lldb::SBStream &stream) {
  LLDB_INSTRUMENT_VA(this, stream);

  Stream &strm = stream.ref();

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return false;
  }

  if (!exe_ctx->HasThreadScope())
    return false;

  StopInfoSP stop_info = exe_ctx->GetThreadPtr()->GetStopInfo();
  StructuredData::ObjectSP info = stop_info->GetExtendedInfo();
  if (!info)
    return false;

  info->Dump(strm);

  return true;
}

SBThreadCollection
SBThread::GetStopReasonExtendedBacktraces(InstrumentationRuntimeType type) {
  LLDB_INSTRUMENT_VA(this, type);

  SBThreadCollection threads;

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBThreadCollection();
  }

  if (!exe_ctx->HasThreadScope())
    return SBThreadCollection();

  ProcessSP process_sp = exe_ctx->GetProcessSP();

  StopInfoSP stop_info = exe_ctx->GetThreadPtr()->GetStopInfo();
  StructuredData::ObjectSP info = stop_info->GetExtendedInfo();
  if (!info)
    return threads;

  threads = process_sp->GetInstrumentationRuntime(type)
                ->GetBacktracesFromExtendedStopInfo(info);
  return threads;
}

bool SBThread::GetStopDescription(lldb::SBStream &stream) const {
  LLDB_INSTRUMENT_VA(this, stream);

  if (!m_opaque_sp)
    return false;

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return false;
  }

  if (!exe_ctx->HasThreadScope())
    return false;

  Stream &strm = stream.ref();
  const std::string stop_desc = exe_ctx->GetThreadPtr()->GetStopDescription();
  strm.PutCString(stop_desc);

  return true;
}

size_t SBThread::GetStopDescription(char *dst_or_null, size_t dst_len) {
  LLDB_INSTRUMENT_VA(this, dst_or_null, dst_len);

  if (dst_or_null)
    *dst_or_null = 0;

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return 0;
  }

  if (!exe_ctx->HasThreadScope())
    return 0;

  std::string thread_stop_desc = exe_ctx->GetThreadPtr()->GetStopDescription();
  if (thread_stop_desc.empty())
    return 0;

  if (dst_or_null)
    return ::snprintf(dst_or_null, dst_len, "%s", thread_stop_desc.c_str()) + 1;

  // NULL dst passed in, return the length needed to contain the
  // description.
  return thread_stop_desc.size() + 1; // Include the NULL byte for size
}

SBValue SBThread::GetStopReturnValue() {
  LLDB_INSTRUMENT_VA(this);

  ValueObjectSP return_valobj_sp;
  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBValue();
  }

  if (exe_ctx->HasThreadScope()) {
    StopInfoSP stop_info_sp = exe_ctx->GetThreadPtr()->GetStopInfo();
    if (stop_info_sp) {
      return_valobj_sp = StopInfo::GetReturnValueObject(stop_info_sp);
    }
  }

  return SBValue(return_valobj_sp);
}

void SBThread::SetThread(const ThreadSP &lldb_object_sp) {
  m_opaque_sp->SetThreadSP(lldb_object_sp);
}

lldb::tid_t SBThread::GetThreadID() const {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return LLDB_INVALID_THREAD_ID;
  }

  ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
  if (thread_sp)
    return thread_sp->GetID();
  return LLDB_INVALID_THREAD_ID;
}

uint32_t SBThread::GetIndexID() const {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return LLDB_INVALID_INDEX32;
  }

  ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
  if (thread_sp)
    return thread_sp->GetIndexID();
  return LLDB_INVALID_INDEX32;
}

const char *SBThread::GetName() const {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return nullptr;
  }

  if (!exe_ctx->HasThreadScope())
    return nullptr;

  return ConstString(exe_ctx->GetThreadPtr()->GetName()).GetCString();
}

const char *SBThread::GetQueueName() const {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return nullptr;
  }

  if (!exe_ctx->HasThreadScope())
    return nullptr;

  return ConstString(exe_ctx->GetThreadPtr()->GetQueueName()).GetCString();
}

lldb::queue_id_t SBThread::GetQueueID() const {
  LLDB_INSTRUMENT_VA(this);

  queue_id_t id = LLDB_INVALID_QUEUE_ID;
  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return id;
  }

  if (exe_ctx->HasThreadScope()) {
    id = exe_ctx->GetThreadPtr()->GetQueueID();
  }

  return id;
}

bool SBThread::GetInfoItemByPathAsString(const char *path, SBStream &strm) {
  LLDB_INSTRUMENT_VA(this, path, strm);

  bool success = false;
  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (exe_ctx) {
    if (exe_ctx->HasThreadScope()) {
      Thread *thread = exe_ctx->GetThreadPtr();
      StructuredData::ObjectSP info_root_sp = thread->GetExtendedInfo();
      if (info_root_sp) {
        StructuredData::ObjectSP node =
            info_root_sp->GetObjectForDotSeparatedPath(path);
        if (node) {
          if (node->GetType() == eStructuredDataTypeString) {
            strm.ref() << node->GetAsString()->GetValue();
            success = true;
          }
          if (node->GetType() == eStructuredDataTypeInteger) {
            strm.Printf("0x%" PRIx64, node->GetUnsignedIntegerValue());
            success = true;
          }
          if (node->GetType() == eStructuredDataTypeFloat) {
            strm.Printf("0x%f", node->GetAsFloat()->GetValue());
            success = true;
          }
          if (node->GetType() == eStructuredDataTypeBoolean) {
            if (node->GetAsBoolean()->GetValue())
              strm.Printf("true");
            else
              strm.Printf("false");
            success = true;
          }
          if (node->GetType() == eStructuredDataTypeNull) {
            strm.Printf("null");
            success = true;
          }
        }
      }
    }
  } else {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return success;
  }

  return success;
}

static Status ResumeNewPlan(StoppedExecutionContext exe_ctx,
                            ThreadPlan *new_plan) {
  Thread *thread = exe_ctx.GetThreadPtr();
  if (!thread)
    return Status::FromErrorString("No thread in SBThread::ResumeNewPlan");

  // User level plans should be Controlling Plans so they can be interrupted,
  // other plans executed, and then a "continue" will resume the plan.
  if (new_plan != nullptr) {
    new_plan->SetIsControllingPlan(true);
    new_plan->SetOkayToDiscard(false);
  }

  // Why do we need to set the current thread by ID here???
  Process *process = exe_ctx.GetProcessPtr();
  process->GetThreadList().SetSelectedThreadByID(thread->GetID());

  // Release the run lock but keep the API lock.
  TargetAPIMutex api_mutex = exe_ctx.AllowResume();
  std::unique_lock<TargetAPIMutex> guard(api_mutex, std::adopt_lock);
  if (process->GetTarget().GetDebugger().GetAsyncExecution())
    return process->Resume();
  return process->ResumeSynchronous(nullptr);
}

void SBThread::StepOver(lldb::RunMode stop_other_threads) {
  LLDB_INSTRUMENT_VA(this, stop_other_threads);

  SBError error; // Ignored
  StepOver(stop_other_threads, error);
}

void SBThread::StepOver(lldb::RunMode stop_other_threads, SBError &error) {
  LLDB_INSTRUMENT_VA(this, stop_other_threads, error);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    error = Status::FromError(exe_ctx.takeError());
    return;
  }

  if (!exe_ctx->HasThreadScope()) {
    error = Status::FromErrorString("this SBThread object is invalid");
    return;
  }

  Thread *thread = exe_ctx->GetThreadPtr();
  bool abort_other_plans = false;
  StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
  if (!frame_sp) {
    error.SetErrorString("No frame to step over");
    return;
  }

  ThreadPlanSP new_plan_sp;
  lldb::StepType step_type =
      frame_sp->HasDebugInformation() || frame_sp->IsSynthetic()
          ? eStepTypeOver
          : eStepTypeTraceOver;

  llvm::Expected<lldb::ThreadPlanSP> frame_plan_result =
      frame_sp->GetThreadPlanForStepType(step_type);
  if (auto llvm_err = frame_plan_result.takeError()) {
    error.SetErrorStringWithFormat("scripted frame provider got an error "
                                   "while constructing step plan: \"%s\"",
                                   llvm::toString(std::move(llvm_err)).c_str());
    return;
  }
  new_plan_sp = *frame_plan_result;

  if (new_plan_sp) {
    thread->QueueThreadPlan(new_plan_sp, false);
  } else {
    Status new_plan_status;
    if (step_type == eStepTypeOver) {
      const LazyBool avoid_no_debug = eLazyBoolCalculate;
      SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
      new_plan_sp = thread->QueueThreadPlanForStepOverRange(
          abort_other_plans, sc.line_entry, sc, stop_other_threads,
          new_plan_status, avoid_no_debug);
    } else {
      new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
          true, abort_other_plans, stop_other_threads, new_plan_status);
    }
  }
  error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get());
}

void SBThread::StepInto(lldb::RunMode stop_other_threads) {
  LLDB_INSTRUMENT_VA(this, stop_other_threads);

  StepInto(nullptr, stop_other_threads);
}

void SBThread::StepInto(const char *target_name,
                        lldb::RunMode stop_other_threads) {
  LLDB_INSTRUMENT_VA(this, target_name, stop_other_threads);

  SBError error; // Ignored
  StepInto(target_name, LLDB_INVALID_LINE_NUMBER, error, stop_other_threads);
}

void SBThread::StepInto(const char *target_name, uint32_t end_line,
                        SBError &error, lldb::RunMode stop_other_threads) {
  LLDB_INSTRUMENT_VA(this, target_name, end_line, error, stop_other_threads);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    error = Status::FromError(exe_ctx.takeError());
    return;
  }

  if (!exe_ctx->HasThreadScope()) {
    error = Status::FromErrorString("this SBThread object is invalid");
    return;
  }

  bool abort_other_plans = false;

  Thread *thread = exe_ctx->GetThreadPtr();
  StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
  ThreadPlanSP new_plan_sp;
  Status new_plan_status;
  lldb::StepType step_type;

  if (frame_sp && (frame_sp->HasDebugInformation() || frame_sp->IsSynthetic()))
    step_type = eStepTypeInto;
  else
    step_type = eStepTypeTrace;

  // First see if the Frame has some special way to do this step:
  if (frame_sp) {
    llvm::Expected<lldb::ThreadPlanSP> frame_plan_result =
        frame_sp->GetThreadPlanForStepType(step_type);
    if (auto llvm_err = frame_plan_result.takeError()) {
      error.SetErrorStringWithFormat(
          "scripted frame provider got an error "
          "while constructing step plan: \"%s\"",
          llvm::toString(std::move(llvm_err)).c_str());
      return;
    }
    new_plan_sp = *frame_plan_result;
  }

  if (new_plan_sp) {
    thread->QueueThreadPlan(new_plan_sp, false);
  } else {
    if (step_type == eStepTypeInto) {
      SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
      AddressRange range;
      if (end_line == LLDB_INVALID_LINE_NUMBER)
        range = sc.line_entry.range;
      else {
        llvm::Error err = sc.GetAddressRangeFromHereToEndLine(end_line, range);
        if (err) {
          error =
              Status::FromErrorString(llvm::toString(std::move(err)).c_str());
          return;
        }
      }

      const LazyBool step_out_avoids_code_without_debug_info =
          eLazyBoolCalculate;
      const LazyBool step_in_avoids_code_without_debug_info =
          eLazyBoolCalculate;
      new_plan_sp = thread->QueueThreadPlanForStepInRange(
          abort_other_plans, range, sc, target_name, stop_other_threads,
          new_plan_status, step_in_avoids_code_without_debug_info,
          step_out_avoids_code_without_debug_info);
    } else {
      new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
          false, abort_other_plans, stop_other_threads, new_plan_status);
    }
  }

  if (new_plan_status.Success())
    error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get());
  else
    error = Status::FromErrorString(new_plan_status.AsCString());
}

void SBThread::StepOut() {
  LLDB_INSTRUMENT_VA(this);

  SBError error; // Ignored
  StepOut(error);
}

void SBThread::StepOut(SBError &error) {
  LLDB_INSTRUMENT_VA(this, error);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    error = Status::FromError(exe_ctx.takeError());
    return;
  }

  if (!exe_ctx->HasThreadScope()) {
    error = Status::FromErrorString("this SBThread object is invalid");
    return;
  }

  bool abort_other_plans = false;
  bool stop_other_threads = false;

  ThreadPlanSP new_plan_sp;

  Thread *thread = exe_ctx->GetThreadPtr();
  StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
  if (frame_sp) {
    llvm::Expected<lldb::ThreadPlanSP> frame_plan_result =
        frame_sp->GetThreadPlanForStepType(eStepTypeOut);
    if (auto llvm_err = frame_plan_result.takeError()) {
      error.SetErrorStringWithFormat(
          "scripted frame provider got an error "
          "while constructing step plan: \"%s\"",
          llvm::toString(std::move(llvm_err)).c_str());
      return;
    }
    new_plan_sp = *frame_plan_result;
  }

  Status new_plan_status;
  if (new_plan_sp) {
    // FIXME: Carry over stop_other_threads, and avoid_no_debug to
    // the new plan?
    thread->QueueThreadPlan(new_plan_sp, false);
  } else {
    const LazyBool avoid_no_debug = eLazyBoolCalculate;
    new_plan_sp = thread->QueueThreadPlanForStepOut(
        abort_other_plans, nullptr, false, stop_other_threads, eVoteYes,
        eVoteNoOpinion, 0, new_plan_status, avoid_no_debug);
  }

  if (new_plan_status.Success())
    error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get());
  else
    error = Status::FromErrorString(new_plan_status.AsCString());
}

void SBThread::StepOutOfFrame(SBFrame &sb_frame) {
  LLDB_INSTRUMENT_VA(this, sb_frame);

  SBError error; // Ignored
  StepOutOfFrame(sb_frame, error);
}

void SBThread::StepOutOfFrame(SBFrame &sb_frame, SBError &error) {
  LLDB_INSTRUMENT_VA(this, sb_frame, error);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    error = Status::FromError(exe_ctx.takeError());
    return;
  }

  if (!sb_frame.IsValid()) {
    error = Status::FromErrorString("passed invalid SBFrame object");
    return;
  }

  StackFrameSP frame_sp(sb_frame.GetFrameSP());

  if (!exe_ctx->HasThreadScope()) {
    error = Status::FromErrorString("this SBThread object is invalid");
    return;
  }

  bool abort_other_plans = false;
  bool stop_other_threads = false;
  Thread *thread = exe_ctx->GetThreadPtr();
  if (sb_frame.GetThread().GetThreadID() != thread->GetID()) {
    error = Status::FromErrorString("passed a frame from another thread");
    return;
  }

  Status new_plan_status;
  ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut(
      abort_other_plans, nullptr, false, stop_other_threads, eVoteYes,
      eVoteNoOpinion, frame_sp->GetFrameIndex(), new_plan_status));

  if (new_plan_status.Success())
    error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get());
  else
    error = Status::FromErrorString(new_plan_status.AsCString());
}

void SBThread::StepInstruction(bool step_over) {
  LLDB_INSTRUMENT_VA(this, step_over);

  SBError error; // Ignored
  StepInstruction(step_over, error);
}

void SBThread::StepInstruction(bool step_over, SBError &error) {
  LLDB_INSTRUMENT_VA(this, step_over, error);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    error = Status::FromError(exe_ctx.takeError());
    return;
  }

  if (!exe_ctx->HasThreadScope()) {
    error = Status::FromErrorString("this SBThread object is invalid");
    return;
  }

  Thread *thread = exe_ctx->GetThreadPtr();
  StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
  lldb::StepType step_type = step_over ? eStepTypeTraceOver : eStepTypeTrace;

  ThreadPlanSP new_plan_sp;

  if (frame_sp) {
    llvm::Expected<lldb::ThreadPlanSP> frame_plan_result =
        frame_sp->GetThreadPlanForStepType(step_type);
    if (auto llvm_err = frame_plan_result.takeError()) {
      error.SetErrorStringWithFormat(
          "scripted frame provider got an error "
          "while constructing step plan: \"%s\"",
          llvm::toString(std::move(llvm_err)).c_str());
      return;
    }
    new_plan_sp = *frame_plan_result;
  }

  Status new_plan_status;
  if (!new_plan_sp)
    new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
        step_over, false, true, new_plan_status);

  if (new_plan_status.Success())
    error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get());
  else
    error = Status::FromErrorString(new_plan_status.AsCString());
}

void SBThread::RunToAddress(lldb::addr_t addr) {
  LLDB_INSTRUMENT_VA(this, addr);

  SBError error; // Ignored
  RunToAddress(addr, error);
}

void SBThread::RunToAddress(lldb::addr_t addr, SBError &error) {
  LLDB_INSTRUMENT_VA(this, addr, error);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    error = Status::FromError(exe_ctx.takeError());
    return;
  }

  if (!exe_ctx->HasThreadScope()) {
    error = Status::FromErrorString("this SBThread object is invalid");
    return;
  }

  bool abort_other_plans = false;
  bool stop_other_threads = true;

  Address target_addr(addr);

  Thread *thread = exe_ctx->GetThreadPtr();

  Status new_plan_status;
  ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForRunToAddress(
      abort_other_plans, target_addr, stop_other_threads, new_plan_status));

  if (new_plan_status.Success())
    error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get());
  else
    error = Status::FromErrorString(new_plan_status.AsCString());
}

SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame,
                                lldb::SBFileSpec &sb_file_spec, uint32_t line) {
  LLDB_INSTRUMENT_VA(this, sb_frame, sb_file_spec, line);

  SBError sb_error;
  char path[PATH_MAX];

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx)
    return Status::FromError(exe_ctx.takeError());

  StackFrameSP frame_sp(sb_frame.GetFrameSP());

  if (exe_ctx->HasThreadScope()) {
    Target *target = exe_ctx->GetTargetPtr();
    Thread *thread = exe_ctx->GetThreadPtr();

    if (line == 0) {
      sb_error = Status::FromErrorString("invalid line argument");
      return sb_error;
    }

    if (!frame_sp) {
      // We don't want to run SelectMostRelevantFrame here, for instance if
      // you called a sequence of StepOverUntil's you wouldn't want the
      // frame changed out from under you because you stepped into a
      // recognized frame.
      frame_sp = thread->GetSelectedFrame(DoNoSelectMostRelevantFrame);
      if (!frame_sp)
        frame_sp = thread->GetStackFrameAtIndex(0);
    }

    SymbolContext frame_sc;
    if (!frame_sp) {
      sb_error = Status::FromErrorString("no valid frames in thread to step");
      return sb_error;
    }

    // If we have a frame, get its line
    frame_sc = frame_sp->GetSymbolContext(
        eSymbolContextCompUnit | eSymbolContextFunction |
        eSymbolContextLineEntry | eSymbolContextSymbol);

    if (frame_sc.comp_unit == nullptr) {
      sb_error = Status::FromErrorStringWithFormat(
          "frame %u doesn't have debug information", frame_sp->GetFrameIndex());
      return sb_error;
    }

    FileSpec step_file_spec;
    if (sb_file_spec.IsValid()) {
      // The file spec passed in was valid, so use it
      step_file_spec = sb_file_spec.ref();
    } else {
      if (frame_sc.line_entry.IsValid())
        step_file_spec = frame_sc.line_entry.GetFile();
      else {
        sb_error = Status::FromErrorString(
            "invalid file argument or no file for frame");
        return sb_error;
      }
    }

    // Grab the current function, then we will make sure the "until" address is
    // within the function.  We discard addresses that are out of the current
    // function, and then if there are no addresses remaining, give an
    // appropriate error message.

    bool all_in_function = true;

    std::vector<addr_t> step_over_until_addrs;
    const bool abort_other_plans = false;
    const bool stop_other_threads = false;
    // TODO: Handle SourceLocationSpec column information
    SourceLocationSpec location_spec(
        step_file_spec, line, /*column=*/std::nullopt, /*check_inlines=*/true,
        /*exact_match=*/false);

    SymbolContextList sc_list;
    frame_sc.comp_unit->ResolveSymbolContext(location_spec,
                                             eSymbolContextLineEntry, sc_list);
    for (const SymbolContext &sc : sc_list) {
      addr_t step_addr =
          sc.line_entry.range.GetBaseAddress().GetLoadAddress(target);
      if (step_addr != LLDB_INVALID_ADDRESS) {
        AddressRange unused_range;
        if (frame_sc.function->GetRangeContainingLoadAddress(step_addr, *target,
                                                             unused_range))
          step_over_until_addrs.push_back(step_addr);
        else
          all_in_function = false;
      }
    }

    if (step_over_until_addrs.empty()) {
      if (all_in_function) {
        step_file_spec.GetPath(path, sizeof(path));
        sb_error = Status::FromErrorStringWithFormat(
            "No line entries for %s:%u", path, line);
      } else
        sb_error = Status::FromErrorString(
            "step until target not in current function");
    } else {
      Status new_plan_status;
      ThreadPlanSP new_plan_sp = thread->QueueThreadPlanForStepUntil(
          abort_other_plans, step_over_until_addrs, stop_other_threads,
          frame_sp->GetFrameIndex(), new_plan_status);

      if (new_plan_status.Success())
        sb_error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get());
      else
        sb_error = Status::FromErrorString(new_plan_status.AsCString());
    }
  } else {
    sb_error = Status::FromErrorString("this SBThread object is invalid");
  }
  return sb_error;
}

SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name) {
  LLDB_INSTRUMENT_VA(this, script_class_name);

  return StepUsingScriptedThreadPlan(script_class_name, true);
}

SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name,
                                            bool resume_immediately) {
  LLDB_INSTRUMENT_VA(this, script_class_name, resume_immediately);

  lldb::SBStructuredData no_data;
  return StepUsingScriptedThreadPlan(script_class_name, no_data,
                                     resume_immediately);
}

SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name,
                                              SBStructuredData &args_data,
                                              bool resume_immediately) {
  LLDB_INSTRUMENT_VA(this, script_class_name, args_data, resume_immediately);

  SBError error;

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx)
    return Status::FromError(exe_ctx.takeError());

  if (!exe_ctx->HasThreadScope()) {
    error = Status::FromErrorString("this SBThread object is invalid");
    return error;
  }

  Thread *thread = exe_ctx->GetThreadPtr();
  Status new_plan_status;
  StructuredData::ObjectSP obj_sp = args_data.m_impl_up->GetObjectSP();

  StructuredData::DictionarySP args_dict_sp;
  if (obj_sp && obj_sp->GetType() == lldb::eStructuredDataTypeDictionary)
    args_dict_sp = std::static_pointer_cast<StructuredData::Dictionary>(obj_sp);

  ScriptedMetadata scripted_metadata(script_class_name, args_dict_sp);
  ThreadPlanSP new_plan_sp = thread->QueueThreadPlanForStepScripted(
      false, scripted_metadata, false, new_plan_status);

  if (new_plan_status.Fail()) {
    error = Status::FromErrorString(new_plan_status.AsCString());
    return error;
  }

  if (!resume_immediately)
    return error;

  if (new_plan_status.Success())
    error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get());
  else
    error = Status::FromErrorString(new_plan_status.AsCString());

  return error;
}

SBError SBThread::JumpToLine(lldb::SBFileSpec &file_spec, uint32_t line) {
  LLDB_INSTRUMENT_VA(this, file_spec, line);

  SBError sb_error;

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx)
    return Status::FromError(exe_ctx.takeError());

  if (!exe_ctx->HasThreadScope()) {
    sb_error = Status::FromErrorString("this SBThread object is invalid");
    return sb_error;
  }

  Thread *thread = exe_ctx->GetThreadPtr();

  Status err = thread->JumpToLine(file_spec.ref(), line, true);
  sb_error.SetError(std::move(err));
  return sb_error;
}

SBError SBThread::ReturnFromFrame(SBFrame &frame, SBValue &return_value) {
  LLDB_INSTRUMENT_VA(this, frame, return_value);

  SBError sb_error;

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx)
    return Status::FromError(exe_ctx.takeError());

  if (exe_ctx->HasThreadScope()) {
    Thread *thread = exe_ctx->GetThreadPtr();
    sb_error.SetError(
        thread->ReturnFromFrame(frame.GetFrameSP(), return_value.GetSP()));
  }

  return sb_error;
}

SBError SBThread::UnwindInnermostExpression() {
  LLDB_INSTRUMENT_VA(this);

  SBError sb_error;

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx)
    return Status::FromError(exe_ctx.takeError());

  if (exe_ctx->HasThreadScope()) {
    Thread *thread = exe_ctx->GetThreadPtr();
    sb_error.SetError(thread->UnwindInnermostExpression());
    if (sb_error.Success())
      thread->SetSelectedFrameByIndex(0, false);
  }

  return sb_error;
}

bool SBThread::Suspend() {
  LLDB_INSTRUMENT_VA(this);

  SBError error; // Ignored
  return Suspend(error);
}

bool SBThread::Suspend(SBError &error) {
  LLDB_INSTRUMENT_VA(this, error);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    error = Status::FromError(exe_ctx.takeError());
    return false;
  }

  bool result = false;
  if (exe_ctx->HasThreadScope()) {
    exe_ctx->GetThreadPtr()->SetResumeState(eStateSuspended);
    result = true;
  } else
    error = Status::FromErrorString("this SBThread object is invalid");
  return result;
}

bool SBThread::Resume() {
  LLDB_INSTRUMENT_VA(this);

  SBError error; // Ignored
  return Resume(error);
}

bool SBThread::Resume(SBError &error) {
  LLDB_INSTRUMENT_VA(this, error);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    error = Status::FromErrorString("process is running");
    return false;
  }

  bool result = false;
  if (exe_ctx->HasThreadScope()) {
    const bool override_suspend = true;
    exe_ctx->GetThreadPtr()->SetResumeState(eStateRunning, override_suspend);
    result = true;
  } else
    error = Status::FromErrorString("this SBThread object is invalid");
  return result;
}

bool SBThread::IsSuspended() {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return false;
  }

  if (exe_ctx->HasThreadScope())
    return exe_ctx->GetThreadPtr()->GetResumeState() == eStateSuspended;
  return false;
}

bool SBThread::IsStopped() {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return false;
  }

  if (exe_ctx->HasThreadScope())
    return StateIsStoppedState(exe_ctx->GetThreadPtr()->GetState(), true);
  return false;
}

SBProcess SBThread::GetProcess() {
  LLDB_INSTRUMENT_VA(this);

  SBProcess sb_process;
  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBProcess();
  }

  if (exe_ctx->HasThreadScope()) {
    // Have to go up to the target so we can get a shared pointer to our
    // process...
    sb_process.SetSP(exe_ctx->GetProcessSP());
  }

  return sb_process;
}

uint32_t SBThread::GetNumFrames() {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return 0;
  }

  if (exe_ctx->HasThreadScope())
    return exe_ctx->GetThreadPtr()->GetStackFrameCount();

  return 0;
}

SBFrame SBThread::GetFrameAtIndex(uint32_t idx) {
  LLDB_INSTRUMENT_VA(this, idx);

  SBFrame sb_frame;
  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBFrame();
  }

  if (exe_ctx->HasThreadScope()) {
    StackFrameSP frame_sp = exe_ctx->GetThreadPtr()->GetStackFrameAtIndex(idx);
    sb_frame.SetFrameSP(frame_sp);
  }

  return sb_frame;
}

lldb::SBFrameList SBThread::GetFrames() const {
  LLDB_INSTRUMENT_VA(this);

  SBFrameList sb_frame_list;
  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBFrameList();
  }

  if (exe_ctx->HasThreadScope()) {
    StackFrameListSP frame_list_sp =
        exe_ctx->GetThreadPtr()->GetStackFrameList();
    sb_frame_list.SetFrameList(frame_list_sp);
  }

  return sb_frame_list;
}

lldb::SBFrame SBThread::GetSelectedFrame() {
  LLDB_INSTRUMENT_VA(this);

  SBFrame sb_frame;
  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBFrame();
  }

  if (exe_ctx->HasThreadScope()) {
    StackFrameSP frame_sp =
        exe_ctx->GetThreadPtr()->GetSelectedFrame(SelectMostRelevantFrame);
    sb_frame.SetFrameSP(frame_sp);
  }

  return sb_frame;
}

lldb::SBFrame SBThread::SetSelectedFrame(uint32_t idx) {
  LLDB_INSTRUMENT_VA(this, idx);

  SBFrame sb_frame;
  StackFrameSP frame_sp;
  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBFrame();
  }

  if (exe_ctx->HasThreadScope()) {
    Thread *thread = exe_ctx->GetThreadPtr();
    frame_sp = thread->GetStackFrameAtIndex(idx);
    if (frame_sp) {
      thread->SetSelectedFrame(frame_sp.get());
      sb_frame.SetFrameSP(frame_sp);
    }
  }

  return sb_frame;
}

bool SBThread::EventIsThreadEvent(const SBEvent &event) {
  LLDB_INSTRUMENT_VA(event);

  return Thread::ThreadEventData::GetEventDataFromEvent(event.get()) != nullptr;
}

SBFrame SBThread::GetStackFrameFromEvent(const SBEvent &event) {
  LLDB_INSTRUMENT_VA(event);

  return Thread::ThreadEventData::GetStackFrameFromEvent(event.get());
}

SBThread SBThread::GetThreadFromEvent(const SBEvent &event) {
  LLDB_INSTRUMENT_VA(event);

  return Thread::ThreadEventData::GetThreadFromEvent(event.get());
}

bool SBThread::operator==(const SBThread &rhs) const {
  LLDB_INSTRUMENT_VA(this, rhs);

  return m_opaque_sp->GetThreadSP().get() ==
         rhs.m_opaque_sp->GetThreadSP().get();
}

bool SBThread::operator!=(const SBThread &rhs) const {
  LLDB_INSTRUMENT_VA(this, rhs);

  return m_opaque_sp->GetThreadSP().get() !=
         rhs.m_opaque_sp->GetThreadSP().get();
}

bool SBThread::GetStatus(SBStream &status) const {
  LLDB_INSTRUMENT_VA(this, status);

  Stream &strm = status.ref();

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return false;
  }

  if (exe_ctx->HasThreadScope()) {
    exe_ctx->GetThreadPtr()->GetStatus(strm, 0, 1, 1, true,
                                       /*show_hidden=*/true);
  } else
    strm.PutCString("No status");

  return true;
}

bool SBThread::GetDescription(SBStream &description) const {
  LLDB_INSTRUMENT_VA(this, description);

  return GetDescription(description, false);
}

bool SBThread::GetDescription(SBStream &description, bool stop_format) const {
  LLDB_INSTRUMENT_VA(this, description, stop_format);

  Stream &strm = description.ref();

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return false;
  }

  if (exe_ctx->HasThreadScope()) {
    exe_ctx->GetThreadPtr()->DumpUsingSettingsFormat(
        strm, LLDB_INVALID_THREAD_ID, stop_format);
  } else
    strm.PutCString("No value");

  return true;
}

SBError SBThread::GetDescriptionWithFormat(const SBFormat &format,
                                           SBStream &output) {
  Stream &strm = output.ref();

  SBError error;
  if (!format) {
    error = Status::FromErrorString("The provided SBFormat object is invalid");
    return error;
  }

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return error;
  }

  if (exe_ctx->HasThreadScope()) {
    if (exe_ctx->GetThreadPtr()->DumpUsingFormat(
            strm, LLDB_INVALID_THREAD_ID, format.GetFormatEntrySP().get())) {
      return error;
    }
  }

  error = Status::FromErrorStringWithFormat(
      "It was not possible to generate a thread description with the given "
      "format string '%s'",
      format.GetFormatEntrySP()->string.c_str());
  return error;
}

SBThread SBThread::GetExtendedBacktraceThread(const char *type) {
  LLDB_INSTRUMENT_VA(this, type);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  SBThread sb_origin_thread;
  if (exe_ctx) {
    if (exe_ctx->HasThreadScope()) {
      ThreadSP real_thread(exe_ctx->GetThreadSP());
      if (real_thread) {
        ConstString type_const(type);
        Process *process = exe_ctx->GetProcessPtr();
        if (process) {
          SystemRuntime *runtime = process->GetSystemRuntime();
          if (runtime) {
            ThreadSP new_thread_sp(
                runtime->GetExtendedBacktraceThread(real_thread, type_const));
            if (new_thread_sp) {
              // Save this in the Process' ExtendedThreadList so a strong
              // pointer retains the object.
              process->GetExtendedThreadList().AddThread(new_thread_sp);
              sb_origin_thread.SetThread(new_thread_sp);
            }
          }
        }
      }
    }
  } else {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
  }

  return sb_origin_thread;
}

uint32_t SBThread::GetExtendedBacktraceOriginatingIndexID() {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return LLDB_INVALID_INDEX32;
  }

  ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
  if (thread_sp)
    return thread_sp->GetExtendedBacktraceOriginatingIndexID();
  return LLDB_INVALID_INDEX32;
}

SBValue SBThread::GetCurrentException() {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBValue();
  }

  ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
  if (!thread_sp)
    return SBValue();

  return SBValue(thread_sp->GetCurrentException());
}

SBThread SBThread::GetCurrentExceptionBacktrace() {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBThread();
  }

  ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
  if (!thread_sp)
    return SBThread();

  return SBThread(thread_sp->GetCurrentExceptionBacktrace());
}

bool SBThread::SafeToCallFunctions() {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return false;
  }

  ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
  if (thread_sp)
    return thread_sp->SafeToCallFunctions();
  return true;
}

lldb::ThreadSP SBThread::GetSP() const { return m_opaque_sp->GetThreadSP(); }

lldb_private::Thread *SBThread::operator->() {
  return get();
}

lldb_private::Thread *SBThread::get() {
  return m_opaque_sp->GetThreadSP().get();
}

SBValue SBThread::GetSiginfo() {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBValue();
  }

  ThreadSP thread_sp = m_opaque_sp->GetThreadSP();
  if (!thread_sp)
    return SBValue();
  return thread_sp->GetSiginfoValue();
}
