From 9c154a67bf5c6841c39afdb90388cc3ba36dc70c Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 1 May 2017 13:46:35 -0400 Subject: [PATCH] rip out everything but `MirPass`, move the logic into suites --- src/librustc/mir/transform.rs | 72 ++--------- src/librustc/ty/maps.rs | 2 +- src/librustc_mir/callgraph.rs | 2 +- src/librustc_mir/transform/dump_mir.rs | 50 +++----- src/librustc_mir/transform/inline.rs | 27 ++--- src/librustc_mir/transform/interprocedural.rs | 28 ++--- src/librustc_mir/transform/mod.rs | 112 +++++++----------- src/librustc_mir/transform/qualify_consts.rs | 35 +----- 8 files changed, 95 insertions(+), 233 deletions(-) diff --git a/src/librustc/mir/transform.rs b/src/librustc/mir/transform.rs index 28b34459b30f..df6f98297d02 100644 --- a/src/librustc/mir/transform.rs +++ b/src/librustc/mir/transform.rs @@ -15,7 +15,6 @@ use hir::def_id::DefId; use hir::map::DefPathData; use mir::{Mir, Promoted}; use ty::TyCtxt; -use std::cell::Ref; use std::rc::Rc; use syntax::ast::NodeId; @@ -83,29 +82,6 @@ pub fn default_name() -> Cow<'static, str> { } } -/// Gives you access to various bits of state during your MIR pass. -pub trait MirCtxt<'a, 'tcx: 'a> { - fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx>; - fn def_id(&self) -> DefId; - fn suite(&self) -> MirSuite; - fn pass_num(&self) -> MirPassIndex; - fn source(&self) -> MirSource; - - // Get a read-only view on the MIR of this def-id from the - // previous pass. - fn read_previous_mir(&self) -> Ref<'tcx, Mir<'tcx>>; - - // Steal the MIR of this def-id from the previous pass; any future - // attempt to access the MIR from the previous pass is a bug. - fn steal_previous_mir(&self) -> Mir<'tcx>; - - // Same as `read_previous_mir()`, but for any def-id you want. - fn read_previous_mir_of(&self, def_id: DefId) -> Ref<'tcx, Mir<'tcx>>; - - // Same as `steal_previous_mir()`, but for any def-id you want. - fn steal_previous_mir_of(&self, def_id: DefId) -> Mir<'tcx>; -} - #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct MirSuite(pub usize); @@ -125,26 +101,19 @@ pub struct MirPassIndex(pub usize); /// the hook will be invoked once per output. pub trait PassHook { fn on_mir_pass<'a, 'tcx: 'a>(&self, - mir_cx: &MirCtxt<'a, 'tcx>, - mir: Option<(DefId, &Mir<'tcx>)>); + 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 an -/// intraprocedural pass; the 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`, which is even more streamlined. -pub trait DefIdPass { - fn name<'a>(&'a self) -> Cow<'a, str> { - default_name::() - } - - fn run_pass<'a, 'tcx: 'a>(&self, mir_cx: &MirCtxt<'a, 'tcx>) -> 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`. @@ -159,32 +128,11 @@ pub trait MirPass { mir: &mut Mir<'tcx>); } -impl DefIdPass for T { - fn name<'a>(&'a self) -> Cow<'a, str> { - MirPass::name(self) - } - - fn run_pass<'a, 'tcx: 'a>(&self, mir_cx: &MirCtxt<'a, 'tcx>) -> Mir<'tcx> { - let tcx = mir_cx.tcx(); - let source = mir_cx.source(); - let mut mir = mir_cx.steal_previous_mir(); - MirPass::run_pass(self, tcx, source, &mut mir); - - let item_id = source.item_id(); - for (promoted_index, promoted_mir) in mir.promoted.iter_enumerated_mut() { - let promoted_source = MirSource::Promoted(item_id, promoted_index); - MirPass::run_pass(self, tcx, promoted_source, promoted_mir); - } - - mir - } -} - /// A manager for MIR passes. #[derive(Clone)] pub struct Passes { pass_hooks: Vec>, - suites: Vec>>, + suites: Vec>>, } /// The number of "pass suites" that we have: @@ -212,7 +160,7 @@ impl<'a, 'tcx> Passes { } /// Pushes a built-in pass. - pub fn push_pass(&mut self, suite: MirSuite, pass: T) { + pub fn push_pass(&mut self, suite: MirSuite, pass: T) { self.suites[suite.0].push(Rc::new(pass)); } @@ -225,7 +173,7 @@ impl<'a, 'tcx> Passes { self.suites[suite.0].len() } - pub fn pass(&self, suite: MirSuite, pass: MirPassIndex) -> &DefIdPass { + pub fn pass(&self, suite: MirSuite, pass: MirPassIndex) -> &MirPass { &*self.suites[suite.0][pass.0] } diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index b37dbc6411ba..b3ca61550d7c 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -818,7 +818,7 @@ define_maps! { <'tcx> /// manually, you're doing it wrong. /// /// See the README for the `mir` module for details. - [multi] mir_pass: mir_pass((MirSuite, MirPassIndex, DefId)) -> &'tcx Steal>, + [] mir_pass: mir_pass((MirSuite, MirPassIndex, DefId)) -> &'tcx Steal>, /// MIR after our optimization passes have run. This is MIR that is ready /// for trans. This is also the only query that can fetch non-local MIR, at present. diff --git a/src/librustc_mir/callgraph.rs b/src/librustc_mir/callgraph.rs index ef271d8b836e..977b9d2e9944 100644 --- a/src/librustc_mir/callgraph.rs +++ b/src/librustc_mir/callgraph.rs @@ -30,7 +30,7 @@ pub struct CallGraph { } impl CallGraph { - pub fn build<'a, 'mir, 'tcx>(cx: &mut InterproceduralCx<'a, 'mir, 'tcx>) -> CallGraph { + pub fn build<'a, 'tcx>(cx: &mut InterproceduralCx<'a, 'tcx>) -> CallGraph { let mut callgraph = CallGraph { node_map: DefIdMap(), graph: graph::Graph::new() diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs index b895a2155859..67a3281dba48 100644 --- a/src/librustc_mir/transform/dump_mir.rs +++ b/src/librustc_mir/transform/dump_mir.rs @@ -15,22 +15,24 @@ use std::fmt; use std::fs::File; use std::io; -use rustc::hir::def_id::DefId; use rustc::mir::Mir; -use rustc::mir::transform::{DefIdPass, MirCtxt, MirSource, PassHook}; +use rustc::mir::transform::{MirPass, MirPassIndex, MirSource, MirSuite, PassHook}; use rustc::session::config::{OutputFilenames, OutputType}; use rustc::ty::TyCtxt; use util as mir_util; pub struct Marker(pub &'static str); -impl DefIdPass for Marker { +impl MirPass for Marker { fn name<'a>(&'a self) -> Cow<'a, str> { Cow::Borrowed(self.0) } - fn run_pass<'a, 'tcx: 'a>(&self, mir_cx: &MirCtxt<'a, 'tcx>) -> Mir<'tcx> { - mir_cx.steal_previous_mir() + fn run_pass<'a, 'tcx>(&self, + _tcx: TyCtxt<'a, 'tcx, 'tcx>, + _source: MirSource, + _mir: &mut Mir<'tcx>) + { } } @@ -49,37 +51,21 @@ pub struct DumpMir; impl PassHook for DumpMir { fn on_mir_pass<'a, 'tcx: 'a>(&self, - mir_cx: &MirCtxt<'a, 'tcx>, - mir: Option<(DefId, &Mir<'tcx>)>) + tcx: TyCtxt<'a, 'tcx, 'tcx>, + suite: MirSuite, + pass_num: MirPassIndex, + pass_name: &str, + source: MirSource, + mir: &Mir<'tcx>, + is_after: bool) { - let tcx = mir_cx.tcx(); - let suite = mir_cx.suite(); - let pass_num = mir_cx.pass_num(); - let pass = tcx.mir_passes.pass(suite, pass_num); - let name = &pass.name(); - let source = match mir { - None => mir_cx.source(), - Some((def_id, _)) => { - let id = tcx.hir.as_local_node_id(def_id) - .expect("mir source requires local def-id"); - MirSource::from_node(tcx, id) - } - }; - if mir_util::dump_enabled(tcx, name, source) { - let previous_mir; - let mir_to_dump = match mir { - Some((_, m)) => m, - None => { - previous_mir = mir_cx.read_previous_mir(); - &*previous_mir - } - }; + if mir_util::dump_enabled(tcx, pass_name, source) { mir_util::dump_mir(tcx, Some((suite, pass_num)), - name, - &Disambiguator { is_after: mir.is_some() }, + pass_name, + &Disambiguator { is_after }, source, - mir_to_dump); + mir); } } } diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 2323b55951d7..caa2aa74ede1 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -18,7 +18,7 @@ use rustc_data_structures::graph; use rustc::dep_graph::DepNode; use rustc::mir::*; -use rustc::mir::transform::{MirCtxt, MirSource, PassId}; +use rustc::mir::transform::{MirSource, PassId}; use rustc::mir::visit::*; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt}; @@ -46,19 +46,14 @@ const UNKNOWN_SIZE_COST: usize = 10; pub struct Inline; pub trait Pass { - fn run_pass<'a, 'tcx: 'a>(&self, mir_cx: &MirCtxt<'a, 'tcx>) + fn run_pass<'a, 'tcx: 'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Multi>>; } impl Pass for Inline { - fn run_pass<'a, 'tcx: 'a>(&self, mir_cx: &MirCtxt<'a, 'tcx>) + fn run_pass<'a, 'tcx: 'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Multi>> { - let tcx = mir_cx.tcx(); - if tcx.sess.opts.debugging_opts.mir_opt_level < 2 { - return Multi::from(tcx.alloc_steal_mir(mir_cx.steal_previous_mir())); - } - - let mut cx = InterproceduralCx::new(mir_cx); + let mut cx = InterproceduralCx::new(tcx); let callgraph = callgraph::CallGraph::build(&mut cx); @@ -72,8 +67,8 @@ impl Pass for Inline { } } -struct Inliner<'mir, 'tcx: 'mir> { - tcx: TyCtxt<'mir, 'tcx, 'tcx>, +struct Inliner<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, } #[derive(Copy, Clone)] @@ -85,11 +80,11 @@ struct CallSite<'tcx> { location: SourceInfo, } -impl<'mir, 'tcx> Inliner<'mir, 'tcx> { - fn inline_scc<'a>(&mut self, - cx: &mut InterproceduralCx<'a, 'mir, 'tcx>, - callgraph: &callgraph::CallGraph, - scc: &[graph::NodeIndex]) -> bool { +impl<'a, 'tcx> Inliner<'a, 'tcx> { + fn inline_scc(&mut self, + cx: &mut InterproceduralCx<'a, 'tcx>, + callgraph: &callgraph::CallGraph, + scc: &[graph::NodeIndex]) -> bool { let tcx = self.tcx; let mut callsites = Vec::new(); let mut in_scc = DefIdSet(); diff --git a/src/librustc_mir/transform/interprocedural.rs b/src/librustc_mir/transform/interprocedural.rs index 02d2b357e043..7a2645567e24 100644 --- a/src/librustc_mir/transform/interprocedural.rs +++ b/src/librustc_mir/transform/interprocedural.rs @@ -10,7 +10,7 @@ use rustc::hir::def_id::DefId; use rustc::mir::Mir; -use rustc::mir::transform::{MirCtxt, PassId}; +use rustc::mir::transform::{PassId}; use rustc::ty::steal::Steal; use rustc::ty::TyCtxt; use rustc_data_structures::fx::FxHashMap; @@ -21,31 +21,21 @@ use rustc_data_structures::fx::FxHashMap; /// stolen and so forth. It is more of a placeholder meant to get /// inlining up and going again, and is probably going to need heavy /// revision as we scale up to more interesting optimizations. -pub struct InterproceduralCx<'a, 'mir: 'a, 'tcx: 'mir> { - pub tcx: TyCtxt<'mir, 'tcx, 'tcx>, - pub mir_cx: &'a MirCtxt<'mir, 'tcx>, +pub struct InterproceduralCx<'a, 'tcx: 'a> { + pub tcx: TyCtxt<'a, 'tcx, 'tcx>, local_cache: FxHashMap>, } -impl<'a, 'mir, 'tcx> InterproceduralCx<'a, 'mir, 'tcx> { - pub fn new(mir_cx: &'a MirCtxt<'mir, 'tcx>) -> Self { +impl<'a, 'tcx> InterproceduralCx<'a, 'tcx> { + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self { InterproceduralCx { - mir_cx, - tcx: mir_cx.tcx(), + tcx: tcx, local_cache: FxHashMap::default(), } } pub fn into_local_mirs(self) -> Vec<(PassId, &'tcx Steal>)> { - let tcx = self.tcx; - let suite = self.mir_cx.suite(); - let pass_num = self.mir_cx.pass_num(); - self.local_cache.into_iter() - .map(|(def_id, mir)| { - let mir = tcx.alloc_steal_mir(mir); - ((suite, pass_num, def_id), mir) - }) - .collect() + unimplemented!() } /// Ensures that the mir for `def_id` is available, if it can be @@ -93,8 +83,6 @@ impl<'a, 'mir, 'tcx> InterproceduralCx<'a, 'mir, 'tcx> { pub fn mir_mut(&mut self, def_id: DefId) -> &mut Mir<'tcx> { assert!(def_id.is_local(), "cannot get mutable mir of remote entry"); - let mir_cx = self.mir_cx; - self.local_cache.entry(def_id) - .or_insert_with(|| mir_cx.steal_previous_mir_of(def_id)) + unimplemented!() } } diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index feef7a197c59..dc67c6f1ef45 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -10,11 +10,11 @@ use rustc::hir::def_id::DefId; use rustc::mir::Mir; -use rustc::mir::transform::{MirCtxt, MirPassIndex, MirSuite, MirSource, MIR_OPTIMIZED, PassId}; +use rustc::mir::transform::{MirPassIndex, MirSuite, MirSource, MIR_VALIDATED, MIR_OPTIMIZED}; +use rustc::ty::{self, TyCtxt}; use rustc::ty::steal::Steal; -use rustc::ty::TyCtxt; -use rustc::ty::maps::{Multi, Providers}; -use std::cell::Ref; +use rustc::ty::maps::Providers; +use syntax_pos::DUMMY_SP; pub mod simplify_branches; pub mod simplify; @@ -51,6 +51,20 @@ fn mir_suite<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, -> &'tcx Steal> { let passes = &tcx.mir_passes; + + if suite == MIR_VALIDATED { + let id = tcx.hir.as_local_node_id(def_id).expect("mir source requires local def-id"); + let source = MirSource::from_node(tcx, id); + if let MirSource::Const(_) = source { + // Ensure that we compute the `mir_const_qualif` for + // constants at this point, before we do any further + // optimization (and before we steal the previous + // MIR). We don't directly need the result, so we can + // just force it. + ty::queries::mir_const_qualif::force(tcx, DUMMY_SP, def_id); + } + } + let len = passes.len_passes(suite); assert!(len > 0, "no passes in {:?}", suite); tcx.mir_pass((suite, MirPassIndex(len - 1), def_id)) @@ -58,82 +72,36 @@ fn mir_suite<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn mir_pass<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, (suite, pass_num, def_id): (MirSuite, MirPassIndex, DefId)) - -> Multi>> + -> &'tcx Steal> { let passes = &tcx.mir_passes; let pass = passes.pass(suite, pass_num); - let mir_ctxt = MirCtxtImpl { tcx, pass_num, suite, def_id }; - for hook in passes.hooks() { - hook.on_mir_pass(&mir_ctxt, None); - } + let id = tcx.hir.as_local_node_id(def_id).expect("mir source requires local def-id"); + let source = MirSource::from_node(tcx, id); - let mir = pass.run_pass(&mir_ctxt); - - for hook in passes.hooks() { - hook.on_mir_pass(&mir_ctxt, Some((def_id, &mir))); - } - - Multi::from(tcx.alloc_steal_mir(mir)) -} - -struct MirCtxtImpl<'a, 'tcx: 'a> { - tcx: TyCtxt<'a, 'tcx, 'tcx>, - pass_num: MirPassIndex, - suite: MirSuite, - def_id: DefId -} - -impl<'a, 'tcx> MirCtxt<'a, 'tcx> for MirCtxtImpl<'a, 'tcx> { - fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { - self.tcx - } - - fn suite(&self) -> MirSuite { - self.suite - } - - fn pass_num(&self) -> MirPassIndex { - self.pass_num - } - - fn def_id(&self) -> DefId { - self.def_id - } - - fn source(&self) -> MirSource { - let id = self.tcx.hir.as_local_node_id(self.def_id) - .expect("mir source requires local def-id"); - MirSource::from_node(self.tcx, id) - } - - fn read_previous_mir(&self) -> Ref<'tcx, Mir<'tcx>> { - self.previous_mir(self.def_id).borrow() - } - - fn steal_previous_mir(&self) -> Mir<'tcx> { - self.previous_mir(self.def_id).steal() - } - - fn read_previous_mir_of(&self, def_id: DefId) -> Ref<'tcx, Mir<'tcx>> { - self.previous_mir(def_id).borrow() - } - - fn steal_previous_mir_of(&self, def_id: DefId) -> Mir<'tcx> { - self.previous_mir(def_id).steal() - } -} - -impl<'a, 'tcx> MirCtxtImpl<'a, 'tcx> { - fn previous_mir(&self, def_id: DefId) -> &'tcx Steal> { - let MirSuite(suite) = self.suite; - let MirPassIndex(pass_num) = self.pass_num; + let mut mir = { + let MirSuite(suite) = suite; + let MirPassIndex(pass_num) = pass_num; if pass_num > 0 { - self.tcx.mir_pass((MirSuite(suite), MirPassIndex(pass_num - 1), def_id)) + tcx.mir_pass((MirSuite(suite), MirPassIndex(pass_num - 1), def_id)).steal() } else if suite > 0 { - self.tcx.mir_suite((MirSuite(suite - 1), def_id)) + tcx.mir_suite((MirSuite(suite - 1), def_id)).steal() } else { - self.tcx.mir_build(def_id) + tcx.mir_build(def_id).steal() } + }; + + for hook in passes.hooks() { + hook.on_mir_pass(tcx, suite, pass_num, &pass.name(), source, &mir, false); } + + pass.run_pass(tcx, source, &mut mir); + + for hook in passes.hooks() { + hook.on_mir_pass(tcx, suite, pass_num, &pass.name(), source, &mir, true); + } + + tcx.alloc_steal_mir(mir) } + diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index c2d2e113f56e..cd37372c2f12 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -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::{DefIdPass, MirCtxt, MirSource, MIR_CONST}; +use rustc::mir::transform::{MirPass, MirSource, MIR_CONST}; use rustc::mir::visit::{LvalueContext, Visitor}; use rustc::middle::lang_items; use syntax::abi::Abi; @@ -938,34 +938,11 @@ fn qualify_const_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub struct QualifyAndPromoteConstants; -impl DefIdPass for QualifyAndPromoteConstants { - fn run_pass<'a, 'tcx: 'a>(&self, mir_cx: &MirCtxt<'a, 'tcx>) -> Mir<'tcx> { - let tcx = mir_cx.tcx(); - match mir_cx.source() { - MirSource::Const(_) => { - // Ensure that we compute the `mir_const_qualif` for - // constants at this point, before we do any further - // optimization (and before we steal the previous - // MIR). We don't directly need the result, so we can - // just force it. - ty::queries::mir_const_qualif::force(tcx, DUMMY_SP, mir_cx.def_id()); - mir_cx.steal_previous_mir() - } - - src => { - let mut mir = mir_cx.steal_previous_mir(); - self.run_pass(tcx, src, &mut mir); - mir - } - } - } -} - -impl<'a, 'tcx> QualifyAndPromoteConstants { - fn run_pass(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - src: MirSource, - mir: &mut Mir<'tcx>) { +impl MirPass for QualifyAndPromoteConstants { + fn run_pass<'a, 'tcx>(&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 {