Skip to content

Commit

Permalink
Auto merge of #37400 - eddyb:lazy-1, r=nikomatsakis
Browse files Browse the repository at this point in the history
[1/n] Move the MIR map into the type context.

*This is part of a series ([prev]() | [next](#37401)) of patches designed to rework rustc into an out-of-order on-demand pipeline model for both better feature support (e.g. [MIR-based](https://github.com/solson/miri) early constant evaluation) and incremental execution of compiler passes (e.g. type-checking), with beneficial consequences to IDE support as well.
If any motivation is unclear, please ask for additional PR description clarifications or code comments.*
<hr>

The first commit reorganizes the `rustc::mir` module to contain the MIR types directly without an extraneous `repr` module which serves no practical purpose but is rather an eyesore.

The second commit performs the actual move of the MIR map into the type context, for the purposes of future integration with requesting analysis/lowering by-products through `TyCtxt`.

Local `Mir` bodies need to be mutated by passes (hence `RefCell`), and at least one pass (`qualify_consts`) needs simultaneous access to multiple `Mir` bodies (hence arena-allocation).
`Mir` bodies loaded from other crates appear as if immutably borrowed (by `.borrow()`-ing one `Ref` and subsequently "leaking" it) to avoid, at least dynamically, *any* possibility of their local mutation.

One caveat is that lint passes can now snoop at the MIR (helpful) or even mutate it (dangerous).
However, lints are unstable anyway and we can find a way to deal with this in due time.
Future work will result in a tighter API, potentially hiding mutation *completely* outside of MIR passes.
  • Loading branch information
bors authored Oct 30, 2016
2 parents 248e7b3 + e34792b commit ef6f743
Show file tree
Hide file tree
Showing 82 changed files with 383 additions and 575 deletions.
11 changes: 1 addition & 10 deletions src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,7 @@ pub mod middle {
pub mod weak_lang_items;
}

pub mod mir {
mod cache;
pub mod repr;
pub mod tcx;
pub mod visit;
pub mod transform;
pub mod traversal;
pub mod mir_map;
}

pub mod mir;
pub mod session;
pub mod traits;
pub mod ty;
Expand Down
16 changes: 6 additions & 10 deletions src/librustc/middle/cstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ use hir::map::definitions::{Definitions, DefKey};
use hir::svh::Svh;
use middle::lang_items;
use ty::{self, Ty, TyCtxt};
use mir::repr::Mir;
use mir::mir_map::MirMap;
use mir::Mir;
use session::Session;
use session::search_paths::PathKind;
use util::nodemap::{NodeSet, DefIdMap};
Expand Down Expand Up @@ -209,8 +208,7 @@ pub trait CrateStore<'tcx> {
fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option<ast::NodeId>;
fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option<DefId>;

fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> Option<Mir<'tcx>>;
fn get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Mir<'tcx>;
fn is_item_mir_available(&self, def: DefId) -> bool;

// This is basically a 1-based range of ints, which is a little
Expand All @@ -228,8 +226,7 @@ pub trait CrateStore<'tcx> {
fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
reexports: &def::ExportMap,
link_meta: &LinkMeta,
reachable: &NodeSet,
mir_map: &MirMap<'tcx>) -> Vec<u8>;
reachable: &NodeSet) -> Vec<u8>;
fn metadata_encoding_version(&self) -> &[u8];
}

Expand Down Expand Up @@ -390,8 +387,8 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
bug!("defid_for_inlined_node")
}

fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> Option<Mir<'tcx>> { bug!("maybe_get_item_mir") }
fn get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> Mir<'tcx> { bug!("get_item_mir") }
fn is_item_mir_available(&self, def: DefId) -> bool {
bug!("is_item_mir_available")
}
Expand All @@ -412,8 +409,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
reexports: &def::ExportMap,
link_meta: &LinkMeta,
reachable: &NodeSet,
mir_map: &MirMap<'tcx>) -> Vec<u8> { vec![] }
reachable: &NodeSet) -> Vec<u8> { vec![] }
fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") }
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/mir/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
use std::cell::{Ref, RefCell};
use rustc_data_structures::indexed_vec::IndexVec;

