[llvm-branch-commits] [llvm] [offload][omp] Add own Error class to libomptarget (PR #226451)

Alex Duran via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Sep 25 04:09:56 PDT 2026


https://github.com/adurang created https://github.com/llvm/llvm-project/pull/226451

<sub>Stack created with <a href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub>

>From f29fa5d31367901a971030f694d918b0e7eacfaf Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Tue, 8 Sep 2026 08:10:29 -0700
Subject: [PATCH] [offload][omp] Add own Error class to libomptarget

---
 offload/include/OmpAccError.h              | 64 ++++++++++++++++++++++
 offload/libompaccsupport/OmpAccError.cpp   | 43 +++++++++++++++
 offload/libompaccsupport/PluginManager.cpp | 11 ++--
 offload/libompaccsupport/Program.cpp       | 27 +++++----
 offload/libompaccsupport/device.cpp        | 58 +++++++++-----------
 offload/libomptarget/CMakeLists.txt        |  1 +
 6 files changed, 153 insertions(+), 51 deletions(-)
 create mode 100644 offload/include/OmpAccError.h
 create mode 100644 offload/libompaccsupport/OmpAccError.cpp

diff --git a/offload/include/OmpAccError.h b/offload/include/OmpAccError.h
new file mode 100644
index 0000000000000..7aea6f4672e3d
--- /dev/null
+++ b/offload/include/OmpAccError.h
@@ -0,0 +1,64 @@
+//===- OmpAccError.h - Error class for the OpenMP offload RTL -------===//
+//
+// 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 OMPTARGET_OMPACCERROR_H
+#define OMPTARGET_OMPACCERROR_H
+
+#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm::omp::target {
+
+enum class ErrorCode {
+  Unknown,
+  InvalidBinary,
+  InvalidValue,
+  BackendFailure,
+};
+
+} // namespace llvm::omp::target
+
+namespace std {
+template <>
+struct is_error_code_enum<llvm::omp::target::ErrorCode> : std::true_type {};
+} // namespace std
+
+namespace llvm::omp::target {
+
+const std::error_category &OmpAccErrCategory();
+
+inline std::error_code make_error_code(ErrorCode E) {
+  return std::error_code(static_cast<int>(E), OmpAccErrCategory());
+}
+
+/// Error class used by the OpenMP offload runtime (libomptarget).
+class OmpAccError : public llvm::ErrorInfo<OmpAccError, llvm::StringError> {
+public:
+  using ErrorInfo<OmpAccError, StringError>::ErrorInfo;
+
+  OmpAccError(const llvm::Twine &S) : ErrorInfo(S, ErrorCode::Unknown) {}
+
+  static char ID;
+};
+
+/// Create an offload runtime error.
+template <typename... ArgsTy>
+[[maybe_unused]] static llvm::Error
+createError(ErrorCode Code, const char *ErrFmt, ArgsTy... Args) {
+  std::string Buffer;
+  llvm::raw_string_ostream(Buffer) << llvm::format(ErrFmt, Args...);
+  return llvm::make_error<OmpAccError>(Code, Buffer);
+}
+
+inline llvm::Error createError(ErrorCode Code, const char *S) {
+  return llvm::make_error<OmpAccError>(Code, S);
+}
+
+} // namespace llvm::omp::target
+
+#endif
diff --git a/offload/libompaccsupport/OmpAccError.cpp b/offload/libompaccsupport/OmpAccError.cpp
new file mode 100644
index 0000000000000..0f2dc7540e698
--- /dev/null
+++ b/offload/libompaccsupport/OmpAccError.cpp
@@ -0,0 +1,43 @@
+//===- OmpAccError.cpp - Error class for the OpenMP offload RTL -----===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "OmpAccError.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace llvm;
+using namespace llvm::omp::target;
+
+namespace {
+// OmpAccError inherits from llvm::StringError which requires a
+// std::error_code. Once/if that requirement is removed, then this
+// std::error_code machinery can be removed.
+class OmpAccErrorCategory : public std::error_category {
+public:
+  const char *name() const noexcept override { return "llvm.omptarget"; }
+  std::string message(int Condition) const override {
+    switch (static_cast<ErrorCode>(Condition)) {
+    case ErrorCode::Unknown:
+      return "unknown error";
+    case ErrorCode::InvalidBinary:
+      return "invalid binary";
+    case ErrorCode::InvalidValue:
+      return "invalid value";
+    case ErrorCode::BackendFailure:
+      return "backend failure";
+    }
+    llvm_unreachable("Unrecognized offload RTL ErrorCode");
+  }
+};
+} // namespace
+
+const std::error_category &llvm::omp::target::OmpAccErrCategory() {
+  static OmpAccErrorCategory Category;
+  return Category;
+}
+
+char OmpAccError::ID;
diff --git a/offload/libompaccsupport/PluginManager.cpp b/offload/libompaccsupport/PluginManager.cpp
index da57080da0de7..6c01d2cc9624b 100644
--- a/offload/libompaccsupport/PluginManager.cpp
+++ b/offload/libompaccsupport/PluginManager.cpp
@@ -12,6 +12,7 @@
 
 #include "PluginManager.h"
 #include "OffloadPolicy.h"
