//===----------- api.cpp - Target independent OpenMP target RTL -----------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Implementation of OpenMP API interface functions.
//
//===----------------------------------------------------------------------===//

#include "../private.h"
#include "OpenMP/OffloadRTL.h"
#include "device.h"
#include "omptarget.h"
#include "rtl.h"

#include "OpenMP/InternalTypes.h"
#include "OpenMP/InteropAPI.h"
#include "OpenMP/Mapping.h"
#include "OpenMP/OMPT/Interface.h"
#include "OpenMP/omp.h"
#include "Shared/Profile.h"

#include "llvm/ADT/SmallVector.h"

#include <climits>
#include <cstdlib>
#include <cstring>
#include <mutex>

EXTERN void ompx_dump_mapping_tables() {
  ident_t Loc = {0, 0, 0, 0, ";libomptarget;libomptarget;0;0;;"};
  auto ExclusiveDevicesAccessor = PM->getExclusiveDevicesAccessor();
  for (auto &Device : PM->devices(ExclusiveDevicesAccessor))
    dumpTargetPointerMappings(&Loc, Device, true);
}

#ifdef OMPT_SUPPORT
using namespace llvm::omp::target::ompt;
#endif
using namespace llvm::omp::target::debug;


void *targetAllocExplicit(size_t Size, int DeviceNum, int Kind,
                          const char *Name);
void targetFreeExplicit(void *DevicePtr, int DeviceNum, int Kind,
                        const char *Name);
void *targetLockExplicit(void *HostPtr, size_t Size, int DeviceNum,
                         const char *Name);
void targetUnlockExplicit(void *HostPtr, int DeviceNum, const char *Name);

EXTERN int omp_get_num_devices(void) {
  TIMESCOPE();
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  size_t NumDevices = PM->getNumDevices();

  ODBG(ODT_Interface) << "Call to " << __func__ << " returning " << NumDevices;

  return NumDevices;
}

EXTERN int omp_get_device_num(void) {
  TIMESCOPE();
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  int HostDevice = omp_get_initial_device();

  ODBG(ODT_Interface) << "Call to " << __func__ << " returning " << HostDevice;

  return HostDevice;
}

static inline bool is_initial_device_uid(const char *DeviceUid) {
  return strcmp(DeviceUid, PM->getHostDeviceUid()) == 0;
}

EXTERN int omp_get_device_from_uid(const char *DeviceUid) {
  TIMESCOPE();
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));

  if (!DeviceUid) {
    ODBG(ODT_Interface) << "Call to " << __func__
                        << " returning omp_invalid_device";
    return omp_invalid_device;
  }
  if (is_initial_device_uid(DeviceUid)) {
    ODBG(ODT_Interface) << "Call to " << __func__
                        << " returning initial device number "
                        << omp_get_initial_device();
    return omp_get_initial_device();
  }

  int DeviceNum = omp_invalid_device;

  auto ExclusiveDevicesAccessor = PM->getExclusiveDevicesAccessor();
  for (const DeviceTy &Device : PM->devices(ExclusiveDevicesAccessor)) {
    if (Device.getUid() == DeviceUid) {
      DeviceNum = Device.DeviceID;
      break;
    }
  }

  ODBG(ODT_Interface) << "Call to " << __func__ << " returning " << DeviceNum;
  return DeviceNum;
}

EXTERN const char *omp_get_uid_from_device(int DeviceNum) {
  TIMESCOPE();
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));

  if (DeviceNum == omp_invalid_device) {
    ODBG(ODT_Interface) << "Call to " << __func__ << " returning nullptr";
    return nullptr;
  }
  if (isInitialDevice(DeviceNum)) {
    ODBG(ODT_Interface) << "Call to " << __func__
                        << " returning initial device UID";
    return PM->getHostDeviceUid();
  }

  auto DeviceOrErr = PM->getDevice(DeviceNum);
  if (!DeviceOrErr)
    FATAL_MESSAGE(DeviceNum, "%s", toString(DeviceOrErr.takeError()).c_str());

  const char *Uid = DeviceOrErr->getUid().data();
  ODBG(ODT_Interface) << "Call to " << __func__ << " returning " << Uid;
  return Uid;
}

