//===-- ExecutionContext.cpp ------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/State.h"

using namespace lldb_private;

ExecutionContext::ExecutionContext()
    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {}

ExecutionContext::ExecutionContext(const ExecutionContext &rhs)
    : m_target_sp(rhs.m_target_sp), m_process_sp(rhs.m_process_sp),
      m_thread_sp(rhs.m_thread_sp), m_frame_sp(rhs.m_frame_sp) {}

ExecutionContext::ExecutionContext(const lldb::TargetSP &target_sp,
                                   bool get_process)
    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
  if (target_sp)
    SetContext(target_sp, get_process);
}

ExecutionContext::ExecutionContext(const lldb::ProcessSP &process_sp)
    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
  if (process_sp)
    SetContext(process_sp);
}

ExecutionContext::ExecutionContext(const lldb::ThreadSP &thread_sp)
    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
  if (thread_sp)
    SetContext(thread_sp);
}

ExecutionContext::ExecutionContext(const lldb::StackFrameSP &frame_sp)
    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
  if (frame_sp)
    SetContext(frame_sp);
}

ExecutionContext::ExecutionContext(const lldb::TargetWP &target_wp,
                                   bool get_process)
    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
  lldb::TargetSP target_sp(target_wp.lock());
  if (target_sp)
    SetContext(target_sp, get_process);
}

ExecutionContext::ExecutionContext(const lldb::ProcessWP &process_wp)
    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
  lldb::ProcessSP process_sp(process_wp.lock());
  if (process_sp)
    SetContext(process_sp);
}

ExecutionContext::ExecutionContext(const lldb::ThreadWP &thread_wp)
    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
  lldb::ThreadSP thread_sp(thread_wp.lock());
  if (thread_sp)
    SetContext(thread_sp);
}

ExecutionContext::ExecutionContext(const lldb::StackFrameWP &frame_wp)
    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
  lldb::StackFrameSP frame_sp(frame_wp.lock());
  if (frame_sp)
    SetContext(frame_sp);
}

ExecutionContext::ExecutionContext(Target *t,
                                   bool fill_current_process_thread_frame)
    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
  if (t) {
    m_target_sp = t->shared_from_this();
    if (fill_current_process_thread_frame) {
      m_process_sp = t->GetProcessSP();
      if (m_process_sp) {
        m_thread_sp = m_process_sp->GetThreadList().GetSelectedThread();
        if (m_thread_sp)
          m_frame_sp = m_thread_sp->GetSelectedFrame();
      }
    }
  }
}

ExecutionContext::ExecutionContext(Process *process, Thread *thread,
                                   StackFrame *frame)
    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
  if (process) {
    m_process_sp = process->shared_from_this();
    m_target_sp = process->GetTarget().shared_from_this();
  }
  if (thread)
    m_thread_sp = thread->shared_from_this();
  if (frame)
    m_frame_sp = frame->shared_from_this();
}

ExecutionContext::ExecutionContext(const ExecutionContextRef &exe_ctx_ref)
    : m_target_sp(exe_ctx_ref.GetTargetSP()),
      m_process_sp(exe_ctx_ref.GetProcessSP()),
      m_thread_sp(exe_ctx_ref.GetThreadSP()),
      m_frame_sp(exe_ctx_ref.GetFrameSP()) {}

ExecutionContext::ExecutionContext(const ExecutionContextRef *exe_ctx_ref_ptr,
                                   bool thread_and_frame_only_if_stopped)
    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
  if (exe_ctx_ref_ptr) {
    m_target_sp = exe_ctx_ref_ptr->GetTargetSP();
    m_process_sp = exe_ctx_ref_ptr->GetProcessSP();
    if (!thread_and_frame_only_if_stopped ||
        (m_process_sp && StateIsStoppedState(m_process_sp->GetState(), true))) {
      m_thread_sp = exe_ctx_ref_ptr->GetThreadSP();
      m_frame_sp = exe_ctx_ref_ptr->GetFrameSP();
    }
  }
}

