blob: 8e156768a8abad1d12546d08554e25e7e0e1e5ff [file] [log] [blame] [edit]
//===-- Dynamically loaded offload API ------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Dynamically loads the API provided by the LLVMOffload library. We need to do
// this dynamically because this tool is used before it is actually built and
// should be provided even when the user did not specify the offload runtime.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVM_GPU_LOADER_LLVM_GPU_LOADER_H
#define LLVM_TOOLS_LLVM_GPU_LOADER_LLVM_GPU_LOADER_H
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/Error.h"
typedef enum ol_alloc_type_t {
OL_ALLOC_TYPE_HOST = 0,
OL_ALLOC_TYPE_DEVICE = 1,
OL_ALLOC_TYPE_FORCE_UINT32 = 0x7fffffff
} ol_alloc_type_t;
typedef enum ol_device_info_t {
OL_DEVICE_INFO_TYPE = 0,
OL_DEVICE_INFO_PLATFORM = 1,
OL_DEVICE_INFO_FORCE_UINT32 = 0x7fffffff
} ol_device_info_t;
typedef enum ol_platform_info_t {
OL_PLATFORM_INFO_NAME = 0,
OL_PLATFORM_INFO_BACKEND = 3,
OL_PLATFORM_INFO_FORCE_UINT32 = 0x7fffffff
} ol_platform_info_t;
typedef enum ol_symbol_kind_t {
OL_SYMBOL_KIND_KERNEL = 0,
OL_SYMBOL_KIND_GLOBAL_VARIABLE = 1,
OL_SYMBOL_KIND_FORCE_UINT32 = 0x7fffffff
} ol_symbol_kind_t;
typedef enum ol_errc_t {
OL_ERRC_SUCCESS = 0,
OL_ERRC_FORCE_UINT32 = 0x7fffffff
} ol_errc_t;
typedef struct ol_error_struct_t {
ol_errc_t Code;
const char *Details;
} ol_error_struct_t;
typedef struct ol_dimensions_t {
uint32_t x;
uint32_t y;
uint32_t z;
} ol_dimensions_t;
typedef struct ol_kernel_launch_size_args_t {
size_t Dimensions;
struct ol_dimensions_t NumGroups;
struct ol_dimensions_t GroupSize;
size_t DynSharedMemory;
} ol_kernel_launch_size_args_t;
typedef enum ol_platform_backend_t {
OL_PLATFORM_BACKEND_UNKNOWN = 0,
OL_PLATFORM_BACKEND_CUDA = 1,
OL_PLATFORM_BACKEND_AMDGPU = 2,
OL_PLATFORM_BACKEND_LEVEL_ZERO = 3,
OL_PLATFORM_BACKEND_HOST = 4,
OL_PLATFORM_BACKEND_LAST = 5,
OL_PLATFORM_BACKEND_FORCE_UINT32 = 0x7fffffff
} ol_platform_backend_t;
typedef enum ol_device_type_t {
OL_DEVICE_TYPE_DEFAULT = 0,
OL_DEVICE_TYPE_ALL = 1,
OL_DEVICE_TYPE_GPU = 2,
OL_DEVICE_TYPE_CPU = 3,
OL_DEVICE_TYPE_HOST = 4,
OL_DEVICE_TYPE_LAST = 5,
OL_DEVICE_TYPE_FORCE_UINT32 = 0x7fffffff
} ol_device_type_t;
typedef struct ol_init_args_t {
size_t Size;
uint32_t NumPlatforms;
const ol_platform_backend_t *Platforms;
} ol_init_args_t;
#define OL_INIT_ARGS_INIT {sizeof(ol_init_args_t), 0, NULL}
typedef struct ol_device_impl_t *ol_device_handle_t;
typedef struct ol_platform_impl_t *ol_platform_handle_t;
typedef struct ol_program_impl_t *ol_program_handle_t;
typedef struct ol_queue_impl_t *ol_queue_handle_t;
typedef struct ol_symbol_impl_t *ol_symbol_handle_t;
typedef const struct ol_error_struct_t *ol_result_t;
typedef bool (*ol_device_iterate_cb_t)(ol_device_handle_t Device,
void *UserData);
ol_result_t (*olInit)(const ol_init_args_t *);
ol_result_t (*olShutDown)();
ol_result_t (*olIterateDevices)(ol_device_iterate_cb_t Callback,
void *UserData);
ol_result_t (*olIsValidBinary)(ol_device_handle_t Device, const void *ProgData,
size_t ProgDataSize, bool *Valid);
ol_result_t (*olCreateProgram)(ol_device_handle_t Device, const void *ProgData,
size_t ProgDataSize,
ol_program_handle_t *Program);
ol_result_t (*olDestroyProgram)(ol_program_handle_t Program);
ol_result_t (*olGetSymbol)(ol_program_handle_t Program, const char *Name,
ol_symbol_kind_t Kind, ol_symbol_handle_t *Symbol);
ol_result_t (*olLaunchKernel)(
ol_queue_handle_t Queue, ol_device_handle_t Device,
ol_symbol_handle_t Kernel, const void *ArgumentsData, size_t ArgumentsSize,
const ol_kernel_launch_size_args_t *LaunchSizeArgs);
ol_result_t (*olCreateQueue)(ol_device_handle_t Device,
ol_queue_handle_t *Queue);
ol_result_t (*olDestroyQueue)(ol_queue_handle_t Queue);
ol_result_t (*olSyncQueue)(ol_queue_handle_t Queue);
ol_result_t (*olMemAlloc)(ol_device_handle_t Device, ol_alloc_type_t Type,
size_t Size, void **AllocationOut);
ol_result_t (*olMemFree)(void *Address);
ol_result_t (*olMemcpy)(ol_queue_handle_t Queue, void *DstPtr,
ol_device_handle_t DstDevice, const void *SrcPtr,
ol_device_handle_t SrcDevice, size_t Size);
ol_result_t (*olGetDeviceInfo)(ol_device_handle_t Device,
ol_device_info_t PropName, size_t PropSize,
void *PropValue);
ol_result_t (*olGetPlatformInfo)(ol_platform_handle_t Platform,
ol_platform_info_t PropName, size_t PropSize,
void *PropValue);
llvm::Error loadLLVMOffload() {
constexpr const char *OffloadLibrary = "libLLVMOffload.so";
std::string ErrMsg;
auto DynlibHandle = std::make_unique<llvm::sys::DynamicLibrary>(
llvm::sys::DynamicLibrary::getPermanentLibrary(OffloadLibrary, &ErrMsg));
if (!DynlibHandle->isValid())
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"Failed to dlopen %s: %s", OffloadLibrary,
ErrMsg.c_str());
#define DYNAMIC_INIT(SYM) \
do { \
void *Ptr = DynlibHandle->getAddressOfSymbol(#SYM); \
if (!Ptr) \
return llvm::createStringError( \
llvm::inconvertibleErrorCode(), "Missing symbol '%s' in %s", \
reinterpret_cast<const char *>(#SYM), OffloadLibrary); \
SYM = reinterpret_cast<decltype(SYM)>(Ptr); \
} while (0)
DYNAMIC_INIT(olInit);
DYNAMIC_INIT(olShutDown);
DYNAMIC_INIT(olIterateDevices);
DYNAMIC_INIT(olIsValidBinary);
DYNAMIC_INIT(olCreateProgram);
DYNAMIC_INIT(olDestroyProgram);
DYNAMIC_INIT(olGetSymbol);
DYNAMIC_INIT(olLaunchKernel);
DYNAMIC_INIT(olCreateQueue);
DYNAMIC_INIT(olDestroyQueue);
DYNAMIC_INIT(olSyncQueue);
DYNAMIC_INIT(olMemAlloc);
DYNAMIC_INIT(olMemFree);
DYNAMIC_INIT(olMemcpy);
DYNAMIC_INIT(olGetDeviceInfo);
DYNAMIC_INIT(olGetPlatformInfo);
#undef DYNAMIC_INIT
return llvm::Error::success();
}
#endif // LLVM_TOOLS_LLVM_GPU_LOADER_LLVM_GPU_LOADER_H