1//===-- Dynamically loaded offload API ------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Dynamically loads the API provided by the LLVMOffload library. We need to do
10// this dynamically because this tool is used before it is actually built and
11// should be provided even when the user did not specify the offload runtime.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_TOOLS_LLVM_GPU_LOADER_LLVM_GPU_LOADER_H
16#define LLVM_TOOLS_LLVM_GPU_LOADER_LLVM_GPU_LOADER_H
17
18#include "llvm/Support/DynamicLibrary.h"
19#include "llvm/Support/Error.h"
20
21typedef enum ol_alloc_type_t {
22 OL_ALLOC_TYPE_HOST = 0,
23 OL_ALLOC_TYPE_DEVICE = 1,
24 OL_ALLOC_TYPE_FORCE_UINT32 = 0x7fffffff
25} ol_alloc_type_t;
26
27typedef enum ol_device_info_t {
28 OL_DEVICE_INFO_TYPE = 0,
29 OL_DEVICE_INFO_PLATFORM = 1,
30 OL_DEVICE_INFO_FORCE_UINT32 = 0x7fffffff
31} ol_device_info_t;
32
33typedef enum ol_platform_info_t {
34 OL_PLATFORM_INFO_NAME = 0,
35 OL_PLATFORM_INFO_BACKEND = 3,
36 OL_PLATFORM_INFO_FORCE_UINT32 = 0x7fffffff
37} ol_platform_info_t;
38
39typedef enum ol_symbol_kind_t {
40 OL_SYMBOL_KIND_KERNEL = 0,
41 OL_SYMBOL_KIND_GLOBAL_VARIABLE = 1,
42 OL_SYMBOL_KIND_FORCE_UINT32 = 0x7fffffff
43} ol_symbol_kind_t;
44
45typedef enum ol_errc_t {
46 OL_ERRC_SUCCESS = 0,
47 OL_ERRC_FORCE_UINT32 = 0x7fffffff
48} ol_errc_t;
49
50typedef struct ol_error_struct_t {
51 ol_errc_t Code;
52 const char *Details;
53} ol_error_struct_t;
54
55typedef struct ol_dimensions_t {
56 uint32_t x;
57 uint32_t y;
58 uint32_t z;
59} ol_dimensions_t;
60
61typedef struct ol_kernel_launch_size_args_t {
62 size_t Dimensions;
63 struct ol_dimensions_t NumGroups;
64 struct ol_dimensions_t GroupSize;
65 size_t DynSharedMemory;
66} ol_kernel_launch_size_args_t;
67
68typedef enum ol_kernel_launch_prop_type_t {
69 OL_KERNEL_LAUNCH_PROP_TYPE_NONE = 0,
70 OL_KERNEL_LAUNCH_PROP_TYPE_FORCE_UINT32 = 0x7fffffff
71} ol_kernel_launch_prop_type_t;
72
73typedef struct ol_kernel_launch_prop_t {
74 ol_kernel_launch_prop_type_t type;
75 void *data;
76} ol_kernel_launch_prop_t;
77
78typedef enum ol_platform_backend_t {
79 OL_PLATFORM_BACKEND_UNKNOWN = 0,
80 OL_PLATFORM_BACKEND_CUDA = 1,
81 OL_PLATFORM_BACKEND_AMDGPU = 2,
82 OL_PLATFORM_BACKEND_LEVEL_ZERO = 3,
83 OL_PLATFORM_BACKEND_HOST = 4,
84 OL_PLATFORM_BACKEND_LAST = 5,
85 OL_PLATFORM_BACKEND_FORCE_UINT32 = 0x7fffffff
86} ol_platform_backend_t;
87
88typedef enum ol_device_type_t {
89 OL_DEVICE_TYPE_DEFAULT = 0,
90 OL_DEVICE_TYPE_ALL = 1,
91 OL_DEVICE_TYPE_GPU = 2,
92 OL_DEVICE_TYPE_CPU = 3,
93 OL_DEVICE_TYPE_HOST = 4,
94 OL_DEVICE_TYPE_LAST = 5,
95 OL_DEVICE_TYPE_FORCE_UINT32 = 0x7fffffff
96} ol_device_type_t;
97
98typedef struct ol_init_args_t {
99 size_t Size;
100 uint32_t NumPlatforms;
101 const ol_platform_backend_t *Platforms;
102} ol_init_args_t;
103
104#define OL_INIT_ARGS_INIT {sizeof(ol_init_args_t), 0, NULL}
105
106typedef struct ol_device_impl_t *ol_device_handle_t;
107typedef struct ol_platform_impl_t *ol_platform_handle_t;
108typedef struct ol_program_impl_t *ol_program_handle_t;
109typedef struct ol_queue_impl_t *ol_queue_handle_t;
110typedef struct ol_symbol_impl_t *ol_symbol_handle_t;
111typedef struct ol_context_impl_t *ol_context_handle_t;
112typedef const struct ol_error_struct_t *ol_result_t;
113
114typedef bool (*ol_device_iterate_cb_t)(ol_device_handle_t Device,
115 void *UserData);
116
117ol_result_t (*olInit)(const ol_init_args_t *);
118ol_result_t (*olShutDown)();
119
120ol_result_t (*olIterateDevices)(ol_device_iterate_cb_t Callback,
121 void *UserData);
122
123ol_result_t (*olIsValidBinary)(ol_device_handle_t Device, const void *ProgData,
124 size_t ProgDataSize, bool *Valid);
125
126ol_result_t (*olCreateProgram)(ol_device_handle_t Device, const void *ProgData,
127 size_t ProgDataSize,
128 ol_program_handle_t *Program);
129
130ol_result_t (*olDestroyProgram)(ol_program_handle_t Program);
131
132ol_result_t (*olGetSymbol)(ol_program_handle_t Program, const char *Name,
133 ol_symbol_kind_t Kind, ol_symbol_handle_t *Symbol);
134
135ol_result_t (*olLaunchKernel)(
136 ol_queue_handle_t Queue, ol_device_handle_t Device,
137 ol_symbol_handle_t Kernel,
138 const ol_kernel_launch_size_args_t *LaunchSizeArgs,
139 const ol_kernel_launch_prop_t *Properties, size_t NumArgs, void **ArgPtrs,
140 const size_t *ArgSizes);
141
142ol_result_t (*olCreateContext)(size_t DevicesCount, ol_device_handle_t *Devices,
143 ol_context_handle_t *Context);
144
145ol_result_t (*olDestroyContext)(ol_context_handle_t Context);
146
147ol_result_t (*olCreateQueue)(ol_context_handle_t Context,
148 ol_device_handle_t Device,
149 ol_queue_handle_t *Queue);
150
151ol_result_t (*olDestroyQueue)(ol_queue_handle_t Queue);
152
153ol_result_t (*olSyncQueue)(ol_queue_handle_t Queue);
154
155ol_result_t (*olMemAlloc)(ol_device_handle_t Device, ol_alloc_type_t Type,
156 size_t Size, void **AllocationOut);
157
158ol_result_t (*olMemAllocHost)(ol_device_handle_t Device, size_t Size,
159 void **AllocationOut);
160
161ol_result_t (*olMemFree)(void *Address);
162
163ol_result_t (*olMemcpy)(ol_queue_handle_t Queue, void *DstPtr,
164 ol_device_handle_t DstDevice, const void *SrcPtr,
165 ol_device_handle_t SrcDevice, size_t Size);
166
167ol_result_t (*olGetDeviceInfo)(ol_device_handle_t Device,
168 ol_device_info_t PropName, size_t PropSize,
169 void *PropValue);
170
171ol_result_t (*olGetPlatformInfo)(ol_platform_handle_t Platform,
172 ol_platform_info_t PropName, size_t PropSize,
173 void *PropValue);
174
175llvm::Error loadLLVMOffload() {
176 constexpr const char *OffloadLibrary = "libLLVMOffload.so";
177
178 std::string ErrMsg;
179 auto DynlibHandle = std::make_unique<llvm::sys::DynamicLibrary>(
180 args: llvm::sys::DynamicLibrary::getPermanentLibrary(filename: OffloadLibrary, errMsg: &ErrMsg));
181
182 if (!DynlibHandle->isValid())
183 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
184 Fmt: "Failed to dlopen %s: %s", Vals: OffloadLibrary,
185 Vals: ErrMsg.c_str());
186
187#define DYNAMIC_INIT(SYM) \
188 do { \
189 void *Ptr = DynlibHandle->getAddressOfSymbol(#SYM); \
190 if (!Ptr) \
191 return llvm::createStringError( \
192 llvm::inconvertibleErrorCode(), "Missing symbol '%s' in %s", \
193 reinterpret_cast<const char *>(#SYM), OffloadLibrary); \
194 SYM = reinterpret_cast<decltype(SYM)>(Ptr); \
195 } while (0)
196
197 DYNAMIC_INIT(olInit);
198 DYNAMIC_INIT(olShutDown);
199 DYNAMIC_INIT(olIterateDevices);
200 DYNAMIC_INIT(olIsValidBinary);
201 DYNAMIC_INIT(olCreateProgram);
202 DYNAMIC_INIT(olDestroyProgram);
203 DYNAMIC_INIT(olGetSymbol);
204 DYNAMIC_INIT(olLaunchKernel);
205 DYNAMIC_INIT(olCreateContext);
206 DYNAMIC_INIT(olDestroyContext);
207 DYNAMIC_INIT(olCreateQueue);
208 DYNAMIC_INIT(olDestroyQueue);
209 DYNAMIC_INIT(olSyncQueue);
210 DYNAMIC_INIT(olMemAlloc);
211 DYNAMIC_INIT(olMemAllocHost);
212 DYNAMIC_INIT(olMemFree);
213 DYNAMIC_INIT(olMemcpy);
214 DYNAMIC_INIT(olGetDeviceInfo);
215 DYNAMIC_INIT(olGetPlatformInfo);
216#undef DYNAMIC_INIT
217
218 return llvm::Error::success();
219}
220
221#endif // LLVM_TOOLS_LLVM_GPU_LOADER_LLVM_GPU_LOADER_H
222