@@ -21,7 +21,7 @@ Rustc consists of a number of crates, including `libsyntax`,
21
21
(the names and divisions are not set in stone and may change;
22
22
in general, a finer-grained division of crates is preferable):
23
23
24
- - ` libsyntax ` contains those things concerned purely with syntax –
24
+ - [ ` libsyntax ` ] [ libsyntax ] contains those things concerned purely with syntax –
25
25
that is, the AST, parser, pretty-printer, lexer, macro expander, and
26
26
utilities for traversing ASTs – are in a separate crate called
27
27
"syntax", whose files are in ` ./../libsyntax ` , where ` . ` is the
@@ -32,32 +32,92 @@ in general, a finer-grained division of crates is preferable):
32
32
passes, such as the type checker, borrow checker, and so forth.
33
33
It is the heart of the compiler.
34
34
35
- - ` librustc_back ` contains some very low-level details that are
35
+ - [ ` librustc_back ` ] [ back ] contains some very low-level details that are
36
36
specific to different LLVM targets and so forth.
37
37
38
- - ` librustc_trans ` contains the code to convert from Rust IR into LLVM
38
+ - [ ` librustc_trans ` ] [ trans ] contains the code to convert from Rust IR into LLVM
39
39
IR, and then from LLVM IR into machine code, as well as the main
40
40
driver that orchestrates all the other passes and various other bits
41
41
of miscellany. In general it contains code that runs towards the
42
42
end of the compilation process.
43
43
44
- - ` librustc_driver ` invokes the compiler from ` libsyntax ` , then the
45
- analysis phases from ` librustc ` , and finally the lowering and
46
- codegen passes from ` librustc_trans ` .
44
+ - [ ` librustc_driver ` ] [ driver ] invokes the compiler from
45
+ [ ` libsyntax ` ] [ libsyntax ] , then the analysis phases from ` librustc ` , and
46
+ finally the lowering and codegen passes from [ ` librustc_trans ` ] [ trans ] .
47
47
48
48
Roughly speaking the "order" of the three crates is as follows:
49
49
50
- libsyntax -> librustc -> librustc_trans
51
- | |
52
- +-----------------+-------------------+
53
- |
54
50
librustc_driver
51
+ |
52
+ +-----------------+-------------------+
53
+ | |
54
+ libsyntax -> librustc -> librustc_trans
55
55
56
56
57
- Modules in the rustc crate
58
- ==========================
59
-
60
- The rustc crate itself consists of the following submodules
57
+ The compiler process:
58
+ =====================
59
+
60
+ The Rust compiler is comprised of six main compilation phases.
61
+
62
+ 1 . Parsing input
63
+ 2 . Configuration & expanding (cfg rules & syntax extension expansion)
64
+ 3 . Running analysis passes
65
+ 4 . Translation to LLVM
66
+ 5 . LLVM passes
67
+ 6 . Linking
68
+
69
+ Phase one is responsible for parsing & lexing the input to the compiler. The
70
+ output of this phase is an abstract syntax tree (AST). The AST at this point
71
+ includes all macro uses & attributes. This means code which will be later
72
+ expanded and/or removed due to ` cfg ` attributes is still present in this
73
+ version of the AST. Parsing abstracts away details about individual files which
74
+ have been read into the AST.
75
+
76
+ Phase two handles configuration and macro expansion. You can think of this
77
+ phase as a function acting on the AST from the previous phase. The input for
78
+ this phase is the unexpanded AST from phase one, and the output is an expanded
79
+ version of the same AST. This phase will expand all macros & syntax
80
+ extensions and will evaluate all ` cfg ` attributes, potentially removing some
81
+ code. The resulting AST will not contain any macros or ` macro_use ` statements.
82
+
83
+ The code for these first two phases is in [ ` libsyntax ` ] [ libsyntax ] .
84
+
85
+ After this phase, the compiler allocates IDs to each node in the AST
86
+ (technically not every node, but most of them). If we are writing out
87
+ dependencies, that happens now.
88
+
89
+ The third phase is analysis. This is the most complex phase in the compiler,
90
+ and makes up much of the code. This phase included name resolution, type
91
+ checking, borrow checking, type & lifetime inference, trait selection, method
92
+ selection, linting and so on. Most of the error detection in the compiler comes
93
+ from this phase (with the exception of parse errors which arise during
94
+ parsing). The "output" of this phase is a set of side tables containing
95
+ semantic information about the source program. The analysis code is in
96
+ [ ` librustc ` ] [ rustc ] and some other crates with the ` librustc_ ` prefix.
97
+
98
+ The fourth phase is translation. This phase translates the AST (and the side
99
+ tables from the previous phase) into LLVM IR (intermediate representation).
100
+ This is achieved by calling into the LLVM libraries. The code for this is in
101
+ [ ` librustc_trans ` ] [ trans ] .
102
+
103
+ Phase five runs the LLVM backend. This runs LLVM's optimization passes on the
104
+ generated IR and generates machine code resulting in object files. This phase
105
+ is not really part of the Rust compiler, as LLVM carries out all the work.
106
+ The interface between LLVM and Rust is in [ ` librustc_llvm ` ] [ llvm ] .
107
+
108
+ The final phase, phase six, links the object files into an executable. This is
109
+ again outsourced to other tools and not performed by the Rust compiler
110
+ directly. The interface is in [ ` librustc_back ` ] [ back ] (which also contains some
111
+ things used primarily during translation).
112
+
113
+ A module called the driver coordinates all these phases. It handles all the
114
+ highest level coordination of compilation from parsing command line arguments
115
+ all the way to invoking the linker to produce an executable.
116
+
117
+ Modules in the librustc crate
118
+ =============================
119
+
120
+ The librustc crate itself consists of the following submodules
61
121
(mostly, but not entirely, in their own directories):
62
122
63
123
- session: options and data that pertain to the compilation session as
@@ -71,7 +131,7 @@ The rustc crate itself consists of the following submodules
71
131
- util: ubiquitous types and helper functions
72
132
- lib: bindings to LLVM
73
133
74
- The entry-point for the compiler is main() in the librustc_driver
134
+ The entry-point for the compiler is main() in the [ ` librustc_driver ` ] [ driver ]
75
135
crate.
76
136
77
137
The 3 central data structures:
@@ -106,23 +166,9 @@ The 3 central data structures:
106
166
Each of these is an opaque pointer to an LLVM type,
107
167
manipulated through the ` lib::llvm ` interface.
108
168
109
-
110
- Control and information flow within the compiler:
111
- -------------------------------------------------
112
-
113
- - main() in lib.rs assumes control on startup. Options are
114
- parsed, platform is detected, etc.
115
-
116
- - ` ./../libsyntax/parse/parser.rs ` parses the input files and produces
117
- an AST that represents the input crate.
118
-
119
- - Multiple middle-end passes (` middle/resolve.rs ` , ` middle/typeck.rs ` )
120
- analyze the semantics of the resulting AST. Each pass generates new
121
- information about the AST and stores it in various environment data
122
- structures. The driver passes environments to each compiler pass
123
- that needs to refer to them.
124
-
125
- - Finally, the ` trans ` module in ` librustc_trans ` translates the Rust
126
- AST to LLVM bitcode in a type-directed way. When it's finished
127
- synthesizing LLVM values, rustc asks LLVM to write them out in some
128
- form (` .bc ` , ` .o ` ) and possibly run the system linker.
169
+ [ libsyntax ] : https://github.com/rust-lang/rust/tree/master/src/libsyntax/
170
+ [ trans ] : https://github.com/rust-lang/rust/tree/master/src/librustc_trans/
171
+ [ llvm ] : https://github.com/rust-lang/rust/tree/master/src/librustc_llvm/
172
+ [ back ] : https://github.com/rust-lang/rust/tree/master/src/librustc_back/
173
+ [ rustc ] : https://github.com/rust-lang/rust/tree/master/src/librustc/
174
+ [ driver ] : https://github.com/rust-lang/rust/tree/master/src/librustc_driver
0 commit comments