@@ -23,75 +23,110 @@ use rustc_span::symbol::Symbol;
2323use rustc_span:: Span ;
2424use rustc_target:: asm:: InlineAsmRegOrRegClass ;
2525
26- /// The various "big phases" that MIR goes through .
26+ /// Represents the "flavors" of MIR.
2727///
28- /// These phases all describe dialects of MIR. Since all MIR uses the same datastructures, the
29- /// dialects forbid certain variants or values in certain phases. The sections below summarize the
30- /// changes, but do not document them thoroughly. The full documentation is found in the appropriate
31- /// documentation for the thing the change is affecting.
28+ /// All flavors of MIR use the same data structure, but there are some important differences. These
29+ /// differences come in two forms: Dialects and phases.
3230///
33- /// Warning: ordering of variants is significant.
31+ /// Dialects represent a stronger distinction than phases. This is because the transitions between
32+ /// dialects are semantic changes, and therefore technically *lowerings* between distinct IRs. In
33+ /// other words, the same [`Body`](crate::mir::Body) might be well-formed for multiple dialects, but
34+ /// have different semantic meaning and different behavior at runtime.
35+ ///
36+ /// Each dialect additionally has a number of phases. However, phase changes never involve semantic
37+ /// changes. If some MIR is well-formed both before and after a phase change, it is also guaranteed
38+ /// that it has the same semantic meaning. In this sense, phase changes can only add additional
39+ /// restrictions on what MIR is well-formed.
40+ ///
41+ /// When adding phases, remember to update [`MirPhase::phase_index`].
3442#[ derive( Copy , Clone , TyEncodable , TyDecodable , Debug , PartialEq , Eq , PartialOrd , Ord ) ]
3543#[ derive( HashStable ) ]
3644pub enum MirPhase {
37- /// The dialect of MIR used during all phases before `DropsLowered` is the same. This is also
38- /// the MIR that analysis such as borrowck uses.
39- ///
40- /// One important thing to remember about the behavior of this section of MIR is that drop terminators
41- /// (including drop and replace) are *conditional*. The elaborate drops pass will then replace each
42- /// instance of a drop terminator with a nop, an unconditional drop, or a drop conditioned on a drop
43- /// flag. Of course, this means that it is important that the drop elaboration can accurately recognize
44- /// when things are initialized and when things are de-initialized. That means any code running on this
45- /// version of MIR must be sure to produce output that drop elaboration can reason about. See the
46- /// section on the drop terminatorss for more details.
47- Built = 0 ,
48- // FIXME(oli-obk): it's unclear whether we still need this phase (and its corresponding query).
49- // We used to have this for pre-miri MIR based const eval.
50- Const = 1 ,
51- /// This phase checks the MIR for promotable elements and takes them out of the main MIR body
52- /// by creating a new MIR body per promoted element. After this phase (and thus the termination
53- /// of the `mir_promoted` query), these promoted elements are available in the `promoted_mir`
54- /// query.
55- ConstsPromoted = 2 ,
56- /// After this projections may only contain deref projections as the first element.
57- Derefered = 3 ,
58- /// Beginning with this phase, the following variants are disallowed:
59- /// * [`TerminatorKind::DropAndReplace`]
45+ /// The MIR that is generated by MIR building.
46+ ///
47+ /// The only things that operate on this dialect are unsafeck, the various MIR lints, and const
48+ /// qualifs.
49+ ///
50+ /// This has no distinct phases.
51+ Built ,
52+ /// The MIR used for most analysis.
53+ ///
54+ /// The only semantic change between analysis and built MIR is constant promotion. In built MIR,
55+ /// sequences of statements that would generally be subject to constant promotion are
56+ /// semantically constants, while in analysis MIR all constants are explicit.
57+ ///
58+ /// The result of const promotion is available from the `mir_promoted` and `promoted_mir` queries.
59+ ///
60+ /// This is the version of MIR used by borrowck and friends.
61+ Analysis ( AnalysisPhase ) ,
62+ /// The MIR used for CTFE, optimizations, and codegen.
63+ ///
64+ /// The semantic changes that occur in the lowering from analysis to runtime MIR are as follows:
65+ ///
66+ /// - Drops: In analysis MIR, `Drop` terminators represent *conditional* drops; roughly speaking,
67+ /// if dataflow analysis determines that the place being dropped is uninitialized, the drop will
68+ /// not be executed. The exact semantics of this aren't written down anywhere, which means they
69+ /// are essentially "what drop elaboration does." In runtime MIR, the drops are unconditional;
70+ /// when a `Drop` terminator is reached, if the type has drop glue that drop glue is always
71+ /// executed. This may be UB if the underlying place is not initialized.
72+ /// - Packed drops: Places might in general be misaligned - in most cases this is UB, the exception
73+ /// is fields of packed structs. In analysis MIR, `Drop(P)` for a `P` that might be misaligned
74+ /// for this reason implicitly moves `P` to a temporary before dropping. Runtime MIR has no such
75+ /// rules, and dropping a misaligned place is simply UB.
76+ /// - Unwinding: in analysis MIR, unwinding from a function which may not unwind aborts. In runtime
77+ /// MIR, this is UB.
78+ /// - Retags: If `-Zmir-emit-retag` is enabled, analysis MIR has "implicit" retags in the same way
79+ /// that Rust itself has them. Where exactly these are is generally subject to change, and so we
80+ /// don't document this here. Runtime MIR has all retags explicit.
81+ /// - Generator bodies: In analysis MIR, locals may actually be behind a pointer that user code has
82+ /// access to. This occurs in generator bodies. Such locals do not behave like other locals,
83+ /// because they eg may be aliased in surprising ways. Runtime MIR has no such special locals -
84+ /// all generator bodies are lowered and so all places that look like locals really are locals.
85+ /// - Const prop lints: The lint pass which reports eg `200_u8 + 200_u8` as an error is run as a
86+ /// part of analysis to runtime MIR lowering. This means that transformations which may supress
87+ /// such errors may not run on analysis MIR.
88+ Runtime ( RuntimePhase ) ,
89+ }
90+
91+ /// See [`MirPhase::Analysis`].
92+ #[ derive( Copy , Clone , TyEncodable , TyDecodable , Debug , PartialEq , Eq , PartialOrd , Ord ) ]
93+ #[ derive( HashStable ) ]
94+ pub enum AnalysisPhase {
95+ Initial = 0 ,
96+ /// Beginning in this phase, the following variants are disallowed:
6097 /// * [`TerminatorKind::FalseUnwind`]
6198 /// * [`TerminatorKind::FalseEdge`]
6299 /// * [`StatementKind::FakeRead`]
63100 /// * [`StatementKind::AscribeUserType`]
64101 /// * [`Rvalue::Ref`] with `BorrowKind::Shallow`
65102 ///
66- /// And the following variant is allowed:
67- /// * [`StatementKind::Retag`]
68- ///
69- /// Furthermore, `Drop` now uses explicit drop flags visible in the MIR and reaching a `Drop`
70- /// terminator means that the auto-generated drop glue will be invoked. Also, `Copy` operands
71- /// are allowed for non-`Copy` types.
72- DropsLowered = 4 ,
73- /// Beginning with this phase, the following variant is disallowed:
103+ /// Furthermore, `Deref` projections must be the first projection within any place (if they
104+ /// appear at all)
105+ PostCleanup = 1 ,
106+ }
107+
108+ /// See [`MirPhase::Runtime`].
109+ #[ derive( Copy , Clone , TyEncodable , TyDecodable , Debug , PartialEq , Eq , PartialOrd , Ord ) ]
110+ #[ derive( HashStable ) ]
111+ pub enum RuntimePhase {
112+ /// In addition to the semantic changes, beginning with this phase, the following variants are
113+ /// disallowed:
114+ /// * [`TerminatorKind::DropAndReplace`]
115+ /// * [`TerminatorKind::Yield`]
116+ /// * [`TerminatorKind::GeneratorDrop`]
74117 /// * [`Rvalue::Aggregate`] for any `AggregateKind` except `Array`
75118 ///
76- /// And the following variant is allowed:
119+ /// And the following variants are allowed:
120+ /// * [`StatementKind::Retag`]
77121 /// * [`StatementKind::SetDiscriminant`]
78- Deaggregated = 5 ,
79- /// Before this phase, generators are in the "source code" form, featuring `yield` statements
80- /// and such. With this phase change, they are transformed into a proper state machine. Running
81- /// optimizations before this change can be potentially dangerous because the source code is to
82- /// some extent a "lie." In particular, `yield` terminators effectively make the value of all
83- /// locals visible to the caller. This means that dead store elimination before them, or code
84- /// motion across them, is not correct in general. This is also exasperated by type checking
85- /// having pre-computed a list of the types that it thinks are ok to be live across a yield
86- /// point - this is necessary to decide eg whether autotraits are implemented. Introducing new
87- /// types across a yield point will lead to ICEs becaues of this.
88- ///
89- /// Beginning with this phase, the following variants are disallowed:
90- /// * [`TerminatorKind::Yield`]
91- /// * [`TerminatorKind::GeneratorDrop`]
122+ /// * [`StatementKind::Deinit`]
123+ ///
124+ /// Furthermore, `Copy` operands are allowed for non-`Copy` types.
125+ Initial = 0 ,
126+ /// Beginning with this phase, the following variant is disallowed:
92127 /// * [`ProjectionElem::Deref`] of `Box`
93- GeneratorsLowered = 6 ,
94- Optimized = 7 ,
128+ PostCleanup = 1 ,
129+ Optimized = 2 ,
95130}
96131
97132///////////////////////////////////////////////////////////////////////////
0 commit comments