Skip to content

Commit d7479a0

Browse files
[Offload] Generate OffloadTypedGetInfo.inc
Various offload APIs `olGet*Info` are essentially untyped because they "return" value via `void *PropValue` output parameter. However, for C++ consumers (e.g., [SYCL][1] in llvm#166927) it would be beneficial if we could recover that type information. Before this PR it was only encoded in the comments near corresponding information info descriptors, e.g., ```c++ /////////////////////////////////////////////////////////////////////////////// /// @brief Supported event info. typedef enum ol_event_info_t { /// [ol_queue_handle_t] The handle of the queue associated with the device. OL_EVENT_INFO_QUEUE = 0, /// [bool] True if and only if the event is complete. OL_EVENT_INFO_IS_COMPLETE = 1, /// @cond OL_EVENT_INFO_LAST = 2, OL_EVENT_INFO_FORCE_UINT32 = 0x7fffffff /// @endcond } ol_event_info_t; ``` so was imposible for consumers to recover programmatically. [1] https://github.com/llvm/llvm-project/blob/b22192afdcbda7441e7a8fe7cbc9a06903e9e6ea/libsycl/src/detail/platform_impl.hpp#L78-L90
1 parent c4898f3 commit d7479a0

File tree

6 files changed

+152
-1
lines changed

6 files changed

+152
-1
lines changed

offload/liboffload/API/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ offload_tablegen(OffloadEntryPoints.inc -gen-entry-points)
1919
offload_tablegen(OffloadFuncs.inc -gen-func-names)
2020
offload_tablegen(OffloadImplFuncDecls.inc -gen-impl-func-decls)
2121
offload_tablegen(OffloadPrint.hpp -gen-print-header)
22+
offload_tablegen(OffloadTypedGetInfo.inc -gen-get-info-wrappers)
2223

2324
add_public_tablegen_target(OffloadGenerate)
2425

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// RUN: %offload-tblgen -gen-get-info-wrappers -I %S/../../../liboffload/API %s | %fcheck-generic
2+
3+
include "APIDefs.td"
4+
5+
def ol_foo_handle_t : Handle {
6+
}
7+
8+
def ol_foo_info_t : Enum {
9+
let is_typed = 1;
10+
let etors = [
11+
TaggedEtor<"INT", "int", "">,
12+
TaggedEtor<"STRING", "char[]", "">,
13+
TaggedEtor<"ARRAY", "int[]", "">,
14+
];
15+
}
16+
17+
def olGetFooInfo : Function {
18+
let params = [
19+
Param<"ol_foo_handle_t", "Foo", "", PARAM_IN>,
20+
Param<"ol_foo_info_t", "PropName", "", PARAM_IN>,
21+
Param<"size_t", "PropSize", "", PARAM_IN>,
22+
TypeTaggedParam<"void*", "PropValue", "array of bytes holding the info.", PARAM_OUT,
23+
TypeInfo<"PropName", "PropSize">>
24+
];
25+
let returns = [
26+
Return<"OL_FOO_INVALID">
27+
];
28+
}
29+
30+
// CHECK-LABEL: template <ol_foo_info_t Desc> inline auto get_info(ol_foo_handle_t Foo);
31+
// CHECK-NEXT: template<> inline auto get_info<OL_FOO_INFO_INT>(ol_foo_handle_t Foo) {
32+
// CHECK-NEXT: int Result;
33+
// CHECK-NEXT: if (auto Err = olGetFooInfo(Foo, OL_FOO_INFO_INT, 1, &Result))
34+
// CHECK-NEXT: return std::variant<int, ol_result_t>{Err};
35+
// CHECK-NEXT: else
36+
// CHECK-NEXT: return std::variant<int, ol_result_t>{Result};
37+
// CHECK-NEXT: }
38+
// CHECK-NEXT: template<> inline auto get_info<OL_FOO_INFO_STRING>(ol_foo_handle_t Foo) {
39+
// CHECK-NEXT: std::string Result;
40+
// CHECK-NEXT: size_t ResultSize = 0; if (auto Err = olGetFooInfoSize(Foo, OL_FOO_INFO_STRING, &ResultSize))
41+
// CHECK-NEXT: return std::variant<std::string, ol_result_t>{Err};
42+
// CHECK-NEXT: Result.resize(ResultSize);
43+
// CHECK-NEXT: if (auto Err = olGetFooInfo(Foo, OL_FOO_INFO_STRING, ResultSize, Result.data()))
44+
// CHECK-NEXT: return std::variant<std::string, ol_result_t>{Err};
45+
// CHECK-NEXT: else
46+
// CHECK-NEXT: return std::variant<std::string, ol_result_t>{Result};
47+
// CHECK-NEXT: }
48+
// CHECK-NEXT: template<> inline auto get_info<OL_FOO_INFO_ARRAY>(ol_foo_handle_t Foo) {
49+
// CHECK-NEXT: std::vector<int> Result;
50+
// CHECK-NEXT: size_t ResultSize = 0; if (auto Err = olGetFooInfoSize(Foo, OL_FOO_INFO_ARRAY, &ResultSize))
51+
// CHECK-NEXT: return std::variant<std::vector<int>, ol_result_t>{Err};
52+
// CHECK-NEXT: Result.resize(ResultSize);
53+
// CHECK-NEXT: if (auto Err = olGetFooInfo(Foo, OL_FOO_INFO_ARRAY, ResultSize, Result.data()))
54+
// CHECK-NEXT: return std::variant<std::vector<int>, ol_result_t>{Err};
55+
// CHECK-NEXT: else
56+
// CHECK-NEXT: return std::variant<std::vector<int>, ol_result_t>{Result};
57+
// CHECK-NEXT: }

offload/tools/offload-tblgen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ add_tablegen(offload-tblgen OFFLOAD
2020
offload-tblgen.cpp
2121
PrintGen.cpp
2222
RecordTypes.hpp
23+
TypedGetInfoWrappers.cpp
2324
)
2425

2526
# Make sure that C++ headers are available, if libcxx is built at the same

offload/tools/offload-tblgen/Generators.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,5 @@ void EmitOffloadExports(const llvm::RecordKeeper &Records,
2525
void EmitOffloadErrcodes(const llvm::RecordKeeper &Records,
2626
llvm::raw_ostream &OS);
2727
void EmitOffloadInfo(const llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
28+
void EmitTypedGetInfoWrappers(const llvm::RecordKeeper &Records,
29+
llvm::raw_ostream &OS);
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This is a Tablegen backend that produces typed C++ inline wrappers for
10+
// various `olGet*Info interfaces.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#include "llvm/ADT/StringExtras.h"
15+
#include "llvm/Support/FormatVariadic.h"
16+
#include "llvm/TableGen/Record.h"
17+
#include "llvm/TableGen/TableGenBackend.h"
18+
19+
#include "GenCommon.hpp"
20+
#include "RecordTypes.hpp"
21+
22+
using namespace llvm;
23+
using namespace offload::tblgen;
24+
25+
void EmitTypedGetInfoWrappers(const llvm::RecordKeeper &Records,
26+
llvm::raw_ostream &OS) {
27+
OS << GenericHeader;
28+
for (auto *R : Records.getAllDerivedDefinitions("Function")) {
29+
auto Name = R->getName();
30+
if (!Name.starts_with("olGet") || !Name.ends_with("Info"))
31+
continue;
32+
auto F = FunctionRec{R};
33+
auto Params = F.getParams();
34+
assert(Params.size() == 4);
35+
auto Object = Params[0];
36+
auto InfoDesc = Params[1];
37+
38+
OS << formatv("template <{} Desc> inline auto get_info({} {});\n",
39+
InfoDesc.getType(), Object.getType(), Object.getName());
40+
41+
EnumRec E{Records.getDef(InfoDesc.getType())};
42+
for (auto &V : E.getValues()) {
43+
auto Desc = E.getEnumValNamePrefix() + "_" + V.getName();
44+
auto TaggedType = V.getTaggedType();
45+
auto ResultType = [TaggedType]() -> std::string {
46+
if (!TaggedType.ends_with("[]"))
47+
return TaggedType.str();
48+
if (TaggedType == "char[]")
49+
return "std::string";
50+
51+
return ("std::vector<" + TaggedType.drop_back(2) + ">").str();
52+
}();
53+
auto ReturnType =
54+
"std::variant<" + ResultType + ", " + PrefixLower + "_result_t>";
55+
OS << formatv("template<> inline auto get_info<{}>({} {}) {{\n", Desc,
56+
Object.getType(), Object.getName());
57+
if (TaggedType.ends_with("[]")) {
58+
OS << TAB_1 << formatv("{0} Result;\n", ResultType);
59+
OS << TAB_1 << "size_t ResultSize = 0;";
60+
OS << TAB_1
61+
<< formatv("if (auto Err = {}Size({}, {}, &ResultSize))\n",
62+
F.getName(), Object.getName(), Desc);
63+
OS << TAB_2 << formatv("return {}{{Err};\n", ReturnType);
64+
OS << TAB_1 << "Result.resize(ResultSize);\n"; // TODO: Or "-1"?
65+
OS << TAB_1
66+
<< formatv("if (auto Err = {}({}, {}, ResultSize, Result.data()))\n",
67+
F.getName(), Object.getName(), Desc);
68+
OS << TAB_2 << formatv("return {0}{{Err};\n", ReturnType);
69+
OS << TAB_1 << "else\n";
70+
OS << TAB_2 << formatv("return {0}{{Result};\n", ReturnType);
71+
} else {
72+
OS << TAB_1 << formatv("{0} Result;\n", TaggedType);
73+
OS << TAB_1
74+
<< formatv("if (auto Err = {}({}, {}, 1, &Result))\n", F.getName(),
75+
Object.getName(), Desc);
76+
OS << TAB_2 << formatv("return {0}{{Err};\n", ReturnType);
77+
OS << TAB_1 << "else\n";
78+
OS << TAB_2 << formatv("return {0}{{Result};\n", ReturnType);
79+
}
80+
OS << "}\n";
81+
}
82+
OS << "\n";
83+
}
84+
}

offload/tools/offload-tblgen/offload-tblgen.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ enum ActionType {
3434
GenExports,
3535
GenErrcodes,
3636
GenInfo,
37+
GenTypedGetInfoWrappers,
3738
};
3839

3940
namespace {
@@ -60,7 +61,10 @@ cl::opt<ActionType> Action(
6061
"Generate export file for the Offload library"),
6162
clEnumValN(GenErrcodes, "gen-errcodes",
6263
"Generate Offload Error Code enum"),
63-
clEnumValN(GenInfo, "gen-info", "Generate Offload Info enum")));
64+
clEnumValN(GenInfo, "gen-info", "Generate Offload Info enum"),
65+
clEnumValN(GenTypedGetInfoWrappers, "gen-get-info-wrappers",
66+
"Generate typed C++ wrappers around various olGet*Info "
67+
"interfaces")));
6468
}
6569

6670
static bool OffloadTableGenMain(raw_ostream &OS, const RecordKeeper &Records) {
@@ -98,6 +102,8 @@ static bool OffloadTableGenMain(raw_ostream &OS, const RecordKeeper &Records) {
98102
case GenInfo:
99103
EmitOffloadInfo(Records, OS);
100104
break;
105+
case GenTypedGetInfoWrappers:
106+
EmitTypedGetInfoWrappers(Records, OS);
101107
}
102108

103109
return false;

0 commit comments

Comments
 (0)