ExecutionContext::ExecutionContext(const ExecutionContextRef *exe_ctx_ref_ptr,
                                   std::unique_lock<std::recursive_mutex> &lock)
    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
  if (exe_ctx_ref_ptr) {
    m_target_sp = exe_ctx_ref_ptr->GetTargetSP();
    if (m_target_sp) {
      lock = std::unique_lock<std::recursive_mutex>(m_target_sp->GetAPIMutex());

      m_process_sp = exe_ctx_ref_ptr->GetProcessSP();
      m_thread_sp = exe_ctx_ref_ptr->GetThreadSP();
      m_frame_sp = exe_ctx_ref_ptr->GetFrameSP();
    }
  }
}

ExecutionContext::ExecutionContext(const ExecutionContextRef &exe_ctx_ref,
                                   std::unique_lock<std::recursive_mutex> &lock)
    : m_target_sp(exe_ctx_ref.GetTargetSP()), m_process_sp(), m_thread_sp(),
      m_frame_sp() {
  if (m_target_sp) {
    lock = std::unique_lock<std::recursive_mutex>(m_target_sp->GetAPIMutex());

    m_process_sp = exe_ctx_ref.GetProcessSP();
    m_thread_sp = exe_ctx_ref.GetThreadSP();
    m_frame_sp = exe_ctx_ref.GetFrameSP();
  }
}

ExecutionContext::ExecutionContext(ExecutionContextScope *exe_scope_ptr)
    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
  if (exe_scope_ptr)
    exe_scope_ptr->CalculateExecutionContext(*this);
}

ExecutionContext::ExecutionContext(ExecutionContextScope &exe_scope_ref) {
  exe_scope_ref.CalculateExecutionContext(*this);
}

void ExecutionContext::Clear() {
  m_target_sp.reset();
  m_process_sp.reset();
  m_thread_sp.reset();
  m_frame_sp.reset();
}

ExecutionContext::~ExecutionContext() = default;

uint32_t ExecutionContext::GetAddressByteSize() const {
  if (m_target_sp && m_target_sp->GetArchitecture().IsValid())
    return m_target_sp->GetArchitecture().GetAddressByteSize();
  if (m_process_sp)
    return m_process_sp->GetAddressByteSize();
  return sizeof(void *);
}

lldb::ByteOrder ExecutionContext::GetByteOrder() const {
  if (m_target_sp && m_target_sp->GetArchitecture().IsValid())
    m_target_sp->GetArchitecture().GetByteOrder();
  if (m_process_sp)
    m_process_sp->GetByteOrder();
  return endian::InlHostByteOrder();
}

RegisterContext *ExecutionContext::GetRegisterContext() const {
  if (m_frame_sp)
    return m_frame_sp->GetRegisterContext().get();
  else if (m_thread_sp)
    return m_thread_sp->GetRegisterContext().get();
  return nullptr;
}

Target *ExecutionContext::GetTargetPtr() const {
  if (m_target_sp)
    return m_target_sp.get();
  if (m_process_sp)
    return &m_process_sp->GetTarget();
  return nullptr;
}

Process *ExecutionContext::GetProcessPtr() const {
  if (m_process_sp)
    return m_process_sp.get();
  if (m_target_sp)
    return m_target_sp->GetProcessSP().get();
  return nullptr;
}

ExecutionContextScope *ExecutionContext::GetBestExecutionContextScope() const {
  if (m_frame_sp)
    return m_frame_sp.get();
  if (m_thread_sp)
    return m_thread_sp.get();
  if (m_process_sp)
    return m_process_sp.get();
  return m_target_sp.get();
}

Target &ExecutionContext::GetTargetRef() const {
#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE)
  assert(m_target_sp);
#endif
  return *m_target_sp;
}

Process &ExecutionContext::GetProcessRef() const {
#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE)
  assert(m_process_sp);
#endif
  return *m_process_sp;
}

Thread &ExecutionContext::GetThreadRef() const {
#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE)
  assert(m_thread_sp);
#endif
  return *m_thread_sp;
}

StackFrame &ExecutionContext::GetFrameRef() const {
#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE)
  assert(m_frame_sp);
#endif
  return *m_frame_sp;
}

void ExecutionContext::SetTargetSP(const lldb::TargetSP &target_sp) {
  m_target_sp = target_sp;
}

void ExecutionContext::SetProcessSP(const lldb::ProcessSP &process_sp) {
  m_process_sp = process_sp;
}

