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 only 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
41add_mlir_dialect(FooOps foo)
42add_mlir_doc(FooOps -gen-dialect-doc FooDialect Dialects/)
43```
44
45This generates the correct rules to run mlir-tblgen, along with a
46'MLIRFooOpsIncGen' target which can be used to declare dependencies.
47
48Dialect transformations are typically declared in a file FooTransforms.td.
49Targets for TableGen are described in typical llvm fashion.
50
51```cmake
52set(LLVM_TARGET_DEFINITIONS FooTransforms.td)
53mlir_tablegen(FooTransforms.h.inc -gen-rewriters)
54add_public_tablegen_target(MLIRFooTransformIncGen)
55```
56
57The result is another 'IncGen' target, which runs mlir-tblgen.
58
59### Library Targets
60
61Dialects may have multiple libraries.  Each library is typically
62declared with add_mlir_dialect_library().  Dialect libraries often
63depend on the generation of header files from TableGen (specified
64using the DEPENDS keyword).  Dialect libraries may also depend on
65other dialect libraries.  Typically this dependence is declared using
66target_link_libraries() and the PUBLIC keyword.  For instance:
67
68```cmake
69add_mlir_dialect_library(MLIRFoo
70  DEPENDS
71  MLIRFooOpsIncGen
72  MLIRFooTransformsIncGen
73
74  LINK_COMPONENTS
75  Core
76
77  LINK_LIBS PUBLIC
78  MLIRBar
79  <some-other-library>
80  )
81```
82
83add_mlir_dialect_library() is a thin wrapper around add_llvm_library()
84which collects a list of all the dialect libraries.  This list is
85often useful for linking tools (e.g. mlir-opt) which should have
86access to all dialects.  This list is also linked into libMLIR.so.
87The list can be retrieved from the MLIR_DIALECT_LIBS global property:
88
89```cmake
90get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
91```
92
93Note that although the Bar dialect also uses TableGen to declare its
94operations, it is not necessary to explicitly depend on the
95corresponding IncGen targets.  The PUBLIC link dependency is
96sufficient.  Also note that we avoid using add_dependencies
97explicitly, since the dependencies need to be available to the
98underlying add_llvm_library() call, allowing it to correctly create
99new targets with the same sources.  However, dialects that depend on
100LLVM IR may need to depend on the LLVM 'intrinsics_gen' target to
101ensure that tablegen'd LLVM header files have been generated.
102
103In addition, linkage to MLIR libraries is specified using the
104LINK_LIBS descriptor and linkage to LLVM libraries is specified using
105the LINK_COMPONENTS descriptor.  This allows cmake infrastructure to
106generate new library targets with correct linkage, in particular, when
107BUILD_SHARED_LIBS=on or LLVM_LINK_LLVM_DYLIB=on are specified.
108
109
110# Dialect Conversions
111
112Conversions from “X” to “Y” live in mlir/include/mlir/Conversion/XToY,
113mlir/lib/Conversion/XToY and mlir/test/Conversion/XToY, respectively.
114
115Default file names for conversion should omit “Convert” from their
116name, e.g. lib/VectorToLLVM/VectorToLLVM.cpp.
117
118Conversion passes should live separately from conversions themselves
119for convenience of users that only care about a pass and not about its
120implementation with patterns or other infrastructure. For example
121include/mlir/VectorToLLVM/VectorToLLVMPass.h.
122
123Common conversion functionality from or to dialect “X” that does not
124belong to the dialect definition can be located in
125mlir/lib/Conversion/XCommon, for example
126mlir/lib/Conversion/GPUCommon.
127
128## CMake best practices
129
130Each conversion typically exists in a separate library, declared with
131add_mlir_conversion_library().  Conversion libraries typically depend
132on their source and target dialects, but may also depend on other
133dialects (e.g. MLIRStandard).  Typically this dependence is specified
134using target_link_libraries() and the PUBLIC keyword.  For instance:
135
136```cmake
137add_mlir_conversion_library(MLIRBarToFoo
138  BarToFoo.cpp
139
140  ADDITIONAL_HEADER_DIRS
141  ${MLIR_MAIN_INCLUDE_DIR}/mlir/Conversion/BarToFoo
142
143  LINK_LIBS PUBLIC
144  MLIRBar
145  MLIRFoo
146  )
147```
148
149add_mlir_conversion_library() is a thin wrapper around
150add_llvm_library() which collects a list of all the conversion
151libraries.  This list is often useful for linking tools
152(e.g. mlir-opt) which should have access to all dialects.  This list
153is also linked in libMLIR.so.  The list can be retrieved from the
154MLIR_CONVERSION_LIBS global property:
155
156```cmake
157get_property(dialect_libs GLOBAL PROPERTY MLIR_CONVERSION_LIBS)
158```
159
160Note that it is only necessary to specify a PUBLIC dependence against
161dialects to generate compile-time and link-time dependencies, and it
162is not necessary to explicitly depend on the dialects' IncGen targets.
163However, conversions that directly include LLVM IR header files may
164need to depend on the LLVM 'intrinsics_gen' target to ensure that
165tablegen'd LLVM header files have been generated.
166