blob: b4eb18c59de306ece6be42c9024fbf6f6cfe80c1 [file] [edit]
//===-- LanguageRuntime.cpp - Kernel language runtime API implementation --===//
//
// 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
//
//===----------------------------------------------------------------------===//
#ifndef LANGUAGE
#error This file should be included, or used, with a LANGUAGE macro set.
#endif
// Rename the generic runtime API before declaring or defining language symbols.
// clang-format off
#include "DefineLanguageNames.inc"
#include "LanguageErrors.h"
#include "LanguageRuntime.h"
// clang-format on
#include "LanguageUtils.h"
#include "State.h"
#include "Stream.h"
#include "Types.h"
#include "OffloadAPI.h"
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace llvm::offload;
Error_t Malloc(void **DevPtr, size_t Size) {
ThreadStateTy &ThreadState = ThreadStateTy::get();
ol_device_handle_t Device = ThreadState.getDefaultDevice();
ol_context_handle_t Context = StateTy::get().getContext();
ol_result_t Result =
olMemAlloc(Context, Device, OL_ALLOC_TYPE_DEVICE, Size, DevPtr);
return convertAndSetLastError(Result);
}
Error_t Free(void *DevPtr) {
ol_context_handle_t Context = StateTy::get().getContext();
ol_result_t Result = olMemFree(Context, DevPtr);
return convertAndSetLastError(Result);
}
Error_t Memcpy(void *Dst, const void *Src, size_t Size, MemcpyKind Kind) {
StateTy &State = StateTy::get();
ThreadStateTy &ThreadState = ThreadStateTy::get();
ol_queue_handle_t Queue = ThreadState.getDefaultQueue();
ol_result_t Result;
switch (Kind) {
case MemcpyHostToHost: {
ol_device_handle_t Host = State.getHostDevice();
Result = olMemcpy(nullptr, Dst, Host, const_cast<void *>(Src), Host, Size);
break;
}
case MemcpyHostToDevice: {
ol_device_handle_t Device = ThreadState.getDefaultDevice();
ol_device_handle_t Host = State.getHostDevice();
Result = olMemcpy(Queue, Dst, Device, const_cast<void *>(Src), Host, Size);
break;
}
case MemcpyDeviceToHost: {
ol_device_handle_t Device = ThreadState.getDefaultDevice();
ol_device_handle_t Host = State.getHostDevice();
Result = olMemcpy(Queue, Dst, Host, const_cast<void *>(Src), Device, Size);
break;
}
case MemcpyDeviceToDevice: {
ol_device_handle_t Device = ThreadState.getDefaultDevice();
Result =
olMemcpy(Queue, Dst, Device, const_cast<void *>(Src), Device, Size);
break;
}
case MemcpyDefault:
FATAL_UNIMPLEMENTED("MemcpyDefault is not implemented yet");
};
if (Result != OL_SUCCESS)
return convertAndSetLastError(Result);
Result = olSyncQueue(Queue);
return convertAndSetLastError(Result);
}
Error_t DeviceSynchronize() {
// TODO: This is not correct. We likely want to pipe this through to the
// plugins.
ThreadStateTy &ThreadState = ThreadStateTy::get();
ol_queue_handle_t Queue = ThreadState.getDefaultQueue();
ol_result_t Result = olSyncQueue(Queue);
return convertAndSetLastError(Result);
}
Error_t GetDevice(int *DeviceNo) {
ThreadStateTy &ThreadState = ThreadStateTy::get();
ol_device_handle_t Device = ThreadState.getDevice(DeviceNo);
if (!Device)
return setLastError(ErrorInvalidDevice);
return setLastError(Success);
}
Error_t GetDeviceCount(int *Count) {
*Count = StateTy::get().getDeviceCount();
return setLastError(Success);
}
Error_t SetDevice(int DeviceNo) {
ThreadStateTy &ThreadState = ThreadStateTy::get();
ol_device_handle_t Device = ThreadState.setDefaultDevice(DeviceNo);
if (!Device)
return setLastError(ErrorInvalidDevice);
assert(Device == ThreadState.getDefaultDevice() &&
"Set Device is not Default Device");
return setLastError(Success);
}
Error_t HostAlloc(void **Ptr, size_t Size, unsigned int Flags) {
ThreadStateTy &ThreadState = ThreadStateTy::get();
ol_device_handle_t Device = ThreadState.getDefaultDevice();
ol_context_handle_t Context = StateTy::get().getContext();
ol_result_t Result = olMemAllocHost(Context, Device, Size, Ptr);
return convertAndSetLastError(Result);
}
Error_t MallocHost(void **Ptr, size_t Size) {
return HostAlloc(Ptr, Size, /* HostAllocDefault */ 0);
}
Error_t FreeHost(void *Ptr) {
ol_context_handle_t Context = StateTy::get().getContext();
ol_result_t Result = olMemFree(Context, Ptr);
return convertAndSetLastError(Result);
}
Error_t GetDeviceProperties(DeviceProp_t *DeviceProp, int DeviceNo) {
ThreadStateTy &ThreadState = ThreadStateTy::get();
ol_device_handle_t Device = ThreadState.getDefaultDevice();
size_t NameSize = 0;
olGetDeviceInfoSize(Device, OL_DEVICE_INFO_NAME, &NameSize);
assert(NameSize <= sizeof(DeviceProp->name) &&
"Device name is too long for DeviceProp_t");
olGetDeviceInfo(Device, OL_DEVICE_INFO_NAME, NameSize, &DeviceProp->name[0]);
olGetDeviceInfo(Device, OL_DEVICE_INFO_GLOBAL_MEM_SIZE, sizeof(size_t),
&DeviceProp->totalGlobalMem);
olGetDeviceInfo(Device, OL_DEVICE_INFO_NUM_COMPUTE_UNITS, sizeof(uint32_t),
&DeviceProp->multiProcessorCount);
olGetDeviceInfo(Device, OL_DEVICE_INFO_NUM_LANES, sizeof(uint32_t),
&DeviceProp->warpSize);
return setLastError(Success);
}
Error_t StreamCreate(Stream_t *Stream) {
if (!Stream)
return setLastError(ErrorInvalidValue);
StateTy &State = StateTy::get();
ThreadStateTy &ThreadState = ThreadStateTy::get();
StreamTy *StreamObj = nullptr;
ol_result_t Result = State.createStream(
ThreadState.getDefaultDevice(), QueueKind::ExplicitBlocking, &StreamObj);
if (Result == OL_SUCCESS)
*Stream = toLanguageStream(StreamObj);
return convertAndSetLastError(Result);
}
Error_t StreamCreateWithFlags(Stream_t *Stream, unsigned int Flags) {
if (!Stream)
return setLastError(ErrorInvalidValue);
if (Flags == StreamDefault)
return StreamCreate(Stream);
if (Flags != StreamNonBlocking)
return setLastError(ErrorInvalidValue);
StateTy &State = StateTy::get();
ThreadStateTy &ThreadState = ThreadStateTy::get();
StreamTy *StreamObj = nullptr;
ol_result_t Result =
State.createStream(ThreadState.getDefaultDevice(),
QueueKind::ExplicitNonBlocking, &StreamObj);
if (Result == OL_SUCCESS)
*Stream = toLanguageStream(StreamObj);
return convertAndSetLastError(Result);
}
Error_t StreamDestroy(Stream_t Stream) {
if (!Stream)
return setLastError(ErrorInvalidValue);
ol_result_t Result = StateTy::get().destroyStream(toInternalStream(Stream));
return convertAndSetLastError(Result);
}
Error_t StreamSynchronize(Stream_t Stream) {
ol_queue_handle_t Queue;
Error_t Err = getQueueFromStream(Stream, &Queue);
if (Err != Success)
return setLastError(Err);
ol_result_t Result = olSyncQueue(Queue);
return convertAndSetLastError(Result);
}
#include "UndefineLanguageNames.inc"