//===----------------------------------------------------------------------===//
//
// 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 <sycl/__impl/usm_functions.hpp>

#include <detail/device_impl.hpp>
#include <detail/offload/offload_utils.hpp>

#include <OffloadAPI.h>

#include <algorithm>

_LIBSYCL_BEGIN_NAMESPACE_SYCL

// SYCL 2020 4.8.3.2. Device allocation functions.

void *malloc_device(std::size_t numBytes, const device &syclDevice,
                    const context &syclContext, const property_list &propList) {
  return malloc(numBytes, syclDevice, syclContext, usm::alloc::device,
                propList);
}

void *malloc_device(std::size_t numBytes, const queue &syclQueue,
                    const property_list &propList) {
  return malloc_device(numBytes, syclQueue.get_device(),
                       syclQueue.get_context(), propList);
}

// SYCL 2020 4.8.3.3. Host allocation functions.

void *malloc_host(std::size_t numBytes, const context &syclContext,
                  const property_list &propList) {
  auto ContextDevices = syclContext.get_devices();
  assert(!ContextDevices.empty() && "Context can't be created without device");
  if (std::none_of(
          ContextDevices.begin(), ContextDevices.end(),
          [](device Dev) { return Dev.has(aspect::usm_host_allocations); }))
    throw sycl::exception(
        sycl::errc::feature_not_supported,
        "All devices of context do not support host USM allocations.");
  return malloc(numBytes, ContextDevices[0], syclContext, usm::alloc::host,
                propList);
}

void *malloc_host(std::size_t numBytes, const queue &syclQueue,
                  const property_list &propList) {
  return malloc_host(numBytes, syclQueue.get_context(), propList);
}

// SYCL 2020 4.8.3.4. Shared allocation functions.

void *malloc_shared(std::size_t numBytes, const device &syclDevice,
                    const context &syclContext, const property_list &propList) {
  return malloc(numBytes, syclDevice, syclContext, usm::alloc::shared,
                propList);
}

void *malloc_shared(std::size_t numBytes, const queue &syclQueue,
                    const property_list &propList) {
  return malloc_shared(numBytes, syclQueue.get_device(),
                       syclQueue.get_context(), propList);
}

// SYCL 2020 4.8.3.5. Parameterized allocation functions.

static aspect getAspectByAllocationKind(usm::alloc kind) {
  switch (kind) {
  case usm::alloc::host:
    return aspect::usm_host_allocations;
  case usm::alloc::device:
    return aspect::usm_device_allocations;
  case usm::alloc::shared:
    return aspect::usm_shared_allocations;
  case usm::alloc::unknown:
    // usm::alloc::unknown can be returned to user from get_pointer_type but
    // it can't be converted to a valid backend type.
    throw exception(sycl::make_error_code(sycl::errc::invalid),
                    "Invalid USM allocation kind requested");
  }
}

void *malloc(std::size_t numBytes, const device &syclDevice,
             const context &syclContext, usm::alloc kind,
             const property_list &propList) {
  auto ContextDevices = syclContext.get_devices();
  assert(!ContextDevices.empty() && "Context can't be created without device");
  if (std::none_of(ContextDevices.begin(), ContextDevices.end(),
                   [&syclDevice](device Dev) { return Dev == syclDevice; }))
    throw exception(make_error_code(errc::invalid),
                    "Specified device is not contained by specified context.");
  if (!syclDevice.has(getAspectByAllocationKind(kind)))
    throw sycl::exception(
        sycl::errc::feature_not_supported,
        "Device doesn't support requested kind of USM allocation");

  if (!numBytes)
    return nullptr;

  void *Ptr{};
  auto Result = detail::callNoCheck(
      olMemAlloc, detail::getSyclObjImpl(syclDevice)->getOLHandle(),
      detail::getOlAllocType(kind), numBytes, &Ptr);
  return detail::isFailed(Result) ? nullptr : Ptr;
}

void *malloc(std::size_t numBytes, const queue &syclQueue, usm::alloc kind,
             const property_list &propList) {
  return malloc(numBytes, syclQueue.get_device(), syclQueue.get_context(), kind,
                propList);
}

// SYCL 2020 4.8.3.6. Memory deallocation functions.

void free(void *ptr, const context &ctxt) {
  std::ignore = ctxt;
  detail::callAndThrow(olMemFree, ptr);
}

void free(void *ptr, const queue &q) { return free(ptr, q.get_context()); }

_LIBSYCL_END_NAMESPACE_SYCL
