xref: /llvm-project/offload/liboffload/API/README.md (revision fd3907ccb583df99e9c19d2fe84e4e7c52d75de9)
1# Offload API definitions
2
3**Note**: This is a work-in-progress. It is loosely based on equivalent
4tooling in Unified Runtime.
5
6The Tablegen files in this directory are used to define the Offload API. They
7are used with the `offload-tblgen` tool to generate API headers, print headers,
8and other implementation details.
9
10The root file is `OffloadAPI.td` - additional `.td` files can be included in
11this file to add them to the API.
12
13## API Objects
14The API consists of a number of objects, which always have a *name* field and
15*description* field, and are one of the following types:
16
17### Function
18Represents an API entry point function. Has a list of returns and parameters.
19Also has fields for details (representing a bullet-point list of
20information about the function that would otherwise be too detailed for the
21description), and analogues (equivalent functions in other APIs).
22
23#### Parameter
24Represents a parameter to a function, has *type*, *name*, and *desc* fields.
25Also has a *flags* field containing flags representing whether the parameter is
26in, out, or optional.
27
28The *type* field is used to infer if the parameter is a pointer or handle type.
29A *handle* type is a pointer to an opaque struct, used to abstract over
30plugin-specific implementation details.
31
32There are two special variants of a *parameter*:
33* **RangedParameter** - Represents a parameter that has a range described by other parameters. Generally these are pointers to an arbitrary number of objects. The range is used for generating validation and printing code. E.g, a range might be between `(0, NumDevices)`
34* **TypeTaggedParameter** - Represents a parameter (usually of `void*` type) that has the type and size of its pointee data described by other function parameters. The type is usually described by a type-tagged enum. This allows functions (e.g. `olGetDeviceInfo`) to return data of an arbitrary type.
35
36#### Return
37A return represents a possible return code from the function, and optionally a
38list of conditions in which this value may be returned. The conditions list is
39not expected to be exhaustive. A condition is considered free-form text, but
40if it is wrapped in \`backticks\` then it is treated as literal code
41representing an error condition (e.g. `someParam < 1`). These conditions are
42used to automatically create validation checks by the `offload-tblgen`
43validation generator.
44
45Returns are automatically generated for functions with pointer or handle
46parameters, so API authors do not need to exhaustively add null checks for
47these types of parameters. All functions also get a number of default return
48values automatically.
49
50
51### Struct
52Represents a struct. Contains a list of members, which each have a *type*,
53*name*, and *desc*.
54
55Also optionally takes a *base_class* field. If this is either of the special
56`offload_base_properties_t` or `offload_base_desc_t` structs, then the struct
57will inherit members from those structs. The generated struct does **not** use
58actual C++ inheritance, but instead explicitly has those members copied in,
59which preserves ABI compatibility with C.
60
61### Enum
62Represents a C-style enum. Contains a list of `etor` values, which have a name
63and description.
64
65A `TaggedEtor` record type also exists which addtionally takes a type. This type
66is used when the enum is used as a parameter to a function with a type-tagged
67function parameter (e.g. `olGetDeviceInfo`).
68
69All enums automatically get a `<enum_name>_FORCE_UINT32 = 0x7fffffff` value,
70which forces the underlying type to be uint32.
71
72### Handle
73Represents a pointer to an opaque struct, as described in the Parameter section.
74It does not take any extra fields.
75
76### Typedef
77Represents a typedef, contains only a *value* field.
78
79### Macro
80Represents a C preprocessor `#define`. Contains a *value* field. Optionally
81takes a *condition* field, which allows the macro to be conditionally defined,
82and an *alt_value* field, which represents the value if the condition is false.
83
84Macro arguments are presented in the *name* field (e.g. name = `mymacro(arg)`).
85
86While there may seem little point generating a macro from tablegen, doing this
87allows the entire source of the header file to be generated from the tablegen
88files, rather than requiring a mix of C source and tablegen.
89
90## Generation
91
92### API header
93```
94./offload-tblgen -I <path-to-llvm>/offload/API  <path-to-llvm>/offload/API/OffloadAPI.td --gen-api
95```
96The comments in the generated header are in Doxygen format, although
97generating documentation from them hasn't been implemented yet.
98
99The entirety of this header is generated by Tablegen, rather than having a predefined header file that includes one or more `.inc` files. This is because this header is expected to be part of the installation and distributed to end-users, so should be self-contained.
100
101### Entry Points
102```
103./offload-tblgen -I <path-to-llvm>/offload/API  <path-to-llvm>/offload/API/OffloadAPI.td --gen-entry-points
104```
105These functions form the actual Offload interface, and are wrappers over the
106functions that contain the actual implementation (see
107'Adding a new entry point').
108
109They implement automatically generated validation checks, and tracing of
110function calls with arguments and results. The tracing can be enabled with the
111`OFFLOAD_TRACE` environment variable.
112
113### Implementation function declarations
114```
115./offload-tblgen -I <path-to-llvm>/offload/API  <path-to-llvm>/offload/API/OffloadAPI.td --gen-impl-func-decls
116```
117Generates declarations of the implementation of functions of every entry point
118in the API, e.g. `offloadDeviceFoo_impl` for `offloadDeviceFoo`.
119
120### Print header
121```
122./offload-tblgen -I <path-to-llvm>/offload/API  <path-to-llvm>/offload/API/OffloadAPI.td --gen-print-header
123```
124This header contains `std::ostream &operator<<(std::ostream&)` definitions for
125various API objects, including function parameters.
126
127As with the API header, it is expected that this header is part of the installed
128package, so it is entirely generated by Tablegen.
129
130For ease of implementation, and since it is not strictly part of the API, this
131is a C++ header file. If a C version is desirable it could be added.
132
133### Future Tablegen backends
134`RecordTypes.hpp` contains wrappers for all of the API object types, which will
135allow more backends to be easily added in future.
136
137## Adding to the API
138
139A new object can be added to the API by adding to one of the existing `.td`
140files. It is also possible to add a new tablegen file to the API by adding it
141to the includes in `OffloadAPI.td`. When the offload target is rebuilt, the
142new definition will be included in the generated files.
143
144### Adding a new entry point
145
146When a new entry point is added (e.g. `offloadDeviceFoo`), the actual entry
147point is automatically generated, which contains validation and tracing code.
148It expects an implementation function (`offloadDeviceFoo_impl`) to be defined,
149which it will call into. The definition of this implementation function should
150be added to `src/offload_impl.cpp`
151