[Offload] Improve liboffload documentation (#142403)
- Update the main README to reflect the current project status - Rework the main API generation documentation. General fixes/tidying, but also spell out explicitly how to make API changes at the top of the document since this is what most people will care about. --------- Co-authored-by: Martin Grant <martingrant@outlook.com>
This commit is contained in:
parent
4e213159af
commit
acb52a8a98
@ -1,8 +1,5 @@
|
||||
# Offload API definitions
|
||||
|
||||
**Note**: This is a work-in-progress. It is loosely based on equivalent
|
||||
tooling in Unified Runtime.
|
||||
|
||||
The Tablegen files in this directory are used to define the Offload API. They
|
||||
are used with the `offload-tblgen` tool to generate API headers, print headers,
|
||||
and other implementation details.
|
||||
@ -10,17 +7,48 @@ and other implementation details.
|
||||
The root file is `OffloadAPI.td` - additional `.td` files can be included in
|
||||
this file to add them to the API.
|
||||
|
||||
## Modifying the API
|
||||
|
||||
API modifications, including additions, can be made by modifying the existing
|
||||
`.td` files. It is also possible to add a new tablegen file to the API by adding
|
||||
it to the includes in `OffloadAPI.td`. When Offload is rebuilt the new
|
||||
definition will be included in the generated files.
|
||||
|
||||
Most API changes and additions do not require any additional work beyond this,
|
||||
other than new functions which are described below.
|
||||
|
||||
### Adding a new function to the API
|
||||
|
||||
When a new function is added (e.g. `offloadDeviceFoo`), the actual entry
|
||||
point is automatically generated, which contains validation and tracing code.
|
||||
It expects an implementation function (`offloadDeviceFoo_impl`) to be defined,
|
||||
which it will call into. The definition of this implementation function should
|
||||
be added to `liboffload/src/OffloadImpl.cpp`
|
||||
|
||||
In short, the steps to add a new function are:
|
||||
* Add the new function definition to the `.td` files.
|
||||
* Build the `LLVMOffload` target. The relevant files will be regenerated, but
|
||||
the library will fail to link because it is missing the implementation
|
||||
function.
|
||||
* Add the new implementation function to `liboffload/src/OffloadImpl.cpp`. You
|
||||
can copy the new function declaration from the generated
|
||||
`OffloadImplFuncDecls.inc` file.
|
||||
* Rebuild `LLVMOffload`
|
||||
|
||||
## API Objects
|
||||
|
||||
The API consists of a number of objects, which always have a *name* field and
|
||||
*description* field, and are one of the following types:
|
||||
|
||||
### Function
|
||||
|
||||
Represents an API entry point function. Has a list of returns and parameters.
|
||||
Also has fields for details (representing a bullet-point list of
|
||||
information about the function that would otherwise be too detailed for the
|
||||
description), and analogues (equivalent functions in other APIs).
|
||||
Also has fields for details (representing a bullet-point list of information
|
||||
about the function that would otherwise be too detailed for the description),
|
||||
and analogues (equivalent functions in other APIs).
|
||||
|
||||
#### Parameter
|
||||
|
||||
Represents a parameter to a function, has *type*, *name*, and *desc* fields.
|
||||
Also has a *flags* field containing flags representing whether the parameter is
|
||||
in, out, or optional.
|
||||
@ -30,17 +58,24 @@ A *handle* type is a pointer to an opaque struct, used to abstract over
|
||||
plugin-specific implementation details.
|
||||
|
||||
There are two special variants of a *parameter*:
|
||||
* **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)`
|
||||
* **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.
|
||||
* **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)`
|
||||
* **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.
|
||||
|
||||
#### Return
|
||||
|
||||
A return represents a possible return code from the function, and optionally a
|
||||
list of conditions in which this value may be returned. The conditions list is
|
||||
not expected to be exhaustive. A condition is considered free-form text, but
|
||||
if it is wrapped in \`backticks\` then it is treated as literal code
|
||||
representing an error condition (e.g. `someParam < 1`). These conditions are
|
||||
used to automatically create validation checks by the `offload-tblgen`
|
||||
validation generator.
|
||||
not expected to be exhaustive. A condition is considered free-form text, but if
|
||||
it is wrapped in \`backticks\` then it is treated as literal code representing
|
||||
an error condition (e.g. `someParam < 1`). These conditions are used to
|
||||
automatically create validation checks by the `offload-tblgen` validation
|
||||
generator.
|
||||
|
||||
Returns are automatically generated for functions with pointer or handle
|
||||
parameters, so API authors do not need to exhaustively add null checks for
|
||||
@ -49,6 +84,7 @@ values automatically.
|
||||
|
||||
|
||||
### Struct
|
||||
|
||||
Represents a struct. Contains a list of members, which each have a *type*,
|
||||
*name*, and *desc*.
|
||||
|
||||
@ -59,24 +95,28 @@ actual C++ inheritance, but instead explicitly has those members copied in,
|
||||
which preserves ABI compatibility with C.
|
||||
|
||||
### Enum
|
||||
|
||||
Represents a C-style enum. Contains a list of `etor` values, which have a name
|
||||
and description.
|
||||
|
||||
A `TaggedEtor` record type also exists which additionally takes a type. This type
|
||||
is used when the enum is used as a parameter to a function with a type-tagged
|
||||
function parameter (e.g. `olGetDeviceInfo`).
|
||||
A `TaggedEtor` record type also exists which additionally takes a type. This
|
||||
type is used when the enum is used as a parameter to a function with a
|
||||
type-tagged function parameter (e.g. `olGetDeviceInfo`).
|
||||
|
||||
All enums automatically get a `<enum_name>_FORCE_UINT32 = 0x7fffffff` value,
|
||||
which forces the underlying type to be uint32.
|
||||
|
||||
### Handle
|
||||
|
||||
Represents a pointer to an opaque struct, as described in the Parameter section.
|
||||
It does not take any extra fields.
|
||||
|
||||
### Typedef
|
||||
|
||||
Represents a typedef, contains only a *value* field.
|
||||
|
||||
### Macro
|
||||
|
||||
Represents a C preprocessor `#define`. Contains a *value* field. Optionally
|
||||
takes a *condition* field, which allows the macro to be conditionally defined,
|
||||
and an *alt_value* field, which represents the value if the condition is false.
|
||||
@ -90,15 +130,20 @@ files, rather than requiring a mix of C source and tablegen.
|
||||
## Generation
|
||||
|
||||
### API header
|
||||
|
||||
```
|
||||
./offload-tblgen -I <path-to-llvm>/offload/API <path-to-llvm>/offload/API/OffloadAPI.td --gen-api
|
||||
```
|
||||
The comments in the generated header are in Doxygen format, although
|
||||
generating documentation from them hasn't been implemented yet.
|
||||
|
||||
The 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.
|
||||
The 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.
|
||||
|
||||
### Entry Points
|
||||
|
||||
```
|
||||
./offload-tblgen -I <path-to-llvm>/offload/API <path-to-llvm>/offload/API/OffloadAPI.td --gen-entry-points
|
||||
```
|
||||
@ -111,6 +156,7 @@ function calls with arguments and results. The tracing can be enabled with the
|
||||
`OFFLOAD_TRACE` environment variable.
|
||||
|
||||
### Implementation function declarations
|
||||
|
||||
```
|
||||
./offload-tblgen -I <path-to-llvm>/offload/API <path-to-llvm>/offload/API/OffloadAPI.td --gen-impl-func-decls
|
||||
```
|
||||
@ -118,11 +164,12 @@ Generates declarations of the implementation of functions of every entry point
|
||||
in the API, e.g. `offloadDeviceFoo_impl` for `offloadDeviceFoo`.
|
||||
|
||||
### Print header
|
||||
|
||||
```
|
||||
./offload-tblgen -I <path-to-llvm>/offload/API <path-to-llvm>/offload/API/OffloadAPI.td --gen-print-header
|
||||
```
|
||||
This header contains `std::ostream &operator<<(std::ostream&)` definitions for
|
||||
various API objects, including function parameters.
|
||||
This header contains `llvm::raw_ostream &operator<<(llvm::raw_ostream &)`
|
||||
definitions for various API objects, including function parameters.
|
||||
|
||||
As with the API header, it is expected that this header is part of the installed
|
||||
package, so it is entirely generated by Tablegen.
|
||||
@ -130,21 +177,7 @@ package, so it is entirely generated by Tablegen.
|
||||
For ease of implementation, and since it is not strictly part of the API, this
|
||||
is a C++ header file. If a C version is desirable it could be added.
|
||||
|
||||
### Future Tablegen backends
|
||||
`RecordTypes.hpp` contains wrappers for all of the API object types, which will
|
||||
allow more backends to be easily added in future.
|
||||
### Additional Tablegen backends
|
||||
|
||||
## Adding to the API
|
||||
|
||||
A new object can be added to the API by adding to one of the existing `.td`
|
||||
files. It is also possible to add a new tablegen file to the API by adding it
|
||||
to the includes in `OffloadAPI.td`. When the `OffloadGenerate` target is
|
||||
rebuilt, the new definition will be included in the generated files.
|
||||
|
||||
### Adding a new entry point
|
||||
|
||||
When a new entry point is added (e.g. `offloadDeviceFoo`), the actual entry
|
||||
point is automatically generated, which contains validation and tracing code.
|
||||
It expects an implementation function (`offloadDeviceFoo_impl`) to be defined,
|
||||
which it will call into. The definition of this implementation function should
|
||||
be added to `src/OffloadImpl.cpp`
|
||||
`RecordTypes.hpp` contains wrappers for all of the API object types, which
|
||||
allows new backends to be easily added if needed.
|
||||
|
@ -1,8 +1,34 @@
|
||||
# Offload New API
|
||||
# Liboffload
|
||||
|
||||
This directory contains the implementation of the experimental work-in-progress
|
||||
new API for Offload. It builds on top of the existing plugin implementations but
|
||||
provides a single level of abstraction suitable for runtimes for languages other
|
||||
than OpenMP to be built on top of.
|
||||
This directory contains the implementation of the work-in-progress new API for
|
||||
Offload. It builds on top of the existing plugin implementations but provides a
|
||||
single level of abstraction suitable for implementation of many offloading
|
||||
language runtimes, rather than just OpenMP.
|
||||
|
||||
See the [API definition readme](API/README.md) for implementation details.
|
||||
## Testing liboffload
|
||||
|
||||
The main test suite for liboffload can be run with the `check-offload-unit`
|
||||
target, which runs the `offload.unittests` executable. The test suite will
|
||||
automatically run on every available device, but can be restricted to a single
|
||||
platform (CUDA, AMDGPU) with a command line argument:
|
||||
|
||||
```sh
|
||||
$ ./offload.unittests --platform=CUDA
|
||||
```
|
||||
|
||||
Tracing of Offload API calls can be enabled by setting the `OFFLOAD_TRACE`
|
||||
environment variable. This works with any program that uses liboffload.
|
||||
|
||||
```sh
|
||||
$ OFFLOAD_TRACE=1 ./offload.unittests
|
||||
---> olInit()-> OL_SUCCESS
|
||||
# etc
|
||||
```
|
||||
|
||||
The host plugin is not currently supported.
|
||||
|
||||
## Modifying liboffload
|
||||
|
||||
The main header (`OffloadAPI.h`) and some implementation details are
|
||||
autogenerated with tablegen. See the [API definition README](API/README.md)
|
||||
for implementation details.
|
||||
|
@ -82,7 +82,7 @@ void EmitOffloadErrcodes(const RecordKeeper &Records, raw_ostream &OS) {
|
||||
#endif
|
||||
|
||||
// Error codes are shared between PluginInterface and liboffload.
|
||||
// To add new error codes, add them to offload/liboffload/API/Common.td and run the GenerateOffload target.
|
||||
// To add new error codes, add them to offload/liboffload/API/Common.td.
|
||||
|
||||
)";
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user