diff --git a/src/librustc/dep_graph/safe.rs b/src/librustc/dep_graph/safe.rs index f85f0338ed9..59dce6f6bb0 100644 --- a/src/librustc/dep_graph/safe.rs +++ b/src/librustc/dep_graph/safe.rs @@ -50,6 +50,12 @@ impl DepGraphSafe for (A, B) { } +/// Shared ref to dep-graph-safe stuff should still be dep-graph-safe. +impl<'a, A> DepGraphSafe for &'a A + where A: DepGraphSafe, +{ +} + /// No data here! :) impl DepGraphSafe for () { } diff --git a/src/librustc/mir/transform.rs b/src/librustc/mir/transform.rs index 37113cee4a5..89f2fb59d51 100644 --- a/src/librustc/mir/transform.rs +++ b/src/librustc/mir/transform.rs @@ -18,7 +18,6 @@ use syntax::ast::NodeId; use util::common::time; use std::borrow::Cow; -use std::fmt; /// Where a specific Mir comes from. #[derive(Debug, Copy, Clone)] @@ -73,59 +72,61 @@ impl<'a, 'tcx> MirSource { /// Various information about pass. pub trait Pass { - // fn should_run(Session) to check if pass should run? - fn name<'a>(&self) -> Cow<'static, str> { - let name = unsafe { ::std::intrinsics::type_name::() }; - if let Some(tail) = name.rfind(":") { - Cow::from(&name[tail+1..]) - } else { - Cow::from(name) - } + fn name<'a>(&'a self) -> Cow<'a, str> { + default_name::() } - fn disambiguator<'a>(&'a self) -> Option> { None } + + fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>); } -/// A pass which inspects the whole Mir map. -pub trait MirMapPass<'tcx>: Pass { - fn run_pass<'a>( - &self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - hooks: &mut [Box MirPassHook<'s>>]); +/// Generates a default name for the pass based on the name of the +/// type `T`. +pub fn default_name() -> Cow<'static, str> { + let name = unsafe { ::std::intrinsics::type_name::() }; + if let Some(tail) = name.rfind(":") { + Cow::from(&name[tail+1..]) + } else { + Cow::from(name) + } } -pub trait MirPassHook<'tcx>: Pass { - fn on_mir_pass<'a>( - &self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - src: MirSource, - mir: &Mir<'tcx>, - pass: &Pass, - is_after: bool - ); +pub trait PassHook { + fn on_mir_pass<'a, 'tcx>(&self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + pass: &Pass, + pass_num: usize, + is_after: bool); } -/// A pass which inspects Mir of functions in isolation. -pub trait MirPass<'tcx>: Pass { - fn run_pass<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - src: MirSource, mir: &mut Mir<'tcx>); +/// 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::() + } + + fn run_pass<'a, 'tcx>(&self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + src: MirSource, + mir: &mut Mir<'tcx>); } -impl<'tcx, T: MirPass<'tcx>> MirMapPass<'tcx> for T { - fn run_pass<'a>(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - hooks: &mut [Box MirPassHook<'s>>]) - { +impl Pass for T { + fn name<'a>(&'a self) -> Cow<'a, str> { + MirPass::name(self) + } + + fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) { for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() { - run_hooks(tcx, hooks, self, false); run_map_pass_task(tcx, self, def_id); - run_hooks(tcx, hooks, self, false); } } } -fn run_map_pass_task<'a, 'tcx, T: MirPass<'tcx>>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - pass: &T, - def_id: DefId) { +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(); let id = tcx.hir.as_local_node_id(def_id).expect("mir source requires local def-id"); @@ -138,36 +139,11 @@ fn run_map_pass_task<'a, 'tcx, T: MirPass<'tcx>>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -/// Invokes `hooks` on all the MIR that exists. This is read-only, so -/// new new tasks need to be created. -pub fn run_hooks<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - hooks: &mut [Box MirPassHook<'s>>], - pass: &Pass, - is_after: bool) -{ - for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() { - let mir = tcx.item_mir(def_id); - let id = tcx.hir.as_local_node_id(def_id).expect("mir source requires local def-id"); - - let source = MirSource::from_node(tcx, id); - for hook in &mut *hooks { - hook.on_mir_pass(tcx, source, &mir, pass, is_after); - } - - for (i, mir) in mir.promoted.iter_enumerated() { - let source = MirSource::Promoted(id, i); - for hook in &mut *hooks { - hook.on_mir_pass(tcx, source, &mir, pass, false); - } - } - } -} - /// A manager for MIR passes. pub struct Passes { - passes: Vec MirMapPass<'tcx>>>, - pass_hooks: Vec MirPassHook<'tcx>>>, - plugin_passes: Vec MirMapPass<'tcx>>> + passes: Vec>, + pass_hooks: Vec>, + plugin_passes: Vec> } impl<'a, 'tcx> Passes { @@ -181,27 +157,34 @@ impl<'a, 'tcx> Passes { } pub fn run_passes(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>) { - let Passes { ref mut passes, ref mut plugin_passes, ref mut pass_hooks } = *self; - for pass in plugin_passes.iter_mut().chain(passes.iter_mut()) { - time(tcx.sess.time_passes(), &*pass.name(), - || pass.run_pass(tcx, pass_hooks)); + // NB: passes are numbered from 1, since "construction" is zero. + for (pass, pass_num) in self.plugin_passes.iter().chain(&self.passes).zip(1..) { + for hook in &self.pass_hooks { + hook.on_mir_pass(tcx, &**pass, pass_num, false); + } + + time(tcx.sess.time_passes(), &*pass.name(), || pass.run_pass(tcx)); + + for hook in &self.pass_hooks { + hook.on_mir_pass(tcx, &**pass, pass_num, true); + } } } /// Pushes a built-in pass. - pub fn push_pass(&mut self, pass: Box MirMapPass<'b>>) { + pub fn push_pass(&mut self, pass: Box) { self.passes.push(pass); } /// Pushes a pass hook. - pub fn push_hook(&mut self, hook: Box MirPassHook<'b>>) { + pub fn push_hook(&mut self, hook: Box) { self.pass_hooks.push(hook); } } /// Copies the plugin passes. -impl ::std::iter::Extend MirMapPass<'a>>> for Passes { - fn extend MirMapPass<'a>>>>(&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/session/config.rs b/src/librustc/session/config.rs index d107e9a8485..fdfcd83d5b4 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1003,6 +1003,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "dump MIR state at various points in translation"), dump_mir_dir: Option = (None, parse_opt_string, [UNTRACKED], "the directory the MIR is dumped into"), + dump_mir_exclude_pass_number: bool = (false, parse_bool, [UNTRACKED], + "if set, exclude the pass number when dumping MIR (used in tests)"), perf_stats: bool = (false, parse_bool, [UNTRACKED], "print some performance-related statistics"), hir_stats: bool = (false, parse_bool, [UNTRACKED], diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index 106d8fe952d..4ae8bdc284b 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -16,7 +16,7 @@ use super::{drop_flag_effects_for_location, on_lookup_result_bits}; use super::MoveDataParamEnv; use rustc::ty::{self, TyCtxt}; use rustc::mir::*; -use rustc::mir::transform::{Pass, MirPass, MirSource}; +use rustc::mir::transform::{MirPass, MirSource}; use rustc::middle::const_val::ConstVal; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::indexed_set::IdxSetBuf; @@ -32,9 +32,11 @@ use std::u32; pub struct ElaborateDrops; -impl<'tcx> MirPass<'tcx> for ElaborateDrops { - fn run_pass<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - src: MirSource, mir: &mut Mir<'tcx>) +impl MirPass for ElaborateDrops { + fn run_pass<'a, 'tcx>(&self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + src: MirSource, + mir: &mut Mir<'tcx>) { debug!("elaborate_drops({:?} @ {:?})", src, mir.span); match src { @@ -74,8 +76,6 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops { } } -impl Pass for ElaborateDrops {} - /// Return the set of basic blocks whose unwind edges are known /// to not be reachable, because they are `drop` terminators /// that can't drop anything. diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 5d6bc235761..64fb2168ca1 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -979,8 +979,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, 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_branches::SimplifyBranches::new("initial")); passes.push_pass(box mir::transform::simplify::SimplifyCfg::new("qualify-consts")); // And run everything. passes.run_passes(tcx); diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index 353ca3bbd09..6aa7089e7a9 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -192,7 +192,7 @@ fn build_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) mem::transmute::>(mir) }; - mir_util::dump_mir(tcx, "mir_map", &0, src, &mir); + mir_util::dump_mir(tcx, 0, "mir_map", &0, src, &mir); tcx.alloc_mir(mir) }) @@ -251,7 +251,7 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mem::transmute::>(mir) }; - mir_util::dump_mir(tcx, "mir_map", &0, src, &mir); + mir_util::dump_mir(tcx, 0, "mir_map", &0, src, &mir); tcx.alloc_mir(mir) }) diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs index 9e67beb86e6..b7c7a1774dd 100644 --- a/src/librustc_mir/transform/add_call_guards.rs +++ b/src/librustc_mir/transform/add_call_guards.rs @@ -10,7 +10,7 @@ use rustc::ty::TyCtxt; use rustc::mir::*; -use rustc::mir::transform::{MirPass, MirSource, Pass}; +use rustc::mir::transform::{MirPass, MirSource}; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; pub struct AddCallGuards; @@ -35,8 +35,11 @@ pub struct AddCallGuards; * */ -impl<'tcx> MirPass<'tcx> for AddCallGuards { - fn run_pass<'a>(&self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) { +impl MirPass for AddCallGuards { + fn run_pass<'a, 'tcx>(&self, + _tcx: TyCtxt<'a, 'tcx, 'tcx>, + _src: MirSource, + mir: &mut Mir<'tcx>) { add_call_guards(mir); } } @@ -82,5 +85,3 @@ pub fn add_call_guards(mir: &mut Mir) { mir.basic_blocks_mut().extend(new_blocks); } - -impl Pass for AddCallGuards {} diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs index b7cacfe1296..fbb67161bac 100644 --- a/src/librustc_mir/transform/copy_prop.rs +++ b/src/librustc_mir/transform/copy_prop.rs @@ -30,7 +30,7 @@ //! future. use rustc::mir::{Constant, Local, LocalKind, Location, Lvalue, Mir, Operand, Rvalue, StatementKind}; -use rustc::mir::transform::{MirPass, MirSource, Pass}; +use rustc::mir::transform::{MirPass, MirSource}; use rustc::mir::visit::MutVisitor; use rustc::ty::TyCtxt; use util::def_use::DefUseAnalysis; @@ -38,13 +38,11 @@ use transform::qualify_consts; pub struct CopyPropagation; -impl Pass for CopyPropagation {} - -impl<'tcx> MirPass<'tcx> for CopyPropagation { - fn run_pass<'a>(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - source: MirSource, - mir: &mut Mir<'tcx>) { +impl MirPass for CopyPropagation { + fn run_pass<'a, 'tcx>(&self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + source: MirSource, + mir: &mut Mir<'tcx>) { match source { MirSource::Const(_) => { // Don't run on constants, because constant qualification might reject the diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs index 6d91e6fa55b..4309f91c635 100644 --- a/src/librustc_mir/transform/deaggregator.rs +++ b/src/librustc_mir/transform/deaggregator.rs @@ -10,16 +10,16 @@ use rustc::ty::TyCtxt; use rustc::mir::*; -use rustc::mir::transform::{MirPass, MirSource, Pass}; +use rustc::mir::transform::{MirPass, MirSource}; use rustc_data_structures::indexed_vec::Idx; pub struct Deaggregator; -impl Pass for Deaggregator {} - -impl<'tcx> MirPass<'tcx> for Deaggregator { - fn run_pass<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - source: MirSource, mir: &mut Mir<'tcx>) { +impl MirPass for Deaggregator { + fn run_pass<'a, 'tcx>(&self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + source: MirSource, + mir: &mut Mir<'tcx>) { let node_id = source.item_id(); let node_path = tcx.item_path_str(tcx.hir.local_def_id(node_id)); debug!("running on: {:?}", node_path); diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs index 4c6754b88b6..528afd184c6 100644 --- a/src/librustc_mir/transform/dump_mir.rs +++ b/src/librustc_mir/transform/dump_mir.rs @@ -10,70 +10,71 @@ //! This pass just dumps MIR at a specified point. +use std::borrow::Cow; use std::fmt; use std::fs::File; use std::io; +use rustc::hir::def_id::LOCAL_CRATE; use rustc::session::config::{OutputFilenames, OutputType}; use rustc::ty::TyCtxt; -use rustc::mir::*; -use rustc::mir::transform::{Pass, MirPass, MirPassHook, MirSource}; +use rustc::mir::transform::{Pass, PassHook, MirSource}; use util as mir_util; -pub struct Marker<'a>(pub &'a str); +pub struct Marker(pub &'static str); -impl<'b, 'tcx> MirPass<'tcx> for Marker<'b> { - fn run_pass<'a>(&self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, - _src: MirSource, _mir: &mut Mir<'tcx>) - {} +impl Pass 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>) { + // no-op + } } -impl<'b> Pass for Marker<'b> { - fn name(&self) -> ::std::borrow::Cow<'static, str> { String::from(self.0).into() } -} - -pub struct Disambiguator<'a> { - pass: &'a Pass, +pub struct Disambiguator { is_after: bool } -impl<'a> fmt::Display for Disambiguator<'a> { +impl fmt::Display for Disambiguator { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let title = if self.is_after { "after" } else { "before" }; - if let Some(fmt) = self.pass.disambiguator() { - write!(formatter, "{}-{}", fmt, title) - } else { - write!(formatter, "{}", title) - } + write!(formatter, "{}", title) } } pub struct DumpMir; -impl<'tcx> MirPassHook<'tcx> for DumpMir { - fn on_mir_pass<'a>( +impl PassHook for DumpMir { + fn on_mir_pass<'a, 'tcx>( &self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - src: MirSource, - mir: &Mir<'tcx>, pass: &Pass, + pass_num: usize, is_after: bool) { - mir_util::dump_mir( - tcx, - &*pass.name(), - &Disambiguator { - pass: pass, - is_after: is_after - }, - src, - mir - ); + // No dump filters enabled. + if tcx.sess.opts.debugging_opts.dump_mir.is_none() { + return; + } + + for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() { + let id = tcx.hir.as_local_node_id(def_id).unwrap(); + let source = MirSource::from_node(tcx, id); + let mir = tcx.item_mir(def_id); + mir_util::dump_mir( + tcx, + pass_num, + &*pass.name(), + &Disambiguator { is_after }, + source, + &mir + ); + } } } -impl<'b> Pass for DumpMir {} - pub fn emit_mir<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, outputs: &OutputFilenames) diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index 05e056ed0be..19714849b09 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -16,7 +16,7 @@ use rustc::ty::subst::Substs; use rustc::ty::{Ty, TyCtxt, ClosureSubsts}; use rustc::mir::*; use rustc::mir::visit::MutVisitor; -use rustc::mir::transform::{MirPass, MirSource, Pass}; +use rustc::mir::transform::{MirPass, MirSource}; struct EraseRegionsVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -69,11 +69,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> { pub struct EraseRegions; -impl Pass for EraseRegions {} - -impl<'tcx> MirPass<'tcx> for EraseRegions { - fn run_pass<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - _: MirSource, mir: &mut Mir<'tcx>) { +impl MirPass for EraseRegions { + fn run_pass<'a, 'tcx>(&self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + _: MirSource, + mir: &mut Mir<'tcx>) { EraseRegionsVisitor::new(tcx).visit_mir(mir); } } diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index b11a3c805f9..b0a067063dd 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -10,7 +10,7 @@ //! Inlining pass for MIR functions -use rustc::hir::def_id::{DefId, LOCAL_CRATE}; +use rustc::hir::def_id::DefId; use rustc_data_structures::bitvec::BitVector; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; @@ -18,7 +18,7 @@ use rustc_data_structures::graph; use rustc::dep_graph::DepNode; use rustc::mir::*; -use rustc::mir::transform::{self, MirMapPass, MirPassHook, MirSource, Pass}; +use rustc::mir::transform::{MirSource, Pass}; use rustc::mir::visit::*; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt}; @@ -42,12 +42,8 @@ const UNKNOWN_SIZE_COST: usize = 10; pub struct Inline; -impl<'tcx> MirMapPass<'tcx> for Inline { - fn run_pass<'a>( - &self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - hooks: &mut [Box MirPassHook<'s>>]) { - +impl Pass for Inline { + fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) { if tcx.sess.opts.debugging_opts.mir_opt_level < 2 { return; } let _ignore = tcx.dep_graph.in_ignore(); @@ -58,18 +54,12 @@ impl<'tcx> MirMapPass<'tcx> for Inline { tcx: tcx, }; - transform::run_hooks(tcx, hooks, self, false); - for scc in callgraph.scc_iter() { inliner.inline_scc(&callgraph, &scc); } - - transform::run_hooks(tcx, hooks, self, true); } } -impl<'tcx> Pass for Inline { } - struct Inliner<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, } diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs index 89ac0762fbf..88a368077d4 100644 --- a/src/librustc_mir/transform/instcombine.rs +++ b/src/librustc_mir/transform/instcombine.rs @@ -11,7 +11,7 @@ //! Performs various peephole optimizations. use rustc::mir::{Location, Lvalue, Mir, Operand, ProjectionElem, Rvalue, Local}; -use rustc::mir::transform::{MirPass, MirSource, Pass}; +use rustc::mir::transform::{MirPass, MirSource}; use rustc::mir::visit::{MutVisitor, Visitor}; use rustc::ty::TyCtxt; use rustc::util::nodemap::FxHashSet; @@ -20,13 +20,11 @@ use std::mem; pub struct InstCombine; -impl Pass for InstCombine {} - -impl<'tcx> MirPass<'tcx> for InstCombine { - fn run_pass<'a>(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - _: MirSource, - mir: &mut Mir<'tcx>) { +impl MirPass for InstCombine { + fn run_pass<'a, 'tcx>(&self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + _: MirSource, + mir: &mut Mir<'tcx>) { // We only run when optimizing MIR (at any level). if tcx.sess.opts.debugging_opts.mir_opt_level == 0 { return diff --git a/src/librustc_mir/transform/no_landing_pads.rs b/src/librustc_mir/transform/no_landing_pads.rs index 264b2ea4bb9..8595663ba18 100644 --- a/src/librustc_mir/transform/no_landing_pads.rs +++ b/src/librustc_mir/transform/no_landing_pads.rs @@ -14,10 +14,25 @@ use rustc::ty::TyCtxt; use rustc::mir::*; use rustc::mir::visit::MutVisitor; -use rustc::mir::transform::{Pass, MirPass, MirSource}; +use rustc::mir::transform::{MirPass, MirSource}; pub struct NoLandingPads; +impl MirPass for NoLandingPads { + fn run_pass<'a, 'tcx>(&self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + _: MirSource, + mir: &mut Mir<'tcx>) { + no_landing_pads(tcx, mir) + } +} + +pub fn no_landing_pads<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<'tcx>) { + if tcx.sess.no_landing_pads() { + NoLandingPads.visit_mir(mir); + } +} + impl<'tcx> MutVisitor<'tcx> for NoLandingPads { fn visit_terminator(&mut self, bb: BasicBlock, @@ -41,18 +56,3 @@ impl<'tcx> MutVisitor<'tcx> for NoLandingPads { self.super_terminator(bb, terminator, location); } } - -pub fn no_landing_pads<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<'tcx>) { - if tcx.sess.no_landing_pads() { - NoLandingPads.visit_mir(mir); - } -} - -impl<'tcx> MirPass<'tcx> for NoLandingPads { - fn run_pass<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - _: MirSource, mir: &mut Mir<'tcx>) { - no_landing_pads(tcx, mir) - } -} - -impl Pass for NoLandingPads {} diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index e0948b75f27..7e7e85f2ec9 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -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, MirMapPass, MirPassHook, MirSource}; +use rustc::mir::transform::{Pass, MirSource}; use rustc::mir::visit::{LvalueContext, Visitor}; use rustc::middle::lang_items; use syntax::abi::Abi; @@ -939,12 +939,9 @@ fn qualify_const_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub struct QualifyAndPromoteConstants; -impl Pass for QualifyAndPromoteConstants {} - -impl<'tcx> MirMapPass<'tcx> for QualifyAndPromoteConstants { - fn run_pass<'a>(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - hooks: &mut [Box MirPassHook<'s>>]) +impl Pass for QualifyAndPromoteConstants { + fn run_pass<'a, 'tcx>(&self, + tcx: TyCtxt<'a, 'tcx, 'tcx>) { for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() { let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id)); @@ -959,20 +956,15 @@ impl<'tcx> MirMapPass<'tcx> for QualifyAndPromoteConstants { let mir = &mut tcx.mir(def_id).borrow_mut(); tcx.dep_graph.write(DepNode::Mir(def_id)); - for hook in &mut *hooks { - hook.on_mir_pass(tcx, src, mir, self, false); - } self.run_pass(tcx, src, mir); - for hook in &mut *hooks { - hook.on_mir_pass(tcx, src, mir, self, true); - } } } } -impl<'tcx> QualifyAndPromoteConstants { - fn run_pass<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - src: MirSource, mir: &mut Mir<'tcx>) { +impl<'a, 'tcx> QualifyAndPromoteConstants { + fn run_pass(&self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + src: MirSource, mir: &mut Mir<'tcx>) { let id = src.item_id(); let def_id = tcx.hir.local_def_id(id); let mode = match src { diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 0881585ddfe..d5b79c0d1c3 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -41,15 +41,15 @@ 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, Pass}; +use rustc::mir::transform::{MirPass, MirSource}; use rustc::mir::visit::{MutVisitor, Visitor, LvalueContext}; -use std::fmt; +use std::borrow::Cow; -pub struct SimplifyCfg<'a> { label: &'a str } +pub struct SimplifyCfg { label: String } -impl<'a> SimplifyCfg<'a> { - pub fn new(label: &'a str) -> Self { - SimplifyCfg { label: label } +impl SimplifyCfg { + pub fn new(label: &str) -> Self { + SimplifyCfg { label: format!("SimplifyCfg-{}", label) } } } @@ -61,22 +61,20 @@ pub fn simplify_cfg(mir: &mut Mir) { mir.basic_blocks_mut().raw.shrink_to_fit(); } -impl<'l, 'tcx> MirPass<'tcx> for SimplifyCfg<'l> { - fn run_pass<'a>(&self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) { +impl MirPass for SimplifyCfg { + fn name<'a>(&'a self) -> Cow<'a, str> { + Cow::Borrowed(&self.label) + } + + fn run_pass<'a, 'tcx>(&self, + _tcx: TyCtxt<'a, 'tcx, 'tcx>, + _src: MirSource, + mir: &mut Mir<'tcx>) { debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, mir); simplify_cfg(mir); } } -impl<'l> Pass for SimplifyCfg<'l> { - fn disambiguator<'a>(&'a self) -> Option> { - Some(Box::new(self.label)) - } - - // avoid calling `type_name` - it contains `<'static>` - fn name(&self) -> ::std::borrow::Cow<'static, str> { "SimplifyCfg".into() } -} - pub struct CfgSimplifier<'a, 'tcx: 'a> { basic_blocks: &'a mut IndexVec>, pred_count: IndexVec @@ -315,12 +313,11 @@ pub fn remove_dead_blocks(mir: &mut Mir) { pub struct SimplifyLocals; -impl Pass for SimplifyLocals { - fn name(&self) -> ::std::borrow::Cow<'static, str> { "SimplifyLocals".into() } -} - -impl<'tcx> MirPass<'tcx> for SimplifyLocals { - fn run_pass<'a>(&self, _: TyCtxt<'a, 'tcx, 'tcx>, _: MirSource, mir: &mut Mir<'tcx>) { +impl MirPass for SimplifyLocals { + fn run_pass<'a, 'tcx>(&self, + _: TyCtxt<'a, 'tcx, 'tcx>, + _: MirSource, + mir: &mut Mir<'tcx>) { let mut marker = DeclMarker { locals: BitVector::new(mir.local_decls.len()) }; marker.visit_mir(mir); // Return pointer and arguments are always live diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs index b16ee65e918..d21a6ddfdfb 100644 --- a/src/librustc_mir/transform/simplify_branches.rs +++ b/src/librustc_mir/transform/simplify_branches.rs @@ -12,21 +12,28 @@ use rustc::ty::TyCtxt; use rustc::middle::const_val::ConstVal; -use rustc::mir::transform::{MirPass, MirSource, Pass}; +use rustc::mir::transform::{MirPass, MirSource}; use rustc::mir::*; -use std::fmt; +use std::borrow::Cow; -pub struct SimplifyBranches<'a> { label: &'a str } +pub struct SimplifyBranches { label: String } -impl<'a> SimplifyBranches<'a> { - pub fn new(label: &'a str) -> Self { - SimplifyBranches { label: label } +impl SimplifyBranches { + pub fn new(label: &str) -> Self { + SimplifyBranches { label: format!("SimplifyBranches-{}", label) } } } -impl<'l, 'tcx> MirPass<'tcx> for SimplifyBranches<'l> { - fn run_pass<'a>(&self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) { +impl MirPass for SimplifyBranches { + fn name<'a>(&'a self) -> Cow<'a, str> { + Cow::Borrowed(&self.label) + } + + fn run_pass<'a, 'tcx>(&self, + _tcx: TyCtxt<'a, 'tcx, 'tcx>, + _src: MirSource, + mir: &mut Mir<'tcx>) { for block in mir.basic_blocks_mut() { let terminator = block.terminator_mut(); terminator.kind = match terminator.kind { @@ -60,11 +67,3 @@ impl<'l, 'tcx> MirPass<'tcx> for SimplifyBranches<'l> { } } -impl<'l> Pass for SimplifyBranches<'l> { - fn disambiguator<'a>(&'a self) -> Option> { - Some(Box::new(self.label)) - } - - // avoid calling `type_name` - it contains `<'static>` - fn name(&self) -> ::std::borrow::Cow<'static, str> { "SimplifyBranches".into() } -} diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 02e34fd7998..b325470ec81 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -18,7 +18,7 @@ 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, Pass}; +use rustc::mir::transform::{MirPass, MirSource}; use rustc::mir::visit::Visitor; use std::fmt; use syntax::ast; @@ -737,9 +737,11 @@ impl TypeckMir { } } -impl<'tcx> MirPass<'tcx> for TypeckMir { - fn run_pass<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - src: MirSource, mir: &mut Mir<'tcx>) { +impl MirPass for TypeckMir { + fn run_pass<'a, 'tcx>(&self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + src: MirSource, + mir: &mut Mir<'tcx>) { let item_id = src.item_id(); let def_id = tcx.hir.local_def_id(item_id); debug!("run_pass: {}", tcx.item_path_str(def_id)); @@ -765,6 +767,3 @@ impl<'tcx> MirPass<'tcx> for TypeckMir { }); } } - -impl Pass for TypeckMir { -} diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index c03c9c907a3..6c637f2b2a9 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -28,7 +28,7 @@ const ALIGN: usize = 40; /// representation of the mir into: /// /// ```text -/// rustc.node.. +/// rustc.node... /// ``` /// /// Output from this function is controlled by passing `-Z dump-mir=`, @@ -39,15 +39,16 @@ const ALIGN: usize = 40; /// that can appear in the pass-name or the `item_path_str` for the given /// node-id. If any one of the substrings match, the data is dumped out. pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + pass_num: usize, pass_name: &str, disambiguator: &Display, - src: MirSource, + source: MirSource, mir: &Mir<'tcx>) { let filters = match tcx.sess.opts.debugging_opts.dump_mir { None => return, Some(ref filters) => filters, }; - let node_id = src.item_id(); + let node_id = source.item_id(); let node_path = tcx.item_path_str(tcx.hir.local_def_id(node_id)); let is_matched = filters.split("&") @@ -60,26 +61,47 @@ pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return; } - let promotion_id = match src { + dump_matched_mir_node(tcx, pass_num, pass_name, &node_path, disambiguator, source, mir); + for (index, promoted_mir) in mir.promoted.iter_enumerated() { + let promoted_source = MirSource::Promoted(source.item_id(), index); + dump_matched_mir_node(tcx, pass_num, pass_name, &node_path, disambiguator, + promoted_source, promoted_mir); + } +} + +fn dump_matched_mir_node<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + pass_num: usize, + pass_name: &str, + node_path: &str, + disambiguator: &Display, + source: MirSource, + mir: &Mir<'tcx>) { + let promotion_id = match source { MirSource::Promoted(_, id) => format!("-{:?}", id), _ => String::new() }; + let pass_num = if tcx.sess.opts.debugging_opts.dump_mir_exclude_pass_number { + format!("") + } else { + format!(".{:03}", pass_num) + }; + let mut file_path = PathBuf::new(); if let Some(ref file_dir) = tcx.sess.opts.debugging_opts.dump_mir_dir { let p = Path::new(file_dir); file_path.push(p); }; - let file_name = format!("rustc.node{}{}.{}.{}.mir", - node_id, promotion_id, pass_name, disambiguator); + let file_name = format!("rustc.node{}{}{}.{}.{}.mir", + source.item_id(), promotion_id, pass_num, pass_name, disambiguator); file_path.push(&file_name); let _ = fs::File::create(&file_path).and_then(|mut file| { writeln!(file, "// MIR for `{}`", node_path)?; - writeln!(file, "// node_id = {}", node_id)?; + writeln!(file, "// source = {:?}", source)?; writeln!(file, "// pass_name = {}", pass_name)?; writeln!(file, "// disambiguator = {}", disambiguator)?; writeln!(file, "")?; - write_mir_fn(tcx, src, mir, &mut file)?; + write_mir_fn(tcx, source, mir, &mut file)?; Ok(()) }); } diff --git a/src/test/mir-opt/basic_assignment.rs b/src/test/mir-opt/basic_assignment.rs index 9c924a23903..e4eb1aeaf9b 100644 --- a/src/test/mir-opt/basic_assignment.rs +++ b/src/test/mir-opt/basic_assignment.rs @@ -36,7 +36,7 @@ fn main() { } // END RUST SOURCE -// START rustc.node4.SimplifyCfg.initial-after.mir +// START rustc.node4.SimplifyCfg-initial.after.mir // bb0: { // StorageLive(_1); // _1 = const false; @@ -82,4 +82,4 @@ fn main() { // StorageDead(_1); // return; // } -// END rustc.node4.SimplifyCfg.initial-after.mir +// END rustc.node4.SimplifyCfg-initial.after.mir diff --git a/src/test/mir-opt/issue-38669.rs b/src/test/mir-opt/issue-38669.rs index fbbffe8953b..5a9336e9659 100644 --- a/src/test/mir-opt/issue-38669.rs +++ b/src/test/mir-opt/issue-38669.rs @@ -21,7 +21,7 @@ fn main() { } // END RUST SOURCE -// START rustc.node4.SimplifyCfg.initial-after.mir +// START rustc.node4.SimplifyCfg-initial.after.mir // bb0: { // StorageLive(_1); // _1 = const false; @@ -48,4 +48,4 @@ fn main() { // _2 = (); // goto -> bb1; // } -// END rustc.node4.SimplifyCfg.initial-after.mir +// END rustc.node4.SimplifyCfg-initial.after.mir diff --git a/src/test/mir-opt/simplify_if.rs b/src/test/mir-opt/simplify_if.rs index 6e80a917467..cff108246a5 100644 --- a/src/test/mir-opt/simplify_if.rs +++ b/src/test/mir-opt/simplify_if.rs @@ -15,13 +15,13 @@ fn main() { } // END RUST SOURCE -// START rustc.node4.SimplifyBranches.initial-before.mir +// START rustc.node4.SimplifyBranches-initial.before.mir // bb0: { // switchInt(const false) -> [0u8: bb2, otherwise: bb1]; // } -// END rustc.node4.SimplifyBranches.initial-before.mir -// START rustc.node4.SimplifyBranches.initial-after.mir +// END rustc.node4.SimplifyBranches-initial.before.mir +// START rustc.node4.SimplifyBranches-initial.after.mir // bb0: { // goto -> bb2; // } -// END rustc.node4.SimplifyBranches.initial-after.mir +// END rustc.node4.SimplifyBranches-initial.after.mir diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 731665ce034..a044282666d 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1402,18 +1402,16 @@ actual:\n\ } } MirOpt => { - args.extend(["-Z", - "dump-mir=all", - "-Z", - "mir-opt-level=3", - "-Z"] + args.extend(["-Zdump-mir=all", + "-Zmir-opt-level=3", + "-Zdump-mir-exclude-pass-number"] .iter() .map(|s| s.to_string())); let mir_dump_dir = self.get_mir_dump_dir(); create_dir_all(mir_dump_dir.as_path()).unwrap(); - let mut dir_opt = "dump-mir-dir=".to_string(); + let mut dir_opt = "-Zdump-mir-dir=".to_string(); dir_opt.push_str(mir_dump_dir.to_str().unwrap()); debug!("dir_opt: {:?}", dir_opt);