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