[llvm] [Offload] Add Error Codes to PluginInterface (PR #138258)
Ross Brunton via llvm-commits
llvm-commits at lists.llvm.org
Fri May 2 05:29:43 PDT 2025
https://github.com/RossBrunton created https://github.com/llvm/llvm-project/pull/138258
A new ErrorCode enumeration is present in PluginInterface which can
be used when returning an llvm::Error from offload and PluginInterface
functions.
This enum must be kept up to sync with liboffload's ol_errc_t enum, so
both are automatically generated from liboffload's enum definition.
Some error codes have also been shuffled around to allow for future
work. Note that this patch only adds the machinery; actual error codes
will be added in a future patch.
Depends on #137339 , please ignore first commit of this MR.
>From 18d142658f185b1a8d0ca12b919f3dd4fff3442c Mon Sep 17 00:00:00 2001
From: Ross Brunton <ross at codeplay.com>
Date: Fri, 25 Apr 2025 15:18:56 +0100
Subject: [PATCH 1/2] [Offload] Ensure all `llvm::Error`s are handled
`llvm::Error`s containing errors must be explicitly handled or an assert
will be raised. With this change, `ol_impl_result_t` can accept and
consume an `llvm::Error` for errors raised by PluginInterface.
Note that there is currently no facility for PluginInterface to
communicate exact error codes, but the constructor is designed in
such a way that it can be easily added later. This MR is to
convert a crash into an error code.
A new test was added, however due to the aforementioned issue with
error codes, it does not pass and instead is disabled.
---
offload/liboffload/include/OffloadImpl.hpp | 14 ++++++++
offload/liboffload/src/OffloadImpl.cpp | 33 ++++++++++---------
.../OffloadAPI/kernel/olGetKernel.cpp | 7 ++++
3 files changed, 39 insertions(+), 15 deletions(-)
diff --git a/offload/liboffload/include/OffloadImpl.hpp b/offload/liboffload/include/OffloadImpl.hpp
index ec470a355309a..48fdc2b884199 100644
--- a/offload/liboffload/include/OffloadImpl.hpp
+++ b/offload/liboffload/include/OffloadImpl.hpp
@@ -19,6 +19,7 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/Error.h"
struct OffloadConfig {
bool TracingEnabled = false;
@@ -88,6 +89,19 @@ struct ol_impl_result_t {
Result = errors().emplace(std::move(Err)).first->get();
}
+ static ol_impl_result_t fromError(llvm::Error &&Error) {
+ ol_errc_t ErrCode;
+ llvm::StringRef Details;
+ llvm::handleAllErrors(std::move(Error), [&](llvm::StringError &Err) {
+ // TODO: PluginInterface doesn't yet have a way to communicate offload
+ // error codes
+ ErrCode = OL_ERRC_UNKNOWN;
+ Details = errorStrs().insert(Err.getMessage()).first->getKeyData();
+ });
+
+ return ol_impl_result_t{ErrCode, Details};
+ }
+
operator ol_result_t() { return Result; }
private:
diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index bef72a7d1851a..b50c7e0f87b7c 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -311,8 +311,7 @@ ol_impl_result_t olMemAlloc_impl(ol_device_handle_t Device,
auto Alloc =
Device->Device->dataAlloc(Size, nullptr, convertOlToPluginAllocTy(Type));
if (!Alloc)
- return {OL_ERRC_OUT_OF_RESOURCES,
- formatv("Could not create allocation on device {0}", Device).str()};
+ return ol_impl_result_t::fromError(Alloc.takeError());
*AllocationOut = *Alloc;
allocInfoMap().insert_or_assign(*Alloc, AllocInfo{Device, Type});
@@ -330,7 +329,7 @@ ol_impl_result_t olMemFree_impl(void *Address) {
auto Res =
Device->Device->dataDelete(Address, convertOlToPluginAllocTy(Type));
if (Res)
- return {OL_ERRC_OUT_OF_RESOURCES, "Could not free allocation"};
+ return ol_impl_result_t::fromError(std::move(Res));
allocInfoMap().erase(Address);
@@ -342,7 +341,7 @@ ol_impl_result_t olCreateQueue_impl(ol_device_handle_t Device,
auto CreatedQueue = std::make_unique<ol_queue_impl_t>(nullptr, Device);
auto Err = Device->Device->initAsyncInfo(&(CreatedQueue->AsyncInfo));
if (Err)
- return {OL_ERRC_UNKNOWN, "Could not initialize stream resource"};
+ return ol_impl_result_t::fromError(std::move(Err));
*Queue = CreatedQueue.release();
return OL_SUCCESS;
@@ -358,7 +357,7 @@ ol_impl_result_t olWaitQueue_impl(ol_queue_handle_t Queue) {
if (Queue->AsyncInfo->Queue) {
auto Err = Queue->Device->Device->synchronize(Queue->AsyncInfo);
if (Err)
- return {OL_ERRC_INVALID_QUEUE, "The queue failed to synchronize"};
+ return ol_impl_result_t::fromError(std::move(Err));
}
// Recreate the stream resource so the queue can be reused
@@ -366,7 +365,7 @@ ol_impl_result_t olWaitQueue_impl(ol_queue_handle_t Queue) {
// it to begin with.
auto Res = Queue->Device->Device->initAsyncInfo(&Queue->AsyncInfo);
if (Res)
- return {OL_ERRC_UNKNOWN, "Could not reinitialize the stream resource"};
+ return ol_impl_result_t::fromError(std::move(Res));
return OL_SUCCESS;
}
@@ -374,7 +373,7 @@ ol_impl_result_t olWaitQueue_impl(ol_queue_handle_t Queue) {
ol_impl_result_t olWaitEvent_impl(ol_event_handle_t Event) {
auto Res = Event->Queue->Device->Device->syncEvent(Event->EventInfo);
if (Res)
- return {OL_ERRC_INVALID_EVENT, "The event failed to synchronize"};
+ return ol_impl_result_t::fromError(std::move(Res));
return OL_SUCCESS;
}
@@ -390,13 +389,17 @@ ol_impl_result_t olDestroyEvent_impl(ol_event_handle_t Event) {
ol_event_handle_t makeEvent(ol_queue_handle_t Queue) {
auto EventImpl = std::make_unique<ol_event_impl_t>(nullptr, Queue);
auto Res = Queue->Device->Device->createEvent(&EventImpl->EventInfo);
- if (Res)
+ if (Res) {
+ llvm::consumeError(std::move(Res));
return nullptr;
+ }
Res = Queue->Device->Device->recordEvent(EventImpl->EventInfo,
Queue->AsyncInfo);
- if (Res)
+ if (Res) {
+ llvm::consumeError(std::move(Res));
return nullptr;
+ }
return EventImpl.release();
}
@@ -422,16 +425,16 @@ ol_impl_result_t olMemcpy_impl(ol_queue_handle_t Queue, void *DstPtr,
if (DstDevice == HostDevice()) {
auto Res = SrcDevice->Device->dataRetrieve(DstPtr, SrcPtr, Size, QueueImpl);
if (Res)
- return {OL_ERRC_UNKNOWN, "The data retrieve operation failed"};
+ return ol_impl_result_t::fromError(std::move(Res));
} else if (SrcDevice == HostDevice()) {
auto Res = DstDevice->Device->dataSubmit(DstPtr, SrcPtr, Size, QueueImpl);
if (Res)
- return {OL_ERRC_UNKNOWN, "The data submit operation failed"};
+ return ol_impl_result_t::fromError(std::move(Res));
} else {
auto Res = SrcDevice->Device->dataExchange(SrcPtr, *DstDevice->Device,
DstPtr, Size, QueueImpl);
if (Res)
- return {OL_ERRC_UNKNOWN, "The data exchange operation failed"};
+ return ol_impl_result_t::fromError(std::move(Res));
}
if (EventOut)
@@ -459,7 +462,7 @@ ol_impl_result_t olCreateProgram_impl(ol_device_handle_t Device,
Device->Device->loadBinary(Device->Device->Plugin, &Prog->DeviceImage);
if (!Res) {
delete Prog;
- return OL_ERRC_INVALID_VALUE;
+ return ol_impl_result_t::fromError(Res.takeError());
}
Prog->Image = *Res;
@@ -483,7 +486,7 @@ ol_impl_result_t olGetKernel_impl(ol_program_handle_t Program,
auto Err = KernelImpl->init(Device, *Program->Image);
if (Err)
- return {OL_ERRC_UNKNOWN, "Could not initialize the kernel"};
+ return ol_impl_result_t::fromError(std::move(Err));
*Kernel = &*KernelImpl;
@@ -526,7 +529,7 @@ olLaunchKernel_impl(ol_queue_handle_t Queue, ol_device_handle_t Device,
AsyncInfoWrapper.finalize(Err);
if (Err)
- return {OL_ERRC_UNKNOWN, "Could not finalize the AsyncInfoWrapper"};
+ return ol_impl_result_t::fromError(std::move(Err));
if (EventOut)
*EventOut = makeEvent(Queue);
diff --git a/offload/unittests/OffloadAPI/kernel/olGetKernel.cpp b/offload/unittests/OffloadAPI/kernel/olGetKernel.cpp
index 097439e19156b..bd1b562eac71e 100644
--- a/offload/unittests/OffloadAPI/kernel/olGetKernel.cpp
+++ b/offload/unittests/OffloadAPI/kernel/olGetKernel.cpp
@@ -29,3 +29,10 @@ TEST_P(olGetKernelTest, InvalidNullKernelPointer) {
ASSERT_ERROR(OL_ERRC_INVALID_NULL_POINTER,
olGetKernel(Program, "foo", nullptr));
}
+
+// Error code returning from plugin interface not yet supported
+TEST_F(olGetKernelTest, DISABLED_InvalidKernelName) {
+ ol_kernel_handle_t Kernel = nullptr;
+ ASSERT_ERROR(OL_ERRC_INVALID_KERNEL_NAME,
+ olGetKernel(Program, "invalid_kernel_name", &Kernel));
+}
>From 6f43c572e53a7b3c89e135ce60440bc1d80c524f Mon Sep 17 00:00:00 2001
From: Ross Brunton <ross at codeplay.com>
Date: Fri, 2 May 2025 12:50:45 +0100
Subject: [PATCH 2/2] [Offload] Add Error Codes to PluginInterface
A new ErrorCode enumeration is present in PluginInterface which can
be used when returning an llvm::Error from offload and PluginInterface
functions.
This enum must be kept up to sync with liboffload's ol_errc_t enum, so
both are automatically generated from liboffload's enum definition.
Some error codes have also been shuffled around to allow for future
work. Note that this patch only adds the machinery; actual error codes
will be added in a future patch.
---
offload/liboffload/API/APIDefs.td | 3 +-
offload/liboffload/API/CMakeLists.txt | 10 ++-
offload/liboffload/API/Common.td | 22 +++--
offload/liboffload/CMakeLists.txt | 2 +
offload/liboffload/include/OffloadImpl.hpp | 14 +++-
.../liboffload/include/generated/OffloadAPI.h | 83 +++++++++----------
.../include/generated/OffloadPrint.hpp | 27 +++---
.../common/include/OffloadErrcodes.inc | 37 +++++++++
.../common/include/PluginInterface.h | 38 ++++++++-
offload/tools/offload-tblgen/APIGen.cpp | 3 +
offload/tools/offload-tblgen/CMakeLists.txt | 3 +-
offload/tools/offload-tblgen/Generators.hpp | 2 +
.../{FuncsGen.cpp => MiscGen.cpp} | 24 ++++++
offload/tools/offload-tblgen/RecordTypes.hpp | 7 ++
.../tools/offload-tblgen/offload-tblgen.cpp | 9 +-
15 files changed, 206 insertions(+), 78 deletions(-)
create mode 100644 offload/plugins-nextgen/common/include/OffloadErrcodes.inc
rename offload/tools/offload-tblgen/{FuncsGen.cpp => MiscGen.cpp} (75%)
diff --git a/offload/liboffload/API/APIDefs.td b/offload/liboffload/API/APIDefs.td
index 640932dcf8464..38508525f1d26 100644
--- a/offload/liboffload/API/APIDefs.td
+++ b/offload/liboffload/API/APIDefs.td
@@ -152,9 +152,10 @@ class Function : APIObject {
AddHandleChecksToReturns<params, returns_with_def>.returns_out>.returns_out;
}
-class Etor<string Name, string Desc> {
+class Etor<string Name, string Desc, int Value=-1> {
string name = Name;
string desc = Desc;
+ int value = Value;
string tagged_type;
}
diff --git a/offload/liboffload/API/CMakeLists.txt b/offload/liboffload/API/CMakeLists.txt
index 8fd6cb539374a..62b8803ca2a13 100644
--- a/offload/liboffload/API/CMakeLists.txt
+++ b/offload/liboffload/API/CMakeLists.txt
@@ -11,13 +11,17 @@ if (CLANG_FORMAT)
tablegen(OFFLOAD OffloadFuncs.inc -gen-func-names)
tablegen(OFFLOAD OffloadImplFuncDecls.inc -gen-impl-func-decls)
tablegen(OFFLOAD OffloadPrint.hpp -gen-print-header)
+ tablegen(OFFLOAD OffloadErrcodes.inc -gen-errcodes)
- set(OFFLOAD_GENERATED_FILES ${TABLEGEN_OUTPUT})
+ set(FILES_TO_COPY "OffloadAPI.h;OffloadEntryPoints.inc;OffloadFuncs.inc;OffloadImplFuncDecls.inc;OffloadPrint.hpp")
+ set(GEN_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../include/generated)
add_public_tablegen_target(OffloadGenerate)
add_custom_command(TARGET OffloadGenerate POST_BUILD COMMAND ${CLANG_FORMAT}
- -i ${OFFLOAD_GENERATED_FILES})
+ -i ${TABLEGEN_OUTPUT})
add_custom_command(TARGET OffloadGenerate POST_BUILD COMMAND ${CMAKE_COMMAND}
- -E copy_if_different ${OFFLOAD_GENERATED_FILES} "${CMAKE_CURRENT_SOURCE_DIR}/../include/generated")
+ -E copy_if_different ${FILES_TO_COPY} ${GEN_DIR})
+ add_custom_command(TARGET OffloadGenerate POST_BUILD COMMAND ${CMAKE_COMMAND}
+ -E copy_if_different OffloadErrcodes.inc "${LIBOFFLOAD_ROOT}/../plugins-nextgen/common/include/OffloadErrcodes.inc")
else()
message(WARNING "clang-format was not found, so the OffloadGenerate target\
will not be available. Offload will still build, but you will not be\
diff --git a/offload/liboffload/API/Common.td b/offload/liboffload/API/Common.td
index de7502b540618..12551d1eb5fd5 100644
--- a/offload/liboffload/API/Common.td
+++ b/offload/liboffload/API/Common.td
@@ -83,26 +83,30 @@ def : Typedef {
let value = "void *";
}
-def : Enum {
+def ErrorCode : Enum {
let name = "ol_errc_t";
let desc = "Defines Return/Error codes";
let etors =[
- Etor<"SUCCESS", "Success">,
- Etor<"INVALID_VALUE", "Invalid Value">,
+ Etor<"SUCCESS", "Success", 0>,
+
+ // Universal errors
+ Etor<"INVALID_NULL_POINTER", "A pointer argument is null when it should not be">,
+ Etor<"INVALID_ARGUMENT", "An argument is invalid">,
+ Etor<"OUT_OF_RESOURCES", "Out of resources">,
+ Etor<"UNSUPPORTED", "generic error code for unsupported features and enums">,
+
+ // Liboffload specific errors
+ Etor<"INVALID_VALUE", "Invalid Value", 0x1000>,
Etor<"INVALID_PLATFORM", "Invalid platform">,
Etor<"INVALID_DEVICE", "Invalid device">,
Etor<"INVALID_QUEUE", "Invalid queue">,
Etor<"INVALID_EVENT", "Invalid event">,
Etor<"INVALID_KERNEL_NAME", "Named kernel not found in the program binary">,
- Etor<"OUT_OF_RESOURCES", "Out of resources">,
- Etor<"UNSUPPORTED_FEATURE", "generic error code for unsupported features">,
- Etor<"INVALID_ARGUMENT", "generic error code for invalid arguments">,
Etor<"INVALID_NULL_HANDLE", "handle argument is not valid">,
- Etor<"INVALID_NULL_POINTER", "pointer argument may not be nullptr">,
Etor<"INVALID_SIZE", "invalid size or dimensions (e.g., must not be zero, or is out of bounds)">,
Etor<"INVALID_ENUMERATION", "enumerator argument is not valid">,
- Etor<"UNSUPPORTED_ENUMERATION", "enumerator argument is not supported by the device">,
- Etor<"UNKNOWN", "Unknown or internal error">
+
+ Etor<"UNKNOWN", "Unknown or internal error", 0x10000>
];
}
diff --git a/offload/liboffload/CMakeLists.txt b/offload/liboffload/CMakeLists.txt
index db12236ddfc7f..9927fa3c3400a 100644
--- a/offload/liboffload/CMakeLists.txt
+++ b/offload/liboffload/CMakeLists.txt
@@ -1,3 +1,5 @@
+set(LIBOFFLOAD_ROOT "${CMAKE_CURRENT_SOURCE_DIR}")
+
add_subdirectory(API)
add_llvm_library(
diff --git a/offload/liboffload/include/OffloadImpl.hpp b/offload/liboffload/include/OffloadImpl.hpp
index 48fdc2b884199..7d2c0c53fc85b 100644
--- a/offload/liboffload/include/OffloadImpl.hpp
+++ b/offload/liboffload/include/OffloadImpl.hpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#pragma once
+#include "PluginInterface.h"
#include <OffloadAPI.h>
#include <iostream>
#include <memory>
@@ -93,9 +94,7 @@ struct ol_impl_result_t {
ol_errc_t ErrCode;
llvm::StringRef Details;
llvm::handleAllErrors(std::move(Error), [&](llvm::StringError &Err) {
- // TODO: PluginInterface doesn't yet have a way to communicate offload
- // error codes
- ErrCode = OL_ERRC_UNKNOWN;
+ ErrCode = GetErrorCode(Err.convertToErrorCode());
Details = errorStrs().insert(Err.getMessage()).first->getKeyData();
});
@@ -105,5 +104,14 @@ struct ol_impl_result_t {
operator ol_result_t() { return Result; }
private:
+ static ol_errc_t GetErrorCode(std::error_code Code) {
+ if (Code.category() == llvm::omp::target::plugin::make_error_code(
+ llvm::omp::target::plugin::ErrorCode::SUCCESS)
+ .category()) {
+ return static_cast<ol_errc_t>(Code.value());
+ }
+ return OL_ERRC_UNKNOWN;
+ }
+
ol_result_t Result;
};
diff --git a/offload/liboffload/include/generated/OffloadAPI.h b/offload/liboffload/include/generated/OffloadAPI.h
index ace31c57cf2f8..13a840ce772fb 100644
--- a/offload/liboffload/include/generated/OffloadAPI.h
+++ b/offload/liboffload/include/generated/OffloadAPI.h
@@ -17,6 +17,45 @@
extern "C" {
#endif
+///////////////////////////////////////////////////////////////////////////////
+/// @brief Defines Return/Error codes
+typedef enum ol_errc_t {
+ /// Success
+ OL_ERRC_SUCCESS = 0,
+ /// A pointer argument is null when it should not be
+ OL_ERRC_INVALID_NULL_POINTER = 1,
+ /// An argument is invalid
+ OL_ERRC_INVALID_ARGUMENT = 2,
+ /// Out of resources
+ OL_ERRC_OUT_OF_RESOURCES = 3,
+ /// generic error code for unsupported features and enums
+ OL_ERRC_UNSUPPORTED = 4,
+ /// Invalid Value
+ OL_ERRC_INVALID_VALUE = 4096,
+ /// Invalid platform
+ OL_ERRC_INVALID_PLATFORM = 4097,
+ /// Invalid device
+ OL_ERRC_INVALID_DEVICE = 4098,
+ /// Invalid queue
+ OL_ERRC_INVALID_QUEUE = 4099,
+ /// Invalid event
+ OL_ERRC_INVALID_EVENT = 4100,
+ /// Named kernel not found in the program binary
+ OL_ERRC_INVALID_KERNEL_NAME = 4101,
+ /// handle argument is not valid
+ OL_ERRC_INVALID_NULL_HANDLE = 4102,
+ /// invalid size or dimensions (e.g., must not be zero, or is out of bounds)
+ OL_ERRC_INVALID_SIZE = 4103,
+ /// enumerator argument is not valid
+ OL_ERRC_INVALID_ENUMERATION = 4104,
+ /// Unknown or internal error
+ OL_ERRC_UNKNOWN = 65536,
+ /// @cond
+ OL_ERRC_FORCE_UINT32 = 0x7fffffff
+ /// @endcond
+
+} ol_errc_t;
+
///////////////////////////////////////////////////////////////////////////////
#ifndef OL_VERSION_MAJOR
/// @brief Major version of the Offload API
@@ -101,47 +140,6 @@ typedef struct ol_program_impl_t *ol_program_handle_t;
/// @brief Handle of kernel object
typedef void *ol_kernel_handle_t;
-///////////////////////////////////////////////////////////////////////////////
-/// @brief Defines Return/Error codes
-typedef enum ol_errc_t {
- /// Success
- OL_ERRC_SUCCESS = 0,
- /// Invalid Value
- OL_ERRC_INVALID_VALUE = 1,
- /// Invalid platform
- OL_ERRC_INVALID_PLATFORM = 2,
- /// Invalid device
- OL_ERRC_INVALID_DEVICE = 3,
- /// Invalid queue
- OL_ERRC_INVALID_QUEUE = 4,
- /// Invalid event
- OL_ERRC_INVALID_EVENT = 5,
- /// Named kernel not found in the program binary
- OL_ERRC_INVALID_KERNEL_NAME = 6,
- /// Out of resources
- OL_ERRC_OUT_OF_RESOURCES = 7,
- /// generic error code for unsupported features
- OL_ERRC_UNSUPPORTED_FEATURE = 8,
- /// generic error code for invalid arguments
- OL_ERRC_INVALID_ARGUMENT = 9,
- /// handle argument is not valid
- OL_ERRC_INVALID_NULL_HANDLE = 10,
- /// pointer argument may not be nullptr
- OL_ERRC_INVALID_NULL_POINTER = 11,
- /// invalid size or dimensions (e.g., must not be zero, or is out of bounds)
- OL_ERRC_INVALID_SIZE = 12,
- /// enumerator argument is not valid
- OL_ERRC_INVALID_ENUMERATION = 13,
- /// enumerator argument is not supported by the device
- OL_ERRC_UNSUPPORTED_ENUMERATION = 14,
- /// Unknown or internal error
- OL_ERRC_UNKNOWN = 15,
- /// @cond
- OL_ERRC_FORCE_UINT32 = 0x7fffffff
- /// @endcond
-
-} ol_errc_t;
-
///////////////////////////////////////////////////////////////////////////////
/// @brief Details of the error condition returned by an API call
typedef struct ol_error_struct_t {
@@ -477,7 +475,8 @@ OL_APIEXPORT ol_result_t OL_APICALL olMemFree(
/// @brief Enqueue a memcpy operation.
///
/// @details
-/// - For host pointers, use the device returned by olGetHostDevice
+/// - For host pointers, use the host device belonging to the
+/// OL_PLATFORM_BACKEND_HOST platform.
/// - If a queue is specified, at least one device must be a non-host device
/// - If a queue is not specified, the memcpy happens synchronously
///
diff --git a/offload/liboffload/include/generated/OffloadPrint.hpp b/offload/liboffload/include/generated/OffloadPrint.hpp
index 7f5e33aea6f73..e99bb2db669fb 100644
--- a/offload/liboffload/include/generated/OffloadPrint.hpp
+++ b/offload/liboffload/include/generated/OffloadPrint.hpp
@@ -49,6 +49,18 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
case OL_ERRC_SUCCESS:
os << "OL_ERRC_SUCCESS";
break;
+ case OL_ERRC_INVALID_NULL_POINTER:
+ os << "OL_ERRC_INVALID_NULL_POINTER";
+ break;
+ case OL_ERRC_INVALID_ARGUMENT:
+ os << "OL_ERRC_INVALID_ARGUMENT";
+ break;
+ case OL_ERRC_OUT_OF_RESOURCES:
+ os << "OL_ERRC_OUT_OF_RESOURCES";
+ break;
+ case OL_ERRC_UNSUPPORTED:
+ os << "OL_ERRC_UNSUPPORTED";
+ break;
case OL_ERRC_INVALID_VALUE:
os << "OL_ERRC_INVALID_VALUE";
break;
@@ -67,30 +79,15 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
case OL_ERRC_INVALID_KERNEL_NAME:
os << "OL_ERRC_INVALID_KERNEL_NAME";
break;
- case OL_ERRC_OUT_OF_RESOURCES:
- os << "OL_ERRC_OUT_OF_RESOURCES";
- break;
- case OL_ERRC_UNSUPPORTED_FEATURE:
- os << "OL_ERRC_UNSUPPORTED_FEATURE";
- break;
- case OL_ERRC_INVALID_ARGUMENT:
- os << "OL_ERRC_INVALID_ARGUMENT";
- break;
case OL_ERRC_INVALID_NULL_HANDLE:
os << "OL_ERRC_INVALID_NULL_HANDLE";
break;
- case OL_ERRC_INVALID_NULL_POINTER:
- os << "OL_ERRC_INVALID_NULL_POINTER";
- break;
case OL_ERRC_INVALID_SIZE:
os << "OL_ERRC_INVALID_SIZE";
break;
case OL_ERRC_INVALID_ENUMERATION:
os << "OL_ERRC_INVALID_ENUMERATION";
break;
- case OL_ERRC_UNSUPPORTED_ENUMERATION:
- os << "OL_ERRC_UNSUPPORTED_ENUMERATION";
- break;
case OL_ERRC_UNKNOWN:
os << "OL_ERRC_UNKNOWN";
break;
diff --git a/offload/plugins-nextgen/common/include/OffloadErrcodes.inc b/offload/plugins-nextgen/common/include/OffloadErrcodes.inc
new file mode 100644
index 0000000000000..146a2cd0ce0bf
--- /dev/null
+++ b/offload/plugins-nextgen/common/include/OffloadErrcodes.inc
@@ -0,0 +1,37 @@
+//===- Auto-generated file, part of the LLVM/Offload project --------------===//
+//
+// 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 OFFLOAD_ERRC
+#error Please define the macro OFFLOAD_ERRCODE(Name, Desc, Value)
+#endif
+
+// Error codes are shared between PluginInterface and liboffload.
+// To add new error codes, add them to offload/liboffload/API/Common.td and run
+// the GenerateOffload target.
+
+OFFLOAD_ERRC(SUCCESS, "Success", 0)
+OFFLOAD_ERRC(INVALID_NULL_POINTER,
+ "A pointer argument is null when it should not be", 1)
+OFFLOAD_ERRC(INVALID_ARGUMENT, "An argument is invalid", 2)
+OFFLOAD_ERRC(OUT_OF_RESOURCES, "Out of resources", 3)
+OFFLOAD_ERRC(UNSUPPORTED,
+ "generic error code for unsupported features and enums", 4)
+OFFLOAD_ERRC(INVALID_VALUE, "Invalid Value", 4096)
+OFFLOAD_ERRC(INVALID_PLATFORM, "Invalid platform", 4097)
+OFFLOAD_ERRC(INVALID_DEVICE, "Invalid device", 4098)
+OFFLOAD_ERRC(INVALID_QUEUE, "Invalid queue", 4099)
+OFFLOAD_ERRC(INVALID_EVENT, "Invalid event", 4100)
+OFFLOAD_ERRC(INVALID_KERNEL_NAME,
+ "Named kernel not found in the program binary", 4101)
+OFFLOAD_ERRC(INVALID_NULL_HANDLE, "handle argument is not valid", 4102)
+OFFLOAD_ERRC(
+ INVALID_SIZE,
+ "invalid size or dimensions (e.g., must not be zero, or is out of bounds)",
+ 4103)
+OFFLOAD_ERRC(INVALID_ENUMERATION, "enumerator argument is not valid", 4104)
+OFFLOAD_ERRC(UNKNOWN, "Unknown or internal error", 65536)
diff --git a/offload/plugins-nextgen/common/include/PluginInterface.h b/offload/plugins-nextgen/common/include/PluginInterface.h
index e54a8afdd3f4f..19fe26b10760b 100644
--- a/offload/plugins-nextgen/common/include/PluginInterface.h
+++ b/offload/plugins-nextgen/common/include/PluginInterface.h
@@ -58,6 +58,30 @@ struct GenericKernelTy;
struct GenericDeviceTy;
struct RecordReplayTy;
+enum class ErrorCode {
+#define OFFLOAD_ERRC(Name, _, Value) Name = Value,
+#include "OffloadErrcodes.inc"
+#undef OFFLOAD_ERRC
+};
+
+class OffloadErrorCategory : public std::error_category {
+ const char *name() const noexcept override { return "Offload Error"; }
+ std::string message(int ev) const override {
+ switch (static_cast<ErrorCode>(ev)) {
+#define OFFLOAD_ERRC(Name, Desc, Value) \
+ case ErrorCode::Name: \
+ return #Desc;
+#include "OffloadErrcodes.inc"
+#undef OFFLOAD_ERRC
+ }
+ }
+};
+
+inline std::error_code make_error_code(ErrorCode EC) {
+ static OffloadErrorCategory Cat{};
+ return {static_cast<int>(EC), Cat};
+}
+
/// Class that wraps the __tgt_async_info to simply its usage. In case the
/// object is constructed without a valid __tgt_async_info, the object will use
/// an internal one and will synchronize the current thread with the pending
@@ -1385,7 +1409,13 @@ static inline Error success() { return Error::success(); }
/// Create a string error.
template <typename... ArgsTy>
static Error error(const char *ErrFmt, ArgsTy... Args) {
- return createStringError(inconvertibleErrorCode(), ErrFmt, Args...);
+ return createStringError(ErrorCode::UNKNOWN, ErrFmt, Args...);
+}
+
+/// Create a string error.
+template <typename... ArgsTy>
+static Error error(ErrorCode Code, const char *ErrFmt, ArgsTy... Args) {
+ return createStringError(Code, ErrFmt, Args...);
}
/// Check the plugin-specific error code and return an error or success
@@ -1596,4 +1626,10 @@ template <typename ResourceRef> class GenericDeviceResourceManagerTy {
} // namespace omp
} // namespace llvm
+namespace std {
+template <>
+struct is_error_code_enum<llvm::omp::target::plugin::ErrorCode>
+ : std::true_type {};
+} // namespace std
+
#endif // OPENMP_LIBOMPTARGET_PLUGINS_COMMON_PLUGININTERFACE_H
diff --git a/offload/tools/offload-tblgen/APIGen.cpp b/offload/tools/offload-tblgen/APIGen.cpp
index 800c9cadfe38b..14f8435c578d7 100644
--- a/offload/tools/offload-tblgen/APIGen.cpp
+++ b/offload/tools/offload-tblgen/APIGen.cpp
@@ -132,6 +132,9 @@ static void ProcessEnum(const EnumRec &Enum, raw_ostream &OS) {
uint32_t EtorVal = 0;
for (const auto &EnumVal : Enum.getValues()) {
+ if (auto NewVal = EnumVal.getEnumValue()) {
+ EtorVal = *NewVal;
+ }
if (Enum.isTyped()) {
OS << MakeComment(
formatv("[{0}] {1}", EnumVal.getTaggedType(), EnumVal.getDesc())
diff --git a/offload/tools/offload-tblgen/CMakeLists.txt b/offload/tools/offload-tblgen/CMakeLists.txt
index e7e7c85490543..613b166d62b4d 100644
--- a/offload/tools/offload-tblgen/CMakeLists.txt
+++ b/offload/tools/offload-tblgen/CMakeLists.txt
@@ -13,7 +13,7 @@ add_tablegen(offload-tblgen OFFLOAD
EXPORT OFFLOAD
APIGen.cpp
EntryPointGen.cpp
- FuncsGen.cpp
+ MiscGen.cpp
GenCommon.hpp
Generators.hpp
offload-tblgen.cpp
@@ -23,4 +23,3 @@ add_tablegen(offload-tblgen OFFLOAD
set(OFFLOAD_TABLEGEN_EXE "${OFFLOAD_TABLEGEN_EXE}" CACHE INTERNAL "")
set(OFFLOAD_TABLEGEN_TARGET "${OFFLOAD_TABLEGEN_TARGET}" CACHE INTERNAL "")
-
diff --git a/offload/tools/offload-tblgen/Generators.hpp b/offload/tools/offload-tblgen/Generators.hpp
index 8b6104c5cd9c6..f3474dfc52e86 100644
--- a/offload/tools/offload-tblgen/Generators.hpp
+++ b/offload/tools/offload-tblgen/Generators.hpp
@@ -21,3 +21,5 @@ void EmitOffloadPrintHeader(const llvm::RecordKeeper &Records,
llvm::raw_ostream &OS);
void EmitOffloadExports(const llvm::RecordKeeper &Records,
llvm::raw_ostream &OS);
+void EmitOffloadErrcodes(const llvm::RecordKeeper &Records,
+ llvm::raw_ostream &OS);
diff --git a/offload/tools/offload-tblgen/FuncsGen.cpp b/offload/tools/offload-tblgen/MiscGen.cpp
similarity index 75%
rename from offload/tools/offload-tblgen/FuncsGen.cpp
rename to offload/tools/offload-tblgen/MiscGen.cpp
index 3238652176198..e0e12ab3af714 100644
--- a/offload/tools/offload-tblgen/FuncsGen.cpp
+++ b/offload/tools/offload-tblgen/MiscGen.cpp
@@ -72,3 +72,27 @@ void EmitOffloadImplFuncDecls(const RecordKeeper &Records, raw_ostream &OS) {
OS << ");\n\n";
}
}
+
+// Emit macro calls for each error enum
+void EmitOffloadErrcodes(const RecordKeeper &Records, raw_ostream &OS) {
+ OS << GenericHeader;
+ OS << R"(
+#ifndef OFFLOAD_ERRC
+#error Please define the macro OFFLOAD_ERRCODE(Name, Desc, Value)
+#endif
+
+// Error codes are shared between PluginInterface and liboffload.
+// To add new error codes, add them to offload/liboffload/API/Common.td and run the GenerateOffload target.
+
+)";
+
+ auto ErrorCodeEnum = EnumRec{Records.getDef("ErrorCode")};
+ uint32_t EtorVal = 0;
+ for (const auto &EnumVal : ErrorCodeEnum.getValues()) {
+ if (auto NewVal = EnumVal.getEnumValue()) {
+ EtorVal = *NewVal;
+ }
+ OS << formatv(TAB_1 "OFFLOAD_ERRC({0}, \"{1}\", {2})\n", EnumVal.getName(),
+ EnumVal.getDesc(), EtorVal++);
+ }
+}
diff --git a/offload/tools/offload-tblgen/RecordTypes.hpp b/offload/tools/offload-tblgen/RecordTypes.hpp
index 686634ed778aa..5969ec311b28e 100644
--- a/offload/tools/offload-tblgen/RecordTypes.hpp
+++ b/offload/tools/offload-tblgen/RecordTypes.hpp
@@ -69,6 +69,13 @@ class EnumValueRec {
StringRef getTaggedType() const {
return rec->getValueAsString("tagged_type");
}
+ std::optional<uint32_t> getEnumValue() const {
+ if (rec->getValueAsInt("value") == -1) {
+ return std::nullopt;
+ } else {
+ return rec->getValueAsInt("value");
+ }
+ }
private:
const Record *rec;
diff --git a/offload/tools/offload-tblgen/offload-tblgen.cpp b/offload/tools/offload-tblgen/offload-tblgen.cpp
index 1912abf5265c7..0509fa3e0fcd5 100644
--- a/offload/tools/offload-tblgen/offload-tblgen.cpp
+++ b/offload/tools/offload-tblgen/offload-tblgen.cpp
@@ -30,7 +30,8 @@ enum ActionType {
GenImplFuncDecls,
GenEntryPoints,
GenPrintHeader,
- GenExports
+ GenExports,
+ GenErrcodes,
};
namespace {
@@ -52,7 +53,8 @@ cl::opt<ActionType> Action(
clEnumValN(GenPrintHeader, "gen-print-header",
"Generate Offload API print header"),
clEnumValN(GenExports, "gen-exports",
- "Generate export file for the Offload library")));
+ "Generate export file for the Offload library"),
+ clEnumValN(GenErrcodes, "gen-errcodes", "Generate Offload Error Code enum")));
}
static bool OffloadTableGenMain(raw_ostream &OS, const RecordKeeper &Records) {
@@ -81,6 +83,9 @@ static bool OffloadTableGenMain(raw_ostream &OS, const RecordKeeper &Records) {
case GenExports:
EmitOffloadExports(Records, OS);
break;
+ case GenErrcodes:
+ EmitOffloadErrcodes(Records, OS);
+ break;
}
return false;
More information about the llvm-commits
mailing list