//!
//! [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;
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};
/// 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 {
/// - `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,
}
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
/// ```
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,
/// 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.
// 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`.
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))
}
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
}
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)
}
}