diff --git a/src/librustc/mir/transform.rs b/src/librustc/mir/transform.rs index 89f2fb59d51..14ad413c538 100644 --- a/src/librustc/mir/transform.rs +++ b/src/librustc/mir/transform.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use dep_graph::DepNode; use hir; use hir::def_id::{DefId, LOCAL_CRATE}; use hir::map::DefPathData; use mir::{Mir, Promoted}; use ty::TyCtxt; +use std::rc::Rc; use syntax::ast::NodeId; use util::common::time; @@ -99,51 +99,77 @@ pub trait PassHook { } /// 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 { +/// pass will be invoked to process the MIR with the given `def_id`. +/// This lets you do things before we fetch the MIR itself. You may +/// prefer `MirPass`. +pub trait DefIdPass { fn name<'a>(&'a self) -> Cow<'a, str> { default_name::() } fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - src: MirSource, - mir: &mut Mir<'tcx>); + def_id: DefId); } -impl Pass for T { +impl Pass for T { fn name<'a>(&'a self) -> Cow<'a, str> { - MirPass::name(self) + DefIdPass::name(self) } fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) { for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() { - run_map_pass_task(tcx, self, def_id); + DefIdPass::run_pass(self, tcx, def_id); } } } -fn run_map_pass_task<'a, 'tcx, T: MirPass>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - pass: &T, - def_id: DefId) { - let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id)); - let mir = &mut tcx.mir(def_id).borrow_mut(); +/// 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: DepGraphSafe { + fn name<'a>(&'a self) -> Cow<'a, str> { + default_name::() + } + + fn run_pass<'a, 'tcx>(&self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + source: MirSource, + mir: &mut Mir<'tcx>); +} + +fn for_each_assoc_mir<'a, 'tcx, OP>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, + mut op: OP) + where OP: FnMut(MirSource, &mut Mir<'tcx>) +{ let id = tcx.hir.as_local_node_id(def_id).expect("mir source requires local def-id"); let source = MirSource::from_node(tcx, id); - MirPass::run_pass(pass, tcx, source, mir); + let mir = &mut tcx.mir(def_id).borrow_mut(); + op(source, mir); - for (i, mir) in mir.promoted.iter_enumerated_mut() { - let source = MirSource::Promoted(id, i); - MirPass::run_pass(pass, tcx, source, mir); + for (promoted_index, promoted_mir) in mir.promoted.iter_enumerated_mut() { + let promoted_source = MirSource::Promoted(id, promoted_index); + op(promoted_source, promoted_mir); + } +} + +impl DefIdPass for T { + fn name<'a>(&'a self) -> Cow<'a, str> { + MirPass::name(self) + } + + fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { + for_each_assoc_mir(tcx, def_id, |src, mir| MirPass::run_pass(self, tcx, src, mir)); } } /// A manager for MIR passes. +#[derive(Clone)] pub struct Passes { - passes: Vec>, - pass_hooks: Vec>, - plugin_passes: Vec> + passes: Vec>, + pass_hooks: Vec>, + plugin_passes: Vec> } impl<'a, 'tcx> Passes { @@ -172,19 +198,19 @@ impl<'a, 'tcx> Passes { } /// Pushes a built-in pass. - pub fn push_pass(&mut self, pass: Box) { - self.passes.push(pass); + pub fn push_pass(&mut self, pass: T) { + self.passes.push(Rc::new(pass)); } /// Pushes a pass hook. - pub fn push_hook(&mut self, hook: Box) { - self.pass_hooks.push(hook); + pub fn push_hook(&mut self, hook: T) { + self.pass_hooks.push(Rc::new(hook)); } } /// Copies the plugin passes. -impl ::std::iter::Extend> for Passes { - fn extend>>(&mut self, it: I) { +impl ::std::iter::Extend> for Passes { + fn extend>>(&mut self, it: I) { self.plugin_passes.extend(it); } } diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index ba475367bc6..a9deb52efb6 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -549,7 +549,7 @@ define_maps! { <'tcx> /// /// Note that cross-crate MIR appears to be always borrowed /// (in the `RefCell` sense) to prevent accidental mutation. - [pub] mir: Mir(DefId) -> &'tcx RefCell>, + [] mir: Mir(DefId) -> &'tcx RefCell>, /// Set of all the def-ids in this crate that have MIR associated with /// them. This includes all the body owners, but also things like struct diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 64fb2168ca1..be344176fd2 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -975,12 +975,12 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, // Push all the built-in validation passes. // NB: if you’re adding an *optimisation* it ought to go to another set of passes // in stage 4 below. - passes.push_hook(box mir::transform::dump_mir::DumpMir); - passes.push_pass(box mir::transform::simplify::SimplifyCfg::new("initial")); - passes.push_pass(box mir::transform::type_check::TypeckMir); - passes.push_pass(box mir::transform::qualify_consts::QualifyAndPromoteConstants); - passes.push_pass(box mir::transform::simplify_branches::SimplifyBranches::new("initial")); - passes.push_pass(box mir::transform::simplify::SimplifyCfg::new("qualify-consts")); + passes.push_hook(mir::transform::dump_mir::DumpMir); + passes.push_pass(mir::transform::simplify::SimplifyCfg::new("initial")); + passes.push_pass(mir::transform::type_check::TypeckMir); + passes.push_pass(mir::transform::qualify_consts::QualifyAndPromoteConstants); + passes.push_pass(mir::transform::simplify_branches::SimplifyBranches::new("initial")); + passes.push_pass(mir::transform::simplify::SimplifyCfg::new("qualify-consts")); // And run everything. passes.run_passes(tcx); }); @@ -1041,27 +1041,27 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // code. time(time_passes, "MIR optimisations", || { let mut passes = ::rustc::mir::transform::Passes::new(); - passes.push_hook(box mir::transform::dump_mir::DumpMir); - passes.push_pass(box mir::transform::no_landing_pads::NoLandingPads); - passes.push_pass(box mir::transform::simplify::SimplifyCfg::new("no-landing-pads")); + passes.push_hook(mir::transform::dump_mir::DumpMir); + passes.push_pass(mir::transform::no_landing_pads::NoLandingPads); + passes.push_pass(mir::transform::simplify::SimplifyCfg::new("no-landing-pads")); // From here on out, regions are gone. - passes.push_pass(box mir::transform::erase_regions::EraseRegions); + passes.push_pass(mir::transform::erase_regions::EraseRegions); - passes.push_pass(box mir::transform::add_call_guards::AddCallGuards); - passes.push_pass(box borrowck::ElaborateDrops); - passes.push_pass(box mir::transform::no_landing_pads::NoLandingPads); - passes.push_pass(box mir::transform::simplify::SimplifyCfg::new("elaborate-drops")); + passes.push_pass(mir::transform::add_call_guards::AddCallGuards); + passes.push_pass(borrowck::ElaborateDrops); + passes.push_pass(mir::transform::no_landing_pads::NoLandingPads); + passes.push_pass(mir::transform::simplify::SimplifyCfg::new("elaborate-drops")); // No lifetime analysis based on borrowing can be done from here on out. - passes.push_pass(box mir::transform::inline::Inline); - passes.push_pass(box mir::transform::instcombine::InstCombine); - passes.push_pass(box mir::transform::deaggregator::Deaggregator); - passes.push_pass(box mir::transform::copy_prop::CopyPropagation); + passes.push_pass(mir::transform::inline::Inline); + passes.push_pass(mir::transform::instcombine::InstCombine); + passes.push_pass(mir::transform::deaggregator::Deaggregator); + passes.push_pass(mir::transform::copy_prop::CopyPropagation); - passes.push_pass(box mir::transform::simplify::SimplifyLocals); - passes.push_pass(box mir::transform::add_call_guards::AddCallGuards); - passes.push_pass(box mir::transform::dump_mir::Marker("PreTrans")); + passes.push_pass(mir::transform::simplify::SimplifyLocals); + passes.push_pass(mir::transform::add_call_guards::AddCallGuards); + passes.push_pass(mir::transform::dump_mir::Marker("PreTrans")); passes.run_passes(tcx); }); diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs index 528afd184c6..43fb0acf2dd 100644 --- a/src/librustc_mir/transform/dump_mir.rs +++ b/src/librustc_mir/transform/dump_mir.rs @@ -15,20 +15,20 @@ use std::fmt; use std::fs::File; use std::io; -use rustc::hir::def_id::LOCAL_CRATE; +use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::session::config::{OutputFilenames, OutputType}; use rustc::ty::TyCtxt; -use rustc::mir::transform::{Pass, PassHook, MirSource}; +use rustc::mir::transform::{DefIdPass, Pass, PassHook, MirSource}; use util as mir_util; pub struct Marker(pub &'static str); -impl Pass for Marker { +impl DefIdPass for Marker { fn name<'a>(&'a self) -> Cow<'a, str> { Cow::Borrowed(self.0) } - fn run_pass<'a, 'tcx>(&self, _tcx: TyCtxt<'a, 'tcx, 'tcx>) { + fn run_pass<'a, 'tcx>(&self, _: TyCtxt<'a, 'tcx, 'tcx>, _: DefId) { // no-op } } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 7e7e85f2ec9..80ec83fcaef 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -19,7 +19,7 @@ use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc::dep_graph::DepNode; use rustc::hir; use rustc::hir::map as hir_map; -use rustc::hir::def_id::{DefId, LOCAL_CRATE}; +use rustc::hir::def_id::DefId; use rustc::hir::map::blocks::FnLikeNode; use rustc::traits::{self, Reveal}; use rustc::ty::{self, TyCtxt, Ty, TypeFoldable}; @@ -27,7 +27,7 @@ use rustc::ty::cast::CastTy; use rustc::ty::maps::Providers; use rustc::mir::*; use rustc::mir::traversal::ReversePostorder; -use rustc::mir::transform::{Pass, MirSource}; +use rustc::mir::transform::{DefIdPass, MirSource}; use rustc::mir::visit::{LvalueContext, Visitor}; use rustc::middle::lang_items; use syntax::abi::Abi; @@ -939,25 +939,24 @@ fn qualify_const_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub struct QualifyAndPromoteConstants; -impl Pass for QualifyAndPromoteConstants { +impl DefIdPass for QualifyAndPromoteConstants { fn run_pass<'a, 'tcx>(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>) + tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) { - for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() { - let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id)); - let id = tcx.hir.as_local_node_id(def_id).unwrap(); - let src = MirSource::from_node(tcx, id); + let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id)); + let id = tcx.hir.as_local_node_id(def_id).unwrap(); + let src = MirSource::from_node(tcx, id); - if let MirSource::Const(_) = src { - tcx.mir_const_qualif(def_id); - continue; - } - - let mir = &mut tcx.mir(def_id).borrow_mut(); - tcx.dep_graph.write(DepNode::Mir(def_id)); - - self.run_pass(tcx, src, mir); + if let MirSource::Const(_) = src { + tcx.mir_const_qualif(def_id); + return; } + + let mir = &mut tcx.mir(def_id).borrow_mut(); + tcx.dep_graph.write(DepNode::Mir(def_id)); + + self.run_pass(tcx, src, mir); } }