[llvm-branch-commits] [llvm] [Offload] Refactor device information queries to use new tagging (PR #147318)

2025-07-07 Thread Ross Brunton via llvm-branch-commits

https://github.com/RossBrunton created 
https://github.com/llvm/llvm-project/pull/147318

Instead using strings to look up device information (which is brittle
and slow), use the new tags that the plugins specify when building the
nodes.


>From 4cce1eec173637a0e50655e10ad520a9821b9960 Mon Sep 17 00:00:00 2001
From: Ross Brunton 
Date: Mon, 7 Jul 2025 16:13:32 +0100
Subject: [PATCH] [Offload] Refactor device information queries to use new
 tagging

Instead using strings to look up device information (which is brittle
and slow), use the new tags that the plugins specify when building the
nodes.
---
 offload/liboffload/src/Helpers.hpp |  19 ++---
 offload/liboffload/src/OffloadImpl.cpp | 111 +++--
 2 files changed, 54 insertions(+), 76 deletions(-)

diff --git a/offload/liboffload/src/Helpers.hpp 
b/offload/liboffload/src/Helpers.hpp
index 8b85945508b98..62e55e500fac7 100644
--- a/offload/liboffload/src/Helpers.hpp
+++ b/offload/liboffload/src/Helpers.hpp
@@ -75,23 +75,16 @@ class InfoWriter {
   InfoWriter(InfoWriter &) = delete;
   ~InfoWriter() = default;
 
-  template  llvm::Error write(llvm::Expected &&Val) {
-if (Val)
-  return getInfo(Size, Target, SizeRet, *Val);
-return Val.takeError();
+  template  llvm::Error write(T Val) {
+return getInfo(Size, Target, SizeRet, Val);
   }
 
-  template 
-  llvm::Error writeArray(llvm::Expected &&Val, size_t Elems) {
-if (Val)
-  return getInfoArray(Elems, Size, Target, SizeRet, *Val);
-return Val.takeError();
+  template  llvm::Error writeArray(T Val, size_t Elems) {
+return getInfoArray(Elems, Size, Target, SizeRet, Val);
   }
 
-  llvm::Error writeString(llvm::Expected &&Val) {
-if (Val)
-  return getInfoString(Size, Target, SizeRet, *Val);
-return Val.takeError();
+  llvm::Error writeString(llvm::StringRef Val) {
+return getInfoString(Size, Target, SizeRet, Val);
   }
 
 private:
diff --git a/offload/liboffload/src/OffloadImpl.cpp 
b/offload/liboffload/src/OffloadImpl.cpp
index f9da638436705..c84bf01460252 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -286,78 +286,63 @@ Error olGetDeviceInfoImplDetail(ol_device_handle_t Device,
 return Plugin::error(ErrorCode::UNIMPLEMENTED, ErrBuffer.c_str());
   };
 
-  // Find the info if it exists under any of the given names
-  auto getInfoString =
-  [&](std::vector Names) -> llvm::Expected {
-for (auto &Name : Names) {
-  if (auto Entry = Device->Info.get(Name)) {
-if (!std::holds_alternative((*Entry)->Value))
-  return makeError(ErrorCode::BACKEND_FAILURE,
-   "plugin returned incorrect type");
-return std::get((*Entry)->Value).c_str();
-  }
-}
-
-return makeError(ErrorCode::UNIMPLEMENTED,
- "plugin did not provide a response for this information");
-  };
-
-  auto getInfoXyz =
-  [&](std::vector Names) -> llvm::Expected {
-for (auto &Name : Names) {
-  if (auto Entry = Device->Info.get(Name)) {
-auto Node = *Entry;
-ol_dimensions_t Out{0, 0, 0};
-
-auto getField = [&](StringRef Name, uint32_t &Dest) {
-  if (auto F = Node->get(Name)) {
-if (!std::holds_alternative((*F)->Value))
-  return makeError(
-  ErrorCode::BACKEND_FAILURE,
-  "plugin returned incorrect type for dimensions element");
-Dest = std::get((*F)->Value);
-  } else
-return makeError(ErrorCode::BACKEND_FAILURE,
- "plugin didn't provide all values for 
dimensions");
-  return Plugin::success();
-};
-
-if (auto Res = getField("x", Out.x))
-  return Res;
-if (auto Res = getField("y", Out.y))
-  return Res;
-if (auto Res = getField("z", Out.z))
-  return Res;
-
-return Out;
-  }
-}
+  // These are not implemented by the plugin interface
+  if (PropName == OL_DEVICE_INFO_PLATFORM)
+return Info.write(Device->Platform);
+  if (PropName == OL_DEVICE_INFO_TYPE)
+return Info.write(OL_DEVICE_TYPE_GPU);
+  // TODO: Update when https://github.com/llvm/llvm-project/pull/147314 is 
merged
+  if (PropName > OL_DEVICE_INFO_MAX_WORK_GROUP_SIZE)
+return createOffloadError(ErrorCode::INVALID_ENUMERATION,
+  "getDeviceInfo enum '%i' is invalid", PropName);
 
+  auto EntryOpt = Device->Info.get(static_cast(PropName));
+  if (!EntryOpt)
 return makeError(ErrorCode::UNIMPLEMENTED,
  "plugin did not provide a response for this information");
-  };
+  auto Entry = *EntryOpt;
 
   switch (PropName) {
-  case OL_DEVICE_INFO_PLATFORM:
-return Info.write(Device->Platform);
-  case OL_DEVICE_INFO_TYPE:
-return Info.write(OL_DEVICE_TYPE_GPU);
   case OL_DEVICE_INFO_NAME:
-return Info.writeString(getInfoString({"Device Name"}));
   case OL_DEVICE_INFO_VENDOR:

[llvm-branch-commits] [llvm] [Offload] Allow "tagging" device info entries with offload keys (PR #147317)

2025-07-07 Thread Ross Brunton via llvm-branch-commits

https://github.com/RossBrunton created 
https://github.com/llvm/llvm-project/pull/147317

When generating the device info tree, nodes can be marked with an
offload Device Info value. The nodes can also look up children based
on this value.


>From 9b79557e7a536ccd4b02365c9dd98a4ef69f87e1 Mon Sep 17 00:00:00 2001
From: Ross Brunton 
Date: Mon, 7 Jul 2025 16:10:19 +0100
Subject: [PATCH] [Offload] Allow "tagging" device info entries with offload
 keys

When generating the device info tree, nodes can be marked with an
offload Device Info value. The nodes can also look up children based
on this value.
---
 offload/plugins-nextgen/amdgpu/src/rtl.cpp| 11 +---
 .../common/include/PluginInterface.h  | 27 ---
 offload/plugins-nextgen/cuda/src/rtl.cpp  |  8 +++---
 3 files changed, 36 insertions(+), 10 deletions(-)

diff --git a/offload/plugins-nextgen/amdgpu/src/rtl.cpp 
b/offload/plugins-nextgen/amdgpu/src/rtl.cpp
index 832c31c43b5d2..52ea3283b24ef 100644
--- a/offload/plugins-nextgen/amdgpu/src/rtl.cpp
+++ b/offload/plugins-nextgen/amdgpu/src/rtl.cpp
@@ -2562,7 +2562,8 @@ struct AMDGPUDeviceTy : public GenericDeviceTy, 
AMDGenericDeviceTy {
 Status2 = hsa_system_get_info(HSA_SYSTEM_INFO_VERSION_MINOR, &Minor);
 if (Status == HSA_STATUS_SUCCESS && Status2 == HSA_STATUS_SUCCESS)
   Info.add("HSA Runtime Version",
-   std::to_string(Major) + "." + std::to_string(Minor));
+   std::to_string(Major) + "." + std::to_string(Minor), "",
+   DeviceInfo::DRIVER_VERSION);
 
 Info.add("HSA OpenMP Device Number", DeviceId);
 
@@ -2572,11 +2573,11 @@ struct AMDGPUDeviceTy : public GenericDeviceTy, 
AMDGenericDeviceTy {
 
 Status = getDeviceAttrRaw(HSA_AGENT_INFO_NAME, TmpChar);
 if (Status == HSA_STATUS_SUCCESS)
-  Info.add("Device Name", TmpChar);
+  Info.add("Device Name", TmpChar, "", DeviceInfo::NAME);
 
 Status = getDeviceAttrRaw(HSA_AGENT_INFO_VENDOR_NAME, TmpChar);
 if (Status == HSA_STATUS_SUCCESS)
-  Info.add("Vendor Name", TmpChar);
+  Info.add("Vendor Name", TmpChar, "", DeviceInfo::VENDOR);
 
 hsa_device_type_t DevType;
 Status = getDeviceAttrRaw(HSA_AGENT_INFO_DEVICE, DevType);
@@ -2652,7 +2653,9 @@ struct AMDGPUDeviceTy : public GenericDeviceTy, 
AMDGenericDeviceTy {
 
 Status = getDeviceAttrRaw(HSA_AGENT_INFO_WORKGROUP_MAX_DIM, WorkgrpMaxDim);
 if (Status == HSA_STATUS_SUCCESS) {
-  auto &MaxSize = *Info.add("Workgroup Max Size per Dimension");
+  auto &MaxSize =
+  *Info.add("Workgroup Max Size per Dimension", std::monostate{}, "",
+DeviceInfo::MAX_WORK_GROUP_SIZE);
   MaxSize.add("x", WorkgrpMaxDim[0]);
   MaxSize.add("y", WorkgrpMaxDim[1]);
   MaxSize.add("z", WorkgrpMaxDim[2]);
diff --git a/offload/plugins-nextgen/common/include/PluginInterface.h 
b/offload/plugins-nextgen/common/include/PluginInterface.h
index b5addc13d6644..9dc01ca0277fe 100644
--- a/offload/plugins-nextgen/common/include/PluginInterface.h
+++ b/offload/plugins-nextgen/common/include/PluginInterface.h
@@ -113,6 +113,12 @@ struct AsyncInfoWrapperTy {
   __tgt_async_info *AsyncInfoPtr;
 };
 
+enum class DeviceInfo {
+#define OFFLOAD_DEVINFO(Name, _, Value) Name = Value,
+#include "OffloadInfo.inc"
+#undef OFFLOAD_DEVINFO
+};
+
 /// Tree node for device information
 ///
 /// This information is either printed or used by liboffload to extract certain
@@ -133,6 +139,8 @@ struct InfoTreeNode {
   // * The same key can appear multiple times
   std::unique_ptr> Children;
 
+  std::map DeviceInfoMap;
+
   InfoTreeNode() : InfoTreeNode("", std::monostate{}, "") {}
   InfoTreeNode(std::string Key, VariantType Value, std::string Units)
   : Key(Key), Value(Value), Units(Units) {}
@@ -140,10 +148,12 @@ struct InfoTreeNode {
   /// Add a new info entry as a child of this node. The entry requires at least
   /// a key string in \p Key. The value in \p Value is optional and can be any
   /// type that is representable as a string. The units in \p Units is optional
-  /// and must be a string.
+  /// and must be a string. Providing a device info key allows liboffload to
+  /// use that value for an appropriate olGetDeviceInfo query
   template 
   InfoTreeNode *add(std::string Key, T Value = T(),
-const std::string &Units = std::string()) {
+const std::string &Units = std::string(),
+std::optional DeviceInfoKey = std::nullopt) {
 assert(!Key.empty() && "Invalid info key");
 
 if (!Children)
@@ -157,7 +167,12 @@ struct InfoTreeNode {
 else
   ValueVariant = std::string{Value};
 
-return &Children->emplace_back(Key, ValueVariant, Units);
+auto Ptr = &Children->emplace_back(Key, ValueVariant, Units);
+
+if (DeviceInfoKey)
+  DeviceInfoMap[*DeviceInfoKey] = Children->size() - 1;
+
+return Ptr;
   }
 
   std::optional get(StringRef Key) {
@@ -171,6 +186,12 @@ struct InfoTreeNode {
  

[llvm-branch-commits] [llvm] [Offload] Allow "tagging" device info entries with offload keys (PR #147317)

2025-07-08 Thread Ross Brunton via llvm-branch-commits

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

>From 9b79557e7a536ccd4b02365c9dd98a4ef69f87e1 Mon Sep 17 00:00:00 2001
From: Ross Brunton 
Date: Mon, 7 Jul 2025 16:10:19 +0100
Subject: [PATCH 1/2] [Offload] Allow "tagging" device info entries with
 offload keys

When generating the device info tree, nodes can be marked with an
offload Device Info value. The nodes can also look up children based
on this value.
---
 offload/plugins-nextgen/amdgpu/src/rtl.cpp| 11 +---
 .../common/include/PluginInterface.h  | 27 ---
 offload/plugins-nextgen/cuda/src/rtl.cpp  |  8 +++---
 3 files changed, 36 insertions(+), 10 deletions(-)

diff --git a/offload/plugins-nextgen/amdgpu/src/rtl.cpp 
b/offload/plugins-nextgen/amdgpu/src/rtl.cpp
index 832c31c43b5d2..52ea3283b24ef 100644
--- a/offload/plugins-nextgen/amdgpu/src/rtl.cpp
+++ b/offload/plugins-nextgen/amdgpu/src/rtl.cpp
@@ -2562,7 +2562,8 @@ struct AMDGPUDeviceTy : public GenericDeviceTy, 
AMDGenericDeviceTy {
 Status2 = hsa_system_get_info(HSA_SYSTEM_INFO_VERSION_MINOR, &Minor);
 if (Status == HSA_STATUS_SUCCESS && Status2 == HSA_STATUS_SUCCESS)
   Info.add("HSA Runtime Version",
-   std::to_string(Major) + "." + std::to_string(Minor));
+   std::to_string(Major) + "." + std::to_string(Minor), "",
+   DeviceInfo::DRIVER_VERSION);
 
 Info.add("HSA OpenMP Device Number", DeviceId);
 
@@ -2572,11 +2573,11 @@ struct AMDGPUDeviceTy : public GenericDeviceTy, 
AMDGenericDeviceTy {
 
 Status = getDeviceAttrRaw(HSA_AGENT_INFO_NAME, TmpChar);
 if (Status == HSA_STATUS_SUCCESS)
-  Info.add("Device Name", TmpChar);
+  Info.add("Device Name", TmpChar, "", DeviceInfo::NAME);
 
 Status = getDeviceAttrRaw(HSA_AGENT_INFO_VENDOR_NAME, TmpChar);
 if (Status == HSA_STATUS_SUCCESS)
-  Info.add("Vendor Name", TmpChar);
+  Info.add("Vendor Name", TmpChar, "", DeviceInfo::VENDOR);
 
 hsa_device_type_t DevType;
 Status = getDeviceAttrRaw(HSA_AGENT_INFO_DEVICE, DevType);
@@ -2652,7 +2653,9 @@ struct AMDGPUDeviceTy : public GenericDeviceTy, 
AMDGenericDeviceTy {
 
 Status = getDeviceAttrRaw(HSA_AGENT_INFO_WORKGROUP_MAX_DIM, WorkgrpMaxDim);
 if (Status == HSA_STATUS_SUCCESS) {
-  auto &MaxSize = *Info.add("Workgroup Max Size per Dimension");
+  auto &MaxSize =
+  *Info.add("Workgroup Max Size per Dimension", std::monostate{}, "",
+DeviceInfo::MAX_WORK_GROUP_SIZE);
   MaxSize.add("x", WorkgrpMaxDim[0]);
   MaxSize.add("y", WorkgrpMaxDim[1]);
   MaxSize.add("z", WorkgrpMaxDim[2]);
diff --git a/offload/plugins-nextgen/common/include/PluginInterface.h 
b/offload/plugins-nextgen/common/include/PluginInterface.h
index b5addc13d6644..9dc01ca0277fe 100644
--- a/offload/plugins-nextgen/common/include/PluginInterface.h
+++ b/offload/plugins-nextgen/common/include/PluginInterface.h
@@ -113,6 +113,12 @@ struct AsyncInfoWrapperTy {
   __tgt_async_info *AsyncInfoPtr;
 };
 
+enum class DeviceInfo {
+#define OFFLOAD_DEVINFO(Name, _, Value) Name = Value,
+#include "OffloadInfo.inc"
+#undef OFFLOAD_DEVINFO
+};
+
 /// Tree node for device information
 ///
 /// This information is either printed or used by liboffload to extract certain
@@ -133,6 +139,8 @@ struct InfoTreeNode {
   // * The same key can appear multiple times
   std::unique_ptr> Children;
 
+  std::map DeviceInfoMap;
+
   InfoTreeNode() : InfoTreeNode("", std::monostate{}, "") {}
   InfoTreeNode(std::string Key, VariantType Value, std::string Units)
   : Key(Key), Value(Value), Units(Units) {}
@@ -140,10 +148,12 @@ struct InfoTreeNode {
   /// Add a new info entry as a child of this node. The entry requires at least
   /// a key string in \p Key. The value in \p Value is optional and can be any
   /// type that is representable as a string. The units in \p Units is optional
-  /// and must be a string.
+  /// and must be a string. Providing a device info key allows liboffload to
+  /// use that value for an appropriate olGetDeviceInfo query
   template 
   InfoTreeNode *add(std::string Key, T Value = T(),
-const std::string &Units = std::string()) {
+const std::string &Units = std::string(),
+std::optional DeviceInfoKey = std::nullopt) {
 assert(!Key.empty() && "Invalid info key");
 
 if (!Children)
@@ -157,7 +167,12 @@ struct InfoTreeNode {
 else
   ValueVariant = std::string{Value};
 
-return &Children->emplace_back(Key, ValueVariant, Units);
+auto Ptr = &Children->emplace_back(Key, ValueVariant, Units);
+
+if (DeviceInfoKey)
+  DeviceInfoMap[*DeviceInfoKey] = Children->size() - 1;
+
+return Ptr;
   }
 
   std::optional get(StringRef Key) {
@@ -171,6 +186,12 @@ struct InfoTreeNode {
 return It;
   }
 
+  std::optional get(DeviceInfo Info) {
+if (DeviceInfoMap.count(Info))
+  return &(*Children)[DeviceInfoMap[Info]];
+ 

[llvm-branch-commits] [llvm] [Offload] Refactor device information queries to use new tagging (PR #147318)

2025-07-08 Thread Ross Brunton via llvm-branch-commits

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

>From 0550a48a4794312063b27a342d68f708ccf55684 Mon Sep 17 00:00:00 2001
From: Ross Brunton 
Date: Mon, 7 Jul 2025 16:13:32 +0100
Subject: [PATCH 1/2] [Offload] Refactor device information queries to use new
 tagging

Instead using strings to look up device information (which is brittle
and slow), use the new tags that the plugins specify when building the
nodes.
---
 offload/liboffload/src/Helpers.hpp |  19 ++---
 offload/liboffload/src/OffloadImpl.cpp | 111 +++--
 2 files changed, 54 insertions(+), 76 deletions(-)

diff --git a/offload/liboffload/src/Helpers.hpp 
b/offload/liboffload/src/Helpers.hpp
index 8b85945508b98..62e55e500fac7 100644
--- a/offload/liboffload/src/Helpers.hpp
+++ b/offload/liboffload/src/Helpers.hpp
@@ -75,23 +75,16 @@ class InfoWriter {
   InfoWriter(InfoWriter &) = delete;
   ~InfoWriter() = default;
 
-  template  llvm::Error write(llvm::Expected &&Val) {
-if (Val)
-  return getInfo(Size, Target, SizeRet, *Val);
-return Val.takeError();
+  template  llvm::Error write(T Val) {
+return getInfo(Size, Target, SizeRet, Val);
   }
 
-  template 
-  llvm::Error writeArray(llvm::Expected &&Val, size_t Elems) {
-if (Val)
-  return getInfoArray(Elems, Size, Target, SizeRet, *Val);
-return Val.takeError();
+  template  llvm::Error writeArray(T Val, size_t Elems) {
+return getInfoArray(Elems, Size, Target, SizeRet, Val);
   }
 
-  llvm::Error writeString(llvm::Expected &&Val) {
-if (Val)
-  return getInfoString(Size, Target, SizeRet, *Val);
-return Val.takeError();
+  llvm::Error writeString(llvm::StringRef Val) {
+return getInfoString(Size, Target, SizeRet, Val);
   }
 
 private:
diff --git a/offload/liboffload/src/OffloadImpl.cpp 
b/offload/liboffload/src/OffloadImpl.cpp
index f9da638436705..c84bf01460252 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -286,78 +286,63 @@ Error olGetDeviceInfoImplDetail(ol_device_handle_t Device,
 return Plugin::error(ErrorCode::UNIMPLEMENTED, ErrBuffer.c_str());
   };
 
-  // Find the info if it exists under any of the given names
-  auto getInfoString =
-  [&](std::vector Names) -> llvm::Expected {
-for (auto &Name : Names) {
-  if (auto Entry = Device->Info.get(Name)) {
-if (!std::holds_alternative((*Entry)->Value))
-  return makeError(ErrorCode::BACKEND_FAILURE,
-   "plugin returned incorrect type");
-return std::get((*Entry)->Value).c_str();
-  }
-}
-
-return makeError(ErrorCode::UNIMPLEMENTED,
- "plugin did not provide a response for this information");
-  };
-
-  auto getInfoXyz =
-  [&](std::vector Names) -> llvm::Expected {
-for (auto &Name : Names) {
-  if (auto Entry = Device->Info.get(Name)) {
-auto Node = *Entry;
-ol_dimensions_t Out{0, 0, 0};
-
-auto getField = [&](StringRef Name, uint32_t &Dest) {
-  if (auto F = Node->get(Name)) {
-if (!std::holds_alternative((*F)->Value))
-  return makeError(
-  ErrorCode::BACKEND_FAILURE,
-  "plugin returned incorrect type for dimensions element");
-Dest = std::get((*F)->Value);
-  } else
-return makeError(ErrorCode::BACKEND_FAILURE,
- "plugin didn't provide all values for 
dimensions");
-  return Plugin::success();
-};
-
-if (auto Res = getField("x", Out.x))
-  return Res;
-if (auto Res = getField("y", Out.y))
-  return Res;
-if (auto Res = getField("z", Out.z))
-  return Res;
-
-return Out;
-  }
-}
+  // These are not implemented by the plugin interface
+  if (PropName == OL_DEVICE_INFO_PLATFORM)
+return Info.write(Device->Platform);
+  if (PropName == OL_DEVICE_INFO_TYPE)
+return Info.write(OL_DEVICE_TYPE_GPU);
+  // TODO: Update when https://github.com/llvm/llvm-project/pull/147314 is 
merged
+  if (PropName > OL_DEVICE_INFO_MAX_WORK_GROUP_SIZE)
+return createOffloadError(ErrorCode::INVALID_ENUMERATION,
+  "getDeviceInfo enum '%i' is invalid", PropName);
 
+  auto EntryOpt = Device->Info.get(static_cast(PropName));
+  if (!EntryOpt)
 return makeError(ErrorCode::UNIMPLEMENTED,
  "plugin did not provide a response for this information");
-  };
+  auto Entry = *EntryOpt;
 
   switch (PropName) {
-  case OL_DEVICE_INFO_PLATFORM:
-return Info.write(Device->Platform);
-  case OL_DEVICE_INFO_TYPE:
-return Info.write(OL_DEVICE_TYPE_GPU);
   case OL_DEVICE_INFO_NAME:
-return Info.writeString(getInfoString({"Device Name"}));
   case OL_DEVICE_INFO_VENDOR:
-return Info.writeString(getInfoString({"Vendor Name"}));
-  case OL_DEVICE_INFO_DRIVER_VERSION:
-return Info.writeString(
-getIn

[llvm-branch-commits] [llvm] [Offload] Refactor device information queries to use new tagging (PR #147318)

2025-07-08 Thread Ross Brunton via llvm-branch-commits

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

>From 0550a48a4794312063b27a342d68f708ccf55684 Mon Sep 17 00:00:00 2001
From: Ross Brunton 
Date: Mon, 7 Jul 2025 16:13:32 +0100
Subject: [PATCH] [Offload] Refactor device information queries to use new
 tagging

Instead using strings to look up device information (which is brittle
and slow), use the new tags that the plugins specify when building the
nodes.
---
 offload/liboffload/src/Helpers.hpp |  19 ++---
 offload/liboffload/src/OffloadImpl.cpp | 111 +++--
 2 files changed, 54 insertions(+), 76 deletions(-)

diff --git a/offload/liboffload/src/Helpers.hpp 
b/offload/liboffload/src/Helpers.hpp
index 8b85945508b98..62e55e500fac7 100644
--- a/offload/liboffload/src/Helpers.hpp
+++ b/offload/liboffload/src/Helpers.hpp
@@ -75,23 +75,16 @@ class InfoWriter {
   InfoWriter(InfoWriter &) = delete;
   ~InfoWriter() = default;
 
-  template  llvm::Error write(llvm::Expected &&Val) {
-if (Val)
-  return getInfo(Size, Target, SizeRet, *Val);
-return Val.takeError();
+  template  llvm::Error write(T Val) {
+return getInfo(Size, Target, SizeRet, Val);
   }
 
-  template 
-  llvm::Error writeArray(llvm::Expected &&Val, size_t Elems) {
-if (Val)
-  return getInfoArray(Elems, Size, Target, SizeRet, *Val);
-return Val.takeError();
+  template  llvm::Error writeArray(T Val, size_t Elems) {
+return getInfoArray(Elems, Size, Target, SizeRet, Val);
   }
 
-  llvm::Error writeString(llvm::Expected &&Val) {
-if (Val)
-  return getInfoString(Size, Target, SizeRet, *Val);
-return Val.takeError();
+  llvm::Error writeString(llvm::StringRef Val) {
+return getInfoString(Size, Target, SizeRet, Val);
   }
 
 private:
diff --git a/offload/liboffload/src/OffloadImpl.cpp 
b/offload/liboffload/src/OffloadImpl.cpp
index f9da638436705..c84bf01460252 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -286,78 +286,63 @@ Error olGetDeviceInfoImplDetail(ol_device_handle_t Device,
 return Plugin::error(ErrorCode::UNIMPLEMENTED, ErrBuffer.c_str());
   };
 
-  // Find the info if it exists under any of the given names
-  auto getInfoString =
-  [&](std::vector Names) -> llvm::Expected {
-for (auto &Name : Names) {
-  if (auto Entry = Device->Info.get(Name)) {
-if (!std::holds_alternative((*Entry)->Value))
-  return makeError(ErrorCode::BACKEND_FAILURE,
-   "plugin returned incorrect type");
-return std::get((*Entry)->Value).c_str();
-  }
-}
-
-return makeError(ErrorCode::UNIMPLEMENTED,
- "plugin did not provide a response for this information");
-  };
-
-  auto getInfoXyz =
-  [&](std::vector Names) -> llvm::Expected {
-for (auto &Name : Names) {
-  if (auto Entry = Device->Info.get(Name)) {
-auto Node = *Entry;
-ol_dimensions_t Out{0, 0, 0};
-
-auto getField = [&](StringRef Name, uint32_t &Dest) {
-  if (auto F = Node->get(Name)) {
-if (!std::holds_alternative((*F)->Value))
-  return makeError(
-  ErrorCode::BACKEND_FAILURE,
-  "plugin returned incorrect type for dimensions element");
-Dest = std::get((*F)->Value);
-  } else
-return makeError(ErrorCode::BACKEND_FAILURE,
- "plugin didn't provide all values for 
dimensions");
-  return Plugin::success();
-};
-
-if (auto Res = getField("x", Out.x))
-  return Res;
-if (auto Res = getField("y", Out.y))
-  return Res;
-if (auto Res = getField("z", Out.z))
-  return Res;
-
-return Out;
-  }
-}
+  // These are not implemented by the plugin interface
+  if (PropName == OL_DEVICE_INFO_PLATFORM)
+return Info.write(Device->Platform);
+  if (PropName == OL_DEVICE_INFO_TYPE)
+return Info.write(OL_DEVICE_TYPE_GPU);
+  // TODO: Update when https://github.com/llvm/llvm-project/pull/147314 is 
merged
+  if (PropName > OL_DEVICE_INFO_MAX_WORK_GROUP_SIZE)
+return createOffloadError(ErrorCode::INVALID_ENUMERATION,
+  "getDeviceInfo enum '%i' is invalid", PropName);
 
+  auto EntryOpt = Device->Info.get(static_cast(PropName));
+  if (!EntryOpt)
 return makeError(ErrorCode::UNIMPLEMENTED,
  "plugin did not provide a response for this information");
-  };
+  auto Entry = *EntryOpt;
 
   switch (PropName) {
-  case OL_DEVICE_INFO_PLATFORM:
-return Info.write(Device->Platform);
-  case OL_DEVICE_INFO_TYPE:
-return Info.write(OL_DEVICE_TYPE_GPU);
   case OL_DEVICE_INFO_NAME:
-return Info.writeString(getInfoString({"Device Name"}));
   case OL_DEVICE_INFO_VENDOR:
-return Info.writeString(getInfoString({"Vendor Name"}));
-  case OL_DEVICE_INFO_DRIVER_VERSION:
-return Info.writeString(
-getInfoSt

[llvm-branch-commits] [llvm] [Offload] Refactor device information queries to use new tagging (PR #147318)

2025-07-09 Thread Ross Brunton via llvm-branch-commits

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

>From 12b08d974c631036f8fa645ec8f4a469fe3cb79c Mon Sep 17 00:00:00 2001
From: Ross Brunton 
Date: Mon, 7 Jul 2025 16:13:32 +0100
Subject: [PATCH 1/2] [Offload] Refactor device information queries to use new
 tagging

Instead using strings to look up device information (which is brittle
and slow), use the new tags that the plugins specify when building the
nodes.
---
 offload/liboffload/src/Helpers.hpp |  19 ++---
 offload/liboffload/src/OffloadImpl.cpp | 111 +++--
 2 files changed, 54 insertions(+), 76 deletions(-)

diff --git a/offload/liboffload/src/Helpers.hpp 
b/offload/liboffload/src/Helpers.hpp
index 8b85945508b98..62e55e500fac7 100644
--- a/offload/liboffload/src/Helpers.hpp
+++ b/offload/liboffload/src/Helpers.hpp
@@ -75,23 +75,16 @@ class InfoWriter {
   InfoWriter(InfoWriter &) = delete;
   ~InfoWriter() = default;
 
-  template  llvm::Error write(llvm::Expected &&Val) {
-if (Val)
-  return getInfo(Size, Target, SizeRet, *Val);
-return Val.takeError();
+  template  llvm::Error write(T Val) {
+return getInfo(Size, Target, SizeRet, Val);
   }
 
-  template 
-  llvm::Error writeArray(llvm::Expected &&Val, size_t Elems) {
-if (Val)
-  return getInfoArray(Elems, Size, Target, SizeRet, *Val);
-return Val.takeError();
+  template  llvm::Error writeArray(T Val, size_t Elems) {
+return getInfoArray(Elems, Size, Target, SizeRet, Val);
   }
 
-  llvm::Error writeString(llvm::Expected &&Val) {
-if (Val)
-  return getInfoString(Size, Target, SizeRet, *Val);
-return Val.takeError();
+  llvm::Error writeString(llvm::StringRef Val) {
+return getInfoString(Size, Target, SizeRet, Val);
   }
 
 private:
diff --git a/offload/liboffload/src/OffloadImpl.cpp 
b/offload/liboffload/src/OffloadImpl.cpp
index f9da638436705..c84bf01460252 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -286,78 +286,63 @@ Error olGetDeviceInfoImplDetail(ol_device_handle_t Device,
 return Plugin::error(ErrorCode::UNIMPLEMENTED, ErrBuffer.c_str());
   };
 
-  // Find the info if it exists under any of the given names
-  auto getInfoString =
-  [&](std::vector Names) -> llvm::Expected {
-for (auto &Name : Names) {
-  if (auto Entry = Device->Info.get(Name)) {
-if (!std::holds_alternative((*Entry)->Value))
-  return makeError(ErrorCode::BACKEND_FAILURE,
-   "plugin returned incorrect type");
-return std::get((*Entry)->Value).c_str();
-  }
-}
-
-return makeError(ErrorCode::UNIMPLEMENTED,
- "plugin did not provide a response for this information");
-  };
-
-  auto getInfoXyz =
-  [&](std::vector Names) -> llvm::Expected {
-for (auto &Name : Names) {
-  if (auto Entry = Device->Info.get(Name)) {
-auto Node = *Entry;
-ol_dimensions_t Out{0, 0, 0};
-
-auto getField = [&](StringRef Name, uint32_t &Dest) {
-  if (auto F = Node->get(Name)) {
-if (!std::holds_alternative((*F)->Value))
-  return makeError(
-  ErrorCode::BACKEND_FAILURE,
-  "plugin returned incorrect type for dimensions element");
-Dest = std::get((*F)->Value);
-  } else
-return makeError(ErrorCode::BACKEND_FAILURE,
- "plugin didn't provide all values for 
dimensions");
-  return Plugin::success();
-};
-
-if (auto Res = getField("x", Out.x))
-  return Res;
-if (auto Res = getField("y", Out.y))
-  return Res;
-if (auto Res = getField("z", Out.z))
-  return Res;
-
-return Out;
-  }
-}
+  // These are not implemented by the plugin interface
+  if (PropName == OL_DEVICE_INFO_PLATFORM)
+return Info.write(Device->Platform);
+  if (PropName == OL_DEVICE_INFO_TYPE)
+return Info.write(OL_DEVICE_TYPE_GPU);
+  // TODO: Update when https://github.com/llvm/llvm-project/pull/147314 is 
merged
+  if (PropName > OL_DEVICE_INFO_MAX_WORK_GROUP_SIZE)
+return createOffloadError(ErrorCode::INVALID_ENUMERATION,
+  "getDeviceInfo enum '%i' is invalid", PropName);
 
+  auto EntryOpt = Device->Info.get(static_cast(PropName));
+  if (!EntryOpt)
 return makeError(ErrorCode::UNIMPLEMENTED,
  "plugin did not provide a response for this information");
-  };
+  auto Entry = *EntryOpt;
 
   switch (PropName) {
-  case OL_DEVICE_INFO_PLATFORM:
-return Info.write(Device->Platform);
-  case OL_DEVICE_INFO_TYPE:
-return Info.write(OL_DEVICE_TYPE_GPU);
   case OL_DEVICE_INFO_NAME:
-return Info.writeString(getInfoString({"Device Name"}));
   case OL_DEVICE_INFO_VENDOR:
-return Info.writeString(getInfoString({"Vendor Name"}));
-  case OL_DEVICE_INFO_DRIVER_VERSION:
-return Info.writeString(
-getIn

[llvm-branch-commits] [llvm] [Offload] Add `olGetGlobalVariable` (PR #147944)

2025-07-10 Thread Ross Brunton via llvm-branch-commits

https://github.com/RossBrunton created 
https://github.com/llvm/llvm-project/pull/147944

Looks up a global variable as a symbol


>From de96f4311a866a3277086df3441c4c72a81970ce Mon Sep 17 00:00:00 2001
From: Ross Brunton 
Date: Thu, 10 Jul 2025 12:53:30 +0100
Subject: [PATCH] [Offload] Add `olGetGlobalVariable`

Looks up a global variable as a symbol
---
 offload/liboffload/API/Symbol.td  | 15 +
 offload/liboffload/src/OffloadImpl.cpp| 22 +++-
 offload/unittests/OffloadAPI/CMakeLists.txt   |  3 +
 .../unittests/OffloadAPI/device_code/global.c |  1 +
 .../OffloadAPI/kernel/olLaunchKernel.cpp  |  8 +++
 .../OffloadAPI/symbol/olGetGlobalVariable.cpp | 56 +++
 6 files changed, 104 insertions(+), 1 deletion(-)
 create mode 100644 offload/unittests/OffloadAPI/symbol/olGetGlobalVariable.cpp

diff --git a/offload/liboffload/API/Symbol.td b/offload/liboffload/API/Symbol.td
index cf4d45b09f035..68ccbc4e68c4b 100644
--- a/offload/liboffload/API/Symbol.td
+++ b/offload/liboffload/API/Symbol.td
@@ -15,5 +15,20 @@ def : Enum {
   let desc = "The kind of a symbol";
   let etors =[
 Etor<"KERNEL", "a kernel object">,
+Etor<"GLOBAL_VARIABLE", "a global variable">,
   ];
 }
+
+def : Function {
+let name = "olGetGlobalVariable";
+let desc = "Get a global variable named `GlobalName` in the given 
program.";
+let details = [
+"Symbol handles are owned by the program, so do not need to be 
destroyed."
+];
+let params = [
+Param<"ol_program_handle_t", "Program", "handle of the program", 
PARAM_IN>,
+Param<"const char*", "GlobalName", "name of the global variable in the 
program", PARAM_IN>,
+Param<"ol_symbol_handle_t*", "Global", "output pointer for the fetched 
global", PARAM_OUT>
+];
+let returns = [];
+}
diff --git a/offload/liboffload/src/OffloadImpl.cpp 
b/offload/liboffload/src/OffloadImpl.cpp
index fa5d18c044048..b4a545e013d6f 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -91,7 +91,9 @@ struct ol_program_impl_t {
 struct ol_symbol_impl_t {
   ol_symbol_impl_t(GenericKernelTy *Kernel)
   : PluginImpl(Kernel), Kind(OL_SYMBOL_KIND_KERNEL) {}
-  std::variant PluginImpl;
+  ol_symbol_impl_t(GlobalTy &&Global)
+  : PluginImpl(Global), Kind(OL_SYMBOL_KIND_GLOBAL_VARIABLE) {}
+  std::variant PluginImpl;
   ol_symbol_kind_t Kind;
 };
 
@@ -726,5 +728,23 @@ Error olLaunchKernel_impl(ol_queue_handle_t Queue, 
ol_device_handle_t Device,
   return Error::success();
 }
 
+Error olGetGlobalVariable_impl(ol_program_handle_t Program,
+   const char *GlobalName,
+   ol_symbol_handle_t *Global) {
+  auto &Device = Program->Image->getDevice();
+
+  GlobalTy GlobalObj{GlobalName};
+  if (auto Res = Device.Plugin.getGlobalHandler().getGlobalMetadataFromDevice(
+  Device, *Program->Image, GlobalObj))
+return Res;
+
+  *Global = Program->Symbols
+.emplace_back(
+std::make_unique(std::move(GlobalObj)))
+.get();
+
+  return Error::success();
+}
+
 } // namespace offload
 } // namespace llvm
diff --git a/offload/unittests/OffloadAPI/CMakeLists.txt 
b/offload/unittests/OffloadAPI/CMakeLists.txt
index 93e5fd2f6cd26..5d734df635cb4 100644
--- a/offload/unittests/OffloadAPI/CMakeLists.txt
+++ b/offload/unittests/OffloadAPI/CMakeLists.txt
@@ -41,3 +41,6 @@ add_offload_unittest("queue"
 queue/olDestroyQueue.cpp
 queue/olGetQueueInfo.cpp
 queue/olGetQueueInfoSize.cpp)
+
+add_offload_unittest("symbol"
+symbol/olGetGlobalVariable.cpp)
diff --git a/offload/unittests/OffloadAPI/device_code/global.c 
b/offload/unittests/OffloadAPI/device_code/global.c
index b30e406fb98c7..9f27f9424324f 100644
--- a/offload/unittests/OffloadAPI/device_code/global.c
+++ b/offload/unittests/OffloadAPI/device_code/global.c
@@ -1,6 +1,7 @@
 #include 
 #include 
 
+[[gnu::visibility("default")]]
 uint32_t global[64];
 
 __gpu_kernel void write() {
diff --git a/offload/unittests/OffloadAPI/kernel/olLaunchKernel.cpp 
b/offload/unittests/OffloadAPI/kernel/olLaunchKernel.cpp
index acda4795edec2..cb77acf1bd21a 100644
--- a/offload/unittests/OffloadAPI/kernel/olLaunchKernel.cpp
+++ b/offload/unittests/OffloadAPI/kernel/olLaunchKernel.cpp
@@ -223,6 +223,14 @@ TEST_P(olLaunchKernelGlobalTest, Success) {
   ASSERT_SUCCESS(olMemFree(Mem));
 }
 
+TEST_P(olLaunchKernelGlobalTest, InvalidNotAKernel) {
+  ol_symbol_handle_t Global = nullptr;
+  ASSERT_SUCCESS(olGetGlobalVariable(Program, "global", &Global));
+  ASSERT_ERROR(
+  OL_ERRC_SYMBOL_KIND,
+  olLaunchKernel(Queue, Device, Global, nullptr, 0, &LaunchArgs, nullptr));
+}
+
 TEST_P(olLaunchKernelGlobalCtorTest, Success) {
   void *Mem;
   ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED,
diff --git a/offload/unittests/OffloadAPI/symbol/olGetGlobalVariable.cpp 
b/offload/unittests/OffloadAPI/symbol/olGetGlobalVariable.

[llvm-branch-commits] [llvm] [Offload] Add `olGetSymbolInfo[Size]` (PR #147962)

2025-07-10 Thread Ross Brunton via llvm-branch-commits

https://github.com/RossBrunton created 
https://github.com/llvm/llvm-project/pull/147962

This mirrors the similar functions for other handles. The only
implemented info at the moment is the symbol's kind.


>From 252c47b65e494ca3d293cec3abb4a9f5c7378a15 Mon Sep 17 00:00:00 2001
From: Ross Brunton 
Date: Thu, 10 Jul 2025 14:32:39 +0100
Subject: [PATCH] [Offload] Add `olGetSymbolInfo[Size]`

This mirrors the similar functions for other handles. The only
implemented info at the moment is the symbol's kind.
---
 offload/liboffload/API/Symbol.td  | 54 +++
 offload/liboffload/src/OffloadImpl.cpp| 28 
 offload/unittests/OffloadAPI/CMakeLists.txt   |  4 +-
 .../unittests/OffloadAPI/common/Fixtures.hpp  | 20 +-
 .../OffloadAPI/symbol/olGetSymbolInfo.cpp | 65 +++
 .../OffloadAPI/symbol/olGetSymbolInfoSize.cpp | 46 +
 6 files changed, 214 insertions(+), 3 deletions(-)
 create mode 100644 offload/unittests/OffloadAPI/symbol/olGetSymbolInfo.cpp
 create mode 100644 offload/unittests/OffloadAPI/symbol/olGetSymbolInfoSize.cpp

diff --git a/offload/liboffload/API/Symbol.td b/offload/liboffload/API/Symbol.td
index 68ccbc4e68c4b..42d473c24febd 100644
--- a/offload/liboffload/API/Symbol.td
+++ b/offload/liboffload/API/Symbol.td
@@ -32,3 +32,57 @@ def : Function {
 ];
 let returns = [];
 }
+
+def : Enum {
+  let name = "ol_symbol_info_t";
+  let desc = "Supported symbol info.";
+  let is_typed = 1;
+  let etors = [
+TaggedEtor<"KIND", "ol_symbol_kind_t", "The kind of this symbol.">
+  ];
+}
+
+def : Function {
+  let name = "olGetSymbolInfo";
+  let desc = "Queries the given property of the symbol.";
+  let details = [
+"`olGetSymbolInfoSize` can be used to query the storage size "
+"required for the given query."
+  ];
+  let params = [
+Param<"ol_symbol_handle_t", "Event", "handle of the symbol", PARAM_IN>,
+Param<"ol_symbol_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 to 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_INVALID_SIZE", [
+  "`PropSize == 0`",
+  "If `PropSize` is less than the real number of bytes needed to return 
the info."
+]>,
+Return<"OL_ERRC_SYMBOL_KIND", [
+  "If the requested info isn't applicable to the type of symbol."
+]>,
+Return<"OL_ERRC_INVALID_SYMBOL">
+  ];
+}
+
+def : Function {
+  let name = "olGetSymbolInfoSize";
+  let desc = "Returns the storage size of the given symbol query.";
+  let details = [];
+  let params = [
+Param<"ol_symbol_handle_t", "Event", "handle of the symbol", PARAM_IN>,
+Param<"ol_symbol_info_t", "PropName", "type of the info to query", 
PARAM_IN>,
+Param<"size_t*", "PropSizeRet", "pointer to the number of bytes required 
to store the query", PARAM_OUT>
+  ];
+  let returns = [
+Return<"OL_ERRC_INVALID_SYMBOL">,
+Return<"OL_ERRC_SYMBOL_KIND", [
+  "If the requested info isn't applicable to the type of symbol."
+]>,
+  ];
+}
diff --git a/offload/liboffload/src/OffloadImpl.cpp 
b/offload/liboffload/src/OffloadImpl.cpp
index b4a545e013d6f..5aefafb1e57ea 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -746,5 +746,33 @@ Error olGetGlobalVariable_impl(ol_program_handle_t Program,
   return Error::success();
 }
 
+Error olGetSymbolInfoImplDetail(ol_symbol_handle_t Symbol,
+ol_symbol_info_t PropName, size_t PropSize,
+void *PropValue, size_t *PropSizeRet) {
+  InfoWriter Info(PropSize, PropValue, PropSizeRet);
+
+  switch (PropName) {
+  case OL_SYMBOL_INFO_KIND:
+return Info.write(Symbol->Kind);
+  default:
+return createOffloadError(ErrorCode::INVALID_ENUMERATION,
+  "olGetSymbolInfo enum '%i' is invalid", 
PropName);
+  }
+
+  return Error::success();
+}
+
+Error olGetSymbolInfo_impl(ol_symbol_handle_t Symbol, ol_symbol_info_t 
PropName,
+   size_t PropSize, void *PropValue) {
+
+  return olGetSymbolInfoImplDetail(Symbol, PropName, PropSize, PropValue,
+   nullptr);
+}
+
+Error olGetSymbolInfoSize_impl(ol_symbol_handle_t Symbol,
+   ol_symbol_info_t PropName, size_t *PropSizeRet) 
{
+  return olGetSymbolInfoImplDetail(Symbol, PropName, 0, nullptr, PropSizeRet);
+}
+
 } // namespace offload
 } // namespace llvm
diff --git a/offload/unittests/OffloadAPI/CMakeLists.txt 
b/offload/unittests/OffloadAPI/CMakeLists.txt
index 5d734df635cb4..0d60fe379a837 100644
--- a/offl

[llvm-branch-commits] [llvm] [Offload] Add `olGetSymbolInfo[Size]` (PR #147962)

2025-07-10 Thread Ross Brunton via llvm-branch-commits

RossBrunton wrote:

@jhuber6 Some queries (such as name and vendor) return strings, binary data or 
arrays. This entry point allows the implementation to pre-allocate storage for 
them.

It's also useful for offload users that want to create a generic "readInfo" 
function that allocates and returns a void * to some memory for callers to cast 
to the appropriate type.

https://github.com/llvm/llvm-project/pull/147962
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [Offload] Add `olGetSymbolInfo[Size]` (PR #147962)

2025-07-10 Thread Ross Brunton via llvm-branch-commits

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

>From b269d41d44e589baa2d0e4b87d1734e39b5de2a0 Mon Sep 17 00:00:00 2001
From: Ross Brunton 
Date: Thu, 10 Jul 2025 14:32:39 +0100
Subject: [PATCH] [Offload] Add `olGetSymbolInfo[Size]`

This mirrors the similar functions for other handles. The only
implemented info at the moment is the symbol's kind.
---
 offload/liboffload/API/Symbol.td  | 54 +++
 offload/liboffload/src/OffloadImpl.cpp| 28 
 offload/unittests/OffloadAPI/CMakeLists.txt   |  4 +-
 .../unittests/OffloadAPI/common/Fixtures.hpp  | 20 +-
 .../OffloadAPI/symbol/olGetSymbolInfo.cpp | 65 +++
 .../OffloadAPI/symbol/olGetSymbolInfoSize.cpp | 46 +
 6 files changed, 214 insertions(+), 3 deletions(-)
 create mode 100644 offload/unittests/OffloadAPI/symbol/olGetSymbolInfo.cpp
 create mode 100644 offload/unittests/OffloadAPI/symbol/olGetSymbolInfoSize.cpp

diff --git a/offload/liboffload/API/Symbol.td b/offload/liboffload/API/Symbol.td
index 68ccbc4e68c4b..42d473c24febd 100644
--- a/offload/liboffload/API/Symbol.td
+++ b/offload/liboffload/API/Symbol.td
@@ -32,3 +32,57 @@ def : Function {
 ];
 let returns = [];
 }
+
+def : Enum {
+  let name = "ol_symbol_info_t";
+  let desc = "Supported symbol info.";
+  let is_typed = 1;
+  let etors = [
+TaggedEtor<"KIND", "ol_symbol_kind_t", "The kind of this symbol.">
+  ];
+}
+
+def : Function {
+  let name = "olGetSymbolInfo";
+  let desc = "Queries the given property of the symbol.";
+  let details = [
+"`olGetSymbolInfoSize` can be used to query the storage size "
+"required for the given query."
+  ];
+  let params = [
+Param<"ol_symbol_handle_t", "Event", "handle of the symbol", PARAM_IN>,
+Param<"ol_symbol_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 to 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_INVALID_SIZE", [
+  "`PropSize == 0`",
+  "If `PropSize` is less than the real number of bytes needed to return 
the info."
+]>,
+Return<"OL_ERRC_SYMBOL_KIND", [
+  "If the requested info isn't applicable to the type of symbol."
+]>,
+Return<"OL_ERRC_INVALID_SYMBOL">
+  ];
+}
+
+def : Function {
+  let name = "olGetSymbolInfoSize";
+  let desc = "Returns the storage size of the given symbol query.";
+  let details = [];
+  let params = [
+Param<"ol_symbol_handle_t", "Event", "handle of the symbol", PARAM_IN>,
+Param<"ol_symbol_info_t", "PropName", "type of the info to query", 
PARAM_IN>,
+Param<"size_t*", "PropSizeRet", "pointer to the number of bytes required 
to store the query", PARAM_OUT>
+  ];
+  let returns = [
+Return<"OL_ERRC_INVALID_SYMBOL">,
+Return<"OL_ERRC_SYMBOL_KIND", [
+  "If the requested info isn't applicable to the type of symbol."
+]>,
+  ];
+}
diff --git a/offload/liboffload/src/OffloadImpl.cpp 
b/offload/liboffload/src/OffloadImpl.cpp
index b4a545e013d6f..5aefafb1e57ea 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -746,5 +746,33 @@ Error olGetGlobalVariable_impl(ol_program_handle_t Program,
   return Error::success();
 }
 
+Error olGetSymbolInfoImplDetail(ol_symbol_handle_t Symbol,
+ol_symbol_info_t PropName, size_t PropSize,
+void *PropValue, size_t *PropSizeRet) {
+  InfoWriter Info(PropSize, PropValue, PropSizeRet);
+
+  switch (PropName) {
+  case OL_SYMBOL_INFO_KIND:
+return Info.write(Symbol->Kind);
+  default:
+return createOffloadError(ErrorCode::INVALID_ENUMERATION,
+  "olGetSymbolInfo enum '%i' is invalid", 
PropName);
+  }
+
+  return Error::success();
+}
+
+Error olGetSymbolInfo_impl(ol_symbol_handle_t Symbol, ol_symbol_info_t 
PropName,
+   size_t PropSize, void *PropValue) {
+
+  return olGetSymbolInfoImplDetail(Symbol, PropName, PropSize, PropValue,
+   nullptr);
+}
+
+Error olGetSymbolInfoSize_impl(ol_symbol_handle_t Symbol,
+   ol_symbol_info_t PropName, size_t *PropSizeRet) 
{
+  return olGetSymbolInfoImplDetail(Symbol, PropName, 0, nullptr, PropSizeRet);
+}
+
 } // namespace offload
 } // namespace llvm
diff --git a/offload/unittests/OffloadAPI/CMakeLists.txt 
b/offload/unittests/OffloadAPI/CMakeLists.txt
index 5d734df635cb4..0d60fe379a837 100644
--- a/offload/unittests/OffloadAPI/CMakeLists.txt
+++ b/offload/unittests/OffloadAPI/CMakeLists.txt
@@ -43,4 +43,6 @@ add_offloa

[llvm-branch-commits] [llvm] [Offload] Add `olGetGlobalVariable` (PR #147944)

2025-07-10 Thread Ross Brunton via llvm-branch-commits

RossBrunton wrote:

@jhuber6 I'm not sure that's possible generically. The AMD backend at least 
needs to mangle kernel names to add ".kd" on the end, so we'd need to know 
ahead of time whether it's a kernel or not.

However, `olGetSymbol` could work if we pass in the symbol kind as a parameter, 
then it dispatches to either kernel or global lookup depending on that.

https://github.com/llvm/llvm-project/pull/147944
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [Offload] Add global variable address/size queries (PR #147972)

2025-07-11 Thread Ross Brunton via llvm-branch-commits

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

>From 77a4183117cd259584c1bb4136aa27dd2b9548b0 Mon Sep 17 00:00:00 2001
From: Ross Brunton 
Date: Thu, 10 Jul 2025 15:34:17 +0100
Subject: [PATCH] [Offload] Add global variable address/size queries

Add two new symbol info types for getting the bounds of a global
variable. As well as a number of tests for reading/writing to it.
---
 offload/liboffload/API/Symbol.td  |   4 +-
 offload/liboffload/src/OffloadImpl.cpp|  19 
 offload/tools/offload-tblgen/PrintGen.cpp |   8 +-
 .../unittests/OffloadAPI/memory/olMemcpy.cpp  | 105 ++
 .../OffloadAPI/symbol/olGetSymbolInfo.cpp |  28 +
 .../OffloadAPI/symbol/olGetSymbolInfoSize.cpp |  14 +++
 6 files changed, 175 insertions(+), 3 deletions(-)

diff --git a/offload/liboffload/API/Symbol.td b/offload/liboffload/API/Symbol.td
index 9317c71df1f10..2e94d703809e7 100644
--- a/offload/liboffload/API/Symbol.td
+++ b/offload/liboffload/API/Symbol.td
@@ -39,7 +39,9 @@ def : Enum {
   let desc = "Supported symbol info.";
   let is_typed = 1;
   let etors = [
-TaggedEtor<"KIND", "ol_symbol_kind_t", "The kind of this symbol.">
+TaggedEtor<"KIND", "ol_symbol_kind_t", "The kind of this symbol.">,
+TaggedEtor<"GLOBAL_VARIABLE_ADDRESS", "void *", "The address in memory for 
this global variable.">,
+TaggedEtor<"GLOBAL_VARIABLE_SIZE", "size_t", "The size in bytes for this 
global variable.">,
   ];
 }
 
diff --git a/offload/liboffload/src/OffloadImpl.cpp 
b/offload/liboffload/src/OffloadImpl.cpp
index 6d98c33ffb8da..17a2b00cb7140 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -753,9 +753,28 @@ Error olGetSymbolInfoImplDetail(ol_symbol_handle_t Symbol,
 void *PropValue, size_t *PropSizeRet) {
   InfoWriter Info(PropSize, PropValue, PropSizeRet);
 
+  auto CheckKind = [&](ol_symbol_kind_t Required) {
+if (Symbol->Kind != Required) {
+  std::string ErrBuffer;
+  llvm::raw_string_ostream(ErrBuffer)
+  << PropName << ": Expected a symbol of Kind " << Required
+  << " but given a symbol of Kind " << Symbol->Kind;
+  return Plugin::error(ErrorCode::SYMBOL_KIND, ErrBuffer.c_str());
+}
+return Plugin::success();
+  };
+
   switch (PropName) {
   case OL_SYMBOL_INFO_KIND:
 return Info.write(Symbol->Kind);
+  case OL_SYMBOL_INFO_GLOBAL_VARIABLE_ADDRESS:
+if (auto Err = CheckKind(OL_SYMBOL_KIND_GLOBAL_VARIABLE))
+  return Err;
+return Info.write(std::get(Symbol->PluginImpl).getPtr());
+  case OL_SYMBOL_INFO_GLOBAL_VARIABLE_SIZE:
+if (auto Err = CheckKind(OL_SYMBOL_KIND_GLOBAL_VARIABLE))
+  return Err;
+return 
Info.write(std::get(Symbol->PluginImpl).getSize());
   default:
 return createOffloadError(ErrorCode::INVALID_ENUMERATION,
   "olGetSymbolInfo enum '%i' is invalid", 
PropName);
diff --git a/offload/tools/offload-tblgen/PrintGen.cpp 
b/offload/tools/offload-tblgen/PrintGen.cpp
index d1189688a90a3..89d7c820426cf 100644
--- a/offload/tools/offload-tblgen/PrintGen.cpp
+++ b/offload/tools/offload-tblgen/PrintGen.cpp
@@ -74,8 +74,12 @@ inline void printTagged(llvm::raw_ostream &os, const void 
*ptr, {0} value, size_
 if (Type == "char[]") {
   OS << formatv(TAB_2 "printPtr(os, (const char*) ptr);\n");
 } else {
-  OS << formatv(TAB_2 "const {0} * const tptr = (const {0} * const)ptr;\n",
-Type);
+  if (Type == "void *")
+OS << formatv(TAB_2 "void * const * const tptr = (void * "
+"const * const)ptr;\n");
+  else
+OS << formatv(
+TAB_2 "const {0} * const tptr = (const {0} * const)ptr;\n", Type);
   // TODO: Handle other cases here
   OS << TAB_2 "os << (const void *)tptr << \" (\";\n";
   if (Type.ends_with("*")) {
diff --git a/offload/unittests/OffloadAPI/memory/olMemcpy.cpp 
b/offload/unittests/OffloadAPI/memory/olMemcpy.cpp
index c1762b451b81d..c1fb6df9bad0d 100644
--- a/offload/unittests/OffloadAPI/memory/olMemcpy.cpp
+++ b/offload/unittests/OffloadAPI/memory/olMemcpy.cpp
@@ -13,6 +13,32 @@
 using olMemcpyTest = OffloadQueueTest;
 OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olMemcpyTest);
 
+struct olMemcpyGlobalTest : OffloadGlobalTest {
+  void SetUp() override {
+RETURN_ON_FATAL_FAILURE(OffloadGlobalTest::SetUp());
+ASSERT_SUCCESS(
+olGetSymbol(Program, "read", OL_SYMBOL_KIND_KERNEL, &ReadKernel));
+ASSERT_SUCCESS(
+olGetSymbol(Program, "write", OL_SYMBOL_KIND_KERNEL, &WriteKernel));
+ASSERT_SUCCESS(olCreateQueue(Device, &Queue));
+ASSERT_SUCCESS(olGetSymbolInfo(
+Global, OL_SYMBOL_INFO_GLOBAL_VARIABLE_ADDRESS, sizeof(Addr), &Addr));
+
+LaunchArgs.Dimensions = 1;
+LaunchArgs.GroupSize = {64, 1, 1};
+LaunchArgs.NumGroups = {1, 1, 1};
+
+LaunchArgs.DynSharedMemory = 0;
+  }
+
+  ol_kernel

[llvm-branch-commits] [llvm] [Offload] Add `olLinkProgram` (PR #148648)

2025-07-15 Thread Ross Brunton via llvm-branch-commits

https://github.com/RossBrunton converted_to_draft 
https://github.com/llvm/llvm-project/pull/148648
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [Offload] Add `olLinkProgram` (PR #148648)

2025-07-15 Thread Ross Brunton via llvm-branch-commits

RossBrunton wrote:

@jhuber6 That would mean that any program that wants to do dynamic linking 
would need to ship a full clang install alongside `libLLVMOffload.so`. The 
programmer would also have to mess around with writing/reading files and 
invoking a subprocess.

IMO, since this code already exists in liboffload, it makes sense to expose 
that to the user as a convenience.

https://github.com/llvm/llvm-project/pull/148648
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [Offload] Add `olLinkProgram` (PR #148648)

2025-07-14 Thread Ross Brunton via llvm-branch-commits

https://github.com/RossBrunton created 
https://github.com/llvm/llvm-project/pull/148648

A version of `olCreateProgram` that inputs many bitcode files and links
them together before loading them.


>From 8589fcc6d053cb2937cf970d1ce354abfb84da31 Mon Sep 17 00:00:00 2001
From: Ross Brunton 
Date: Mon, 14 Jul 2025 16:05:41 +0100
Subject: [PATCH] [Offload] Add `olLinkProgram`

A version of `olCreateProgram` that inputs many bitcode files and links
them together before loading them.
---
 offload/liboffload/API/Program.td | 28 ++
 offload/liboffload/src/OffloadImpl.cpp| 33 +++
 offload/plugins-nextgen/common/include/JIT.h  |  4 +
 .../common/include/PluginInterface.h  |  4 +
 offload/plugins-nextgen/common/src/JIT.cpp| 41 
 .../common/src/PluginInterface.cpp|  7 ++
 offload/unittests/OffloadAPI/CMakeLists.txt   |  3 +-
 .../OffloadAPI/device_code/CMakeLists.txt |  4 +
 .../unittests/OffloadAPI/device_code/link_a.c | 11 +++
 .../unittests/OffloadAPI/device_code/link_b.c | 10 ++
 .../OffloadAPI/program/olLinkProgram.cpp  | 99 +++
 11 files changed, 243 insertions(+), 1 deletion(-)
 create mode 100644 offload/unittests/OffloadAPI/device_code/link_a.c
 create mode 100644 offload/unittests/OffloadAPI/device_code/link_b.c
 create mode 100644 offload/unittests/OffloadAPI/program/olLinkProgram.cpp

diff --git a/offload/liboffload/API/Program.td 
b/offload/liboffload/API/Program.td
index 0476fa1f7c27a..3dae37f288ff7 100644
--- a/offload/liboffload/API/Program.td
+++ b/offload/liboffload/API/Program.td
@@ -25,6 +25,34 @@ def : Function {
 let returns = [];
 }
 
+def : Struct {
+let name = "ol_program_link_buffer_t";
+let desc = "An image to link with `olLinkProgram`.";
+let members = [
+StructMember<"void *", "Address", "base address of memory image">,
+StructMember<"size_t", "Size", "size in bytes of memory image">,
+];
+}
+
+def : Function {
+let name = "olLinkProgram";
+let desc = "Compile and link multiple bitcode images into a single 
binary.";
+let details = [
+"No caching is performed; multiple calls to `olLinkProgram` with the 
same images will result in multiple linking operations",
+];
+let params = [
+Param<"ol_device_handle_t", "Device", "handle of the device to link 
for", PARAM_IN>,
+Param<"ol_program_link_buffer_t *", "Images", "a pointer to an array 
of `ImagesSize` entries, one for each image to link", PARAM_IN>,
+Param<"size_t", "ImagesSize", "the number of elements in `Images`", 
PARAM_IN>,
+Param<"ol_program_handle_t*", "Program", "output handle for the 
created program", PARAM_OUT>
+];
+let returns = [
+Return<"OL_ERRC_INVALID_SIZE", ["`ImagesSize == 0`"]>,
+Return<"OL_ERRC_INVALID_BINARY", ["Any image is not in the bitcode 
format"]>,
+Return<"OL_ERRC_UNSUPPORTED", ["Linking is not supported for this 
device and `ImagesSize` > 1"]>,
+];
+}
+
 def : Function {
 let name = "olDestroyProgram";
 let desc = "Destroy the program and free all underlying resources.";
diff --git a/offload/liboffload/src/OffloadImpl.cpp 
b/offload/liboffload/src/OffloadImpl.cpp
index 17a2b00cb7140..14af015460c8c 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -650,6 +650,39 @@ Error olCreateProgram_impl(ol_device_handle_t Device, 
const void *ProgData,
   return Error::success();
 }
 
+Error olLinkProgram_impl(ol_device_impl_t *Device,
+ ol_program_link_buffer_t *Images, size_t ImagesSize,
+ ol_program_handle_t *Program) {
+  std::vector<__tgt_device_image> DevImages;
+  for (size_t I = 0; I < ImagesSize; I++) {
+auto &ProgData = Images[I];
+DevImages.push_back({ProgData.Address,
+ utils::advancePtr(ProgData.Address, ProgData.Size),
+ nullptr, nullptr});
+  }
+
+  auto LinkResult =
+  Device->Device->jitLinkBinary(Device->Device->Plugin, DevImages);
+  if (!LinkResult)
+return LinkResult.takeError();
+
+  ol_program_handle_t Prog =
+  new ol_program_impl_t(nullptr, nullptr, *LinkResult);
+
+  auto Res =
+  Device->Device->loadBinary(Device->Device->Plugin, &Prog->DeviceImage);
+  if (!Res) {
+delete Prog;
+return Res.takeError();
+  }
+  assert(*Res != nullptr && "loadBinary returned nullptr");
+
+  Prog->Image = *Res;
+  *Program = Prog;
+
+  return Error::success();
+}
+
 Error olDestroyProgram_impl(ol_program_handle_t Program) {
   auto &Device = Program->Image->getDevice();
   if (auto Err = Device.unloadBinary(Program->Image))
diff --git a/offload/plugins-nextgen/common/include/JIT.h 
b/offload/plugins-nextgen/common/include/JIT.h
index 1d6280a0af141..08b82c4aefb8d 100644
--- a/offload/plugins-nextgen/common/include/JIT.h
+++ b/offload/plugins-nextgen/common/include/JIT.h
@@ -55,6 +55,10 @@ struct JITEngine {
   process(con