BorrowCheck(D),
RvalueCheck(D),
Reachability,
+ MirKeys,
LateLintCheck,
TransCrateItem(D),
TransInlinedItem(D),
Variance => Some(Variance),
PrivacyAccessLevels(k) => Some(PrivacyAccessLevels(k)),
Reachability => Some(Reachability),
+ MirKeys => Some(MirKeys),
LateLintCheck => Some(LateLintCheck),
TransWriteMetadata => Some(TransWriteMetadata),
pub use self::query::DepGraphQuery;
pub use self::safe::AssertDepGraphSafe;
pub use self::safe::DepGraphSafe;
-pub use self::visit::visit_all_bodies_in_krate;
pub use self::visit::visit_all_item_likes_in_krate;
pub use self::raii::DepTask;
krate.visit_all_item_likes(&mut tracking_visitor)
}
-pub fn visit_all_bodies_in_krate<'a, 'tcx, C>(tcx: TyCtxt<'a, 'tcx, 'tcx>, callback: C)
- where C: Fn(/* body_owner */
- DefId,
- /* body id */
- hir::BodyId)
-{
- let krate = tcx.hir.krate();
- for &body_id in &krate.body_ids {
- let body_owner_def_id = tcx.hir.body_owner_def_id(body_id);
- callback(body_owner_def_id, body_id);
- }
-}
use dep_graph::DepNode;
use hir;
+use hir::def_id::LOCAL_CRATE;
use hir::map::DefPathData;
use mir::{Mir, Promoted};
use ty::TyCtxt;
tcx: TyCtxt<'a, 'tcx, 'tcx>,
hooks: &mut [Box<for<'s> MirPassHook<'s>>])
{
- let def_ids = tcx.maps.mir.borrow().keys();
- for def_id in def_ids {
- if !def_id.is_local() {
- continue;
- }
-
+ 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.maps.mir.borrow()[&def_id].borrow_mut();
+ let mir = &mut tcx.mir(def_id).borrow_mut();
tcx.dep_graph.write(DepNode::Mir(def_id));
let id = tcx.hir.as_local_node_id(def_id).unwrap();
use ty::{self, CrateInherentImpls, Ty, TyCtxt};
use ty::item_path;
use ty::subst::Substs;
-use util::nodemap::NodeSet;
+use util::nodemap::{DefIdSet, NodeSet};
use rustc_data_structures::indexed_vec::IndexVec;
use std::cell::{RefCell, RefMut};
impl<'tcx> QueryDescription for queries::const_eval<'tcx> {
fn describe(tcx: TyCtxt, (def_id, _): (DefId, &'tcx Substs<'tcx>)) -> String {
- format!("const-evaluating `{}`",
- tcx.item_path_str(def_id))
+ format!("const-evaluating `{}`", tcx.item_path_str(def_id))
+ }
+}
+
+impl<'tcx> QueryDescription for queries::mir_keys<'tcx> {
+ fn describe(_: TyCtxt, _: CrateNum) -> String {
+ format!("getting a list of all mir_keys")
}
}
/// (in the `RefCell` sense) to prevent accidental mutation.
[pub] mir: Mir(DefId) -> &'tcx RefCell<mir::Mir<'tcx>>,
+ /// Set of all the def-ids in this crate that have MIR associated with
+ /// them. This includes all the body owners, but also things like struct
+ /// constructors.
+ [] mir_keys: mir_keys(CrateNum) -> Rc<DefIdSet>,
+
/// Maps DefId's that have an associated Mir to the result
/// of the MIR qualify_consts pass. The actual meaning of
/// the value isn't known except to the pass itself.
fn const_eval_dep_node((def_id, _): (DefId, &Substs)) -> DepNode<DefId> {
DepNode::ConstEval(def_id)
}
+
+fn mir_keys(_: CrateNum) -> DepNode<DefId> {
+ DepNode::MirKeys
+}
self.typeck_tables_of(self.hir.body_owner_def_id(body))
}
+ /// Returns an iterator of the def-ids for all body-owners in this
+ /// crate. If you would prefer to iterate over the bodies
+ /// themselves, you can do `self.hir.krate().body_ids.iter()`.
+ pub fn body_owners(self) -> impl Iterator<Item = DefId> + 'a {
+ self.hir.krate()
+ .body_ids
+ .iter()
+ .map(move |&body_id| self.hir.body_owner_def_id(body_id))
+ }
+
pub fn expr_span(self, id: NodeId) -> Span {
match self.hir.find(id) {
Some(hir_map::NodeExpr(e)) => {
/// Given the DefId of an item, returns its MIR, borrowed immutably.
/// Returns None if there is no MIR for the DefId
pub fn maybe_item_mir(self, did: DefId) -> Option<Ref<'gcx, Mir<'gcx>>> {
- if did.is_local() && !self.maps.mir.borrow().contains_key(&did) {
+ if did.is_local() && !self.mir_keys(LOCAL_CRATE).contains(&did) {
return None;
}
dep_graph::visit_all_item_likes_in_krate(self.global_tcx(), dep_node_fn, visitor);
}
- /// Invokes `callback` for each body in the krate. This will
- /// create a read edge from `DepNode::Krate` to the current task;
- /// it is meant to be run in the context of some global task like
- /// `BorrowckCrate`. The callback would then create a task like
- /// `BorrowckBody(DefId)` to process each individual item.
- pub fn visit_all_bodies_in_krate<C>(self, callback: C)
- where C: Fn(/* body_owner */ DefId, /* body id */ hir::BodyId),
- {
- dep_graph::visit_all_bodies_in_krate(self.global_tcx(), callback)
- }
-
/// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err`
/// with the name of the crate containing the impl.
pub fn span_of_impl(self, impl_did: DefId) -> Result<Span, Symbol> {
pub type LoanDataFlow<'a, 'tcx> = DataFlowContext<'a, 'tcx, LoanDataFlowOperator>;
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
- tcx.visit_all_bodies_in_krate(|body_owner_def_id, _body_id| {
+ for body_owner_def_id in tcx.body_owners() {
tcx.borrowck(body_owner_def_id);
- });
+ }
}
pub fn provide(providers: &mut Providers) {
use std::cell::Cell;
use std::fs::File;
use std::io::{self, Write};
-use std::iter;
use std::option;
use std::path::Path;
use std::str::FromStr;
if let Some(nodeid) = nodeid {
let def_id = tcx.hir.local_def_id(nodeid);
match ppm {
- PpmMir => write_mir_pretty(tcx, iter::once(def_id), &mut out),
- PpmMirCFG => write_mir_graphviz(tcx, iter::once(def_id), &mut out),
+ PpmMir => write_mir_pretty(tcx, Some(def_id), &mut out),
+ PpmMirCFG => write_mir_graphviz(tcx, Some(def_id), &mut out),
_ => unreachable!(),
}?;
} else {
match ppm {
- PpmMir => {
- write_mir_pretty(tcx,
- tcx.maps.mir.borrow().keys().into_iter(),
- &mut out)
- }
- PpmMirCFG => {
- write_mir_graphviz(tcx,
- tcx.maps.mir.borrow().keys().into_iter(),
- &mut out)
- }
+ PpmMir => write_mir_pretty(tcx, None, &mut out),
+ PpmMirCFG => write_mir_graphviz(tcx, None, &mut out),
_ => unreachable!(),
}?;
}
fn encode_mir(&mut self, def_id: DefId) -> Option<Lazy<mir::Mir<'tcx>>> {
debug!("EntryBuilder::encode_mir({:?})", def_id);
- self.tcx.maps.mir.borrow().get(&def_id).map(|mir| self.lazy(&*mir.borrow()))
+ if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) {
+ let mir = self.tcx.item_mir(def_id);
+ Some(self.lazy(&mir))
+ } else {
+ None
+ }
}
// Encodes the inherent implementations of a structure, enumeration, or trait.
//!
//! This only considers direct calls
-use rustc::hir::def_id::DefId;
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc_data_structures::graph;
use rustc::mir::*;
// FIXME: allow for construction of a callgraph that inspects
// cross-crate MIRs if available.
pub fn build<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> CallGraph {
- let def_ids = tcx.maps.mir.borrow().keys();
-
let mut callgraph = CallGraph {
node_map: DefIdMap(),
graph: graph::Graph::new()
};
- for def_id in def_ids {
- if !def_id.is_local() { continue; }
-
+ for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() {
let idx = callgraph.add_node(def_id);
let mut call_visitor = CallVisitor {
//! - `#[rustc_mir(pretty="file.mir")]`
use build;
-use rustc::hir::def_id::DefId;
+use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc::dep_graph::DepNode;
use rustc::mir::Mir;
use rustc::mir::transform::MirSource;
use rustc::ty::subst::Substs;
use rustc::hir;
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
+use rustc::util::nodemap::DefIdSet;
use syntax::abi::Abi;
use syntax::ast;
use syntax_pos::Span;
use std::cell::RefCell;
use std::mem;
+use std::rc::Rc;
pub fn build_mir_for_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
tcx.dep_graph.with_task(DepNode::MirKrate, tcx, (), build_mir_for_crate_task);
fn build_mir_for_crate_task<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, (): ()) {
- tcx.visit_all_bodies_in_krate(|body_owner_def_id, _body_id| {
+ for &body_owner_def_id in tcx.mir_keys(LOCAL_CRATE).iter() {
tcx.item_mir(body_owner_def_id);
- });
-
- // Tuple struct/variant constructors don't have a BodyId, so we need
- // to build them separately.
- struct GatherCtors<'a, 'tcx: 'a> {
- tcx: TyCtxt<'a, 'tcx, 'tcx>
- }
- impl<'a, 'tcx> Visitor<'tcx> for GatherCtors<'a, 'tcx> {
- fn visit_variant_data(&mut self,
- v: &'tcx hir::VariantData,
- _: ast::Name,
- _: &'tcx hir::Generics,
- _: ast::NodeId,
- _: Span) {
- if let hir::VariantData::Tuple(_, node_id) = *v {
- self.tcx.item_mir(self.tcx.hir.local_def_id(node_id));
- }
- intravisit::walk_struct_def(self, v)
- }
- fn nested_visit_map<'b>(&'b mut self) -> NestedVisitorMap<'b, 'tcx> {
- NestedVisitorMap::None
- }
}
- tcx.hir.krate().visit_all_item_likes(&mut GatherCtors {
- tcx: tcx
- }.as_deep_visitor());
}
}
pub fn provide(providers: &mut Providers) {
providers.mir = build_mir;
+ providers.mir_keys = mir_keys;
+}
+
+fn mir_keys<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, krate: CrateNum)
+ -> Rc<DefIdSet> {
+ assert_eq!(krate, LOCAL_CRATE);
+
+ let mut set = DefIdSet();
+
+ // All body-owners have MIR associated with them.
+ set.extend(tcx.body_owners());
+
+ // Additionally, tuple struct/variant constructors have MIR, but
+ // they don't have a BodyId, so we need to build them separately.
+ struct GatherCtors<'a, 'tcx: 'a> {
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ set: &'a mut DefIdSet,
+ }
+ impl<'a, 'tcx> Visitor<'tcx> for GatherCtors<'a, 'tcx> {
+ fn visit_variant_data(&mut self,
+ v: &'tcx hir::VariantData,
+ _: ast::Name,
+ _: &'tcx hir::Generics,
+ _: ast::NodeId,
+ _: Span) {
+ if let hir::VariantData::Tuple(_, node_id) = *v {
+ self.set.insert(self.tcx.hir.local_def_id(node_id));
+ }
+ intravisit::walk_struct_def(self, v)
+ }
+ fn nested_visit_map<'b>(&'b mut self) -> NestedVisitorMap<'b, 'tcx> {
+ NestedVisitorMap::None
+ }
+ }
+ tcx.hir.krate().visit_all_item_likes(&mut GatherCtors {
+ tcx: tcx,
+ set: &mut set,
+ }.as_deep_visitor());
+
+ Rc::new(set)
}
fn build_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
{
let path = outputs.path(OutputType::Mir);
let mut f = File::create(&path)?;
- mir_util::write_mir_pretty(tcx, tcx.maps.mir.borrow().keys().into_iter(), &mut f)?;
+ mir_util::write_mir_pretty(tcx, None, &mut f)?;
Ok(())
}
//! Inlining pass for MIR functions
-use rustc::hir::def_id::DefId;
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc_data_structures::bitvec::BitVector;
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
tcx: tcx,
};
- let def_ids = tcx.maps.mir.borrow().keys();
- for &def_id in &def_ids {
- if !def_id.is_local() { continue; }
-
+ for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() {
let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id));
- let mut mir = if let Some(mir) = tcx.maps.mir.borrow().get(&def_id) {
- mir.borrow_mut()
- } else {
- continue;
- };
-
- tcx.dep_graph.write(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, &mut mir, self, false);
+ hook.on_mir_pass(tcx, src, mir, self, false);
}
}
inliner.inline_scc(&callgraph, &scc);
}
- for def_id in def_ids {
- if !def_id.is_local() { continue; }
-
+ for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() {
let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id));
- let mut mir = tcx.maps.mir.borrow()[&def_id].borrow_mut();
- tcx.dep_graph.write(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, &mut mir, self, true);
+ hook.on_mir_pass(tcx, src, mir, self, true);
}
}
}
};
- let mut caller_mir = {
- let map = self.tcx.maps.mir.borrow();
- let mir = map.get(&callsite.caller).unwrap();
- mir.borrow_mut()
- };
+ let mut caller_mir = self.tcx.mir(callsite.caller).borrow_mut();
let start = caller_mir.basic_blocks().len();
let _task = self.tcx.dep_graph.in_task(DepNode::Mir(def_id));
self.tcx.dep_graph.write(DepNode::Mir(def_id));
- let mut caller_mir = {
- let map = self.tcx.maps.mir.borrow();
- let mir = map.get(&def_id).unwrap();
- mir.borrow_mut()
- };
+ let mut caller_mir = self.tcx.mir(def_id).borrow_mut();
debug!("Running simplify cfg on {:?}", def_id);
CfgSimplifier::new(&mut caller_mir).simplify();
use rustc::dep_graph::DepNode;
use rustc::hir;
use rustc::hir::map as hir_map;
-use rustc::hir::def_id::DefId;
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::hir::map::blocks::FnLikeNode;
use rustc::traits::{self, Reveal};
use rustc::ty::{self, TyCtxt, Ty, TypeFoldable};
tcx: TyCtxt<'a, 'tcx, 'tcx>,
hooks: &mut [Box<for<'s> MirPassHook<'s>>])
{
- let def_ids = tcx.maps.mir.borrow().keys();
- for def_id in def_ids {
- if !def_id.is_local() {
- continue;
- }
-
+ for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() {
let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id));
let id = tcx.hir.as_local_node_id(def_id).unwrap();
let src = MirSource::from_node(tcx, id);
continue;
}
- let mir = &mut tcx.maps.mir.borrow()[&def_id].borrow_mut();
+ let mir = &mut tcx.mir(def_id).borrow_mut();
tcx.dep_graph.write(DepNode::Mir(def_id));
for hook in &mut *hooks {
use rustc_data_structures::indexed_vec::Idx;
+use super::pretty::dump_mir_def_ids;
+
/// Write a graphviz DOT graph of a list of MIRs.
-pub fn write_mir_graphviz<'a, 'b, 'tcx, W, I>(tcx: TyCtxt<'b, 'tcx, 'tcx>,
- iter: I,
- w: &mut W)
- -> io::Result<()>
- where W: Write, I: Iterator<Item=DefId>
+pub fn write_mir_graphviz<'a, 'tcx, W>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ single: Option<DefId>,
+ w: &mut W)
+ -> io::Result<()>
+ where W: Write
{
- for def_id in iter {
+ for def_id in dump_mir_def_ids(tcx, single) {
let nodeid = tcx.hir.as_local_node_id(def_id).unwrap();
let mir = &tcx.item_mir(def_id);
// except according to those terms.
use rustc::hir;
-use rustc::hir::def_id::DefId;
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::mir::*;
use rustc::mir::transform::MirSource;
use rustc::ty::TyCtxt;
}
/// Write out a human-readable textual representation for the given MIR.
-pub fn write_mir_pretty<'a, 'b, 'tcx, I>(tcx: TyCtxt<'b, 'tcx, 'tcx>,
- iter: I,
- w: &mut Write)
- -> io::Result<()>
- where I: Iterator<Item=DefId>, 'tcx: 'a
+pub fn write_mir_pretty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ single: Option<DefId>,
+ w: &mut Write)
+ -> io::Result<()>
{
writeln!(w, "// WARNING: This output format is intended for human consumers only")?;
writeln!(w, "// and is subject to change without notice. Knock yourself out.")?;
let mut first = true;
- for def_id in iter.filter(DefId::is_local) {
+ for def_id in dump_mir_def_ids(tcx, single) {
let mir = &tcx.item_mir(def_id);
if first {
Ok(())
}
+
+pub fn dump_mir_def_ids(tcx: TyCtxt, single: Option<DefId>) -> Vec<DefId> {
+ if let Some(i) = single {
+ vec![i]
+ } else {
+ tcx.mir_keys(LOCAL_CRATE).iter().cloned().collect()
+ }
+}
// completely accurate (some things might be counted twice, others missed).
use rustc_const_math::{ConstUsize};
+use rustc::hir::def_id::LOCAL_CRATE;
use rustc::middle::const_val::{ConstVal};
use rustc::mir::{AggregateKind, AssertMessage, BasicBlock, BasicBlockData};
use rustc::mir::{Constant, Literal, Location, LocalDecl};
// For debugging instrumentation like this, we don't need to worry
// about maintaining the dep graph.
let _ignore = tcx.dep_graph.in_ignore();
- let mir_map = tcx.maps.mir.borrow();
- for def_id in mir_map.keys() {
- let mir = mir_map.get(&def_id).unwrap();
- collector.visit_mir(&mir.borrow());
+ for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() {
+ let mir = tcx.item_mir(def_id);
+ collector.visit_mir(&mir);
}
collector.print(title);
}
fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> CompileResult {
debug_assert!(crate_num == LOCAL_CRATE);
tcx.sess.track_errors(|| {
- tcx.visit_all_bodies_in_krate(|body_owner_def_id, _body_id| {
+ for body_owner_def_id in tcx.body_owners() {
tcx.typeck_tables_of(body_owner_def_id);
- });
+ }
})
}