Auto merge of #45916 - eddyb:even-mirer-0, r=nikomatsakis
rustc_mir: hardcode pass list internally and remove premature pluggability. Fixes #41712 by moving the MIR pass lists from `rustc_driver` to `rustc_mir`. The application of the passes is done with the `rustc_mir::transform::run_passes` macro, which is public, as are all the passes AFAIK, and can be used to apply MIR passes outside of `rustc_mir`. With the ability to override query providers through the `rustc_driver` (orthogonal to, and not included in this PR), custom drivers will be able to substitute the entire pass list if they want to. **EDIT**: the aforementioned ability is added by #45944. r? @nikomatsakis
This commit is contained in:
commit
24840dab0b
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T: ?Sized>() -> Cow<'static, str> {
|
||||
let name = unsafe { ::std::intrinsics::type_name::<T>() };
|
||||
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::<Self>()
|
||||
}
|
||||
|
||||
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<Rc<PassHook>>,
|
||||
suites: Vec<Vec<Rc<MirPass>>>,
|
||||
}
|
||||
|
||||
/// 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<T: MirPass + 'static>(&mut self, suite: MirSuite, pass: T) {
|
||||
self.suites[suite.0].push(Rc::new(pass));
|
||||
}
|
||||
|
||||
/// Pushes a pass hook.
|
||||
pub fn push_hook<T: PassHook + 'static>(&mut self, hook: T) {
|
||||
self.pass_hooks.push(Rc::new(hook));
|
||||
}
|
||||
|
||||
pub fn passes(&self, suite: MirSuite) -> &[Rc<MirPass>] {
|
||||
&self.suites[suite.0]
|
||||
}
|
||||
|
||||
pub fn hooks(&self) -> &[Rc<PassHook>] {
|
||||
&self.pass_hooks
|
||||
}
|
||||
}
|
|
@ -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<Passes>,
|
||||
|
||||
// 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<Passes>,
|
||||
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(),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<F>(source_string: &str,
|
|||
&*cstore,
|
||||
ty::maps::Providers::default(),
|
||||
ty::maps::Providers::default(),
|
||||
Rc::new(Passes::new()),
|
||||
&arenas,
|
||||
&arena,
|
||||
resolutions,
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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<'tcx>>(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<'tcx>>(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
|
||||
})
|
||||
|
|
|
@ -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<region::Scope> {
|
||||
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!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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))
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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(()) );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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<BasicBlock, liveness::LocalSet>) {
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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<Promoted>,
|
||||
}
|
||||
|
||||
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<T: ?Sized>() -> Cow<'static, str> {
|
||||
let name = unsafe { ::std::intrinsics::type_name::<T>() };
|
||||
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::<Self>()
|
||||
}
|
||||
|
||||
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<Mir<'tcx>> {
|
||||
// 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<Mir<'tcx>> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 }
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<W: Write>(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=<fn {}(", dot::escape_html(&tcx.node_path_str(nid)))?;
|
||||
write!(w, " label=<fn {}(", dot::escape_html(&tcx.item_path_str(def_id)))?;
|
||||
|
||||
// fn argument types.
|
||||
for (i, arg) in mir.args_iter().enumerate() {
|
||||
|
|
|
@ -38,12 +38,12 @@ use rustc::mir::visit::{LvalueContext, Visitor};
|
|||
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||
use rustc_data_structures::indexed_set::IdxSetBuf;
|
||||
use util::pretty::{dump_enabled, write_basic_block, write_mir_intro};
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc::ty::item_path;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::fs;
|
||||
use rustc::ty::TyCtxt;
|
||||
use std::io::{self, Write};
|
||||
use transform::MirSource;
|
||||
|
||||
pub type LocalSet = IdxSetBuf<Local>;
|
||||
|
||||
|
@ -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)?;
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
_ => {}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue