}
impl<'a, 'tcx> MirSource {
+ pub fn from_local_def_id(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> MirSource {
+ let id = tcx.hir.as_local_node_id(def_id).expect("mir source requires local def-id");
+ Self::from_node(tcx, id)
+ }
+
pub fn from_node(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId) -> MirSource {
use hir::*;
self.pass_hooks.push(Rc::new(hook));
}
- pub fn len_passes(&self, suite: MirSuite) -> usize {
- self.suites[suite.0].len()
- }
-
- pub fn pass(&self, suite: MirSuite, pass: MirPassIndex) -> &MirPass {
- &*self.suites[suite.0][pass.0]
+ pub fn passes(&self, suite: MirSuite) -> &[Rc<MirPass>] {
+ &self.suites[suite.0]
}
pub fn hooks(&self) -> &[Rc<PassHook>] {
}
}
-impl<'tcx> QueryDescription for queries::mir_suite<'tcx> {
- fn describe(_: TyCtxt, (suite, _): (MirSuite, DefId)) -> String {
- format!("MIR suite #{}.*", suite.0)
- }
-}
-
-impl<'tcx> QueryDescription for queries::mir_pass<'tcx> {
- fn describe(_: TyCtxt, (suite, pass_num, _): (MirSuite, MirPassIndex, DefId)) -> String {
- format!("MIR pass #{}.{}", suite.0, pass_num.0)
- }
-}
-
macro_rules! define_maps {
(<$tcx:tt>
$($(#[$attr:meta])*
/// the value isn't known except to the pass itself.
[] mir_const_qualif: Mir(DefId) -> u8,
- /// Performs the initial MIR construction. You almost certainly do not
- /// want to use this query, because its output is intended to be stolen
- /// immediately by the MIR passes below. Consider `optimized_mir` instead.
+ /// Fetch the MIR for a given def-id up till the point where it is
+ /// ready for const evaluation.
///
/// See the README for the `mir` module for details.
- [] mir_build: Mir(DefId) -> &'tcx Steal<mir::Mir<'tcx>>,
+ [] mir_const: Mir(DefId) -> &'tcx Steal<mir::Mir<'tcx>>,
- /// Fetch the MIR for a given def-id after the given set of passes has ben
- /// applied to it. This is mostly an "intermediate" query. Normally, you would
- /// prefer to use `optimized_mir(def_id)`, which will fetch the MIR after all
- /// optimizations and so forth.
- ///
- /// See the README for the `mir` module for details.
- [] mir_suite: mir_suite((MirSuite, DefId)) -> &'tcx Steal<mir::Mir<'tcx>>,
-
- /// Fetch the MIR for a given def-id after a given pass has been executed. This is
- /// **only** intended to be used by the `mir_suite` provider -- if you are using it
- /// manually, you're doing it wrong.
- ///
- /// See the README for the `mir` module for details.
- [] mir_pass: mir_pass((MirSuite, MirPassIndex, DefId)) -> &'tcx Steal<mir::Mir<'tcx>>,
+ [] mir_validated: Mir(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.
fn mir_keys(_: CrateNum) -> DepNode<DefId> {
DepNode::MirKeys
}
-
-fn mir_suite((_suite, def_id): (MirSuite, DefId)) -> DepNode<DefId> {
- DepNode::Mir(def_id)
-}
-
-fn mir_pass((_suite, _pass_num, def_id): (MirSuite, MirPassIndex, DefId)) -> DepNode<DefId> {
- DepNode::Mir(def_id)
-}
use rustc::mir::visit::MutVisitor;
use rustc::traits::Reveal;
use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::steal::Steal;
use rustc::ty::subst::Substs;
use rustc::util::nodemap::NodeMap;
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use syntax_pos::Span;
use util as mir_util;
-pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Mir<'tcx>> {
+/// Construct the MIR for a given def-id.
+pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'tcx> {
let id = tcx.hir.as_local_node_id(def_id).unwrap();
let unsupported = || {
span_bug!(tcx.hir.span(id), "can't build MIR for {:?}", def_id);
mir_util::dump_mir(tcx, None, "mir_map", &0, src, &mir);
- tcx.alloc_steal_mir(mir)
+ mir
})
}
fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
ctor_id: ast::NodeId,
v: &'tcx hir::VariantData)
- -> &'tcx Steal<Mir<'tcx>>
+ -> Mir<'tcx>
{
let span = tcx.hir.span(ctor_id);
if let hir::VariantData::Tuple(ref fields, ctor_id) = *v {
mir_util::dump_mir(tcx, None, "mir_map", &0, src, &mir);
- tcx.alloc_steal_mir(mir)
+ mir
})
} else {
span_bug!(span, "attempting to create MIR for non-tuple variant {:?}", v);
//! - `#[rustc_mir(graphviz="file.gv")]`
//! - `#[rustc_mir(pretty="file.mir")]`
-use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
-
-use rustc::ty::TyCtxt;
+use build;
+use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc::mir::Mir;
+use rustc::mir::transform::{MirSource, MIR_CONST, MIR_VALIDATED, MIR_OPTIMIZED};
+use rustc::ty::{self, TyCtxt};
use rustc::ty::maps::Providers;
+use rustc::ty::steal::Steal;
use rustc::hir;
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::util::nodemap::DefIdSet;
use syntax::ast;
-use syntax_pos::Span;
+use syntax_pos::{DUMMY_SP, Span};
+use transform;
use std::rc::Rc;
pub fn provide(providers: &mut Providers) {
- use build::mir_build;
*providers = Providers {
- mir_build,
mir_keys,
+ mir_const,
+ mir_validated,
+ optimized_mir,
..*providers
};
}
+/// Finds the full set of def-ids within the current crate that have
+/// MIR associated with them.
fn mir_keys<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, krate: CrateNum)
-> Rc<DefIdSet> {
assert_eq!(krate, LOCAL_CRATE);
Rc::new(set)
}
+
+fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Mir<'tcx>> {
+ let mut mir = build::mir_build(tcx, def_id);
+ let source = MirSource::from_local_def_id(tcx, def_id);
+ transform::run_suite(tcx, source, MIR_CONST, &mut mir);
+ tcx.alloc_steal_mir(mir)
+}
+
+fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Mir<'tcx>> {
+ let source = MirSource::from_local_def_id(tcx, def_id);
+ if let MirSource::Const(_) = source {
+ // Ensure that we compute the `mir_const_qualif` for constants at
+ // this point, before we steal the mir-const result. We don't
+ // directly need the result or `mir_const_qualif`, so we can just force it.
+ ty::queries::mir_const_qualif::force(tcx, DUMMY_SP, def_id);
+ }
+
+ let mut mir = tcx.mir_const(def_id).steal();
+ transform::run_suite(tcx, source, MIR_VALIDATED, &mut mir);
+ tcx.alloc_steal_mir(mir)
+}
+
+fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Mir<'tcx> {
+ let mut mir = tcx.mir_validated(def_id).steal();
+ let source = MirSource::from_local_def_id(tcx, def_id);
+ transform::run_suite(tcx, source, MIR_OPTIMIZED, &mut mir);
+ tcx.alloc_mir(mir)
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use rustc::hir::def_id::DefId;
use rustc::mir::Mir;
-use rustc::mir::transform::{MirPassIndex, MirSuite, MirSource, MIR_VALIDATED, MIR_OPTIMIZED};
-use rustc::ty::{self, TyCtxt};
-use rustc::ty::steal::Steal;
+use rustc::mir::transform::{MirPassIndex, MirSuite, MirSource};
+use rustc::ty::TyCtxt;
use rustc::ty::maps::Providers;
-use syntax_pos::DUMMY_SP;
pub mod simplify_branches;
pub mod simplify;
pub mod inline;
pub mod interprocedural;
-pub fn provide(providers: &mut Providers) {
+pub(crate) fn provide(providers: &mut Providers) {
self::qualify_consts::provide(providers);
*providers = Providers {
- optimized_mir,
- mir_suite,
- mir_pass,
..*providers
};
}
-fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Mir<'tcx> {
- let mir = tcx.mir_suite((MIR_OPTIMIZED, def_id)).steal();
- tcx.alloc_mir(mir)
-}
-
-fn mir_suite<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- (suite, def_id): (MirSuite, DefId))
- -> &'tcx Steal<Mir<'tcx>>
+pub(crate) fn run_suite<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ source: MirSource,
+ suite: MirSuite,
+ mir: &mut 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))
-}
+ let passes = tcx.mir_passes.passes(suite);
-fn mir_pass<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- (suite, pass_num, def_id): (MirSuite, MirPassIndex, DefId))
- -> &'tcx Steal<Mir<'tcx>>
-{
- let passes = &tcx.mir_passes;
- let pass = passes.pass(suite, pass_num);
+ for (pass, index) in passes.iter().zip(0..) {
+ let pass_num = MirPassIndex(index);
- 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 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 tcx.mir_passes.hooks() {
+ hook.on_mir_pass(tcx, suite, pass_num, &pass.name(), source, &mir, false);
}
- };
-
- for hook in passes.hooks() {
- hook.on_mir_pass(tcx, suite, pass_num, &pass.name(), source, &mir, false);
- }
- pass.run_pass(tcx, source, &mut mir);
+ pass.run_pass(tcx, source, mir);
- for hook in passes.hooks() {
- hook.on_mir_pass(tcx, suite, pass_num, &pass.name(), source, &mir, true);
+ for hook in tcx.mir_passes.hooks() {
+ hook.on_mir_pass(tcx, suite, pass_num, &pass.name(), source, &mir, true);
+ }
}
-
- tcx.alloc_steal_mir(mir)
}
-
use rustc::ty::maps::Providers;
use rustc::mir::*;
use rustc::mir::traversal::ReversePostorder;
-use rustc::mir::transform::{MirPass, MirSource, MIR_CONST};
+use rustc::mir::transform::{MirPass, MirSource};
use rustc::mir::visit::{LvalueContext, Visitor};
use rustc::middle::lang_items;
use syntax::abi::Abi;
}
pub fn provide(providers: &mut Providers) {
- providers.mir_const_qualif = qualify_const_item;
+ *providers = Providers {
+ mir_const_qualif,
+ ..*providers
+ };
}
-fn qualify_const_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- def_id: DefId)
- -> u8 {
- let mir = &tcx.mir_suite((MIR_CONST, def_id)).borrow();
+fn mir_const_qualif<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ def_id: DefId)
+ -> u8 {
+ // NB: This `borrow()` is guaranteed to be valid (i.e., the value
+ // cannot yet be stolen), because `mir_validated()`, which steals
+ // from `mir_const(), forces this query to execute before
+ // performing the steal.
+ let mir = &tcx.mir_const(def_id).borrow();
+
if mir.return_ty.references_error() {
return Qualif::NOT_CONST.bits();
}