Use llvm-tblgen-20 to Inspect TableGen Records and JSON
You will parse a small LLVM TableGen source file, inspect the records that the front end creates, and write the same data as JSON. This is a read-and-generate workflow: llvm-tblgen-20 does not edit the .td input. Allow about 15 minutes for the example, or longer if you are adapting it to a target backend.
The route
Jump straight to the step you need, or tick off Done means at the end.
The commands here were checked with Ubuntu LLVM version 20.1.8 from package llvm-20. TableGen is primarily a compiler-development tool, not a general-purpose configuration parser. You need a shell, the executable, and a writable working directory. No command below needs elevated privileges.
1. Check the installed executable
Start by checking which binary will run and which LLVM build supplied it:
$ command -v llvm-tblgen-20
/usr/bin/llvm-tblgen-20
$ llvm-tblgen-20 --version
Ubuntu LLVM version 20.1.8
Optimized build.
The version matters because the available backends and their options are tied to the LLVM build. The installed manual describes the program as translating .td target-description files into C++ and other output formats. A plain invocation uses the default record-printing backend; useful generated output normally requires an explicit backend such as -dump-json or one of the --gen-... actions.
Checkpoint
If the command is missing, stop here and install the LLVM package through your normal package-management process. Do not copy an unverified binary into /usr/bin.
2. Create a small TableGen input
Use a separate file while learning. This example defines a class with two fields and creates two records from it:
$ mkdir -p ~/tblgen-check
$ cd ~/tblgen-check
$ editor records.td
Put this in records.td:
class Item<string name, int value> {
string Name = name;
int Value = value;
}
def First : Item<"first", 1>;
def Second : Item<"second", 2>;
TableGen syntax uses angle brackets for template arguments. They are escaped in this HTML code block, but the file itself must contain ordinary < and > characters. The class supplies the fields; each def instantiates a named record.
Check that the file contains exactly the source you intend before running a larger input:
$ sed -n '1,20p' records.td
class Item<string name, int value> {
string Name = name;
int Value = value;
}
def First : Item<"first", 1>;
def Second : Item<"second", 2>;
3. Inspect the default records
Pass the input filename as the optional positional argument:
$ llvm-tblgen-20 records.td
------------- Classes -----------------
class Item<string Item:name = ?, int Item:value = ?> {
string Name = Item:name;
int Value = Item:value;
}
------------- Defs -----------------
def First {
string Name = "first";
int Value = 1;
}
def Second {
string Name = "second";
int Value = 2;
}
The exact formatting can vary, including comments identifying parent classes. The useful checks are that the command exits successfully and that the named definitions have the expected values. This default output is mainly a debugging view. It is not C++ and should not be treated as a stable machine-readable interface.
TableGen can also read standard input when no filename is supplied. This is useful for a quick parser check, but a saved .td file is easier to review and reproduce:
$ printf '%s\n' 'def Answer { int Value = 42; }' | llvm-tblgen-20 -print-records -
------------- Classes -----------------
------------- Defs -----------------
def Answer {
int Value = 42;
}
4. Produce JSON for another tool
Use the JSON backend when a script needs structured records. The -o option selects the output file; it does not modify records.td:
$ llvm-tblgen-20 records.td -dump-json -o records.json
$ test -s records.json && echo 'JSON written'
JSON written
$ head -c 300 records.json
{"!instanceof":{"Item":["First","Second"]},"!tablegen_json_version":1,"First":{...}
The output contains metadata such as the TableGen JSON format version, inheritance information, source locations, and the resolved field values. Do not parse it by grepping for a particular line: JSON is a data format and the order or whitespace is not the interface your script should depend on.
Validate the file with a JSON parser available on your system:
$ python3 -m json.tool records.json > /dev/null
$ echo $?
0
That check only proves that the output is valid JSON. It does not prove that the records are semantically correct, so also inspect the input and check for expected names in the parsed data. If you use a script, treat a missing field as an error rather than silently substituting a default.
5. Find the backend or option you actually need
The installed binary has more actions than the short manual page can list. Ask the same executable for its local help:
$ 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
-o <filename> - Output filename
--version - Display the version of this program
--dump-json - Dump all records as machine-readable JSON
The help output also lists target-specific generation actions such as --gen-instr-info and --gen-register-info. Use the action expected by the LLVM component you are building, and read that component's build files to see its input paths, include directories, macros, and output name. Do not guess a backend from its name: an action can require target-specific classes that are absent from a small test file.
For included descriptions, add an include directory with -I. For conditional source sections, -D defines a macro name without a value, as documented by the installed command guide. Record the exact command in your build or review notes so another person can reproduce the generated file.
6. Avoid overwriting generated output
Output files can be valuable build artefacts. Shell redirection and -o can replace an existing file, depending on the command and options you choose. When testing a new input, use a new destination first:
$ llvm-tblgen-20 records.td -dump-json -o records.json.new
$ python3 -m json.tool records.json.new > /dev/null
$ mv records.json.new records.json
The final mv changes state by replacing the old output. Only run it after validation and after checking the diff if the file is tracked:
$ git diff -- records.json
If generation fails, leave the old output in place and remove the untrusted temporary file when you have finished investigating. Do not use sudo to work around a write-permission problem in a project tree; fix the directory ownership or choose a writable build directory instead.
7. Diagnose the common failures
A parse error usually names the source location. Check the reported line, then rerun the smallest input that reproduces it. An unknown option means the installed binary does not support the command copied from another LLVM release, so compare llvm-tblgen-20 -help with the command you are using.
An include failure is normally a missing or incorrect -I directory. Use an absolute path while diagnosing, and confirm it contains the requested .td file:
$ test -r /path/to/include/Base.td && echo readable
readable
$ llvm-tblgen-20 -I /path/to/include records.td -dump-json -o records.json.new
If a backend complains about missing definitions, use the target's own TableGen inputs and include paths. The front end may parse your file correctly while a backend still lacks the records it expects. Keep source and generated files separate, and compare outputs after changing one input at a time.
Done means
llvm-tblgen-20 --versionidentifies the LLVM 20.1.8 executable you intended to use.- A reviewed
.tdfile parses successfully with the expected records. - The chosen backend is present in the executable's local help output.
- JSON output passes a parser check and contains the expected record data.
- Existing generated output was not replaced until the new file was validated.