Skip to content

Commit ef6f743

Browse files
authored
Auto merge of #37400 - eddyb:lazy-1, r=nikomatsakis
[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.
2 parents 248e7b3 + e34792b commit ef6f743

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+383
-575
lines changed

src/librustc/lib.rs

+1-10
Original file line numberDiff line numberDiff line change
@@ -105,16 +105,7 @@ pub mod middle {
105105
pub mod weak_lang_items;
106106
}
107107

108-
pub mod mir {
109-
mod cache;
110-
pub mod repr;
111-
pub mod tcx;
112-
pub mod visit;
113-
pub mod transform;
114-
pub mod traversal;
115-
pub mod mir_map;
116-
}
117-
108+
pub mod mir;
118109
pub mod session;
119110
pub mod traits;
120111
pub mod ty;

src/librustc/middle/cstore.rs

+6-10
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ use hir::map::definitions::{Definitions, DefKey};
2929
use hir::svh::Svh;
3030
use middle::lang_items;
3131
use ty::{self, Ty, TyCtxt};
32-
use mir::repr::Mir;
33-
use mir::mir_map::MirMap;
32+
use mir::Mir;
3433
use session::Session;
3534
use session::search_paths::PathKind;
3635
use util::nodemap::{NodeSet, DefIdMap};
@@ -209,8 +208,7 @@ pub trait CrateStore<'tcx> {
209208
fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option<ast::NodeId>;
210209
fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option<DefId>;
211210

212-
fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
213-
-> Option<Mir<'tcx>>;
211+
fn get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Mir<'tcx>;
214212
fn is_item_mir_available(&self, def: DefId) -> bool;
215213

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

@@ -390,8 +387,8 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
390387
bug!("defid_for_inlined_node")
391388
}
392389

393-
fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
394-
-> Option<Mir<'tcx>> { bug!("maybe_get_item_mir") }
390+
fn get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
391+
-> Mir<'tcx> { bug!("get_item_mir") }
395392
fn is_item_mir_available(&self, def: DefId) -> bool {
396393
bug!("is_item_mir_available")
397394
}
@@ -412,8 +409,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
412409
fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
413410
reexports: &def::ExportMap,
414411
link_meta: &LinkMeta,
415-
reachable: &NodeSet,
416-
mir_map: &MirMap<'tcx>) -> Vec<u8> { vec![] }
412+
reachable: &NodeSet) -> Vec<u8> { vec![] }
417413
fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") }
418414
}
419415

src/librustc/mir/cache.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use std::cell::{Ref, RefCell};
1212
use rustc_data_structures::indexed_vec::IndexVec;
1313

14-
use mir::repr::{Mir, BasicBlock};
14+
use mir::{Mir, BasicBlock};
1515

1616
use rustc_serialize as serialize;
1717

src/librustc/mir/mir_map.rs

-38
This file was deleted.

src/librustc/mir/repr.rs renamed to src/librustc/mir/mod.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@ use std::vec::IntoIter;
3232
use syntax::ast::{self, Name};
3333
use syntax_pos::Span;
3434

35-
use super::cache::Cache;
35+
mod cache;
36+
pub mod tcx;
37+
pub mod visit;
38+
pub mod transform;
39+
pub mod traversal;
3640

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

108112
/// A cache for various calculations
109-
cache: Cache
113+
cache: cache::Cache
110114
}
111115

112116
/// where execution begins
@@ -137,7 +141,7 @@ impl<'tcx> Mir<'tcx> {
137141
upvar_decls: upvar_decls,
138142
spread_arg: None,
139143
span: span,
140-
cache: Cache::new()
144+
cache: cache::Cache::new()
141145
}
142146
}
143147

src/librustc/mir/tcx.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* building is complete.
1414
*/
1515

16-
use mir::repr::*;
16+
use mir::*;
1717
use ty::subst::{Subst, Substs};
1818
use ty::{self, AdtDef, Ty, TyCtxt};
1919
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};

src/librustc/mir/transform.rs

+12-9
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@
1111
use dep_graph::DepNode;
1212
use hir;
1313
use hir::map::DefPathData;
14-
use mir::mir_map::MirMap;
15-
use mir::repr::{Mir, Promoted};
14+
use mir::{Mir, Promoted};
1615
use ty::TyCtxt;
1716
use syntax::ast::NodeId;
1817
use util::common::time;
@@ -85,12 +84,11 @@ pub trait Pass {
8584
fn disambiguator<'a>(&'a self) -> Option<Box<fmt::Display+'a>> { None }
8685
}
8786

88-
/// A pass which inspects the whole MirMap.
87+
/// A pass which inspects the whole Mir map.
8988
pub trait MirMapPass<'tcx>: Pass {
9089
fn run_pass<'a>(
9190
&mut self,
9291
tcx: TyCtxt<'a, 'tcx, 'tcx>,
93-
map: &mut MirMap<'tcx>,
9492
hooks: &mut [Box<for<'s> MirPassHook<'s>>]);
9593
}
9694