EXTERN int omp_get_initial_device(void) {
  TIMESCOPE();
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  int HostDevice = omp_get_num_devices();
  ODBG(ODT_Interface) << "Call to " << __func__ << " returning " << HostDevice;
  return HostDevice;
}

EXTERN size_t omp_get_gprivate_limit(int DeviceNum, omp_access_t AccessGroup) {
  TIMESCOPE();
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  if (isInitialDevice(DeviceNum))
    return 0;

  if (AccessGroup != omp_access_cgroup)
    return 0;

  auto DeviceOrErr = PM->getDevice(DeviceNum);
  if (!DeviceOrErr)
    FATAL_MESSAGE(DeviceNum, "%s", toString(DeviceOrErr.takeError()).c_str());

  return DeviceOrErr->getInfo<uint64_t>(
      OL_DEVICE_INFO_WORK_GROUP_LOCAL_MEM_SIZE);
}

EXTERN void *omp_target_alloc(size_t Size, int DeviceNum) {
  TIMESCOPE_WITH_DETAILS("dst_dev=" + std::to_string(DeviceNum) +
                         ";size=" + std::to_string(Size));
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  return targetAllocExplicit(Size, DeviceNum, TARGET_ALLOC_DEFAULT, __func__);
}

EXTERN void *llvm_omp_target_alloc_device(size_t Size, int DeviceNum) {
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  return targetAllocExplicit(Size, DeviceNum, TARGET_ALLOC_DEVICE, __func__);
}

EXTERN void *llvm_omp_target_alloc_host(size_t Size, int DeviceNum) {
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  return targetAllocExplicit(Size, DeviceNum, TARGET_ALLOC_HOST, __func__);
}

EXTERN void *llvm_omp_target_alloc_shared(size_t Size, int DeviceNum) {
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  return targetAllocExplicit(Size, DeviceNum, TARGET_ALLOC_SHARED, __func__);
}

EXTERN void omp_target_free(void *Ptr, int DeviceNum) {
  TIMESCOPE();
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  return targetFreeExplicit(Ptr, DeviceNum, TARGET_ALLOC_DEFAULT, __func__);
}

EXTERN void llvm_omp_target_free_device(void *Ptr, int DeviceNum) {
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  return targetFreeExplicit(Ptr, DeviceNum, TARGET_ALLOC_DEVICE, __func__);
}

EXTERN void llvm_omp_target_free_host(void *Ptr, int DeviceNum) {
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  return targetFreeExplicit(Ptr, DeviceNum, TARGET_ALLOC_HOST, __func__);
}

EXTERN void llvm_omp_target_free_shared(void *Ptre, int DeviceNum) {
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  return targetFreeExplicit(Ptre, DeviceNum, TARGET_ALLOC_SHARED, __func__);
}

EXTERN void *llvm_omp_target_dynamic_shared_alloc() {
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  return nullptr;
}

EXTERN void *llvm_omp_get_dynamic_shared() {
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  return nullptr;
}

EXTERN [[nodiscard]] void *llvm_omp_target_lock_mem(void *Ptr, size_t Size,
                                                    int DeviceNum) {
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  return targetLockExplicit(Ptr, Size, DeviceNum, __func__);
}

EXTERN void llvm_omp_target_unlock_mem(void *Ptr, int DeviceNum) {
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  targetUnlockExplicit(Ptr, DeviceNum, __func__);
}