use mir::repr::{Mir, BasicBlock};
use mir::{Mir, BasicBlock};

use rustc_serialize as serialize;

Expand Down
38 changes: 0 additions & 38 deletions src/librustc/mir/mir_map.rs

This file was deleted.

10 changes: 7 additions & 3 deletions src/librustc/mir/repr.rs → src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ use std::vec::IntoIter;
use syntax::ast::{self, Name};
use syntax_pos::Span;

use super::cache::Cache;
mod cache;
pub mod tcx;
pub mod visit;
pub mod transform;
pub mod traversal;

macro_rules! newtype_index {
($name:ident, $debug_name:expr) => (
Expand Down Expand Up @@ -106,7 +110,7 @@ pub struct Mir<'tcx> {
pub span: Span,

/// A cache for various calculations
cache: Cache
cache: cache::Cache
}

/// where execution begins
Expand Down Expand Up @@ -137,7 +141,7 @@ impl<'tcx> Mir<'tcx> {
upvar_decls: upvar_decls,
spread_arg: None,
span: span,
cache: Cache::new()
cache: cache::Cache::new()
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/mir/tcx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* building is complete.
*/

use mir::repr::*;
use mir::*;
use ty::subst::{Subst, Substs};
use ty::{self, AdtDef, Ty, TyCtxt};
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
Expand Down
21 changes: 12 additions & 9 deletions src/librustc/mir/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
use dep_graph::DepNode;
use hir;
use hir::map::DefPathData;
use mir::mir_map::MirMap;
use mir::repr::{Mir, Promoted};
use mir::{Mir, Promoted};
use ty::TyCtxt;
use syntax::ast::NodeId;
use util::common::time;
Expand Down Expand Up @@ -85,12 +84,11 @@ pub trait Pass {
fn disambiguator<'a>(&'a self) -> Option<Box<fmt::Display+'a>> { None }
}

/// A pass which inspects the whole MirMap.
/// A pass which inspects the whole Mir map.
pub trait MirMapPass<'tcx>: Pass {
fn run_pass<'a>(
&mut self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
map: &mut MirMap<'tcx>,
hooks: &mut [Box<for<'s> MirPassHook<'s>>]);
}

Expand All @@ -114,13 +112,18 @@ pub trait MirPass<'tcx>: Pass {
impl<'tcx, T: MirPass<'tcx>> MirMapPass<'tcx> for T {
fn run_pass<'a>(&mut self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
map: &mut MirMap<'tcx>,
hooks: &mut [Box<for<'s> MirPassHook<'s>>])
{
let def_ids = map.map.keys();
let def_ids = tcx.mir_map.borrow().keys();
for def_id in def_ids {
if !def_id.is_local() {
continue;
}

let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id));
let mir = map.map.get_mut(&def_id).unwrap();
let mir = &mut tcx.mir_map.borrow()[&def_id].borrow_mut();
tcx.dep_graph.write(DepNode::Mir(def_id));

let id = tcx.map.as_local_node_id(def_id).unwrap();
let src = MirSource::from_node(tcx, id);

Expand Down Expand Up @@ -163,11 +166,11 @@ impl<'a, 'tcx> Passes {
passes
}

