Skip to content

Commit 841d002

Browse files
committed
[Offload] Introduce offload-tblgen and initial new API implementation
1 parent c0b3e49 commit 841d002

22 files changed

+1971
-0
lines changed

offload/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,9 @@ add_subdirectory(tools)
349349
# Build target agnostic offloading library.
350350
add_subdirectory(src)
351351

352+
add_subdirectory(tools/offload-tblgen)
353+
add_subdirectory(new-api)
354+
352355
# Add tests.
353356
add_subdirectory(test)
354357

offload/new-api/API/APIDefs.td

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
//===-- APIDefs.td - Base definitions for Offload tablegen -*- tablegen -*-===//
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 file contains the class definitions used to implement the Offload API,
10+
// as well as helper functions used to help populate relevant records.
11+
// See offload/API/README.md for more detailed documentation.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
// Prefix for API naming. This could be hard-coded in the future when a value
16+
// is agreed upon.
17+
defvar PREFIX = "OFFLOAD";
18+
defvar prefix = !tolower(PREFIX);
19+
20+
// Parameter flags
21+
defvar PARAM_IN = 0x1;
22+
defvar PARAM_OUT = 0x2;
23+
defvar PARAM_OPTIONAL = 0x4;
24+
defvar PARAM_IN_OPTIONAL = !or(PARAM_IN, PARAM_OPTIONAL);
25+
defvar PARAM_OUT_OPTIONAL = !or(PARAM_OUT, PARAM_OPTIONAL);
26+
27+
// Does the type end with '_handle_t'?
28+
class IsHandleType<string Type> {
29+
// size("_handle_t") == 9
30+
bit ret = !if(!lt(!size(Type), 9), 0,
31+
!ne(!find(Type, "_handle_t", !sub(!size(Type), 9)), -1));
32+
}
33+
34+
// Does the type end with '*'?
35+
class IsPointerType<string Type> {
36+
bit ret = !ne(!find(Type, "*", !sub(!size(Type), 1)), -1);
37+
}
38+
39+
// Describes the valid range of a pointer parameter that reperesents an array
40+
class Range<string Begin, string End> {
41+
string begin = Begin;
42+
string end = End;
43+
}
44+
45+
// Names the parameters that indicate the type and size of the data pointed to
46+
// by an opaque pointer parameter
47+
class TypeInfo<string TypeEnum, string TypeSize> {
48+
string enum = TypeEnum;
49+
string size = TypeSize;
50+
}
51+
52+
class Param<string Type, string Name, string Desc, bits<3> Flags = 0> {
53+
string type = Type;
54+
string name = Name;
55+
string desc = Desc;
56+
bits<3> flags = Flags;
57+
Range range = Range<"", "">;
58+
TypeInfo type_info = TypeInfo<"", "">;
59+
bit IsHandle = IsHandleType<type>.ret;
60+
bit IsPointer = IsPointerType<type>.ret;
61+
}
62+
63+
// A parameter whose range is described by other parameters in the function.
64+
class RangedParam<string Type, string Name, string Desc, bits<3> Flags, Range ParamRange> : Param<Type, Name, Desc, Flags> {
65+
let range = ParamRange;
66+
}
67+
68+
// A parameter (normally of type void*) which has its pointee type and size
69+
// described by other parameters in the function.
70+
class TypeTaggedParam<string Type, string Name, string Desc, bits<3> Flags, TypeInfo ParamTypeInfo> : Param<Type, Name, Desc, Flags> {
71+
let type_info = ParamTypeInfo;
72+
}
73+
74+
class Return<string Value, list<string> Conditions = []> {
75+
string value = Value;
76+
list<string> conditions = Conditions;
77+
}
78+
79+
class ShouldCheckHandle<Param P> {
80+
bit ret = !and(P.IsHandle, !eq(!and(PARAM_OPTIONAL, P.flags), 0));
81+
}
82+
83+
class ShouldCheckPointer<Param P> {
84+
bit ret = !and(P.IsPointer, !eq(!and(PARAM_OPTIONAL, P.flags), 0));
85+
}
86+
87+
// For a list of returns that contains a specific return code, find and append
88+
// new conditions to that return
89+
class AppendConditionsToReturn<list<Return> Returns, string ReturnValue,
90+
list<string> Conditions> {
91+
list<Return> ret =
92+
!foreach(Ret, Returns,
93+
!if(!eq(Ret.value, ReturnValue),
94+
Return<Ret.value, Ret.conditions#Conditions>, Ret));
95+
}
96+
97+
// Add null handle checks to a function's return value descriptions
98+
class AddHandleChecksToReturns<list<Param> Params, list<Return> Returns> {
99+
list<string> handle_params =
100+
!foreach(P, Params, !if(ShouldCheckHandle<P>.ret, P.name, ""));
101+
list<string> handle_params_filt =
102+
!filter(param, handle_params, !ne(param, ""));
103+
list<string> handle_param_conds =
104+
!foreach(handle, handle_params_filt, "`NULL == "#handle#"`");
105+
106+
// Does the list of returns already contain ERROR_INVALID_NULL_HANDLE?
107+
bit returns_has_inv_handle = !foldl(
108+
0, Returns, HasErr, Ret,
109+
!or(HasErr, !eq(Ret.value, PREFIX#"_RESULT_ERROR_INVALID_NULL_HANDLE")));
110+
111+
list<Return> returns_out = !if(returns_has_inv_handle,
112+
AppendConditionsToReturn<Returns, PREFIX # "_RESULT_ERROR_INVALID_NULL_HANDLE", handle_param_conds>.ret,
113+
!listconcat(Returns, [Return<PREFIX # "_RESULT_ERROR_INVALID_NULL_HANDLE", handle_param_conds>])
114+
);
115+
}
116+
117+
// Add null pointer checks to a function's return value descriptions
118+
class AddPointerChecksToReturns<list<Param> Params, list<Return> Returns> {
119+
list<string> ptr_params =
120+
!foreach(P, Params, !if(ShouldCheckPointer<P>.ret, P.name, ""));
121+
list<string> ptr_params_filt = !filter(param, ptr_params, !ne(param, ""));
122+
list<string> ptr_param_conds =
123+
!foreach(ptr, ptr_params_filt, "`NULL == "#ptr#"`");
124+
125+
// Does the list of returns already contain ERROR_INVALID_NULL_POINTER?
126+
bit returns_has_inv_ptr = !foldl(
127+
0, Returns, HasErr, Ret,
128+
!or(HasErr, !eq(Ret.value, PREFIX#"_RESULT_ERROR_INVALID_NULL_POINTER")));
129+
list<Return> returns_out = !if(returns_has_inv_ptr,
130+
AppendConditionsToReturn<Returns, PREFIX # "_RESULT_ERROR_INVALID_NULL_POINTER", ptr_param_conds>.ret,
131+
!listconcat(Returns, [Return<PREFIX # "_RESULT_ERROR_INVALID_NULL_POINTER", ptr_param_conds>])
132+
);
133+
}
134+
135+
defvar DefaultReturns = [Return<PREFIX#"_RESULT_SUCCESS">,
136+
Return<PREFIX#"_RESULT_ERROR_UNINITIALIZED">,
137+
Return<PREFIX#"_RESULT_ERROR_DEVICE_LOST">];
138+
139+
class APIObject {
140+
string name;
141+
string desc;
142+
}
143+
144+
class Function : APIObject {
145+
list<Param> params;
146+
list<Return> returns;
147+
list<string> details = [];
148+
list<string> analogues = [];
149+
150+
list<Return> returns_with_def = !listconcat(DefaultReturns, returns);
151+
list<Return> all_returns = AddPointerChecksToReturns<params,
152+
AddHandleChecksToReturns<params, returns_with_def>.returns_out>.returns_out;
153+
}
154+
155+
class Etor<string Name, string Desc> {
156+
string name = Name;
157+
string desc = Desc;
158+
string tagged_type;
159+
}
160+
161+
class TaggedEtor<string Name, string Type, string Desc> : Etor<Name, Desc> {
162+
let tagged_type = Type;
163+
}
164+
165+
class Enum : APIObject {
166+
// This refers to whether the enumerator descriptions specify a return
167+
// type for functions where this enum may be used as an output type. If set,
168+
// all Etor values must be TaggedEtor records
169+
bit is_typed = 0;
170+
171+
list<Etor> etors = [];
172+
}
173+
174+
class StructMember<string Type, string Name, string Desc> {
175+
string type = Type;
176+
string name = Name;
177+
string desc = Desc;
178+
}
179+
180+
defvar DefaultPropStructMembers =
181+
[StructMember<prefix#"_structure_type_t", "stype",
182+
"type of this structure">,
183+
StructMember<"void*", "pNext", "pointer to extension-specific structure">];
184+
185+
class StructHasInheritedMembers<string BaseClass> {
186+
bit ret = !or(!eq(BaseClass, prefix#"_base_properties_t"),
187+
!eq(BaseClass, prefix#"_base_desc_t"));
188+
}
189+
190+
class Struct : APIObject {
191+
string base_class = "";
192+
list<StructMember> members;
193+
list<StructMember> all_members =
194+
!if(StructHasInheritedMembers<base_class>.ret,
195+
DefaultPropStructMembers, [])#members;
196+
}
197+
198+
class Typedef : APIObject { string value; }
199+
200+
class FptrTypedef : APIObject {
201+
list<Param> params;
202+
list<Return> returns;
203+
}
204+
205+
class Macro : APIObject {
206+
string value;
207+
208+
string condition;
209+
string alt_value;
210+
}
211+
212+
class Handle : APIObject;

offload/new-api/API/Common.td

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
def : Macro {
2+
let name = "OFFLOAD_APICALL";
3+
let desc = "Calling convention for all API functions";
4+
let condition = "defined(_WIN32)";
5+
let value = "__cdecl";
6+
let alt_value = "";
7+
}
8+
9+
def : Macro {
10+
let name = "OFFLOAD_APIEXPORT";
11+
let desc = "Microsoft-specific dllexport storage-class attribute";
12+
let condition = "defined(_WIN32)";
13+
let value = "__declspec(dllexport)";
14+
let alt_value = "";
15+
}
16+
17+
def : Macro {
18+
let name = "OFFLOAD_DLLEXPORT";
19+
let desc = "Microsoft-specific dllexport storage-class attribute";
20+
let condition = "defined(_WIN32)";
21+
let value = "__declspec(dllexport)";
22+
}
23+
24+
def : Macro {
25+
let name = "OFFLOAD_DLLEXPORT";
26+
let desc = "GCC-specific dllexport storage-class attribute";
27+
let condition = "__GNUC__ >= 4";
28+
let value = "__attribute__ ((visibility (\"default\")))";
29+
let alt_value = "";
30+
}
31+
32+
def : Typedef {
33+
let name = "offload_bool_t";
34+
let value = "uint8_t";
35+
let desc = "compiler-independent type";
36+
}
37+
38+
def : Handle {
39+
let name = "offload_platform_handle_t";
40+
let desc = "Handle of a platform instance";
41+
}
42+
43+
def : Handle {
44+
let name = "offload_device_handle_t";
45+
let desc = "Handle of platform's device object";
46+
}
47+
48+
def : Handle {
49+
let name = "offload_context_handle_t";
50+
let desc = "Handle of context object";
51+
}
52+
53+
def : Enum {
54+
let name = "offload_result_t";
55+
let desc = "Defines Return/Error codes";
56+
let etors =[
57+
Etor<"SUCCESS", "Success">,
58+
Etor<"ERROR_INVALID_VALUE", "Invalid Value">,
59+
Etor<"ERROR_INVALID_PLATFORM", "Invalid platform">,
60+
Etor<"ERROR_DEVICE_NOT_FOUND", "Device not found">,
61+
Etor<"ERROR_INVALID_DEVICE", "Invalid device">,
62+
Etor<"ERROR_DEVICE_LOST", "Device hung, reset, was removed, or driver update occurred">,
63+
Etor<"ERROR_UNINITIALIZED", "plugin is not initialized or specific entry-point is not implemented">,
64+
Etor<"ERROR_OUT_OF_RESOURCES", "Out of resources">,
65+
Etor<"ERROR_UNSUPPORTED_VERSION", "[Validation] generic error code for unsupported versions">,
66+
Etor<"ERROR_UNSUPPORTED_FEATURE", "[Validation] generic error code for unsupported features">,
67+
Etor<"ERROR_INVALID_ARGUMENT", "[Validation] generic error code for invalid arguments">,
68+
Etor<"ERROR_INVALID_NULL_HANDLE", "[Validation] handle argument is not valid">,
69+
Etor<"ERROR_INVALID_NULL_POINTER", "[Validation] pointer argument may not be nullptr">,
70+
Etor<"ERROR_INVALID_SIZE", "[Validation] invalid size or dimensions (e.g., must not be zero, or is out of bounds)">,
71+
Etor<"ERROR_INVALID_ENUMERATION", "[Validation] enumerator argument is not valid">,
72+
Etor<"ERROR_UNSUPPORTED_ENUMERATION", "[Validation] enumerator argument is not supported by the device">,
73+
Etor<"ERROR_UNKNOWN", "Unknown or internal error">
74+
];
75+
}

0 commit comments

Comments
 (0)