1# Creating a Dialect
2
3[TOC]
4
5Public dialects are typically separated into at least 3 directories:
6* mlir/include/mlir/Dialect/Foo   (for public include files)
7* mlir/lib/Dialect/Foo            (for sources)
8* mlir/lib/Dialect/Foo/IR         (for operations)
9* mlir/lib/Dialect/Foo/Transforms (for transforms)
10* mlir/test/Dialect/Foo           (for tests)
11
12Along with other public headers, the 'include' directory contains a
13TableGen file in the [ODS format](OpDefinitions.md), describing the
14operations in the dialect.  This is used to generate operation
15declarations (FooOps.h.inc) and definitions (FooOps.cpp.inc) and
16operation interface declarations (FooOpsInterfaces.h.inc) and
17definitions (FooOpsInterfaces.cpp.inc).
18
19The 'IR' directory typically contains implementations of functions for
20the dialect which are not automatically generated by ODS.  These are
21typically defined in FooDialect.cpp, which includes FooOps.cpp.inc and
22FooOpsInterfaces.h.inc.
23
24The 'Transforms' directory contains rewrite rules for the dialect,
25typically described in TableGen file using the [DDR
26format](DeclarativeRewrites.md).
27
28Note that dialect names should not generally be suffixed with “Ops”,
29although some files pertaining to the operations of a dialect (e.g.
30FooOps.cpp) might be.
31
32## CMake best practices
33
34### TableGen Targets
35
36Operations in dialects are typically declared using the ODS format in
37tablegen in a file FooOps.td.  This file forms the core of a dialect and
38is declared using add_mlir_dialect().
39
40```cmake
41
42add_mlir_dialect(FooOps foo)
43add_mlir_doc(FooOps -gen-dialect-doc FooDialect Dialects/)
44
45```
46
47This generates the correct rules to run mlir-tblgen, along with a
48'MLIRFooOpsIncGen' target which can be used to declare dependencies.
49
50Dialect transformations are typically declared in a file FooTransforms.td.
51Targets for TableGen are described in typical llvm fashion.
52```cmake
53set(LLVM_TARGET_DEFINITIONS FooTransforms.td)
54mlir_tablegen(FooTransforms.h.inc -gen-rewriters)
55add_public_tablegen_target(MLIRFooTransformIncGen)
56```
57
58The result is another 'IncGen' target, which runs mlir-tblgen.
59
60### Library Targets
61
62Dialects may have multiple libraries.  Each library is typically
63declared with add_mlir_dialect_library().  Dialect libraries often
64depend on the generation of header files from TableGen (specified
65using the DEPENDS keyword).  Dialect libraries may also depend on
66other dialect libraries.  Typically this dependence is declared using
67target_link_libraries() and the PUBLIC keyword.  For instance:
68
69```cmake
70
71add_mlir_dialect_library(FooOps
72	DEPENDS
73	MLIRFooOpsIncGen
74	MLIRFooTransformsIncGen
75
76	LINK_COMPONENTS
77	Core
78
79	LINK_LIBS PUBLIC
80	BarOps
81	<some-other-library>
82   )
83
84```
85
86add_mlir_dialect_library() is a thin wrapper around add_llvm_library()
87which collects a list of all the dialect libraries.  This list is
88often useful for linking tools (e.g. mlir-opt) which should have
89access to all dialects.  This list is also linked into libMLIR.so.
90The list can be retrieved from the MLIR_DIALECT_LIBS global property:
91
92```cmake
93
94get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
95
96```
97
98Note that although the Bar dialect also uses TableGen to declare its
99operations, it is not necessary to explicitly depend on the
100corresponding IncGen targets.  The PUBLIC link dependency is
101sufficient.  Also note that we avoid using add_dependencies
102explicitly, since the dependencies need to be available to the
103underlying add_llvm_library() call, allowing it to correctly create
104new targets with the same sources.  However, dialects that depend on
105LLVM IR may need to depend on the LLVM 'intrinsics_gen' target to
106ensure that tablegen'd LLVM header files have been generated.
107
108In addition, linkage to MLIR libraries is specified using the
109LINK_LIBS descriptor and linkage to LLVM libraries is specified using
110the LINK_COMPONENTS descriptor.  This allows cmake infrastructure to
111generate new library targets with correct linkage, in particular, when
112BUILD_SHARED_LIBS=on or LLVM_LINK_LLVM_DYLIB=on are specified.
113
114
115# Dialect Conversions
116
117Conversions from “X” to “Y” live in mlir/include/mlir/Conversion/XToY,
118mlir/lib/Conversion/XToY and mlir/test/Conversion/XToY, respectively.
119
120Default file names for conversion should omit “Convert” from their
121name, e.g. lib/VectorToLLVM/VectorToLLVM.cpp.
122
123Conversion passes should live separately from conversions themselves
124for convenience of users that only care about a pass and not about its
125implementation with patterns or other infrastructure. For example
126include/mlir/VectorToLLVM/VectorToLLVMPass.h.
127
128Common conversion functionality from or to dialect “X” that does not
129belong to the dialect definition can be located in
130mlir/lib/Conversion/XCommon, for example
131mlir/lib/Conversion/GPUCommon.
132
133## CMake best practices
134
135Each conversion typically exists in a separate library, declared with
136add_mlir_conversion_library().  Conversion libraries typically depend
137on their source and target dialects, but may also depend on other
138dialects (e.g. MLIRStandard).  Typically this dependence is specified
139using target_link_libraries() and the PUBLIC keyword.  For instance:
140
141```cmake
142
143add_mlir_conversion_library(MLIRBarToFoo
144	BarToFoo.cpp
145
146        ADDITIONAL_HEADER_DIRS
147        ${MLIR_MAIN_INCLUDE_DIR}/mlir/Conversion/BarToFoo
148
149   LINK_LIBS PUBLIC
150	BarOps
151	FooOps
152	)
153
154```
155
156add_mlir_conversion_library() is a thin wrapper around
157add_llvm_library() which collects a list of all the conversion
158libraries.  This list is often useful for linking tools
159(e.g. mlir-opt) which should have access to all dialects.  This list
160is also linked in libMLIR.so.  The list can be retrieved from the
161MLIR_CONVERSION_LIBS global property:
162
163```cmake
164
165get_property(dialect_libs GLOBAL PROPERTY MLIR_CONVERSION_LIBS)
166
167```
168
169Note that it is only necessary to specify a PUBLIC dependence against
170dialects to generate compile-time and link-time dependencies, and it
171is not necessary to explicitly depend on the dialects' IncGen targets.
172However, conversions that directly include LLVM IR header files may
173need to depend on the LLVM 'intrinsics_gen' target to ensure that
174tablegen'd LLVM header files have been generated.
175