# Creating a Dialect
[TOC]
Public dialects are typically separated into at least 3 directories:
* mlir/include/mlir/Dialect/Foo (for public include files)
* mlir/lib/Dialect/Foo (for sources)
* mlir/lib/Dialect/Foo/IR (for operations)
* mlir/lib/Dialect/Foo/Transforms (for transforms)
* mlir/test/Dialect/Foo (for tests)
Along with other public headers, the 'include' directory contains a
TableGen file in the [ODS format](../DefiningDialects/Operations.md), describing the
operations in the dialect. This is used to generate operation
declarations (FooOps.h.inc) and definitions (FooOps.cpp.inc) and
operation interface declarations (FooOpsInterfaces.h.inc) and
definitions (FooOpsInterfaces.cpp.inc).
The 'IR' directory typically contains implementations of functions for
the dialect which are not automatically generated by ODS. These are
typically defined in FooDialect.cpp, which includes FooOps.cpp.inc and
FooOpsInterfaces.h.inc.
The 'Transforms' directory contains rewrite rules for the dialect,
typically described in TableGen file using the [DDR
format](../DeclarativeRewrites.md).
Note that dialect names should not generally be suffixed with “Ops”,
although some files pertaining only to the operations of a dialect (e.g.
FooOps.cpp) might be.
## CMake best practices
### TableGen Targets
Operations in dialects are typically declared using the ODS format in
tablegen in a file FooOps.td. This file forms the core of a dialect and
is declared using add_mlir_dialect().
```cmake
add_mlir_dialect(FooOps foo)
add_mlir_doc(FooOps FooDialect Dialects/ -gen-dialect-doc)
```
This generates the correct rules to run mlir-tblgen, along with a
'MLIRFooOpsIncGen' target which can be used to declare dependencies.
Dialect transformations are typically declared in a file FooTransforms.td.
Targets for TableGen are described in typical llvm fashion.
```cmake
set(LLVM_TARGET_DEFINITIONS FooTransforms.td)
mlir_tablegen(FooTransforms.h.inc -gen-rewriters)
add_public_tablegen_target(MLIRFooTransformIncGen)
```
The result is another 'IncGen' target, which runs mlir-tblgen.
### Library Targets
Dialects may have multiple libraries. Each library is typically
declared with add_mlir_dialect_library(). Dialect libraries often
depend on the generation of header files from TableGen (specified
using the DEPENDS keyword). Dialect libraries may also depend on
other dialect libraries. Typically this dependence is declared using
target_link_libraries() and the PUBLIC keyword. For instance:
```cmake
add_mlir_dialect_library(MLIRFoo
DEPENDS
MLIRFooOpsIncGen
MLIRFooTransformsIncGen
LINK_COMPONENTS
Core
LINK_LIBS PUBLIC
MLIRBar
<some-other-library>
)
```
add_mlir_dialect_library() is a thin wrapper around add_llvm_library()
which collects a list of all the dialect libraries. This list is
often useful for linking tools (e.g. mlir-opt) which should have
access to all dialects. This list is also linked into libMLIR.so.
The list can be retrieved from the MLIR_DIALECT_LIBS global property:
```cmake
get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
```
Note that although the Bar dialect also uses TableGen to declare its
operations, it is not necessary to explicitly depend on the
corresponding IncGen targets. The PUBLIC link dependency is
sufficient. Also note that we avoid using add_dependencies
explicitly, since the dependencies need to be available to the
underlying add_llvm_library() call, allowing it to correctly create
new targets with the same sources. However, dialects that depend on
LLVM IR may need to depend on the LLVM 'intrinsics_gen' target to
ensure that tablegen'd LLVM header files have been generated.
In addition, linkage to MLIR libraries is specified using the
LINK_LIBS descriptor and linkage to LLVM libraries is specified using
the LINK_COMPONENTS descriptor. This allows cmake infrastructure to
generate new library targets with correct linkage, in particular, when
BUILD_SHARED_LIBS=on or LLVM_LINK_LLVM_DYLIB=on are specified.
# Dialect Conversions
Conversions from “X” to “Y” live in mlir/include/mlir/Conversion/XToY,
mlir/lib/Conversion/XToY and mlir/test/Conversion/XToY, respectively.
Default file names for conversion should omit “Convert” from their
name, e.g. lib/VectorToLLVM/VectorToLLVM.cpp.
Conversion passes should live separately from conversions themselves
for convenience of users that only care about a pass and not about its
implementation with patterns or other infrastructure. For example
include/mlir/VectorToLLVM/VectorToLLVMPass.h.
Common conversion functionality from or to dialect “X” that does not
belong to the dialect definition can be located in
mlir/lib/Conversion/XCommon, for example
mlir/lib/Conversion/GPUCommon.
## CMake best practices
Each conversion typically exists in a separate library, declared with
add_mlir_conversion_library(). Conversion libraries typically depend
on their source and target dialects, but may also depend on other
dialects (e.g. MLIRFunc). Typically this dependence is specified
using target_link_libraries() and the PUBLIC keyword. For instance:
```cmake
add_mlir_conversion_library(MLIRBarToFoo
BarToFoo.cpp
ADDITIONAL_HEADER_DIRS
${MLIR_MAIN_INCLUDE_DIR}/mlir/Conversion/BarToFoo
LINK_LIBS PUBLIC
MLIRBar
MLIRFoo
)
```
add_mlir_conversion_library() is a thin wrapper around
add_llvm_library() which collects a list of all the conversion
libraries. This list is often useful for linking tools
(e.g. mlir-opt) which should have access to all dialects. This list
is also linked in libMLIR.so. The list can be retrieved from the
MLIR_CONVERSION_LIBS global property:
```cmake
get_property(dialect_libs GLOBAL PROPERTY MLIR_CONVERSION_LIBS)
```
Note that it is only necessary to specify a PUBLIC dependence against
dialects to generate compile-time and link-time dependencies, and it
is not necessary to explicitly depend on the dialects' IncGen targets.
However, conversions that directly include LLVM IR header files may
need to depend on the LLVM 'intrinsics_gen' target to ensure that
tablegen'd LLVM header files have been generated.