diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 453d30dde75..1b590c2b2c4 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -448,6 +448,28 @@ impl<'hir> Map<'hir> { }) } + pub fn body_owner_kind(&self, id: NodeId) -> BodyOwnerKind { + // Handle constants in enum discriminants, types, and repeat expressions. + let def_id = self.local_def_id(id); + let def_key = self.def_key(def_id); + if def_key.disambiguated_data.data == DefPathData::Initializer { + return BodyOwnerKind::Const; + } + + match self.get(id) { + NodeItem(&Item { node: ItemConst(..), .. }) | + NodeTraitItem(&TraitItem { node: TraitItemKind::Const(..), .. }) | + NodeImplItem(&ImplItem { node: ImplItemKind::Const(..), .. }) => { + BodyOwnerKind::Const + } + NodeItem(&Item { node: ItemStatic(_, m, _), .. }) => { + BodyOwnerKind::Static(m) + } + // Default to function if it's not a constant or static. + _ => BodyOwnerKind::Fn + } + } + pub fn ty_param_owner(&self, id: NodeId) -> NodeId { match self.get(id) { NodeItem(&Item { node: ItemTrait(..), .. }) => id, diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 39e222230e5..a7206f5d420 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1028,6 +1028,18 @@ impl Body { } } +#[derive(Copy, Clone, Debug)] +pub enum BodyOwnerKind { + /// Functions and methods. + Fn, + + /// Constants and associated constants. + Const, + + /// Initializer of a `static` item. + Static(Mutability), +} + /// An expression #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)] pub struct Expr { diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 89707839144..a7882992d61 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -31,7 +31,6 @@ use hir; use hir::def_id::DefId; use hir::intravisit::{self, Visitor, NestedVisitorMap}; use hir::{Block, Arm, Pat, PatKind, Stmt, Expr, Local}; -use mir::transform::MirSource; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; @@ -1298,7 +1297,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionResolutionVisitor<'a, 'tcx> { // The body of the every fn is a root scope. self.cx.parent = self.cx.var_parent; - if let MirSource::Fn(_) = MirSource::from_node(self.tcx, owner_id) { + if let hir::BodyOwnerKind::Fn = self.tcx.hir.body_owner_kind(owner_id) { self.visit_expr(&body.value); } else { // Only functions have an outer terminating (drop) scope, while diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index cd017650633..18c26500dbe 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -41,7 +41,6 @@ use syntax_pos::Span; mod cache; pub mod tcx; pub mod visit; -pub mod transform; pub mod traversal; /// Types for locals diff --git a/src/librustc/mir/transform.rs b/src/librustc/mir/transform.rs deleted file mode 100644 index 6c90a5f38d0..00000000000 --- a/src/librustc/mir/transform.rs +++ /dev/null @@ -1,190 +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. - -//! See [the README](README.md) for details on writing your own pass. - -use hir; -use hir::def_id::DefId; -use hir::map::DefPathData; -use mir::{Mir, Promoted}; -use ty::TyCtxt; -use std::rc::Rc; -use syntax::ast::NodeId; - -use std::borrow::Cow; - -/// Where a specific Mir comes from. -#[derive(Debug, Copy, Clone)] -pub enum MirSource { - /// Functions and methods. - Fn(NodeId), - - /// Constants and associated constants. - Const(NodeId), - - /// Initializer of a `static` item. - Static(NodeId, hir::Mutability), - - /// Promoted rvalues within a function. - Promoted(NodeId, Promoted), - - /// Drop glue for a generator. - GeneratorDrop(NodeId), -} - -impl<'a, 'gcx, 'tcx> MirSource { - pub fn from_local_def_id(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> MirSource { - let id = tcx.hir.as_local_node_id(def_id).expect("mir source requires local def-id"); - Self::from_node(tcx, id) - } - - pub fn from_node(tcx: TyCtxt<'a, 'gcx, 'tcx>, id: NodeId) -> MirSource { - use hir::*; - - // Handle constants in enum discriminants, types, and repeat expressions. - let def_id = tcx.hir.local_def_id(id); - let def_key = tcx.def_key(def_id); - if def_key.disambiguated_data.data == DefPathData::Initializer { - return MirSource::Const(id); - } - - match tcx.hir.get(id) { - map::NodeItem(&Item { node: ItemConst(..), .. }) | - map::NodeTraitItem(&TraitItem { node: TraitItemKind::Const(..), .. }) | - map::NodeImplItem(&ImplItem { node: ImplItemKind::Const(..), .. }) => { - MirSource::Const(id) - } - map::NodeItem(&Item { node: ItemStatic(_, m, _), .. }) => { - MirSource::Static(id, m) - } - // Default to function if it's not a constant or static. - _ => MirSource::Fn(id) - } - } - - pub fn item_id(&self) -> NodeId { - match *self { - MirSource::Fn(id) | - MirSource::Const(id) | - MirSource::GeneratorDrop(id) | - MirSource::Static(id, _) | - MirSource::Promoted(id, _) => id - } - } -} - -/// Generates a default name for the pass based on the name of the -/// type `T`. -pub fn default_name() -> Cow<'static, str> { - let name = unsafe { ::std::intrinsics::type_name::() }; - if let Some(tail) = name.rfind(":") { - Cow::from(&name[tail+1..]) - } else { - Cow::from(name) - } -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct MirSuite(pub usize); - -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct MirPassIndex(pub usize); - -/// A pass hook is invoked both before and after each pass executes. -/// This is primarily used to dump MIR for debugging. -/// -/// You can tell whether this is before or after by inspecting the -/// `mir` parameter -- before the pass executes, it will be `None` (in -/// which case you can inspect the MIR from previous pass by executing -/// `mir_cx.read_previous_mir()`); after the pass executes, it will be -/// `Some()` with the result of the pass (in which case the output -/// from the previous pass is most likely stolen, so you would not -/// want to try and access it). If the pass is interprocedural, then -/// the hook will be invoked once per output. -pub trait PassHook { - fn on_mir_pass<'a, 'tcx: 'a>(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - suite: MirSuite, - pass_num: MirPassIndex, - pass_name: &str, - source: MirSource, - mir: &Mir<'tcx>, - is_after: bool); -} - -/// The full suite of types that identifies a particular -/// application of a pass to a def-id. -pub type PassId = (MirSuite, MirPassIndex, DefId); - -/// A streamlined trait that you can implement to create a pass; the -/// pass will be named after the type, and it will consist of a main -/// loop that goes over each available MIR and applies `run_pass`. -pub trait MirPass { - fn name<'a>(&'a self) -> Cow<'a, str> { - default_name::() - } - - fn run_pass<'a, 'tcx>(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - source: MirSource, - mir: &mut Mir<'tcx>); -} - -/// A manager for MIR passes. -/// -/// FIXME(#41712) -- it is unclear whether we should have this struct. -#[derive(Clone)] -pub struct Passes { - pass_hooks: Vec>, - suites: Vec>>, -} - -/// The number of "pass suites" that we have: -/// -/// - ready for constant evaluation -/// - unopt -/// - optimized -pub const MIR_SUITES: usize = 3; - -/// Run the passes we need to do constant qualification and evaluation. -pub const MIR_CONST: MirSuite = MirSuite(0); - -/// Run the passes we need to consider the MIR validated and ready for borrowck etc. -pub const MIR_VALIDATED: MirSuite = MirSuite(1); - -/// Run the passes we need to consider the MIR *optimized*. -pub const MIR_OPTIMIZED: MirSuite = MirSuite(2); - -impl<'a, 'tcx> Passes { - pub fn new() -> Passes { - Passes { - pass_hooks: Vec::new(), - suites: (0..MIR_SUITES).map(|_| Vec::new()).collect(), - } - } - - /// Pushes a built-in pass. - pub fn push_pass(&mut self, suite: MirSuite, pass: T) { - self.suites[suite.0].push(Rc::new(pass)); - } - - /// Pushes a pass hook. - pub fn push_hook(&mut self, hook: T) { - self.pass_hooks.push(Rc::new(hook)); - } - - pub fn passes(&self, suite: MirSuite) -> &[Rc] { - &self.suites[suite.0] - } - - pub fn hooks(&self) -> &[Rc] { - &self.pass_hooks - } -} diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 37c4346a7dc..193c3673607 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -31,7 +31,6 @@ use middle::lang_items; use middle::resolve_lifetime::{self, ObjectLifetimeDefault}; use middle::stability; use mir::Mir; -use mir::transform::Passes; use ty::subst::{Kind, Substs}; use ty::ReprOptions; use traits; @@ -882,8 +881,6 @@ pub struct GlobalCtxt<'tcx> { pub maps: maps::Maps<'tcx>, - pub mir_passes: Rc, - // Records the free variables refrenced by every closure // expression. Do not track deps for this, just recompute it from // scratch every time. @@ -1055,7 +1052,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { cstore: &'tcx CrateStore, local_providers: ty::maps::Providers<'tcx>, extern_providers: ty::maps::Providers<'tcx>, - mir_passes: Rc, arenas: &'tcx GlobalArenas<'tcx>, arena: &'tcx DroplessArena, resolutions: ty::Resolutions, @@ -1172,7 +1168,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { hir, def_path_hash_to_def_id, maps: maps::Maps::new(providers), - mir_passes, rcache: RefCell::new(FxHashMap()), selection_cache: traits::SelectionCache::new(), evaluation_cache: traits::EvaluationCache::new(), diff --git a/src/librustc/ty/maps/keys.rs b/src/librustc/ty/maps/keys.rs index ee4523d6f3e..b7b64c9761a 100644 --- a/src/librustc/ty/maps/keys.rs +++ b/src/librustc/ty/maps/keys.rs @@ -11,7 +11,6 @@ //! Defines the set of legal keys that can be used in queries. use hir::def_id::{CrateNum, DefId, LOCAL_CRATE, DefIndex}; -use mir::transform::{MirSuite, MirPassIndex}; use ty::{self, Ty, TyCtxt}; use ty::subst::Substs; use ty::fast_reject::SimplifiedType; @@ -116,24 +115,6 @@ impl<'tcx> Key for (DefId, &'tcx Substs<'tcx>) { } } -impl Key for (MirSuite, DefId) { - fn map_crate(&self) -> CrateNum { - self.1.map_crate() - } - fn default_span(&self, tcx: TyCtxt) -> Span { - self.1.default_span(tcx) - } -} - -impl Key for (MirSuite, MirPassIndex, DefId) { - fn map_crate(&self) -> CrateNum { - self.2.map_crate() - } - fn default_span(&self, tcx: TyCtxt) -> Span { - self.2.default_span(tcx) - } -} - impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) { fn map_crate(&self) -> CrateNum { self.1.def_id().krate diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 855362cf645..f7c03fde222 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -22,7 +22,6 @@ use rustc::lint; use rustc::middle::{self, stability, reachable}; use rustc::middle::cstore::CrateStore; use rustc::middle::privacy::AccessLevels; -use rustc::mir::transform::{MIR_CONST, MIR_VALIDATED, MIR_OPTIMIZED, Passes}; use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas}; use rustc::traits; use rustc::util::common::{ErrorReported, time}; @@ -989,63 +988,12 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, // FIXME(eddyb) get rid of this once we replace const_eval with miri. rustc_const_eval::provide(&mut extern_providers); - // Setup the MIR passes that we want to run. - let mut passes = Passes::new(); - passes.push_hook(mir::transform::dump_mir::DumpMir); - - // Remove all `EndRegion` statements that are not involved in borrows. - passes.push_pass(MIR_CONST, mir::transform::clean_end_regions::CleanEndRegions); - - // What we need to do constant evaluation. - passes.push_pass(MIR_CONST, mir::transform::simplify::SimplifyCfg::new("initial")); - passes.push_pass(MIR_CONST, mir::transform::type_check::TypeckMir); - passes.push_pass(MIR_CONST, mir::transform::rustc_peek::SanityCheck); - - // We compute "constant qualifications" between MIR_CONST and MIR_VALIDATED. - - // What we need to run borrowck etc. - - passes.push_pass(MIR_VALIDATED, mir::transform::qualify_consts::QualifyAndPromoteConstants); - passes.push_pass(MIR_VALIDATED, mir::transform::simplify::SimplifyCfg::new("qualify-consts")); - - // borrowck runs between MIR_VALIDATED and MIR_OPTIMIZED. - - passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads); - passes.push_pass(MIR_OPTIMIZED, - mir::transform::simplify_branches::SimplifyBranches::new("initial")); - - // These next passes must be executed together - passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::CriticalCallEdges); - passes.push_pass(MIR_OPTIMIZED, mir::transform::elaborate_drops::ElaborateDrops); - passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads); - // AddValidation needs to run after ElaborateDrops and before EraseRegions, and it needs - // an AllCallEdges pass right before it. - passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::AllCallEdges); - passes.push_pass(MIR_OPTIMIZED, mir::transform::add_validation::AddValidation); - passes.push_pass(MIR_OPTIMIZED, mir::transform::simplify::SimplifyCfg::new("elaborate-drops")); - // No lifetime analysis based on borrowing can be done from here on out. - - // From here on out, regions are gone. - passes.push_pass(MIR_OPTIMIZED, mir::transform::erase_regions::EraseRegions); - - // Optimizations begin. - passes.push_pass(MIR_OPTIMIZED, mir::transform::inline::Inline); - passes.push_pass(MIR_OPTIMIZED, mir::transform::instcombine::InstCombine); - passes.push_pass(MIR_OPTIMIZED, mir::transform::deaggregator::Deaggregator); - passes.push_pass(MIR_OPTIMIZED, mir::transform::copy_prop::CopyPropagation); - passes.push_pass(MIR_OPTIMIZED, mir::transform::simplify::SimplifyLocals); - - passes.push_pass(MIR_OPTIMIZED, mir::transform::generator::StateTransform); - passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::CriticalCallEdges); - passes.push_pass(MIR_OPTIMIZED, mir::transform::dump_mir::Marker("PreTrans")); - let (tx, rx) = mpsc::channel(); TyCtxt::create_and_enter(sess, cstore, local_providers, extern_providers, - Rc::new(passes), arenas, arena, resolutions, diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 5ff75351b63..9e02065145d 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -28,7 +28,6 @@ use rustc::infer::{self, InferOk, InferResult}; use rustc::infer::type_variable::TypeVariableOrigin; use rustc_metadata::cstore::CStore; use rustc::hir::map as hir_map; -use rustc::mir::transform::Passes; use rustc::session::{self, config}; use rustc::session::config::{OutputFilenames, OutputTypes}; use rustc_trans_utils::trans_crate::TransCrate; @@ -151,7 +150,6 @@ fn test_env(source_string: &str, &*cstore, ty::maps::Providers::default(), ty::maps::Providers::default(), - Rc::new(Passes::new()), &arenas, &arena, resolutions, diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index c56631d429c..deffb85bf87 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -18,7 +18,6 @@ use rustc::ty::maps::Providers; use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Location, Lvalue, Local}; use rustc::mir::{Mir, Mutability, Operand, Projection, ProjectionElem, Rvalue}; use rustc::mir::{Statement, StatementKind, Terminator, TerminatorKind}; -use rustc::mir::transform::MirSource; use transform::nll; use rustc_data_structures::indexed_set::{self, IdxSetBuf}; @@ -50,8 +49,7 @@ pub fn provide(providers: &mut Providers) { fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { let input_mir = tcx.mir_validated(def_id); - let src = MirSource::from_local_def_id(tcx, def_id); - debug!("run query mir_borrowck: {}", tcx.node_path_str(src.item_id())); + debug!("run query mir_borrowck: {}", tcx.item_path_str(def_id)); if { !tcx.has_attr(def_id, "rustc_mir_borrowck") && @@ -63,21 +61,20 @@ fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { tcx.infer_ctxt().enter(|infcx| { let input_mir: &Mir = &input_mir.borrow(); - do_mir_borrowck(&infcx, input_mir, def_id, src); + do_mir_borrowck(&infcx, input_mir, def_id); }); debug!("mir_borrowck done"); } fn do_mir_borrowck<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, input_mir: &Mir<'gcx>, - def_id: DefId, - src: MirSource) + def_id: DefId) { let tcx = infcx.tcx; let attributes = tcx.get_attrs(def_id); let param_env = tcx.param_env(def_id); - - let id = src.item_id(); + let id = tcx.hir.as_local_node_id(def_id) + .expect("do_mir_borrowck: non-local DefId"); let move_data: MoveData<'tcx> = match MoveData::gather_moves(input_mir, tcx, param_env) { Ok(move_data) => move_data, @@ -117,7 +114,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, let opt_regioncx = if !tcx.sess.opts.debugging_opts.nll { None } else { - Some(nll::compute_regions(infcx, src, mir)) + Some(nll::compute_regions(infcx, def_id, mir)) }; let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 2073d495300..0489a03c97e 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -16,7 +16,6 @@ use rustc::hir; use rustc::hir::def_id::DefId; use rustc::middle::region; use rustc::mir::*; -use rustc::mir::transform::MirSource; use rustc::mir::visit::{MutVisitor, TyContext}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::Substs; @@ -30,6 +29,7 @@ use syntax::abi::Abi; use syntax::ast; use syntax::symbol::keywords; use syntax_pos::Span; +use transform::MirSource; use util as mir_util; /// Construct the MIR for a given def-id. @@ -83,12 +83,11 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t _ => unsupported(), }; - let src = MirSource::from_node(tcx, id); tcx.infer_ctxt().enter(|infcx| { - let cx = Cx::new(&infcx, src); + let cx = Cx::new(&infcx, id); let mut mir = if cx.tables().tainted_by_errors { build::construct_error(cx, body_id) - } else if let MirSource::Fn(id) = src { + } else if let hir::BodyOwnerKind::Fn = cx.body_owner_kind { // fetch the fully liberated fn signature (that is, all bound // types/lifetimes replaced) let fn_hir_id = tcx.hir.node_to_hir_id(id); @@ -150,7 +149,8 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t mem::transmute::>(mir) }; - mir_util::dump_mir(tcx, None, "mir_map", &0, src, &mir, |_, _| Ok(()) ); + mir_util::dump_mir(tcx, None, "mir_map", &0, + MirSource::item(def_id), &mir, |_, _| Ok(()) ); mir }) @@ -214,8 +214,7 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let span = tcx.hir.span(ctor_id); if let hir::VariantData::Tuple(ref fields, ctor_id) = *v { tcx.infer_ctxt().enter(|infcx| { - let (mut mir, src) = - shim::build_adt_ctor(&infcx, ctor_id, fields, span); + let mut mir = shim::build_adt_ctor(&infcx, ctor_id, fields, span); // Convert the Mir to global types. let tcx = infcx.tcx.global_tcx(); @@ -228,7 +227,9 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mem::transmute::>(mir) }; - mir_util::dump_mir(tcx, None, "mir_map", &0, src, &mir, |_, _| Ok(()) ); + mir_util::dump_mir(tcx, None, "mir_map", &0, + MirSource::item(tcx.hir.local_def_id(ctor_id)), + &mir, |_, _| Ok(()) ); mir }) diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index c0d17a1590f..3c3dabdfa54 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -91,9 +91,9 @@ use build::{BlockAnd, BlockAndExtension, Builder, CFG}; use hair::LintLevel; use rustc::middle::region; use rustc::ty::{Ty, TyCtxt}; +use rustc::hir; use rustc::hir::def_id::LOCAL_CRATE; use rustc::mir::*; -use rustc::mir::transform::MirSource; use syntax_pos::{Span}; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::fx::FxHashMap; @@ -596,16 +596,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// When building statics/constants, returns `None` since /// intermediate values do not have to be dropped in that case. pub fn local_scope(&self) -> Option { - match self.hir.src { - MirSource::Const(_) | - MirSource::Static(..) => + match self.hir.body_owner_kind { + hir::BodyOwnerKind::Const | + hir::BodyOwnerKind::Static(_) => // No need to free storage in this context. None, - MirSource::Fn(_) => + hir::BodyOwnerKind::Fn => Some(self.topmost_scope()), - MirSource::Promoted(..) | - MirSource::GeneratorDrop(..) => - bug!(), } } diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 4434df0ac3e..50264238aac 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -15,7 +15,6 @@ //! use hair::*; -use rustc::mir::transform::MirSource; use rustc::middle::const_val::{ConstEvalErr, ConstVal}; use rustc_const_eval::ConstContext; @@ -51,8 +50,8 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { /// `const`, or the body of a `const fn`. constness: hir::Constness, - /// What are we compiling? - pub src: MirSource, + /// What kind of body is being compiled. + pub body_owner_kind: hir::BodyOwnerKind, /// True if this constant/function needs overflow checks. check_overflow: bool, @@ -60,22 +59,20 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - src: MirSource) -> Cx<'a, 'gcx, 'tcx> { - let constness = match src { - MirSource::Const(_) | - MirSource::Static(..) => hir::Constness::Const, - MirSource::GeneratorDrop(..) => hir::Constness::NotConst, - MirSource::Fn(id) => { - let fn_like = FnLikeNode::from_node(infcx.tcx.hir.get(id)); + src_id: ast::NodeId) -> Cx<'a, 'gcx, 'tcx> { + let tcx = infcx.tcx; + let src_def_id = tcx.hir.local_def_id(src_id); + let body_owner_kind = tcx.hir.body_owner_kind(src_id); + + let constness = match body_owner_kind { + hir::BodyOwnerKind::Const | + hir::BodyOwnerKind::Static(_) => hir::Constness::Const, + hir::BodyOwnerKind::Fn => { + let fn_like = FnLikeNode::from_node(infcx.tcx.hir.get(src_id)); fn_like.map_or(hir::Constness::NotConst, |f| f.constness()) } - MirSource::Promoted(..) => bug!(), }; - let tcx = infcx.tcx; - let src_id = src.item_id(); - let src_def_id = tcx.hir.local_def_id(src_id); - let attrs = tcx.hir.attrs(src_id); // Some functions always have overflow checks enabled, @@ -100,7 +97,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { region_scope_tree: tcx.region_scope_tree(src_def_id), tables: tcx.typeck_tables_of(src_def_id), constness, - src, + body_owner_kind, check_overflow, } } diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index b72823dff2b..5e65398e2b9 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -20,6 +20,8 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(box_syntax)] #![feature(conservative_impl_trait)] #![feature(const_fn)] +#![feature(core_intrinsics)] +#![feature(decl_macro)] #![feature(i128_type)] #![feature(rustc_diagnostic_macros)] #![feature(placement_in_syntax)] diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index a3a986918a4..e1f0e01b88c 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -13,7 +13,6 @@ use rustc::hir::def_id::DefId; use rustc::infer; use rustc::middle::const_val::ConstVal; use rustc::mir::*; -use rustc::mir::transform::MirSource; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::ty::maps::Providers; @@ -826,7 +825,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, ctor_id: ast::NodeId, fields: &[hir::StructField], span: Span) - -> (Mir<'tcx>, MirSource) + -> Mir<'tcx> { let tcx = infcx.tcx; let def_id = tcx.hir.local_def_id(ctor_id); @@ -875,7 +874,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, is_cleanup: false }; - let mir = Mir::new( + Mir::new( IndexVec::from_elem_n(start_block, 1), IndexVec::from_elem_n( VisibilityScopeData { span: span, parent_scope: None }, 1 @@ -888,6 +887,5 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, sig.inputs().len(), vec![], span - ); - (mir, MirSource::Fn(ctor_id)) + ) } diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs index 3f14a6be8b2..5be369f85bc 100644 --- a/src/librustc_mir/transform/add_call_guards.rs +++ b/src/librustc_mir/transform/add_call_guards.rs @@ -10,8 +10,8 @@ use rustc::ty::TyCtxt; use rustc::mir::*; -use rustc::mir::transform::{MirPass, MirSource}; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; +use transform::{MirPass, MirSource}; #[derive(PartialEq)] pub enum AddCallGuards { diff --git a/src/librustc_mir/transform/add_validation.rs b/src/librustc_mir/transform/add_validation.rs index 8fad538af97..c6f2154eaa4 100644 --- a/src/librustc_mir/transform/add_validation.rs +++ b/src/librustc_mir/transform/add_validation.rs @@ -17,8 +17,8 @@ use rustc::ty::{self, TyCtxt, RegionKind}; use rustc::hir; use rustc::mir::*; -use rustc::mir::transform::{MirPass, MirSource}; use rustc::middle::region; +use transform::{MirPass, MirSource}; pub struct AddValidation; @@ -106,8 +106,9 @@ fn fn_contains_unsafe<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource) -> } } - let fn_like = match src { - MirSource::Fn(node_id) => { + let node_id = tcx.hir.as_local_node_id(src.def_id).unwrap(); + let fn_like = match tcx.hir.body_owner_kind(node_id) { + hir::BodyOwnerKind::Fn => { match FnLikeNode::from_node(tcx.hir.get(node_id)) { Some(fn_like) => fn_like, None => return false, // e.g. struct ctor shims -- such auto-generated code cannot diff --git a/src/librustc_mir/transform/clean_end_regions.rs b/src/librustc_mir/transform/clean_end_regions.rs index d356d3b5a85..7986313aa81 100644 --- a/src/librustc_mir/transform/clean_end_regions.rs +++ b/src/librustc_mir/transform/clean_end_regions.rs @@ -22,10 +22,10 @@ use rustc_data_structures::fx::FxHashSet; use rustc::middle::region; -use rustc::mir::transform::{MirPass, MirSource}; use rustc::mir::{BasicBlock, Location, Mir, Rvalue, Statement, StatementKind}; use rustc::mir::visit::{MutVisitor, Visitor, TyContext}; use rustc::ty::{Ty, RegionKind, TyCtxt}; +use transform::{MirPass, MirSource}; pub struct CleanEndRegions; diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs index a730fc30615..2966290c296 100644 --- a/src/librustc_mir/transform/copy_prop.rs +++ b/src/librustc_mir/transform/copy_prop.rs @@ -29,10 +29,11 @@ //! (non-mutating) use of `SRC`. These restrictions are conservative and may be relaxed in the //! future. +use rustc::hir; use rustc::mir::{Constant, Local, LocalKind, Location, Lvalue, Mir, Operand, Rvalue, StatementKind}; -use rustc::mir::transform::{MirPass, MirSource}; use rustc::mir::visit::MutVisitor; use rustc::ty::TyCtxt; +use transform::{MirPass, MirSource}; use util::def_use::DefUseAnalysis; pub struct CopyPropagation; @@ -42,25 +43,22 @@ impl MirPass for CopyPropagation { tcx: TyCtxt<'a, 'tcx, 'tcx>, source: MirSource, mir: &mut Mir<'tcx>) { - match source { - MirSource::Const(_) => { - // Don't run on constants, because constant qualification might reject the - // optimized IR. - return - } - MirSource::Static(..) | MirSource::Promoted(..) => { - // Don't run on statics and promoted statics, because trans might not be able to - // evaluate the optimized IR. - return - } - MirSource::Fn(function_node_id) => { - if tcx.is_const_fn(tcx.hir.local_def_id(function_node_id)) { + // Don't run on constant MIR, because trans might not be able to + // evaluate the modified MIR. + // FIXME(eddyb) Remove check after miri is merged. + let id = tcx.hir.as_local_node_id(source.def_id).unwrap(); + match (tcx.hir.body_owner_kind(id), source.promoted) { + (_, Some(_)) | + (hir::BodyOwnerKind::Const, _) | + (hir::BodyOwnerKind::Static(_), _) => return, + + (hir::BodyOwnerKind::Fn, _) => { + if tcx.is_const_fn(source.def_id) { // Don't run on const functions, as, again, trans might not be able to evaluate // the optimized IR. return } } - MirSource::GeneratorDrop(_) => (), } // We only run when the MIR optimization level is > 1. diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs index d21dbeafb5d..61b4716c564 100644 --- a/src/librustc_mir/transform/deaggregator.rs +++ b/src/librustc_mir/transform/deaggregator.rs @@ -8,10 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use rustc::hir; use rustc::ty::TyCtxt; use rustc::mir::*; -use rustc::mir::transform::{MirPass, MirSource}; use rustc_data_structures::indexed_vec::Idx; +use transform::{MirPass, MirSource}; pub struct Deaggregator; @@ -20,16 +21,21 @@ impl MirPass for Deaggregator { tcx: TyCtxt<'a, 'tcx, 'tcx>, source: MirSource, mir: &mut Mir<'tcx>) { - let node_id = source.item_id(); - let node_path = tcx.item_path_str(tcx.hir.local_def_id(node_id)); + let node_path = tcx.item_path_str(source.def_id); debug!("running on: {:?}", node_path); // we only run when mir_opt_level > 2 if tcx.sess.opts.debugging_opts.mir_opt_level <= 2 { return; } - // Do not trigger on constants. Could be revised in future - if let MirSource::Fn(_) = source {} else { return; } + // Don't run on constant MIR, because trans might not be able to + // evaluate the modified MIR. + // FIXME(eddyb) Remove check after miri is merged. + let id = tcx.hir.as_local_node_id(source.def_id).unwrap(); + match (tcx.hir.body_owner_kind(id), source.promoted) { + (hir::BodyOwnerKind::Fn, None) => {}, + _ => return + } // In fact, we might not want to trigger in other cases. // Ex: when we could use SROA. See issue #35259 diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs index cea66837d9a..98753eaa5a3 100644 --- a/src/librustc_mir/transform/dump_mir.rs +++ b/src/librustc_mir/transform/dump_mir.rs @@ -16,9 +16,9 @@ use std::fs::File; use std::io; use rustc::mir::Mir; -use rustc::mir::transform::{MirPass, MirPassIndex, MirSource, MirSuite, PassHook}; use rustc::session::config::{OutputFilenames, OutputType}; use rustc::ty::TyCtxt; +use transform::{MirPass, MirSource}; use util as mir_util; pub struct Marker(pub &'static str); @@ -47,37 +47,21 @@ impl fmt::Display for Disambiguator { } } -pub struct DumpMir; -impl PassHook for DumpMir { - fn on_mir_pass<'a, 'tcx: 'a>(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - suite: MirSuite, - pass_num: MirPassIndex, - pass_name: &str, - source: MirSource, - mir: &Mir<'tcx>, - is_after: bool) - { - if mir_util::dump_enabled(tcx, pass_name, source) { - mir_util::dump_mir(tcx, - Some((suite, pass_num)), - pass_name, - &Disambiguator { is_after }, - source, - mir, - |_, _| Ok(()) ); - for (index, promoted_mir) in mir.promoted.iter_enumerated() { - let promoted_source = MirSource::Promoted(source.item_id(), index); - mir_util::dump_mir(tcx, - Some((suite, pass_num)), - pass_name, - &Disambiguator { is_after }, - promoted_source, - promoted_mir, - |_, _| Ok(()) ); - } - } +pub fn on_mir_pass<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + pass_num: &fmt::Display, + pass_name: &str, + source: MirSource, + mir: &Mir<'tcx>, + is_after: bool) { + if mir_util::dump_enabled(tcx, pass_name, source) { + mir_util::dump_mir(tcx, + Some(pass_num), + pass_name, + &Disambiguator { is_after }, + source, + mir, + |_, _| Ok(()) ); } } diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index 94da1f31a96..c24256cc92c 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -15,13 +15,14 @@ use dataflow::{on_all_children_bits, on_all_drop_children_bits}; use dataflow::{drop_flag_effects_for_location, on_lookup_result_bits}; use dataflow::MoveDataParamEnv; use dataflow; +use rustc::hir; use rustc::ty::{self, TyCtxt}; use rustc::mir::*; -use rustc::mir::transform::{MirPass, MirSource}; use rustc::middle::const_val::ConstVal; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::indexed_set::IdxSetBuf; use rustc_data_structures::indexed_vec::Idx; +use transform::{MirPass, MirSource}; use util::patch::MirPatch; use util::elaborate_drops::{DropFlagState, Unwind, elaborate_drop}; use util::elaborate_drops::{DropElaborator, DropStyle, DropFlagMode}; @@ -39,12 +40,16 @@ impl MirPass for ElaborateDrops { mir: &mut Mir<'tcx>) { debug!("elaborate_drops({:?} @ {:?})", src, mir.span); - match src { - MirSource::Fn(..) => {}, + + // Don't run on constant MIR, because trans might not be able to + // evaluate the modified MIR. + // FIXME(eddyb) Remove check after miri is merged. + let id = tcx.hir.as_local_node_id(src.def_id).unwrap(); + match (tcx.hir.body_owner_kind(id), src.promoted) { + (hir::BodyOwnerKind::Fn, None) => {}, _ => return } - let id = src.item_id(); - let param_env = tcx.param_env(tcx.hir.local_def_id(id)); + let param_env = tcx.param_env(src.def_id); let move_data = MoveData::gather_moves(mir, tcx, param_env).unwrap(); let elaborate_patch = { let mir = &*mir; diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index 08ca20e50eb..dfa048e2e4b 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -18,7 +18,7 @@ use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; use rustc::mir::*; use rustc::mir::visit::{MutVisitor, TyContext}; -use rustc::mir::transform::{MirPass, MirSource}; +use transform::{MirPass, MirSource}; struct EraseRegionsVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 52a50333f45..7d12d50355b 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -63,7 +63,6 @@ use rustc::hir; use rustc::hir::def_id::DefId; use rustc::middle::const_val::ConstVal; use rustc::mir::*; -use rustc::mir::transform::{MirPass, MirSource}; use rustc::mir::visit::{LvalueContext, Visitor, MutVisitor}; use rustc::ty::{self, TyCtxt, AdtDef, Ty, GeneratorInterior}; use rustc::ty::subst::{Kind, Substs}; @@ -76,6 +75,7 @@ use std::collections::HashMap; use std::borrow::Cow; use std::iter::once; use std::mem; +use transform::{MirPass, MirSource}; use transform::simplify; use transform::no_landing_pads::no_landing_pads; use dataflow::{self, MaybeStorageLive, state_for_location}; @@ -338,7 +338,7 @@ fn locals_live_across_suspend_points<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, (liveness::LocalSet, HashMap) { let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); - let node_id = source.item_id(); + let node_id = tcx.hir.as_local_node_id(source.def_id).unwrap(); let analysis = MaybeStorageLive::new(mir); let storage_live = dataflow::do_dataflow(tcx, mir, node_id, &[], &dead_unwinds, analysis, @@ -763,8 +763,8 @@ impl MirPass for StateTransform { assert!(mir.generator_drop.is_none()); - let node_id = source.item_id(); - let def_id = tcx.hir.local_def_id(source.item_id()); + let def_id = source.def_id; + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); let hir_id = tcx.hir.node_to_hir_id(node_id); // Get the interior types which typeck computed diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index ed809836c4f..5dec6177b36 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -10,18 +10,19 @@ //! Inlining pass for MIR functions +use rustc::hir; use rustc::hir::def_id::DefId; use rustc_data_structures::bitvec::BitVector; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc::mir::*; -use rustc::mir::transform::{MirPass, MirSource}; use rustc::mir::visit::*; use rustc::ty::{self, Instance, Ty, TyCtxt, TypeFoldable}; use rustc::ty::subst::{Subst,Substs}; use std::collections::VecDeque; +use transform::{MirPass, MirSource}; use super::simplify::{remove_dead_blocks, CfgSimplifier}; use syntax::{attr}; @@ -77,12 +78,12 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { let mut callsites = VecDeque::new(); - let param_env; + let param_env = self.tcx.param_env(self.source.def_id); // Only do inlining into fn bodies. - if let MirSource::Fn(caller_id) = self.source { - let caller_def_id = self.tcx.hir.local_def_id(caller_id); - param_env = self.tcx.param_env(caller_def_id); + let id = self.tcx.hir.as_local_node_id(self.source.def_id).unwrap(); + let body_owner_kind = self.tcx.hir.body_owner_kind(id); + if let (hir::BodyOwnerKind::Fn, None) = (body_owner_kind, self.source.promoted) { for (bb, bb_data) in caller_mir.basic_blocks().iter_enumerated() { // Don't inline calls that are in cleanup blocks. @@ -251,8 +252,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { // FIXME: Give a bonus to functions with only a single caller - let def_id = tcx.hir.local_def_id(self.source.item_id()); - let param_env = tcx.param_env(def_id); + let param_env = tcx.param_env(self.source.def_id); let mut first_block = true; let mut cost = 0; diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs index 6ccc886577a..b091f2f4b6d 100644 --- a/src/librustc_mir/transform/instcombine.rs +++ b/src/librustc_mir/transform/instcombine.rs @@ -11,12 +11,12 @@ //! Performs various peephole optimizations. use rustc::mir::{Location, Lvalue, Mir, Operand, ProjectionElem, Rvalue, Local}; -use rustc::mir::transform::{MirPass, MirSource}; use rustc::mir::visit::{MutVisitor, Visitor}; use rustc::ty::TyCtxt; use rustc::util::nodemap::FxHashSet; use rustc_data_structures::indexed_vec::Idx; use std::mem; +use transform::{MirPass, MirSource}; pub struct InstCombine; diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 34cc3a289d1..441f9be9be1 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -10,19 +10,17 @@ use build; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; -use rustc::mir::Mir; -use rustc::mir::transform::{MirPassIndex, MirSuite, MirSource, - MIR_CONST, MIR_VALIDATED, MIR_OPTIMIZED}; +use rustc::mir::{Mir, Promoted}; use rustc::ty::TyCtxt; use rustc::ty::maps::Providers; use rustc::ty::steal::Steal; use rustc::hir; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::util::nodemap::DefIdSet; +use std::borrow::Cow; use std::rc::Rc; use syntax::ast; use syntax_pos::Span; -use transform; pub mod add_validation; pub mod clean_end_regions; @@ -109,26 +107,112 @@ fn mir_built<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Stea tcx.alloc_steal_mir(mir) } +/// Where a specific Mir comes from. +#[derive(Debug, Copy, Clone)] +pub struct MirSource { + pub def_id: DefId, + + /// If `Some`, this is a promoted rvalue within the parent function. + pub promoted: Option, +} + +impl MirSource { + pub fn item(def_id: DefId) -> Self { + MirSource { + def_id, + promoted: None + } + } +} + +/// Generates a default name for the pass based on the name of the +/// type `T`. +pub fn default_name() -> Cow<'static, str> { + let name = unsafe { ::std::intrinsics::type_name::() }; + if let Some(tail) = name.rfind(":") { + Cow::from(&name[tail+1..]) + } else { + Cow::from(name) + } +} + +/// A streamlined trait that you can implement to create a pass; the +/// pass will be named after the type, and it will consist of a main +/// loop that goes over each available MIR and applies `run_pass`. +pub trait MirPass { + fn name<'a>(&'a self) -> Cow<'a, str> { + default_name::() + } + + fn run_pass<'a, 'tcx>(&self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + source: MirSource, + mir: &mut Mir<'tcx>); +} + +pub macro run_passes($tcx:ident, $mir:ident, $def_id:ident, $suite_index:expr; $($pass:expr,)*) {{ + let suite_index: usize = $suite_index; + let run_passes = |mir: &mut _, promoted| { + let source = MirSource { + def_id: $def_id, + promoted + }; + let mut index = 0; + let mut run_pass = |pass: &MirPass| { + let run_hooks = |mir: &_, index, is_after| { + dump_mir::on_mir_pass($tcx, &format_args!("{:03}-{:03}", suite_index, index), + &pass.name(), source, mir, is_after); + }; + run_hooks(mir, index, false); + pass.run_pass($tcx, source, mir); + run_hooks(mir, index, true); + + index += 1; + }; + $(run_pass(&$pass);)* + }; + + run_passes(&mut $mir, None); + + for (index, promoted_mir) in $mir.promoted.iter_enumerated_mut() { + run_passes(promoted_mir, Some(index)); + + // Let's make sure we don't miss any nested instances + assert!(promoted_mir.promoted.is_empty()); + } +}} + fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal> { // Unsafety check uses the raw mir, so make sure it is run let _ = tcx.unsafety_check_result(def_id); - let source = MirSource::from_local_def_id(tcx, def_id); let mut mir = tcx.mir_built(def_id).steal(); - transform::run_suite(tcx, source, MIR_CONST, &mut mir); + run_passes![tcx, mir, def_id, 0; + // Remove all `EndRegion` statements that are not involved in borrows. + clean_end_regions::CleanEndRegions, + + // What we need to do constant evaluation. + simplify::SimplifyCfg::new("initial"), + type_check::TypeckMir, + rustc_peek::SanityCheck, + ]; tcx.alloc_steal_mir(mir) } fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal> { - let source = MirSource::from_local_def_id(tcx, def_id); - if let MirSource::Const(_) = source { + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + if let hir::BodyOwnerKind::Const = tcx.hir.body_owner_kind(node_id) { // Ensure that we compute the `mir_const_qualif` for constants at // this point, before we steal the mir-const result. let _ = tcx.mir_const_qualif(def_id); } let mut mir = tcx.mir_const(def_id).steal(); - transform::run_suite(tcx, source, MIR_VALIDATED, &mut mir); + run_passes![tcx, mir, def_id, 1; + // What we need to run borrowck etc. + qualify_consts::QualifyAndPromoteConstants, + simplify::SimplifyCfg::new("qualify-consts"), + ]; tcx.alloc_steal_mir(mir) } @@ -139,37 +223,34 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx let _ = tcx.borrowck(def_id); let mut mir = tcx.mir_validated(def_id).steal(); - let source = MirSource::from_local_def_id(tcx, def_id); - transform::run_suite(tcx, source, MIR_OPTIMIZED, &mut mir); + run_passes![tcx, mir, def_id, 2; + no_landing_pads::NoLandingPads, + simplify_branches::SimplifyBranches::new("initial"), + + // These next passes must be executed together + add_call_guards::CriticalCallEdges, + elaborate_drops::ElaborateDrops, + no_landing_pads::NoLandingPads, + // AddValidation needs to run after ElaborateDrops and before EraseRegions, and it needs + // an AllCallEdges pass right before it. + add_call_guards::AllCallEdges, + add_validation::AddValidation, + simplify::SimplifyCfg::new("elaborate-drops"), + // No lifetime analysis based on borrowing can be done from here on out. + + // From here on out, regions are gone. + erase_regions::EraseRegions, + + // Optimizations begin. + inline::Inline, + instcombine::InstCombine, + deaggregator::Deaggregator, + copy_prop::CopyPropagation, + simplify::SimplifyLocals, + + generator::StateTransform, + add_call_guards::CriticalCallEdges, + dump_mir::Marker("PreTrans"), + ]; tcx.alloc_mir(mir) } - -fn run_suite<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - source: MirSource, - suite: MirSuite, - mir: &mut Mir<'tcx>) -{ - let passes = tcx.mir_passes.passes(suite); - - for (pass, index) in passes.iter().zip(0..) { - let pass_num = MirPassIndex(index); - - for hook in tcx.mir_passes.hooks() { - hook.on_mir_pass(tcx, suite, pass_num, &pass.name(), source, &mir, false); - } - - pass.run_pass(tcx, source, mir); - - for (index, promoted_mir) in mir.promoted.iter_enumerated_mut() { - let promoted_source = MirSource::Promoted(source.item_id(), index); - pass.run_pass(tcx, promoted_source, promoted_mir); - - // Let's make sure we don't miss any nested instances - assert!(promoted_mir.promoted.is_empty()); - } - - for hook in tcx.mir_passes.hooks() { - hook.on_mir_pass(tcx, suite, pass_num, &pass.name(), source, &mir, true); - } - } -} diff --git a/src/librustc_mir/transform/nll/constraint_generation.rs b/src/librustc_mir/transform/nll/constraint_generation.rs index a2f9bbb174e..b095a198d8f 100644 --- a/src/librustc_mir/transform/nll/constraint_generation.rs +++ b/src/librustc_mir/transform/nll/constraint_generation.rs @@ -10,7 +10,6 @@ use rustc::hir; use rustc::mir::{BasicBlock, BorrowKind, Location, Lvalue, Mir, Rvalue, Statement, StatementKind}; -use rustc::mir::transform::MirSource; use rustc::mir::visit::Visitor; use rustc::mir::Lvalue::Projection; use rustc::mir::{LvalueProjection, ProjectionElem}; @@ -31,7 +30,7 @@ pub(super) fn generate_constraints<'a, 'gcx, 'tcx>( infcx: &InferCtxt<'a, 'gcx, 'tcx>, regioncx: &mut RegionInferenceContext<'tcx>, mir: &Mir<'tcx>, - mir_source: MirSource, + param_env: ty::ParamEnv<'tcx>, liveness: &LivenessResults, ) { ConstraintGeneration { @@ -39,7 +38,7 @@ pub(super) fn generate_constraints<'a, 'gcx, 'tcx>( regioncx, mir, liveness, - mir_source, + param_env, }.add_constraints(); } @@ -48,7 +47,7 @@ struct ConstraintGeneration<'cx, 'gcx: 'tcx, 'tcx: 'cx> { regioncx: &'cx mut RegionInferenceContext<'tcx>, mir: &'cx Mir<'tcx>, liveness: &'cx LivenessResults, - mir_source: MirSource, + param_env: ty::ParamEnv<'tcx>, } impl<'cx, 'gcx, 'tcx> ConstraintGeneration<'cx, 'gcx, 'tcx> { @@ -153,13 +152,11 @@ impl<'cx, 'gcx, 'tcx> ConstraintGeneration<'cx, 'gcx, 'tcx> { // `dtorck_constraint_for_ty` could not resolve (e.g., // associated types and parameters). We need to normalize // associated types here and possibly recursively process. - let def_id = tcx.hir.local_def_id(self.mir_source.item_id()); - let param_env = self.infcx.tcx.param_env(def_id); for ty in dtorck_types { // FIXME -- I think that this may disregard some region obligations // or something. Do we care? -nmatsakis let cause = ObligationCause::dummy(); - match traits::fully_normalize(self.infcx, cause, param_env, &ty) { + match traits::fully_normalize(self.infcx, cause, self.param_env, &ty) { Ok(ty) => match ty.sty { ty::TyParam(..) | ty::TyProjection(..) | ty::TyAnon(..) => { self.add_regular_live_constraint(ty, location); diff --git a/src/librustc_mir/transform/nll/free_regions.rs b/src/librustc_mir/transform/nll/free_regions.rs index 006a2f9047a..554d212880e 100644 --- a/src/librustc_mir/transform/nll/free_regions.rs +++ b/src/librustc_mir/transform/nll/free_regions.rs @@ -22,9 +22,9 @@ //! The code in this file doesn't *do anything* with those results; it //! just returns them for other code to use. +use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; use rustc::middle::free_region::FreeRegionMap; -use rustc::mir::transform::MirSource; use rustc::ty; use rustc::ty::subst::Substs; use rustc::util::nodemap::FxHashMap; @@ -43,12 +43,9 @@ pub struct FreeRegions<'tcx> { pub fn free_regions<'a, 'gcx, 'tcx>( infcx: &InferCtxt<'a, 'gcx, 'tcx>, - source: MirSource, + item_def_id: DefId, ) -> FreeRegions<'tcx> { - debug!("free_regions(source={:?})", source); - - let item_id = source.item_id(); - let item_def_id = infcx.tcx.hir.local_def_id(item_id); + debug!("free_regions(item_def_id={:?})", item_def_id); let mut indices = FxHashMap(); @@ -63,6 +60,7 @@ pub fn free_regions<'a, 'gcx, 'tcx>( // Extract the late-bound regions. Use the liberated fn sigs, // where the late-bound regions will have been converted into free // regions, and add them to the map. + let item_id = infcx.tcx.hir.as_local_node_id(item_def_id).unwrap(); let fn_hir_id = infcx.tcx.hir.node_to_hir_id(item_id); let tables = infcx.tcx.typeck_tables_of(item_def_id); let fn_sig = tables.liberated_fn_sigs()[fn_hir_id].clone(); diff --git a/src/librustc_mir/transform/nll/mod.rs b/src/librustc_mir/transform/nll/mod.rs index e24def2292e..f27d0a8da16 100644 --- a/src/librustc_mir/transform/nll/mod.rs +++ b/src/librustc_mir/transform/nll/mod.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::ty::{self, RegionKind}; +use rustc::hir::def_id::DefId; use rustc::mir::Mir; -use rustc::mir::transform::MirSource; use rustc::infer::InferCtxt; +use rustc::ty::{self, RegionKind}; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::indexed_vec::Idx; use std::collections::BTreeSet; +use transform::MirSource; use util::liveness::{self, LivenessMode, LivenessResult, LocalSet}; use util as mir_util; @@ -34,11 +35,11 @@ mod renumber; /// This may result in errors being reported. pub fn compute_regions<'a, 'gcx, 'tcx>( infcx: &InferCtxt<'a, 'gcx, 'tcx>, - source: MirSource, + def_id: DefId, mir: &mut Mir<'tcx>, ) -> RegionInferenceContext<'tcx> { // Compute named region information. - let free_regions = &free_regions::free_regions(infcx, source); + let free_regions = &free_regions::free_regions(infcx, def_id); // Replace all regions with fresh inference variables. let num_region_variables = renumber::renumber_mir(infcx, free_regions, mir); @@ -65,12 +66,13 @@ pub fn compute_regions<'a, 'gcx, 'tcx>( // Create the region inference context, generate the constraints, // and then solve them. let mut regioncx = RegionInferenceContext::new(free_regions, num_region_variables, mir); - constraint_generation::generate_constraints(infcx, &mut regioncx, &mir, source, liveness); + let param_env = infcx.tcx.param_env(def_id); + constraint_generation::generate_constraints(infcx, &mut regioncx, &mir, param_env, liveness); regioncx.solve(infcx, &mir); // Dump MIR results into a file, if that is enabled. This let us // write unit-tests. - dump_mir_results(infcx, liveness, source, &mir, ®ioncx); + dump_mir_results(infcx, liveness, MirSource::item(def_id), &mir, ®ioncx); regioncx } diff --git a/src/librustc_mir/transform/no_landing_pads.rs b/src/librustc_mir/transform/no_landing_pads.rs index 7de8de3c96b..dd5898cb561 100644 --- a/src/librustc_mir/transform/no_landing_pads.rs +++ b/src/librustc_mir/transform/no_landing_pads.rs @@ -14,7 +14,7 @@ use rustc::ty::TyCtxt; use rustc::mir::*; use rustc::mir::visit::MutVisitor; -use rustc::mir::transform::{MirPass, MirSource}; +use transform::{MirPass, MirSource}; pub struct NoLandingPads; diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 583dfd9b616..ab29134c325 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -26,7 +26,6 @@ use rustc::ty::cast::CastTy; use rustc::ty::maps::Providers; use rustc::mir::*; use rustc::mir::traversal::ReversePostorder; -use rustc::mir::transform::{MirPass, MirSource}; use rustc::mir::visit::{LvalueContext, Visitor}; use rustc::middle::lang_items; use syntax::abi::Abi; @@ -38,6 +37,7 @@ use std::fmt; use std::rc::Rc; use std::usize; +use transform::{MirPass, MirSource}; use super::promote_consts::{self, Candidate, TempState}; bitflags! { @@ -961,25 +961,27 @@ impl MirPass for QualifyAndPromoteConstants { return; } - let id = src.item_id(); - let def_id = tcx.hir.local_def_id(id); + if src.promoted.is_some() { + return; + } + + let def_id = src.def_id; + let id = tcx.hir.as_local_node_id(def_id).unwrap(); let mut const_promoted_temps = None; - let mode = match src { - MirSource::Fn(_) => { + let mode = match tcx.hir.body_owner_kind(id) { + hir::BodyOwnerKind::Fn => { if tcx.is_const_fn(def_id) { Mode::ConstFn } else { Mode::Fn } } - MirSource::Const(_) => { + hir::BodyOwnerKind::Const => { const_promoted_temps = Some(tcx.mir_const_qualif(def_id).1); Mode::Const } - MirSource::Static(_, hir::MutImmutable) => Mode::Static, - MirSource::Static(_, hir::MutMutable) => Mode::StaticMut, - MirSource::GeneratorDrop(_) | - MirSource::Promoted(..) => return + hir::BodyOwnerKind::Static(hir::MutImmutable) => Mode::Static, + hir::BodyOwnerKind::Static(hir::MutMutable) => Mode::StaticMut, }; if mode == Mode::Fn || mode == Mode::ConstFn { diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index 8d6458d7934..32d4a14c7f7 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -14,9 +14,9 @@ use syntax_pos::Span; use rustc::ty::{self, TyCtxt}; use rustc::mir::{self, Mir, Location}; -use rustc::mir::transform::{MirPass, MirSource}; use rustc_data_structures::indexed_set::IdxSetBuf; use rustc_data_structures::indexed_vec::Idx; +use transform::{MirPass, MirSource}; use dataflow::do_dataflow; use dataflow::MoveDataParamEnv; @@ -34,8 +34,8 @@ pub struct SanityCheck; impl MirPass for SanityCheck { fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &mut Mir<'tcx>) { - let id = src.item_id(); - let def_id = tcx.hir.local_def_id(id); + let def_id = src.def_id; + let id = tcx.hir.as_local_node_id(def_id).unwrap(); if !tcx.has_attr(def_id, "rustc_mir_borrowck") { debug!("skipping rustc_peek::SanityCheck on {}", tcx.item_path_str(def_id)); return; diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 89828cf375a..02ae6328461 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -41,9 +41,9 @@ use rustc_data_structures::bitvec::BitVector; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc::ty::TyCtxt; use rustc::mir::*; -use rustc::mir::transform::{MirPass, MirSource}; use rustc::mir::visit::{MutVisitor, Visitor, LvalueContext}; use std::borrow::Cow; +use transform::{MirPass, MirSource}; pub struct SimplifyCfg { label: String } diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs index edbbe5305e9..20c33bab1aa 100644 --- a/src/librustc_mir/transform/simplify_branches.rs +++ b/src/librustc_mir/transform/simplify_branches.rs @@ -12,8 +12,8 @@ use rustc::ty::{self, TyCtxt}; use rustc::middle::const_val::ConstVal; -use rustc::mir::transform::{MirPass, MirSource}; use rustc::mir::*; +use transform::{MirPass, MirSource}; use std::borrow::Cow; diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index b07e818ee87..dc462cd9c74 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -18,11 +18,11 @@ use rustc::ty::{self, Ty, TyCtxt, TypeVariants}; use rustc::middle::const_val::ConstVal; use rustc::mir::*; use rustc::mir::tcx::LvalueTy; -use rustc::mir::transform::{MirPass, MirSource}; use rustc::mir::visit::Visitor; use std::fmt; use syntax::ast; use syntax_pos::{Span, DUMMY_SP}; +use transform::{MirPass, MirSource}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_vec::Idx; @@ -794,8 +794,8 @@ impl MirPass for TypeckMir { tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &mut Mir<'tcx>) { - let item_id = src.item_id(); - let def_id = tcx.hir.local_def_id(item_id); + let def_id = src.def_id; + let id = tcx.hir.as_local_node_id(def_id).unwrap(); debug!("run_pass: {:?}", def_id); if tcx.sess.err_count() > 0 { @@ -805,7 +805,7 @@ impl MirPass for TypeckMir { } let param_env = tcx.param_env(def_id); tcx.infer_ctxt().enter(|infcx| { - let mut checker = TypeChecker::new(&infcx, item_id, param_env); + let mut checker = TypeChecker::new(&infcx, id, param_env); { let mut verifier = TypeVerifier::new(&mut checker, mir); verifier.visit_mir(mir); diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs index a38d317b823..b3c7b4bce03 100644 --- a/src/librustc_mir/util/graphviz.rs +++ b/src/librustc_mir/util/graphviz.rs @@ -14,7 +14,6 @@ use rustc::mir::*; use rustc::ty::TyCtxt; use std::fmt::Debug; use std::io::{self, Write}; -use syntax::ast::NodeId; use rustc_data_structures::indexed_vec::Idx; @@ -28,21 +27,20 @@ pub fn write_mir_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>, where W: Write { for def_id in dump_mir_def_ids(tcx, single) { - let nodeid = tcx.hir.as_local_node_id(def_id).unwrap(); let mir = &tcx.optimized_mir(def_id); - write_mir_fn_graphviz(tcx, nodeid, mir, w)?; + write_mir_fn_graphviz(tcx, def_id, mir, w)?; } Ok(()) } /// Write a graphviz DOT graph of the MIR. pub fn write_mir_fn_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>, - nodeid: NodeId, + def_id: DefId, mir: &Mir, w: &mut W) -> io::Result<()> where W: Write { - writeln!(w, "digraph Mir_{} {{", nodeid)?; + writeln!(w, "digraph Mir_{} {{", tcx.hir.as_local_node_id(def_id).unwrap())?; // Global graph properties writeln!(w, r#" graph [fontname="monospace"];"#)?; @@ -50,7 +48,7 @@ pub fn write_mir_fn_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>, writeln!(w, r#" edge [fontname="monospace"];"#)?; // Graph label - write_graph_label(tcx, nodeid, mir, w)?; + write_graph_label(tcx, def_id, mir, w)?; // Nodes for (block, _) in mir.basic_blocks().iter_enumerated() { @@ -138,11 +136,11 @@ fn write_edges(source: BasicBlock, mir: &Mir, w: &mut W) -> io::Result /// will appear below the graph, showing the type of the `fn` this MIR represents and the types of /// all the variables and temporaries. fn write_graph_label<'a, 'gcx, 'tcx, W: Write>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - nid: NodeId, + def_id: DefId, mir: &Mir, w: &mut W) -> io::Result<()> { - write!(w, " label=; @@ -357,7 +357,7 @@ pub fn dump_mir<'a, 'tcx>( } let node_path = item_path::with_forced_impl_filename_line(|| { // see notes on #41697 below - tcx.item_path_str(tcx.hir.local_def_id(source.item_id())) + tcx.item_path_str(source.def_id) }); dump_matched_mir_node(tcx, pass_name, &node_path, source, mir, result); } @@ -375,7 +375,8 @@ fn dump_matched_mir_node<'a, 'tcx>( let p = Path::new(file_dir); file_path.push(p); }; - let file_name = format!("rustc.node{}{}-liveness.mir", source.item_id(), pass_name); + let item_id = tcx.hir.as_local_node_id(source.def_id).unwrap(); + let file_name = format!("rustc.node{}{}-liveness.mir", item_id, pass_name); file_path.push(&file_name); let _ = fs::File::create(&file_path).and_then(|mut file| { writeln!(file, "// MIR local liveness analysis for `{}`", node_path)?; diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 0f07f1fe550..5dc7a324c2d 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -11,7 +11,6 @@ use rustc::hir; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::mir::*; -use rustc::mir::transform::{MirSuite, MirPassIndex, MirSource}; use rustc::ty::TyCtxt; use rustc::ty::item_path; use rustc_data_structures::fx::FxHashMap; @@ -21,6 +20,7 @@ use std::fs; use std::io::{self, Write}; use std::path::{PathBuf, Path}; use super::graphviz::write_mir_fn_graphviz; +use transform::MirSource; const INDENT: &'static str = " "; /// Alignment for lining up comments following MIR statements @@ -57,7 +57,7 @@ pub enum PassWhere { /// that can appear in the pass-name or the `item_path_str` for the given /// node-id. If any one of the substrings match, the data is dumped out. pub fn dump_mir<'a, 'gcx, 'tcx, F>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - pass_num: Option<(MirSuite, MirPassIndex)>, + pass_num: Option<&Display>, pass_name: &str, disambiguator: &Display, source: MirSource, @@ -71,7 +71,7 @@ where } let node_path = item_path::with_forced_impl_filename_line(|| { // see notes on #41697 below - tcx.item_path_str(tcx.hir.local_def_id(source.item_id())) + tcx.item_path_str(source.def_id) }); dump_matched_mir_node(tcx, pass_num, pass_name, &node_path, disambiguator, source, mir, extra_data); @@ -85,9 +85,8 @@ pub fn dump_enabled<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, None => return false, Some(ref filters) => filters, }; - let node_id = source.item_id(); let node_path = item_path::with_forced_impl_filename_line(|| { // see notes on #41697 below - tcx.item_path_str(tcx.hir.local_def_id(node_id)) + tcx.item_path_str(source.def_id) }); filters.split("&") .any(|filter| { @@ -102,7 +101,7 @@ pub fn dump_enabled<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, // run while we are already attempting to evaluate `type_of`. fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - pass_num: Option<(MirSuite, MirPassIndex)>, + pass_num: Option<&Display>, pass_name: &str, node_path: &str, disambiguator: &Display, @@ -112,10 +111,9 @@ fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>(tcx: TyCtxt<'a, 'gcx, 'tcx>, where F: FnMut(PassWhere, &mut Write) -> io::Result<()> { - let promotion_id = match source { - MirSource::Promoted(_, id) => format!("-{:?}", id), - MirSource::GeneratorDrop(_) => format!("-drop"), - _ => String::new() + let promotion_id = match source.promoted { + Some(id) => format!("-{:?}", id), + None => String::new() }; let pass_num = if tcx.sess.opts.debugging_opts.dump_mir_exclude_pass_number { @@ -123,7 +121,7 @@ where } else { match pass_num { None => format!(".-------"), - Some((suite, pass_num)) => format!(".{:03}-{:03}", suite.0, pass_num.0), + Some(pass_num) => format!(".{}", pass_num), } }; @@ -134,11 +132,9 @@ where }; let _ = fs::create_dir_all(&file_path); - let function_name = tcx.hir.def_path_from_id(source.item_id()) - .map(|d| d.to_filename_friendly_no_crate()) - .unwrap_or(format!("node{}", source.item_id())); + let item_name = tcx.hir.def_path(source.def_id).to_filename_friendly_no_crate(); let file_name = format!("rustc.{}{}{}.{}.{}.mir", - function_name, promotion_id, pass_num, pass_name, disambiguator); + item_name, promotion_id, pass_num, pass_name, disambiguator); file_path.push(&file_name); let _ = fs::File::create(&file_path).and_then(|mut file| { writeln!(file, "// MIR for `{}`", node_path)?; @@ -158,7 +154,7 @@ where if tcx.sess.opts.debugging_opts.dump_mir_graphviz { file_path.set_extension("dot"); let _ = fs::File::create(&file_path).and_then(|mut file| { - write_mir_fn_graphviz(tcx, source.item_id(), mir, &mut file)?; + write_mir_fn_graphviz(tcx, source.def_id, mir, &mut file)?; Ok(()) }); } @@ -184,13 +180,15 @@ pub fn write_mir_pretty<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, writeln!(w, "")?; } - let id = tcx.hir.as_local_node_id(def_id).unwrap(); - let src = MirSource::from_node(tcx, id); - write_mir_fn(tcx, src, mir, &mut |_, _| Ok(()), w)?; + write_mir_fn(tcx, MirSource::item(def_id), mir, &mut |_, _| Ok(()), w)?; for (i, mir) in mir.promoted.iter_enumerated() { writeln!(w, "")?; - write_mir_fn(tcx, MirSource::Promoted(id, i), mir, &mut |_, _| Ok(()), w)?; + let src = MirSource { + def_id, + promoted: Some(i) + }; + write_mir_fn(tcx, src, mir, &mut |_, _| Ok(()), w)?; } } Ok(()) @@ -368,21 +366,22 @@ pub fn write_mir_intro<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut Write) -> io::Result<()> { - match src { - MirSource::Fn(_) => write!(w, "fn")?, - MirSource::Const(_) => write!(w, "const")?, - MirSource::Static(_, hir::MutImmutable) => write!(w, "static")?, - MirSource::Static(_, hir::MutMutable) => write!(w, "static mut")?, - MirSource::Promoted(_, i) => write!(w, "{:?} in", i)?, - MirSource::GeneratorDrop(_) => write!(w, "drop_glue")?, + let id = tcx.hir.as_local_node_id(src.def_id).unwrap(); + let body_owner_kind = tcx.hir.body_owner_kind(id); + match (body_owner_kind, src.promoted) { + (_, Some(i)) => write!(w, "{:?} in", i)?, + (hir::BodyOwnerKind::Fn, _) => write!(w, "fn")?, + (hir::BodyOwnerKind::Const, _) => write!(w, "const")?, + (hir::BodyOwnerKind::Static(hir::MutImmutable), _) => write!(w, "static")?, + (hir::BodyOwnerKind::Static(hir::MutMutable), _) => write!(w, "static mut")?, } item_path::with_forced_impl_filename_line(|| { // see notes on #41697 elsewhere - write!(w, " {}", tcx.node_path_str(src.item_id())) + write!(w, " {}", tcx.item_path_str(src.def_id)) })?; - match src { - MirSource::Fn(_) | MirSource::GeneratorDrop(_) => { + match (body_owner_kind, src.promoted) { + (hir::BodyOwnerKind::Fn, None) => { write!(w, "(")?; // fn argument types. @@ -395,9 +394,9 @@ fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut Write) write!(w, ") -> {}", mir.return_ty) } - MirSource::Const(..) | - MirSource::Static(..) | - MirSource::Promoted(..) => { + (hir::BodyOwnerKind::Const, _) | + (hir::BodyOwnerKind::Static(_), _) | + (_, Some(_)) => { assert_eq!(mir.arg_count, 0); write!(w, ": {} =", mir.return_ty) } diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 4515d9c7837..776b5f3c984 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -37,7 +37,6 @@ use rustc::hir::map::blocks::FnLikeNode; use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization as mc; use rustc::middle::mem_categorization::Categorization; -use rustc::mir::transform::MirSource; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::maps::{queries, Providers}; use rustc::ty::subst::Substs; @@ -184,9 +183,9 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { self.in_fn = false; self.in_static = false; - match MirSource::from_node(self.tcx, item_id) { - MirSource::Fn(_) => self.in_fn = true, - MirSource::Static(_, _) => self.in_static = true, + match self.tcx.hir.body_owner_kind(item_id) { + hir::BodyOwnerKind::Fn => self.in_fn = true, + hir::BodyOwnerKind::Static(_) => self.in_static = true, _ => {} };