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