]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_middle/mir/mod.rs
Auto merge of #75912 - scottmcm:manuallydrop-vs-forget, r=Mark-Simulacrum
[rust.git] / src / librustc_middle / mir / mod.rs
index 1faed87f8ff17026327f88f233ff55334b16b83a..7ac7d9b23f172640686813b74489b4352fb7d823 100644 (file)
@@ -2,6 +2,7 @@
 //!
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html
 
+use crate::mir::coverage::{CodeRegion, CoverageKind};
 use crate::mir::interpret::{Allocation, ConstValue, GlobalAlloc, Scalar};
 use crate::mir::visit::MirVisitable;
 use crate::ty::adjustment::PointerCast;
@@ -25,7 +26,6 @@
 use rustc_data_structures::graph::{self, GraphSuccessors};
 use rustc_index::bit_set::BitMatrix;
 use rustc_index::vec::{Idx, IndexVec};
-use rustc_macros::HashStable;
 use rustc_serialize::{Decodable, Encodable};
 use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
@@ -73,15 +73,35 @@ fn local_decls(&self) -> &LocalDecls<'tcx> {
 
 /// The various "big phases" that MIR goes through.
 ///
+/// These phases all describe dialects of MIR. Since all MIR uses the same datastructures, the
+/// dialects forbid certain variants or values in certain phases.
+///
+/// Note: Each phase's validation checks all invariants of the *previous* phases' dialects. A phase
+/// that changes the dialect documents what invariants must be upheld *after* that phase finishes.
+///
 /// Warning: ordering of variants is significant.
 #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)]
 #[derive(HashStable)]
 pub enum MirPhase {
     Build = 0,
+    // FIXME(oli-obk): it's unclear whether we still need this phase (and its corresponding query).
+    // We used to have this for pre-miri MIR based const eval.
     Const = 1,
-    Validated = 2,
-    DropElab = 3,
-    Optimized = 4,
+    /// This phase checks the MIR for promotable elements and takes them out of the main MIR body
+    /// by creating a new MIR body per promoted element. After this phase (and thus the termination
+    /// of the `mir_promoted` query), these promoted elements are available in the `promoted_mir`
+    /// query.
+    ConstPromotion = 2,
+    /// After this phase
+    /// * the only `AggregateKind`s allowed are `Array` and `Generator`,
+    /// * `DropAndReplace` is gone for good
+    /// * `Drop` now uses explicit drop flags visible in the MIR and reaching a `Drop` terminator
+    ///   means that the auto-generated drop glue will be invoked.
+    DropLowering = 3,
+    /// After this phase, generators are explicit state machines (no more `Yield`).
+    /// `AggregateKind::Generator` is gone for good.
+    GeneratorLowering = 4,
+    Optimization = 5,
 }
 
 impl MirPhase {
@@ -1400,6 +1420,12 @@ pub enum StatementKind<'tcx> {
     /// - `Bivariant` -- no effect
     AscribeUserType(Box<(Place<'tcx>, UserTypeProjection)>, ty::Variance),
 
+    /// Marks the start of a "coverage region", injected with '-Zinstrument-coverage'. A
+    /// `CoverageInfo` statement carries metadata about the coverage region, used to inject a coverage
+    /// map into the binary. The `Counter` kind also generates executable code, to increment a
+    /// counter varible at runtime, each time the code region is executed.
+    Coverage(Box<Coverage>),
+
     /// No-op. Useful for deleting instructions without affecting statement indices.
     Nop,
 }
@@ -1495,11 +1521,18 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
             AscribeUserType(box (ref place, ref c_ty), ref variance) => {
                 write!(fmt, "AscribeUserType({:?}, {:?}, {:?})", place, variance, c_ty)
             }
+            Coverage(box ref coverage) => write!(fmt, "{:?}", coverage),
             Nop => write!(fmt, "nop"),
         }
     }
 }
 
+#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
+pub struct Coverage {
+    pub kind: CoverageKind,
+    pub code_region: CodeRegion,
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // Places
 
@@ -1531,10 +1564,10 @@ pub enum ProjectionElem<V, T> {
     /// ```
     ConstantIndex {
         /// index or -index (in Python terms), depending on from_end
-        offset: u32,
+        offset: u64,
         /// The thing being indexed must be at least this long. For arrays this
         /// is always the exact length.
-        min_length: u32,
+        min_length: u64,
         /// Counting backwards from end? This is always false when indexing an
         /// array.
         from_end: bool,
@@ -1545,8 +1578,8 @@ pub enum ProjectionElem<V, T> {
     /// If `from_end` is true `slice[from..slice.len() - to]`.
     /// Otherwise `array[from..to]`.
     Subslice {
-        from: u32,
-        to: u32,
+        from: u64,
+        to: u64,
         /// Whether `to` counts from the start or end of the array/slice.
         /// For `PlaceElem`s this is `true` if and only if the base is a slice.
         /// For `ProjectionKind`, this can also be `true` for arrays.
@@ -1583,7 +1616,7 @@ fn is_indirect(&self) -> bool {
 
 // At least on 64 bit systems, `PlaceElem` should not be larger than two pointers.
 #[cfg(target_arch = "x86_64")]
-static_assert_size!(PlaceElem<'_>, 16);
+static_assert_size!(PlaceElem<'_>, 24);
 
 /// Alias for projections as they appear in `UserTypeProjection`, where we
 /// need neither the `V` parameter for `Index` nor the `T` for `Field`.
@@ -2297,7 +2330,7 @@ pub fn index(self) -> Self {
         self.map_projections(|pat_ty_proj| pat_ty_proj.index())
     }
 
-    pub fn subslice(self, from: u32, to: u32) -> Self {
+    pub fn subslice(self, from: u64, to: u64) -> Self {
         self.map_projections(|pat_ty_proj| pat_ty_proj.subslice(from, to))
     }
 
@@ -2343,7 +2376,7 @@ pub(crate) fn index(mut self) -> Self {
         self
     }
 
-    pub(crate) fn subslice(mut self, from: u32, to: u32) -> Self {
+    pub(crate) fn subslice(mut self, from: u64, to: u64) -> Self {
         self.projs.push(ProjectionElem::Subslice { from, to, from_end: true });
         self
     }
@@ -2419,7 +2452,10 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
 
 impl<'tcx> Display for Constant<'tcx> {
     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
-        write!(fmt, "const ")?;
+        match self.literal.ty.kind {
+            ty::FnDef(..) => {}
+            _ => write!(fmt, "const ")?,
+        }
         pretty_print_const(self.literal, fmt, true)
     }
 }