aboutsummaryrefslogtreecommitdiff
path: root/offload/liboffload/API
diff options
context:
space:
mode:
Diffstat (limited to 'offload/liboffload/API')
-rw-r--r--offload/liboffload/API/APIDefs.td212
-rw-r--r--offload/liboffload/API/CMakeLists.txt25
-rw-r--r--offload/liboffload/API/Common.td141
-rw-r--r--offload/liboffload/API/Device.td106
-rw-r--r--offload/liboffload/API/OffloadAPI.td15
-rw-r--r--offload/liboffload/API/Platform.td112
-rw-r--r--offload/liboffload/API/README.md150
7 files changed, 761 insertions, 0 deletions
diff --git a/offload/liboffload/API/APIDefs.td b/offload/liboffload/API/APIDefs.td
new file mode 100644
index 0000000..60c1b85
--- /dev/null
+++ b/offload/liboffload/API/APIDefs.td
@@ -0,0 +1,212 @@
+//===-- APIDefs.td - Base definitions for Offload tablegen -*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the class definitions used to implement the Offload API,
+// as well as helper functions used to help populate relevant records.
+// See offload/API/README.md for more detailed documentation.
+//
+//===----------------------------------------------------------------------===//
+
+// Prefix for API naming. This could be hard-coded in the future when a value
+// is agreed upon.
+defvar PREFIX = "OL";
+defvar prefix = !tolower(PREFIX);
+
+// Parameter flags
+defvar PARAM_IN = 0x1;
+defvar PARAM_OUT = 0x2;
+defvar PARAM_OPTIONAL = 0x4;
+defvar PARAM_IN_OPTIONAL = !or(PARAM_IN, PARAM_OPTIONAL);
+defvar PARAM_OUT_OPTIONAL = !or(PARAM_OUT, PARAM_OPTIONAL);
+
+// Does the type end with '_handle_t'?
+class IsHandleType<string Type> {
+ // size("_handle_t") == 9
+ bit ret = !if(!lt(!size(Type), 9), 0,
+ !ne(!find(Type, "_handle_t", !sub(!size(Type), 9)), -1));
+}
+
+// Does the type end with '*'?
+class IsPointerType<string Type> {
+ bit ret = !ne(!find(Type, "*", !sub(!size(Type), 1)), -1);
+}
+
+// Describes the valid range of a pointer parameter that reperesents an array
+class Range<string Begin, string End> {
+ string begin = Begin;
+ string end = End;
+}
+
+// Names the parameters that indicate the type and size of the data pointed to
+// by an opaque pointer parameter
+class TypeInfo<string TypeEnum, string TypeSize> {
+ string enum = TypeEnum;
+ string size = TypeSize;
+}
+
+class Param<string Type, string Name, string Desc, bits<3> Flags = 0> {
+ string type = Type;
+ string name = Name;
+ string desc = Desc;
+ bits<3> flags = Flags;
+ Range range = Range<"", "">;
+ TypeInfo type_info = TypeInfo<"", "">;
+ bit IsHandle = IsHandleType<type>.ret;
+ bit IsPointer = IsPointerType<type>.ret;
+}
+
+// A parameter whose range is described by other parameters in the function.
+class RangedParam<string Type, string Name, string Desc, bits<3> Flags, Range ParamRange> : Param<Type, Name, Desc, Flags> {
+ let range = ParamRange;
+}
+
+// A parameter (normally of type void*) which has its pointee type and size
+// described by other parameters in the function.
+class TypeTaggedParam<string Type, string Name, string Desc, bits<3> Flags, TypeInfo ParamTypeInfo> : Param<Type, Name, Desc, Flags> {
+ let type_info = ParamTypeInfo;
+}
+
+class Return<string Value, list<string> Conditions = []> {
+ string value = Value;
+ list<string> conditions = Conditions;
+}
+
+class ShouldCheckHandle<Param P> {
+ bit ret = !and(P.IsHandle, !eq(!and(PARAM_OPTIONAL, P.flags), 0));
+}
+
+class ShouldCheckPointer<Param P> {
+ bit ret = !and(P.IsPointer, !eq(!and(PARAM_OPTIONAL, P.flags), 0));
+}
+
+// For a list of returns that contains a specific return code, find and append
+// new conditions to that return
+class AppendConditionsToReturn<list<Return> Returns, string ReturnValue,
+ list<string> Conditions> {
+ list<Return> ret =
+ !foreach(Ret, Returns,
+ !if(!eq(Ret.value, ReturnValue),
+ Return<Ret.value, Ret.conditions#Conditions>, Ret));
+}
+
+// Add null handle checks to a function's return value descriptions
+class AddHandleChecksToReturns<list<Param> Params, list<Return> Returns> {
+ list<string> handle_params =
+ !foreach(P, Params, !if(ShouldCheckHandle<P>.ret, P.name, ""));
+ list<string> handle_params_filt =
+ !filter(param, handle_params, !ne(param, ""));
+ list<string> handle_param_conds =
+ !foreach(handle, handle_params_filt, "`NULL == "#handle#"`");
+
+ // Does the list of returns already contain ERROR_INVALID_NULL_HANDLE?
+ bit returns_has_inv_handle = !foldl(
+ 0, Returns, HasErr, Ret,
+ !or(HasErr, !eq(Ret.value, PREFIX#"_ERRC_INVALID_NULL_HANDLE")));
+
+ list<Return> returns_out = !if(returns_has_inv_handle,
+ AppendConditionsToReturn<Returns, PREFIX # "_ERRC_INVALID_NULL_HANDLE", handle_param_conds>.ret,
+ !listconcat(Returns, [Return<PREFIX # "_ERRC_INVALID_NULL_HANDLE", handle_param_conds>])
+ );
+}
+
+// Add null pointer checks to a function's return value descriptions
+class AddPointerChecksToReturns<list<Param> Params, list<Return> Returns> {
+ list<string> ptr_params =
+ !foreach(P, Params, !if(ShouldCheckPointer<P>.ret, P.name, ""));
+ list<string> ptr_params_filt = !filter(param, ptr_params, !ne(param, ""));
+ list<string> ptr_param_conds =
+ !foreach(ptr, ptr_params_filt, "`NULL == "#ptr#"`");
+
+ // Does the list of returns already contain ERROR_INVALID_NULL_POINTER?
+ bit returns_has_inv_ptr = !foldl(
+ 0, Returns, HasErr, Ret,
+ !or(HasErr, !eq(Ret.value, PREFIX#"_ERRC_INVALID_NULL_POINTER")));
+ list<Return> returns_out = !if(returns_has_inv_ptr,
+ AppendConditionsToReturn<Returns, PREFIX # "_ERRC_INVALID_NULL_POINTER", ptr_param_conds>.ret,
+ !listconcat(Returns, [Return<PREFIX # "_ERRC_INVALID_NULL_POINTER", ptr_param_conds>])
+ );
+}
+
+defvar DefaultReturns = [Return<PREFIX#"_RESULT_SUCCESS">,
+ Return<PREFIX#"_ERRC_UNINITIALIZED">,
+ Return<PREFIX#"_ERRC_DEVICE_LOST">];
+
+class APIObject {
+ string name;
+ string desc;
+}
+
+class Function : APIObject {
+ list<Param> params;
+ list<Return> returns;
+ list<string> details = [];
+ list<string> analogues = [];
+
+ list<Return> returns_with_def = !listconcat(DefaultReturns, returns);
+ list<Return> all_returns = AddPointerChecksToReturns<params,
+ AddHandleChecksToReturns<params, returns_with_def>.returns_out>.returns_out;
+}
+
+class Etor<string Name, string Desc> {
+ string name = Name;
+ string desc = Desc;
+ string tagged_type;
+}
+
+class TaggedEtor<string Name, string Type, string Desc> : Etor<Name, Desc> {
+ let tagged_type = Type;
+}
+
+class Enum : APIObject {
+ // This refers to whether the enumerator descriptions specify a return
+ // type for functions where this enum may be used as an output type. If set,
+ // all Etor values must be TaggedEtor records
+ bit is_typed = 0;
+
+ list<Etor> etors = [];
+}
+
+class StructMember<string Type, string Name, string Desc> {
+ string type = Type;
+ string name = Name;
+ string desc = Desc;
+}
+
+defvar DefaultPropStructMembers =
+ [StructMember<prefix#"_structure_type_t", "stype",
+ "type of this structure">,
+ StructMember<"void*", "pNext", "pointer to extension-specific structure">];
+
+class StructHasInheritedMembers<string BaseClass> {
+ bit ret = !or(!eq(BaseClass, prefix#"_base_properties_t"),
+ !eq(BaseClass, prefix#"_base_desc_t"));
+}
+
+class Struct : APIObject {
+ string base_class = "";
+ list<StructMember> members;
+ list<StructMember> all_members =
+ !if(StructHasInheritedMembers<base_class>.ret,
+ DefaultPropStructMembers, [])#members;
+}
+
+class Typedef : APIObject { string value; }
+
+class FptrTypedef : APIObject {
+ list<Param> params;
+ list<Return> returns;
+}
+
+class Macro : APIObject {
+ string value;
+
+ string condition;
+ string alt_value;
+}
+
+class Handle : APIObject;
diff --git a/offload/liboffload/API/CMakeLists.txt b/offload/liboffload/API/CMakeLists.txt
new file mode 100644
index 0000000..8fd6cb5
--- /dev/null
+++ b/offload/liboffload/API/CMakeLists.txt
@@ -0,0 +1,25 @@
+# The OffloadGenerate target is used to regenerate the generated files in the
+# include directory. These files are checked in with the rest of the source,
+# therefore it is only needed when making changes to the API.
+
+find_program(CLANG_FORMAT clang-format PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH)
+if (CLANG_FORMAT)
+ set(LLVM_TARGET_DEFINITIONS ${CMAKE_CURRENT_SOURCE_DIR}/OffloadAPI.td)
+
+ tablegen(OFFLOAD OffloadAPI.h -gen-api)
+ tablegen(OFFLOAD OffloadEntryPoints.inc -gen-entry-points)
+ tablegen(OFFLOAD OffloadFuncs.inc -gen-func-names)
+ tablegen(OFFLOAD OffloadImplFuncDecls.inc -gen-impl-func-decls)
+ tablegen(OFFLOAD OffloadPrint.hpp -gen-print-header)
+
+ set(OFFLOAD_GENERATED_FILES ${TABLEGEN_OUTPUT})
+ add_public_tablegen_target(OffloadGenerate)
+ add_custom_command(TARGET OffloadGenerate POST_BUILD COMMAND ${CLANG_FORMAT}
+ -i ${OFFLOAD_GENERATED_FILES})
+ add_custom_command(TARGET OffloadGenerate POST_BUILD COMMAND ${CMAKE_COMMAND}
+ -E copy_if_different ${OFFLOAD_GENERATED_FILES} "${CMAKE_CURRENT_SOURCE_DIR}/../include/generated")
+else()
+ message(WARNING "clang-format was not found, so the OffloadGenerate target\
+ will not be available. Offload will still build, but you will not be\
+ able to make changes to the API.")
+endif()
diff --git a/offload/liboffload/API/Common.td b/offload/liboffload/API/Common.td
new file mode 100644
index 0000000..5b19d1d
--- /dev/null
+++ b/offload/liboffload/API/Common.td
@@ -0,0 +1,141 @@
+def : Macro {
+ let name = "OL_VERSION_MAJOR";
+ let desc = "Major version of the Offload API";
+ let value = "0";
+}
+
+def : Macro {
+ let name = "OL_VERSION_MINOR";
+ let desc = "Minor version of the Offload API";
+ let value = "0";
+}
+
+def : Macro {
+ let name = "OL_VERSION_PATCH";
+ let desc = "Patch version of the Offload API";
+ let value = "1";
+}
+
+def : Macro {
+ let name = "OL_APICALL";
+ let desc = "Calling convention for all API functions";
+ let condition = "defined(_WIN32)";
+ let value = "__cdecl";
+ let alt_value = "";
+}
+
+def : Macro {
+ let name = "OL_APIEXPORT";
+ let desc = "Microsoft-specific dllexport storage-class attribute";
+ let condition = "defined(_WIN32)";
+ let value = "__declspec(dllexport)";
+ let alt_value = "";
+}
+
+def : Macro {
+ let name = "OL_DLLEXPORT";
+ let desc = "Microsoft-specific dllexport storage-class attribute";
+ let condition = "defined(_WIN32)";
+ let value = "__declspec(dllexport)";
+}
+
+def : Macro {
+ let name = "OL_DLLEXPORT";
+ let desc = "GCC-specific dllexport storage-class attribute";
+ let condition = "__GNUC__ >= 4";
+ let value = "__attribute__ ((visibility (\"default\")))";
+ let alt_value = "";
+}
+
+def : Handle {
+ let name = "ol_platform_handle_t";
+ let desc = "Handle of a platform instance";
+}
+
+def : Handle {
+ let name = "ol_device_handle_t";
+ let desc = "Handle of platform's device object";
+}
+
+def : Handle {
+ let name = "ol_context_handle_t";
+ let desc = "Handle of context object";
+}
+
+def : Enum {
+ let name = "ol_errc_t";
+ let desc = "Defines Return/Error codes";
+ let etors =[
+ Etor<"SUCCESS", "Success">,
+ Etor<"INVALID_VALUE", "Invalid Value">,
+ Etor<"INVALID_PLATFORM", "Invalid platform">,
+ Etor<"DEVICE_NOT_FOUND", "Device not found">,
+ Etor<"INVALID_DEVICE", "Invalid device">,
+ Etor<"DEVICE_LOST", "Device hung, reset, was removed, or driver update occurred">,
+ Etor<"UNINITIALIZED", "plugin is not initialized or specific entry-point is not implemented">,
+ Etor<"OUT_OF_RESOURCES", "Out of resources">,
+ Etor<"UNSUPPORTED_VERSION", "generic error code for unsupported versions">,
+ Etor<"UNSUPPORTED_FEATURE", "generic error code for unsupported features">,
+ Etor<"INVALID_ARGUMENT", "generic error code for invalid arguments">,
+ Etor<"INVALID_NULL_HANDLE", "handle argument is not valid">,
+ Etor<"INVALID_NULL_POINTER", "pointer argument may not be nullptr">,
+ Etor<"INVALID_SIZE", "invalid size or dimensions (e.g., must not be zero, or is out of bounds)">,
+ Etor<"INVALID_ENUMERATION", "enumerator argument is not valid">,
+ Etor<"UNSUPPORTED_ENUMERATION", "enumerator argument is not supported by the device">,
+ Etor<"UNKNOWN", "Unknown or internal error">
+ ];
+}
+
+def : Struct {
+ let name = "ol_error_struct_t";
+ let desc = "Details of the error condition returned by an API call";
+ let members = [
+ StructMember<"ol_errc_t", "Code", "The error code">,
+ StructMember<"const char*", "Details", "String containing error details">
+ ];
+}
+
+def : Typedef {
+ let name = "ol_result_t";
+ let desc = "Result type returned by all entry points.";
+ let value = "const ol_error_struct_t*";
+}
+
+def : Macro {
+ let name = "OL_SUCCESS";
+ let desc = "Success condition";
+ let value = "NULL";
+}
+
+def : Struct {
+ let name = "ol_code_location_t";
+ let desc = "Code location information that can optionally be associated with an API call";
+ let members = [
+ StructMember<"const char*", "FunctionName", "Function name">,
+ StructMember<"const char*", "SourceFile", "Source code file">,
+ StructMember<"uint32_t", "LineNumber", "Source code line number">,
+ StructMember<"uint32_t", "ColumnNumber", "Source code column number">
+ ];
+}
+
+def : Function {
+ let name = "olInit";
+ let desc = "Perform initialization of the Offload library and plugins";
+ let details = [
+ "This must be the first API call made by a user of the Offload library",
+ "Each call will increment an internal reference count that is decremented by `olShutDown`"
+ ];
+ let params = [];
+ let returns = [];
+}
+
+def : Function {
+ let name = "olShutDown";
+ let desc = "Release the resources in use by Offload";
+ let details = [
+ "This decrements an internal reference count. When this reaches 0, all resources will be released",
+ "Subsequent API calls made after this are not valid"
+ ];
+ let params = [];
+ let returns = [];
+}
diff --git a/offload/liboffload/API/Device.td b/offload/liboffload/API/Device.td
new file mode 100644
index 0000000..30c0b71
--- /dev/null
+++ b/offload/liboffload/API/Device.td
@@ -0,0 +1,106 @@
+//===-- Device.td - Device definitions for Offload ---------*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains Offload API definitions related to the Device handle
+//
+//===----------------------------------------------------------------------===//
+
+def : Enum {
+ let name = "ol_device_type_t";
+ let desc = "Supported device types";
+ let etors =[
+ Etor<"DEFAULT", "The default device type as preferred by the runtime">,
+ Etor<"ALL", "Devices of all types">,
+ Etor<"GPU", "GPU device type">,
+ Etor<"CPU", "CPU device type">,
+ ];
+}
+
+def : Enum {
+ let name = "ol_device_info_t";
+ let desc = "Supported device info";
+ let is_typed = 1;
+ let etors =[
+ TaggedEtor<"TYPE", "ol_device_type_t", "type of the device">,
+ TaggedEtor<"PLATFORM", "ol_platform_handle_t", "the platform associated with the device">,
+ TaggedEtor<"NAME", "char[]", "Device name">,
+ TaggedEtor<"VENDOR", "char[]", "Device vendor">,
+ TaggedEtor<"DRIVER_VERSION", "char[]", "Driver version">
+ ];
+}
+
+def : Function {
+ let name = "olGetDeviceCount";
+ let desc = "Retrieves the number of available devices within a platform";
+ let params = [
+ Param<"ol_platform_handle_t", "Platform", "handle of the platform instance", PARAM_IN>,
+ Param<"uint32_t*", "NumDevices", "pointer to the number of devices.", PARAM_OUT>
+ ];
+ let returns = [];
+}
+
+def : Function {
+ let name = "olGetDevice";
+ let desc = "Retrieves devices within a platform";
+ let details = [
+ "Multiple calls to this function will return identical device handles, in the same order.",
+ ];
+ let params = [
+ Param<"ol_platform_handle_t", "Platform", "handle of the platform instance", PARAM_IN>,
+ Param<"uint32_t", "NumEntries", "the number of devices to be added to phDevices, which must be greater than zero", PARAM_IN>,
+ RangedParam<"ol_device_handle_t*", "Devices", "Array of device handles. "
+ "If NumEntries is less than the number of devices available, then this function shall only retrieve that number of devices.", PARAM_OUT,
+ Range<"0", "NumEntries">>
+ ];
+ let returns = [
+ Return<"OL_ERRC_INVALID_SIZE", [
+ "`NumEntries == 0`"
+ ]>
+ ];
+}
+
+def : Function {
+ let name = "olGetDeviceInfo";
+ let desc = "Queries the given property of the device";
+ let details = [];
+ let params = [
+ Param<"ol_device_handle_t", "Device", "handle of the device instance", PARAM_IN>,
+ Param<"ol_device_info_t", "PropName", "type of the info to retrieve", PARAM_IN>,
+ Param<"size_t", "PropSize", "the number of bytes pointed to by PropValue.", PARAM_IN>,
+ TypeTaggedParam<"void*", "PropValue", "array of bytes holding the info. If PropSize is not equal to or greater than the real "
+ "number of bytes needed to return the info then the OL_ERRC_INVALID_SIZE error is returned and "
+ "PropValue is not used.", PARAM_OUT, TypeInfo<"PropName" , "PropSize">>
+ ];
+ let returns = [
+ Return<"OL_ERRC_UNSUPPORTED_ENUMERATION", [
+ "If `PropName` is not supported by the device."
+ ]>,
+ Return<"OL_ERRC_INVALID_SIZE", [
+ "`PropSize == 0`",
+ "If `PropSize` is less than the real number of bytes needed to return the info."
+ ]>,
+ Return<"OL_ERRC_INVALID_DEVICE">
+ ];
+}
+
+def : Function {
+ let name = "olGetDeviceInfoSize";
+ let desc = "Returns the storage size of the given device query";
+ let details = [];
+ let params = [
+ Param<"ol_device_handle_t", "Device", "handle of the device instance", PARAM_IN>,
+ Param<"ol_device_info_t", "PropName", "type of the info to retrieve", PARAM_IN>,
+ Param<"size_t*", "PropSizeRet", "pointer to the number of bytes required to store the query", PARAM_OUT>
+ ];
+ let returns = [
+ Return<"OL_ERRC_UNSUPPORTED_ENUMERATION", [
+ "If `PropName` is not supported by the device."
+ ]>,
+ Return<"OL_ERRC_INVALID_DEVICE">
+ ];
+}
diff --git a/offload/liboffload/API/OffloadAPI.td b/offload/liboffload/API/OffloadAPI.td
new file mode 100644
index 0000000..8a0c3c40
--- /dev/null
+++ b/offload/liboffload/API/OffloadAPI.td
@@ -0,0 +1,15 @@
+//===-- OffloadAPI.td - Root tablegen file for Offload -----*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Always include this file first
+include "APIDefs.td"
+
+// Add API definition files here
+include "Common.td"
+include "Platform.td"
+include "Device.td"
diff --git a/offload/liboffload/API/Platform.td b/offload/liboffload/API/Platform.td
new file mode 100644
index 0000000..03e70cf9
--- /dev/null
+++ b/offload/liboffload/API/Platform.td
@@ -0,0 +1,112 @@
+//===-- Platform.td - Platform definitions for Offload -----*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains Offload API definitions related to the Platform handle
+//
+//===----------------------------------------------------------------------===//
+def : Function {
+ let name = "olGetPlatform";
+ let desc = "Retrieves all available platforms";
+ let details = [
+ "Multiple calls to this function will return identical platforms handles, in the same order.",
+ ];
+ let params = [
+ Param<"uint32_t", "NumEntries",
+ "The number of platforms to be added to Platforms. NumEntries must be "
+ "greater than zero.",
+ PARAM_IN>,
+ RangedParam<"ol_platform_handle_t*", "Platforms",
+ "Array of handle of platforms. If NumEntries is less than the number of "
+ "platforms available, then olGetPlatform shall only retrieve that "
+ "number of platforms.",
+ PARAM_OUT, Range<"0", "NumEntries">>
+ ];
+ let returns = [
+ Return<"OL_ERRC_INVALID_SIZE", [
+ "`NumEntries == 0`"
+ ]>
+ ];
+}
+
+def : Function {
+ let name = "olGetPlatformCount";
+ let desc = "Retrieves the number of available platforms";
+ let params = [
+ Param<"uint32_t*",
+ "NumPlatforms", "returns the total number of platforms available.",
+ PARAM_OUT>
+ ];
+ let returns = [];
+}
+
+def : Enum {
+ let name = "ol_platform_info_t";
+ let desc = "Supported platform info";
+ let is_typed = 1;
+ let etors = [
+ TaggedEtor<"NAME", "char[]", "The string denoting name of the platform. The size of the info needs to be dynamically queried.">,
+ TaggedEtor<"VENDOR_NAME", "char[]", "The string denoting name of the vendor of the platform. The size of the info needs to be dynamically queried.">,
+ TaggedEtor<"VERSION", "char[]", "The string denoting the version of the platform. The size of the info needs to be dynamically queried.">,
+ TaggedEtor<"BACKEND", "ol_platform_backend_t", "The native backend of the platform.">
+ ];
+}
+
+def : Enum {
+ let name = "ol_platform_backend_t";
+ let desc = "Identifies the native backend of the platform";
+ let etors =[
+ Etor<"UNKNOWN", "The backend is not recognized">,
+ Etor<"CUDA", "The backend is CUDA">,
+ Etor<"AMDGPU", "The backend is AMDGPU">,
+ ];
+}
+
+def : Function {
+ let name = "olGetPlatformInfo";
+ let desc = "Queries the given property of the platform";
+ let details = [
+ "`olGetPlatformInfoSize` can be used to query the storage size "
+ "required for the given query."
+ ];
+ let params = [
+ Param<"ol_platform_handle_t", "Platform", "handle of the platform", PARAM_IN>,
+ Param<"ol_platform_info_t", "PropName", "type of the info to retrieve", PARAM_IN>,
+ Param<"size_t", "PropSize", "the number of bytes pointed to by pPlatformInfo.", PARAM_IN>,
+ TypeTaggedParam<"void*", "PropValue", "array of bytes holding the info. "
+ "If Size is not equal to or greater to the real number of bytes needed to return the info "
+ "then the OL_ERRC_INVALID_SIZE error is returned and pPlatformInfo is not used.", PARAM_OUT,
+ TypeInfo<"PropName" , "PropSize">>
+ ];
+ let returns = [
+ Return<"OL_ERRC_UNSUPPORTED_ENUMERATION", [
+ "If `PropName` is not supported by the platform."
+ ]>,
+ Return<"OL_ERRC_INVALID_SIZE", [
+ "`PropSize == 0`",
+ "If `PropSize` is less than the real number of bytes needed to return the info."
+ ]>,
+ Return<"OL_ERRC_INVALID_PLATFORM">
+ ];
+}
+
+def : Function {
+ let name = "olGetPlatformInfoSize";
+ let desc = "Returns the storage size of the given platform query";
+ let details = [];
+ let params = [
+ Param<"ol_platform_handle_t", "Platform", "handle of the platform", PARAM_IN>,
+ Param<"ol_platform_info_t", "PropName", "type of the info to query", PARAM_IN>,
+ Param<"size_t*", "PropSizeRet", "pointer to the number of bytes required to store the query", PARAM_OUT>
+ ];
+ let returns = [
+ Return<"OL_ERRC_UNSUPPORTED_ENUMERATION", [
+ "If `PropName` is not supported by the platform."
+ ]>,
+ Return<"OL_ERRC_INVALID_PLATFORM">
+ ];
+}
diff --git a/offload/liboffload/API/README.md b/offload/liboffload/API/README.md
new file mode 100644
index 0000000..38a0558
--- /dev/null
+++ b/offload/liboffload/API/README.md
@@ -0,0 +1,150 @@
+# 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.
+
+The root file is `OffloadAPI.td` - additional `.td` files can be included in
+this file to add them to the API.
+
+## 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).
+
+#### 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.
+
+The *type* field is used to infer if the parameter is a pointer or handle type.
+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.
+
+#### 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.
+
+Returns are automatically generated for functions with pointer or handle
+parameters, so API authors do not need to exhaustively add null checks for
+these types of parameters. All functions also get a number of default return
+values automatically.
+
+
+### Struct
+Represents a struct. Contains a list of members, which each have a *type*,
+*name*, and *desc*.
+
+Also optionally takes a *base_class* field. If this is either of the special
+`offload_base_properties_t` or `offload_base_desc_t` structs, then the struct
+will inherit members from those structs. The generated struct does **not** use
+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 addtionally 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.
+
+Macro arguments are presented in the *name* field (e.g. name = `mymacro(arg)`).
+
+While there may seem little point generating a macro from tablegen, doing this
+allows the entire source of the header file to be generated from the tablegen
+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.
+
+### Entry Points
+```
+./offload-tblgen -I <path-to-llvm>/offload/API <path-to-llvm>/offload/API/OffloadAPI.td --gen-entry-points
+```
+These functions form the actual Offload interface, and are wrappers over the
+functions that contain the actual implementation (see
+'Adding a new entry point').
+
+They implement automatically generated validation checks, and tracing of
+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
+```
+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.
+
+As with the API header, it is expected that this header is part of the installed
+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.
+
+## 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 offload 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/offload_impl.cpp`