//===-- 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/LazyImport.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"
#include <llvm/Support/ConvertUTF.h>

using namespace lldb;
using namespace lldb_private;

NativeThreadWindows::NativeThreadWindows(NativeProcessWindows &process,
                                         const HostThread &thread)
    : NativeThreadProtocol(process, thread.GetNativeThread().GetThreadId()),
      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 == static_cast<DWORD>(-1))
      return Status(::GetLastError(), eErrorTypeWin32);

    // Invalidate cached register values on every stop.
    GetRegisterContext().InvalidateAllRegisters();

    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) {
    // Clear any stop info left over from a previous stop.
    ClearStopInfo();

    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 == static_cast<DWORD>(-1))
        return Status(::GetLastError(), eErrorTypeWin32);

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

  return Status();
}

std::string NativeThreadWindows::GetName() {
  Log *log = GetLog(LLDBLog::Thread);
  static LazyImport<HRESULT(WINAPI *)(HANDLE, PWSTR *)>
      s_get_thread_description{L"Kernel32.dll", "GetThreadDescription"};
  if (!s_get_thread_description)
    return m_name;
  auto GetThreadDescription = *s_get_thread_description;

  PWSTR pszThreadName;
  if (SUCCEEDED(GetThreadDescription(
          m_host_thread.GetNativeThread().GetSystemHandle(), &pszThreadName))) {
    LLDB_LOGF(log, "GetThreadDescription: %ls", pszThreadName);
    m_name.clear();
    llvm::convertUTF16ToUTF8String(
        llvm::ArrayRef(reinterpret_cast<char *>(pszThreadName),
                       wcslen(pszThreadName) * sizeof(wchar_t)),
        m_name);
    ::LocalFree(pszThreadName);
  }

  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.");
}