pub fn run_passes(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, map: &mut MirMap<'tcx>) {
pub fn run_passes(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>) {
let Passes { ref mut passes, ref mut plugin_passes, ref mut pass_hooks } = *self;
for pass in plugin_passes.iter_mut().chain(passes.iter_mut()) {
time(tcx.sess.time_passes(), &*pass.name(),
|| pass.run_pass(tcx, map, pass_hooks));
|| pass.run_pass(tcx, pass_hooks));
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/mir/traversal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use std::vec;
use rustc_data_structures::bitvec::BitVector;
use rustc_data_structures::indexed_vec::Idx;

use super::repr::*;
use super::*;

/// Preorder traversal of a graph.
///
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use middle::const_val::ConstVal;
use hir::def_id::DefId;
use ty::subst::Substs;
use ty::{ClosureSubsts, Region, Ty};
use mir::repr::*;
use mir::*;
use rustc_const_math::ConstUsize;
use rustc_data_structures::tuple_slice::TupleSlice;
use rustc_data_structures::indexed_vec::Idx;
Expand Down
29 changes: 23 additions & 6 deletions src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use middle::free_region::FreeRegionMap;
use middle::region::RegionMaps;
use middle::resolve_lifetime;
use middle::stability;
use mir::Mir;
use ty::subst::{Kind, Substs};
use traits;
use ty::{self, TraitRef, Ty, TypeAndMut};
Expand Down Expand Up @@ -65,8 +66,9 @@ pub struct CtxtArenas<'tcx> {

// references
generics: TypedArena<ty::Generics<'tcx>>,
trait_defs: TypedArena<ty::TraitDef<'tcx>>,
adt_defs: TypedArena<ty::AdtDefData<'tcx, 'tcx>>,
trait_def: TypedArena<ty::TraitDef<'tcx>>,
adt_def: TypedArena<ty::AdtDefData<'tcx, 'tcx>>,
mir: TypedArena<RefCell<Mir<'tcx>>>,
}

impl<'tcx> CtxtArenas<'tcx> {
Expand All @@ -81,8 +83,9 @@ impl<'tcx> CtxtArenas<'tcx> {
layout: TypedArena::new(),

generics: TypedArena::new(),
trait_defs: TypedArena::new(),
adt_defs: TypedArena::new()
trait_def: TypedArena::new(),
adt_def: TypedArena::new(),
mir: TypedArena::new()
}
}
}
Expand Down Expand Up @@ -358,6 +361,15 @@ pub struct GlobalCtxt<'tcx> {

pub map: ast_map::Map<'tcx>,

/// Maps from the def-id of a function/method or const/static
/// to its MIR. Mutation is done at an item granularity to
/// allow MIR optimization passes to function and still
/// access cross-crate MIR (e.g. inlining or const eval).
///
/// Note that cross-crate MIR appears to be always borrowed
/// (in the `RefCell` sense) to prevent accidental mutation.
pub mir_map: RefCell<DepTrackingMap<maps::Mir<'tcx>>>,

// Records the free variables refrenced by every closure
// expression. Do not track deps for this, just recompute it from
// scratch every time.
Expand Down Expand Up @@ -604,6 +616,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
self.global_interners.arenas.generics.alloc(generics)
}

pub fn alloc_mir(self, mir: Mir<'gcx>) -> &'gcx RefCell<Mir<'gcx>> {
self.global_interners.arenas.mir.alloc(RefCell::new(mir))
}