@@ -114,13 +112,18 @@ pub trait MirPass<'tcx>: Pass {
114112
impl<'tcx, T: MirPass<'tcx>> MirMapPass<'tcx> for T {
115113
fn run_pass<'a>(&mut self,
116114
tcx: TyCtxt<'a, 'tcx, 'tcx>,
117-
map: &mut MirMap<'tcx>,
118115
hooks: &mut [Box<for<'s> MirPassHook<'s>>])
119116
{
120-
let def_ids = map.map.keys();
117+
let def_ids = tcx.mir_map.borrow().keys();
121118
for def_id in def_ids {
119+
if !def_id.is_local() {
120+
continue;
121+
}
122+
122123
let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id));
123-
let mir = map.map.get_mut(&def_id).unwrap();
124+
let mir = &mut tcx.mir_map.borrow()[&def_id].borrow_mut();
125+
tcx.dep_graph.write(DepNode::Mir(def_id));
126+
124127
let id = tcx.map.as_local_node_id(def_id).unwrap();
125128
let src = MirSource::from_node(tcx, id);
126129

@@ -163,11 +166,11 @@ impl<'a, 'tcx> Passes {
163166
passes
164167
}
165168

166-
pub fn run_passes(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, map: &mut MirMap<'tcx>) {
169+
pub fn run_passes(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>) {
167170
let Passes { ref mut passes, ref mut plugin_passes, ref mut pass_hooks } = *self;
168171
for pass in plugin_passes.iter_mut().chain(passes.iter_mut()) {
169172
time(tcx.sess.time_passes(), &*pass.name(),
170-
|| pass.run_pass(tcx, map, pass_hooks));
173+
|| pass.run_pass(tcx, pass_hooks));
171174
}
172175
}
173176

src/librustc/mir/traversal.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use std::vec;
1313
use rustc_data_structures::bitvec::BitVector;
1414
use rustc_data_structures::indexed_vec::Idx;
1515

16-
use super::repr::*;
16+
use super::*;
1717

1818
/// Preorder traversal of a graph.
1919
///

src/librustc/mir/visit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use middle::const_val::ConstVal;
1212
use hir::def_id::DefId;
1313
use ty::subst::Substs;
1414
use ty::{ClosureSubsts, Region, Ty};
15-
use mir::repr::*;
15+
use mir::*;
1616
use rustc_const_math::ConstUsize;
1717
use rustc_data_structures::tuple_slice::TupleSlice;
1818
use rustc_data_structures::indexed_vec::Idx;

src/librustc/ty/context.rs

+23-6
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use middle::free_region::FreeRegionMap;
2222
use middle::region::RegionMaps;
2323
use middle::resolve_lifetime;
2424
use middle::stability;
25+
use mir::Mir;
2526
use ty::subst::{Kind, Substs};
2627
use traits;
2728
use ty::{self, TraitRef, Ty, TypeAndMut};
@@ -65,8 +66,9 @@ pub struct CtxtArenas<'tcx> {
6566

6667
// references
6768
generics: TypedArena<ty::Generics<'tcx>>,
68-
trait_defs: TypedArena<ty::TraitDef<'tcx>>,
69-
adt_defs: TypedArena<ty::AdtDefData<'tcx, 'tcx>>,
69+
trait_def: TypedArena<ty::TraitDef<'tcx>>,
70+
adt_def: TypedArena<ty::AdtDefData<'tcx, 'tcx>>,
71+
mir: TypedArena<RefCell<Mir<'tcx>>>,
7072
}
7173

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

8385
generics: TypedArena::new(),
84-
trait_defs: TypedArena::new(),
85-
adt_defs: TypedArena::new()
86+
trait_def: TypedArena::new(),
87+
adt_def: TypedArena::new(),
88+
mir: TypedArena::new()
8689
}
8790
}
8891
}
@@ -358,6 +361,15 @@ pub struct GlobalCtxt<'tcx> {
358361

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

364+
/// Maps from the def-id of a function/method or const/static
365+
/// to its MIR. Mutation is done at an item granularity to
366+
/// allow MIR optimization passes to function and still
367+
/// access cross-crate MIR (e.g. inlining or const eval).
368+
///
369+
/// Note that cross-crate MIR appears to be always borrowed
370+
/// (in the `RefCell` sense) to prevent accidental mutation.
371+
pub mir_map: RefCell<DepTrackingMap<maps::Mir<'tcx>>>,
372+
361373
// Records the free variables refrenced by every closure
362374
// expression. Do not track deps for this, just recompute it from
363375
// scratch every time.
@@ -604,6 +616,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
604616
self.global_interners.arenas.generics.alloc(generics)
605617
}
606618

