Home / Alt manpages / mlir-tblgen-20(1)

  • mlir-tblgen-20(1)
  • User command
  • linux

Generate MLIR C++ from TableGen with mlir-tblgen

You will finish with a repeatable command for turning an MLIR TableGen source file into generated C++, checking the result without overwriting useful files, and separating a bad include path from a bad generator choice. The examples target LLVM 20.1 and the mlir-tblgen-20 command name.

Allow 15 to 30 minutes if the MLIR build tree already exists. You need an MLIR source or build tree containing the dialect definitions, a shell, and an mlir-tblgen executable built for that tree. The Debian llvm-20 package installed on this host is version 20.1.8 and installs the manpage, but it does not include an mlir-tblgen-20 binary. That check is worth doing before debugging a command that cannot start.

1. Check the executable before writing anything

First inspect the command you will use. This is an ordinary, read-only check and does not need elevated privileges:

$ command -v mlir-tblgen-20 || command -v mlir-tblgen
$ mlir-tblgen-20 --version
Ubuntu LLVM version 20.1.8

On a source or CMake build, the binary is commonly under the build tree's bin directory rather than on PATH. Use its full path if necessary:

$ /path/to/llvm-project/build/bin/mlir-tblgen --version

Do not substitute llvm-tblgen-20 for an MLIR generator. They share the TableGen front end, but MLIR backends such as --gen-op-decls belong to the MLIR tool.

Checkpoint

Continue only when command -v or the full path identifies the executable that will process your MLIR definitions. If the check fails, install or build the MLIR tools through your normal LLVM workflow. sudo is not a fix for a missing binary in a build tree.

2. Inspect the available MLIR generators

The installed manpage defines the command as a translator for compiler-related .td files and defers the option list to the common TableGen documentation. Ask the executable itself for the list, because backends can vary with the build:

$ mlir-tblgen-20 --help | less
$ mlir-tblgen-20 --help | grep -E 'gen-op|gen-dialect|gen-rewriters|gen-attr'

For a normal MLIR operation definition, the useful first choices are usually --gen-op-decls for declarations and --gen-op-defs for definitions. Dialect documentation and rewrite rules use different backends. Treat the help output from your installed executable as authoritative rather than copying a backend name from an unrelated MLIR checkout.

3. Locate the matching include tree

MLIR .td files commonly include definitions from the MLIR source tree, such as mlir/IR/OpBase.td. Pass an include directory that contains the top-level mlir directory:

$ test -f /path/to/llvm-project/mlir/include/mlir/IR/OpBase.td && echo include-tree-ok
include-tree-ok

If your file includes generated TableGen files from a build, add the build include directory as well. Keep paths explicit so a command cannot silently use headers from a different checkout:

$ MLIR_SRC=/path/to/llvm-project
$ MLIR_BUILD=/path/to/llvm-project/build
$ test -f "$MLIR_SRC/mlir/include/mlir/IR/OpBase.td"
$ test -d "$MLIR_BUILD/include"
$ echo "source and build include roots found"

These assignments change only the current shell. They do not alter system configuration and need no elevated privileges.

4. Generate operation declarations to a new file

Use the declaration backend and send output to a new destination. Replace the three uppercase placeholders with paths from your checkout:

$ mlir-tblgen-20 \
    --gen-op-decls \
    -I "$MLIR_SRC/mlir/include" \
    -I "$MLIR_BUILD/include" \
    /path/to/MyDialectOps.td \
    -o /path/to/MyDialectOps.h.inc

The filename argument is the .td input. -I adds an include search directory, and -o selects the output file. A successful run may print nothing. Check the exit status and the generated file:

$ printf 'exit status: %s\n' "$?"
exit status: 0
$ test -s /path/to/MyDialectOps.h.inc && echo generated
generated

The generated file is normally included by C++ source rather than compiled as a standalone translation unit. Keep it in the build or generated-source area selected by the project's build system.

5. Generate definitions or inspect output on standard output

Use the definitions backend separately when the build expects method bodies or other generated definitions:

$ mlir-tblgen-20 \
    --gen-op-defs \
    -I "$MLIR_SRC/mlir/include" \
    -I "$MLIR_BUILD/include" \
    /path/to/MyDialectOps.td \
    -o /path/to/MyDialectOps.cpp.inc

For a quick inspection, write to standard output instead of creating a file:

$ mlir-tblgen-20 --gen-op-decls \
    -I "$MLIR_SRC/mlir/include" \
    /path/to/MyDialectOps.td -o - | sed -n '1,80p'

Do not redirect exploratory output over a checked-in generated file. Shell redirection with > truncates its destination before the program has succeeded. If you need an atomic replacement, generate a temporary file beside the destination, inspect it, then replace the old file only after the command and checks pass:

$ tmp=/path/to/MyDialectOps.h.inc.new
$ mlir-tblgen-20 --gen-op-decls \
    -I "$MLIR_SRC/mlir/include" -I "$MLIR_BUILD/include" \
    /path/to/MyDialectOps.td -o "$tmp" && test -s "$tmp"
$ mv "$tmp" /path/to/MyDialectOps.h.inc

The final mv changes state and replaces the previous file. Keep a backup if that file is hand-maintained or tracked outside version control. If generation fails, remove only the .new file after checking that it is the temporary path you intended; the old output remains in place.

6. Diagnose the failures that waste the most time

A "no such file" error for an included .td file usually means an include root is wrong. The path after -I must be the directory above the first component in the include, not the directory containing the included file. For an include of mlir/IR/OpBase.td, the useful root ends in mlir/include.

An unknown argument such as --gen-op-decls means that you are probably invoking the LLVM tool, an older MLIR build, or a tool from another checkout. Compare command -v, the full executable path, and --help before changing the source file.

A parse error in a file that worked elsewhere often indicates mismatched source and build trees. Use the same checkout for the .td input, include directories and executable. Do not work around it by adding every directory under /usr; that makes the result dependent on unrelated installed versions.

Generated output can change when the input or backend changes. Review the diff before committing it. Running the generator does not require root, and using elevated privileges can leave root-owned generated files that your normal build user cannot update.

Done means

  • The MLIR-specific executable exists and its version matches the intended LLVM 20.1 toolchain.
  • --help confirms the backend used by the command.
  • The include roots resolve the source and any build-generated .td files.
  • Declarations or definitions are written to the path expected by the build.
  • Exploratory output was inspected without truncating a useful file.
  • No command needed elevated privileges, and failed generation leaves the previous output intact.