| # Function Signatures | |
| A key job of the IREE compiler and runtime is capturing function call semantics | |
| from the originating system and providing mechanisms so that invocations can be | |
| performed in as similar way as possible in various target languages. In general, | |
| this requires additional metadata on top of the raw characteristics of a | |
| function. Where possible, this is done by attaching attributes to a function. | |
| - `iree.abi` : JSON encoded description of the function's calling convention. | |
| ## V1 ABI | |
| This is the default ABI supported by the IREE VM invocations. It attempts to | |
| provide a default calling convention that can be used without further reflection | |
| metadata but which may be enhanced with it. | |
| It natively allows monomorphic functions to be exported where arguments and | |
| results are composed of the following types: | |
| ### Value Types: | |
| - Byte aligned integer type (i8, i16, i32, i64) | |
| - Floating point value (f16, f32, f64) | |
| ### Reference Types: | |
| - ND-Array buffers of Value Types: | |
| - Simple: Packed, C-layout | |
| - Strided: Arbitrary layout with strides (future) | |
| - String (byte arrays) | |
| - Opaque reference object | |
| ### Sequence Types: | |
| - Tuples: fixed length lists where each position has its own type bound | |
| - Homogenous list: lists of arbitrary size where a single type bound applies | |
| to all elements | |
| The intent with these low level types is that calling conventions can be | |
| synthesized to bind arbitrary high level, domain/language specific signatures to | |
| these types, possibly by way of additional reflection metadata. | |
| ### Representations: | |
| The above are all representable with native constructs in the VM: | |
| - ValueType: | |
| - Runtime: | |
| [`iree_vm_value`](https://github.com/openxla/iree/blob/main/iree/vm/value.h) | |
| - Compile Time: primitive MLIR integer/floating point types | |
| - Simple ND-Array Buffer: | |
| - Runtime: | |
| [`iree_hal_buffer_view`](https://github.com/openxla/iree/blob/main/iree/hal/buffer_view.h) | |
| - Compile Time: `tensor<>` | |
| - String: | |
| - Runtime: | |
| [`iree_vm_list`](https://github.com/openxla/iree/blob/main/iree/vm/list.h) | |
| containing `i8` | |
| - Compile Time: `!util.list<i8>` | |
| - Tuple: | |
| - Runtime: | |
| [`iree_vm_list`](https://github.com/openxla/iree/blob/main/iree/vm/list.h) | |
| of variant | |
| - Compile Time: `!util.list<?>` | |
| - Note that these are statically type erased at the boundary. | |
| - TypedList (homogenous): | |
| - Runtime: | |
| [`iree_vm_list`](https://github.com/openxla/iree/blob/main/iree/vm/list.h) | |
| of `T` | |
| - Compile Time: `!util.list<T>` | |
| ### Extended Type Calling Conventions | |
| While the above features of the native ABI may be sufficient for direct use by | |
| various programs, many programs and callers will need to represent various | |
| higher level types, consistently mapping them to the above facilities. This | |
| section describes calling conventions for various higher level types which do | |
| not map 1:1 to the above. Not all source language types are representable, and | |
| extending these calling conventions (and the fundamental types above) is demand | |
| driven. | |
| All of these calling conventions presume that the arity of the arguments/results | |
| of the raw function matches the user-level function, meaning that the calling | |
| convention is specified per argument/result. Higher-level whole function | |
| transformations may also exist for some domains but are outside of the scope of | |
| this specification. | |
| #### Structure | |
| A `Structure` is a common enough entity to have a dedicated calling convention. | |
| In C-like languages, this may just be a `struct`. In Python, it is typically a | |
| `dict` with an associated schema providing a name and type bound for each of its | |
| slots. In both, its slots are of fixed arity. | |
| In this convention, such a structure is represented as a `Tuple` in the native | |
| calling convention (i.e. `!util.list` of variant type). The order of the | |
| elements of the tuple are the natural order of the structure, where that is | |
| either: | |
| - For a C-like system where order is determinate, it is the order of | |
| declaration. | |
| - For a name-based system (i.e. bind to `dict`) where no order is defined, the | |
| natural order will be the lexically sorted order of the keys. | |
| #### String | |
| Most languages interop between byte arrays (i.e. the native ABI `String` type) | |
| by way of applying an encoding. Such strings are just a sequence of bytes (i.e. | |
| `!util.list<i8>`). | |
| #### Typed List | |
| High level lists which all share the same type bound are represented as a | |
| `TypedList` in the native ABI. | |
| #### NDArray of Reference Types | |
| NDArrays of reference types are considered separately from those of value types. | |
| Internally, the code generated for them is completely different from what gets | |
| generated for numeric based arrays (i.e. has ref-counting, ownership semantics, | |
| non-POD, etc). These types are permitted for completeness, not necessarily | |
| performance: by nature they are already indirected and have overheads. | |
| In the native ABI, these are represented as a composite tuple type (i.e. today a | |
| list since sugar for tuple is not yet defined): `!iree.tuple<!util.list<T>, | |
| !util.list<index>>`. The first element of the tuple is the list of values, | |
| packed with a C-Layout and the second element is the list of dimension sizes. | |
| #### Reflection | |
| Additional reflection metadata may be encoded in a custom JSON form, providing | |
| additional typing hints for arguments and results. If present, this will be a | |
| reflection attribute with key `d`, containing a serialized JSON object. | |
| The JSON object contains: | |
| - `a` (array): List of type records for each argument. | |
| - `r` (array): List of type records for each argument. | |
| Type records are one of: | |
| - A string naming a primitive type: | |
| - `i[0-9]+`: Integer type with given bit width | |
| - `f[0-9]+`: IEEE floating point type with given bit width | |
| - `bf16`: BFloat16 | |
| - JSON `null`: A null reference value | |
| - `"unknown"`: An unknown/unmapped type | |
| - An array, interpreted as a tuple describing a compound type. | |
| ##### Compound type tuples | |
| A compound type tuple has a type identifier as its first element, followed with | |
| type specific fields: | |
| - `["named", "key", {slot_type}]`: Associates a name with a slot. This is | |
| used with the root argument list to denote named arguments that can be | |
| passed positionally or by keyword. | |
| - `["ndarray", {element_type}, {rank}, {dim...}]`: For unknown rank, the | |
| `rank` will be `null` and there will be no dims. Any unknown dim will be | |
| `null`. | |
| - `["slist", {slot_type...}]`: An anonymous structured list of fixed arity and | |
| slot specific types. If there are gaps in the list, empty slots will have a | |
| `null` type. | |
| - `["stuple", {slot_type...}]`: Same as `slist` but some languages | |
| differentiate between sequences represented as lists and those represented | |
| as tuples (read-only lists). | |
| - `["sdict", ["key", {slot_type}]...]`: An anonymous structure with named | |
| slots. Note that when passing these types, the keys are not passed to the | |
| function (only the slot values). | |
| - `["py_homogeneous_list", {element_type}]`: A Python list of unknown size | |
| with elements sharing a common type bound given by `element_type`. |