introduce DefIdPass and remove all impls of Pass but Inline

This commit is contained in:
Niko Matsakis 2017-04-27 11:46:17 -04:00
parent 46b342fbc0
commit e9e6ccc042
5 changed files with 95 additions and 70 deletions

View File

@ -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::<Self>()
}
fn run_pass<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
src: MirSource,
mir: &mut Mir<'tcx>);
def_id: DefId);
}
impl<T: MirPass> Pass for T {
impl<T: DefIdPass> 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::<Self>()
}
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<T: MirPass> 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<Box<Pass>>,
pass_hooks: Vec<Box<PassHook>>,
plugin_passes: Vec<Box<Pass>>
passes: Vec<Rc<Pass>>,
pass_hooks: Vec<Rc<PassHook>>,
plugin_passes: Vec<Rc<Pass>>
}
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<Pass>) {
self.passes.push(pass);
pub fn push_pass<T: Pass + 'static>(&mut self, pass: T) {
self.passes.push(Rc::new(pass));
}
/// Pushes a pass hook.
pub fn push_hook(&mut self, hook: Box<PassHook>) {
self.pass_hooks.push(hook);
pub fn push_hook<T: PassHook + 'static>(&mut self, hook: T) {
self.pass_hooks.push(Rc::new(hook));
}
}
/// Copies the plugin passes.
impl ::std::iter::Extend<Box<Pass>> for Passes {
fn extend<I: IntoIterator<Item=Box<Pass>>>(&mut self, it: I) {
impl ::std::iter::Extend<Rc<Pass>> for Passes {
fn extend<I: IntoIterator<Item=Rc<Pass>>>(&mut self, it: I) {
self.plugin_passes.extend(it);
}
}

View File

@ -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<'tcx>>,
[] mir: Mir(DefId) -> &'tcx RefCell<mir::Mir<'tcx>>,
/// 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

View File

@ -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 youre 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);
});

View File

@ -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
}
}

View File

@ -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);
}
}