[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

`+

`

``

49

`+

`

``

50

`+

one of two forms:

`

``

51

`` +

``

``

52

`` +

example, mlirOperationCreate;

``

``

53

`+

`

``

54

`` +

mlirYTake<...>, for example mlirOperationStateTakeRegion.

``

``

55

`+

`

``

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

`+

`

``

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

`+

`

``

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

`` +

``

``

93

`` +

``

``

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

`` +

``

``

109

`` +

``

``

110

`+

contains the given object, or a null object if the given object is the last

`

``

111

`+

in this list.

`

``

112

`` +

``

``

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


```