Skip to content

Commit f242360

Browse files
authored
[Offload] Add type information to device info nodes (#144535)
Rather than being "stringly typed", store values as a std::variant that can hold various types. This means that liboffload doesn't have to do any string parsing for integer/bool device info keys.
1 parent e0633d5 commit f242360

File tree

2 files changed

+38
-21
lines changed

2 files changed

+38
-21
lines changed

offload/liboffload/src/OffloadImpl.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -246,23 +246,23 @@ Error olGetDeviceInfoImplDetail(ol_device_handle_t Device,
246246
ReturnHelper ReturnValue(PropSize, PropValue, PropSizeRet);
247247

248248
// Find the info if it exists under any of the given names
249-
auto GetInfo = [&](std::vector<std::string> Names) {
249+
auto GetInfoString = [&](std::vector<std::string> Names) {
250250
if (Device == OffloadContext::get().HostDevice())
251-
return std::string("Host");
251+
return "Host";
252252

253253
if (!Device->Device)
254-
return std::string("");
254+
return "";
255255

256256
auto Info = Device->Device->obtainInfoImpl();
257257
if (auto Err = Info.takeError())
258-
return std::string("");
258+
return "";
259259

260260
for (auto Name : Names) {
261261
if (auto Entry = Info->get(Name))
262-
return (*Entry)->Value;
262+
return std::get<std::string>((*Entry)->Value).c_str();
263263
}
264264

265-
return std::string("");
265+
return "";
266266
};
267267

268268
switch (PropName) {
@@ -273,12 +273,12 @@ Error olGetDeviceInfoImplDetail(ol_device_handle_t Device,
273273
? ReturnValue(OL_DEVICE_TYPE_HOST)
274274
: ReturnValue(OL_DEVICE_TYPE_GPU);
275275
case OL_DEVICE_INFO_NAME:
276-
return ReturnValue(GetInfo({"Device Name"}).c_str());
276+
return ReturnValue(GetInfoString({"Device Name"}));
277277
case OL_DEVICE_INFO_VENDOR:
278-
return ReturnValue(GetInfo({"Vendor Name"}).c_str());
278+
return ReturnValue(GetInfoString({"Vendor Name"}));
279279
case OL_DEVICE_INFO_DRIVER_VERSION:
280280
return ReturnValue(
281-
GetInfo({"CUDA Driver Version", "HSA Runtime Version"}).c_str());
281+
GetInfoString({"CUDA Driver Version", "HSA Runtime Version"}));
282282
default:
283283
return createOffloadError(ErrorCode::INVALID_ENUMERATION,
284284
"getDeviceInfo enum '%i' is invalid", PropName);

offload/plugins-nextgen/common/include/PluginInterface.h

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <list>
1818
#include <map>
1919
#include <shared_mutex>
20+
#include <variant>
2021
#include <vector>
2122

2223
#include "ExclusiveAccess.h"
@@ -122,7 +123,8 @@ struct InfoTreeNode {
122123
static constexpr uint64_t IndentSize = 4;
123124

124125
std::string Key;
125-
std::string Value;
126+
using VariantType = std::variant<uint64_t, std::string, bool, std::monostate>;
127+
VariantType Value;
126128
std::string Units;
127129
// Need to specify a default value number of elements here as `InfoTreeNode`'s
128130
// size is unknown. This is a vector (rather than a Key->Value map) since:
@@ -131,31 +133,31 @@ struct InfoTreeNode {
131133
// * The same key can appear multiple times
132134
std::unique_ptr<llvm::SmallVector<InfoTreeNode, 8>> Children;
133135

134-
InfoTreeNode() : InfoTreeNode("", "", "") {}
135-
InfoTreeNode(std::string Key, std::string Value, std::string Units)
136+
InfoTreeNode() : InfoTreeNode("", std::monostate{}, "") {}
137+
InfoTreeNode(std::string Key, VariantType Value, std::string Units)
136138
: Key(Key), Value(Value), Units(Units) {}
137139

138140
/// Add a new info entry as a child of this node. The entry requires at least
139141
/// a key string in \p Key. The value in \p Value is optional and can be any
140142
/// type that is representable as a string. The units in \p Units is optional
141143
/// and must be a string.
142-
template <typename T = std::string>
144+
template <typename T = std::monostate>
143145
InfoTreeNode *add(std::string Key, T Value = T(),
144146
const std::string &Units = std::string()) {
145147
assert(!Key.empty() && "Invalid info key");
146148

147149
if (!Children)
148150
Children = std::make_unique<llvm::SmallVector<InfoTreeNode, 8>>();
149151

150-
std::string ValueStr;
151-
if constexpr (std::is_same_v<T, bool>)
152-
ValueStr = Value ? "Yes" : "No";
152+
VariantType ValueVariant;
153+
if constexpr (std::is_same_v<T, bool> || std::is_same_v<T, std::monostate>)
154+
ValueVariant = Value;
153155
else if constexpr (std::is_arithmetic_v<T>)
154-
ValueStr = std::to_string(Value);
156+
ValueVariant = static_cast<uint64_t>(Value);
155157
else
156-
ValueStr = Value;
158+
ValueVariant = std::string{Value};
157159

158-
return &Children->emplace_back(Key, ValueStr, Units);
160+
return &Children->emplace_back(Key, ValueVariant, Units);
159161
}
160162

161163
std::optional<InfoTreeNode *> get(StringRef Key) {
@@ -184,8 +186,23 @@ struct InfoTreeNode {
184186
MaxKeySize - (Key.size() + KeyIndentSize) + IndentSize;
185187

186188
llvm::outs() << std::string(KeyIndentSize, ' ') << Key
187-
<< std::string(ValIndentSize, ' ') << Value
188-
<< (Units.empty() ? "" : " ") << Units << "\n";
189+
<< std::string(ValIndentSize, ' ');
190+
std::visit(
191+
[](auto &&V) {
192+
using T = std::decay_t<decltype(V)>;
193+
if constexpr (std::is_same_v<T, std::string>)
194+
llvm::outs() << V;
195+
else if constexpr (std::is_same_v<T, bool>)
196+
llvm::outs() << (V ? "Yes" : "No");
197+
else if constexpr (std::is_same_v<T, uint64_t>)
198+
llvm::outs() << V;
199+
else if constexpr (std::is_same_v<T, std::monostate>) {
200+
// Do nothing
201+
} else
202+
static_assert(false, "doPrint visit not exhaustive");
203+
},
204+
Value);
205+
llvm::outs() << (Units.empty() ? "" : " ") << Units << "\n";
189206
}
190207

191208
// Print children

0 commit comments

Comments
 (0)