about summary refs log tree commit diff
path: root/src/doc/rustc-dev-guide
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-01-31 14:12:41 -0500
committerGitHub <noreply@github.com>2018-01-31 14:12:41 -0500
commitb354719755519e40624ec3527c3dd58110933af2 (patch)
treeab8c4914582d050e0e888a83ca3c80bfe419d69e /src/doc/rustc-dev-guide
parent05b26f16d91f794f5fcc5ae65a530556be22164d (diff)
parenta8b512e2b1c7d6fe3841efc88520ec9694411299 (diff)
downloadrust-b354719755519e40624ec3527c3dd58110933af2.tar.gz
rust-b354719755519e40624ec3527c3dd58110933af2.zip
Merge pull request #36 from mark-i-m/markim_readme_02
Copy MIR readme
Diffstat (limited to 'src/doc/rustc-dev-guide')
-rw-r--r--src/doc/rustc-dev-guide/src/mir.md105
1 files changed, 102 insertions, 3 deletions
diff --git a/src/doc/rustc-dev-guide/src/mir.md b/src/doc/rustc-dev-guide/src/mir.md
index eeba6847295..dbac8eb53f6 100644
--- a/src/doc/rustc-dev-guide/src/mir.md
+++ b/src/doc/rustc-dev-guide/src/mir.md
@@ -1,6 +1,105 @@
 # The MIR (Mid-level IR)
 
-TODO
+MIR is Rust's _Mid-level Intermediate Representation_. It is constructed from
+HIR (described in an earlier chapter).
 
-Defined in the `src/librustc/mir/` module, but much of the code that
-manipulates it is found in `src/librustc_mir`.
+MIR is defined in the [`src/librustc/mir/`][mir] module, but much of the code
+that manipulates it is found in [`src/librustc_mir`][mirmanip].
+
+
+_NOTE: copy/pasted from README... needs editing_
+
+# MIR definition and pass system
+
+This file contains the definition of the MIR datatypes along with the
+various types for the "MIR Pass" system, which lets you easily
+register and define new MIR transformations and analyses.
+
+Most of the code that operates on MIR can be found in the
+`librustc_mir` crate or other crates. The code found here in
+`librustc` is just the datatype definitions, along with the functions
+which operate on MIR to be placed everywhere else.
+
+## MIR Data Types and visitor
+
+The main MIR data type is `rustc::mir::Mir`, defined in `mod.rs`.
+There is also the MIR visitor (in `visit.rs`) which allows you to walk
+the MIR and override what actions will be taken at various points (you
+can visit in either shared or mutable mode; the latter allows changing
+the MIR in place). Finally `traverse.rs` contains various traversal
+routines for visiting the MIR CFG in [different standard orders][traversal]
+(e.g. pre-order, reverse post-order, and so forth).
+
+[traversal]: https://en.wikipedia.org/wiki/Tree_traversal
+
+## MIR pass suites and their integration into the query system
+
+As a MIR *consumer*, you are expected to use one of the queries that
+returns a "final MIR". As of the time of this writing, there is only
+one: `optimized_mir(def_id)`, but more are expected to come in the
+future. For foreign def-ids, we simply read the MIR from the other
+crate's metadata. But for local def-ids, the query will construct the
+MIR and then iteratively optimize it by putting it through various
+pipeline stages. This section describes those pipeline stages and how
+you can extend them.
+
+To produce the `optimized_mir(D)` for a given def-id `D`, the MIR
+passes through several suites of optimizations, each represented by a
+query. Each suite consists of multiple optimizations and
+transformations. These suites represent useful intermediate points
+where we want to access the MIR for type checking or other purposes:
+
+- `mir_build(D)` -- not a query, but this constructs the initial MIR
+- `mir_const(D)` -- applies some simple transformations to make MIR ready for constant evaluation;
+- `mir_validated(D)` -- applies some more transformations, making MIR ready for borrow checking;
+- `optimized_mir(D)` -- the final state, after all optimizations have been performed.
+
+### Stealing
+
+The intermediate queries `mir_const()` and `mir_validated()` yield up
+a `&'tcx Steal<Mir<'tcx>>`, allocated using
+`tcx.alloc_steal_mir()`. This indicates that the result may be
+**stolen** by the next suite of optimizations -- this is an
+optimization to avoid cloning the MIR. Attempting to use a stolen
+result will cause a panic in the compiler. Therefore, it is important
+that you do not read directly from these intermediate queries except as
+part of the MIR processing pipeline.
+
+Because of this stealing mechanism, some care must also be taken to
+ensure that, before the MIR at a particular phase in the processing
+pipeline is stolen, anyone who may want to read from it has already
+done so. Concretely, this means that if you have some query `foo(D)`
+that wants to access the result of `mir_const(D)` or
+`mir_validated(D)`, you need to have the successor pass "force"
+`foo(D)` using `ty::queries::foo::force(...)`. This will force a query
+to execute even though you don't directly require its result.
+
+As an example, consider MIR const qualification. It wants to read the
+result produced by the `mir_const()` suite. However, that result will
+be **stolen** by the `mir_validated()` suite. If nothing was done,
+then `mir_const_qualif(D)` would succeed if it came before
+`mir_validated(D)`, but fail otherwise. Therefore, `mir_validated(D)`
+will **force** `mir_const_qualif` before it actually steals, thus
+ensuring that the reads have already happened:
+
+```
+mir_const(D) --read-by--> mir_const_qualif(D)
+     |                       ^
+  stolen-by                  |
+     |                    (forces)
+     v                       |
+mir_validated(D) ------------+
+```
+
+### Implementing and registering a pass
+
+To create a new MIR pass, you simply implement the `MirPass` trait for
+some fresh singleton type `Foo`. Once you have implemented a trait for
+your type `Foo`, you then have to insert `Foo` into one of the suites;
+this is done in `librustc_driver/driver.rs` by invoking `push_pass(S,
+Foo)` with the appropriate suite substituted for `S`.
+
+
+[mir]: https://github.com/rust-lang/rust/tree/master/src/librustc/mir
+[mirmanip]: https://github.com/rust-lang/rust/tree/master/src/librustc_mir
+[mir]: https://github.com/rust-lang/rust/tree/master/src/librustc/mir