提交 9c154a67 编写于 作者: N Niko Matsakis

rip out everything but `MirPass`, move the logic into suites

上级 c253df52
......@@ -15,7 +15,6 @@
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<T: ?Sized>() -> 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 trait MirCtxt<'a, 'tcx: 'a> {
/// 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`.
......@@ -159,32 +128,11 @@ fn run_pass<'a, 'tcx>(&self,
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:
......@@ -212,7 +160,7 @@ pub fn new() -> Passes {
}
/// 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));
}
......@@ -225,7 +173,7 @@ pub fn len_passes(&self, suite: MirSuite) -> usize {
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]
}
......
......@@ -818,7 +818,7 @@ fn default() -> Self {
/// 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.
......
......@@ -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()
......
......@@ -15,22 +15,24 @@
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 @@ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
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);
}
}
}
......
......@@ -18,7 +18,7 @@
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 @@
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);
......@@ -72,8 +67,8 @@ fn run_pass<'a, 'tcx: 'a>(&self, mir_cx: &MirCtxt<'a, 'tcx>)
}
}
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();
......
......@@ -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 @@
/// 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
......@@ -93,8 +83,6 @@ pub fn mir(&self, def_id: DefId) -> Option<&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!()
}
}
......@@ -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<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))
......@@ -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<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)
}
}
}
......@@ -26,7 +26,7 @@
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 {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册