pub fn intern_trait_def(self, def: ty::TraitDef<'gcx>)
-> &'gcx ty::TraitDef<'gcx> {
let did = def.trait_ref.def_id;
Expand All @@ -617,7 +633,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {

pub fn alloc_trait_def(self, def: ty::TraitDef<'gcx>)
-> &'gcx ty::TraitDef<'gcx> {
self.global_interners.arenas.trait_defs.alloc(def)
self.global_interners.arenas.trait_def.alloc(def)
}

pub fn insert_adt_def(self, did: DefId, adt_def: ty::AdtDefMaster<'gcx>) {
Expand All @@ -633,7 +649,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
variants: Vec<ty::VariantDefData<'gcx, 'gcx>>)
-> ty::AdtDefMaster<'gcx> {
let def = ty::AdtDefData::new(self, did, kind, variants);
let interned = self.global_interners.arenas.adt_defs.alloc(def);
let interned = self.global_interners.arenas.adt_def.alloc(def);
self.insert_adt_def(did, interned);
interned
}
Expand Down Expand Up @@ -738,6 +754,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
super_predicates: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
fulfilled_predicates: RefCell::new(fulfilled_predicates),
map: map,
mir_map: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
freevars: RefCell::new(freevars),
maybe_unused_trait_imports: maybe_unused_trait_imports,
tcache: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
Expand Down
4 changes: 4 additions & 0 deletions src/librustc/ty/maps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@

use dep_graph::{DepNode, DepTrackingMapConfig};
use hir::def_id::DefId;
use mir;
use ty::{self, Ty};

use std::cell::RefCell;
use std::marker::PhantomData;
use std::rc::Rc;
use syntax::{attr, ast};
Expand Down Expand Up @@ -43,3 +46,4 @@ dep_map_ty! { InherentImpls: InherentImpls(DefId) -> Vec<DefId> }
dep_map_ty! { TraitItems: TraitItems(DefId) -> Rc<Vec<ty::ImplOrTraitItem<'tcx>>> }
dep_map_ty! { ReprHints: ReprHints(DefId) -> Rc<Vec<attr::ReprAttr>> }
dep_map_ty! { InlinedClosures: Hir(DefId) -> ast::NodeId }
dep_map_ty! { Mir: Mir(DefId) -> &'tcx RefCell<mir::Mir<'tcx>> }
16 changes: 15 additions & 1 deletion src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use hir::def::{Def, CtorKind, PathResolution, ExportMap};
use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
use middle::region::{CodeExtent, ROOT_CODE_EXTENT};
use mir::Mir;
use traits;
use ty;
use ty::subst::{Subst, Substs};
Expand All @@ -34,7 +35,7 @@ use util::nodemap::FnvHashMap;

use serialize::{self, Encodable, Encoder};
use std::borrow::Cow;
use std::cell::{Cell, RefCell};
use std::cell::{Cell, RefCell, Ref};
use std::hash::{Hash, Hasher};
use std::iter;
use std::ops::Deref;
Expand Down Expand Up @@ -2519,6 +2520,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|| self.sess.cstore.item_super_predicates(self.global_tcx(), did))
}

/// Given the did of an item, returns its MIR, borrowed immutably.
pub fn item_mir(self, did: DefId) -> Ref<'gcx, Mir<'gcx>> {
lookup_locally_or_in_crate_store("mir_map", did, &self.mir_map, || {
let mir = self.sess.cstore.get_item_mir(self.global_tcx(), did);
let mir = self.alloc_mir(mir);

// Perma-borrow MIR from extern crates to prevent mutation.
mem::forget(mir.borrow());

mir
}).borrow()
}

/// If `type_needs_drop` returns true, then `ty` is definitely
/// non-copy and *might* have a destructor attached; if it returns
/// false, then `ty` definitely has no destructor (i.e. no drop glue).
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_borrowck/borrowck/mir/abs_domain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
//! `a[x]` would still overlap them both. But that is not this
//! representation does today.)
use rustc::mir::repr::{Lvalue, LvalueElem};
use rustc::mir::repr::{Operand, Projection, ProjectionElem};
use rustc::mir::{Lvalue, LvalueElem};
use rustc::mir::{Operand, Projection, ProjectionElem};

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct AbstractOperand;
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
//! Hook into libgraphviz for rendering dataflow graphs for MIR.
use syntax::ast::NodeId;
use rustc::mir::repr::{BasicBlock, Mir};
use rustc::mir::{BasicBlock, Mir};
use rustc_data_structures::bitslice::bits_to_string;
use rustc_data_structures::indexed_set::{IdxSet};
use rustc_data_structures::indexed_vec::Idx;
Expand Down
Loading

0 comments on commit ef6f743

Please sign in to comment.