EXTERN int omp_target_is_present(const void *Ptr, int DeviceNum) {
  TIMESCOPE();
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  ODBG(ODT_Interface) << "Call to " << __func__ << " for device " << DeviceNum
                      << " and address " << Ptr;

  if (!Ptr) {
    ODBG(ODT_Interface) << "Call to " << __func__
                        << " with NULL ptr, returning false";
    return false;
  }

  if (isInitialDevice(DeviceNum)) {
    ODBG(ODT_Interface) << "Call to " << __func__ << " on host, returning true";
    return true;
  }

  auto DeviceOrErr = PM->getDevice(DeviceNum);
  if (!DeviceOrErr)
    FATAL_MESSAGE(DeviceNum, "%s", toString(DeviceOrErr.takeError()).c_str());

  // omp_target_is_present tests whether a host pointer refers to storage that
  // is mapped to a given device. However, due to the lack of the storage size,
  // only check 1 byte. Cannot set size 0 which checks whether the pointer (zero
  // length array) is mapped instead of the referred storage.
  TargetPointerResultTy TPR =
      DeviceOrErr->getMappingInfo().getTgtPtrBegin(const_cast<void *>(Ptr), 1,
                                                   /*UpdateRefCount=*/false,
                                                   /*UseHoldRefCount=*/false);
  int Rc = TPR.isPresent();
  ODBG(ODT_Interface) << "Call to " << __func__ << " returns " << Rc;
  return Rc;
}

/// Check whether a pointer is accessible from a device.
/// Returns true when accessibility is guaranteed otherwise returns false.
EXTERN int omp_target_is_accessible(const void *Ptr, size_t Size,
                                    int DeviceNum) {
  TIMESCOPE();
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  ODBG(ODT_Interface) << "Call to " << __func__ << " for device " << DeviceNum
                      << ", address " << Ptr << ", size " << Size;

  if (!Ptr) {
    ODBG(ODT_Interface) << "Call to " << __func__
                        << " with NULL ptr returning false";
    return false;
  }

  if (Size == 0) {
    ODBG(ODT_Interface) << "Call to " << __func__
                        << " with zero size returning false";
    return false;
  }

  if (isInitialDevice(DeviceNum)) {
    ODBG(ODT_Interface) << "Call to " << __func__ << " on host, returning true";
    return true;
  }

  // The device number must refer to a valid device
  auto DeviceOrErr = PM->getDevice(DeviceNum);
  if (!DeviceOrErr)
    FATAL_MESSAGE(DeviceNum, "%s", toString(DeviceOrErr.takeError()).c_str());

  return DeviceOrErr->isAccessiblePtr(Ptr, Size);
}

