| # 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 [DRR | |
| 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. |