//===--------- Misc.cpp - OpenMP device misc interfaces ----------- C++ -*-===//
//
// 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 "Allocator.h"
#include "Configuration.h"
#include "DeviceTypes.h"
#include "Shared/RPCOpcodes.h"
#include "shared/rpc.h"

#include "Debug.h"

namespace ompx {
namespace impl {

/// Lookup a device-side function using a host pointer /p HstPtr using the table
/// provided by the device plugin. The table is an ordered pair of host and
/// device pointers sorted on the value of the host pointer.
static FnPtrTy indirectCallLookup(FnPtrTy HstPtr) {
  if (!HstPtr)
    return nullptr;

  struct IndirectCallTable {
    FnPtrTy HstPtr;
    FnPtrTy DevPtr;
  };
  IndirectCallTable *Table =
      reinterpret_cast<IndirectCallTable *>(config::getIndirectCallTablePtr());
  uint64_t TableSize = config::getIndirectCallTableSize();

  // If the table is empty we assume this is device pointer.
  if (!Table || !TableSize)
    return HstPtr;

  uint32_t Left = 0;
  uint32_t Right = TableSize;

  // If the pointer is definitely not contained in the table we exit early.
  if (HstPtr < Table[Left].HstPtr || HstPtr > Table[Right - 1].HstPtr)
    return HstPtr;

  while (Left != Right) {
    uint32_t Current = Left + (Right - Left) / 2;
    if (Table[Current].HstPtr == HstPtr)
      return Table[Current].DevPtr;

    if (HstPtr < Table[Current].HstPtr)
      Right = Current;
    else
      Left = Current;
  }

  // If we searched the whole table and found nothing this is a device pointer.
  return HstPtr;
}

/// Split the ";file;function;line;column;;" string carried by an ident into its
/// filename and line/column. \p File is not NUL-terminated, so \p FileLen gives
/// its length. Returns false only if the string is missing or malformed; calls
/// with no debug location parse successfully as "unknown" at 0:0, which the
/// host runtime also reports. offload's SourceInfo parses the same format but
/// needs std::string, which is unavailable here.
static bool getSourceLocation(const IdentTy *Loc, const char *&File,
                              int32_t &FileLen, int32_t &Line,
                              int32_t &Column) {
  if (!Loc || !Loc->psource || *Loc->psource != ';')
    return false;

  const char *P = Loc->psource + 1;

  File = P;
  while (*P && *P != ';')
    ++P;
  FileLen = static_cast<int32_t>(P - File);
  if (*P != ';')
    return false;
  ++P;

  // Skip the function name field; it is the mangled kernel name.
  while (*P && *P != ';')
    ++P;
  if (*P != ';')
    return false;
  ++P;

  for (Line = 0; *P >= '0' && *P <= '9'; ++P)
    Line = Line * 10 + (*P - '0');
  if (*P != ';')
    return false;
  ++P;

  for (Column = 0; *P >= '0' && *P <= '9'; ++P)
    Column = Column * 10 + (*P - '0');

  return true;
}

/// The openmp client instance used to communicate with the server.
[[gnu::visibility("protected"),
  gnu::weak]] rpc::Client Client asm("__llvm_rpc_client");

} // namespace impl
} // namespace ompx

/// Interfaces
///
///{

extern "C" {
int32_t __kmpc_cancellationpoint(IdentTy *, int32_t, int32_t) { return 0; }

int32_t __kmpc_cancel(IdentTy *, int32_t, int32_t) { return 0; }

void __kmpc_error(IdentTy *Loc, int32_t Severity, const char *Message) {
  const char *Kind = Severity == 1 ? "warning" : "error";
  const char *File;
  int32_t FileLen, Line, Column;
  bool HasLoc = ompx::impl::getSourceLocation(Loc, File, FileLen, Line, Column);

  if (HasLoc && Message)
    ompx::printf("OMP: %.*s:%d:%d: Encountered user-directed %s: %s.\n",
                 FileLen, File, Line, Column, Kind, Message);
  else if (HasLoc)
    ompx::printf("OMP: %.*s:%d:%d: Encountered user-directed %s.\n", FileLen,
                 File, Line, Column, Kind);
  else if (Message)
    ompx::printf("OMP: Encountered user-directed %s: %s.\n", Kind, Message);
  else
    ompx::printf("OMP: Encountered user-directed %s.\n", Kind);

  if (Severity != 1)
    __builtin_trap();
}

double omp_get_wtick(void) {
  // The number of ticks per second for the AMDGPU clock varies by card and can
  // only be retrieved by querying the driver. We rely on the device environment
  // to inform us what the proper frequency is. NVPTX uses a nanosecond
  // resolution, we could omit the global read but this makes it consistent.
  return 1.0 / ompx::config::getClockFrequency();
}

double omp_get_wtime(void) {
  return static_cast<double>(__builtin_readsteadycounter()) * omp_get_wtick();
}

FnPtrTy __llvm_omp_indirect_call_lookup(FnPtrTy HstPtr) {
  return ompx::impl::indirectCallLookup(HstPtr);
}

void *omp_alloc(size_t size, omp_allocator_handle_t allocator) {
  switch (allocator) {
  case omp_default_mem_alloc:
  case omp_large_cap_mem_alloc:
  case omp_const_mem_alloc:
  case omp_high_bw_mem_alloc:
  case omp_low_lat_mem_alloc:
    return ompx::allocator::alloc(size);
  default:
    return nullptr;
  }
}

void omp_free(void *ptr, omp_allocator_handle_t allocator) {
  switch (allocator) {
  case omp_default_mem_alloc:
  case omp_large_cap_mem_alloc:
  case omp_const_mem_alloc:
  case omp_high_bw_mem_alloc:
  case omp_low_lat_mem_alloc:
    ompx::allocator::free(ptr);
    return;
  case omp_null_allocator:
  default:
    return;
  }
}

unsigned long long __llvm_omp_host_call(void *fn, void *data, size_t size) {
  rpc::Client::Port Port = ompx::impl::Client.open<OFFLOAD_HOST_CALL>();
  Port.send_n(data, size);
  Port.send([=](rpc::Buffer *buffer, uint32_t) {
    buffer->data[0] = reinterpret_cast<uintptr_t>(fn);
  });
  unsigned long long Ret;
  Port.recv([&](rpc::Buffer *Buffer, uint32_t) {
    Ret = static_cast<unsigned long long>(Buffer->data[0]);
  });
  return Ret;
}
}

// C++ ABI helpers.
extern "C" {
[[gnu::weak]] void __cxa_pure_virtual(void) { __builtin_trap(); }
[[gnu::weak]] void __cxa_deleted_virtual(void) { __builtin_trap(); }
}

///}