EXTERN int omp_target_memcpy(void *Dst, const void *Src, size_t Length,
                             size_t DstOffset, size_t SrcOffset, int DstDevice,
                             int SrcDevice) {
  TIMESCOPE_WITH_DETAILS("dst_dev=" + std::to_string(DstDevice) +
                         ";src_dev=" + std::to_string(SrcDevice) +
                         ";size=" + std::to_string(Length));
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  ODBG(ODT_Interface) << "Call to " << __func__ << ", dst device " << DstDevice
                      << ", src device " << SrcDevice << ", dst addr " << Dst
                      << ", src addr " << Src << ", dst offset " << DstOffset
                      << ", src offset " << SrcOffset << ", length " << Length;

  if (!Dst || !Src || Length <= 0) {
    if (Length == 0) {
      ODBG(ODT_Interface) << "Call to " << __func__
                          << " with zero length, nothing to do";
      return OFFLOAD_SUCCESS;
    }

    REPORT() << "Call to " << __func__ << " with invalid arguments";
    return OFFLOAD_FAIL;
  }

  int Rc = OFFLOAD_SUCCESS;
  void *SrcAddr = (char *)const_cast<void *>(Src) + SrcOffset;
  void *DstAddr = (char *)Dst + DstOffset;

  if (isInitialDevice(SrcDevice) && isInitialDevice(DstDevice)) {
    ODBG(ODT_Interface) << "copy from host to host";
    const void *P = memcpy(DstAddr, SrcAddr, Length);
    if (P == NULL)
      Rc = OFFLOAD_FAIL;
  } else if (isInitialDevice(SrcDevice)) {
    ODBG(ODT_Interface) << "copy from host to device";
    auto DstDeviceOrErr = PM->getDevice(DstDevice);
    if (!DstDeviceOrErr)
      FATAL_MESSAGE(DstDevice, "%s",
                    toString(DstDeviceOrErr.takeError()).c_str());
    AsyncInfoTy AsyncInfo(*DstDeviceOrErr);
    Rc = DstDeviceOrErr->submitData(DstAddr, SrcAddr, Length, AsyncInfo);
  } else if (isInitialDevice(DstDevice)) {
    ODBG(ODT_Interface) << "copy from device to host";
    auto SrcDeviceOrErr = PM->getDevice(SrcDevice);
    if (!SrcDeviceOrErr)
      FATAL_MESSAGE(SrcDevice, "%s",
                    toString(SrcDeviceOrErr.takeError()).c_str());
    AsyncInfoTy AsyncInfo(*SrcDeviceOrErr);
    Rc = SrcDeviceOrErr->retrieveData(DstAddr, SrcAddr, Length, AsyncInfo);
  } else {
    ODBG(ODT_Interface) << "copy from device to device";
    auto SrcDeviceOrErr = PM->getDevice(SrcDevice);
    if (!SrcDeviceOrErr)
      FATAL_MESSAGE(SrcDevice, "%s",
                    toString(SrcDeviceOrErr.takeError()).c_str());
    auto DstDeviceOrErr = PM->getDevice(DstDevice);
    if (!DstDeviceOrErr)
      FATAL_MESSAGE(DstDevice, "%s",
                    toString(DstDeviceOrErr.takeError()).c_str());
    AsyncInfoTy AsyncInfo(*SrcDeviceOrErr);
    Rc = SrcDeviceOrErr->dataExchange(SrcAddr, *DstDeviceOrErr, DstAddr, Length,
                                      AsyncInfo);
  }

  ODBG(ODT_Interface) << __func__ << " returns " << Rc;
  return Rc;
}

// The helper function that calls omp_target_memcpy or omp_target_memcpy_rect
static int libomp_target_memcpy_async_task(int32_t Gtid, kmp_task_t *Task) {
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  if (Task == nullptr)
    return OFFLOAD_FAIL;

  TargetMemcpyArgsTy *Args = (TargetMemcpyArgsTy *)Task->shareds;

  if (Args == nullptr)
    return OFFLOAD_FAIL;

  // Call blocked version
  int Rc = OFFLOAD_SUCCESS;
  if (Args->IsRectMemcpy) {
    Rc = omp_target_memcpy_rect(
        Args->Dst, Args->Src, Args->ElementSize, Args->NumDims, Args->Volume,
        Args->DstOffsets, Args->SrcOffsets, Args->DstDimensions,
        Args->SrcDimensions, Args->DstDevice, Args->SrcDevice);

    ODBG(ODT_Interface) << " omp_target_memcpy_rect returns " << Rc;
  } else {
    Rc = omp_target_memcpy(Args->Dst, Args->Src, Args->Length, Args->DstOffset,
                           Args->SrcOffset, Args->DstDevice, Args->SrcDevice);

    ODBG(ODT_Interface) << " omp_target_memcpy returns " << Rc;
  }

  // Release the arguments object
  delete Args;

  return Rc;
}

static int libomp_target_memset_async_task(int32_t Gtid, kmp_task_t *Task) {
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  if (!Task)
    return OFFLOAD_FAIL;

  auto *Args = reinterpret_cast<TargetMemsetArgsTy *>(Task->shareds);
  if (!Args)
    return OFFLOAD_FAIL;

  // call omp_target_memset()
  omp_target_memset(Args->Ptr, Args->C, Args->N, Args->DeviceNum);

  delete Args;

  return OFFLOAD_SUCCESS;
}

static inline void
convertDepObjVector(llvm::SmallVector<kmp_depend_info_t> &Vec, int DepObjCount,
                    omp_depend_t *DepObjList) {
  for (int i = 0; i < DepObjCount; ++i) {
    omp_depend_t DepObj = DepObjList[i];
    Vec.push_back(*((kmp_depend_info_t *)DepObj));
  }
}

