@@ -23,75 +23,110 @@ use rustc_span::symbol::Symbol;
23
23
use rustc_span:: Span ;
24
24
use rustc_target:: asm:: InlineAsmRegOrRegClass ;
25
25
26
- /// The various "big phases" that MIR goes through .
26
+ /// Represents the "flavors" of MIR.
27
27
///
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.
32
30
///
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`].
34
42
#[ derive( Copy , Clone , TyEncodable , TyDecodable , Debug , PartialEq , Eq , PartialOrd , Ord ) ]
35
43
#[ derive( HashStable ) ]
36
44
pub 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:
60
97
/// * [`TerminatorKind::FalseUnwind`]
61
98
/// * [`TerminatorKind::FalseEdge`]
62
99
/// * [`StatementKind::FakeRead`]
63
100
/// * [`StatementKind::AscribeUserType`]
64
101
/// * [`Rvalue::Ref`] with `BorrowKind::Shallow`
65
102
///
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`]
74
117
/// * [`Rvalue::Aggregate`] for any `AggregateKind` except `Array`
75
118
///
76
- /// And the following variant is allowed:
119
+ /// And the following variants are allowed:
120
+ /// * [`StatementKind::Retag`]
77
121
/// * [`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:
92
127
/// * [`ProjectionElem::Deref`] of `Box`
93
- GeneratorsLowered = 6 ,
94
- Optimized = 7 ,
128
+ PostCleanup = 1 ,
129
+ Optimized = 2 ,
95
130
}
96
131
97
132
///////////////////////////////////////////////////////////////////////////
0 commit comments