Generate LLDB C++ from TableGen Files with lldb-tblgen-18
TableGen errors are famously unhelpful until you separate parsing from code generation, and lldb-tblgen-18 is where that split actually matters. This guide turns an LLDB TableGen .td file into generated output, or checks that it parses cleanly before you even pick a backend. Allow 15 to 30 minutes if you already have a valid source file and its include directories.
The route
Jump straight to the step you need, or tick off Done means at the end.
The installed manual belongs to LLVM 18's llvm-18 package, version 1:18.1.3-1ubuntu1. On this machine the manpage is present but the lldb-tblgen-18 executable is not, so the commands below are a version-specific workflow drawn from the local manual: test them against an LLVM development installation that actually includes the LLDB tool. You need a shell, an LLDB source tree or another project supplying the required .td files, and write permission on the output directory. Nothing here needs sudo, and running a generator as root won't fix an ordinary file-permission mistake.
1. Check the tool and the input path
Confirm the exact executable and package version on the machine where you'll actually generate code:
$ command -v lldb-tblgen-18
/usr/bin/lldb-tblgen-18
$ lldb-tblgen-18 -version
LLVM version 18.1.3
$ test -r /path/to/input.td && echo 'input is readable'
input is readable
The first two lines are illustrative: the queued Ubuntu package provides the manual, while this reference machine doesn't provide the executable. Your binary may live under an LLVM installation directory rather than /usr/bin. The input is one filename, normally ending in .td, and TableGen resolves included files through its built-in search rules plus any directories you supply with -I.
Checkpoint
Stop here if command -v finds nothing or the input is unreadable. Fix the installation or the path before chasing generated output.
2. Parse the file without running a backend
-null-backend is the low-risk first pass: it parses the source and builds records, then deliberately stops before running any backend:
$ lldb-tblgen-18 -null-backend /path/to/input.td
$ printf 'exit status: %s\n' "$?"
exit status: 0
A zero status here means this invocation completed successfully. It's a useful syntax and include-path check, not proof the input has the records a later LLDB backend needs. If the command reports an unknown include or record, read the diagnostic before you change anything. Add an include directory explicitly when the source relies on project-relative files:
$ lldb-tblgen-18 -I /path/to/llvm/include -I /path/to/lldb/include \
-null-backend /path/to/input.td
Use absolute paths while diagnosing. It removes a common distraction: the current working directory changes what a relative include path even means.
3. Inspect records before generating code
Once parsing succeeds, print the records to standard output instead of creating a file, a purely read-only inspection step:
$ lldb-tblgen-18 -I /path/to/include -print-records \
/path/to/input.td > /tmp/lldb-records.txt
$ test -s /tmp/lldb-records.txt && echo 'records were written'
records were written
-print-records is the default backend. Reach for -print-detailed-records when you need global variables, classes and records in more depth. These reports show what TableGen actually built; they are not the C++ implementation an LLDB build normally consumes.
Keep temporary reports outside the source tree if you're unsure whether a build watches that directory: it avoids triggering unrelated rebuilds and keeps generated deliverables clearly separate.
4. Emit an output file safely
A project-specific backend option selects what C++ or other output gets generated. The local manual lists the common output controls, but the LLDB backend options depend on the source tree and aren't enumerated by the short lldb-tblgen page. Ask the installed binary for its complete list, then combine the selected backend with -o:
$ lldb-tblgen-18 --help-list > /tmp/lldb-tblgen-options.txt
$ lldb-tblgen-18 -I /path/to/include -o /path/to/generated/output.cpp \
-YOUR_LLDB_BACKEND_OPTION /path/to/input.td
Replace -YOUR_LLDB_BACKEND_OPTION with an option your own binary actually shows you. Don't borrow a backend name from a nearby LLVM or Clang build. The short manual's documented common options include -o filename, -d filename for a dependency file, -D=macroname for a defined macro, and -write-if-changed to skip rewriting an unchanged output.
Warning
-o can replace an existing file. Prefer a new build-directory path, and add -write-if-changed when the generated file is tracked or watched by other tools:
$ mkdir -p /path/to/build/generated
$ lldb-tblgen-18 -I /path/to/include -write-if-changed \
-o /path/to/build/generated/output.cpp \
-YOUR_LLDB_BACKEND_OPTION /path/to/input.td
$ test -s /path/to/build/generated/output.cpp && echo 'output is non-empty'
output is non-empty
If the output is wrong, remove only the generated file in the build directory and rerun after fixing the source or backend selection. Never delete source .td files as a recovery step. If you overwrote a tracked generated file, restore it through your normal version control, then regenerate into a clean build directory.
5. Produce machine-readable records when needed
For tooling that needs to inspect records programmatically, use -dump-json. It writes a JSON representation of every record, suitable for further automated processing:
$ lldb-tblgen-18 -I /path/to/include -dump-json \
/path/to/input.td > /tmp/lldb-records.json
$ python3 -m json.tool /tmp/lldb-records.json > /dev/null
$ echo 'valid JSON'
valid JSON
That Python check only validates the JSON syntax; it says nothing about whether the records are semantically right for LLDB. Keep the output in a temporary or build location until the schema and record names are confirmed.
6. Diagnose slow or surprising runs
Use -time-phases to report parser and backend timing, and -stats for backend statistics:
$ lldb-tblgen-18 -time-phases -stats \
-YOUR_LLDB_BACKEND_OPTION /path/to/input.td
-debug output can be far noisier and may expose implementation details that aren't stable between LLVM releases. Turn it on for a single diagnostic run, capture the output, and turn it back off once you understand the failure. A successful exit status still only means this invocation completed: inspect the generated file and the build's later compiler step for the rest of the story.
Done means
- lldb-tblgen-18 is available from the LLVM 18 installation used for the build.
- The input .td file parses with the required
-Idirectories and-null-backend. - The backend option came from that binary's own help, not guessed from another TableGen tool.
- Generated output lives in a build directory, uses
-write-if-changedwhere appropriate, and was checked after generation. - Any JSON or diagnostic report stays separate from source files, and no elevated privilege was used.