template <class T>
static inline int
libomp_helper_task_creation(T *Args, int (*Fn)(int32_t, kmp_task_t *),
                            int DepObjCount, omp_depend_t *DepObjList) {
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  // Create global thread ID
  int Gtid = __kmpc_global_thread_num(nullptr);

  // Setup the hidden helper flags
  int32_t Flags = 0;
  kmp_tasking_flags_t *InputFlags = (kmp_tasking_flags_t *)&Flags;
  InputFlags->hidden_helper = 1;

  // Alloc the helper task
  kmp_task_t *Task = __kmpc_omp_target_task_alloc(
      nullptr, Gtid, Flags, sizeof(kmp_task_t), 0, Fn, -1);
  if (!Task) {
    delete Args;
    return OFFLOAD_FAIL;
  }

  // Setup the arguments for the helper task
  Task->shareds = Args;

  // Convert types of depend objects
  llvm::SmallVector<kmp_depend_info_t> DepObjs;
  convertDepObjVector(DepObjs, DepObjCount, DepObjList);

  // Launch the helper task
  int Rc = __kmpc_omp_task_with_deps(nullptr, Gtid, Task, DepObjCount,
                                     DepObjs.data(), 0, nullptr);

  return Rc;
}

EXTERN void *omp_target_memset(void *Ptr, int ByteVal, size_t NumBytes,
                               int DeviceNum) {
  TIMESCOPE();
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  ODBG(ODT_Interface) << "Call to " << __func__ << ", device " << DeviceNum
                      << ", device pointer " << Ptr << ", size " << NumBytes;

  // Behave as a no-op if N==0 or if Ptr is nullptr (as a useful implementation
  // of unspecified behavior, see OpenMP spec).
  if (!Ptr || NumBytes == 0) {
    return Ptr;
  }

  if (isInitialDevice(DeviceNum)) {
    ODBG(ODT_Interface) << "filling memory on host via memset";
    memset(Ptr, ByteVal, NumBytes); // ignore return value, memset() cannot fail
  } else {
    OMPT_IF_BUILT(InterfaceRAII TargetMemsetRAII(
        RegionInterface.getCallbacks<ompt_target_data_memset>(), DeviceNum,
        nullptr, const_cast<void *>(Ptr), NumBytes,
        __builtin_return_address(0)));

    auto DeviceOrErr = PM->getDevice(DeviceNum);
    if (!DeviceOrErr)
      FATAL_MESSAGE(DeviceNum, "%s", toString(DeviceOrErr.takeError()).c_str());
    AsyncInfoTy AsyncInfo(*DeviceOrErr);
    ol_queue_handle_t Queue = AsyncInfo.getQueue();
    if (!Queue) {
      ODBG(ODT_Interface) << "Failed to get queue for async memset on device "
                          << DeviceNum;
      return Ptr;
    }
    if (auto Res = olMemFill(Queue, Ptr, 1, &ByteVal, NumBytes)) {
      ODBG(ODT_Interface)
          << __func__ << " failed to fill memory due to error with dataFill:"
          << Res->Details;
      // If the dataFill failed, let's just not do anything.
      // omp_target_memset does not have any good way to fail.
      // Depending on the RTL implementation, the application will
      // abort anyway.
    }
  }

  ODBG(ODT_Interface) << __func__ << " returns " << Ptr;
  return Ptr;
}

