//===-- NativeThreadWindows.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 "NativeThreadWindows.h"
#include "NativeProcessWindows.h"

#include "lldb/Host/HostThread.h"
#include "lldb/Host/windows/HostThreadWindows.h"
#include "lldb/Host/windows/windows.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/State.h"

#include "lldb/lldb-forward.h"

using namespace lldb;
using namespace lldb_private;

NativeThreadWindows::NativeThreadWindows(NativeProcessWindows &process,
                                         const HostThread &thread)
    : NativeThreadProtocol(process, thread.GetNativeThread().GetThreadId()),
      m_stop_info(), m_stop_description(), m_host_thread(thread) {
  m_reg_context_up =
      (NativeRegisterContextWindows::CreateHostNativeRegisterContextWindows(
          process.GetArchitecture(), *this));
}

Status NativeThreadWindows::DoStop() {
  if (m_state != eStateStopped) {
    DWORD previous_suspend_count =
        ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle());
    if (previous_suspend_count == (DWORD)-1)
      return Status(::GetLastError(), eErrorTypeWin32);

    m_state = eStateStopped;
  }
  return Status();
}

Status NativeThreadWindows::DoResume(lldb::StateType resume_state) {
  StateType current_state = GetState();
  if (resume_state == current_state)
    return Status();

  if (resume_state == eStateStepping) {
    Log *log = GetLog(LLDBLog::Thread);

    uint32_t flags_index =
        GetRegisterContext().ConvertRegisterKindToRegisterNumber(
            eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
    uint64_t flags_value =
        GetRegisterContext().ReadRegisterAsUnsigned(flags_index, 0);
    NativeProcessProtocol &process = GetProcess();
    const ArchSpec &arch = process.GetArchitecture();
    switch (arch.GetMachine()) {
    case llvm::Triple::x86:
    case llvm::Triple::x86_64:
      flags_value |= 0x100; // Set the trap flag on the CPU
      break;
    case llvm::Triple::aarch64:
    case llvm::Triple::arm:
    case llvm::Triple::thumb:
      flags_value |= 0x200000; // The SS bit in PState
      break;
    default:
      LLDB_LOG(log, "single stepping unsupported on this architecture");
      break;
    }
    GetRegisterContext().WriteRegisterFromUnsigned(flags_index, flags_value);
  }

  if (resume_state == eStateStepping || resume_state == eStateRunning) {
    DWORD previous_suspend_count = 0;
    HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle();
    do {
      // ResumeThread returns -1 on error, or the thread's *previous* suspend
      // count on success. This means that the return value is 1 when the thread
      // was restarted. Note that DWORD is an unsigned int, so we need to
      // explicitly compare with -1.
      previous_suspend_count = ::ResumeThread(thread_handle);

      if (previous_suspend_count == (DWORD)-1)
        return Status(::GetLastError(), eErrorTypeWin32);

    } while (previous_suspend_count > 1);
    m_state = eStateRunning;
  }

  return Status();
}

std::string NativeThreadWindows::GetName() {
  if (!m_name.empty())
    return m_name;

  // Name is not a property of the Windows thread. Create one with the
  // process's.
  NativeProcessProtocol &process = GetProcess();
  ProcessInstanceInfo process_info;
  if (Host::GetProcessInfo(process.GetID(), process_info)) {
    std::string process_name(process_info.GetName());
    m_name = process_name;
  }
  return m_name;
}

void NativeThreadWindows::SetStopReason(ThreadStopInfo stop_info,
                                        std::string description) {
  m_state = eStateStopped;
  m_stop_info = stop_info;
  m_stop_description = description;
}

bool NativeThreadWindows::GetStopReason(ThreadStopInfo &stop_info,
                                        std::string &description) {
  Log *log = GetLog(LLDBLog::Thread);

  switch (m_state) {
  case eStateStopped:
  case eStateCrashed:
  case eStateExited:
  case eStateSuspended:
  case eStateUnloaded:
    stop_info = m_stop_info;
    description = m_stop_description;
    return true;

  case eStateInvalid:
  case eStateConnected:
  case eStateAttaching:
  case eStateLaunching:
  case eStateRunning:
  case eStateStepping:
  case eStateDetached:
    if (log) {
      log->Printf("NativeThreadWindows::%s tid %" PRIu64
                  " in state %s cannot answer stop reason",
                  __FUNCTION__, GetID(), StateAsCString(m_state));
    }
    return false;
  }
  llvm_unreachable("unhandled StateType!");
}

Status NativeThreadWindows::SetWatchpoint(lldb::addr_t addr, size_t size,
                                          uint32_t watch_flags, bool hardware) {
  if (!hardware)
    return Status::FromErrorString("not implemented");
  if (m_state == eStateLaunching)
    return Status();
  Status error = RemoveWatchpoint(addr);
  if (error.Fail())
    return error;
  uint32_t wp_index =
      m_reg_context_up->SetHardwareWatchpoint(addr, size, watch_flags);
  if (wp_index == LLDB_INVALID_INDEX32)
    return Status::FromErrorString("Setting hardware watchpoint failed.");
  m_watchpoint_index_map.insert({addr, wp_index});
  return Status();
}

Status NativeThreadWindows::RemoveWatchpoint(lldb::addr_t addr) {
  auto wp = m_watchpoint_index_map.find(addr);
  if (wp == m_watchpoint_index_map.end())
    return Status();
  uint32_t wp_index = wp->second;
  m_watchpoint_index_map.erase(wp);
  if (m_reg_context_up->ClearHardwareWatchpoint(wp_index))
    return Status();
  return Status::FromErrorString("Clearing hardware watchpoint failed.");
}

Status NativeThreadWindows::SetHardwareBreakpoint(lldb::addr_t addr,
                                                  size_t size) {
  return Status::FromErrorString("unimplemented.");
}

Status NativeThreadWindows::RemoveHardwareBreakpoint(lldb::addr_t addr) {
  return Status::FromErrorString("unimplemented.");
}
