| # Lowering IREEPyDM to IREE |
| |
| At the top-level, a program expressed in IREEPyDM ("PyDM") can be lowered to |
| IREE via the overall conversion pass `-convert-iree-pydm-to-iree`; however, |
| additional steps are needed to link a runtime library, etc. |
| |
| This document provides application notes for how the conversion is |
| implemented. |
| |
| ## Type Conversion |
| |
| Generally, types in PyDM map 1:1 with IREE types in a way which facilitates |
| a direct conversion. |
| |
| ## `object` and `object<type>` records |
| |
| Objects map to IREE variant lists (`!iree.list<?>`) of N elements, where the |
| elements are laid out as: |
| |
| * [0]: Type Code - i32 representing the type code of the object. |
| * [1] (optional): Data corresponding to the type. |
| * [2] (optional): i64 TypeID - if the `id()` function has been evaluated for |
| this object, then this element will contain the unique id. |
| |
| ### Type Codes |
| |
| The special type code `0` means "not assigned", which is distinct from `None`. |
| Other built-in types correspond to the `BuiltinTypeCode` enum in the dialect. |
| |
| The following specifies the contents of the `data` field (1) of the object |
| record, per type code: |
| |
| * `None`: No contents |
| * `Tuple`: An `!iree.list` of objects |
| * `List`: An `!iree.list` of objects |
| * `Str`: TODO: needs to be a union of i8/i16/i32 codepoint array |
| * `Bytes`: TODO: should be a memory buffer of some kind |
| * `ExceptionResult`: TODO: should hold a boxed exception of some kind |
| * `Type`: An object representing the type |
| * `Bool`: Implementation defined `iree_vm_value_type_t` field (typically |
| `iree_vm_value_type_t.i8`). |
| * `Integer`: Implementation defined `iree_vm_value_type_t` field (typically |
| `iree_vm_value_type_t.i32`). |
| * `Real`: Implementation defined `iree_vm_value_type_t` field (typically |
| `iree_vm_value_type_t.f32`). |
| * `Complex`: TODO |
| * `Integer1` / `UInteger1`: `iree_vm_value_type_t.i8` |
| * `Integer2` / `UInteger2`: `iree_vm_value_type_t.i16` |
| * `Integer4` / `UInteger4`: `iree_vm_value_type_t.i32 |
| * `Integer8` / `UInteger8`: `iree_vm_value_type_t.i64 |
| * `Float2` : `iree_vm_value_type_t.i16` with bit value of an IEEE FP16 |
| * `Float4` : `iree_vm_value_type_t.f32` |
| * `Float8` : `iree_vm_value_type_t.f64` |
| * `BFloat2` : `iree_vm_value_type_t.i16` with bit value of a BFloat16 (thanks |
| Google). |
| * `Complex4` : TODO |
| * `Complex8` : TODO |
| * `Object` (and custom): An object record, as described here |
| |
| ### Mutability |
| |
| The VM enforces no immutability constraints on the object records here (i.e. |
| they are just lists). If the compiler believes that it can recycle an object, |
| it is free to resize it appropriately and re-assign its contents. In this |
| way, things like closure cells and free variable cells can just be |
| allocated object records that that compiler completely reassigns the contents |
| of on assignment. |
| |
| ## Unboxed values |
| |
| All values can exist in the program unboxed and will have a VM IR type which |
| corresponds to their runtime variant form (i.e. `!iree.list`, `i32`, etc). |
| |
| ## `!iree_pydm.exception_result` |
| |
| The `exception_result` type is returned from every PyDM function indicating |
| whether the call completed successfully or in an error state. We encode it as |
| a signed `i32` value at runtime, where: |
| |
| * `0` : indicates normal termination. |
| * `<0` : signals one of a predefined list of primitive exception types |
| which do not contain any detail (i.e. `ValueException` analog). |
| * `>0` : is an index into a global exception lookup table with slots |
| corresponding to logical threads of execution. |
| |
| ### Pre-defined exception codes: |
| |
| * `-1` : `StopIteration` - Standard exception which indicates exhaustion of |
| an iterator. |
| * `-2` : `StopAsyncIteration` - Standard exception which indicates exhaustion |
| of an async iterator. |
| * `-3` : `RuntimeError` - general catch-all failure exception class. |
| * `-4` : `ValueError` |
| * `-5` : `NotImplementedError` |
| * `-6` : `KeyError` |
| * `-7` : `IndexError` |
| * `-8` : `AttributeError` |
| * `-9` : `TypeError` |
| * `-10` : `UnboundLocalError` |
| |
| These pre-defined exception codes are allocated when the compiler has a need |
| to raise or interoperate with an exception category. |