[mlir] Initial version of C APIs · llvm/llvm-project@75f239e (original) (raw)
``
1
`+
MLIR C API
`
``
2
+
``
3
`+
Current status: Under development, API unstable, built by default.
`
``
4
+
``
5
`+
Design
`
``
6
+
``
7
`+
Many languages can interoperate with C but have a harder time with C++ due to
`
``
8
`+
name mangling and memory model differences. Although the C API for MLIR can be
`
``
9
`+
used directly from C, it is primarily intended to be wrapped in higher-level
`
``
10
`+
language- or library-specific constructs. Therefore the API tends towards
`
``
11
`+
simplicity and feature minimalism.
`
``
12
+
``
13
`+
Note: while the C API is expected to be more stable than C++ API, it
`
``
14
`+
currently offers no stability guarantees.
`
``
15
+
``
16
`+
Scope
`
``
17
+
``
18
`+
The API is provided for core IR components (attributes, blocks, operations,
`
``
19
`+
regions, types, values), Passes and some fundamental type and attribute kinds.
`
``
20
`+
The core IR API is intentionally low-level, e.g. exposes a plain list of
`
``
21
`+
operation's operands and attributes without attempting to assign "semantic"
`
``
22
`+
names to them. Users of specific dialects are expected to wrap the core API in a
`
``
23
`+
dialect-specific way, for example, by implementing an ODS backend.
`
``
24
+
``
25
`+
Object Model
`
``
26
+
``
27
`+
Core IR components are exposed as opaque handles to an IR object existing in
`
``
28
`+
C++. They are not intended to be inspected by the API users (and, in many cases,
`
``
29
`+
cannot be meaningfully inspected). Instead the users are expected to pass
`
``
30
`+
handles to the appropriate manipulation functions.
`
``
31
+
``
32
`+
The handle may or may not own the underlying object.
`
``
33
+
``
34
`+
Naming Convention and Ownership Model
`
``
35
+
``
36
`` +
All objects are prefixed with Mlir
. They are typedefs and should be used
``
``
37
`` +
without struct
.
``
``
38
+
``
39
`` +
All functions are prefixed with mlir
.
``
``
40
+
``
41
`` +
Functions primarily operating on an instance of MlirX
are prefixed with
``
``
42
`` +
mlirX
. They take the instance being acted upon as their first argument (except
``
``
43
`` +
for creation functions). For example, mlirOperationGetNumOperands
inspects an
``
``
44
`` +
MlirOperation
, which it takes as its first operand.
``
``
45
+
``
46
`+
The 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
+
``
66
`+
If the code owns an object, it is responsible for destroying the object when it
`
``
67
`+
is no longer necessary. If an object that owns other objects is destroyed, any
`
``
68
`+
handles to those objects become invalid. Note that types and attributes are
`
``
69
`` +
owned by the MlirContext
in which they were created.
``
``
70
+
``
71
`+
Nullity
`
``
72
+
``
73
`+
A handle may refer to a null object. It is the responsibility of the caller to
`
``
74
`` +
check if an object is null by using MlirXIsNull(MlirX)
. API functions do not
``
``
75
`+
expect null objects as arguments unless explicitly stated otherwise. API
`
``
76
`+
functions may return null objects.
`
``
77
+
``
78
`+
Common Patterns
`
``
79
+
``
80
`+
The API adopts the following patterns for recurrent functionality in MLIR.
`
``
81
+
``
82
`+
Indexed Components
`
``
83
+
``
84
`+
An object has an indexed component if it has fields accessible using a
`
``
85
`+
zero-based contiguous integer index, typically arrays. For example, an
`
``
86
`` +
MlirBlock
has its arguments as a indexed component. An object may have several
``
``
87
`` +
such components. For example, an MlirOperation
has attributes, operands,
``
``
88
`+
regions, results and successors.
`
``
89
+
``
90
`+
For 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
+
``
95
`+
Note that the name of subobject in the function does not necessarily match the
`
``
96
`` +
type of the subobject. For example, mlirOperationGetOperand
returns a
``
``
97
`` +
MlirValue
.
``
``
98
+
``
99
`+
Iterable Components
`
``
100
+
``
101
`+
An object has an iterable component if it has iterators accessing its fields
`
``
102
`+
in some order other than integer indexing, typically linked lists. For example,
`
``
103
`` +
an MlirBlock
has an iterable list of operations it contains. An object may
``
``
104
`+
have several iterable components.
`
``
105
+
``
106
`+
For 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
+
``
114
`+
Note that the name of subobject in the function may or may not match its type.
`
``
115
+
``
116
`+
This approach enables one to iterate as follows.
`
``
117
+
``
118
```c++
``
119
`+
MlirY iter;
`
``
120
`+
for (iter = mlirXGetFirst(x); !mlirYIsNull(iter);
`
``
121
`+
iter = mlirYGetNextIn(iter)) {
`
``
122
`+
/* User 'iter'. */
`
``
123
`+
}
`
``
124
```