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