EXTERN void *omp_target_memset_async(void *Ptr, int ByteVal, size_t NumBytes,
                                     int DeviceNum, int DepObjCount,
                                     omp_depend_t *DepObjList) {
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  ODBG(ODT_Interface) << "Call to " << __func__ << ", device " << DeviceNum
                      << ", device pointer " << Ptr << ", size " << NumBytes;

  // Behave as a no-op if N==0 or if Ptr is nullptr (as a useful implementation
  // of unspecified behavior, see OpenMP spec).
  if (!Ptr || NumBytes == 0)
    return Ptr;

  // Create the task object to deal with the async invocation
  auto *Args = new TargetMemsetArgsTy{Ptr, ByteVal, NumBytes, DeviceNum};

  // omp_target_memset_async() cannot fail via a return code, so ignore the
  // return code of the helper function
  (void)libomp_helper_task_creation(Args, &libomp_target_memset_async_task,
                                    DepObjCount, DepObjList);

  return Ptr;
}

EXTERN int omp_target_memcpy_async(void *Dst, const void *Src, size_t Length,
                                   size_t DstOffset, size_t SrcOffset,
                                   int DstDevice, int SrcDevice,
                                   int DepObjCount, omp_depend_t *DepObjList) {
  TIMESCOPE_WITH_DETAILS("dst_dev=" + std::to_string(DstDevice) +
                         ";src_dev=" + std::to_string(SrcDevice) +
                         ";size=" + std::to_string(Length));
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  ODBG(ODT_Interface) << "Call to " << __func__ << ", dst device " << DstDevice
                      << ", src device " << SrcDevice << ", dst addr " << Dst
                      << ", src addr " << Src << ", dst offset " << DstOffset
                      << ", src offset " << SrcOffset << ", length " << Length;

  // Check the source and dest address
  if (Dst == nullptr || Src == nullptr)
    return OFFLOAD_FAIL;

  // Create task object
  TargetMemcpyArgsTy *Args = new TargetMemcpyArgsTy(
      Dst, Src, Length, DstOffset, SrcOffset, DstDevice, SrcDevice);

  // Create and launch helper task
  int Rc = libomp_helper_task_creation(Args, &libomp_target_memcpy_async_task,
                                       DepObjCount, DepObjList);

  ODBG(ODT_Interface) << __func__ << " returns " << Rc;
  return Rc;
}

EXTERN int
omp_target_memcpy_rect(void *Dst, const void *Src, size_t ElementSize,
                       int NumDims, const size_t *Volume,
                       const size_t *DstOffsets, const size_t *SrcOffsets,
                       const size_t *DstDimensions, const size_t *SrcDimensions,
                       int DstDevice, int SrcDevice) {
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  ODBG(ODT_Interface) << "Call to " << __func__ << ", dst device " << DstDevice
                      << ", src device " << SrcDevice << ", dst addr " << Dst
                      << ", src addr " << Src << ", dst offsets " << DstOffsets
                      << ", src offsets " << SrcOffsets << ", dst dims "
                      << DstDimensions << ", src dims " << SrcDimensions
                      << ", volume " << Volume << ", element size "
                      << ElementSize << ", num_dims " << NumDims;

  if (!(Dst || Src)) {
    ODBG(ODT_Interface) << "Call to " << __func__
                        << " returns max supported dimensions " << INT_MAX;
    return INT_MAX;
  }

  if (!Dst || !Src || ElementSize < 1 || NumDims < 1 || !Volume ||
      !DstOffsets || !SrcOffsets || !DstDimensions || !SrcDimensions) {
    REPORT() << "Call to " << __func__ << " with invalid arguments";
    return OFFLOAD_FAIL;
  }

  int Rc;
  if (NumDims == 1) {
    Rc = omp_target_memcpy(Dst, Src, ElementSize * Volume[0],
                           ElementSize * DstOffsets[0],
                           ElementSize * SrcOffsets[0], DstDevice, SrcDevice);
  } else {
    size_t DstSliceSize = ElementSize;
    size_t SrcSliceSize = ElementSize;
    for (int I = 1; I < NumDims; ++I) {
      DstSliceSize *= DstDimensions[I];
      SrcSliceSize *= SrcDimensions[I];
    }

    size_t DstOff = DstOffsets[0] * DstSliceSize;
    size_t SrcOff = SrcOffsets[0] * SrcSliceSize;
    for (size_t I = 0; I < Volume[0]; ++I) {
      Rc = omp_target_memcpy_rect(
          (char *)Dst + DstOff + DstSliceSize * I,
          (char *)const_cast<void *>(Src) + SrcOff + SrcSliceSize * I,
          ElementSize, NumDims - 1, Volume + 1, DstOffsets + 1, SrcOffsets + 1,
          DstDimensions + 1, SrcDimensions + 1, DstDevice, SrcDevice);

      if (Rc) {
        ODBG(ODT_Interface)
            << "Recursive call to " << __func__ << " returns unsuccessfully";
        return Rc;
      }
    }
  }

  ODBG(ODT_Interface) << " returns " << Rc;
  return Rc;
}

