| //===-- 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" |