619+
pub fn alloc_mir(self, mir: Mir<'gcx>) -> &'gcx RefCell<Mir<'gcx>> {
620+
self.global_interners.arenas.mir.alloc(RefCell::new(mir))
621+
}
622+
607623
pub fn intern_trait_def(self, def: ty::TraitDef<'gcx>)
608624
-> &'gcx ty::TraitDef<'gcx> {
609625
let did = def.trait_ref.def_id;
@@ -617,7 +633,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
617633

618634
pub fn alloc_trait_def(self, def: ty::TraitDef<'gcx>)
619635
-> &'gcx ty::TraitDef<'gcx> {
620-
self.global_interners.arenas.trait_defs.alloc(def)
636+
self.global_interners.arenas.trait_def.alloc(def)
621637
}
622638

623639
pub fn insert_adt_def(self, did: DefId, adt_def: ty::AdtDefMaster<'gcx>) {
@@ -633,7 +649,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
633649
variants: Vec<ty::VariantDefData<'gcx, 'gcx>>)
634650
-> ty::AdtDefMaster<'gcx> {
635651
let def = ty::AdtDefData::new(self, did, kind, variants);
636-
let interned = self.global_interners.arenas.adt_defs.alloc(def);
652+
let interned = self.global_interners.arenas.adt_def.alloc(def);
637653
self.insert_adt_def(did, interned);
638654
interned
639655
}
@@ -738,6 +754,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
738754
super_predicates: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
739755
fulfilled_predicates: RefCell::new(fulfilled_predicates),
740756
map: map,
757+
mir_map: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
741758
freevars: RefCell::new(freevars),
742759
maybe_unused_trait_imports: maybe_unused_trait_imports,
743760
tcache: RefCell::new(DepTrackingMap::new(dep_graph.clone())),

src/librustc/ty/maps.rs

+4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@
1010

1111
use dep_graph::{DepNode, DepTrackingMapConfig};
1212
use hir::def_id::DefId;
13+
use mir;
1314
use ty::{self, Ty};
15+
16+
use std::cell::RefCell;
1417
use std::marker::PhantomData;
1518
use std::rc::Rc;
1619
use syntax::{attr, ast};
@@ -43,3 +46,4 @@ dep_map_ty! { InherentImpls: InherentImpls(DefId) -> Vec<DefId> }
4346
dep_map_ty! { TraitItems: TraitItems(DefId) -> Rc<Vec<ty::ImplOrTraitItem<'tcx>>> }
4447
dep_map_ty! { ReprHints: ReprHints(DefId) -> Rc<Vec<attr::ReprAttr>> }
4548
dep_map_ty! { InlinedClosures: Hir(DefId) -> ast::NodeId }
49+
dep_map_ty! { Mir: Mir(DefId) -> &'tcx RefCell<mir::Mir<'tcx>> }

src/librustc/ty/mod.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use hir::def::{Def, CtorKind, PathResolution, ExportMap};
2424
use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
2525
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
2626
use middle::region::{CodeExtent, ROOT_CODE_EXTENT};
27+
use mir::Mir;
2728
use traits;
2829
use ty;
2930
use ty::subst::{Subst, Substs};
@@ -34,7 +35,7 @@ use util::nodemap::FnvHashMap;
3435

3536
use serialize::{self, Encodable, Encoder};
3637
use std::borrow::Cow;
37-
use std::cell::{Cell, RefCell};
38+
use std::cell::{Cell, RefCell, Ref};
3839
use std::hash::{Hash, Hasher};
3940
use std::iter;
4041
use std::ops::Deref;
@@ -2519,6 +2520,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
25192520
|| self.sess.cstore.item_super_predicates(self.global_tcx(), did))
25202521
}
25212522

2523+
/// Given the did of an item, returns its MIR, borrowed immutably.
2524+
pub fn item_mir(self, did: DefId) -> Ref<'gcx, Mir<'gcx>> {
2525+
lookup_locally_or_in_crate_store("mir_map", did, &self.mir_map, || {
2526+
let mir = self.sess.cstore.get_item_mir(self.global_tcx(), did);
2527+
let mir = self.alloc_mir(mir);
2528+
2529+
// Perma-borrow MIR from extern crates to prevent mutation.
2530+
mem::forget(mir.borrow());
2531+
2532+
mir
2533+
}).borrow()
2534+
}
2535+
25222536
/// If `type_needs_drop` returns true, then `ty` is definitely
25232537
/// non-copy and *might* have a destructor attached; if it returns
25242538
/// false, then `ty` definitely has no destructor (i.e. no drop glue).

src/librustc_borrowck/borrowck/mir/abs_domain.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
//! `a[x]` would still overlap them both. But that is not this
2222
//! representation does today.)
2323
24-
use rustc::mir::repr::{Lvalue, LvalueElem};
25-
use rustc::mir::repr::{Operand, Projection, ProjectionElem};
24+
use rustc::mir::{Lvalue, LvalueElem};
25+
use rustc::mir::{Operand, Projection, ProjectionElem};
2626

2727
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
2828
pub struct AbstractOperand;

src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
//! Hook into libgraphviz for rendering dataflow graphs for MIR.
1212
1313
use syntax::ast::NodeId;
14-
use rustc::mir::repr::{BasicBlock, Mir};
14+
use rustc::mir::{BasicBlock, Mir};
1515
use rustc_data_structures::bitslice::bits_to_string;
1616
use rustc_data_structures::indexed_set::{IdxSet};
1717
use rustc_data_structures::indexed_vec::Idx;

0 commit comments

Comments
 (0)