Experimental TPDE backend
Spice ships with the LLVM code generator as its default and stable compilation backend. Alongside it, an
experimental alternative backend is available: TPDE, a fast compiler
back-end framework that consumes LLVM IR directly and emits ELF objects at roughly -O0 code quality but
10-20× faster than clang -O0 — useful for tight edit/compile iteration loops.
This backend is not a drop-in replacement for LLVM CodeGen. It performs no optimization and supports only a narrow slice of the targets LLVM does. It is opt-in at runtime. The Linux release packages of Spice come with it; for other builds, it is opt-in at build time as well.
Experimental
The TPDE backend is under active development and disabled by default. Expect rough edges, unsupported language features, and possible codegen bugs. Do not use for production builds. Bug reports welcome.
Supported configurations¶
| Property | Value |
|---|---|
| Host operating systems | Linux (ELF only) |
| Target architectures | x86_64, aarch64 |
| Code model | small only (--code-model default or small) |
| Relocation model | PIC only (--relocation-model pic or pie) |
| Optimization | none — -O flags are accepted but ignored |
| Link-time optimization | not supported (-lto is rejected) |
| No red zone (x86_64) | not supported (--no-red-zone is rejected) |
| CPU features | not supported (--cpu-features is rejected) |
Building Spice with TPDE support¶
The Linux release packages of Spice (x86_64 and aarch64) are built with TPDE support, so this is only needed when
building Spice from source.
TPDE is pulled in as a git submodule at deps/tpde/. Build its libraries into the std, then build Spice:
The compiler emits objects via the std TPDE bindings (see Using TPDE from Spice code), so it is only backed by TPDE if the TPDE libraries were available while building it.
Requirements:
- The same LLVM version Spice is built against must be one of TPDE's supported versions. Spice's regular LLVM build already satisfies this on modern systems.
- A matching
clangbinary must be discoverable; TPDE uses it to compile its encoding templates.dev-setup.pyinstalls a suitable one alongside LLVM.
Selecting the backend¶
Once built with TPDE support, choose the backend per compilation with --backend:
| Bash | |
|---|---|
If the compiler was built without the TPDE libraries, passing --backend=tpde produces a CLI error.
Limitations you may hit¶
--dump-assemblyand--dump-object-fileare not meaningful under TPDE; they return placeholder text.- Any Spice code that requires wide vectors, exception handling, or non-
smallcode model will fail to compile. - Debug info emission (
-g) works but produces-O0-quality info regardless of the--build-mode. - TPDE does not support inline assembly, so the
asmbuiltin and thesyscallbuiltin are rejected with a compile error.
Using TPDE from Spice code¶
Besides being a backend of the Spice compiler, TPDE can also be used from Spice programs, which build LLVM modules with
the LLVM bindings (std/bindings/llvm). The TPDE bindings (std/bindings/tpde) compile such a module to an ELF object,
in a file or in memory:
TPDE only offers a C++ API, so the bindings compile a small C API wrapper (std/bindings/tpde/tpde-wrapper.cpp) along
with the program. They need the TPDE libraries and headers, in addition to what the LLVM bindings need.
The Linux release packages ship them inside the std, at std/bindings/tpde/lib and std/bindings/tpde/include, and the
compiler points the bindings to them on its own. The shipped libraries are built against the LLVM version of the release
(see LLVM_VERSION in the release workflow), so the LLVM the program links against has to be the same version.
When building Spice from source on Linux, build TPDE with python setup-deps.py --tpde. It builds the deps/tpde
submodule with its own CMake project, against the LLVM from LLVM_DIR (<llvm>/lib/cmake/llvm) or llvm-config, and
installs the libraries, headers and licenses into std/bindings/tpde, like the release packages ship them. The compiler
then finds them on its own. It needs a clang matching the LLVM version, to compile TPDE's encoding templates.
The TPDE_FLAGS environment variable takes precedence over the libraries in the std. It holds the include flag for the
TPDE headers and the paths of the TPDE static libraries, space-separated:
Without TPDE libraries, or on platforms other than Linux, the bindings still compile and link, but tpde::isAvailable() returns
false and every compilation fails with an error message.