[llvm] [Offload] Enable querying a kernel's program (PR #142632)

Ross Brunton via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 4 03:28:10 PDT 2025


https://github.com/RossBrunton updated https://github.com/llvm/llvm-project/pull/142632

>From b0fabb337faf5ab9c3a33bb662e092d95ebce487 Mon Sep 17 00:00:00 2001
From: Ross Brunton <ross at codeplay.com>
Date: Tue, 3 Jun 2025 16:12:39 +0100
Subject: [PATCH 1/3] [Offload] Enable querying a kernel's program

Added new entrypoints GetKernelInfo and GetKernelInfoSize for querying
info about a kernel. Currently, the only supported info is the program
handle which was used to create the program.

As part of implementing this, `ol_kernel_handle_t` has been "promoted"
to a real handle type rather than a bitcast.
---
 offload/liboffload/API/Common.td              |  3 +-
 offload/liboffload/API/Kernel.td              | 50 +++++++++++++++++
 offload/liboffload/src/OffloadImpl.cpp        | 39 ++++++++++++-
 offload/unittests/OffloadAPI/CMakeLists.txt   |  4 +-
 .../OffloadAPI/kernel/olGetKernelInfo.cpp     | 55 +++++++++++++++++++
 .../OffloadAPI/kernel/olGetKernelInfoSize.cpp | 20 +++++++
 6 files changed, 166 insertions(+), 5 deletions(-)
 create mode 100644 offload/unittests/OffloadAPI/kernel/olGetKernelInfo.cpp
 create mode 100644 offload/unittests/OffloadAPI/kernel/olGetKernelInfoSize.cpp

diff --git a/offload/liboffload/API/Common.td b/offload/liboffload/API/Common.td
index 7674da0438c29..680396e379f16 100644
--- a/offload/liboffload/API/Common.td
+++ b/offload/liboffload/API/Common.td
@@ -77,10 +77,9 @@ def : Handle {
   let desc = "Handle of program object";
 }
 
