From: Niko Matsakis Date: Tue, 25 Apr 2017 22:22:59 +0000 (-0400) Subject: rework `MirPass` API to be stateless and extract helper fns X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=11b6b0663ae0a89eea913f44aa1eb859b0ef0d3a;p=rust.git rework `MirPass` API to be stateless and extract helper fns --- diff --git a/src/librustc/mir/transform.rs b/src/librustc/mir/transform.rs index 78a3c1919db..37113cee4a5 100644 --- a/src/librustc/mir/transform.rs +++ b/src/librustc/mir/transform.rs @@ -10,7 +10,7 @@ use dep_graph::DepNode; use hir; -use hir::def_id::LOCAL_CRATE; +use hir::def_id::{DefId, LOCAL_CRATE}; use hir::map::DefPathData; use mir::{Mir, Promoted}; use ty::TyCtxt; @@ -88,14 +88,14 @@ fn disambiguator<'a>(&'a self) -> Option> { None } /// A pass which inspects the whole Mir map. pub trait MirMapPass<'tcx>: Pass { fn run_pass<'a>( - &mut self, + &self, tcx: TyCtxt<'a, 'tcx, 'tcx>, hooks: &mut [Box MirPassHook<'s>>]); } pub trait MirPassHook<'tcx>: Pass { fn on_mir_pass<'a>( - &mut self, + &self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &Mir<'tcx>, @@ -106,40 +106,58 @@ fn on_mir_pass<'a>( /// A pass which inspects Mir of functions in isolation. pub trait MirPass<'tcx>: Pass { - fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, + fn run_pass<'a>(&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>(&mut self, + fn run_pass<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, hooks: &mut [Box MirPassHook<'s>>]) { for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() { - let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id)); - let mir = &mut tcx.mir(def_id).borrow_mut(); - tcx.dep_graph.write(DepNode::Mir(def_id)); + run_hooks(tcx, hooks, self, false); + run_map_pass_task(tcx, self, def_id); + run_hooks(tcx, hooks, self, false); + } + } +} - let id = tcx.hir.as_local_node_id(def_id).unwrap(); - let src = MirSource::from_node(tcx, id); +fn run_map_pass_task<'a, 'tcx, T: MirPass<'tcx>>(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"); + let source = MirSource::from_node(tcx, id); + MirPass::run_pass(pass, tcx, 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 hook in &mut *hooks { - hook.on_mir_pass(tcx, src, mir, self, false); - } - MirPass::run_pass(self, tcx, src, mir); - for hook in &mut *hooks { - hook.on_mir_pass(tcx, src, mir, self, true); - } +/// 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_mut() { - let src = MirSource::Promoted(id, i); - for hook in &mut *hooks { - hook.on_mir_pass(tcx, src, mir, self, false); - } - MirPass::run_pass(self, tcx, src, mir); - for hook in &mut *hooks { - hook.on_mir_pass(tcx, src, mir, self, true); - } + 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); } } } diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index ca313622a3a..106d8fe952d 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -33,7 +33,7 @@ pub struct ElaborateDrops; impl<'tcx> MirPass<'tcx> for ElaborateDrops { - fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, + fn run_pass<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &mut Mir<'tcx>) { debug!("elaborate_drops({:?} @ {:?})", src, mir.span); diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index aa33d4b5539..5d6bc235761 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -1056,7 +1056,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // 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::new()); + 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); diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs index 80b17c6a008..9e67beb86e6 100644 --- a/src/librustc_mir/transform/add_call_guards.rs +++ b/src/librustc_mir/transform/add_call_guards.rs @@ -36,7 +36,7 @@ */ impl<'tcx> MirPass<'tcx> for AddCallGuards { - fn run_pass<'a>(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) { + fn run_pass<'a>(&self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) { add_call_guards(mir); } } diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs index 5d127a5aed4..b7cacfe1296 100644 --- a/src/librustc_mir/transform/copy_prop.rs +++ b/src/librustc_mir/transform/copy_prop.rs @@ -41,7 +41,7 @@ impl Pass for CopyPropagation {} impl<'tcx> MirPass<'tcx> for CopyPropagation { - fn run_pass<'a>(&mut self, + fn run_pass<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, source: MirSource, mir: &mut Mir<'tcx>) { diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs index 3a93bef36c5..6d91e6fa55b 100644 --- a/src/librustc_mir/transform/deaggregator.rs +++ b/src/librustc_mir/transform/deaggregator.rs @@ -18,7 +18,7 @@ impl Pass for Deaggregator {} impl<'tcx> MirPass<'tcx> for Deaggregator { - fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, + fn run_pass<'a>(&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)); diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs index 6895facd6af..4c6754b88b6 100644 --- a/src/librustc_mir/transform/dump_mir.rs +++ b/src/librustc_mir/transform/dump_mir.rs @@ -23,7 +23,7 @@ pub struct Marker<'a>(pub &'a str); impl<'b, 'tcx> MirPass<'tcx> for Marker<'b> { - fn run_pass<'a>(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, + fn run_pass<'a>(&self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, _mir: &mut Mir<'tcx>) {} } @@ -52,7 +52,7 @@ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { impl<'tcx> MirPassHook<'tcx> for DumpMir { fn on_mir_pass<'a>( - &mut self, + &self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &Mir<'tcx>, diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index 5cc5cf29793..05e056ed0be 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -72,7 +72,7 @@ fn visit_closure_substs(&mut self, impl Pass for EraseRegions {} impl<'tcx> MirPass<'tcx> for EraseRegions { - fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, + fn run_pass<'a>(&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 fcd5f970882..b11a3c805f9 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -18,7 +18,7 @@ use rustc::dep_graph::DepNode; use rustc::mir::*; -use rustc::mir::transform::{MirMapPass, MirPassHook, MirSource, Pass}; +use rustc::mir::transform::{self, MirMapPass, MirPassHook, MirSource, Pass}; use rustc::mir::visit::*; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt}; @@ -44,7 +44,7 @@ impl<'tcx> MirMapPass<'tcx> for Inline { fn run_pass<'a>( - &mut self, + &self, tcx: TyCtxt<'a, 'tcx, 'tcx>, hooks: &mut [Box MirPassHook<'s>>]) { @@ -58,33 +58,13 @@ fn run_pass<'a>( tcx: tcx, }; - for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() { - let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id)); - let mir = &tcx.item_mir(def_id); - - let id = tcx.hir.as_local_node_id(def_id).unwrap(); - let src = MirSource::from_node(tcx, id); - - for hook in &mut *hooks { - hook.on_mir_pass(tcx, src, mir, self, false); - } - } + transform::run_hooks(tcx, hooks, self, false); for scc in callgraph.scc_iter() { inliner.inline_scc(&callgraph, &scc); } - for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() { - let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id)); - let mir = &tcx.item_mir(def_id); - - let id = tcx.hir.as_local_node_id(def_id).unwrap(); - let src = MirSource::from_node(tcx, id); - - for hook in &mut *hooks { - hook.on_mir_pass(tcx, src, mir, self, true); - } - } + transform::run_hooks(tcx, hooks, self, true); } } diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs index 3f6abb31fe9..89ac0762fbf 100644 --- a/src/librustc_mir/transform/instcombine.rs +++ b/src/librustc_mir/transform/instcombine.rs @@ -18,22 +18,12 @@ use rustc_data_structures::indexed_vec::Idx; use std::mem; -pub struct InstCombine { - optimizations: OptimizationList, -} - -impl InstCombine { - pub fn new() -> InstCombine { - InstCombine { - optimizations: OptimizationList::default(), - } - } -} +pub struct InstCombine; impl Pass for InstCombine {} impl<'tcx> MirPass<'tcx> for InstCombine { - fn run_pass<'a>(&mut self, + fn run_pass<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, _: MirSource, mir: &mut Mir<'tcx>) { @@ -45,18 +35,22 @@ fn run_pass<'a>(&mut self, // First, find optimization opportunities. This is done in a pre-pass to keep the MIR // read-only so that we can do global analyses on the MIR in the process (e.g. // `Lvalue::ty()`). - { + let optimizations = { let mut optimization_finder = OptimizationFinder::new(mir, tcx); optimization_finder.visit_mir(mir); - self.optimizations = optimization_finder.optimizations - } + optimization_finder.optimizations + }; // Then carry out those optimizations. - MutVisitor::visit_mir(&mut *self, mir); + MutVisitor::visit_mir(&mut InstCombineVisitor { optimizations }, mir); } } -impl<'tcx> MutVisitor<'tcx> for InstCombine { +pub struct InstCombineVisitor { + optimizations: OptimizationList, +} + +impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor { fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) { if self.optimizations.and_stars.remove(&location) { debug!("Replacing `&*`: {:?}", rvalue); diff --git a/src/librustc_mir/transform/no_landing_pads.rs b/src/librustc_mir/transform/no_landing_pads.rs index 3654ae6940c..264b2ea4bb9 100644 --- a/src/librustc_mir/transform/no_landing_pads.rs +++ b/src/librustc_mir/transform/no_landing_pads.rs @@ -49,7 +49,7 @@ pub fn no_landing_pads<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<'tcx } impl<'tcx> MirPass<'tcx> for NoLandingPads { - fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, + fn run_pass<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, _: MirSource, mir: &mut Mir<'tcx>) { no_landing_pads(tcx, mir) } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index f5662295296..e0948b75f27 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -942,7 +942,7 @@ fn qualify_const_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl Pass for QualifyAndPromoteConstants {} impl<'tcx> MirMapPass<'tcx> for QualifyAndPromoteConstants { - fn run_pass<'a>(&mut self, + fn run_pass<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, hooks: &mut [Box MirPassHook<'s>>]) { @@ -971,7 +971,7 @@ fn run_pass<'a>(&mut self, } impl<'tcx> QualifyAndPromoteConstants { - fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, + fn run_pass<'a>(&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); diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index ef7990653ba..0881585ddfe 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -62,7 +62,7 @@ pub fn simplify_cfg(mir: &mut Mir) { } impl<'l, 'tcx> MirPass<'tcx> for SimplifyCfg<'l> { - fn run_pass<'a>(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) { + fn run_pass<'a>(&self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) { debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, mir); simplify_cfg(mir); } @@ -320,7 +320,7 @@ fn name(&self) -> ::std::borrow::Cow<'static, str> { "SimplifyLocals".into() } } impl<'tcx> MirPass<'tcx> for SimplifyLocals { - fn run_pass<'a>(&mut self, _: TyCtxt<'a, 'tcx, 'tcx>, _: MirSource, mir: &mut Mir<'tcx>) { + fn run_pass<'a>(&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 3d5106c4b06..b16ee65e918 100644 --- a/src/librustc_mir/transform/simplify_branches.rs +++ b/src/librustc_mir/transform/simplify_branches.rs @@ -26,7 +26,7 @@ pub fn new(label: &'a str) -> Self { } impl<'l, 'tcx> MirPass<'tcx> for SimplifyBranches<'l> { - fn run_pass<'a>(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) { + fn run_pass<'a>(&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 { diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index d2e4c1a9649..02e34fd7998 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -738,7 +738,7 @@ pub fn new() -> Self { } impl<'tcx> MirPass<'tcx> for TypeckMir { - fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, + fn run_pass<'a>(&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);