use hir::map::DefPathData;
use mir::{Mir, Promoted};
use ty::TyCtxt;
-use std::cell::Ref;
use std::rc::Rc;
use syntax::ast::NodeId;
}
}
-/// 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);
/// 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::<Self>()
- }
-
- 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`.
mir: &mut Mir<'tcx>);
}
-impl<T: MirPass> 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<Rc<PassHook>>,
- suites: Vec<Vec<Rc<DefIdPass>>>,
+ suites: Vec<Vec<Rc<MirPass>>>,
}
/// The number of "pass suites" that we have:
}
/// Pushes a built-in pass.
- pub fn push_pass<T: DefIdPass + 'static>(&mut self, suite: MirSuite, pass: T) {
+ pub fn push_pass<T: MirPass + 'static>(&mut self, suite: MirSuite, pass: T) {
self.suites[suite.0].push(Rc::new(pass));
}
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]
}
/// 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::Mir<'tcx>>,
+ [] mir_pass: mir_pass((MirSuite, MirPassIndex, DefId)) -> &'tcx Steal<mir::Mir<'tcx>>,
/// 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.
}
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()
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>)
+ {
}
}
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);
}
}
}
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};
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<PassId, &'tcx Steal<Mir<'tcx>>>;
}
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<PassId, &'tcx Steal<Mir<'tcx>>> {
- 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);
}
}
-struct Inliner<'mir, 'tcx: 'mir> {
- tcx: TyCtxt<'mir, 'tcx, 'tcx>,
+struct Inliner<'a, 'tcx: 'a> {
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
#[derive(Copy, Clone)]
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();
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;
/// 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<DefId, Mir<'tcx>>,
}
-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<Mir<'tcx>>)> {
- 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
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!()
}
}
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;
-> &'tcx Steal<Mir<'tcx>>
{
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))
fn mir_pass<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
(suite, pass_num, def_id): (MirSuite, MirPassIndex, DefId))
- -> Multi<PassId, &'tcx Steal<Mir<'tcx>>>
+ -> &'tcx Steal<Mir<'tcx>>
{
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);
+ let mut mir = {
+ let MirSuite(suite) = suite;
+ let MirPassIndex(pass_num) = pass_num;
+ if pass_num > 0 {
+ tcx.mir_pass((MirSuite(suite), MirPassIndex(pass_num - 1), def_id)).steal()
+ } else if suite > 0 {
+ tcx.mir_suite((MirSuite(suite - 1), def_id)).steal()
+ } else {
+ tcx.mir_build(def_id).steal()
+ }
+ };
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()
+ hook.on_mir_pass(tcx, suite, pass_num, &pass.name(), source, &mir, false);
}
- fn steal_previous_mir(&self) -> Mir<'tcx> {
- self.previous_mir(self.def_id).steal()
- }
+ pass.run_pass(tcx, source, &mut mir);
- fn read_previous_mir_of(&self, def_id: DefId) -> Ref<'tcx, Mir<'tcx>> {
- self.previous_mir(def_id).borrow()
+ for hook in passes.hooks() {
+ hook.on_mir_pass(tcx, suite, pass_num, &pass.name(), source, &mir, true);
}
- fn steal_previous_mir_of(&self, def_id: DefId) -> Mir<'tcx> {
- self.previous_mir(def_id).steal()
- }
+ tcx.alloc_steal_mir(mir)
}
-impl<'a, 'tcx> MirCtxtImpl<'a, 'tcx> {
- fn previous_mir(&self, def_id: DefId) -> &'tcx Steal<Mir<'tcx>> {
- let MirSuite(suite) = self.suite;
- let MirPassIndex(pass_num) = self.pass_num;
- if pass_num > 0 {
- self.tcx.mir_pass((MirSuite(suite), MirPassIndex(pass_num - 1), def_id))
- } else if suite > 0 {
- self.tcx.mir_suite((MirSuite(suite - 1), def_id))
- } else {
- self.tcx.mir_build(def_id)
- }
- }
-}
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;
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 {