-def : Typedef {
+def : Handle {
   let name = "ol_kernel_handle_t";
   let desc = "Handle of kernel object";
-  let value = "void *";
 }
 
 def ErrorCode : Enum {
diff --git a/offload/liboffload/API/Kernel.td b/offload/liboffload/API/Kernel.td
index 247f9c1bf5b6a..e61916d91f2dd 100644
--- a/offload/liboffload/API/Kernel.td
+++ b/offload/liboffload/API/Kernel.td
@@ -10,6 +10,15 @@
 //
 //===----------------------------------------------------------------------===//
 
+def : Enum {
+  let name = "ol_kernel_info_t";
+  let desc = "Supported kernel info.";
+  let is_typed = 1;
+  let etors =[
+    TaggedEtor<"PROGRAM", "ol_program_handle_t", "the program associated with this kernel">,
+  ];
+}
+
 def : Function {
     let name = "olGetKernel";
     let desc = "Get a kernel from the function identified by `KernelName` in the given program.";
@@ -59,3 +68,44 @@ def : Function {
         Return<"OL_ERRC_INVALID_DEVICE", ["If Queue is non-null but does not belong to Device"]>,
     ];
 }
+
+def : Function {
+  let name = "olGetKernelInfo";
+  let desc = "Queries the given property of the device.";
+  let details = [];
+  let params = [
+    Param<"ol_kernel_handle_t", "Kernel", "handle of the kernel instance", PARAM_IN>,
+    Param<"ol_kernel_info_t", "PropName", "type of the info to retrieve", PARAM_IN>,
+    Param<"size_t", "PropSize", "the number of bytes pointed to by PropValue.", PARAM_IN>,
+    TypeTaggedParam<"void*", "PropValue", "array of bytes holding the info. If PropSize is not equal to or greater than the real "
+                    "number of bytes needed to return the info then the OL_ERRC_INVALID_SIZE error is returned and "
+                    "PropValue is not used.", PARAM_OUT, TypeInfo<"PropName" , "PropSize">>
+  ];
+  let returns = [
+    Return<"OL_ERRC_UNSUPPORTED_ENUMERATION", [
+      "If `PropName` is not supported by the kernel."
+    ]>,
+    Return<"OL_ERRC_INVALID_SIZE", [
+      "`PropSize == 0`",
+      "If `PropSize` is less than the real number of bytes needed to return the info."
+    ]>,
+    Return<"OL_ERRC_INVALID_DEVICE">
+  ];
+}
+
+def : Function {
+  let name = "olGetKernelInfoSize";
+  let desc = "Returns the storage size of the given device query.";
+  let details = [];
+  let params = [
+    Param<"ol_kernel_handle_t", "Kernel", "handle of the kernel instance", PARAM_IN>,
+    Param<"ol_kernel_info_t", "PropName", "type of the info to retrieve", PARAM_IN>,
+    Param<"size_t*", "PropSizeRet", "pointer to the number of bytes required to store the query", PARAM_OUT>
+  ];
+  let returns = [
+    Return<"OL_ERRC_UNSUPPORTED_ENUMERATION", [
+      "If `PropName` is not supported by the kernel."
+    ]>,
+    Return<"OL_ERRC_INVALID_DEVICE">
+  ];
+}
diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index 7b67cbba43e68..71aff00052ace 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -85,6 +85,13 @@ struct ol_program_impl_t {
   __tgt_device_image DeviceImage;
 };
 
+struct ol_kernel_impl_t {
+  ol_kernel_impl_t(plugin::GenericKernelTy *Kernel, ol_program_handle_t Program)
+      : Kernel(Kernel), Program(Program) {}
+  plugin::GenericKernelTy *Kernel;
+  ol_program_handle_t Program;
+};
+
 namespace llvm {
 namespace offload {
 
@@ -286,6 +293,34 @@ Error olGetDeviceInfoSize_impl(ol_device_handle_t Device,
   return olGetDeviceInfoImplDetail(Device, PropName, 0, nullptr, PropSizeRet);
 }
 
+Error olGetKernelInfoImplDetail(ol_kernel_handle_t Kernel,
+                                ol_kernel_info_t PropName, size_t PropSize,
+                                void *PropValue, size_t *PropSizeRet) {
+
+  ReturnHelper ReturnValue(PropSize, PropValue, PropSizeRet);
+
+  switch (PropName) {
+  case OL_KERNEL_INFO_PROGRAM:
+    return ReturnValue(Kernel->Program);
+  default:
+    return createOffloadError(ErrorCode::INVALID_ENUMERATION,
+                              "getKernelInfo enum '%i' is invalid", PropName);
+  }
+
+  return Error::success();
+}
+
+Error olGetKernelInfo_impl(ol_kernel_handle_t Kernel, ol_kernel_info_t PropName,
+                           size_t PropSize, void *PropValue) {
+  return olGetKernelInfoImplDetail(Kernel, PropName, PropSize, PropValue,
+                                   nullptr);
+}
+
+Error olGetKernelInfoSize_impl(ol_kernel_handle_t Kernel,
+                               ol_kernel_info_t PropName, size_t *PropSizeRet) {
+  return olGetKernelInfoImplDetail(Kernel, PropName, 0, nullptr, PropSizeRet);
+}
+
 Error olIterateDevices_impl(ol_device_iterate_cb_t Callback, void *UserData) {
   for (auto &Platform : Platforms()) {
     for (auto &Device : Platform.Devices) {
@@ -479,7 +514,7 @@ Error olGetKernel_impl(ol_program_handle_t Program, const char *KernelName,
   if (auto Err = KernelImpl->init(Device, *Program->Image))
     return Err;
 
-  *Kernel = &*KernelImpl;
+  *Kernel = new ol_kernel_impl_t(std::move(&*KernelImpl), Program);
 
   return Error::success();
 }
@@ -514,7 +549,7 @@ Error olLaunchKernel_impl(ol_queue_handle_t Queue, ol_device_handle_t Device,
   // Don't do anything with pointer indirection; use arg data as-is
   LaunchArgs.Flags.IsCUDA = true;
 
-  auto *KernelImpl = reinterpret_cast<GenericKernelTy *>(Kernel);
+  auto *KernelImpl = Kernel->Kernel;
   auto Err = KernelImpl->launch(*DeviceImpl, LaunchArgs.ArgPtrs, nullptr,
                                 LaunchArgs, AsyncInfoWrapper);
 
diff --git a/offload/unittests/OffloadAPI/CMakeLists.txt b/offload/unittests/OffloadAPI/CMakeLists.txt
index 2844b675e5de1..245710e7d8ac4 100644
--- a/offload/unittests/OffloadAPI/CMakeLists.txt
+++ b/offload/unittests/OffloadAPI/CMakeLists.txt
@@ -14,7 +14,9 @@ add_offload_unittest("event"
 
 add_offload_unittest("kernel"
     kernel/olGetKernel.cpp
-    kernel/olLaunchKernel.cpp)
+    kernel/olLaunchKernel.cpp
+    kernel/olGetKernelInfo.cpp
+    kernel/olGetKernelInfoSize.cpp)
 
 add_offload_unittest("memory"
     memory/olMemAlloc.cpp
diff --git a/offload/unittests/OffloadAPI/kernel/olGetKernelInfo.cpp b/offload/unittests/OffloadAPI/kernel/olGetKernelInfo.cpp
new file mode 100644
index 0000000000000..ceaf40fb0d353
--- /dev/null
+++ b/offload/unittests/OffloadAPI/kernel/olGetKernelInfo.cpp
@@ -0,0 +1,55 @@
+//===------- Offload API tests - olGetKernelInfo --------------------------===//
+//
+// 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 <OffloadAPI.h>
+
+#include "../common/Fixtures.hpp"
+
+using olGetKernelInfoTest = OffloadKernelTest;
+OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olGetKernelInfoTest);
+
+TEST_P(olGetKernelInfoTest, SuccessProgram) {
+  ol_program_handle_t ReadProgram;
+  ASSERT_SUCCESS(olGetKernelInfo(Kernel, OL_KERNEL_INFO_PROGRAM,
+                                 sizeof(ol_program_handle_t), &ReadProgram));
+  ASSERT_EQ(Program, ReadProgram);
+}
+
+TEST_P(olGetKernelInfoTest, InvalidNullHandle) {
+  ol_program_handle_t Program;
+  ASSERT_ERROR(OL_ERRC_INVALID_NULL_HANDLE,
+               olGetKernelInfo(nullptr, OL_KERNEL_INFO_PROGRAM, sizeof(Program),
+                               &Program));
+}
+
+TEST_P(olGetKernelInfoTest, InvalidKernelInfoEnumeration) {
+  ol_program_handle_t Program;
+  ASSERT_ERROR(OL_ERRC_INVALID_ENUMERATION,
+               olGetKernelInfo(Kernel, OL_KERNEL_INFO_FORCE_UINT32,
+                               sizeof(Program), &Program));
+}
+
+TEST_P(olGetKernelInfoTest, InvalidSizeZero) {
+  ol_program_handle_t Program;
+  ASSERT_ERROR(OL_ERRC_INVALID_SIZE,
+               olGetKernelInfo(Kernel, OL_KERNEL_INFO_PROGRAM, 0, &Program));
+}
+
+TEST_P(olGetKernelInfoTest, InvalidSizeSmall) {
+  ol_program_handle_t Program;
+  ASSERT_ERROR(OL_ERRC_INVALID_SIZE,
+               olGetKernelInfo(Kernel, OL_KERNEL_INFO_PROGRAM,
+                               sizeof(Program) - 1, &Program));
+}
+
+TEST_P(olGetKernelInfoTest, InvalidNullPointerPropValue) {
+  ol_program_handle_t Program;
+  ASSERT_ERROR(OL_ERRC_INVALID_NULL_POINTER,
+               olGetKernelInfo(Kernel, OL_KERNEL_INFO_PROGRAM, sizeof(Program),
+                               nullptr));
+}
diff --git a/offload/unittests/OffloadAPI/kernel/olGetKernelInfoSize.cpp b/offload/unittests/OffloadAPI/kernel/olGetKernelInfoSize.cpp
new file mode 100644
index 0000000000000..4c726764f4e42
--- /dev/null
+++ b/offload/unittests/OffloadAPI/kernel/olGetKernelInfoSize.cpp
@@ -0,0 +1,20 @@
+//===------- Offload API tests - olGetKernelInfoSize ----------------------===//
+//
+// 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 <OffloadAPI.h>
+
+#include "../common/Fixtures.hpp"
+
+using olGetKernelInfoSizeTest = OffloadKernelTest;
+OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olGetKernelInfoSizeTest);
+
+TEST_P(olGetKernelInfoSizeTest, SuccessProgram) {
+  size_t Size = 0;
+  ASSERT_SUCCESS(olGetKernelInfoSize(Kernel, OL_KERNEL_INFO_PROGRAM, &Size));
+  ASSERT_EQ(Size, sizeof(ol_program_handle_t));
+}

>From 842bdaae6f0f9bc388c1d5437ee167dadd7be88b Mon Sep 17 00:00:00 2001
From: Ross Brunton <ross at codeplay.com>
Date: Tue, 3 Jun 2025 16:26:06 +0100
Subject: [PATCH 2/3] Don't std::move a pointer

---
 offload/liboffload/src/OffloadImpl.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index 71aff00052ace..348dda0f06a5d 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -514,7 +514,7 @@ Error olGetKernel_impl(ol_program_handle_t Program, const char *KernelName,
   if (auto Err = KernelImpl->init(Device, *Program->Image))
     return Err;
 
-  *Kernel = new ol_kernel_impl_t(std::move(&*KernelImpl), Program);
+  *Kernel = new ol_kernel_impl_t(&*KernelImpl, Program);
 
   return Error::success();
 }

>From 3ede7b6d12be2b986aa065d101084c25c4097c52 Mon Sep 17 00:00:00 2001
From: Ross Brunton <ross at codeplay.com>
Date: Wed, 4 Jun 2025 11:27:51 +0100
Subject: [PATCH 3/3] Track down some misrenames

---
 offload/liboffload/API/Common.td | 1 +
 offload/liboffload/API/Kernel.td | 8 ++++----
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/offload/liboffload/API/Common.td b/offload/liboffload/API/Common.td
index 680396e379f16..b3e7000628b58 100644
--- a/offload/liboffload/API/Common.td
+++ b/offload/liboffload/API/Common.td
@@ -112,6 +112,7 @@ def ErrorCode : Enum {
     Etor<"INVALID_DEVICE", "invalid device">,
     Etor<"INVALID_QUEUE", "invalid queue">,
     Etor<"INVALID_EVENT", "invalid event">,
+    Etor<"INVALID_KERNEL", "invalid kernel">,
   ];
 }
 
diff --git a/offload/liboffload/API/Kernel.td b/offload/liboffload/API/Kernel.td
index e61916d91f2dd..765ffdf2f1860 100644
--- a/offload/liboffload/API/Kernel.td
+++ b/offload/liboffload/API/Kernel.td
@@ -71,7 +71,7 @@ def : Function {
 
 def : Function {
   let name = "olGetKernelInfo";
-  let desc = "Queries the given property of the device.";
+  let desc = "Queries the given property of the kernel.";
   let details = [];
   let params = [
     Param<"ol_kernel_handle_t", "Kernel", "handle of the kernel instance", PARAM_IN>,
@@ -89,13 +89,13 @@ def : Function {
       "`PropSize == 0`",
       "If `PropSize` is less than the real number of bytes needed to return the info."
     ]>,
-    Return<"OL_ERRC_INVALID_DEVICE">
+    Return<"OL_ERRC_INVALID_KERNEL">
   ];
 }
 
 def : Function {
   let name = "olGetKernelInfoSize";
-  let desc = "Returns the storage size of the given device query.";
+  let desc = "Returns the storage size of the given kernel query.";
   let details = [];
   let params = [
     Param<"ol_kernel_handle_t", "Kernel", "handle of the kernel instance", PARAM_IN>,
@@ -106,6 +106,6 @@ def : Function {
     Return<"OL_ERRC_UNSUPPORTED_ENUMERATION", [
       "If `PropName` is not supported by the kernel."
     ]>,
-    Return<"OL_ERRC_INVALID_DEVICE">
+    Return<"OL_ERRC_INVALID_KERNEL">
   ];
 }



More information about the llvm-commits mailing list