Skip to content

Commit 87ae827

Browse files
authored
Merge pull request #36 from mark-i-m/markim_readme_02
Copy MIR readme
2 parents 28b7fab + 239e2c6 commit 87ae827

File tree

1 file changed

+102
-3
lines changed

1 file changed

+102
-3
lines changed

src/mir.md

+102-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,105 @@
11
# The MIR (Mid-level IR)
22

3-
TODO
3+
MIR is Rust's _Mid-level Intermediate Representation_. It is constructed from
4+
HIR (described in an earlier chapter).
45

5-
Defined in the `src/librustc/mir/` module, but much of the code that
6-
manipulates it is found in `src/librustc_mir`.
6+
MIR is defined in the [`src/librustc/mir/`][mir] module, but much of the code
7+
that manipulates it is found in [`src/librustc_mir`][mirmanip].
8+
9+
10+
_NOTE: copy/pasted from README... needs editing_
11+
12+
# MIR definition and pass system
13+
14+
This file contains the definition of the MIR datatypes along with the
15+
various types for the "MIR Pass" system, which lets you easily
16+
register and define new MIR transformations and analyses.
17+
18+
Most of the code that operates on MIR can be found in the
19+
`librustc_mir` crate or other crates. The code found here in
20+
`librustc` is just the datatype definitions, along with the functions
21+
which operate on MIR to be placed everywhere else.
22+
23+
## MIR Data Types and visitor
24+
25+
The main MIR data type is `rustc::mir::Mir`, defined in `mod.rs`.
26+
There is also the MIR visitor (in `visit.rs`) which allows you to walk
27+
the MIR and override what actions will be taken at various points (you
28+
can visit in either shared or mutable mode; the latter allows changing
29+
the MIR in place). Finally `traverse.rs` contains various traversal
30+
routines for visiting the MIR CFG in [different standard orders][traversal]
31+
(e.g. pre-order, reverse post-order, and so forth).
32+
33+
[traversal]: https://en.wikipedia.org/wiki/Tree_traversal
34+
35+
## MIR pass suites and their integration into the query system
36+
37+
As a MIR *consumer*, you are expected to use one of the queries that
38+
returns a "final MIR". As of the time of this writing, there is only
39+
one: `optimized_mir(def_id)`, but more are expected to come in the
40+
future. For foreign def-ids, we simply read the MIR from the other
41+
crate's metadata. But for local def-ids, the query will construct the
42+
MIR and then iteratively optimize it by putting it through various
43+
pipeline stages. This section describes those pipeline stages and how
44+
you can extend them.
45+
46+
To produce the `optimized_mir(D)` for a given def-id `D`, the MIR
47+
passes through several suites of optimizations, each represented by a
48+
query. Each suite consists of multiple optimizations and
49+
transformations. These suites represent useful intermediate points
50+
where we want to access the MIR for type checking or other purposes:
51+
52+
- `mir_build(D)` -- not a query, but this constructs the initial MIR
53+
- `mir_const(D)` -- applies some simple transformations to make MIR ready for constant evaluation;
54+
- `mir_validated(D)` -- applies some more transformations, making MIR ready for borrow checking;
55+
- `optimized_mir(D)` -- the final state, after all optimizations have been performed.
56+
57+
### Stealing
58+
59+
The intermediate queries `mir_const()` and `mir_validated()` yield up
60+
a `&'tcx Steal<Mir<'tcx>>`, allocated using
61+
`tcx.alloc_steal_mir()`. This indicates that the result may be
62+
**stolen** by the next suite of optimizations -- this is an
63+
optimization to avoid cloning the MIR. Attempting to use a stolen
64+
result will cause a panic in the compiler. Therefore, it is important
65+
that you do not read directly from these intermediate queries except as
66+
part of the MIR processing pipeline.
67+
68+
Because of this stealing mechanism, some care must also be taken to
69+
ensure that, before the MIR at a particular phase in the processing
70+
pipeline is stolen, anyone who may want to read from it has already
71+
done so. Concretely, this means that if you have some query `foo(D)`
72+
that wants to access the result of `mir_const(D)` or
73+
`mir_validated(D)`, you need to have the successor pass "force"
74+
`foo(D)` using `ty::queries::foo::force(...)`. This will force a query
75+
to execute even though you don't directly require its result.
76+
77+
As an example, consider MIR const qualification. It wants to read the
78+
result produced by the `mir_const()` suite. However, that result will
79+
be **stolen** by the `mir_validated()` suite. If nothing was done,
80+
then `mir_const_qualif(D)` would succeed if it came before
81+
`mir_validated(D)`, but fail otherwise. Therefore, `mir_validated(D)`
82+
will **force** `mir_const_qualif` before it actually steals, thus
83+
ensuring that the reads have already happened:
84+
85+
```
86+
mir_const(D) --read-by--> mir_const_qualif(D)
87+
| ^
88+
stolen-by |
89+
| (forces)
90+
v |
91+
mir_validated(D) ------------+
92+
```
93+
94+
### Implementing and registering a pass
95+
96+
To create a new MIR pass, you simply implement the `MirPass` trait for
97+
some fresh singleton type `Foo`. Once you have implemented a trait for
98+
your type `Foo`, you then have to insert `Foo` into one of the suites;
99+
this is done in `librustc_driver/driver.rs` by invoking `push_pass(S,
100+
Foo)` with the appropriate suite substituted for `S`.
101+
102+
103+
[mir]: https://github.com/rust-lang/rust/tree/master/src/librustc/mir
104+
[mirmanip]: https://github.com/rust-lang/rust/tree/master/src/librustc_mir
105+
[mir]: https://github.com/rust-lang/rust/tree/master/src/librustc/mir

0 commit comments

Comments
 (0)