blob: 3e474c1d377e64001146ecd617624b1b672b2347 [file] [log] [blame]
Chariseeb1d32802022-09-22 15:38:41 +00001//! This defines the syntax of MIR, i.e., the set of available MIR operations, and other definitions
2//! closely related to MIR semantics.
3//! This is in a dedicated file so that changes to this file can be reviewed more carefully.
4//! The intention is that this file only contains datatype declarations, no code.
5
Charisee635618d2023-06-01 20:46:00 +00006use super::{BasicBlock, Constant, Local, SwitchTargets, UserTypeProjection};
Chariseeb1d32802022-09-22 15:38:41 +00007
8use crate::mir::coverage::{CodeRegion, CoverageKind};
Chris Wailes977026a2023-02-13 09:13:10 -08009use crate::traits::Reveal;
Chariseeb1d32802022-09-22 15:38:41 +000010use crate::ty::adjustment::PointerCast;
11use crate::ty::subst::SubstsRef;
12use crate::ty::{self, List, Ty};
13use crate::ty::{Region, UserTypeAnnotationIndex};
14
15use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
16use rustc_hir::def_id::DefId;
17use rustc_hir::{self as hir};
18use rustc_hir::{self, GeneratorKind};
Chris Wailescd1aefd2023-07-13 13:36:21 -070019use rustc_index::IndexVec;
Charisee635618d2023-06-01 20:46:00 +000020use rustc_target::abi::{FieldIdx, VariantIdx};
Chariseeb1d32802022-09-22 15:38:41 +000021
22use rustc_ast::Mutability;
23use rustc_span::def_id::LocalDefId;
24use rustc_span::symbol::Symbol;
25use rustc_span::Span;
26use rustc_target::asm::InlineAsmRegOrRegClass;
27
Chris Wailes2f380c12022-11-09 13:04:22 -080028/// Represents the "flavors" of MIR.
Chariseeb1d32802022-09-22 15:38:41 +000029///
Chris Wailes2f380c12022-11-09 13:04:22 -080030/// All flavors of MIR use the same data structure, but there are some important differences. These
31/// differences come in two forms: Dialects and phases.
Chariseeb1d32802022-09-22 15:38:41 +000032///
Chris Wailes2f380c12022-11-09 13:04:22 -080033/// Dialects represent a stronger distinction than phases. This is because the transitions between
34/// dialects are semantic changes, and therefore technically *lowerings* between distinct IRs. In
35/// other words, the same [`Body`](crate::mir::Body) might be well-formed for multiple dialects, but
36/// have different semantic meaning and different behavior at runtime.
37///
38/// Each dialect additionally has a number of phases. However, phase changes never involve semantic
39/// changes. If some MIR is well-formed both before and after a phase change, it is also guaranteed
40/// that it has the same semantic meaning. In this sense, phase changes can only add additional
41/// restrictions on what MIR is well-formed.
42///
43/// When adding phases, remember to update [`MirPhase::phase_index`].
Chariseeb1d32802022-09-22 15:38:41 +000044#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)]
45#[derive(HashStable)]
46pub enum MirPhase {
Chris Wailes2f380c12022-11-09 13:04:22 -080047 /// The MIR that is generated by MIR building.
Chariseeb1d32802022-09-22 15:38:41 +000048 ///
Chris Wailes2f380c12022-11-09 13:04:22 -080049 /// The only things that operate on this dialect are unsafeck, the various MIR lints, and const
50 /// qualifs.
51 ///
52 /// This has no distinct phases.
53 Built,
54 /// The MIR used for most analysis.
55 ///
56 /// The only semantic change between analysis and built MIR is constant promotion. In built MIR,
57 /// sequences of statements that would generally be subject to constant promotion are
58 /// semantically constants, while in analysis MIR all constants are explicit.
59 ///
60 /// The result of const promotion is available from the `mir_promoted` and `promoted_mir` queries.
61 ///
62 /// This is the version of MIR used by borrowck and friends.
63 Analysis(AnalysisPhase),
64 /// The MIR used for CTFE, optimizations, and codegen.
65 ///
66 /// The semantic changes that occur in the lowering from analysis to runtime MIR are as follows:
67 ///
68 /// - Drops: In analysis MIR, `Drop` terminators represent *conditional* drops; roughly speaking,
69 /// if dataflow analysis determines that the place being dropped is uninitialized, the drop will
70 /// not be executed. The exact semantics of this aren't written down anywhere, which means they
71 /// are essentially "what drop elaboration does." In runtime MIR, the drops are unconditional;
72 /// when a `Drop` terminator is reached, if the type has drop glue that drop glue is always
73 /// executed. This may be UB if the underlying place is not initialized.
74 /// - Packed drops: Places might in general be misaligned - in most cases this is UB, the exception
75 /// is fields of packed structs. In analysis MIR, `Drop(P)` for a `P` that might be misaligned
76 /// for this reason implicitly moves `P` to a temporary before dropping. Runtime MIR has no such
77 /// rules, and dropping a misaligned place is simply UB.
78 /// - Unwinding: in analysis MIR, unwinding from a function which may not unwind aborts. In runtime
79 /// MIR, this is UB.
80 /// - Retags: If `-Zmir-emit-retag` is enabled, analysis MIR has "implicit" retags in the same way
81 /// that Rust itself has them. Where exactly these are is generally subject to change, and so we
Charisee635618d2023-06-01 20:46:00 +000082 /// don't document this here. Runtime MIR has most retags explicit (though implicit retags
83 /// can still occur at `Rvalue::{Ref,AddrOf}`).
Chris Wailes2f380c12022-11-09 13:04:22 -080084 /// - Generator bodies: In analysis MIR, locals may actually be behind a pointer that user code has
85 /// access to. This occurs in generator bodies. Such locals do not behave like other locals,
86 /// because they eg may be aliased in surprising ways. Runtime MIR has no such special locals -
87 /// all generator bodies are lowered and so all places that look like locals really are locals.
Chariseef7ad1c42023-01-30 22:46:42 +000088 ///
89 /// Also note that the lint pass which reports eg `200_u8 + 200_u8` as an error is run as a part
90 /// of analysis to runtime MIR lowering. To ensure lints are reported reliably, this means that
Chris Wailes977026a2023-02-13 09:13:10 -080091 /// transformations which may suppress such errors should not run on analysis MIR.
Chris Wailes2f380c12022-11-09 13:04:22 -080092 Runtime(RuntimePhase),
93}
94
Chris Wailes977026a2023-02-13 09:13:10 -080095impl MirPhase {
96 pub fn name(&self) -> &'static str {
97 match *self {
98 MirPhase::Built => "built",
99 MirPhase::Analysis(AnalysisPhase::Initial) => "analysis",
100 MirPhase::Analysis(AnalysisPhase::PostCleanup) => "analysis-post-cleanup",
101 MirPhase::Runtime(RuntimePhase::Initial) => "runtime",
102 MirPhase::Runtime(RuntimePhase::PostCleanup) => "runtime-post-cleanup",
103 MirPhase::Runtime(RuntimePhase::Optimized) => "runtime-optimized",
104 }
105 }
106
107 pub fn reveal(&self) -> Reveal {
108 match *self {
109 MirPhase::Built | MirPhase::Analysis(_) => Reveal::UserFacing,
110 MirPhase::Runtime(_) => Reveal::All,
111 }
112 }
113}
114
Chris Wailes2f380c12022-11-09 13:04:22 -0800115/// See [`MirPhase::Analysis`].
116#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)]
117#[derive(HashStable)]
118pub enum AnalysisPhase {
119 Initial = 0,
120 /// Beginning in this phase, the following variants are disallowed:
Chariseeb1d32802022-09-22 15:38:41 +0000121 /// * [`TerminatorKind::FalseUnwind`]
122 /// * [`TerminatorKind::FalseEdge`]
123 /// * [`StatementKind::FakeRead`]
124 /// * [`StatementKind::AscribeUserType`]
125 /// * [`Rvalue::Ref`] with `BorrowKind::Shallow`
126 ///
Chris Wailes2f380c12022-11-09 13:04:22 -0800127 /// Furthermore, `Deref` projections must be the first projection within any place (if they
128 /// appear at all)
129 PostCleanup = 1,
130}
131
132/// See [`MirPhase::Runtime`].
133#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)]
134#[derive(HashStable)]
135pub enum RuntimePhase {
136 /// In addition to the semantic changes, beginning with this phase, the following variants are
137 /// disallowed:
Chariseeb1d32802022-09-22 15:38:41 +0000138 /// * [`TerminatorKind::Yield`]
139 /// * [`TerminatorKind::GeneratorDrop`]
Chris Wailes2f380c12022-11-09 13:04:22 -0800140 /// * [`Rvalue::Aggregate`] for any `AggregateKind` except `Array`
141 ///
142 /// And the following variants are allowed:
143 /// * [`StatementKind::Retag`]
144 /// * [`StatementKind::SetDiscriminant`]
145 /// * [`StatementKind::Deinit`]
146 ///
147 /// Furthermore, `Copy` operands are allowed for non-`Copy` types.
148 Initial = 0,
149 /// Beginning with this phase, the following variant is disallowed:
Chariseeb1d32802022-09-22 15:38:41 +0000150 /// * [`ProjectionElem::Deref`] of `Box`
Chris Wailes2f380c12022-11-09 13:04:22 -0800151 PostCleanup = 1,
152 Optimized = 2,
Chariseeb1d32802022-09-22 15:38:41 +0000153}
154
155///////////////////////////////////////////////////////////////////////////
156// Borrow kinds
157
158#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, TyEncodable, TyDecodable)]
159#[derive(Hash, HashStable)]
160pub enum BorrowKind {
161 /// Data must be immutable and is aliasable.
162 Shared,
163
164 /// The immediately borrowed place must be immutable, but projections from
165 /// it don't need to be. For example, a shallow borrow of `a.b` doesn't
166 /// conflict with a mutable borrow of `a.b.c`.
167 ///
168 /// This is used when lowering matches: when matching on a place we want to
169 /// ensure that place have the same value from the start of the match until
170 /// an arm is selected. This prevents this code from compiling:
171 /// ```compile_fail,E0510
172 /// let mut x = &Some(0);
173 /// match *x {
174 /// None => (),
175 /// Some(_) if { x = &None; false } => (),
176 /// Some(_) => (),
177 /// }
178 /// ```
179 /// This can't be a shared borrow because mutably borrowing (*x as Some).0
180 /// should not prevent `if let None = x { ... }`, for example, because the
181 /// mutating `(*x as Some).0` can't affect the discriminant of `x`.
182 /// We can also report errors with this kind of borrow differently.
183 Shallow,
184
185 /// Data must be immutable but not aliasable. This kind of borrow
186 /// cannot currently be expressed by the user and is used only in
187 /// implicit closure bindings. It is needed when the closure is
188 /// borrowing or mutating a mutable referent, e.g.:
189 /// ```
190 /// let mut z = 3;
191 /// let x: &mut isize = &mut z;
192 /// let y = || *x += 5;
193 /// ```
194 /// If we were to try to translate this closure into a more explicit
195 /// form, we'd encounter an error with the code as written:
196 /// ```compile_fail,E0594
197 /// struct Env<'a> { x: &'a &'a mut isize }
198 /// let mut z = 3;
199 /// let x: &mut isize = &mut z;
200 /// let y = (&mut Env { x: &x }, fn_ptr); // Closure is pair of env and fn
201 /// fn fn_ptr(env: &mut Env) { **env.x += 5; }
202 /// ```
203 /// This is then illegal because you cannot mutate an `&mut` found
204 /// in an aliasable location. To solve, you'd have to translate with
205 /// an `&mut` borrow:
206 /// ```compile_fail,E0596
207 /// struct Env<'a> { x: &'a mut &'a mut isize }
208 /// let mut z = 3;
209 /// let x: &mut isize = &mut z;
210 /// let y = (&mut Env { x: &mut x }, fn_ptr); // changed from &x to &mut x
211 /// fn fn_ptr(env: &mut Env) { **env.x += 5; }
212 /// ```
213 /// Now the assignment to `**env.x` is legal, but creating a
214 /// mutable pointer to `x` is not because `x` is not mutable. We
215 /// could fix this by declaring `x` as `let mut x`. This is ok in
216 /// user code, if awkward, but extra weird for closures, since the
217 /// borrow is hidden.
218 ///
219 /// So we introduce a "unique imm" borrow -- the referent is
220 /// immutable, but not aliasable. This solves the problem. For
221 /// simplicity, we don't give users the way to express this
222 /// borrow, it's just used when translating closures.
Charisee635618d2023-06-01 20:46:00 +0000223 ///
224 // FIXME(#112072): This is wrong. Unique borrows are mutable borrows except
225 // that they do not require their pointee to be marked as a mutable.
226 // They should still be treated as mutable borrows in every other way,
227 // e.g. for variance or overlap checking.
Chariseeb1d32802022-09-22 15:38:41 +0000228 Unique,
229
230 /// Data is mutable and not aliasable.
231 Mut {
232 /// `true` if this borrow arose from method-call auto-ref
233 /// (i.e., `adjustment::Adjust::Borrow`).
234 allow_two_phase_borrow: bool,
235 },
236}
237
238///////////////////////////////////////////////////////////////////////////
239// Statements
240
241/// The various kinds of statements that can appear in MIR.
242///
243/// Not all of these are allowed at every [`MirPhase`]. Check the documentation there to see which
244/// ones you do not have to worry about. The MIR validator will generally enforce such restrictions,
245/// causing an ICE if they are violated.
246#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
247#[derive(TypeFoldable, TypeVisitable)]
248pub enum StatementKind<'tcx> {
249 /// Assign statements roughly correspond to an assignment in Rust proper (`x = ...`) except
250 /// without the possibility of dropping the previous value (that must be done separately, if at
251 /// all). The *exact* way this works is undecided. It probably does something like evaluating
252 /// the LHS to a place and the RHS to a value, and then storing the value to the place. Various
253 /// parts of this may do type specific things that are more complicated than simply copying
254 /// bytes.
255 ///
256 /// **Needs clarification**: The implication of the above idea would be that assignment implies
257 /// that the resulting value is initialized. I believe we could commit to this separately from
258 /// committing to whatever part of the memory model we would need to decide on to make the above
Chris Wailescd1aefd2023-07-13 13:36:21 -0700259 /// paragraph precise. Do we want to?
Chariseeb1d32802022-09-22 15:38:41 +0000260 ///
261 /// Assignments in which the types of the place and rvalue differ are not well-formed.
262 ///
263 /// **Needs clarification**: Do we ever want to worry about non-free (in the body) lifetimes for
264 /// the typing requirement in post drop-elaboration MIR? I think probably not - I'm not sure we
265 /// could meaningfully require this anyway. How about free lifetimes? Is ignoring this
266 /// interesting for optimizations? Do we want to allow such optimizations?
267 ///
268 /// **Needs clarification**: We currently require that the LHS place not overlap with any place
269 /// read as part of computation of the RHS for some rvalues (generally those not producing
270 /// primitives). This requirement is under discussion in [#68364]. As a part of this discussion,
271 /// it is also unclear in what order the components are evaluated.
272 ///
273 /// [#68364]: https://github.com/rust-lang/rust/issues/68364
274 ///
275 /// See [`Rvalue`] documentation for details on each of those.
276 Assign(Box<(Place<'tcx>, Rvalue<'tcx>)>),
277
278 /// This represents all the reading that a pattern match may do (e.g., inspecting constants and
279 /// discriminant values), and the kind of pattern it comes from. This is in order to adapt
280 /// potential error messages to these specific patterns.
281 ///
282 /// Note that this also is emitted for regular `let` bindings to ensure that locals that are
283 /// never accessed still get some sanity checks for, e.g., `let x: ! = ..;`
284 ///
285 /// When executed at runtime this is a nop.
286 ///
287 /// Disallowed after drop elaboration.
288 FakeRead(Box<(FakeReadCause, Place<'tcx>)>),
289
290 /// Write the discriminant for a variant to the enum Place.
291 ///
292 /// This is permitted for both generators and ADTs. This does not necessarily write to the
293 /// entire place; instead, it writes to the minimum set of bytes as required by the layout for
294 /// the type.
295 SetDiscriminant { place: Box<Place<'tcx>>, variant_index: VariantIdx },
296
297 /// Deinitializes the place.
298 ///
299 /// This writes `uninit` bytes to the entire place.
300 Deinit(Box<Place<'tcx>>),
301
302 /// `StorageLive` and `StorageDead` statements mark the live range of a local.
303 ///
304 /// At any point during the execution of a function, each local is either allocated or
305 /// unallocated. Except as noted below, all locals except function parameters are initially
306 /// unallocated. `StorageLive` statements cause memory to be allocated for the local while
307 /// `StorageDead` statements cause the memory to be freed. Using a local in any way (not only
308 /// reading/writing from it) while it is unallocated is UB.
309 ///
310 /// Some locals have no `StorageLive` or `StorageDead` statements within the entire MIR body.
311 /// These locals are implicitly allocated for the full duration of the function. There is a
312 /// convenience method at `rustc_mir_dataflow::storage::always_storage_live_locals` for
313 /// computing these locals.
314 ///
315 /// If the local is already allocated, calling `StorageLive` again is UB. However, for an
316 /// unallocated local an additional `StorageDead` all is simply a nop.
317 StorageLive(Local),
318
319 /// See `StorageLive` above.
320 StorageDead(Local),
321
322 /// Retag references in the given place, ensuring they got fresh tags.
323 ///
324 /// This is part of the Stacked Borrows model. These statements are currently only interpreted
325 /// by miri and only generated when `-Z mir-emit-retag` is passed. See
326 /// <https://internals.rust-lang.org/t/stacked-borrows-an-aliasing-model-for-rust/8153/> for
327 /// more details.
328 ///
Chariseed720b3f2023-03-09 17:35:07 +0000329 /// For code that is not specific to stacked borrows, you should consider retags to read and
330 /// modify the place in an opaque way.
331 ///
332 /// Only `RetagKind::Default` and `RetagKind::FnEntry` are permitted.
Chariseeb1d32802022-09-22 15:38:41 +0000333 Retag(RetagKind, Box<Place<'tcx>>),
334
Charisee635618d2023-06-01 20:46:00 +0000335 /// This statement exists to preserve a trace of a scrutinee matched against a wildcard binding.
336 /// This is especially useful for `let _ = PLACE;` bindings that desugar to a single
337 /// `PlaceMention(PLACE)`.
338 ///
Chris Wailescd1aefd2023-07-13 13:36:21 -0700339 /// When executed at runtime, this computes the given place, but then discards
340 /// it without doing a load. It is UB if the place is not pointing to live memory.
Charisee635618d2023-06-01 20:46:00 +0000341 PlaceMention(Box<Place<'tcx>>),
342
Chariseeb1d32802022-09-22 15:38:41 +0000343 /// Encodes a user's type ascription. These need to be preserved
344 /// intact so that NLL can respect them. For example:
345 /// ```ignore (illustrative)
346 /// let a: T = y;
347 /// ```
348 /// The effect of this annotation is to relate the type `T_y` of the place `y`
349 /// to the user-given type `T`. The effect depends on the specified variance:
350 ///
351 /// - `Covariant` -- requires that `T_y <: T`
352 /// - `Contravariant` -- requires that `T_y :> T`
353 /// - `Invariant` -- requires that `T_y == T`
354 /// - `Bivariant` -- no effect
355 ///
356 /// When executed at runtime this is a nop.
357 ///
358 /// Disallowed after drop elaboration.
359 AscribeUserType(Box<(Place<'tcx>, UserTypeProjection)>, ty::Variance),
360
361 /// Marks the start of a "coverage region", injected with '-Cinstrument-coverage'. A
362 /// `Coverage` statement carries metadata about the coverage region, used to inject a coverage
363 /// map into the binary. If `Coverage::kind` is a `Counter`, the statement also generates
364 /// executable code, to increment a counter variable at runtime, each time the code region is
365 /// executed.
366 Coverage(Box<Coverage>),
367
Chris Wailes2f380c12022-11-09 13:04:22 -0800368 /// Denotes a call to an intrinsic that does not require an unwind path and always returns.
369 /// This avoids adding a new block and a terminator for simple intrinsics.
370 Intrinsic(Box<NonDivergingIntrinsic<'tcx>>),
371
Chris Wailes5c0824a2023-04-24 16:30:59 -0700372 /// Instructs the const eval interpreter to increment a counter; this counter is used to track
373 /// how many steps the interpreter has taken. It is used to prevent the user from writing const
374 /// code that runs for too long or infinitely. Other than in the const eval interpreter, this
375 /// is a no-op.
376 ConstEvalCounter,
377
Chris Wailes2f380c12022-11-09 13:04:22 -0800378 /// No-op. Useful for deleting instructions without affecting statement indices.
379 Nop,
380}
381
382#[derive(
383 Clone,
384 TyEncodable,
385 TyDecodable,
386 Debug,
387 PartialEq,
388 Hash,
389 HashStable,
390 TypeFoldable,
391 TypeVisitable
392)]
393pub enum NonDivergingIntrinsic<'tcx> {
394 /// Denotes a call to the intrinsic function `assume`.
395 ///
396 /// The operand must be a boolean. Optimizers may use the value of the boolean to backtrack its
397 /// computation to infer information about other variables. So if the boolean came from a
398 /// `x < y` operation, subsequent operations on `x` and `y` could elide various bound checks.
399 /// If the argument is `false`, this operation is equivalent to `TerminatorKind::Unreachable`.
400 Assume(Operand<'tcx>),
401
Chariseeb1d32802022-09-22 15:38:41 +0000402 /// Denotes a call to the intrinsic function `copy_nonoverlapping`.
403 ///
404 /// First, all three operands are evaluated. `src` and `dest` must each be a reference, pointer,
405 /// or `Box` pointing to the same type `T`. `count` must evaluate to a `usize`. Then, `src` and
406 /// `dest` are dereferenced, and `count * size_of::<T>()` bytes beginning with the first byte of
Chris Wailes2f380c12022-11-09 13:04:22 -0800407 /// the `src` place are copied to the contiguous range of bytes beginning with the first byte
Chariseeb1d32802022-09-22 15:38:41 +0000408 /// of `dest`.
409 ///
410 /// **Needs clarification**: In what order are operands computed and dereferenced? It should
411 /// probably match the order for assignment, but that is also undecided.
412 ///
413 /// **Needs clarification**: Is this typed or not, ie is there a typed load and store involved?
414 /// I vaguely remember Ralf saying somewhere that he thought it should not be.
Chris Wailes2f380c12022-11-09 13:04:22 -0800415 CopyNonOverlapping(CopyNonOverlapping<'tcx>),
416}
Chariseeb1d32802022-09-22 15:38:41 +0000417
Chris Wailes2f380c12022-11-09 13:04:22 -0800418impl std::fmt::Display for NonDivergingIntrinsic<'_> {
419 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
420 match self {
421 Self::Assume(op) => write!(f, "assume({op:?})"),
422 Self::CopyNonOverlapping(CopyNonOverlapping { src, dst, count }) => {
423 write!(f, "copy_nonoverlapping(dst = {dst:?}, src = {src:?}, count = {count:?})")
424 }
425 }
426 }
Chariseeb1d32802022-09-22 15:38:41 +0000427}
428
429/// Describes what kind of retag is to be performed.
430#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, Hash, HashStable)]
431#[rustc_pass_by_value]
432pub enum RetagKind {
Chris Wailes977026a2023-02-13 09:13:10 -0800433 /// The initial retag of arguments when entering a function.
Chariseeb1d32802022-09-22 15:38:41 +0000434 FnEntry,
435 /// Retag preparing for a two-phase borrow.
436 TwoPhase,
437 /// Retagging raw pointers.
438 Raw,
439 /// A "normal" retag.
440 Default,
441}
442
443/// The `FakeReadCause` describes the type of pattern why a FakeRead statement exists.
444#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, Hash, HashStable, PartialEq)]
445pub enum FakeReadCause {
446 /// Inject a fake read of the borrowed input at the end of each guards
447 /// code.
448 ///
449 /// This should ensure that you cannot change the variant for an enum while
450 /// you are in the midst of matching on it.
451 ForMatchGuard,
452
453 /// `let x: !; match x {}` doesn't generate any read of x so we need to
454 /// generate a read of x to check that it is initialized and safe.
455 ///
456 /// If a closure pattern matches a Place starting with an Upvar, then we introduce a
457 /// FakeRead for that Place outside the closure, in such a case this option would be
458 /// Some(closure_def_id).
459 /// Otherwise, the value of the optional LocalDefId will be None.
460 //
Chris Wailes2f380c12022-11-09 13:04:22 -0800461 // We can use LocalDefId here since fake read statements are removed
Chariseeb1d32802022-09-22 15:38:41 +0000462 // before codegen in the `CleanupNonCodegenStatements` pass.
463 ForMatchedPlace(Option<LocalDefId>),
464
465 /// A fake read of the RefWithinGuard version of a bind-by-value variable
466 /// in a match guard to ensure that its value hasn't change by the time
467 /// we create the OutsideGuard version.
468 ForGuardBinding,
469
470 /// Officially, the semantics of
471 ///
472 /// `let pattern = <expr>;`
473 ///
474 /// is that `<expr>` is evaluated into a temporary and then this temporary is
475 /// into the pattern.
476 ///
477 /// However, if we see the simple pattern `let var = <expr>`, we optimize this to
478 /// evaluate `<expr>` directly into the variable `var`. This is mostly unobservable,
479 /// but in some cases it can affect the borrow checker, as in #53695.
480 /// Therefore, we insert a "fake read" here to ensure that we get
481 /// appropriate errors.
482 ///
483 /// If a closure pattern matches a Place starting with an Upvar, then we introduce a
484 /// FakeRead for that Place outside the closure, in such a case this option would be
485 /// Some(closure_def_id).
486 /// Otherwise, the value of the optional DefId will be None.
487 ForLet(Option<LocalDefId>),
488
489 /// If we have an index expression like
490 ///
491 /// (*x)[1][{ x = y; 4}]
492 ///
493 /// then the first bounds check is invalidated when we evaluate the second
494 /// index expression. Thus we create a fake borrow of `x` across the second
495 /// indexer, which will cause a borrow check error.
496 ForIndex,
497}
498
499#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
500#[derive(TypeFoldable, TypeVisitable)]
501pub struct Coverage {
502 pub kind: CoverageKind,
503 pub code_region: Option<CodeRegion>,
504}
505
506#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
507#[derive(TypeFoldable, TypeVisitable)]
508pub struct CopyNonOverlapping<'tcx> {
509 pub src: Operand<'tcx>,
510 pub dst: Operand<'tcx>,
511 /// Number of elements to copy from src to dest, not bytes.
512 pub count: Operand<'tcx>,
513}
514
515///////////////////////////////////////////////////////////////////////////
516// Terminators
517
518/// The various kinds of terminators, representing ways of exiting from a basic block.
519///
520/// A note on unwinding: Panics may occur during the execution of some terminators. Depending on the
521/// `-C panic` flag, this may either cause the program to abort or the call stack to unwind. Such
Charisee635618d2023-06-01 20:46:00 +0000522/// terminators have a `unwind: UnwindAction` field on them. If stack unwinding occurs, then
523/// once the current function is reached, an action will be taken based on the `unwind` field.
524/// If the action is `Cleanup`, then the execution continues at the given basic block. If the
525/// action is `Continue` then no cleanup is performed, and the stack continues unwinding.
Chariseeb1d32802022-09-22 15:38:41 +0000526///
Charisee635618d2023-06-01 20:46:00 +0000527/// The basic block pointed to by a `Cleanup` unwind action must have its `cleanup` flag set.
528/// `cleanup` basic blocks have a couple restrictions:
529/// 1. All `unwind` fields in them must be `UnwindAction::Terminate` or `UnwindAction::Unreachable`.
530/// 2. `Return` terminators are not allowed in them. `Terminate` and `Resume` terminators are.
Chariseeb1d32802022-09-22 15:38:41 +0000531/// 3. All other basic blocks (in the current body) that are reachable from `cleanup` basic blocks
532/// must also be `cleanup`. This is a part of the type system and checked statically, so it is
533/// still an error to have such an edge in the CFG even if it's known that it won't be taken at
534/// runtime.
Chariseed720b3f2023-03-09 17:35:07 +0000535/// 4. The control flow between cleanup blocks must look like an upside down tree. Roughly
536/// speaking, this means that control flow that looks like a V is allowed, while control flow
537/// that looks like a W is not. This is necessary to ensure that landing pad information can be
538/// correctly codegened on MSVC. More precisely:
539///
540/// Begin with the standard control flow graph `G`. Modify `G` as follows: for any two cleanup
541/// vertices `u` and `v` such that `u` dominates `v`, contract `u` and `v` into a single vertex,
542/// deleting self edges and duplicate edges in the process. Now remove all vertices from `G`
543/// that are not cleanup vertices or are not reachable. The resulting graph must be an inverted
544/// tree, that is each vertex may have at most one successor and there may be no cycles.
Chris Wailes2f380c12022-11-09 13:04:22 -0800545#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, TypeFoldable, TypeVisitable)]
Chariseeb1d32802022-09-22 15:38:41 +0000546pub enum TerminatorKind<'tcx> {
547 /// Block has one successor; we continue execution there.
548 Goto { target: BasicBlock },
549
550 /// Switches based on the computed value.
551 ///
552 /// First, evaluates the `discr` operand. The type of the operand must be a signed or unsigned
553 /// integer, char, or bool, and must match the given type. Then, if the list of switch targets
554 /// contains the computed value, continues execution at the associated basic block. Otherwise,
555 /// continues execution at the "otherwise" basic block.
556 ///
557 /// Target values may not appear more than once.
558 SwitchInt {
559 /// The discriminant value being tested.
560 discr: Operand<'tcx>,
Chariseeb1d32802022-09-22 15:38:41 +0000561 targets: SwitchTargets,
562 },
563
564 /// Indicates that the landing pad is finished and that the process should continue unwinding.
565 ///
566 /// Like a return, this marks the end of this invocation of the function.
567 ///
568 /// Only permitted in cleanup blocks. `Resume` is not permitted with `-C unwind=abort` after
569 /// deaggregation runs.
570 Resume,
571
Charisee635618d2023-06-01 20:46:00 +0000572 /// Indicates that the landing pad is finished and that the process should terminate.
Chariseeb1d32802022-09-22 15:38:41 +0000573 ///
574 /// Used to prevent unwinding for foreign items or with `-C unwind=abort`. Only permitted in
575 /// cleanup blocks.
Charisee635618d2023-06-01 20:46:00 +0000576 Terminate,
Chariseeb1d32802022-09-22 15:38:41 +0000577
578 /// Returns from the function.
579 ///
580 /// Like function calls, the exact semantics of returns in Rust are unclear. Returning very
581 /// likely at least assigns the value currently in the return place (`_0`) to the place
582 /// specified in the associated `Call` terminator in the calling function, as if assigned via
583 /// `dest = move _0`. It might additionally do other things, like have side-effects in the
584 /// aliasing model.
585 ///
586 /// If the body is a generator body, this has slightly different semantics; it instead causes a
587 /// `GeneratorState::Returned(_0)` to be created (as if by an `Aggregate` rvalue) and assigned
588 /// to the return place.
589 Return,
590
591 /// Indicates a terminator that can never be reached.
592 ///
593 /// Executing this terminator is UB.
594 Unreachable,
595
596 /// The behavior of this statement differs significantly before and after drop elaboration.
Chariseeb1d32802022-09-22 15:38:41 +0000597 ///
Chariseed720b3f2023-03-09 17:35:07 +0000598 /// After drop elaboration: `Drop` terminators are a complete nop for types that have no drop
599 /// glue. For other types, `Drop` terminators behave exactly like a call to
600 /// `core::mem::drop_in_place` with a pointer to the given place.
601 ///
602 /// `Drop` before drop elaboration is a *conditional* execution of the drop glue. Specifically,
603 /// the `Drop` will be executed if...
Chariseeb1d32802022-09-22 15:38:41 +0000604 ///
605 /// **Needs clarification**: End of that sentence. This in effect should document the exact
606 /// behavior of drop elaboration. The following sounds vaguely right, but I'm not quite sure:
607 ///
608 /// > The drop glue is executed if, among all statements executed within this `Body`, an assignment to
609 /// > the place or one of its "parents" occurred more recently than a move out of it. This does not
610 /// > consider indirect assignments.
Chris Wailescd1aefd2023-07-13 13:36:21 -0700611 ///
612 /// The `replace` flag indicates whether this terminator was created as part of an assignment.
613 /// This should only be used for diagnostic purposes, and does not have any operational
614 /// meaning.
615 Drop { place: Place<'tcx>, target: BasicBlock, unwind: UnwindAction, replace: bool },
Chariseeb1d32802022-09-22 15:38:41 +0000616
617 /// Roughly speaking, evaluates the `func` operand and the arguments, and starts execution of
618 /// the referred to function. The operand types must match the argument types of the function.
619 /// The return place type must match the return type. The type of the `func` operand must be
620 /// callable, meaning either a function pointer, a function type, or a closure type.
621 ///
622 /// **Needs clarification**: The exact semantics of this. Current backends rely on `move`
623 /// operands not aliasing the return place. It is unclear how this is justified in MIR, see
624 /// [#71117].
625 ///
626 /// [#71117]: https://github.com/rust-lang/rust/issues/71117
627 Call {
628 /// The function that’s being called.
629 func: Operand<'tcx>,
630 /// Arguments the function is called with.
631 /// These are owned by the callee, which is free to modify them.
632 /// This allows the memory occupied by "by-value" arguments to be
633 /// reused across function calls without duplicating the contents.
634 args: Vec<Operand<'tcx>>,
635 /// Where the returned value will be written
636 destination: Place<'tcx>,
637 /// Where to go after this call returns. If none, the call necessarily diverges.
638 target: Option<BasicBlock>,
Charisee635618d2023-06-01 20:46:00 +0000639 /// Action to be taken if the call unwinds.
640 unwind: UnwindAction,
Chariseeb1d32802022-09-22 15:38:41 +0000641 /// `true` if this is from a call in HIR rather than from an overloaded
642 /// operator. True for overloaded function call.
643 from_hir_call: bool,
644 /// This `Span` is the span of the function, without the dot and receiver
645 /// (e.g. `foo(a, b)` in `x.foo(a, b)`
646 fn_span: Span,
647 },
648
649 /// Evaluates the operand, which must have type `bool`. If it is not equal to `expected`,
650 /// initiates a panic. Initiating a panic corresponds to a `Call` terminator with some
651 /// unspecified constant as the function to call, all the operands stored in the `AssertMessage`
652 /// as parameters, and `None` for the destination. Keep in mind that the `cleanup` path is not
653 /// necessarily executed even in the case of a panic, for example in `-C panic=abort`. If the
654 /// assertion does not fail, execution continues at the specified basic block.
Chris Wailes5c0824a2023-04-24 16:30:59 -0700655 ///
656 /// When overflow checking is disabled and this is run-time MIR (as opposed to compile-time MIR
657 /// that is used for CTFE), the following variants of this terminator behave as `goto target`:
658 /// - `OverflowNeg(..)`,
Charisee635618d2023-06-01 20:46:00 +0000659 /// - `Overflow(op, ..)` if op is add, sub, mul, shl, shr, but NOT div or rem.
Chariseeb1d32802022-09-22 15:38:41 +0000660 Assert {
661 cond: Operand<'tcx>,
662 expected: bool,
Chris Wailescd1aefd2023-07-13 13:36:21 -0700663 msg: Box<AssertMessage<'tcx>>,
Chariseeb1d32802022-09-22 15:38:41 +0000664 target: BasicBlock,
Charisee635618d2023-06-01 20:46:00 +0000665 unwind: UnwindAction,
Chariseeb1d32802022-09-22 15:38:41 +0000666 },
667
668 /// Marks a suspend point.
669 ///
670 /// Like `Return` terminators in generator bodies, this computes `value` and then a
671 /// `GeneratorState::Yielded(value)` as if by `Aggregate` rvalue. That value is then assigned to
672 /// the return place of the function calling this one, and execution continues in the calling
673 /// function. When next invoked with the same first argument, execution of this function
674 /// continues at the `resume` basic block, with the second argument written to the `resume_arg`
675 /// place. If the generator is dropped before then, the `drop` basic block is invoked.
676 ///
677 /// Not permitted in bodies that are not generator bodies, or after generator lowering.
678 ///
679 /// **Needs clarification**: What about the evaluation order of the `resume_arg` and `value`?
680 Yield {
681 /// The value to return.
682 value: Operand<'tcx>,
683 /// Where to resume to.
684 resume: BasicBlock,
685 /// The place to store the resume argument in.
686 resume_arg: Place<'tcx>,
687 /// Cleanup to be done if the generator is dropped at this suspend point.
688 drop: Option<BasicBlock>,
689 },
690
691 /// Indicates the end of dropping a generator.
692 ///
693 /// Semantically just a `return` (from the generators drop glue). Only permitted in the same situations
694 /// as `yield`.
695 ///
696 /// **Needs clarification**: Is that even correct? The generator drop code is always confusing
697 /// to me, because it's not even really in the current body.
698 ///
699 /// **Needs clarification**: Are there type system constraints on these terminators? Should
700 /// there be a "block type" like `cleanup` blocks for them?
701 GeneratorDrop,
702
703 /// A block where control flow only ever takes one real path, but borrowck needs to be more
704 /// conservative.
705 ///
706 /// At runtime this is semantically just a goto.
707 ///
708 /// Disallowed after drop elaboration.
709 FalseEdge {
710 /// The target normal control flow will take.
711 real_target: BasicBlock,
712 /// A block control flow could conceptually jump to, but won't in
713 /// practice.
714 imaginary_target: BasicBlock,
715 },
716
717 /// A terminator for blocks that only take one path in reality, but where we reserve the right
718 /// to unwind in borrowck, even if it won't happen in practice. This can arise in infinite loops
719 /// with no function calls for example.
720 ///
721 /// At runtime this is semantically just a goto.
722 ///
723 /// Disallowed after drop elaboration.
724 FalseUnwind {
725 /// The target normal control flow will take.
726 real_target: BasicBlock,
727 /// The imaginary cleanup block link. This particular path will never be taken
728 /// in practice, but in order to avoid fragility we want to always
729 /// consider it in borrowck. We don't want to accept programs which
730 /// pass borrowck only when `panic=abort` or some assertions are disabled
Charisee635618d2023-06-01 20:46:00 +0000731 /// due to release vs. debug mode builds.
732 unwind: UnwindAction,
Chariseeb1d32802022-09-22 15:38:41 +0000733 },
734
735 /// Block ends with an inline assembly block. This is a terminator since
736 /// inline assembly is allowed to diverge.
737 InlineAsm {
738 /// The template for the inline assembly, with placeholders.
739 template: &'tcx [InlineAsmTemplatePiece],
740
741 /// The operands for the inline assembly, as `Operand`s or `Place`s.
742 operands: Vec<InlineAsmOperand<'tcx>>,
743
744 /// Miscellaneous options for the inline assembly.
745 options: InlineAsmOptions,
746
747 /// Source spans for each line of the inline assembly code. These are
748 /// used to map assembler errors back to the line in the source code.
749 line_spans: &'tcx [Span],
750
751 /// Destination block after the inline assembly returns, unless it is
752 /// diverging (InlineAsmOptions::NORETURN).
753 destination: Option<BasicBlock>,
754
Charisee635618d2023-06-01 20:46:00 +0000755 /// Action to be taken if the inline assembly unwinds. This is present
Chariseeb1d32802022-09-22 15:38:41 +0000756 /// if and only if InlineAsmOptions::MAY_UNWIND is set.
Charisee635618d2023-06-01 20:46:00 +0000757 unwind: UnwindAction,
Chariseeb1d32802022-09-22 15:38:41 +0000758 },
759}
760
Chris Wailescd1aefd2023-07-13 13:36:21 -0700761impl TerminatorKind<'_> {
762 /// Returns a simple string representation of a `TerminatorKind` variant, independent of any
763 /// values it might hold (e.g. `TerminatorKind::Call` always returns `"Call"`).
764 pub const fn name(&self) -> &'static str {
765 match self {
766 TerminatorKind::Goto { .. } => "Goto",
767 TerminatorKind::SwitchInt { .. } => "SwitchInt",
768 TerminatorKind::Resume => "Resume",
769 TerminatorKind::Terminate => "Terminate",
770 TerminatorKind::Return => "Return",
771 TerminatorKind::Unreachable => "Unreachable",
772 TerminatorKind::Drop { .. } => "Drop",
773 TerminatorKind::Call { .. } => "Call",
774 TerminatorKind::Assert { .. } => "Assert",
775 TerminatorKind::Yield { .. } => "Yield",
776 TerminatorKind::GeneratorDrop => "GeneratorDrop",
777 TerminatorKind::FalseEdge { .. } => "FalseEdge",
778 TerminatorKind::FalseUnwind { .. } => "FalseUnwind",
779 TerminatorKind::InlineAsm { .. } => "InlineAsm",
780 }
781 }
782}
783
Charisee635618d2023-06-01 20:46:00 +0000784/// Action to be taken when a stack unwind happens.
785#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
786#[derive(TypeFoldable, TypeVisitable)]
787pub enum UnwindAction {
788 /// No action is to be taken. Continue unwinding.
789 ///
790 /// This is similar to `Cleanup(bb)` where `bb` does nothing but `Resume`, but they are not
791 /// equivalent, as presence of `Cleanup(_)` will make a frame non-POF.
792 Continue,
793 /// Triggers undefined behavior if unwind happens.
794 Unreachable,
795 /// Terminates the execution if unwind happens.
796 ///
797 /// Depending on the platform and situation this may cause a non-unwindable panic or abort.
798 Terminate,
799 /// Cleanups to be done.
800 Cleanup(BasicBlock),
801}
802
Chariseeb1d32802022-09-22 15:38:41 +0000803/// Information about an assertion failure.
Chris Wailes2f380c12022-11-09 13:04:22 -0800804#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, TypeFoldable, TypeVisitable)]
Chariseeb1d32802022-09-22 15:38:41 +0000805pub enum AssertKind<O> {
806 BoundsCheck { len: O, index: O },
807 Overflow(BinOp, O, O),
808 OverflowNeg(O),
809 DivisionByZero(O),
810 RemainderByZero(O),
811 ResumedAfterReturn(GeneratorKind),
812 ResumedAfterPanic(GeneratorKind),
Charisee635618d2023-06-01 20:46:00 +0000813 MisalignedPointerDereference { required: O, found: O },
Chariseeb1d32802022-09-22 15:38:41 +0000814}
815
816#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
817#[derive(TypeFoldable, TypeVisitable)]
818pub enum InlineAsmOperand<'tcx> {
819 In {
820 reg: InlineAsmRegOrRegClass,
821 value: Operand<'tcx>,
822 },
823 Out {
824 reg: InlineAsmRegOrRegClass,
825 late: bool,
826 place: Option<Place<'tcx>>,
827 },
828 InOut {
829 reg: InlineAsmRegOrRegClass,
830 late: bool,
831 in_value: Operand<'tcx>,
832 out_place: Option<Place<'tcx>>,
833 },
834 Const {
835 value: Box<Constant<'tcx>>,
836 },
837 SymFn {
838 value: Box<Constant<'tcx>>,
839 },
840 SymStatic {
841 def_id: DefId,
842 },
843}
844
845/// Type for MIR `Assert` terminator error messages.
846pub type AssertMessage<'tcx> = AssertKind<Operand<'tcx>>;
847
848///////////////////////////////////////////////////////////////////////////
849// Places
850
851/// Places roughly correspond to a "location in memory." Places in MIR are the same mathematical
852/// object as places in Rust. This of course means that what exactly they are is undecided and part
853/// of the Rust memory model. However, they will likely contain at least the following pieces of
854/// information in some form:
855///
856/// 1. The address in memory that the place refers to.
857/// 2. The provenance with which the place is being accessed.
858/// 3. The type of the place and an optional variant index. See [`PlaceTy`][super::tcx::PlaceTy].
859/// 4. Optionally, some metadata. This exists if and only if the type of the place is not `Sized`.
860///
861/// We'll give a description below of how all pieces of the place except for the provenance are
862/// calculated. We cannot give a description of the provenance, because that is part of the
863/// undecided aliasing model - we only include it here at all to acknowledge its existence.
864///
865/// Each local naturally corresponds to the place `Place { local, projection: [] }`. This place has
866/// the address of the local's allocation and the type of the local.
867///
868/// **Needs clarification:** Unsized locals seem to present a bit of an issue. Their allocation
869/// can't actually be created on `StorageLive`, because it's unclear how big to make the allocation.
870/// Furthermore, MIR produces assignments to unsized locals, although that is not permitted under
871/// `#![feature(unsized_locals)]` in Rust. Besides just putting "unsized locals are special and
872/// different" in a bunch of places, I (JakobDegen) don't know how to incorporate this behavior into
873/// the current MIR semantics in a clean way - possibly this needs some design work first.
874///
875/// For places that are not locals, ie they have a non-empty list of projections, we define the
876/// values as a function of the parent place, that is the place with its last [`ProjectionElem`]
877/// stripped. The way this is computed of course depends on the kind of that last projection
878/// element:
879///
880/// - [`Downcast`](ProjectionElem::Downcast): This projection sets the place's variant index to the
881/// given one, and makes no other changes. A `Downcast` projection on a place with its variant
882/// index already set is not well-formed.
883/// - [`Field`](ProjectionElem::Field): `Field` projections take their parent place and create a
884/// place referring to one of the fields of the type. The resulting address is the parent
885/// address, plus the offset of the field. The type becomes the type of the field. If the parent
886/// was unsized and so had metadata associated with it, then the metadata is retained if the
887/// field is unsized and thrown out if it is sized.
888///
889/// These projections are only legal for tuples, ADTs, closures, and generators. If the ADT or
890/// generator has more than one variant, the parent place's variant index must be set, indicating
891/// which variant is being used. If it has just one variant, the variant index may or may not be
892/// included - the single possible variant is inferred if it is not included.
Chariseef7ad1c42023-01-30 22:46:42 +0000893/// - [`OpaqueCast`](ProjectionElem::OpaqueCast): This projection changes the place's type to the
894/// given one, and makes no other changes. A `OpaqueCast` projection on any type other than an
895/// opaque type from the current crate is not well-formed.
Chariseeb1d32802022-09-22 15:38:41 +0000896/// - [`ConstantIndex`](ProjectionElem::ConstantIndex): Computes an offset in units of `T` into the
897/// place as described in the documentation for the `ProjectionElem`. The resulting address is
898/// the parent's address plus that offset, and the type is `T`. This is only legal if the parent
899/// place has type `[T; N]` or `[T]` (*not* `&[T]`). Since such a `T` is always sized, any
900/// resulting metadata is thrown out.
901/// - [`Subslice`](ProjectionElem::Subslice): This projection calculates an offset and a new
902/// address in a similar manner as `ConstantIndex`. It is also only legal on `[T; N]` and `[T]`.
903/// However, this yields a `Place` of type `[T]`, and additionally sets the metadata to be the
904/// length of the subslice.
905/// - [`Index`](ProjectionElem::Index): Like `ConstantIndex`, only legal on `[T; N]` or `[T]`.
906/// However, `Index` additionally takes a local from which the value of the index is computed at
907/// runtime. Computing the value of the index involves interpreting the `Local` as a
908/// `Place { local, projection: [] }`, and then computing its value as if done via
909/// [`Operand::Copy`]. The array/slice is then indexed with the resulting value. The local must
910/// have type `usize`.
911/// - [`Deref`](ProjectionElem::Deref): Derefs are the last type of projection, and the most
912/// complicated. They are only legal on parent places that are references, pointers, or `Box`. A
913/// `Deref` projection begins by loading a value from the parent place, as if by
914/// [`Operand::Copy`]. It then dereferences the resulting pointer, creating a place of the
915/// pointee's type. The resulting address is the address that was stored in the pointer. If the
916/// pointee type is unsized, the pointer additionally stored the value of the metadata.
917///
918/// Computing a place may cause UB. One possibility is that the pointer used for a `Deref` may not
919/// be suitably aligned. Another possibility is that the place is not in bounds, meaning it does not
920/// point to an actual allocation.
921///
922/// However, if this is actually UB and when the UB kicks in is undecided. This is being discussed
923/// in [UCG#319]. The options include that every place must obey those rules, that only some places
924/// must obey them, or that places impose no rules of their own.
925///
926/// [UCG#319]: https://github.com/rust-lang/unsafe-code-guidelines/issues/319
927///
928/// Rust currently requires that every place obey those two rules. This is checked by MIRI and taken
929/// advantage of by codegen (via `gep inbounds`). That is possibly subject to change.
Chris Wailes2f380c12022-11-09 13:04:22 -0800930#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, HashStable, TypeFoldable, TypeVisitable)]
Chariseeb1d32802022-09-22 15:38:41 +0000931pub struct Place<'tcx> {
932 pub local: Local,
933
934 /// projection out of a place (access a field, deref a pointer, etc)
935 pub projection: &'tcx List<PlaceElem<'tcx>>,
936}
937
938#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
Chris Wailes2f380c12022-11-09 13:04:22 -0800939#[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
Chariseeb1d32802022-09-22 15:38:41 +0000940pub enum ProjectionElem<V, T> {
941 Deref,
Charisee635618d2023-06-01 20:46:00 +0000942
943 /// A field (e.g., `f` in `_1.f`) is one variant of [`ProjectionElem`]. Conceptually,
944 /// rustc can identify that a field projection refers to either two different regions of memory
945 /// or the same one between the base and the 'projection element'.
946 /// Read more about projections in the [rustc-dev-guide][mir-datatypes]
947 ///
948 /// [mir-datatypes]: https://rustc-dev-guide.rust-lang.org/mir/index.html#mir-data-types
949 Field(FieldIdx, T),
950
Chariseeb1d32802022-09-22 15:38:41 +0000951 /// Index into a slice/array.
952 ///
953 /// Note that this does not also dereference, and so it does not exactly correspond to slice
954 /// indexing in Rust. In other words, in the below Rust code:
955 ///
956 /// ```rust
957 /// let x = &[1, 2, 3, 4];
958 /// let i = 2;
959 /// x[i];
960 /// ```
961 ///
962 /// The `x[i]` is turned into a `Deref` followed by an `Index`, not just an `Index`. The same
963 /// thing is true of the `ConstantIndex` and `Subslice` projections below.
964 Index(V),
965
966 /// These indices are generated by slice patterns. Easiest to explain
967 /// by example:
968 ///
969 /// ```ignore (illustrative)
970 /// [X, _, .._, _, _] => { offset: 0, min_length: 4, from_end: false },
971 /// [_, X, .._, _, _] => { offset: 1, min_length: 4, from_end: false },
972 /// [_, _, .._, X, _] => { offset: 2, min_length: 4, from_end: true },
973 /// [_, _, .._, _, X] => { offset: 1, min_length: 4, from_end: true },
974 /// ```
975 ConstantIndex {
976 /// index or -index (in Python terms), depending on from_end
977 offset: u64,
978 /// The thing being indexed must be at least this long. For arrays this
979 /// is always the exact length.
980 min_length: u64,
981 /// Counting backwards from end? This is always false when indexing an
982 /// array.
983 from_end: bool,
984 },
985
986 /// These indices are generated by slice patterns.
987 ///
988 /// If `from_end` is true `slice[from..slice.len() - to]`.
989 /// Otherwise `array[from..to]`.
990 Subslice {
991 from: u64,
992 to: u64,
993 /// Whether `to` counts from the start or end of the array/slice.
994 /// For `PlaceElem`s this is `true` if and only if the base is a slice.
995 /// For `ProjectionKind`, this can also be `true` for arrays.
996 from_end: bool,
997 },
998
999 /// "Downcast" to a variant of an enum or a generator.
1000 ///
1001 /// The included Symbol is the name of the variant, used for printing MIR.
1002 Downcast(Option<Symbol>, VariantIdx),
Chariseef7ad1c42023-01-30 22:46:42 +00001003
1004 /// Like an explicit cast from an opaque type to a concrete type, but without
1005 /// requiring an intermediate variable.
1006 OpaqueCast(T),
Chariseeb1d32802022-09-22 15:38:41 +00001007}
1008
1009/// Alias for projections as they appear in places, where the base is a place
1010/// and the index is a local.
1011pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
1012
1013///////////////////////////////////////////////////////////////////////////
1014// Operands
1015
1016/// An operand in MIR represents a "value" in Rust, the definition of which is undecided and part of
1017/// the memory model. One proposal for a definition of values can be found [on UCG][value-def].
1018///
1019/// [value-def]: https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/value-domain.md
1020///
1021/// The most common way to create values is via loading a place. Loading a place is an operation
1022/// which reads the memory of the place and converts it to a value. This is a fundamentally *typed*
1023/// operation. The nature of the value produced depends on the type of the conversion. Furthermore,
1024/// there may be other effects: if the type has a validity constraint loading the place might be UB
1025/// if the validity constraint is not met.
1026///
1027/// **Needs clarification:** Ralf proposes that loading a place not have side-effects.
1028/// This is what is implemented in miri today. Are these the semantics we want for MIR? Is this
1029/// something we can even decide without knowing more about Rust's memory model?
1030///
Chris Wailescd1aefd2023-07-13 13:36:21 -07001031/// **Needs clarification:** Is loading a place that has its variant index set well-formed? Miri
Chariseeb1d32802022-09-22 15:38:41 +00001032/// currently implements it, but it seems like this may be something to check against in the
1033/// validator.
Chris Wailes2f380c12022-11-09 13:04:22 -08001034#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
Chariseeb1d32802022-09-22 15:38:41 +00001035pub enum Operand<'tcx> {
1036 /// Creates a value by loading the given place.
1037 ///
1038 /// Before drop elaboration, the type of the place must be `Copy`. After drop elaboration there
1039 /// is no such requirement.
1040 Copy(Place<'tcx>),
1041
1042 /// Creates a value by performing loading the place, just like the `Copy` operand.
1043 ///
1044 /// This *may* additionally overwrite the place with `uninit` bytes, depending on how we decide
1045 /// in [UCG#188]. You should not emit MIR that may attempt a subsequent second load of this
1046 /// place without first re-initializing it.
1047 ///
1048 /// [UCG#188]: https://github.com/rust-lang/unsafe-code-guidelines/issues/188
1049 Move(Place<'tcx>),
1050
1051 /// Constants are already semantically values, and remain unchanged.
1052 Constant(Box<Constant<'tcx>>),
1053}
1054
1055///////////////////////////////////////////////////////////////////////////
1056// Rvalues
1057
1058/// The various kinds of rvalues that can appear in MIR.
1059///
1060/// Not all of these are allowed at every [`MirPhase`] - when this is the case, it's stated below.
1061///
1062/// Computing any rvalue begins by evaluating the places and operands in some order (**Needs
1063/// clarification**: Which order?). These are then used to produce a "value" - the same kind of
1064/// value that an [`Operand`] produces.
Chris Wailes2f380c12022-11-09 13:04:22 -08001065#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, TypeFoldable, TypeVisitable)]
Chariseeb1d32802022-09-22 15:38:41 +00001066pub enum Rvalue<'tcx> {
1067 /// Yields the operand unchanged
1068 Use(Operand<'tcx>),
1069
1070 /// Creates an array where each element is the value of the operand.
1071 ///
1072 /// This is the cause of a bug in the case where the repetition count is zero because the value
1073 /// is not dropped, see [#74836].
1074 ///
1075 /// Corresponds to source code like `[x; 32]`.
1076 ///
1077 /// [#74836]: https://github.com/rust-lang/rust/issues/74836
1078 Repeat(Operand<'tcx>, ty::Const<'tcx>),
1079
1080 /// Creates a reference of the indicated kind to the place.
1081 ///
1082 /// There is not much to document here, because besides the obvious parts the semantics of this
1083 /// are essentially entirely a part of the aliasing model. There are many UCG issues discussing
1084 /// exactly what the behavior of this operation should be.
1085 ///
1086 /// `Shallow` borrows are disallowed after drop lowering.
1087 Ref(Region<'tcx>, BorrowKind, Place<'tcx>),
1088
1089 /// Creates a pointer/reference to the given thread local.
1090 ///
1091 /// The yielded type is a `*mut T` if the static is mutable, otherwise if the static is extern a
1092 /// `*const T`, and if neither of those apply a `&T`.
1093 ///
1094 /// **Note:** This is a runtime operation that actually executes code and is in this sense more
1095 /// like a function call. Also, eliminating dead stores of this rvalue causes `fn main() {}` to
1096 /// SIGILL for some reason that I (JakobDegen) never got a chance to look into.
1097 ///
1098 /// **Needs clarification**: Are there weird additional semantics here related to the runtime
1099 /// nature of this operation?
1100 ThreadLocalRef(DefId),
1101
1102 /// Creates a pointer with the indicated mutability to the place.
1103 ///
1104 /// This is generated by pointer casts like `&v as *const _` or raw address of expressions like
1105 /// `&raw v` or `addr_of!(v)`.
1106 ///
1107 /// Like with references, the semantics of this operation are heavily dependent on the aliasing
1108 /// model.
1109 AddressOf(Mutability, Place<'tcx>),
1110
1111 /// Yields the length of the place, as a `usize`.
1112 ///
1113 /// If the type of the place is an array, this is the array length. For slices (`[T]`, not
1114 /// `&[T]`) this accesses the place's metadata to determine the length. This rvalue is
1115 /// ill-formed for places of other types.
1116 Len(Place<'tcx>),
1117
1118 /// Performs essentially all of the casts that can be performed via `as`.
1119 ///
1120 /// This allows for casts from/to a variety of types.
1121 ///
1122 /// **FIXME**: Document exactly which `CastKind`s allow which types of casts. Figure out why
1123 /// `ArrayToPointer` and `MutToConstPointer` are special.
1124 Cast(CastKind, Operand<'tcx>, Ty<'tcx>),
1125
1126 /// * `Offset` has the same semantics as [`offset`](pointer::offset), except that the second
1127 /// parameter may be a `usize` as well.
1128 /// * The comparison operations accept `bool`s, `char`s, signed or unsigned integers, floats,
1129 /// raw pointers, or function pointers and return a `bool`. The types of the operands must be
1130 /// matching, up to the usual caveat of the lifetimes in function pointers.
1131 /// * Left and right shift operations accept signed or unsigned integers not necessarily of the
1132 /// same type and return a value of the same type as their LHS. Like in Rust, the RHS is
1133 /// truncated as needed.
1134 /// * The `Bit*` operations accept signed integers, unsigned integers, or bools with matching
1135 /// types and return a value of that type.
1136 /// * The remaining operations accept signed integers, unsigned integers, or floats with
1137 /// matching types and return a value of that type.
1138 BinaryOp(BinOp, Box<(Operand<'tcx>, Operand<'tcx>)>),
1139
1140 /// Same as `BinaryOp`, but yields `(T, bool)` with a `bool` indicating an error condition.
1141 ///
Chariseeb1d32802022-09-22 15:38:41 +00001142 /// For addition, subtraction, and multiplication on integers the error condition is set when
Charisee635618d2023-06-01 20:46:00 +00001143 /// the infinite precision result would not be equal to the actual result.
Chariseeb1d32802022-09-22 15:38:41 +00001144 ///
1145 /// Other combinations of types and operators are unsupported.
1146 CheckedBinaryOp(BinOp, Box<(Operand<'tcx>, Operand<'tcx>)>),
1147
1148 /// Computes a value as described by the operation.
Chris Wailescd1aefd2023-07-13 13:36:21 -07001149 NullaryOp(NullOp<'tcx>, Ty<'tcx>),
Chariseeb1d32802022-09-22 15:38:41 +00001150
1151 /// Exactly like `BinaryOp`, but less operands.
1152 ///
1153 /// Also does two's-complement arithmetic. Negation requires a signed integer or a float;
1154 /// bitwise not requires a signed integer, unsigned integer, or bool. Both operation kinds
1155 /// return a value with the same type as their operand.
1156 UnaryOp(UnOp, Operand<'tcx>),
1157
1158 /// Computes the discriminant of the place, returning it as an integer of type
1159 /// [`discriminant_ty`]. Returns zero for types without discriminant.
1160 ///
1161 /// The validity requirements for the underlying value are undecided for this rvalue, see
1162 /// [#91095]. Note too that the value of the discriminant is not the same thing as the
1163 /// variant index; use [`discriminant_for_variant`] to convert.
1164 ///
1165 /// [`discriminant_ty`]: crate::ty::Ty::discriminant_ty
1166 /// [#91095]: https://github.com/rust-lang/rust/issues/91095
1167 /// [`discriminant_for_variant`]: crate::ty::Ty::discriminant_for_variant
1168 Discriminant(Place<'tcx>),
1169
1170 /// Creates an aggregate value, like a tuple or struct.
1171 ///
1172 /// This is needed because dataflow analysis needs to distinguish
1173 /// `dest = Foo { x: ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case that `Foo`
1174 /// has a destructor.
1175 ///
1176 /// Disallowed after deaggregation for all aggregate kinds except `Array` and `Generator`. After
1177 /// generator lowering, `Generator` aggregate kinds are disallowed too.
Charisee635618d2023-06-01 20:46:00 +00001178 Aggregate(Box<AggregateKind<'tcx>>, IndexVec<FieldIdx, Operand<'tcx>>),
Chariseeb1d32802022-09-22 15:38:41 +00001179
1180 /// Transmutes a `*mut u8` into shallow-initialized `Box<T>`.
1181 ///
1182 /// This is different from a normal transmute because dataflow analysis will treat the box as
1183 /// initialized but its content as uninitialized. Like other pointer casts, this in general
1184 /// affects alias analysis.
1185 ShallowInitBox(Operand<'tcx>, Ty<'tcx>),
1186
1187 /// A CopyForDeref is equivalent to a read from a place at the
1188 /// codegen level, but is treated specially by drop elaboration. When such a read happens, it
1189 /// is guaranteed (via nature of the mir_opt `Derefer` in rustc_mir_transform/src/deref_separator)
1190 /// that the only use of the returned value is a deref operation, immediately
1191 /// followed by one or more projections. Drop elaboration treats this rvalue as if the
1192 /// read never happened and just projects further. This allows simplifying various MIR
1193 /// optimizations and codegen backends that previously had to handle deref operations anywhere
1194 /// in a place.
1195 CopyForDeref(Place<'tcx>),
1196}
1197
1198#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
1199pub enum CastKind {
1200 /// An exposing pointer to address cast. A cast between a pointer and an integer type, or
1201 /// between a function pointer and an integer type.
1202 /// See the docs on `expose_addr` for more details.
1203 PointerExposeAddress,
1204 /// An address-to-pointer cast that picks up an exposed provenance.
1205 /// See the docs on `from_exposed_addr` for more details.
1206 PointerFromExposedAddress,
1207 /// All sorts of pointer-to-pointer casts. Note that reference-to-raw-ptr casts are
1208 /// translated into `&raw mut/const *r`, i.e., they are not actually casts.
1209 Pointer(PointerCast),
Chris Wailes2f380c12022-11-09 13:04:22 -08001210 /// Cast into a dyn* object.
1211 DynStar,
Chariseef7ad1c42023-01-30 22:46:42 +00001212 IntToInt,
1213 FloatToInt,
1214 FloatToFloat,
1215 IntToFloat,
1216 PtrToPtr,
1217 FnPtrToPtr,
Charisee635618d2023-06-01 20:46:00 +00001218 /// Reinterpret the bits of the input as a different type.
1219 ///
1220 /// MIR is well-formed if the input and output types have different sizes,
1221 /// but running a transmute between differently-sized types is UB.
1222 ///
1223 /// Allowed only in [`MirPhase::Runtime`]; Earlier it's a [`TerminatorKind::Call`].
1224 Transmute,
Chariseeb1d32802022-09-22 15:38:41 +00001225}
1226
1227#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
Chris Wailes2f380c12022-11-09 13:04:22 -08001228#[derive(TypeFoldable, TypeVisitable)]
Chariseeb1d32802022-09-22 15:38:41 +00001229pub enum AggregateKind<'tcx> {
1230 /// The type is of the element
1231 Array(Ty<'tcx>),
1232 Tuple,
1233
1234 /// The second field is the variant index. It's equal to 0 for struct
Charisee635618d2023-06-01 20:46:00 +00001235 /// and union expressions. The last field is the
Chariseeb1d32802022-09-22 15:38:41 +00001236 /// active field number and is present only for union expressions
1237 /// -- e.g., for a union expression `SomeUnion { c: .. }`, the
1238 /// active field index would identity the field `c`
Charisee635618d2023-06-01 20:46:00 +00001239 Adt(DefId, VariantIdx, SubstsRef<'tcx>, Option<UserTypeAnnotationIndex>, Option<FieldIdx>),
Chariseeb1d32802022-09-22 15:38:41 +00001240
Chris Wailes5c0824a2023-04-24 16:30:59 -07001241 Closure(DefId, SubstsRef<'tcx>),
1242 Generator(DefId, SubstsRef<'tcx>, hir::Movability),
Chariseeb1d32802022-09-22 15:38:41 +00001243}
1244
Chris Wailescd1aefd2023-07-13 13:36:21 -07001245#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
1246pub enum NullOp<'tcx> {
Chariseeb1d32802022-09-22 15:38:41 +00001247 /// Returns the size of a value of that type
1248 SizeOf,
1249 /// Returns the minimum alignment of a type
1250 AlignOf,
Chris Wailescd1aefd2023-07-13 13:36:21 -07001251 /// Returns the offset of a field
1252 OffsetOf(&'tcx List<FieldIdx>),
Chariseeb1d32802022-09-22 15:38:41 +00001253}
1254
Chris Wailes977026a2023-02-13 09:13:10 -08001255#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1256#[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)]
Chariseeb1d32802022-09-22 15:38:41 +00001257pub enum UnOp {
1258 /// The `!` operator for logical inversion
1259 Not,
1260 /// The `-` operator for negation
1261 Neg,
1262}
1263
Chris Wailes977026a2023-02-13 09:13:10 -08001264#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
1265#[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
Chariseeb1d32802022-09-22 15:38:41 +00001266pub enum BinOp {
1267 /// The `+` operator (addition)
1268 Add,
1269 /// The `-` operator (subtraction)
1270 Sub,
1271 /// The `*` operator (multiplication)
1272 Mul,
1273 /// The `/` operator (division)
1274 ///
1275 /// Division by zero is UB, because the compiler should have inserted checks
1276 /// prior to this.
1277 Div,
1278 /// The `%` operator (modulus)
1279 ///
1280 /// Using zero as the modulus (second operand) is UB, because the compiler
1281 /// should have inserted checks prior to this.
1282 Rem,
1283 /// The `^` operator (bitwise xor)
1284 BitXor,
1285 /// The `&` operator (bitwise and)
1286 BitAnd,
1287 /// The `|` operator (bitwise or)
1288 BitOr,
1289 /// The `<<` operator (shift left)
1290 ///
1291 /// The offset is truncated to the size of the first operand before shifting.
1292 Shl,
1293 /// The `>>` operator (shift right)
1294 ///
1295 /// The offset is truncated to the size of the first operand before shifting.
1296 Shr,
1297 /// The `==` operator (equality)
1298 Eq,
1299 /// The `<` operator (less than)
1300 Lt,
1301 /// The `<=` operator (less than or equal to)
1302 Le,
1303 /// The `!=` operator (not equal to)
1304 Ne,
1305 /// The `>=` operator (greater than or equal to)
1306 Ge,
1307 /// The `>` operator (greater than)
1308 Gt,
1309 /// The `ptr.offset` operator
1310 Offset,
1311}
1312
1313// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
1314#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
1315mod size_asserts {
1316 use super::*;
Chariseef7ad1c42023-01-30 22:46:42 +00001317 // tidy-alphabetical-start
Charisee635618d2023-06-01 20:46:00 +00001318 static_assert_size!(AggregateKind<'_>, 32);
Chariseeb1d32802022-09-22 15:38:41 +00001319 static_assert_size!(Operand<'_>, 24);
1320 static_assert_size!(Place<'_>, 16);
1321 static_assert_size!(PlaceElem<'_>, 24);
1322 static_assert_size!(Rvalue<'_>, 40);
Chariseef7ad1c42023-01-30 22:46:42 +00001323 // tidy-alphabetical-end
Chariseeb1d32802022-09-22 15:38:41 +00001324}