EXTERN int omp_target_memcpy_rect_async(
    void *Dst, const void *Src, size_t ElementSize, int NumDims,
    const size_t *Volume, const size_t *DstOffsets, const size_t *SrcOffsets,
    const size_t *DstDimensions, const size_t *SrcDimensions, int DstDevice,
    int SrcDevice, int DepObjCount, omp_depend_t *DepObjList) {
  TIMESCOPE_WITH_DETAILS("dst_dev=" + std::to_string(DstDevice) +
                         ";src_dev=" + std::to_string(SrcDevice) +
                         ";size=" + std::to_string(ElementSize) +
                         ";num_dims=" + std::to_string(NumDims));
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  ODBG(ODT_Interface) << "Call to " << __func__ << ", dst device " << DstDevice
                      << ", src device " << SrcDevice << ", dst addr " << Dst
                      << ", src addr " << Src << ", dst offsets " << DstOffsets
                      << ", src offsets " << SrcOffsets << ", dst dims "
                      << DstDimensions << ", src dims " << SrcDimensions
                      << ", volume " << Volume << ", element size "
                      << ElementSize << ", num_dims " << NumDims;

  // Need to check this first to not return OFFLOAD_FAIL instead
  if (!Dst && !Src) {
    ODBG(ODT_Interface) << "Call to " << __func__
                        << " returns max supported dimensions " << INT_MAX;
    return INT_MAX;
  }

  // Check the source and dest address
  if (Dst == nullptr || Src == nullptr)
    return OFFLOAD_FAIL;

  // Create task object
  TargetMemcpyArgsTy *Args = new TargetMemcpyArgsTy(
      Dst, Src, ElementSize, NumDims, Volume, DstOffsets, SrcOffsets,
      DstDimensions, SrcDimensions, DstDevice, SrcDevice);

  // Create and launch helper task
  int Rc = libomp_helper_task_creation(Args, &libomp_target_memcpy_async_task,
                                       DepObjCount, DepObjList);

  ODBG(ODT_Interface) << __func__ << " returns " << Rc;
  return Rc;
}

EXTERN int omp_target_associate_ptr(const void *HostPtr, const void *DevicePtr,
                                    size_t Size, size_t DeviceOffset,
                                    int DeviceNum) {
  TIMESCOPE();
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  ODBG(ODT_Interface) << "Call to " << __func__ << " with host_ptr " << HostPtr
                      << ", device_ptr " << DevicePtr << ", size " << Size
                      << ", device_offset " << DeviceOffset << ", device_num "
                      << DeviceNum;

  if (!HostPtr || !DevicePtr || Size <= 0) {
    REPORT() << "Call to " << __func__ << " with invalid arguments";
    return OFFLOAD_FAIL;
  }

  if (isInitialDevice(DeviceNum)) {
    REPORT() << __func__ << ": no association possible on the host";
    return OFFLOAD_FAIL;
  }

  auto DeviceOrErr = PM->getDevice(DeviceNum);
  if (!DeviceOrErr)
    FATAL_MESSAGE(DeviceNum, "%s", toString(DeviceOrErr.takeError()).c_str());

  void *DeviceAddr = (void *)((uint64_t)DevicePtr + (uint64_t)DeviceOffset);

  OMPT_IF_BUILT(InterfaceRAII(
      RegionInterface.getCallbacks<ompt_target_data_associate>(), DeviceNum,
      const_cast<void *>(HostPtr), const_cast<void *>(DevicePtr), Size,
      __builtin_return_address(0)));

  int Rc = DeviceOrErr->getMappingInfo().associatePtr(
      const_cast<void *>(HostPtr), const_cast<void *>(DeviceAddr), Size);
  ODBG(ODT_Interface) << __func__ << " returns " << Rc;
  return Rc;
}

