simplify the MirPass traits and passes dramatically

Overall goal: reduce the amount of context a mir pass needs so that it
resembles a query.

- The hooks are no longer "threaded down" to the pass, but rather run
  automatically from the top-level (we also thread down the current pass
  number, so that the files are sorted better).
  - The hook now receives a *single* callback, rather than a callback per-MIR.
- The traits are no longer lifetime parameters, which moved to the
  methods -- given that we required
  `for<'tcx>` objecs, there wasn't much point to that.
- Several passes now store a `String` instead of a `&'l str` (again, no
  point).
This commit is contained in:
Niko Matsakis 2017-04-25 18:23:33 -04:00
parent 11b6b0663a
commit 46b342fbc0
23 changed files with 252 additions and 267 deletions

View File

@ -50,6 +50,12 @@ impl<A, B> 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 () {
}

View File

@ -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::<Self>() };
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::<Self>()
}
fn disambiguator<'a>(&'a self) -> Option<Box<fmt::Display+'a>> { 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<for<'s> MirPassHook<'s>>]);
/// Generates a default name for the pass based on the name of the
/// type `T`.
pub fn default_name<T: ?Sized>() -> Cow<'static, str> {
let name = unsafe { ::std::intrinsics::type_name::<T>() };
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::<Self>()
}
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<for<'s> MirPassHook<'s>>])
{
impl<T: MirPass> 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<for<'s> 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<Box<for<'tcx> MirMapPass<'tcx>>>,
pass_hooks: Vec<Box<for<'tcx> MirPassHook<'tcx>>>,
plugin_passes: Vec<Box<for<'tcx> MirMapPass<'tcx>>>
passes: Vec<Box<Pass>>,
pass_hooks: Vec<Box<PassHook>>,
plugin_passes: Vec<Box<Pass>>
}
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<for<'b> MirMapPass<'b>>) {
pub fn push_pass(&mut self, pass: Box<Pass>) {
self.passes.push(pass);
}
/// Pushes a pass hook.
pub fn push_hook(&mut self, hook: Box<for<'b> MirPassHook<'b>>) {
pub fn push_hook(&mut self, hook: Box<PassHook>) {
self.pass_hooks.push(hook);
}
}
/// Copies the plugin passes.
impl ::std::iter::Extend<Box<for<'a> MirMapPass<'a>>> for Passes {
fn extend<I: IntoIterator<Item=Box<for <'a> MirMapPass<'a>>>>(&mut self, it: I) {
impl ::std::iter::Extend<Box<Pass>> for Passes {
fn extend<I: IntoIterator<Item=Box<Pass>>>(&mut self, it: I) {
self.plugin_passes.extend(it);
}
}

View File

@ -1003,6 +1003,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"dump MIR state at various points in translation"),
dump_mir_dir: Option<String> = (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],

View File

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

View File

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

View File

@ -192,7 +192,7 @@ fn build_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
mem::transmute::<Mir, Mir<'tcx>>(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<'tcx>>(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)
})

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<for<'s> 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>,
}

View File

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

View File

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

View File

@ -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<for<'s> 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 {

View File

@ -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<Box<fmt::Display+'a>> {
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<BasicBlock, BasicBlockData<'tcx>>,
pred_count: IndexVec<BasicBlock, u32>
@ -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

View File

@ -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<Box<fmt::Display+'a>> {
Some(Box::new(self.label))
}
// avoid calling `type_name` - it contains `<'static>`
fn name(&self) -> ::std::borrow::Cow<'static, str> { "SimplifyBranches".into() }
}

View File

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

View File

@ -28,7 +28,7 @@ const ALIGN: usize = 40;
/// representation of the mir into:
///
/// ```text
/// rustc.node<node_id>.<pass_name>.<disambiguator>
/// rustc.node<node_id>.<pass_num>.<pass_name>.<disambiguator>
/// ```
///
/// Output from this function is controlled by passing `-Z dump-mir=<filter>`,
@ -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(())
});
}

View File

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

View File

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

View File

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

View File

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