1# MLIR C API 2 3**Current status: Under development, API unstable, built by default.** 4 5## Design 6 7Many languages can interoperate with C but have a harder time with C++ due to 8name mangling and memory model differences. Although the C API for MLIR can be 9used directly from C, it is primarily intended to be wrapped in higher-level 10language- or library-specific constructs. Therefore the API tends towards 11simplicity and feature minimalism. 12 13**Note:** while the C API is expected to be more stable than C++ API, it 14currently offers no stability guarantees. 15 16### Scope 17 18The API is provided for core IR components (attributes, blocks, operations, 19regions, types, values), Passes and some fundamental type and attribute kinds. 20The core IR API is intentionally low-level, e.g. exposes a plain list of 21operation's operands and attributes without attempting to assign "semantic" 22names to them. Users of specific dialects are expected to wrap the core API in a 23dialect-specific way, for example, by implementing an ODS backend. 24 25### Object Model 26 27Core IR components are exposed as opaque _handles_ to an IR object existing in 28C++. They are not intended to be inspected by the API users (and, in many cases, 29cannot be meaningfully inspected). Instead the users are expected to pass 30handles to the appropriate manipulation functions. 31 32The handle _may or may not_ own the underlying object. 33 34### Naming Convention and Ownership Model 35 36All objects are prefixed with `Mlir`. They are typedefs and should be used 37without `struct`. 38 39All functions are prefixed with `mlir`. 40 41Functions primarily operating on an instance of `MlirX` are prefixed with 42`mlirX`. They take the instance being acted upon as their first argument (except 43for creation functions). For example, `mlirOperationGetNumOperands` inspects an 44`MlirOperation`, which it takes as its first operand. 45 46The *ownership* model is encoded in the naming convention as follows. 47 48- By default, the ownership is not transerred. 49- Functions that tranfer the ownership of the result to the caller can be in 50 one of two forms: 51 * functions that create a new object have the name `mlirXCreate<...>`, for 52 example, `mlirOperationCreate`; 53 * functions that detach an object from a parent object have the name 54 `mlirYTake<...>`, for example `mlirOperationStateTakeRegion`. 55- Functions that take ownership of some of their arguments have the form 56 `mlirY<...>OwnedX<...>` where `X` can refer to the type or any other 57 sufficiently unique description of the argument, the ownership of which will 58 be taken by the callee, for example `mlirRegionAppendOwnedBlock`. 59- Functions that create an object by default do not transfer its ownership to 60 the caller, i.e. one of other objects passed in as an argument retains the 61 ownership, they have the form `mlirX<...>Get`. For example, 62 `mlirTypeParseGet`. 63- Functions that destroy an object owned by the caller are of the form 64 `mlirXDestroy`. 65 66If the code owns an object, it is responsible for destroying the object when it 67is no longer necessary. If an object that owns other objects is destroyed, any 68handles to those objects become invalid. Note that types and attributes are 69owned by the `MlirContext` in which they were created. 70 71### Nullity 72 73A handle may refer to a _null_ object. It is the responsibility of the caller to 74check if an object is null by using `MlirXIsNull(MlirX)`. API functions do _not_ 75expect null objects as arguments unless explicitly stated otherwise. API 76functions _may_ return null objects. 77 78### Common Patterns 79 80The API adopts the following patterns for recurrent functionality in MLIR. 81 82#### Indexed Components 83 84An object has an _indexed component_ if it has fields accessible using a 85zero-based contiguous integer index, typically arrays. For example, an 86`MlirBlock` has its arguments as a indexed component. An object may have several 87such components. For example, an `MlirOperation` has attributes, operands, 88regions, results and successors. 89 90For indexed components, the following pair of functions is provided. 91 92- `unsigned mlirXGetNum<Y>s(MlirX)` returns the upper bound on the index. 93- `MlirY mlirXGet<Y>(MlirX, unsigned pos)` returns 'pos'-th subobject. 94 95Note that the name of subobject in the function does not necessarily match the 96type of the subobject. For example, `mlirOperationGetOperand` returns a 97`MlirValue`. 98 99#### Iterable Components 100 101An object has an _iterable component_ if it has iterators accessing its fields 102in some order other than integer indexing, typically linked lists. For example, 103an `MlirBlock` has an iterable list of operations it contains. An object may 104have several iterable components. 105 106For iterable components, the following triple of functions is provided. 107 108- `MlirY mlirXGetFirst<Y>(MlirX)` returns the first subobject in the list. 109- `MlirY mlirYGetNextIn<X>(MlirY)` returns the next subobject in the list that 110 contains the given object, or a null object if the given object is the last 111 in this list. 112- `int mlirYIsNull(MlirY)` returns 1 if the given object is null. 113 114Note that the name of subobject in the function may or may not match its type. 115 116This approach enables one to iterate as follows. 117 118```c++ 119MlirY iter; 120for (iter = mlirXGetFirst<Y>(x); !mlirYIsNull(iter); 121 iter = mlirYGetNextIn<X>(iter)) { 122 /* User 'iter'. */ 123} 124``` 125