2121#include " llvm/ADT/StringExtras.h"
2222#include " llvm/ADT/StringRef.h"
2323#include " llvm/ADT/Twine.h"
24+ #include " llvm/Support/Error.h"
2425#include " llvm/Support/ErrorHandling.h"
2526#include " llvm/Support/ErrorOr.h"
2627#include " llvm/Support/MemoryBuffer.h"
@@ -198,38 +199,55 @@ DeviceContext::DeviceContext(llvm::StringRef Platform, std::size_t DeviceId)
198199 }
199200 }
200201
201- if (!FoundGlobalDeviceId. has_value () )
202+ if (!FoundGlobalDeviceId)
202203 FATAL_ERROR (" Invalid DeviceId: " + llvm::Twine (DeviceId) +
203204 " , but the number of available devices on '" + Platform +
204205 " ' is " + llvm::Twine (MatchCount));
205206
206- GlobalDeviceId = FoundGlobalDeviceId. value () ;
207+ GlobalDeviceId = * FoundGlobalDeviceId;
207208 DeviceHandle = Devices[GlobalDeviceId].Handle ;
208209}
209210
210- [[nodiscard]] std::shared_ptr<DeviceImage>
211- DeviceContext::loadBinary (llvm::StringRef Directory, llvm::StringRef BinaryName,
212- llvm::StringRef Extension) const {
211+ [[nodiscard]] llvm::Expected<std::shared_ptr<DeviceImage>>
212+ DeviceContext::loadBinaryImpl (llvm::StringRef Directory,
213+ llvm::StringRef BinaryName) const {
214+ auto Backend = getDevices ()[GlobalDeviceId].Backend ;
215+ llvm::StringRef Extension;
216+
217+ switch (Backend) {
218+ case OL_PLATFORM_BACKEND_AMDGPU:
219+ Extension = " .amdgpu.bin" ;
220+ break ;
221+ case OL_PLATFORM_BACKEND_CUDA:
222+ Extension = " .nvptx64.bin" ;
223+ break ;
224+ default :
225+ llvm_unreachable (" Unsupported backend to infer binary extension" );
226+ }
227+
213228 llvm::SmallString<128 > FullPath (Directory);
214229 llvm::sys::path::append (FullPath, llvm::Twine (BinaryName) + Extension);
215230
216- // For simplicity, this implementation intentionally reads the binary from
217- // disk on every call.
218- //
219- // Other use cases could benefit from a global, thread-safe cache to avoid
220- // redundant file I/O and GPU program creation.
221-
222231 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileOrErr =
223232 llvm::MemoryBuffer::getFile (FullPath);
233+
224234 if (std::error_code ErrorCode = FileOrErr.getError ())
225- FATAL_ERROR (llvm::Twine (" Failed to read device binary file '" ) + FullPath +
226- " ': " + ErrorCode.message ());
235+ return llvm::errorCodeToError (ErrorCode);
227236
228237 std::unique_ptr<llvm::MemoryBuffer> &BinaryData = *FileOrErr;
229238
230239 ol_program_handle_t ProgramHandle = nullptr ;
231- OL_CHECK (olCreateProgram (DeviceHandle, BinaryData->getBufferStart (),
232- BinaryData->getBufferSize (), &ProgramHandle));
240+ const ol_result_t OlResult =
241+ olCreateProgram (DeviceHandle, BinaryData->getBufferStart (),
242+ BinaryData->getBufferSize (), &ProgramHandle);
243+
244+ if (OlResult != OL_SUCCESS) {
245+ llvm::StringRef Details =
246+ OlResult->Details ? OlResult->Details : " No details provided" ;
247+
248+ return llvm::createStringError (llvm::Twine (Details) + " (Code " +
249+ llvm::Twine (OlResult->Code ) + " )" );
250+ }
233251
234252 return std::shared_ptr<DeviceImage>(
235253 new DeviceImage (DeviceHandle, ProgramHandle));
@@ -238,29 +256,46 @@ DeviceContext::loadBinary(llvm::StringRef Directory, llvm::StringRef BinaryName,
238256[[nodiscard]] std::shared_ptr<DeviceImage>
239257DeviceContext::loadBinary (llvm::StringRef Directory,
240258 llvm::StringRef BinaryName) const {
241- auto Backend = getDevices ()[GlobalDeviceId].Backend ;
242- llvm::StringRef Extension;
259+ auto ImageOrErr = loadBinaryImpl (Directory, BinaryName);
243260
244- switch (Backend) {
245- case OL_PLATFORM_BACKEND_AMDGPU:
246- Extension = " .amdgpu.bin" ;
247- break ;
248- case OL_PLATFORM_BACKEND_CUDA:
249- Extension = " .nvptx64.bin" ;
250- break ;
251- default :
252- llvm_unreachable (" Unsupported backend to infer binary extension" );
261+ if (auto Err = ImageOrErr.takeError ())
262+ FATAL_ERROR (llvm::toString (std::move (Err)));
263+
264+ return std::move (*ImageOrErr);
265+ }
266+
267+ [[nodiscard]] std::optional<std::shared_ptr<DeviceImage>>
268+ DeviceContext::tryLoadBinary (llvm::StringRef Directory,
269+ llvm::StringRef BinaryName) const {
270+ auto ImageOrErr = loadBinaryImpl (Directory, BinaryName);
271+
272+ if (auto Err = ImageOrErr.takeError ()) {
273+ llvm::consumeError (std::move (Err));
274+ return std::nullopt ;
253275 }
254276
255- return loadBinary (Directory, BinaryName, Extension );
277+ return std::move (*ImageOrErr );
256278}
257279
258- void DeviceContext::getKernelImpl (
259- ol_program_handle_t ProgramHandle, llvm::StringRef KernelName,
260- ol_symbol_handle_t *KernelHandle) const noexcept {
280+ [[nodiscard]] llvm::Expected<ol_symbol_handle_t >
281+ DeviceContext::getKernelImpl (ol_program_handle_t ProgramHandle,
282+ llvm::StringRef KernelName) const noexcept {
283+ ol_symbol_handle_t KernelHandle = nullptr ;
261284 llvm::SmallString<32 > KernelNameBuffer (KernelName);
262- OL_CHECK (olGetSymbol (ProgramHandle, KernelNameBuffer.c_str (),
263- OL_SYMBOL_KIND_KERNEL, KernelHandle));
285+
286+ const ol_result_t OlResult =
287+ olGetSymbol (ProgramHandle, KernelNameBuffer.c_str (),
288+ OL_SYMBOL_KIND_KERNEL, &KernelHandle);
289+
290+ if (OlResult != OL_SUCCESS) {
291+ llvm::StringRef Details =
292+ OlResult->Details ? OlResult->Details : " No details provided" ;
293+
294+ return llvm::createStringError (llvm::Twine (Details) + " (Code " +
295+ llvm::Twine (OlResult->Code ) + " )" );
296+ }
297+
298+ return KernelHandle;
264299}
265300
266301void DeviceContext::launchKernelImpl (
@@ -277,10 +312,10 @@ void DeviceContext::launchKernelImpl(
277312 KernelArgsSize, &LaunchArgs, nullptr ));
278313}
279314
280- [[nodiscard]] llvm::StringRef DeviceContext::getName () const {
315+ [[nodiscard]] llvm::StringRef DeviceContext::getName () const noexcept {
281316 return getDevices ()[GlobalDeviceId].Name ;
282317}
283318
284- [[nodiscard]] llvm::StringRef DeviceContext::getPlatform () const {
319+ [[nodiscard]] llvm::StringRef DeviceContext::getPlatform () const noexcept {
285320 return getDevices ()[GlobalDeviceId].Platform ;
286321}
0 commit comments