void ExecutionContext::SetThreadSP(const lldb::ThreadSP &thread_sp) {
  m_thread_sp = thread_sp;
}

void ExecutionContext::SetFrameSP(const lldb::StackFrameSP &frame_sp) {
  m_frame_sp = frame_sp;
}

void ExecutionContext::SetTargetPtr(Target *target) {
  if (target)
    m_target_sp = target->shared_from_this();
  else
    m_target_sp.reset();
}

void ExecutionContext::SetProcessPtr(Process *process) {
  if (process)
    m_process_sp = process->shared_from_this();
  else
    m_process_sp.reset();
}

void ExecutionContext::SetThreadPtr(Thread *thread) {
  if (thread)
    m_thread_sp = thread->shared_from_this();
  else
    m_thread_sp.reset();
}

void ExecutionContext::SetFramePtr(StackFrame *frame) {
  if (frame)
    m_frame_sp = frame->shared_from_this();
  else
    m_frame_sp.reset();
}

void ExecutionContext::SetContext(const lldb::TargetSP &target_sp,
                                  bool get_process) {
  m_target_sp = target_sp;
  if (get_process && target_sp)
    m_process_sp = target_sp->GetProcessSP();
  else
    m_process_sp.reset();
  m_thread_sp.reset();
  m_frame_sp.reset();
}

void ExecutionContext::SetContext(const lldb::ProcessSP &process_sp) {
  m_process_sp = process_sp;
  if (process_sp)
    m_target_sp = process_sp->GetTarget().shared_from_this();
  else
    m_target_sp.reset();
  m_thread_sp.reset();
  m_frame_sp.reset();
}

void ExecutionContext::SetContext(const lldb::ThreadSP &thread_sp) {
  m_frame_sp.reset();
  m_thread_sp = thread_sp;
  if (thread_sp) {
    m_process_sp = thread_sp->GetProcess();
    if (m_process_sp)
      m_target_sp = m_process_sp->GetTarget().shared_from_this();
    else
      m_target_sp.reset();
  } else {
    m_target_sp.reset();
    m_process_sp.reset();
  }
}

void ExecutionContext::SetContext(const lldb::StackFrameSP &frame_sp) {
  m_frame_sp = frame_sp;
  if (frame_sp) {
    m_thread_sp = frame_sp->CalculateThread();
    if (m_thread_sp) {
      m_process_sp = m_thread_sp->GetProcess();
      if (m_process_sp)
        m_target_sp = m_process_sp->GetTarget().shared_from_this();
      else
        m_target_sp.reset();
    } else {
      m_target_sp.reset();
      m_process_sp.reset();
    }
  } else {
    m_target_sp.reset();
    m_process_sp.reset();
    m_thread_sp.reset();
  }
}

ExecutionContext &ExecutionContext::operator=(const ExecutionContext &rhs) {
  if (this != &rhs) {
    m_target_sp = rhs.m_target_sp;
    m_process_sp = rhs.m_process_sp;
    m_thread_sp = rhs.m_thread_sp;
    m_frame_sp = rhs.m_frame_sp;
  }
  return *this;
}

bool ExecutionContext::operator==(const ExecutionContext &rhs) const {
  // Check that the frame shared pointers match, or both are valid and their
  // stack IDs match since sometimes we get new objects that represent the same
  // frame within a thread.
  if ((m_frame_sp == rhs.m_frame_sp) ||
      (m_frame_sp && rhs.m_frame_sp &&
       m_frame_sp->GetStackID() == rhs.m_frame_sp->GetStackID())) {
    // Check that the thread shared pointers match, or both are valid and their
    // thread IDs match since sometimes we get new objects that represent the
    // same thread within a process.
    if ((m_thread_sp == rhs.m_thread_sp) ||
        (m_thread_sp && rhs.m_thread_sp &&
         m_thread_sp->GetID() == rhs.m_thread_sp->GetID())) {
      // Processes and targets don't change much
      return m_process_sp == rhs.m_process_sp && m_target_sp == rhs.m_target_sp;
    }
  }
  return false;
}

bool ExecutionContext::operator!=(const ExecutionContext &rhs) const {
  return !(*this == rhs);
}

