rustc: move the MIR pass infrastructure and list to rustc_mir.
This commit is contained in:
parent
9b53f0a662
commit
86206f22a0
25 changed files with 201 additions and 215 deletions
|
@ -13,13 +13,10 @@
|
|||
use hir;
|
||||
use hir::def_id::DefId;
|
||||
use hir::map::DefPathData;
|
||||
use mir::{Mir, Promoted};
|
||||
use mir::Promoted;
|
||||
use ty::TyCtxt;
|
||||
use std::rc::Rc;
|
||||
use syntax::ast::NodeId;
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
/// Where a specific Mir comes from.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum MirSource {
|
||||
|
@ -79,112 +76,3 @@ impl<'a, 'gcx, 'tcx> MirSource {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a default name for the pass based on the name of the
|
||||
/// type `T`.
|
||||
pub fn default_name<T: ?Sized>() -> Cow<'static, str> {
|
||||
let name = unsafe { ::std::intrinsics::type_name::<T>() };
|
||||
if let Some(tail) = name.rfind(":") {
|
||||
Cow::from(&name[tail+1..])
|
||||
} else {
|
||||
Cow::from(name)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct MirSuite(pub usize);
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct MirPassIndex(pub usize);
|
||||
|
||||
/// A pass hook is invoked both before and after each pass executes.
|
||||
/// This is primarily used to dump MIR for debugging.
|
||||
///
|
||||
/// You can tell whether this is before or after by inspecting the
|
||||
/// `mir` parameter -- before the pass executes, it will be `None` (in
|
||||
/// which case you can inspect the MIR from previous pass by executing
|
||||
/// `mir_cx.read_previous_mir()`); after the pass executes, it will be
|
||||
/// `Some()` with the result of the pass (in which case the output
|
||||
/// from the previous pass is most likely stolen, so you would not
|
||||
/// want to try and access it). If the pass is interprocedural, then
|
||||
/// the hook will be invoked once per output.
|
||||
pub trait PassHook {
|
||||
fn on_mir_pass<'a, 'tcx: 'a>(&self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
suite: MirSuite,
|
||||
pass_num: MirPassIndex,
|
||||
pass_name: &str,
|
||||
source: MirSource,
|
||||
mir: &Mir<'tcx>,
|
||||
is_after: bool);
|
||||
}
|
||||
|
||||
/// The full suite of types that identifies a particular
|
||||
/// application of a pass to a def-id.
|
||||
pub type PassId = (MirSuite, MirPassIndex, DefId);
|
||||
|
||||
/// A streamlined trait that you can implement to create a pass; the
|
||||
/// pass will be named after the type, and it will consist of a main
|
||||
/// loop that goes over each available MIR and applies `run_pass`.
|
||||
pub trait MirPass {
|
||||
fn name<'a>(&'a self) -> Cow<'a, str> {
|
||||
default_name::<Self>()
|
||||
}
|
||||
|
||||
fn run_pass<'a, 'tcx>(&self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
source: MirSource,
|
||||
mir: &mut Mir<'tcx>);
|
||||
}
|
||||
|
||||
/// A manager for MIR passes.
|
||||
///
|
||||
/// FIXME(#41712) -- it is unclear whether we should have this struct.
|
||||
#[derive(Clone)]
|
||||
pub struct Passes {
|
||||
pass_hooks: Vec<Rc<PassHook>>,
|
||||
suites: Vec<Vec<Rc<MirPass>>>,
|
||||
}
|
||||
|
||||
/// The number of "pass suites" that we have:
|
||||
///
|
||||
/// - ready for constant evaluation
|
||||
/// - unopt
|
||||
/// - optimized
|
||||
pub const MIR_SUITES: usize = 3;
|
||||
|
||||
/// Run the passes we need to do constant qualification and evaluation.
|
||||
pub const MIR_CONST: MirSuite = MirSuite(0);
|
||||
|
||||
/// Run the passes we need to consider the MIR validated and ready for borrowck etc.
|
||||
pub const MIR_VALIDATED: MirSuite = MirSuite(1);
|
||||
|
||||
/// Run the passes we need to consider the MIR *optimized*.
|
||||
pub const MIR_OPTIMIZED: MirSuite = MirSuite(2);
|
||||
|
||||
impl<'a, 'tcx> Passes {
|
||||
pub fn new() -> Passes {
|
||||
Passes {
|
||||
pass_hooks: Vec::new(),
|
||||
suites: (0..MIR_SUITES).map(|_| Vec::new()).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Pushes a built-in pass.
|
||||
pub fn push_pass<T: MirPass + 'static>(&mut self, suite: MirSuite, pass: T) {
|
||||
self.suites[suite.0].push(Rc::new(pass));
|
||||
}
|
||||
|
||||
/// Pushes a pass hook.
|
||||
pub fn push_hook<T: PassHook + 'static>(&mut self, hook: T) {
|
||||
self.pass_hooks.push(Rc::new(hook));
|
||||
}
|
||||
|
||||
pub fn passes(&self, suite: MirSuite) -> &[Rc<MirPass>] {
|
||||
&self.suites[suite.0]
|
||||
}
|
||||
|
||||
pub fn hooks(&self) -> &[Rc<PassHook>] {
|
||||
&self.pass_hooks
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ use middle::lang_items;
|
|||
use middle::resolve_lifetime::{self, ObjectLifetimeDefault};
|
||||
use middle::stability;
|
||||
use mir::Mir;
|
||||
use mir::transform::Passes;
|
||||
use ty::subst::{Kind, Substs};
|
||||
use ty::ReprOptions;
|
||||
use traits;
|
||||
|
@ -882,8 +881,6 @@ pub struct GlobalCtxt<'tcx> {
|
|||
|
||||
pub maps: maps::Maps<'tcx>,
|
||||
|
||||
pub mir_passes: Rc<Passes>,
|
||||
|
||||
// Records the free variables refrenced by every closure
|
||||
// expression. Do not track deps for this, just recompute it from
|
||||
// scratch every time.
|
||||
|
@ -1055,7 +1052,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
cstore: &'tcx CrateStore,
|
||||
local_providers: ty::maps::Providers<'tcx>,
|
||||
extern_providers: ty::maps::Providers<'tcx>,
|
||||
mir_passes: Rc<Passes>,
|
||||
arenas: &'tcx GlobalArenas<'tcx>,
|
||||
arena: &'tcx DroplessArena,
|
||||
resolutions: ty::Resolutions,
|
||||
|
@ -1172,7 +1168,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
hir,
|
||||
def_path_hash_to_def_id,
|
||||
maps: maps::Maps::new(providers),
|
||||
mir_passes,
|
||||
rcache: RefCell::new(FxHashMap()),
|
||||
selection_cache: traits::SelectionCache::new(),
|
||||
evaluation_cache: traits::EvaluationCache::new(),
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
//! Defines the set of legal keys that can be used in queries.
|
||||
|
||||
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE, DefIndex};
|
||||
use mir::transform::{MirSuite, MirPassIndex};
|
||||
use ty::{self, Ty, TyCtxt};
|
||||
use ty::subst::Substs;
|
||||
use ty::fast_reject::SimplifiedType;
|
||||
|
@ -116,24 +115,6 @@ impl<'tcx> Key for (DefId, &'tcx Substs<'tcx>) {
|
|||
}
|
||||
}
|
||||
|
||||
impl Key for (MirSuite, DefId) {
|
||||
fn map_crate(&self) -> CrateNum {
|
||||
self.1.map_crate()
|
||||
}
|
||||
fn default_span(&self, tcx: TyCtxt) -> Span {
|
||||
self.1.default_span(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl Key for (MirSuite, MirPassIndex, DefId) {
|
||||
fn map_crate(&self) -> CrateNum {
|
||||
self.2.map_crate()
|
||||
}
|
||||
fn default_span(&self, tcx: TyCtxt) -> Span {
|
||||
self.2.default_span(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) {
|
||||
fn map_crate(&self) -> CrateNum {
|
||||
self.1.def_id().krate
|
||||
|
|
|
@ -22,7 +22,6 @@ use rustc::lint;
|
|||
use rustc::middle::{self, stability, reachable};
|
||||
use rustc::middle::cstore::CrateStore;
|
||||
use rustc::middle::privacy::AccessLevels;
|
||||
use rustc::mir::transform::{MIR_CONST, MIR_VALIDATED, MIR_OPTIMIZED, Passes};
|
||||
use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas};
|
||||
use rustc::traits;
|
||||
use rustc::util::common::{ErrorReported, time};
|
||||
|
@ -989,63 +988,12 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
|||
// FIXME(eddyb) get rid of this once we replace const_eval with miri.
|
||||
rustc_const_eval::provide(&mut extern_providers);
|
||||
|
||||
// Setup the MIR passes that we want to run.
|
||||
let mut passes = Passes::new();
|
||||
passes.push_hook(mir::transform::dump_mir::DumpMir);
|
||||
|
||||
// Remove all `EndRegion` statements that are not involved in borrows.
|
||||
passes.push_pass(MIR_CONST, mir::transform::clean_end_regions::CleanEndRegions);
|
||||
|
||||
// What we need to do constant evaluation.
|
||||
passes.push_pass(MIR_CONST, mir::transform::simplify::SimplifyCfg::new("initial"));
|
||||
passes.push_pass(MIR_CONST, mir::transform::type_check::TypeckMir);
|
||||
passes.push_pass(MIR_CONST, mir::transform::rustc_peek::SanityCheck);
|
||||
|
||||
// We compute "constant qualifications" between MIR_CONST and MIR_VALIDATED.
|
||||
|
||||
// What we need to run borrowck etc.
|
||||
|
||||
passes.push_pass(MIR_VALIDATED, mir::transform::qualify_consts::QualifyAndPromoteConstants);
|
||||
passes.push_pass(MIR_VALIDATED, mir::transform::simplify::SimplifyCfg::new("qualify-consts"));
|
||||
|
||||
// borrowck runs between MIR_VALIDATED and MIR_OPTIMIZED.
|
||||
|
||||
passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads);
|
||||
passes.push_pass(MIR_OPTIMIZED,
|
||||
mir::transform::simplify_branches::SimplifyBranches::new("initial"));
|
||||
|
||||
// These next passes must be executed together
|
||||
passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::CriticalCallEdges);
|
||||
passes.push_pass(MIR_OPTIMIZED, mir::transform::elaborate_drops::ElaborateDrops);
|
||||
passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads);
|
||||
// AddValidation needs to run after ElaborateDrops and before EraseRegions, and it needs
|
||||
// an AllCallEdges pass right before it.
|
||||
passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::AllCallEdges);
|
||||
passes.push_pass(MIR_OPTIMIZED, mir::transform::add_validation::AddValidation);
|
||||
passes.push_pass(MIR_OPTIMIZED, mir::transform::simplify::SimplifyCfg::new("elaborate-drops"));
|
||||
// No lifetime analysis based on borrowing can be done from here on out.
|
||||
|
||||
// From here on out, regions are gone.
|
||||
passes.push_pass(MIR_OPTIMIZED, mir::transform::erase_regions::EraseRegions);
|
||||
|
||||
// Optimizations begin.
|
||||
passes.push_pass(MIR_OPTIMIZED, mir::transform::inline::Inline);
|
||||
passes.push_pass(MIR_OPTIMIZED, mir::transform::instcombine::InstCombine);
|
||||
passes.push_pass(MIR_OPTIMIZED, mir::transform::deaggregator::Deaggregator);
|
||||
passes.push_pass(MIR_OPTIMIZED, mir::transform::copy_prop::CopyPropagation);
|
||||
passes.push_pass(MIR_OPTIMIZED, mir::transform::simplify::SimplifyLocals);
|
||||
|
||||
passes.push_pass(MIR_OPTIMIZED, mir::transform::generator::StateTransform);
|
||||
passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::CriticalCallEdges);
|
||||
passes.push_pass(MIR_OPTIMIZED, mir::transform::dump_mir::Marker("PreTrans"));
|
||||
|
||||
let (tx, rx) = mpsc::channel();
|
||||
|
||||
TyCtxt::create_and_enter(sess,
|
||||
cstore,
|
||||
local_providers,
|
||||
extern_providers,
|
||||
Rc::new(passes),
|
||||
arenas,
|
||||
arena,
|
||||
resolutions,
|
||||
|
|
|
@ -28,7 +28,6 @@ use rustc::infer::{self, InferOk, InferResult};
|
|||
use rustc::infer::type_variable::TypeVariableOrigin;
|
||||
use rustc_metadata::cstore::CStore;
|
||||
use rustc::hir::map as hir_map;
|
||||
use rustc::mir::transform::Passes;
|
||||
use rustc::session::{self, config};
|
||||
use rustc::session::config::{OutputFilenames, OutputTypes};
|
||||
use rustc_trans_utils::trans_crate::TransCrate;
|
||||
|
@ -151,7 +150,6 @@ fn test_env<F>(source_string: &str,
|
|||
&*cstore,
|
||||
ty::maps::Providers::default(),
|
||||
ty::maps::Providers::default(),
|
||||
Rc::new(Passes::new()),
|
||||
&arenas,
|
||||
&arena,
|
||||
resolutions,
|
||||
|
|
|
@ -20,6 +20,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
|
|||
#![feature(box_syntax)]
|
||||
#![feature(conservative_impl_trait)]
|
||||
#![feature(const_fn)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(i128_type)]
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
#![feature(placement_in_syntax)]
|
||||
|
|
|
@ -10,8 +10,9 @@
|
|||
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::transform::{MirPass, MirSource};
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||
use transform::MirPass;
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub enum AddCallGuards {
|
||||
|
|
|
@ -17,8 +17,9 @@
|
|||
use rustc::ty::{self, TyCtxt, RegionKind};
|
||||
use rustc::hir;
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::transform::{MirPass, MirSource};
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc::middle::region;
|
||||
use transform::MirPass;
|
||||
|
||||
pub struct AddValidation;
|
||||
|
||||
|
|
|
@ -22,10 +22,11 @@
|
|||
use rustc_data_structures::fx::FxHashSet;
|
||||
|
||||
use rustc::middle::region;
|
||||
use rustc::mir::transform::{MirPass, MirSource};
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc::mir::{BasicBlock, Location, Mir, Rvalue, Statement, StatementKind};
|
||||
use rustc::mir::visit::{MutVisitor, Visitor, TyContext};
|
||||
use rustc::ty::{Ty, RegionKind, TyCtxt};
|
||||
use transform::MirPass;
|
||||
|
||||
pub struct CleanEndRegions;
|
||||
|
||||
|
|
|
@ -30,9 +30,10 @@
|
|||
//! future.
|
||||
|
||||
use rustc::mir::{Constant, Local, LocalKind, Location, Lvalue, Mir, Operand, Rvalue, StatementKind};
|
||||
use rustc::mir::transform::{MirPass, MirSource};
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc::mir::visit::MutVisitor;
|
||||
use rustc::ty::TyCtxt;
|
||||
use transform::MirPass;
|
||||
use util::def_use::DefUseAnalysis;
|
||||
|
||||
pub struct CopyPropagation;
|
||||
|
|
|
@ -10,8 +10,9 @@
|
|||
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::transform::{MirPass, MirSource};
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use transform::MirPass;
|
||||
|
||||
pub struct Deaggregator;
|
||||
|
||||
|
|
|
@ -16,9 +16,10 @@ use std::fs::File;
|
|||
use std::io;
|
||||
|
||||
use rustc::mir::Mir;
|
||||
use rustc::mir::transform::{MirPass, MirPassIndex, MirSource, MirSuite, PassHook};
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc::session::config::{OutputFilenames, OutputType};
|
||||
use rustc::ty::TyCtxt;
|
||||
use transform::{MirPass, MirPassIndex, MirSuite, PassHook};
|
||||
use util as mir_util;
|
||||
|
||||
pub struct Marker(pub &'static str);
|
||||
|
|
|
@ -17,11 +17,12 @@ use dataflow::MoveDataParamEnv;
|
|||
use dataflow;
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::transform::{MirPass, MirSource};
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
use rustc_data_structures::indexed_set::IdxSetBuf;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use transform::MirPass;
|
||||
use util::patch::MirPatch;
|
||||
use util::elaborate_drops::{DropFlagState, Unwind, elaborate_drop};
|
||||
use util::elaborate_drops::{DropElaborator, DropStyle, DropFlagMode};
|
||||
|
|
|
@ -18,7 +18,8 @@ use rustc::ty::subst::Substs;
|
|||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::visit::{MutVisitor, TyContext};
|
||||
use rustc::mir::transform::{MirPass, MirSource};
|
||||
use rustc::mir::transform::MirSource;
|
||||
use transform::MirPass;
|
||||
|
||||
struct EraseRegionsVisitor<'a, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
|
|
@ -63,7 +63,7 @@ use rustc::hir;
|
|||
use rustc::hir::def_id::DefId;
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::transform::{MirPass, MirSource};
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc::mir::visit::{LvalueContext, Visitor, MutVisitor};
|
||||
use rustc::ty::{self, TyCtxt, AdtDef, Ty, GeneratorInterior};
|
||||
use rustc::ty::subst::{Kind, Substs};
|
||||
|
@ -76,6 +76,7 @@ use std::collections::HashMap;
|
|||
use std::borrow::Cow;
|
||||
use std::iter::once;
|
||||
use std::mem;
|
||||
use transform::MirPass;
|
||||
use transform::simplify;
|
||||
use transform::no_landing_pads::no_landing_pads;
|
||||
use dataflow::{self, MaybeStorageLive, state_for_location};
|
||||
|
|
|
@ -16,12 +16,13 @@ use rustc_data_structures::bitvec::BitVector;
|
|||
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::transform::{MirPass, MirSource};
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc::mir::visit::*;
|
||||
use rustc::ty::{self, Instance, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc::ty::subst::{Subst,Substs};
|
||||
|
||||
use std::collections::VecDeque;
|
||||
use transform::MirPass;
|
||||
use super::simplify::{remove_dead_blocks, CfgSimplifier};
|
||||
|
||||
use syntax::{attr};
|
||||
|
|
|
@ -11,12 +11,13 @@
|
|||
//! Performs various peephole optimizations.
|
||||
|
||||
use rustc::mir::{Location, Lvalue, Mir, Operand, ProjectionElem, Rvalue, Local};
|
||||
use rustc::mir::transform::{MirPass, MirSource};
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc::mir::visit::{MutVisitor, Visitor};
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc::util::nodemap::FxHashSet;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use std::mem;
|
||||
use transform::MirPass;
|
||||
|
||||
pub struct InstCombine;
|
||||
|
||||
|
|
|
@ -11,14 +11,14 @@
|
|||
use build;
|
||||
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||
use rustc::mir::Mir;
|
||||
use rustc::mir::transform::{MirPassIndex, MirSuite, MirSource,
|
||||
MIR_CONST, MIR_VALIDATED, MIR_OPTIMIZED};
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc::ty::maps::Providers;
|
||||
use rustc::ty::steal::Steal;
|
||||
use rustc::hir;
|
||||
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
use rustc::util::nodemap::DefIdSet;
|
||||
use std::borrow::Cow;
|
||||
use std::rc::Rc;
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
|
@ -144,17 +144,174 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
|
|||
tcx.alloc_mir(mir)
|
||||
}
|
||||
|
||||
/// Generates a default name for the pass based on the name of the
|
||||
/// type `T`.
|
||||
pub fn default_name<T: ?Sized>() -> Cow<'static, str> {
|
||||
let name = unsafe { ::std::intrinsics::type_name::<T>() };
|
||||
if let Some(tail) = name.rfind(":") {
|
||||
Cow::from(&name[tail+1..])
|
||||
} else {
|
||||
Cow::from(name)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct MirSuite(pub usize);
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct MirPassIndex(pub usize);
|
||||
|
||||
/// A pass hook is invoked both before and after each pass executes.
|
||||
/// This is primarily used to dump MIR for debugging.
|
||||
///
|
||||
/// You can tell whether this is before or after by inspecting the
|
||||
/// `mir` parameter -- before the pass executes, it will be `None` (in
|
||||
/// which case you can inspect the MIR from previous pass by executing
|
||||
/// `mir_cx.read_previous_mir()`); after the pass executes, it will be
|
||||
/// `Some()` with the result of the pass (in which case the output
|
||||
/// from the previous pass is most likely stolen, so you would not
|
||||
/// want to try and access it). If the pass is interprocedural, then
|
||||
/// the hook will be invoked once per output.
|
||||
pub trait PassHook {
|
||||
fn on_mir_pass<'a, 'tcx: 'a>(&self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
suite: MirSuite,
|
||||
pass_num: MirPassIndex,
|
||||
pass_name: &str,
|
||||
source: MirSource,
|
||||
mir: &Mir<'tcx>,
|
||||
is_after: bool);
|
||||
}
|
||||
|
||||
/// The full suite of types that identifies a particular
|
||||
/// application of a pass to a def-id.
|
||||
pub type PassId = (MirSuite, MirPassIndex, DefId);
|
||||
|
||||
/// A streamlined trait that you can implement to create a pass; the
|
||||
/// pass will be named after the type, and it will consist of a main
|
||||
/// loop that goes over each available MIR and applies `run_pass`.
|
||||
pub trait MirPass {
|
||||
fn name<'a>(&'a self) -> Cow<'a, str> {
|
||||
default_name::<Self>()
|
||||
}
|
||||
|
||||
fn run_pass<'a, 'tcx>(&self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
source: MirSource,
|
||||
mir: &mut Mir<'tcx>);
|
||||
}
|
||||
|
||||
/// A manager for MIR passes.
|
||||
///
|
||||
/// FIXME(#41712) -- it is unclear whether we should have this struct.
|
||||
#[derive(Clone)]
|
||||
pub struct Passes {
|
||||
pass_hooks: Vec<Rc<PassHook>>,
|
||||
suites: Vec<Vec<Rc<MirPass>>>,
|
||||
}
|
||||
|
||||
/// The number of "pass suites" that we have:
|
||||
///
|
||||
/// - ready for constant evaluation
|
||||
/// - unopt
|
||||
/// - optimized
|
||||
pub const MIR_SUITES: usize = 3;
|
||||
|
||||
/// Run the passes we need to do constant qualification and evaluation.
|
||||
pub const MIR_CONST: MirSuite = MirSuite(0);
|
||||
|
||||
/// Run the passes we need to consider the MIR validated and ready for borrowck etc.
|
||||
pub const MIR_VALIDATED: MirSuite = MirSuite(1);
|
||||
|
||||
/// Run the passes we need to consider the MIR *optimized*.
|
||||
pub const MIR_OPTIMIZED: MirSuite = MirSuite(2);
|
||||
|
||||
impl<'a, 'tcx> Passes {
|
||||
pub fn new() -> Passes {
|
||||
Passes {
|
||||
pass_hooks: Vec::new(),
|
||||
suites: (0..MIR_SUITES).map(|_| Vec::new()).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Pushes a built-in pass.
|
||||
pub fn push_pass<T: MirPass + 'static>(&mut self, suite: MirSuite, pass: T) {
|
||||
self.suites[suite.0].push(Rc::new(pass));
|
||||
}
|
||||
|
||||
/// Pushes a pass hook.
|
||||
pub fn push_hook<T: PassHook + 'static>(&mut self, hook: T) {
|
||||
self.pass_hooks.push(Rc::new(hook));
|
||||
}
|
||||
|
||||
pub fn passes(&self, suite: MirSuite) -> &[Rc<MirPass>] {
|
||||
&self.suites[suite.0]
|
||||
}
|
||||
|
||||
pub fn hooks(&self) -> &[Rc<PassHook>] {
|
||||
&self.pass_hooks
|
||||
}
|
||||
}
|
||||
|
||||
fn run_suite<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
source: MirSource,
|
||||
suite: MirSuite,
|
||||
mir: &mut Mir<'tcx>)
|
||||
{
|
||||
let passes = tcx.mir_passes.passes(suite);
|
||||
// Setup the MIR passes that we want to run.
|
||||
let mut passes = Passes::new();
|
||||
passes.push_hook(dump_mir::DumpMir);
|
||||
|
||||
for (pass, index) in passes.iter().zip(0..) {
|
||||
// Remove all `EndRegion` statements that are not involved in borrows.
|
||||
passes.push_pass(MIR_CONST, clean_end_regions::CleanEndRegions);
|
||||
|
||||
// What we need to do constant evaluation.
|
||||
passes.push_pass(MIR_CONST, simplify::SimplifyCfg::new("initial"));
|
||||
passes.push_pass(MIR_CONST, type_check::TypeckMir);
|
||||
passes.push_pass(MIR_CONST, rustc_peek::SanityCheck);
|
||||
|
||||
// We compute "constant qualifications" between MIR_CONST and MIR_VALIDATED.
|
||||
|
||||
// What we need to run borrowck etc.
|
||||
|
||||
passes.push_pass(MIR_VALIDATED, qualify_consts::QualifyAndPromoteConstants);
|
||||
passes.push_pass(MIR_VALIDATED, simplify::SimplifyCfg::new("qualify-consts"));
|
||||
|
||||
// borrowck runs between MIR_VALIDATED and MIR_OPTIMIZED.
|
||||
|
||||
passes.push_pass(MIR_OPTIMIZED, no_landing_pads::NoLandingPads);
|
||||
passes.push_pass(MIR_OPTIMIZED,
|
||||
simplify_branches::SimplifyBranches::new("initial"));
|
||||
|
||||
// These next passes must be executed together
|
||||
passes.push_pass(MIR_OPTIMIZED, add_call_guards::CriticalCallEdges);
|
||||
passes.push_pass(MIR_OPTIMIZED, elaborate_drops::ElaborateDrops);
|
||||
passes.push_pass(MIR_OPTIMIZED, no_landing_pads::NoLandingPads);
|
||||
// AddValidation needs to run after ElaborateDrops and before EraseRegions, and it needs
|
||||
// an AllCallEdges pass right before it.
|
||||
passes.push_pass(MIR_OPTIMIZED, add_call_guards::AllCallEdges);
|
||||
passes.push_pass(MIR_OPTIMIZED, add_validation::AddValidation);
|
||||
passes.push_pass(MIR_OPTIMIZED, simplify::SimplifyCfg::new("elaborate-drops"));
|
||||
// No lifetime analysis based on borrowing can be done from here on out.
|
||||
|
||||
// From here on out, regions are gone.
|
||||
passes.push_pass(MIR_OPTIMIZED, erase_regions::EraseRegions);
|
||||
|
||||
// Optimizations begin.
|
||||
passes.push_pass(MIR_OPTIMIZED, inline::Inline);
|
||||
passes.push_pass(MIR_OPTIMIZED, instcombine::InstCombine);
|
||||
passes.push_pass(MIR_OPTIMIZED, deaggregator::Deaggregator);
|
||||
passes.push_pass(MIR_OPTIMIZED, copy_prop::CopyPropagation);
|
||||
passes.push_pass(MIR_OPTIMIZED, simplify::SimplifyLocals);
|
||||
|
||||
passes.push_pass(MIR_OPTIMIZED, generator::StateTransform);
|
||||
passes.push_pass(MIR_OPTIMIZED, add_call_guards::CriticalCallEdges);
|
||||
passes.push_pass(MIR_OPTIMIZED, dump_mir::Marker("PreTrans"));
|
||||
|
||||
for (index, pass) in passes.passes(suite).iter().enumerate() {
|
||||
let pass_num = MirPassIndex(index);
|
||||
|
||||
for hook in tcx.mir_passes.hooks() {
|
||||
for hook in passes.hooks() {
|
||||
hook.on_mir_pass(tcx, suite, pass_num, &pass.name(), source, &mir, false);
|
||||
}
|
||||
|
||||
|
@ -168,7 +325,7 @@ fn run_suite<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
assert!(promoted_mir.promoted.is_empty());
|
||||
}
|
||||
|
||||
for hook in tcx.mir_passes.hooks() {
|
||||
for hook in passes.hooks() {
|
||||
hook.on_mir_pass(tcx, suite, pass_num, &pass.name(), source, &mir, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
use rustc::ty::TyCtxt;
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::visit::MutVisitor;
|
||||
use rustc::mir::transform::{MirPass, MirSource};
|
||||
use rustc::mir::transform::MirSource;
|
||||
use transform::MirPass;
|
||||
|
||||
pub struct NoLandingPads;
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ use rustc::ty::cast::CastTy;
|
|||
use rustc::ty::maps::Providers;
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::traversal::ReversePostorder;
|
||||
use rustc::mir::transform::{MirPass, MirSource};
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc::mir::visit::{LvalueContext, Visitor};
|
||||
use rustc::middle::lang_items;
|
||||
use syntax::abi::Abi;
|
||||
|
@ -38,6 +38,7 @@ use std::fmt;
|
|||
use std::rc::Rc;
|
||||
use std::usize;
|
||||
|
||||
use transform::MirPass;
|
||||
use super::promote_consts::{self, Candidate, TempState};
|
||||
|
||||
bitflags! {
|
||||
|
|
|
@ -14,9 +14,10 @@ use syntax_pos::Span;
|
|||
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::mir::{self, Mir, Location};
|
||||
use rustc::mir::transform::{MirPass, MirSource};
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc_data_structures::indexed_set::IdxSetBuf;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use transform::MirPass;
|
||||
|
||||
use dataflow::do_dataflow;
|
||||
use dataflow::MoveDataParamEnv;
|
||||
|
|
|
@ -41,9 +41,10 @@ use rustc_data_structures::bitvec::BitVector;
|
|||
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::transform::{MirPass, MirSource};
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc::mir::visit::{MutVisitor, Visitor, LvalueContext};
|
||||
use std::borrow::Cow;
|
||||
use transform::MirPass;
|
||||
|
||||
pub struct SimplifyCfg { label: String }
|
||||
|
||||
|
|
|
@ -12,8 +12,9 @@
|
|||
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc::mir::transform::{MirPass, MirSource};
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc::mir::*;
|
||||
use transform::MirPass;
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
|
|
|
@ -18,11 +18,12 @@ use rustc::ty::{self, Ty, TyCtxt, TypeVariants};
|
|||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::tcx::LvalueTy;
|
||||
use rustc::mir::transform::{MirPass, MirSource};
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc::mir::visit::Visitor;
|
||||
use std::fmt;
|
||||
use syntax::ast;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use transform::MirPass;
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
use rustc::hir;
|
||||
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::transform::{MirSuite, MirPassIndex, MirSource};
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc::ty::item_path;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
|
@ -20,6 +20,7 @@ use std::fmt::Display;
|
|||
use std::fs;
|
||||
use std::io::{self, Write};
|
||||
use std::path::{PathBuf, Path};
|
||||
use transform::{MirSuite, MirPassIndex};
|
||||
use super::graphviz::write_mir_fn_graphviz;
|
||||
|
||||
const INDENT: &'static str = " ";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue