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_platform_backend_t {
69 OL_PLATFORM_BACKEND_UNKNOWN = 0,
70 OL_PLATFORM_BACKEND_CUDA = 1,
71 OL_PLATFORM_BACKEND_AMDGPU = 2,
72 OL_PLATFORM_BACKEND_LEVEL_ZERO = 3,
73 OL_PLATFORM_BACKEND_HOST = 4,
74 OL_PLATFORM_BACKEND_LAST = 5,
75 OL_PLATFORM_BACKEND_FORCE_UINT32 = 0x7fffffff
76} ol_platform_backend_t;
77
78typedef enum ol_device_type_t {
79 OL_DEVICE_TYPE_DEFAULT = 0,
80 OL_DEVICE_TYPE_ALL = 1,
81 OL_DEVICE_TYPE_GPU = 2,
82 OL_DEVICE_TYPE_CPU = 3,
83 OL_DEVICE_TYPE_HOST = 4,
84 OL_DEVICE_TYPE_LAST = 5,
85 OL_DEVICE_TYPE_FORCE_UINT32 = 0x7fffffff
86} ol_device_type_t;
87
88typedef struct ol_init_args_t {
89 size_t Size;
90 uint32_t NumPlatforms;
91 const ol_platform_backend_t *Platforms;
92} ol_init_args_t;
93
94#define OL_INIT_ARGS_INIT {sizeof(ol_init_args_t), 0, NULL}
95
96typedef struct ol_device_impl_t *ol_device_handle_t;
97typedef struct ol_platform_impl_t *ol_platform_handle_t;
98typedef struct ol_program_impl_t *ol_program_handle_t;
99typedef struct ol_queue_impl_t *ol_queue_handle_t;
100typedef struct ol_symbol_impl_t *ol_symbol_handle_t;
101typedef const struct ol_error_struct_t *ol_result_t;
102
103typedef bool (*ol_device_iterate_cb_t)(ol_device_handle_t Device,
104 void *UserData);
105
106ol_result_t (*olInit)(const ol_init_args_t *);
107ol_result_t (*olShutDown)();
108
109ol_result_t (*olIterateDevices)(ol_device_iterate_cb_t Callback,
110 void *UserData);
111
112ol_result_t (*olIsValidBinary)(ol_device_handle_t Device, const void *ProgData,
113 size_t ProgDataSize, bool *Valid);
114
115ol_result_t (*olCreateProgram)(ol_device_handle_t Device, const void *ProgData,
116 size_t ProgDataSize,
117 ol_program_handle_t *Program);
118
119ol_result_t (*olDestroyProgram)(ol_program_handle_t Program);
120
121ol_result_t (*olGetSymbol)(ol_program_handle_t Program, const char *Name,
122 ol_symbol_kind_t Kind, ol_symbol_handle_t *Symbol);
123
124ol_result_t (*olLaunchKernel)(
125 ol_queue_handle_t Queue, ol_device_handle_t Device,
126 ol_symbol_handle_t Kernel, const void *ArgumentsData, size_t ArgumentsSize,
127 const ol_kernel_launch_size_args_t *LaunchSizeArgs);
128
129ol_result_t (*olCreateQueue)(ol_device_handle_t Device,
130 ol_queue_handle_t *Queue);
131
132ol_result_t (*olDestroyQueue)(ol_queue_handle_t Queue);
133
134ol_result_t (*olSyncQueue)(ol_queue_handle_t Queue);
135
136ol_result_t (*olMemAlloc)(ol_device_handle_t Device, ol_alloc_type_t Type,
137 size_t Size, void **AllocationOut);
138
139ol_result_t (*olMemFree)(void *Address);
140
141ol_result_t (*olMemcpy)(ol_queue_handle_t Queue, void *DstPtr,
142 ol_device_handle_t DstDevice, const void *SrcPtr,
143 ol_device_handle_t SrcDevice, size_t Size);
144
145ol_result_t (*olGetDeviceInfo)(ol_device_handle_t Device,
146 ol_device_info_t PropName, size_t PropSize,
147 void *PropValue);
148
149ol_result_t (*olGetPlatformInfo)(ol_platform_handle_t Platform,
150 ol_platform_info_t PropName, size_t PropSize,
151 void *PropValue);
152
153llvm::Error loadLLVMOffload() {
154 constexpr const char *OffloadLibrary = "libLLVMOffload.so";
155
156 std::string ErrMsg;
157 auto DynlibHandle = std::make_unique<llvm::sys::DynamicLibrary>(
158 args: llvm::sys::DynamicLibrary::getPermanentLibrary(filename: OffloadLibrary, errMsg: &ErrMsg));
159
160 if (!DynlibHandle->isValid())
161 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
162 Fmt: "Failed to dlopen %s: %s", Vals: OffloadLibrary,
163 Vals: ErrMsg.c_str());
164
165#define DYNAMIC_INIT(SYM) \
166 do { \
167 void *Ptr = DynlibHandle->getAddressOfSymbol(#SYM); \
168 if (!Ptr) \
169 return llvm::createStringError( \
170 llvm::inconvertibleErrorCode(), "Missing symbol '%s' in %s", \
171 reinterpret_cast<const char *>(#SYM), OffloadLibrary); \
172 SYM = reinterpret_cast<decltype(SYM)>(Ptr); \
173 } while (0)
174
175 DYNAMIC_INIT(olInit);
176 DYNAMIC_INIT(olShutDown);
177 DYNAMIC_INIT(olIterateDevices);
178 DYNAMIC_INIT(olIsValidBinary);
179 DYNAMIC_INIT(olCreateProgram);
180 DYNAMIC_INIT(olDestroyProgram);
181 DYNAMIC_INIT(olGetSymbol);
182 DYNAMIC_INIT(olLaunchKernel);
183 DYNAMIC_INIT(olCreateQueue);
184 DYNAMIC_INIT(olDestroyQueue);
185 DYNAMIC_INIT(olSyncQueue);
186 DYNAMIC_INIT(olMemAlloc);
187 DYNAMIC_INIT(olMemFree);
188 DYNAMIC_INIT(olMemcpy);
189 DYNAMIC_INIT(olGetDeviceInfo);
190 DYNAMIC_INIT(olGetPlatformInfo);
191#undef DYNAMIC_INIT
192
193 return llvm::Error::success();
194}
195
196#endif // LLVM_TOOLS_LLVM_GPU_LOADER_LLVM_GPU_LOADER_H
197