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

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

Run an LLDB TableGen File Safely with LLVM 20

Before trusting an lldb-tblgen-20 command found online, check whether the binary is even on your machine. This guide builds a checked TableGen workflow for LLDB .td input, identifies the installed LLVM 20 tools, parses a small file without leaving anything behind, then writes generated data to a deliberate destination. Allow about twenty minutes.

The package installed on this machine provides the lldb-tblgen-20 manual page but not an executable of that name, so verification here uses the installed llvm-tblgen-20 binary instead, and the guide is explicit about where that substitution matters. You need a shell, the llvm-20 package, a TableGen source tree or a small test file, and permission to read its included files. These are ordinary user commands: nothing needs sudo, and none of it alters an LLVM checkout or a system service.

1. Check the installed version and executable names

Start with the package and binary checks. Both are read-only and make the version assumption visible before you build on it:

$ dpkg-query -W -f='${Package} ${Version}\n' llvm-20
llvm-20 1:20.1.8~++20250804090239+87f0227cb601-1~exp1~20250804210352.139
$ command -v llvm-tblgen-20
/usr/bin/llvm-tblgen-20
$ llvm-tblgen-20 --version
Ubuntu LLVM version 20.1.8
  Optimized build.

The installed package owns the lldb-tblgen-20 manpage, but this host has no lldb-tblgen-20 command in PATH. That packaging detail is worth checking before you put the name in a build script: the manpage describes the common *-tblgen interface, and it is not proof every family member got installed alongside it.

Checkpoint

If command -v lldb-tblgen-20 prints a path on your machine, use that executable for the LLDB-specific backend work. If it prints nothing, continue with the available LLVM 20 binary for syntax and record checks, then build or install the LLDB tool through your normal LLVM process before asking for an LLDB-specific backend.

2. Learn the input and output boundary

TableGen reads a Target Description file, normally ending in .td. It parses declarations into records, and a backend turns those records into generated output. The filename is optional: leave it out and TableGen reads standard input instead. -o picks an output file, and -o - sends it to standard output.

Don't treat a generic backend as an LLDB backend. The output depends on the executable and the backend option, not the filename extension. Start with -null-backend when the only question is whether the source parses and records can be built.

Option spellings in the LLVM 20 manpage include -I for include directories, -D for a defined macro, -d for a dependency file, -o for output, -null-backend, -print-records, -dump-json and -write-if-changed. Ask the installed program for its complete list when you're working with a particular backend:

$ llvm-tblgen-20 --help | sed -n '1,45p'
USAGE: llvm-tblgen-20 [options] <input file>

OPTIONS:

General options:
  -D <macro name>       Name of the macro to be defined
  -I <directory>        Directory of include files
  -d <filename>         Dependency filename

3. Parse a small source without creating a file

Use standard input for a smoke test. This source defines one class and one concrete record, exercising parsing and record construction without claiming to model an actual LLDB target:

$ printf '%s\n' \
    'class Demo<int N> { int value = N; }' \
    'def Example : Demo<7>;' \
  | llvm-tblgen-20 -null-backend -
$ printf 'exit status: %s\n' "$?"
exit status: 0

A zero status means this frontend accepted the input and built its records. -null-backend deliberately produces no generated file, so there's nothing to clean up afterwards. It's a useful first checkpoint when a larger file fails: it separates a tool installation problem from an include, syntax or backend problem.

To see what the parser actually built, use the default record-printing backend instead:

$ printf '%s\n' \
    'class Demo<int N> { int value = N; }' \
    'def Example : Demo<7>;' \
  | llvm-tblgen-20 -print-records -
------------- Classes -----------------
class Demo<int Demo:N = ?> {
  int value = Demo:N;
}
------------- Defs -----------------
def Example {    // Demo
  int value = 7;
}

Formatting can change between LLVM releases, so check the exit status and the records themselves rather than matching whitespace in a script.

4. Run a real file with its include path

Move to the directory used by the source tree and pass include roots explicitly. LLVM projects lean heavily on included .td files, so running from an arbitrary directory can produce a misleading missing-file error:

$ cd /path/to/llvm-project
$ llvm-tblgen-20 -I /path/to/llvm-project/llvm/include \
    -I /path/to/llvm-project/lldb/include \
    -null-backend /path/to/input.td
$ printf 'exit status: %s\n' "$?"
exit status: 0

Replace both paths and the input with locations that exist in your own checkout. Add further -I values only for directories the source's include statements actually require. If an include is missing, check the path and spelling before touching the source: elevated privileges will not repair a wrong include root.

Once the file parses, pick the backend the consuming tool actually needs. Backend names are executable-specific: check lldb-tblgen-20 --help when that command exists, or the build documentation for your LLVM revision. Don't copy an llvm-tblgen-20 backend option into an LLDB command without verifying it first.

5. Write output without losing an existing file

Generation changes files, so inspect the destination first. Shell redirection and -o can both replace an existing file. Write to a new temporary destination on the same filesystem, verify it, then replace the final file only once you're ready:

$ test ! -e /path/to/generated.new || \
    { printf '%s\n' 'Refusing to overwrite generated.new'; exit 1; }
$ llvm-tblgen-20 -I /path/to/include \
    -print-records /path/to/input.td -o /path/to/generated.new
$ test -s /path/to/generated.new
$ mv -- /path/to/generated.new /path/to/generated.inc

Warning

That final mv replaces generated.inc if it already exists. Keep a copy or use version control before doing that in a working tree. If generation fails, don't move the incomplete file: remove only the named temporary file after checking the failure, leaving the original generated file untouched.

For repeatable builds, -write-if-changed can skip rewriting output whose content is identical. That cuts timestamp churn, but it says nothing about whether you picked the right backend.

Common traps

  • Missing lldb-tblgen-20 command. Different problem from a bad .td file. Rerun command -v and dpkg-query. If only llvm-tblgen-20 is present, generic parsing works but LLDB-specific generation isn't demonstrated on this host.
  • Non-zero status with an include error. Usually an -I directory is missing or points at the wrong checkout.
  • Syntax or type diagnostic. Points at the source itself.
  • Successful parse, then an unknown backend option. That option belongs to a different TableGen executable or LLVM revision.

Keep the full diagnostic and the exact version output when you report an issue. Don't use sudo to run a compiler generator against a source tree you own: it can leave root-owned generated files behind and hide ordinary path mistakes. Reach for elevated privileges only when the build directory is intentionally protected, and fix its ownership or permissions through the project administrator instead.

Done means

  • The installed LLVM package and TableGen version were recorded.
  • You checked whether the LLDB-specific executable exists instead of assuming the manpage installed it.
  • A small .td input parsed successfully with -null-backend.
  • Real source files use explicit include directories and a verified backend.
  • Generated output is written to a new path, checked, and only then moved into place.
  • A failed generation cannot overwrite the previous output, and no service or system configuration was changed.