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