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;
/// 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<for<'s> 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>,
/// 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<for<'s> 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<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_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);
}
}
}
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);
// 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);
*/
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);
}
}
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>) {
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));
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>)
{}
}
impl<'tcx> MirPassHook<'tcx> for DumpMir {
fn on_mir_pass<'a>(
- &mut self,
+ &self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
src: MirSource,
mir: &Mir<'tcx>,
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);
}
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};
impl<'tcx> MirMapPass<'tcx> for Inline {
fn run_pass<'a>(
- &mut self,
+ &self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
hooks: &mut [Box<for<'s> MirPassHook<'s>>]) {
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);
}
}
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>) {
// 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);
}
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)
}
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<for<'s> MirPassHook<'s>>])
{
}
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);
}
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);
}
}
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
}
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 {
}
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);