|
| 1 | +# The Rustc Driver |
| 2 | + |
| 3 | +The [`rustc_driver`] is essentially `rustc`'s `main()` function. It acts as |
| 4 | +the glue for running the various phases of the compiler in the correct order, |
| 5 | +managing state such as the [`CodeMap`] \(maps AST nodes to source code), |
| 6 | +[`Session`] \(general build context and error messaging) and the [`TyCtxt`] |
| 7 | +\(the "typing context", allowing you to query the type system and other cool |
| 8 | +stuff). The `rustc_driver` crate also provides external users with a method |
| 9 | +for running code at particular times during the compilation process, allowing |
| 10 | +third parties to effectively use `rustc`'s internals as a library for |
| 11 | +analysing a crate. |
| 12 | + |
| 13 | +For those using `rustc` as a library, the `run_compiler()` function is the main |
| 14 | +entrypoint to the compiler. Its main parameters are a list of command-line |
| 15 | +arguments and a reference to something which implements the `CompilerCalls` |
| 16 | +trait. A `CompilerCalls` creates the overall `CompileController`, letting it |
| 17 | +govern which compiler passes are run and attach callbacks to be fired at the end |
| 18 | +of each phase. |
| 19 | + |
| 20 | +From `rustc_driver`'s perspective, the main phases of the compiler are: |
| 21 | + |
| 22 | +1. *Parse Input:* Initial crate parsing |
| 23 | +2. *Configure and Expand:* Resolve `#[cfg]` attributes and expand macros |
| 24 | +3. *Run Analysis Passes:* Run the resolution, typechecking, region checking |
| 25 | + and other miscellaneous analysis passes on the crate |
| 26 | +4. *Translate to LLVM:* Turn the analysed program into executable code |
| 27 | + |
| 28 | +The `CompileController` then gives users the ability to inspect the ongoing |
| 29 | +compilation process |
| 30 | + |
| 31 | +- after parsing |
| 32 | +- after AST expansion |
| 33 | +- after HIR lowering |
| 34 | +- after analysis, and |
| 35 | +- when compilation is done |
| 36 | + |
| 37 | +The `CompileState`'s various `state_after_*()` constructors can be inspected to |
| 38 | +determine what bits of information are available to which callback. |
| 39 | + |
| 40 | +## A Note On Lifetimes |
| 41 | + |
| 42 | +The Rust compiler is a fairly large program containing lots of big data |
| 43 | +structures (e.g. the AST, HIR, and the type system) and as such, arenas and |
| 44 | +references are heavily relied upon to minimize unnecessary memory use. This |
| 45 | +manifests itself in the way people can plug into the compiler, preferring a |
| 46 | +"push"-style API (callbacks) instead of the more Rust-ic "pull" style (think |
| 47 | +the `Iterator` trait). |
| 48 | + |
| 49 | +For example the [`CompileState`], the state passed to callbacks after each |
| 50 | +phase, is essentially just a box of optional references to pieces inside the |
| 51 | +compiler. The lifetime bound on the `CompilerCalls` trait then helps to ensure |
| 52 | +compiler internals don't "escape" the compiler (e.g. if you tried to keep a |
| 53 | +reference to the AST after the compiler is finished), while still letting users |
| 54 | +record *some* state for use after the `run_compiler()` function finishes. |
| 55 | + |
| 56 | +Thread-local storage and interning are used a lot through the compiler to reduce |
| 57 | +duplication while also preventing a lot of the ergonomic issues due to many |
| 58 | +pervasive lifetimes. The `rustc::ty::tls` module is used to access these |
| 59 | +thread-locals, although you should rarely need to touch it. |
| 60 | + |
| 61 | + |
| 62 | +[`rustc_driver`]: https://github.com/rust-lang/rust/tree/master/src/librustc_driver |
| 63 | +[`CompileState`]: https://github.com/rust-lang/rust/blob/master/src/librustc_driver/driver.rs |
| 64 | +[`Session`]: https://github.com/rust-lang/rust/blob/master/src/librustc/session/mod.rs |
| 65 | +[`TyCtxt`]: https://github.com/rust-lang/rust/blob/master/src/librustc/ty/context.rs |
| 66 | +[`CodeMap`]: https://github.com/rust-lang/rust/blob/master/src/libsyntax/codemap.rs |
0 commit comments