bool ExecutionContext::HasTargetScope() const {
  return ((bool)m_target_sp && m_target_sp->IsValid());
}

bool ExecutionContext::HasProcessScope() const {
  return (HasTargetScope() && ((bool)m_process_sp && m_process_sp->IsValid()));
}

bool ExecutionContext::HasThreadScope() const {
  return (HasProcessScope() && ((bool)m_thread_sp && m_thread_sp->IsValid()));
}

bool ExecutionContext::HasFrameScope() const {
  return HasThreadScope() && m_frame_sp;
}

ExecutionContextRef::ExecutionContextRef()
    : m_target_wp(), m_process_wp(), m_thread_wp(),
      m_tid(LLDB_INVALID_THREAD_ID), m_stack_id() {}

ExecutionContextRef::ExecutionContextRef(const ExecutionContext *exe_ctx)
    : m_target_wp(), m_process_wp(), m_thread_wp(),
      m_tid(LLDB_INVALID_THREAD_ID), m_stack_id() {
  if (exe_ctx)
    *this = *exe_ctx;
}

ExecutionContextRef::ExecutionContextRef(const ExecutionContext &exe_ctx)
    : m_target_wp(), m_process_wp(), m_thread_wp(),
      m_tid(LLDB_INVALID_THREAD_ID), m_stack_id() {
  *this = exe_ctx;
}

ExecutionContextRef::ExecutionContextRef(Target *target, bool adopt_selected)
    : m_target_wp(), m_process_wp(), m_thread_wp(),
      m_tid(LLDB_INVALID_THREAD_ID), m_stack_id() {
  SetTargetPtr(target, adopt_selected);
}

ExecutionContextRef::ExecutionContextRef(const ExecutionContextRef &rhs)
    : m_target_wp(rhs.m_target_wp), m_process_wp(rhs.m_process_wp),
      m_thread_wp(rhs.m_thread_wp), m_tid(rhs.m_tid),
      m_stack_id(rhs.m_stack_id) {}

ExecutionContextRef &ExecutionContextRef::
operator=(const ExecutionContextRef &rhs) {
  if (this != &rhs) {
    m_target_wp = rhs.m_target_wp;
    m_process_wp = rhs.m_process_wp;
    m_thread_wp = rhs.m_thread_wp;
    m_tid = rhs.m_tid;
    m_stack_id = rhs.m_stack_id;
  }
  return *this;
}

ExecutionContextRef &ExecutionContextRef::
operator=(const ExecutionContext &exe_ctx) {
  m_target_wp = exe_ctx.GetTargetSP();
  m_process_wp = exe_ctx.GetProcessSP();
  lldb::ThreadSP thread_sp(exe_ctx.GetThreadSP());
  m_thread_wp = thread_sp;
  if (thread_sp)
    m_tid = thread_sp->GetID();
  else
    m_tid = LLDB_INVALID_THREAD_ID;
  lldb::StackFrameSP frame_sp(exe_ctx.GetFrameSP());
  if (frame_sp)
    m_stack_id = frame_sp->GetStackID();
  else
    m_stack_id.Clear();
  return *this;
}

void ExecutionContextRef::Clear() {
  m_target_wp.reset();
  m_process_wp.reset();
  ClearThread();
  ClearFrame();
}

ExecutionContextRef::~ExecutionContextRef() = default;

void ExecutionContextRef::SetTargetSP(const lldb::TargetSP &target_sp) {
  m_target_wp = target_sp;
}

void ExecutionContextRef::SetProcessSP(const lldb::ProcessSP &process_sp) {
  if (process_sp) {
    m_process_wp = process_sp;
    SetTargetSP(process_sp->GetTarget().shared_from_this());
  } else {
    m_process_wp.reset();
    m_target_wp.reset();
  }
}

void ExecutionContextRef::SetThreadSP(const lldb::ThreadSP &thread_sp) {
  if (thread_sp) {
    m_thread_wp = thread_sp;
    m_tid = thread_sp->GetID();
    SetProcessSP(thread_sp->GetProcess());
  } else {
    ClearThread();
    m_process_wp.reset();
    m_target_wp.reset();
  }
}

