//===-- 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/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/State.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)
    SetSingleStepFlag();

  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;
    m_single_stepping = resume_state == eStateStepping;
  }

  return Status();
}

void NativeThreadWindows::SetSingleStepFlag() {
  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);
  const ArchSpec &arch = GetProcess().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);
}

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:
    LLDB_LOGF(log, "tid %" PRIu64 " in state %s cannot answer stop reason",
              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.");
}

StructuredData::ObjectSP NativeThreadWindows::GetExtendedInfo() const {
  return m_host_thread.GetNativeThread().GetExtendedInfo();
}