EXTERN int omp_target_disassociate_ptr(const void *HostPtr, int DeviceNum) {
  TIMESCOPE();
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  ODBG(ODT_Interface) << "Call to " << __func__ << " with host_ptr " << HostPtr
                      << ", device_num " << DeviceNum;

  if (!HostPtr) {
    REPORT() << "Call to " << __func__ << " with invalid host_ptr";
    return OFFLOAD_FAIL;
  }

  if (isInitialDevice(DeviceNum)) {
    REPORT() << __func__ << ": no association possible on the host";
    return OFFLOAD_FAIL;
  }

  auto DeviceOrErr = PM->getDevice(DeviceNum);
  if (!DeviceOrErr)
    FATAL_MESSAGE(DeviceNum, "%s", toString(DeviceOrErr.takeError()).c_str());

  OMPT_IF_BUILT(InterfaceRAII(
      RegionInterface.getCallbacks<ompt_target_data_disassociate>(), DeviceNum,
      const_cast<void *>(HostPtr),
      /*DevicePtr=*/nullptr, /*Size=*/0, __builtin_return_address(0)));

  int Rc = DeviceOrErr->getMappingInfo().disassociatePtr(
      const_cast<void *>(HostPtr));
  ODBG(ODT_Interface) << __func__ << " returns " << Rc;
  return Rc;
}

EXTERN void *omp_get_mapped_ptr(const void *Ptr, int DeviceNum) {
  TIMESCOPE();
  OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
  ODBG(ODT_Interface) << "Call to " << __func__ << " with ptr " << Ptr
                      << ", device_num " << DeviceNum;

  if (!Ptr) {
    REPORT() << "Call to " << __func__ << " with nullptr.";
    return nullptr;
  }

  int NumDevices = omp_get_initial_device();
  if (isInitialDevice(DeviceNum)) {
    ODBG(ODT_Interface) << "Device " << DeviceNum
                        << " is initial device, returning Ptr " << Ptr;
    return const_cast<void *>(Ptr);
  }

  if (NumDevices <= DeviceNum) {
    ODBG(ODT_Interface) << "DeviceNum " << DeviceNum
                        << " is invalid, returning nullptr.";
    return nullptr;
  }

  auto DeviceOrErr = PM->getDevice(DeviceNum);
  if (!DeviceOrErr)
    FATAL_MESSAGE(DeviceNum, "%s", toString(DeviceOrErr.takeError()).c_str());

  TargetPointerResultTy TPR =
      DeviceOrErr->getMappingInfo().getTgtPtrBegin(const_cast<void *>(Ptr), 1,
                                                   /*UpdateRefCount=*/false,
                                                   /*UseHoldRefCount=*/false);
  if (!TPR.isPresent()) {
    ODBG(ODT_Interface) << "Ptr " << Ptr
                        << "is not present on device %d, returning nullptr.";
    return nullptr;
  }

  ODBG(ODT_Interface) << __func__ << " returns " << TPR.TargetPointer << ".";

  return TPR.TargetPointer;
}

// This routine gets called from the Host RTL at sync points (taskwait, barrier,
// ...) so we can synchronize the necessary objects from the offload side.
EXTERN void __tgt_target_sync(ident_t *loc_ref, int gtid, void *current_task,
                              void *event) {
  if (!RTLAlive)
    return;

  RTLOngoingSyncs++;
  if (!RTLAlive) {
    RTLOngoingSyncs--;
    return;
  }

  syncImplicitInterops(gtid, event);

  RTLOngoingSyncs--;
}
