Compiler Internals
This section is for those curious about how the Flint compiler works under the hood. Understanding the internals is not required to use Flint. If you are here to write firmware, skip to Getting Started.
The Big Picture
Flint’s compiler is implemented in Rust and structured as a set of library crates under crates/ in the repository. The main crates are:
| Crate | Role |
|---|---|
flint-cli | The flint binary and argument parsing |
flint-driver | Command orchestration and pipeline execution |
flint-lexer | Tokenization |
flint-parser | Parsing, CST construction, error recovery |
flint-syntax | Shared token kinds, spans, CST/AST node types |
flint-check | Semantic analysis: symbol resolution, type checking, ownership |
flint-lower | HIR and FIR lowering, type inference, ownership analysis, CFG |
flint-backend | RP2040-specific machine lowering and Thumb v6-M code generation |
flint-diagnostics | Diagnostic types, human-readable and JSON rendering |
flint-manifest | flint.toml parsing and validation |
flint-lsp | Language server: completion, diagnostics, navigation, editor features |
flint-elf | ELF image packaging |
flint-uf2 | UF2 image packaging |
Pipeline at a Glance
Source (.fl files)
│
▼
Lexer ← flint-lexer
│
▼
Parser ← flint-parser
│
▼
CST → AST ← flint-syntax, flint-parser
│
▼
Resolver ← flint-check
Type Checker ← flint-check / flint-lower
│
▼
HIR ← flint-lower (high-level IR)
│
▼
FIR ← flint-lower (target-independent IR)
│
▼
Machine Lowering ← flint-backend (target-specific)
│
▼
Code Gen ← flint-backend (Thumb / ARM instruction emission)
│
▼
ELF / BIN / UF2 ← flint-backend, flint-elf, flint-uf2
The key architectural property is that FIR is target-independent. Everything above FIR is shared across all targets. Everything below FIR is per-target.
Design Goals
- No external toolchain dependencies. The compiler emits machine code directly. No GCC, LLVM, or external assembler.
- Fast compilation. MCU programs are small. Compilation should be in tens of milliseconds, not seconds.
- Good diagnostics. Errors point at real source locations with clear messages. JSON output for tooling.
- Recoverable parsing. The parser continues after errors so you see multiple diagnostics in one run.
Self-Hosted Standard Library
Where possible, the standard library (micro/*, std/*, board/*) is written in Flint source. The compiler and runtime provide privileged backing implementations for things Flint source cannot express (allocator hooks, startup glue, target intrinsics), but high-level APIs are Flint.
This keeps the language honest: the standard library is an ordinary user of the language, not a hidden exception to it.