From e34792b181ab6af0221c0fb35940b1cc5dc476e1 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Fri, 28 Oct 2016 13:55:49 +0300 Subject: [PATCH] rustc: move the MIR map into TyCtxt. --- src/librustc/middle/cstore.rs | 14 +- src/librustc/mir/mir_map.rs | 38 ---- src/librustc/mir/mod.rs | 1 - src/librustc/mir/transform.rs | 19 +- src/librustc/ty/context.rs | 29 ++- src/librustc/ty/maps.rs | 4 + src/librustc/ty/mod.rs | 16 +- src/librustc_borrowck/borrowck/mir/mod.rs | 24 +-- src/librustc_borrowck/borrowck/mod.rs | 17 +- src/librustc_driver/driver.rs | 53 ++---- src/librustc_driver/pretty.rs | 57 +++--- src/librustc_metadata/cstore_impl.rs | 13 +- src/librustc_metadata/encoder.rs | 8 +- src/librustc_mir/graphviz.rs | 4 +- src/librustc_mir/mir_map.rs | 39 ++-- src/librustc_mir/pretty.rs | 4 +- src/librustc_mir/transform/qualify_consts.rs | 179 ++++++++---------- src/librustc_trans/base.rs | 8 +- src/librustc_trans/collector.rs | 16 +- src/librustc_trans/common.rs | 18 +- src/librustc_trans/context.rs | 46 ----- .../debuginfo/create_scope_map.rs | 2 +- src/librustc_trans/lib.rs | 1 + src/librustc_trans/mir/constant.rs | 4 +- src/librustc_trans/mir/mod.rs | 23 +-- src/librustdoc/core.rs | 2 +- 26 files changed, 231 insertions(+), 408 deletions(-) delete mode 100644 src/librustc/mir/mir_map.rs diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 43b0491758dda..c88af45124b18 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -30,7 +30,6 @@ use hir::svh::Svh; use middle::lang_items; use ty::{self, Ty, TyCtxt}; use mir::Mir; -use mir::mir_map::MirMap; use session::Session; use session::search_paths::PathKind; use util::nodemap::{NodeSet, DefIdMap}; @@ -209,8 +208,7 @@ pub trait CrateStore<'tcx> { fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option; fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option; - fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Option>; + 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 @@ -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; + reachable: &NodeSet) -> Vec; fn metadata_encoding_version(&self) -> &[u8]; } @@ -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> { 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") } @@ -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 { vec![] } + reachable: &NodeSet) -> Vec { vec![] } fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") } } diff --git a/src/librustc/mir/mir_map.rs b/src/librustc/mir/mir_map.rs deleted file mode 100644 index 56355941b5706..0000000000000 --- a/src/librustc/mir/mir_map.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig}; -use hir::def_id::DefId; -use mir::Mir; -use std::marker::PhantomData; - -pub struct MirMap<'tcx> { - pub map: DepTrackingMap>, -} - -impl<'tcx> MirMap<'tcx> { - pub fn new(graph: DepGraph) -> Self { - MirMap { - map: DepTrackingMap::new(graph) - } - } -} - -pub struct MirMapConfig<'tcx> { - data: PhantomData<&'tcx ()> -} - -impl<'tcx> DepTrackingMapConfig for MirMapConfig<'tcx> { - type Key = DefId; - type Value = Mir<'tcx>; - fn to_dep_node(key: &DefId) -> DepNode { - DepNode::Mir(*key) - } -} diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index cda71ac225c58..994316d05ec78 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -37,7 +37,6 @@ pub mod tcx; pub mod visit; pub mod transform; pub mod traversal; -pub mod mir_map; macro_rules! newtype_index { ($name:ident, $debug_name:expr) => ( diff --git a/src/librustc/mir/transform.rs b/src/librustc/mir/transform.rs index c6a719abe54b6..3576ae662a005 100644 --- a/src/librustc/mir/transform.rs +++ b/src/librustc/mir/transform.rs @@ -11,7 +11,6 @@ use dep_graph::DepNode; use hir; use hir::map::DefPathData; -use mir::mir_map::MirMap; use mir::{Mir, Promoted}; use ty::TyCtxt; use syntax::ast::NodeId; @@ -85,12 +84,11 @@ pub trait Pass { fn disambiguator<'a>(&'a self) -> Option> { 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 MirPassHook<'s>>]); } @@ -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 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); @@ -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)); } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 8c7a2da3be7fa..62cc78141db46 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -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}; @@ -65,8 +66,9 @@ pub struct CtxtArenas<'tcx> { // references generics: TypedArena>, - trait_defs: TypedArena>, - adt_defs: TypedArena>, + trait_def: TypedArena>, + adt_def: TypedArena>, + mir: TypedArena>>, } impl<'tcx> CtxtArenas<'tcx> { @@ -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() } } } @@ -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>>, + // Records the free variables refrenced by every closure // expression. Do not track deps for this, just recompute it from // scratch every time. @@ -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> { + 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; @@ -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>) { @@ -633,7 +649,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { variants: Vec>) -> 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 } @@ -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())), diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 3a552a8b437d3..cad87081a93b4 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -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}; @@ -43,3 +46,4 @@ dep_map_ty! { InherentImpls: InherentImpls(DefId) -> Vec } dep_map_ty! { TraitItems: TraitItems(DefId) -> Rc>> } dep_map_ty! { ReprHints: ReprHints(DefId) -> Rc> } dep_map_ty! { InlinedClosures: Hir(DefId) -> ast::NodeId } +dep_map_ty! { Mir: Mir(DefId) -> &'tcx RefCell> } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 96700a8da86a3..588857e557c22 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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}; @@ -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; @@ -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). diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_borrowck/borrowck/mir/mod.rs index 02f31af094133..cea9170da9ffd 100644 --- a/src/librustc_borrowck/borrowck/mir/mod.rs +++ b/src/librustc_borrowck/borrowck/mir/mod.rs @@ -55,15 +55,13 @@ pub struct MoveDataParamEnv<'tcx> { param_env: ty::ParameterEnvironment<'tcx>, } -pub fn borrowck_mir<'a, 'tcx: 'a>( - bcx: &mut BorrowckCtxt<'a, 'tcx>, - fk: FnKind, - _decl: &hir::FnDecl, - mir: &'a Mir<'tcx>, - body: &hir::Block, - _sp: Span, - id: ast::NodeId, - attributes: &[ast::Attribute]) { +pub fn borrowck_mir(bcx: &mut BorrowckCtxt, + fk: FnKind, + _decl: &hir::FnDecl, + body: &hir::Block, + _sp: Span, + id: ast::NodeId, + attributes: &[ast::Attribute]) { match fk { FnKind::ItemFn(name, ..) | FnKind::Method(name, ..) => { @@ -75,8 +73,10 @@ pub fn borrowck_mir<'a, 'tcx: 'a>( } let tcx = bcx.tcx; - let param_env = ty::ParameterEnvironment::for_item(tcx, id); + + let mir = &tcx.item_mir(tcx.map.local_def_id(id)); + let move_data = MoveData::gather_moves(mir, tcx, ¶m_env); let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; let flow_inits = @@ -170,8 +170,8 @@ pub struct MirBorrowckCtxt<'b, 'a: 'b, 'tcx: 'a> { mir: &'b Mir<'tcx>, node_id: ast::NodeId, move_data: MoveData<'tcx>, - flow_inits: DataflowResults>, - flow_uninits: DataflowResults> + flow_inits: DataflowResults>, + flow_uninits: DataflowResults> } impl<'b, 'a: 'b, 'tcx: 'a> MirBorrowckCtxt<'b, 'a, 'tcx> { diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 89b12e76c3c18..ef6936b6e7db3 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -51,8 +51,6 @@ use rustc::hir::{FnDecl, Block}; use rustc::hir::intravisit; use rustc::hir::intravisit::{Visitor, FnKind}; -use rustc::mir::mir_map::MirMap; - pub mod check_loans; pub mod gather_loans; @@ -102,10 +100,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for BorrowckCtxt<'a, 'tcx> { } } -pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir_map: &MirMap<'tcx>) { +pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut bccx = BorrowckCtxt { tcx: tcx, - mir_map: Some(mir_map), free_region_map: FreeRegionMap::new(), stats: BorrowStats { loaned_paths_same: 0, @@ -168,12 +165,9 @@ fn borrowck_fn(this: &mut BorrowckCtxt, attributes: &[ast::Attribute]) { debug!("borrowck_fn(id={})", id); - let def_id = this.tcx.map.local_def_id(id); - if attributes.iter().any(|item| item.check_name("rustc_mir_borrowck")) { - let mir = this.mir_map.unwrap().map.get(&def_id).unwrap(); this.with_temp_region_map(id, |this| { - mir::borrowck_mir(this, fk, decl, mir, body, sp, id, attributes) + mir::borrowck_mir(this, fk, decl, body, sp, id, attributes) }); } @@ -249,7 +243,6 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, /// the `BorrowckCtxt` itself , e.g. the flowgraph visualizer. pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, - mir_map: Option<&'a MirMap<'tcx>>, fn_parts: FnParts<'a>, cfg: &cfg::CFG) -> (BorrowckCtxt<'a, 'tcx>, AnalysisData<'a, 'tcx>) @@ -257,7 +250,6 @@ pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>( let mut bccx = BorrowckCtxt { tcx: tcx, - mir_map: mir_map, free_region_map: FreeRegionMap::new(), stats: BorrowStats { loaned_paths_same: 0, @@ -297,10 +289,7 @@ pub struct BorrowckCtxt<'a, 'tcx: 'a> { free_region_map: FreeRegionMap, // Statistics: - stats: BorrowStats, - - // NodeId to MIR mapping (for methods that carry the #[rustc_mir] attribute). - mir_map: Option<&'a MirMap<'tcx>>, + stats: BorrowStats } #[derive(Clone)] diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 9b27f7a29e9a8..5a7fc0bdb966e 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -13,7 +13,6 @@ use rustc::hir::{map as hir_map, FreevarMap, TraitMap}; use rustc::hir::def::DefMap; use rustc::hir::lowering::lower_crate; use rustc_mir as mir; -use rustc::mir::mir_map::MirMap; use rustc::session::{Session, CompileResult, compile_result_from_err_count}; use rustc::session::config::{self, Input, OutputFilenames, OutputType, OutputTypes}; @@ -175,7 +174,7 @@ pub fn compile_input(sess: &Session, resolutions, &arenas, &crate_name, - |tcx, mir_map, analysis, incremental_hashes_map, result| { + |tcx, analysis, incremental_hashes_map, result| { { // Eventually, we will want to track plugins. let _ignore = tcx.dep_graph.in_ignore(); @@ -187,7 +186,6 @@ pub fn compile_input(sess: &Session, opt_crate, tcx.map.krate(), &analysis, - mir_map.as_ref(), tcx, &crate_name); (control.after_analysis.callback)(&mut state); @@ -203,10 +201,7 @@ pub fn compile_input(sess: &Session, println!("Pre-trans"); tcx.print_debug_stats(); } - let trans = phase_4_translate_to_llvm(tcx, - mir_map.unwrap(), - analysis, - &incremental_hashes_map); + let trans = phase_4_translate_to_llvm(tcx, analysis, &incremental_hashes_map); if log_enabled!(::log::INFO) { println!("Post-trans"); @@ -348,7 +343,6 @@ pub struct CompileState<'a, 'b, 'ast: 'a, 'tcx: 'b> where 'ast: 'tcx { pub hir_crate: Option<&'a hir::Crate>, pub ast_map: Option<&'a hir_map::Map<'ast>>, pub resolutions: Option<&'a Resolutions>, - pub mir_map: Option<&'b MirMap<'tcx>>, pub analysis: Option<&'a ty::CrateAnalysis<'a>>, pub tcx: Option>, pub trans: Option<&'a trans::CrateTranslation>, @@ -375,7 +369,6 @@ impl<'a, 'b, 'ast, 'tcx> CompileState<'a, 'b, 'ast, 'tcx> { ast_map: None, resolutions: None, analysis: None, - mir_map: None, tcx: None, trans: None, } @@ -449,13 +442,11 @@ impl<'a, 'b, 'ast, 'tcx> CompileState<'a, 'b, 'ast, 'tcx> { krate: Option<&'a ast::Crate>, hir_crate: &'a hir::Crate, analysis: &'a ty::CrateAnalysis<'a>, - mir_map: Option<&'b MirMap<'tcx>>, tcx: TyCtxt<'b, 'tcx, 'tcx>, crate_name: &'a str) -> CompileState<'a, 'b, 'ast, 'tcx> { CompileState { analysis: Some(analysis), - mir_map: mir_map, tcx: Some(tcx), expanded_crate: krate, hir_crate: Some(hir_crate), @@ -812,17 +803,16 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, f: F) -> Result where F: for<'a> FnOnce(TyCtxt<'a, 'tcx, 'tcx>, - Option>, ty::CrateAnalysis, IncrementalHashesMap, CompileResult) -> R { macro_rules! try_with_f { - ($e: expr, ($t: expr, $m: expr, $a: expr, $h: expr)) => { + ($e: expr, ($t: expr, $a: expr, $h: expr)) => { match $e { Ok(x) => x, Err(x) => { - f($t, $m, $a, $h, Err(x)); + f($t, $a, $h, Err(x)); return Err(x); } } @@ -888,7 +878,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, || rustc_incremental::load_dep_graph(tcx, &incremental_hashes_map)); // passes are timed inside typeck - try_with_f!(typeck::check_crate(tcx), (tcx, None, analysis, incremental_hashes_map)); + try_with_f!(typeck::check_crate(tcx), (tcx, analysis, incremental_hashes_map)); time(time_passes, "const checking", @@ -928,28 +918,28 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, "rvalue checking", || rvalues::check_crate(tcx)); - let mut mir_map = - time(time_passes, - "MIR dump", - || mir::mir_map::build_mir_for_crate(tcx)); + time(time_passes, + "MIR dump", + || mir::mir_map::build_mir_for_crate(tcx)); time(time_passes, "MIR passes", || { let mut passes = sess.mir_passes.borrow_mut(); // Push all the built-in passes. passes.push_hook(box mir::transform::dump_mir::DumpMir); passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg::new("initial")); - passes.push_pass(box mir::transform::qualify_consts::QualifyAndPromoteConstants); + passes.push_pass( + box mir::transform::qualify_consts::QualifyAndPromoteConstants::default()); passes.push_pass(box mir::transform::type_check::TypeckMir); passes.push_pass( box mir::transform::simplify_branches::SimplifyBranches::new("initial")); passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg::new("qualify-consts")); // And run everything. - passes.run_passes(tcx, &mut mir_map); + passes.run_passes(tcx); }); time(time_passes, "borrow checking", - || borrowck::check_crate(tcx, &mir_map)); + || borrowck::check_crate(tcx)); // Avoid overwhelming user with errors if type checking failed. // I'm not sure how helpful this is, to be honest, but it avoids @@ -958,11 +948,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, // lint warnings and so on -- kindck used to do this abort, but // kindck is gone now). -nmatsakis if sess.err_count() > 0 { - return Ok(f(tcx, - Some(mir_map), - analysis, - incremental_hashes_map, - Err(sess.err_count()))); + return Ok(f(tcx, analysis, incremental_hashes_map, Err(sess.err_count()))); } analysis.reachable = @@ -990,20 +976,15 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, // The above three passes generate errors w/o aborting if sess.err_count() > 0 { - return Ok(f(tcx, - Some(mir_map), - analysis, - incremental_hashes_map, - Err(sess.err_count()))); + return Ok(f(tcx, analysis, incremental_hashes_map, Err(sess.err_count()))); } - Ok(f(tcx, Some(mir_map), analysis, incremental_hashes_map, Ok(()))) + Ok(f(tcx, analysis, incremental_hashes_map, Ok(()))) }) } /// Run the translation phase to LLVM, after which the AST and analysis can pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - mut mir_map: MirMap<'tcx>, analysis: ty::CrateAnalysis, incremental_hashes_map: &IncrementalHashesMap) -> trans::CrateTranslation { @@ -1037,13 +1018,13 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, passes.push_pass(box mir::transform::add_call_guards::AddCallGuards); passes.push_pass(box mir::transform::dump_mir::Marker("PreTrans")); - passes.run_passes(tcx, &mut mir_map); + passes.run_passes(tcx); }); let translation = time(time_passes, "translation", - move || trans::trans_crate(tcx, &mir_map, analysis, &incremental_hashes_map)); + move || trans::trans_crate(tcx, analysis, &incremental_hashes_map)); time(time_passes, "assert dep graph", diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 215287f84399c..10ff7dc89f9a3 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -52,8 +52,6 @@ use rustc::hir::map::{blocks, NodePrinter}; use rustc::hir; use rustc::hir::print as pprust_hir; -use rustc::mir::mir_map::MirMap; - #[derive(Copy, Clone, PartialEq, Debug)] pub enum PpSourceMode { PpmNormal, @@ -234,7 +232,7 @@ impl PpSourceMode { resolutions.clone(), arenas, id, - |tcx, _, _, _, _| { + |tcx, _, _, _| { let annotation = TypedAnnotation { tcx: tcx, }; @@ -695,7 +693,6 @@ impl fold::Folder for ReplaceBodyWithLoop { fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec, tcx: TyCtxt<'a, 'tcx, 'tcx>, - mir_map: Option<&MirMap<'tcx>>, code: blocks::Code, mode: PpFlowGraphMode, mut out: W) @@ -725,7 +722,6 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec, blocks::FnLikeCode(fn_like) => { let (bccx, analysis_data) = borrowck::build_borrowck_dataflow_data_for_fn(tcx, - mir_map, fn_like.to_fn_parts(), &cfg); @@ -952,32 +948,28 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session, resolutions.clone(), arenas, crate_name, - |tcx, mir_map, _, _, _| { + |tcx, _, _, _| { match ppm { PpmMir | PpmMirCFG => { - if let Some(mir_map) = mir_map { - if let Some(nodeid) = nodeid { - let def_id = tcx.map.local_def_id(nodeid); - match ppm { - PpmMir => write_mir_pretty(tcx, iter::once(def_id), &mir_map, &mut out), - PpmMirCFG => { - write_mir_graphviz(tcx, iter::once(def_id), &mir_map, &mut out) - } - _ => unreachable!(), - }?; - } else { - match ppm { - PpmMir => write_mir_pretty(tcx, - mir_map.map.keys().into_iter(), - &mir_map, - &mut out), - PpmMirCFG => write_mir_graphviz(tcx, - mir_map.map.keys().into_iter(), - &mir_map, - &mut out), - _ => unreachable!(), - }?; - } + if let Some(nodeid) = nodeid { + let def_id = tcx.map.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) + } + _ => unreachable!(), + }?; + } else { + match ppm { + PpmMir => write_mir_pretty(tcx, + tcx.mir_map.borrow().keys().into_iter(), + &mut out), + PpmMirCFG => write_mir_graphviz(tcx, + tcx.mir_map.borrow().keys().into_iter(), + &mut out), + _ => unreachable!(), + }?; } Ok(()) } @@ -995,12 +987,7 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session, let out: &mut Write = &mut out; - print_flowgraph(variants, - tcx, - mir_map.as_ref(), - code, - mode, - out) + print_flowgraph(variants, tcx, code, mode, out) } None => { let message = format!("--pretty=flowgraph needs block, fn, or method; got \ diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index e45a372147f39..13ffc04a89879 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -24,7 +24,6 @@ use rustc::dep_graph::DepNode; use rustc::hir::map as hir_map; use rustc::hir::map::DefKey; use rustc::mir::Mir; -use rustc::mir::mir_map::MirMap; use rustc::util::nodemap::{NodeSet, DefIdMap}; use rustc_back::PanicStrategy; @@ -467,10 +466,11 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.defid_for_inlined_node.borrow().get(&node_id).map(|x| *x) } - fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Option> { + fn get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Mir<'tcx> { self.dep_graph.read(DepNode::MetaData(def)); - self.get_crate_data(def.krate).maybe_get_item_mir(tcx, def.index) + self.get_crate_data(def.krate).maybe_get_item_mir(tcx, def.index).unwrap_or_else(|| { + bug!("get_item_mir: missing MIR for {}", tcx.item_path_str(def)) + }) } fn is_item_mir_available(&self, def: DefId) -> bool { @@ -523,10 +523,9 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, reexports: &def::ExportMap, link_meta: &LinkMeta, - reachable: &NodeSet, - mir_map: &MirMap<'tcx>) -> Vec + reachable: &NodeSet) -> Vec { - encoder::encode_metadata(tcx, self, reexports, link_meta, reachable, mir_map) + encoder::encode_metadata(tcx, self, reexports, link_meta, reachable) } fn metadata_encoding_version(&self) -> &[u8] diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 561cd3ab91411..e8734e4275712 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -22,7 +22,6 @@ use rustc::mir; use rustc::traits::specialization_graph; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::mir::mir_map::MirMap; use rustc::session::config::{self, CrateTypeProcMacro}; use rustc::util::nodemap::{FnvHashMap, NodeSet}; @@ -51,7 +50,6 @@ pub struct EncodeContext<'a, 'tcx: 'a> { link_meta: &'a LinkMeta, cstore: &'a cstore::CStore, reachable: &'a NodeSet, - mir_map: &'a MirMap<'tcx>, lazy_state: LazyState, type_shorthands: FnvHashMap, usize>, @@ -606,7 +604,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_mir(&mut self, def_id: DefId) -> Option>> { - self.mir_map.map.get(&def_id).map(|mir| self.lazy(mir)) + self.tcx.mir_map.borrow().get(&def_id).map(|mir| self.lazy(&*mir.borrow())) } // Encodes the inherent implementations of a structure, enumeration, or trait. @@ -1346,8 +1344,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cstore: &cstore::CStore, reexports: &def::ExportMap, link_meta: &LinkMeta, - reachable: &NodeSet, - mir_map: &MirMap<'tcx>) + reachable: &NodeSet) -> Vec { let mut cursor = Cursor::new(vec![]); cursor.write_all(METADATA_HEADER).unwrap(); @@ -1362,7 +1359,6 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, link_meta: link_meta, cstore: cstore, reachable: reachable, - mir_map: mir_map, lazy_state: LazyState::NoNode, type_shorthands: Default::default(), predicate_shorthands: Default::default(), diff --git a/src/librustc_mir/graphviz.rs b/src/librustc_mir/graphviz.rs index deacdb7d95b09..dd4dd4699d858 100644 --- a/src/librustc_mir/graphviz.rs +++ b/src/librustc_mir/graphviz.rs @@ -11,7 +11,6 @@ use dot; use rustc::hir::def_id::DefId; use rustc::mir::*; -use rustc::mir::mir_map::MirMap; use rustc::ty::TyCtxt; use std::fmt::Debug; use std::io::{self, Write}; @@ -22,14 +21,13 @@ use rustc_data_structures::indexed_vec::Idx; /// 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, - mir_map: &MirMap<'tcx>, w: &mut W) -> io::Result<()> where W: Write, I: Iterator { for def_id in iter { let nodeid = tcx.map.as_local_node_id(def_id).unwrap(); - let mir = &mir_map.map[&def_id]; + let mir = &tcx.item_mir(def_id); writeln!(w, "digraph Mir_{} {{", nodeid)?; diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index f5e1eaae82310..b0e2d6e73d37a 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -25,7 +25,6 @@ use rustc::mir::visit::MutVisitor; use pretty; use hair::cx::Cx; -use rustc::mir::mir_map::MirMap; use rustc::infer::InferCtxtBuilder; use rustc::traits::Reveal; use rustc::ty::{self, Ty, TyCtxt}; @@ -37,16 +36,10 @@ use syntax_pos::Span; use std::mem; -pub fn build_mir_for_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> MirMap<'tcx> { - let mut map = MirMap::new(tcx.dep_graph.clone()); - { - let mut dump = BuildMir { - tcx: tcx, - map: &mut map, - }; - tcx.visit_all_items_in_krate(DepNode::Mir, &mut dump); - } - map +pub fn build_mir_for_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { + tcx.visit_all_items_in_krate(DepNode::Mir, &mut BuildMir { + tcx: tcx + }); } /// A pass to lift all the types and substitutions in a Mir @@ -83,8 +76,7 @@ impl<'a, 'gcx: 'tcx, 'tcx> MutVisitor<'tcx> for GlobalizeMir<'a, 'gcx> { // BuildMir -- walks a crate, looking for fn items and methods to build MIR from struct BuildMir<'a, 'tcx: 'a> { - tcx: TyCtxt<'a, 'tcx, 'tcx>, - map: &'a mut MirMap<'tcx>, + tcx: TyCtxt<'a, 'tcx, 'tcx> } /// Helper type of a temporary returned by BuildMir::cx(...). @@ -93,8 +85,7 @@ struct BuildMir<'a, 'tcx: 'a> { struct CxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { src: MirSource, def_id: DefId, - infcx: InferCtxtBuilder<'a, 'gcx, 'tcx>, - map: &'a mut MirMap<'gcx>, + infcx: InferCtxtBuilder<'a, 'gcx, 'tcx> } impl<'a, 'gcx, 'tcx> BuildMir<'a, 'gcx> { @@ -104,8 +95,7 @@ impl<'a, 'gcx, 'tcx> BuildMir<'a, 'gcx> { CxBuilder { src: src, infcx: self.tcx.infer_ctxt(None, Some(param_env), Reveal::NotSpecializable), - def_id: def_id, - map: self.map + def_id: def_id } } } @@ -114,13 +104,14 @@ impl<'a, 'gcx, 'tcx> CxBuilder<'a, 'gcx, 'tcx> { fn build(&'tcx mut self, f: F) where F: for<'b> FnOnce(Cx<'b, 'gcx, 'tcx>) -> (Mir<'tcx>, build::ScopeAuxiliaryVec) { - let src = self.src; - let mir = self.infcx.enter(|infcx| { + let (src, def_id) = (self.src, self.def_id); + self.infcx.enter(|infcx| { let (mut mir, scope_auxiliary) = f(Cx::new(&infcx, src)); // Convert the Mir to global types. + let tcx = infcx.tcx.global_tcx(); let mut globalizer = GlobalizeMir { - tcx: infcx.tcx.global_tcx(), + tcx: tcx, span: mir.span }; globalizer.visit_mir(&mut mir); @@ -128,13 +119,11 @@ impl<'a, 'gcx, 'tcx> CxBuilder<'a, 'gcx, 'tcx> { mem::transmute::>(mir) }; - pretty::dump_mir(infcx.tcx.global_tcx(), "mir_map", &0, - src, &mir, Some(&scope_auxiliary)); + pretty::dump_mir(tcx, "mir_map", &0, src, &mir, Some(&scope_auxiliary)); - mir + let mir = tcx.alloc_mir(mir); + assert!(tcx.mir_map.borrow_mut().insert(def_id, mir).is_none()); }); - - assert!(self.map.map.insert(self.def_id, mir).is_none()) } } diff --git a/src/librustc_mir/pretty.rs b/src/librustc_mir/pretty.rs index c8c34d6e377e4..d2fc8aeaa2eea 100644 --- a/src/librustc_mir/pretty.rs +++ b/src/librustc_mir/pretty.rs @@ -12,7 +12,6 @@ use build::{ScopeAuxiliaryVec, ScopeId}; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::mir::*; -use rustc::mir::mir_map::MirMap; use rustc::mir::transform::MirSource; use rustc::ty::TyCtxt; use rustc_data_structures::fnv::FnvHashMap; @@ -90,14 +89,13 @@ pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, /// 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, - mir_map: &MirMap<'tcx>, w: &mut Write) -> io::Result<()> where I: Iterator, 'tcx: 'a { let mut first = true; for def_id in iter { - let mir = &mir_map.map[&def_id]; + let mir = &tcx.item_mir(def_id); if first { first = false; diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 102f6ac1154b9..b33a7060e3753 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -16,7 +16,6 @@ use rustc_data_structures::bitvec::BitVector; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; -use rustc::dep_graph::DepNode; use rustc::hir; use rustc::hir::map as hir_map; use rustc::hir::def_id::DefId; @@ -26,9 +25,8 @@ use rustc::traits::{self, Reveal}; use rustc::ty::{self, TyCtxt, Ty}; use rustc::ty::cast::CastTy; use rustc::mir::*; -use rustc::mir::mir_map::MirMap; use rustc::mir::traversal::ReversePostorder; -use rustc::mir::transform::{Pass, MirMapPass, MirPassHook, MirSource}; +use rustc::mir::transform::{Pass, MirPass, MirSource}; use rustc::mir::visit::{LvalueContext, Visitor}; use rustc::util::nodemap::DefIdMap; use syntax::abi::Abi; @@ -142,7 +140,6 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, param_env: ty::ParameterEnvironment<'tcx>, qualif_map: &'a mut DefIdMap, - mir_map: Option<&'a MirMap<'tcx>>, temp_qualif: IndexVec>, return_qualif: Option, qualif: Qualif, @@ -155,7 +152,6 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParameterEnvironment<'tcx>, qualif_map: &'a mut DefIdMap, - mir_map: Option<&'a MirMap<'tcx>>, def_id: DefId, mir: &'a Mir<'tcx>, mode: Mode) @@ -172,7 +168,6 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { tcx: tcx, param_env: param_env, qualif_map: qualif_map, - mir_map: mir_map, temp_qualif: IndexVec::from_elem(None, &mir.local_decls), return_qualif: None, qualif: Qualif::empty(), @@ -595,7 +590,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } else { let qualif = qualify_const_item_cached(self.tcx, self.qualif_map, - self.mir_map, def_id); self.add(qualif); } @@ -949,7 +943,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { fn qualify_const_item_cached<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, qualif_map: &mut DefIdMap, - mir_map: Option<&MirMap<'tcx>>, def_id: DefId) -> Qualif { match qualif_map.entry(def_id) { @@ -960,124 +953,100 @@ fn qualify_const_item_cached<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } - let extern_mir; - let param_env_and_mir = if def_id.is_local() { - mir_map.and_then(|map| map.map.get(&def_id)).map(|mir| { - let node_id = tcx.map.as_local_node_id(def_id).unwrap(); - (ty::ParameterEnvironment::for_item(tcx, node_id), mir) - }) - } else if let Some(mir) = tcx.sess.cstore.maybe_get_item_mir(tcx, def_id) { - // These should only be monomorphic constants. - extern_mir = mir; - Some((tcx.empty_parameter_environment(), &extern_mir)) + let param_env = if def_id.is_local() { + let node_id = tcx.map.as_local_node_id(def_id).unwrap(); + ty::ParameterEnvironment::for_item(tcx, node_id) } else { - None + // These should only be monomorphic constants. + tcx.empty_parameter_environment() }; - let (param_env, mir) = param_env_and_mir.unwrap_or_else(|| { - bug!("missing constant MIR for {}", tcx.item_path_str(def_id)) - }); - - let mut qualifier = Qualifier::new(tcx, param_env, qualif_map, mir_map, - def_id, mir, Mode::Const); + let mir = &tcx.item_mir(def_id); + let mut qualifier = Qualifier::new(tcx, param_env, qualif_map, def_id, mir, Mode::Const); let qualif = qualifier.qualify_const(); qualifier.qualif_map.insert(def_id, qualif); qualif } -pub struct QualifyAndPromoteConstants; +#[derive(Default)] +pub struct QualifyAndPromoteConstants { + qualif_map: DefIdMap +} impl Pass for QualifyAndPromoteConstants {} -impl<'tcx> MirMapPass<'tcx> for QualifyAndPromoteConstants { - fn run_pass<'a>(&mut self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - map: &mut MirMap<'tcx>, - hooks: &mut [Box MirPassHook<'s>>]) { - let mut qualif_map = DefIdMap(); - - // First, visit `const` items, potentially recursing, to get - // accurate MUTABLE_INTERIOR and NEEDS_DROP qualifications. - let keys = map.map.keys(); - for &def_id in &keys { - let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id)); - let id = tcx.map.as_local_node_id(def_id).unwrap(); - let src = MirSource::from_node(tcx, id); - if let MirSource::Const(_) = src { - qualify_const_item_cached(tcx, &mut qualif_map, Some(map), def_id); +impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants { + fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, + src: MirSource, mir: &mut Mir<'tcx>) { + let id = src.item_id(); + let def_id = tcx.map.local_def_id(id); + let mode = match src { + MirSource::Fn(_) => { + if is_const_fn(tcx, def_id) { + Mode::ConstFn + } else { + Mode::Fn + } } - } - - // Then, handle everything else, without recursing, - // as the MIR map is not shared, since promotion - // in functions (including `const fn`) mutates it. - for &def_id in &keys { - let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id)); - let id = tcx.map.as_local_node_id(def_id).unwrap(); - let src = MirSource::from_node(tcx, id); - let mode = match src { - MirSource::Fn(_) => { - if is_const_fn(tcx, def_id) { - Mode::ConstFn - } else { - Mode::Fn + MirSource::Const(_) => { + match self.qualif_map.entry(def_id) { + Entry::Occupied(_) => return, + Entry::Vacant(entry) => { + // Guard against `const` recursion. + entry.insert(Qualif::RECURSIVE); } } - MirSource::Const(_) => continue, - MirSource::Static(_, hir::MutImmutable) => Mode::Static, - MirSource::Static(_, hir::MutMutable) => Mode::StaticMut, - MirSource::Promoted(..) => bug!() - }; - let param_env = ty::ParameterEnvironment::for_item(tcx, id); - - let mir = map.map.get_mut(&def_id).unwrap(); - for hook in &mut *hooks { - hook.on_mir_pass(tcx, src, mir, self, false); + Mode::Const } - - if mode == Mode::Fn || mode == Mode::ConstFn { - // This is ugly because Qualifier holds onto mir, - // which can't be mutated until its scope ends. - let (temps, candidates) = { - let mut qualifier = Qualifier::new(tcx, param_env, &mut qualif_map, - None, def_id, mir, mode); - if mode == Mode::ConstFn { - // Enforce a constant-like CFG for `const fn`. - qualifier.qualify_const(); - } else { - while let Some((bb, data)) = qualifier.rpo.next() { - qualifier.visit_basic_block_data(bb, data); - } + MirSource::Static(_, hir::MutImmutable) => Mode::Static, + MirSource::Static(_, hir::MutMutable) => Mode::StaticMut, + MirSource::Promoted(..) => return + }; + let param_env = ty::ParameterEnvironment::for_item(tcx, id); + + if mode == Mode::Fn || mode == Mode::ConstFn { + // This is ugly because Qualifier holds onto mir, + // which can't be mutated until its scope ends. + let (temps, candidates) = { + let mut qualifier = Qualifier::new(tcx, param_env, + &mut self.qualif_map, + def_id, mir, mode); + if mode == Mode::ConstFn { + // Enforce a constant-like CFG for `const fn`. + qualifier.qualify_const(); + } else { + while let Some((bb, data)) = qualifier.rpo.next() { + qualifier.visit_basic_block_data(bb, data); } + } - (qualifier.temp_promotion_state, - qualifier.promotion_candidates) - }; + (qualifier.temp_promotion_state, qualifier.promotion_candidates) + }; - // Do the actual promotion, now that we know what's viable. - promote_consts::promote_candidates(mir, tcx, temps, candidates); - } else { - let mut qualifier = Qualifier::new(tcx, param_env, &mut qualif_map, - None, def_id, mir, mode); - qualifier.qualify_const(); - } + // Do the actual promotion, now that we know what's viable. + promote_consts::promote_candidates(mir, tcx, temps, candidates); + } else { + let mut qualifier = Qualifier::new(tcx, param_env, + &mut self.qualif_map, + def_id, mir, mode); + let qualif = qualifier.qualify_const(); - for hook in &mut *hooks { - hook.on_mir_pass(tcx, src, mir, self, true); + if mode == Mode::Const { + qualifier.qualif_map.insert(def_id, qualif); } + } - // Statics must be Sync. - if mode == Mode::Static { - let ty = mir.return_ty; - tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| { - let cause = traits::ObligationCause::new(mir.span, id, traits::SharedStatic); - let mut fulfillment_cx = traits::FulfillmentContext::new(); - fulfillment_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause); - if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(&err); - } - }); - } + // Statics must be Sync. + if mode == Mode::Static { + let ty = mir.return_ty; + tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| { + let cause = traits::ObligationCause::new(mir.span, id, traits::SharedStatic); + let mut fulfillment_cx = traits::FulfillmentContext::new(); + fulfillment_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause); + if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { + infcx.report_fulfillment_errors(&err); + } + }); } } } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index d4d4f883e7b85..14b2a2f55afb6 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -44,7 +44,6 @@ use rustc::ty::adjustment::CustomCoerceUnsized; use rustc::dep_graph::{DepNode, WorkProduct}; use rustc::hir::map as hir_map; use rustc::util::common::time; -use rustc::mir::mir_map::MirMap; use session::config::{self, NoDebugInfo}; use rustc_incremental::IncrementalHashesMap; use session::Session; @@ -866,7 +865,7 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> { false }; - let mir = def_id.and_then(|id| ccx.get_mir(id)); + let mir = def_id.map(|id| ccx.tcx().item_mir(id)); let debug_context = if let (false, Some((instance, sig, abi)), &Some(ref mir)) = (no_debug, definition, &mir) { @@ -1278,8 +1277,7 @@ fn write_metadata(cx: &SharedCrateContext, let metadata = cstore.encode_metadata(cx.tcx(), cx.export_map(), cx.link_meta(), - reachable_ids, - cx.mir_map()); + reachable_ids); if kind == MetadataKind::Uncompressed { return metadata; } @@ -1527,7 +1525,6 @@ pub fn filter_reachable_ids(tcx: TyCtxt, reachable: NodeSet) -> NodeSet { } pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - mir_map: &MirMap<'tcx>, analysis: ty::CrateAnalysis, incremental_hashes_map: &IncrementalHashesMap) -> CrateTranslation { @@ -1551,7 +1548,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let link_meta = link::build_link_meta(incremental_hashes_map, name); let shared_ccx = SharedCrateContext::new(tcx, - &mir_map, export_map, Sha256::new(), link_meta.clone(), diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index e7dd6adb8cf68..8348da9f7b7bf 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -205,7 +205,6 @@ use rustc::mir::visit::Visitor as MirVisitor; use rustc_const_eval as const_eval; use syntax::abi::Abi; -use errors; use syntax_pos::DUMMY_SP; use base::custom_coerce_unsize_info; use context::SharedCrateContext; @@ -346,8 +345,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>, // Scan the MIR in order to find function calls, closures, and // drop-glue - let mir = errors::expect(scx.sess().diagnostic(), scx.get_mir(def_id), - || format!("Could not find MIR for static: {:?}", def_id)); + let mir = scx.tcx().item_mir(def_id); let empty_substs = scx.empty_substs_for_def_id(def_id); let visitor = MirNeighborCollector { @@ -367,8 +365,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>, // Scan the MIR in order to find function calls, closures, and // drop-glue - let mir = errors::expect(scx.sess().diagnostic(), scx.get_mir(instance.def), - || format!("Could not find MIR for function: {}", instance)); + let mir = scx.tcx().item_mir(instance.def); let visitor = MirNeighborCollector { scx: scx, @@ -451,11 +448,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { match *rvalue { mir::Rvalue::Aggregate(mir::AggregateKind::Closure(def_id, ref substs), _) => { - let mir = errors::expect(self.scx.sess().diagnostic(), - self.scx.get_mir(def_id), - || { - format!("Could not find MIR for closure: {:?}", def_id) - }); + let mir = self.scx.tcx().item_mir(def_id); let concrete_substs = monomorphize::apply_param_substs(self.scx, self.param_substs, @@ -1248,8 +1241,7 @@ fn collect_const_item_neighbours<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, { // Scan the MIR in order to find function calls, closures, and // drop-glue - let mir = errors::expect(scx.sess().diagnostic(), scx.get_mir(def_id), - || format!("Could not find MIR for const: {:?}", def_id)); + let mir = scx.tcx().item_mir(def_id); let visitor = MirNeighborCollector { scx: scx, diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index e12232212625a..464b261b08e05 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -19,6 +19,7 @@ use llvm::{True, False, Bool, OperandBundleDef}; use rustc::hir::def::Def; use rustc::hir::def_id::DefId; use rustc::infer::TransNormalize; +use rustc::mir::Mir; use rustc::util::common::MemoizationMap; use middle::lang_items::LangItem; use rustc::ty::subst::Substs; @@ -32,7 +33,6 @@ use consts; use debuginfo::{self, DebugLoc}; use declare; use machine; -use mir::CachedMir; use monomorphize; use type_::Type; use value::Value; @@ -46,7 +46,7 @@ use arena::TypedArena; use libc::{c_uint, c_char}; use std::ops::Deref; use std::ffi::CString; -use std::cell::{Cell, RefCell}; +use std::cell::{Cell, RefCell, Ref}; use syntax::ast; use syntax::parse::token::InternedString; @@ -250,10 +250,8 @@ pub fn validate_substs(substs: &Substs) { // Function context. Every LLVM function we create will have one of // these. pub struct FunctionContext<'a, 'tcx: 'a> { - // The MIR for this function. At present, this is optional because - // we only have MIR available for things that are local to the - // crate. - pub mir: Option>, + // The MIR for this function. + pub mir: Option>>, // The ValueRef returned from a call to llvm::LLVMAddFunction; the // address of the first instruction in the sequence of @@ -313,8 +311,8 @@ pub struct FunctionContext<'a, 'tcx: 'a> { } impl<'a, 'tcx> FunctionContext<'a, 'tcx> { - pub fn mir(&self) -> CachedMir<'a, 'tcx> { - self.mir.clone().expect("fcx.mir was empty") + pub fn mir(&self) -> Ref<'tcx, Mir<'tcx>> { + self.mir.as_ref().map(Ref::clone).expect("fcx.mir was empty") } pub fn cleanup(&self) { @@ -490,7 +488,7 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> { self.set_lpad_ref(lpad.map(|p| &*self.fcx().lpad_arena.alloc(p))) } - pub fn mir(&self) -> CachedMir<'blk, 'tcx> { + pub fn mir(&self) -> Ref<'tcx, Mir<'tcx>> { self.fcx.mir() } @@ -609,7 +607,7 @@ impl<'blk, 'tcx> BlockAndBuilder<'blk, 'tcx> { self.bcx.llbb } - pub fn mir(&self) -> CachedMir<'blk, 'tcx> { + pub fn mir(&self) -> Ref<'tcx, Mir<'tcx>> { self.bcx.mir() } diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index d243c534ee102..42773a8cd2c44 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -15,15 +15,12 @@ use middle::cstore::LinkMeta; use rustc::hir::def::ExportMap; use rustc::hir::def_id::DefId; use rustc::traits; -use rustc::mir::mir_map::MirMap; -use rustc::mir; use base; use builder::Builder; use common::BuilderRef_res; use debuginfo; use declare; use glue::DropGlueKind; -use mir::CachedMir; use monomorphize::Instance; use partitioning::CodegenUnit; @@ -76,8 +73,6 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, stats: Stats, check_overflow: bool, - mir_map: &'a MirMap<'tcx>, - mir_cache: RefCell>>, use_dll_storage_attrs: bool, @@ -184,19 +179,6 @@ impl<'tcx> DepTrackingMapConfig for TraitSelectionCache<'tcx> { } } -// Cache for mir loaded from metadata -struct MirCache<'tcx> { - data: PhantomData<&'tcx ()> -} - -impl<'tcx> DepTrackingMapConfig for MirCache<'tcx> { - type Key = DefId; - type Value = Rc>; - fn to_dep_node(key: &DefId) -> DepNode { - DepNode::Mir(*key) - } -} - // # Global Cache pub struct ProjectionCache<'gcx> { @@ -453,7 +435,6 @@ unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextR impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>, - mir_map: &'b MirMap<'tcx>, export_map: ExportMap, symbol_hasher: Sha256, link_meta: LinkMeta, @@ -517,8 +498,6 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { link_meta: link_meta, symbol_hasher: RefCell::new(symbol_hasher), tcx: tcx, - mir_map: mir_map, - mir_cache: RefCell::new(DepTrackingMap::new(tcx.dep_graph.clone())), stats: Stats { n_glues_created: Cell::new(0), n_null_glues: Cell::new(0), @@ -582,23 +561,6 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { self.use_dll_storage_attrs } - pub fn get_mir(&self, def_id: DefId) -> Option> { - if def_id.is_local() { - self.mir_map.map.get(&def_id).map(CachedMir::Ref) - } else { - if let Some(mir) = self.mir_cache.borrow().get(&def_id).cloned() { - return Some(CachedMir::Owned(mir)); - } - - let mir = self.sess().cstore.maybe_get_item_mir(self.tcx, def_id); - let cached = mir.map(Rc::new); - if let Some(ref mir) = cached { - self.mir_cache.borrow_mut().insert(def_id, mir.clone()); - } - cached.map(CachedMir::Owned) - } - } - pub fn translation_items(&self) -> &RefCell>> { &self.translation_items } @@ -617,10 +579,6 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { &self.symbol_hasher } - pub fn mir_map(&self) -> &MirMap<'tcx> { - &self.mir_map - } - pub fn metadata_symbol_name(&self) -> String { format!("rust_metadata_{}_{}", self.link_meta().crate_name, @@ -1008,10 +966,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { self.shared.use_dll_storage_attrs() } - pub fn get_mir(&self, def_id: DefId) -> Option> { - self.shared.get_mir(def_id) - } - pub fn symbol_map(&self) -> &SymbolMap<'tcx> { &*self.local().symbol_map } diff --git a/src/librustc_trans/debuginfo/create_scope_map.rs b/src/librustc_trans/debuginfo/create_scope_map.rs index 4f3ff2fbaee41..e0c1a80be394d 100644 --- a/src/librustc_trans/debuginfo/create_scope_map.rs +++ b/src/librustc_trans/debuginfo/create_scope_map.rs @@ -45,7 +45,7 @@ impl MirDebugScope { /// Produce DIScope DIEs for each MIR Scope which has variables defined in it. /// If debuginfo is disabled, the returned vector is empty. pub fn create_mir_scopes(fcx: &FunctionContext) -> IndexVec { - let mir = fcx.mir.clone().expect("create_mir_scopes: missing MIR for fn"); + let mir = fcx.mir(); let null_scope = MirDebugScope { scope_metadata: ptr::null_mut(), file_start_pos: BytePos(0), diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 81c0c184f66b2..07acc54962b87 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -25,6 +25,7 @@ #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(cell_extras)] #![feature(const_fn)] #![feature(custom_attribute)] #![feature(dotdot_in_tuple_patterns)] diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 587a9c8df3a29..3d0d889760943 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -261,9 +261,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { } } - let mir = ccx.get_mir(instance.def).unwrap_or_else(|| { - bug!("missing constant MIR for {}", instance) - }); + let mir = ccx.tcx().item_mir(instance.def); MirConstContext::new(ccx, &mir, instance.substs, args).trans() } diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index d6caef81445c2..d2adf88c91683 100644 --- a/src/librustc_trans/mir/mod.rs +++ b/src/librustc_trans/mir/mod.rs @@ -23,8 +23,7 @@ use type_of; use syntax_pos::{DUMMY_SP, NO_EXPANSION, COMMAND_LINE_EXPN, BytePos}; use syntax::parse::token::keywords; -use std::ops::Deref; -use std::rc::Rc; +use std::cell::Ref; use std::iter; use basic_block::BasicBlock; @@ -39,25 +38,9 @@ use rustc::mir::traversal; use self::operand::{OperandRef, OperandValue}; -#[derive(Clone)] -pub enum CachedMir<'mir, 'tcx: 'mir> { - Ref(&'mir mir::Mir<'tcx>), - Owned(Rc>) -} - -impl<'mir, 'tcx: 'mir> Deref for CachedMir<'mir, 'tcx> { - type Target = mir::Mir<'tcx>; - fn deref(&self) -> &mir::Mir<'tcx> { - match *self { - CachedMir::Ref(r) => r, - CachedMir::Owned(ref rc) => rc - } - } -} - /// Master context for translating MIR. pub struct MirContext<'bcx, 'tcx:'bcx> { - mir: CachedMir<'bcx, 'tcx>, + mir: Ref<'tcx, mir::Mir<'tcx>>, /// Function context fcx: &'bcx common::FunctionContext<'bcx, 'tcx>, @@ -223,7 +206,7 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) { let scopes = debuginfo::create_mir_scopes(fcx); let mut mircx = MirContext { - mir: mir.clone(), + mir: Ref::clone(&mir), fcx: fcx, llpersonalityslot: None, blocks: block_bcxs, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 208819a4a0b06..2881ba53f7254 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -189,7 +189,7 @@ pub fn run_core(search_paths: SearchPaths, resolutions, &arenas, &name, - |tcx, _, analysis, _, result| { + |tcx, analysis, _, result| { if let Err(_) = result { sess.fatal("Compilation failed, aborting rustdoc"); }