void ExecutionContextRef::SetFrameSP(const lldb::StackFrameSP &frame_sp) {
  if (frame_sp) {
    m_stack_id = frame_sp->GetStackID();
    SetThreadSP(frame_sp->GetThread());
  } else {
    ClearFrame();
    ClearThread();
    m_process_wp.reset();
    m_target_wp.reset();
  }
}

void ExecutionContextRef::SetTargetPtr(Target *target, bool adopt_selected) {
  Clear();
  if (target) {
    lldb::TargetSP target_sp(target->shared_from_this());
    if (target_sp) {
      m_target_wp = target_sp;
      if (adopt_selected) {
        lldb::ProcessSP process_sp(target_sp->GetProcessSP());
        if (process_sp) {
          m_process_wp = process_sp;
          if (process_sp) {
            // Only fill in the thread and frame if our process is stopped
            // Don't just check the state, since we might be in the middle of
            // resuming.
            Process::StopLocker stop_locker;

            if (stop_locker.TryLock(&process_sp->GetRunLock()) &&
                StateIsStoppedState(process_sp->GetState(), true)) {
              lldb::ThreadSP thread_sp(
                  process_sp->GetThreadList().GetSelectedThread());
              if (!thread_sp)
                thread_sp = process_sp->GetThreadList().GetThreadAtIndex(0);

              if (thread_sp) {
                SetThreadSP(thread_sp);
                lldb::StackFrameSP frame_sp(thread_sp->GetSelectedFrame());
                if (!frame_sp)
                  frame_sp = thread_sp->GetStackFrameAtIndex(0);
                if (frame_sp)
                  SetFrameSP(frame_sp);
              }
            }
          }
        }
      }
    }
  }
}

void ExecutionContextRef::SetProcessPtr(Process *process) {
  if (process) {
    SetProcessSP(process->shared_from_this());
  } else {
    m_process_wp.reset();
    m_target_wp.reset();
  }
}

void ExecutionContextRef::SetThreadPtr(Thread *thread) {
  if (thread) {
    SetThreadSP(thread->shared_from_this());
  } else {
    ClearThread();
    m_process_wp.reset();
    m_target_wp.reset();
  }
}

void ExecutionContextRef::SetFramePtr(StackFrame *frame) {
  if (frame)
    SetFrameSP(frame->shared_from_this());
  else
    Clear();
}

lldb::TargetSP ExecutionContextRef::GetTargetSP() const {
  lldb::TargetSP target_sp(m_target_wp.lock());
  if (target_sp && !target_sp->IsValid())
    target_sp.reset();
  return target_sp;
}

lldb::ProcessSP ExecutionContextRef::GetProcessSP() const {
  lldb::ProcessSP process_sp(m_process_wp.lock());
  if (process_sp && !process_sp->IsValid())
    process_sp.reset();
  return process_sp;
}

lldb::ThreadSP ExecutionContextRef::GetThreadSP() const {
  lldb::ThreadSP thread_sp(m_thread_wp.lock());

  if (m_tid != LLDB_INVALID_THREAD_ID) {
    // We check if the thread has been destroyed in cases where clients might
    // still have shared pointer to a thread, but the thread is not valid
    // anymore (not part of the process)
    if (!thread_sp || !thread_sp->IsValid()) {
      lldb::ProcessSP process_sp(GetProcessSP());
      if (process_sp && process_sp->IsValid()) {
        thread_sp = process_sp->GetThreadList().FindThreadByID(m_tid);
        m_thread_wp = thread_sp;
      }
    }
  }

  // Check that we aren't about to return an invalid thread sp.  We might
  // return a nullptr thread_sp, but don't return an invalid one.

  if (thread_sp && !thread_sp->IsValid())
    thread_sp.reset();

  return thread_sp;
}

lldb::StackFrameSP ExecutionContextRef::GetFrameSP() const {
  if (m_stack_id.IsValid()) {
    lldb::ThreadSP thread_sp(GetThreadSP());
    if (thread_sp)
      return thread_sp->GetFrameWithStackID(m_stack_id);
  }
  return lldb::StackFrameSP();
}

ExecutionContext
ExecutionContextRef::Lock(bool thread_and_frame_only_if_stopped) const {
  return ExecutionContext(this, thread_and_frame_only_if_stopped);
}
