xref: /llvm-project/offload/liboffload/API/APIDefs.td (revision fd3907ccb583df99e9c19d2fe84e4e7c52d75de9)
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.
17defvar PREFIX = "OL";
18defvar prefix = !tolower(PREFIX);
19
20// Parameter flags
21defvar PARAM_IN = 0x1;
22defvar PARAM_OUT = 0x2;
23defvar PARAM_OPTIONAL = 0x4;
24defvar PARAM_IN_OPTIONAL = !or(PARAM_IN, PARAM_OPTIONAL);
25defvar PARAM_OUT_OPTIONAL = !or(PARAM_OUT, PARAM_OPTIONAL);
26
27// Does the type end with '_handle_t'?
28class 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 '*'?
35class 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
40class 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
47class TypeInfo<string TypeEnum, string TypeSize> {
48  string enum = TypeEnum;
49  string size = TypeSize;
50}
51
52class 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.
64class 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.
70class TypeTaggedParam<string Type, string Name, string Desc, bits<3> Flags, TypeInfo ParamTypeInfo> : Param<Type, Name, Desc, Flags> {
71  let type_info = ParamTypeInfo;
72}
73
74class Return<string Value, list<string> Conditions = []> {
75  string value = Value;
76  list<string> conditions = Conditions;
77}
78
79class ShouldCheckHandle<Param P> {
80  bit ret = !and(P.IsHandle, !eq(!and(PARAM_OPTIONAL, P.flags), 0));
81}
82
83class 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
89class 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
98class 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#"_ERRC_INVALID_NULL_HANDLE")));
110
111  list<Return> returns_out = !if(returns_has_inv_handle,
112        AppendConditionsToReturn<Returns, PREFIX # "_ERRC_INVALID_NULL_HANDLE", handle_param_conds>.ret,
113        !listconcat(Returns, [Return<PREFIX # "_ERRC_INVALID_NULL_HANDLE", handle_param_conds>])
114    );
115}
116
117// Add null pointer checks to a function's return value descriptions
118class 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#"_ERRC_INVALID_NULL_POINTER")));
129  list<Return> returns_out = !if(returns_has_inv_ptr,
130        AppendConditionsToReturn<Returns, PREFIX # "_ERRC_INVALID_NULL_POINTER", ptr_param_conds>.ret,
131        !listconcat(Returns, [Return<PREFIX # "_ERRC_INVALID_NULL_POINTER", ptr_param_conds>])
132    );
133}
134
135defvar DefaultReturns = [Return<PREFIX#"_RESULT_SUCCESS">,
136                         Return<PREFIX#"_ERRC_UNINITIALIZED">,
137                         Return<PREFIX#"_ERRC_DEVICE_LOST">];
138
139class APIObject {
140  string name;
141  string desc;
142}
143
144class 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
155class Etor<string Name, string Desc> {
156  string name = Name;
157  string desc = Desc;
158  string tagged_type;
159}
160
161class TaggedEtor<string Name, string Type, string Desc> : Etor<Name, Desc> {
162  let tagged_type = Type;
163}
164
165class 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
174class StructMember<string Type, string Name, string Desc> {
175  string type = Type;
176  string name = Name;
177  string desc = Desc;
178}
179
180defvar DefaultPropStructMembers =
181    [StructMember<prefix#"_structure_type_t", "stype",
182                  "type of this structure">,
183     StructMember<"void*", "pNext", "pointer to extension-specific structure">];
184
185class StructHasInheritedMembers<string BaseClass> {
186  bit ret = !or(!eq(BaseClass, prefix#"_base_properties_t"),
187                !eq(BaseClass, prefix#"_base_desc_t"));
188}
189
190class 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
198class Typedef : APIObject { string value; }
199
200class FptrTypedef : APIObject {
201  list<Param> params;
202  list<Return> returns;
203}
204
205class Macro : APIObject {
206  string value;
207
208  string condition;
209  string alt_value;
210}
211
212class Handle : APIObject;
213