+#include "OmpAccError.h"
 #include "OpenMP/OMPT/Interface.h"
 #include "Shared/Debug.h"
 #include "Shared/Profile.h"
@@ -27,6 +28,7 @@ using namespace llvm::omp::target::ompt;
 
 using namespace llvm;
 using namespace llvm::sys;
+using namespace llvm::omp::target;
 using namespace llvm::omp::target::debug;
 
 PluginManager *PM = nullptr;
@@ -619,8 +621,8 @@ Expected<DeviceTy &> PluginManager::getDevice(uint32_t DeviceNo) {
   {
     auto ExclusiveDevicesAccessor = getExclusiveDevicesAccessor();
     if (DeviceNo >= ExclusiveDevicesAccessor->size())
-      return error::createOffloadError(
-          error::ErrorCode::INVALID_VALUE,
+      return createError(
+          ErrorCode::InvalidValue,
           "device number '%i' out of range, only %i devices available",
           DeviceNo, ExclusiveDevicesAccessor->size());
 
@@ -630,8 +632,7 @@ Expected<DeviceTy &> PluginManager::getDevice(uint32_t DeviceNo) {
   // Check whether global data has been mapped for this device
   if (DevicePtr->hasPendingImages())
     if (loadImagesOntoDevice(*DevicePtr) != OFFLOAD_SUCCESS)
-      return error::createOffloadError(error::ErrorCode::BACKEND_FAILURE,
-                                       "failed to load images on device '%i'",
-                                       DeviceNo);
+      return createError(ErrorCode::BackendFailure,
+                         "failed to load images on device '%i'", DeviceNo);
   return *DevicePtr;
 }
diff --git a/offload/libompaccsupport/Program.cpp b/offload/libompaccsupport/Program.cpp
index f3842711262f9..58ffc992bb5d4 100644
--- a/offload/libompaccsupport/Program.cpp
+++ b/offload/libompaccsupport/Program.cpp
@@ -7,11 +7,12 @@
 //===----------------------------------------------------------------------===//
 
 #include "Program.h"
-#include "OffloadError.h"
+#include "OmpAccError.h"
 
 #include <cstdint>
 
 using namespace llvm;
+using namespace llvm::omp::target;
 
 // Temporary helper to help transition of libomptarget to liboffload: returns
 // the opaque plugin kernel handle backing a kernel symbol, for use with the
@@ -27,9 +28,8 @@ Expected<ProgramTy> ProgramTy::create(ol_context_handle_t Context,
                      reinterpret_cast<uintptr_t>(Img->ImageStart);
   if (auto Res =
           olCreateProgram(Context, Device, Img->ImageStart, ImageSize, &Handle))
-    return error::createOffloadError(error::ErrorCode::INVALID_BINARY,
-                                     "failed to load binary %p: %s", Img,
-                                     Res->Details);
+    return createError(ErrorCode::InvalidBinary, "failed to load binary %p: %s",
+                       Img, Res->Details);
 
   return ProgramTy(Handle);
 }
@@ -39,17 +39,16 @@ Expected<void *> ProgramTy::getGlobalAddress(const char *Name,
   ol_symbol_handle_t Symbol;
   if (auto Res =
           olGetSymbol(Handle, Name, OL_SYMBOL_KIND_GLOBAL_VARIABLE, &Symbol))
-    return error::createOffloadError(error::ErrorCode::INVALID_BINARY,
-                                     "failed to find global symbol %s: %s",
-                                     Name, Res->Details);
+    return createError(ErrorCode::InvalidBinary,
+                       "failed to find global symbol %s: %s", Name,
+                       Res->Details);
 
   void *Address = nullptr;
   if (auto Res = olGetSymbolInfo(Symbol, OL_SYMBOL_INFO_GLOBAL_VARIABLE_ADDRESS,
                                  sizeof(Address), &Address))
-    return error::createOffloadError(
-        error::ErrorCode::INVALID_BINARY,
-        "failed to get device address of global symbol %s: %s", Name,
-        Res->Details);
+    return createError(ErrorCode::InvalidBinary,
+                       "failed to get device address of global symbol %s: %s",
+                       Name, Res->Details);
 
   if (Size && olGetSymbolInfo(Symbol, OL_SYMBOL_INFO_GLOBAL_VARIABLE_SIZE,
                               sizeof(*Size), Size))
@@ -61,9 +60,9 @@ Expected<void *> ProgramTy::getGlobalAddress(const char *Name,
 Expected<void *> ProgramTy::getKernelAddress(const char *Name) const {
   ol_symbol_handle_t Symbol;
   if (auto Res = olGetSymbol(Handle, Name, OL_SYMBOL_KIND_KERNEL, &Symbol))
-    return error::createOffloadError(error::ErrorCode::INVALID_BINARY,
-                                     "failed to find kernel symbol %s: %s",
-                                     Name, Res->Details);
+    return createError(ErrorCode::InvalidBinary,
+                       "failed to find kernel symbol %s: %s", Name,
+                       Res->Details);
 
   return __ol_tgt_GetKernelFromSymbol(Symbol);
 }
diff --git a/offload/libompaccsupport/device.cpp b/offload/libompaccsupport/device.cpp
index aacfd6b6ec0b2..526715714e7f6 100644
--- a/offload/libompaccsupport/device.cpp
+++ b/offload/libompaccsupport/device.cpp
@@ -12,6 +12,7 @@
 
 #include "device.h"
 #include "OffloadEntry.h"
+#include "OmpAccError.h"
 #include "OpenMP/Mapping.h"
 #include "OpenMP/OMPT/Callback.h"
 #include "OpenMP/OMPT/Interface.h"
@@ -38,6 +39,7 @@
 using namespace llvm::omp::target::ompt;
 #endif
 
+using namespace llvm::omp::target;
 using namespace llvm::omp::target::plugin;
 using namespace llvm::omp::target::debug;
 
@@ -76,9 +78,8 @@ DeviceTy::~DeviceTy() {
 
 llvm::Error DeviceTy::init() {
   if (olCreateContext(1, &DeviceHandle, &Context)) {
-    return error::createOffloadError(error::ErrorCode::BACKEND_FAILURE,
-                                     "failed to create context for device %d\n",
-                                     DeviceID);
+    return createError(ErrorCode::BackendFailure,
+                       "failed to create context for device %d\n", DeviceID);
   }
 
   OMPT_IF_BUILT_AND_INITIALIZED({
@@ -139,9 +140,8 @@ llvm::Error DeviceTy::init() {
         OMPX_RecordReportFilename.get().c_str(),
         OMPX_RecordOutputDir.get().c_str());
     if (Ret != OFFLOAD_SUCCESS)
-      return error::createOffloadError(error::ErrorCode::BACKEND_FAILURE,
-                                       "failed to initialize RR in device %d\n",
-                                       DeviceID);
+      return createError(ErrorCode::BackendFailure,
+                         "failed to initialize RR in device %d\n", DeviceID);
   }
 
   return llvm::Error::success();
@@ -149,9 +149,8 @@ llvm::Error DeviceTy::init() {
 
 llvm::Error DeviceTy::deinit() {
   if (olDestroyContext(Context)) {
-    return error::createOffloadError(
-        error::ErrorCode::BACKEND_FAILURE,
-        "failed to destroy context for device %d\n", DeviceID);
+    return createError(ErrorCode::BackendFailure,
+                       "failed to destroy context for device %d\n", DeviceID);
   }
   return llvm::Error::success();
 }
@@ -207,12 +206,12 @@ setupIndirectCallTable(DeviceTy &Device, __tgt_device_image *Image,
 
       // HstPtr = Entry.Address;
       if (Device.retrieveData(&res, Vtable, PtrSize, AsyncInfo))
-        return error::createOffloadError(error::ErrorCode::INVALID_BINARY,
-                                         "failed to load %s", Entry.SymbolName);
+        return createError(ErrorCode::InvalidBinary, "failed to load %s",
+                           Entry.SymbolName);
       if (Device.synchronize(AsyncInfo))
-        return error::createOffloadError(
-            error::ErrorCode::INVALID_BINARY,
-            "failed to synchronize after retrieving %s", Entry.SymbolName);
+        return createError(ErrorCode::InvalidBinary,
+                           "failed to synchronize after retrieving %s",
+                           Entry.SymbolName);
       // Calculate and emplace entire Vtable from first Vtable byte
       for (uint64_t i = 0; i < Entry.Size / PtrSize; ++i) {
         auto &[HstPtr, DevPtr] = IndirectCallTable.emplace_back();
@@ -234,13 +233,13 @@ setupIndirectCallTable(DeviceTy &Device, __tgt_device_image *Image,
 
       HstPtr = Entry.Address;
       if (Device.retrieveData(&DevPtr, Ptr, Entry.Size, AsyncInfo))
-        return error::createOffloadError(error::ErrorCode::INVALID_BINARY,
-                                         "failed to load %s", Entry.SymbolName);
+        return createError(ErrorCode::InvalidBinary, "failed to load %s",
+                           Entry.SymbolName);
     }
     if (Device.synchronize(AsyncInfo))
-      return error::createOffloadError(
-          error::ErrorCode::INVALID_BINARY,
-          "failed to synchronize after retrieving %s", Entry.SymbolName);
+      return createError(ErrorCode::InvalidBinary,
+                         "failed to synchronize after retrieving %s",
+                         Entry.SymbolName);
   }
 
   // If we do not have any indirect globals we exit early.
@@ -256,14 +255,12 @@ setupIndirectCallTable(DeviceTy &Device, __tgt_device_image *Image,
   void *DevicePtr = Device.allocData(TableSize, nullptr, TARGET_ALLOC_DEVICE);
   if (Device.submitData(DevicePtr, IndirectCallTable.data(), TableSize,
                         AsyncInfo))
-    return error::createOffloadError(error::ErrorCode::INVALID_BINARY,
-                                     "failed to copy data");
+    return createError(ErrorCode::InvalidBinary, "failed to copy data");
   // The IndirectCallTable is on the stack, so we must synchronize to ensure
   // the data is copied before we return.
   if (Device.synchronize(AsyncInfo))
-    return error::createOffloadError(
-        error::ErrorCode::INVALID_BINARY,
-        "failed to synchronize after copying data");
+    return createError(ErrorCode::InvalidBinary,
+                       "failed to synchronize after copying data");
 
   return std::pair<void *, uint64_t>(DevicePtr, IndirectCallTable.size());
 }
@@ -314,8 +311,7 @@ llvm::Expected<ProgramTy> DeviceTy::loadBinary(__tgt_device_image *Img) {
   AsyncInfoTy AsyncInfo(*this);
   if (submitData(DeviceEnvironmentPtr, &DeviceEnvironment,
                  sizeof(DeviceEnvironment), AsyncInfo))
-    return error::createOffloadError(error::ErrorCode::INVALID_BINARY,
-                                     "failed to copy data");
+    return createError(ErrorCode::InvalidBinary, "failed to copy data");
 
   return std::move(Program);
 }
@@ -435,9 +431,8 @@ llvm::Expected<void *> DeviceTy::registerMemory(void *HstPtr, int64_t Size,
   ol_memory_register_flags_t Flags =
       LockMemory ? OL_MEMORY_REGISTER_FLAG_LOCK_MEMORY : 0;
   if (auto Res = olMemRegister(DeviceHandle, HstPtr, Size, Flags, &LockedPtr))
-    return error::createOffloadError(error::ErrorCode::UNKNOWN,
-                                     "failed to lock memory %p: %s", HstPtr,
-                                     Res->Details);
+    return createError(ErrorCode::Unknown, "failed to lock memory %p: %s",
+                       HstPtr, Res->Details);
   return LockedPtr;
 }
 
@@ -445,9 +440,8 @@ llvm::Error DeviceTy::unregisterMemory(void *HstPtr, bool UnlockMemory) {
   ol_memory_register_flags_t Flags =
       UnlockMemory ? OL_MEMORY_REGISTER_FLAG_UNLOCK_MEMORY : 0;
   if (auto Res = olMemUnregister(DeviceHandle, HstPtr, Flags))
-    return error::createOffloadError(error::ErrorCode::UNKNOWN,
-                                     "failed to unlock memory %p: %s", HstPtr,
-                                     Res->Details);
+    return createError(ErrorCode::Unknown, "failed to unlock memory %p: %s",
+                       HstPtr, Res->Details);
   return llvm::Error::success();
 }
 
diff --git a/offload/libomptarget/CMakeLists.txt b/offload/libomptarget/CMakeLists.txt
index 05a1c9b21207e..de7f6b0cbdcda 100644
--- a/offload/libomptarget/CMakeLists.txt
+++ b/offload/libomptarget/CMakeLists.txt
@@ -20,6 +20,7 @@ add_library(omptarget SHARED
   ../libompaccsupport/DeviceImage.cpp
   ../libompaccsupport/Mapping.cpp
   ../libompaccsupport/Program.cpp
+  ../libompaccsupport/OmpAccError.cpp
 
   KernelLanguage/API.cpp
 )



More information about the llvm-branch-commits mailing list