From 14efbf148109888f939f671fbd5b60650c5f4744 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 3 May 2016 00:26:41 +0300 Subject: [PATCH] mir: prepare for rvalue promotion support. --- src/librustc/dep_graph/dep_node.rs | 2 + src/librustc/mir/repr.rs | 12 +++ src/librustc/mir/transform.rs | 77 ++++++++++++++++- src/librustc/mir/visit.rs | 4 +- src/librustc_metadata/decoder.rs | 3 + src/librustc_mir/build/mod.rs | 1 + src/librustc_mir/mir_map.rs | 35 +++++--- src/librustc_mir/pretty.rs | 63 +++++++++----- .../transform/break_critical_edges.rs | 5 +- src/librustc_mir/transform/erase_regions.rs | 5 +- src/librustc_mir/transform/no_landing_pads.rs | 5 +- .../transform/remove_dead_blocks.rs | 5 +- src/librustc_mir/transform/simplify_cfg.rs | 9 +- src/librustc_mir/transform/type_check.rs | 16 ++-- src/librustc_trans/collector.rs | 3 + src/librustc_trans/mir/constant.rs | 82 +++++++++++-------- .../auxiliary/dummy_mir_pass.rs | 6 +- 17 files changed, 237 insertions(+), 96 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 85b4b4f59c4..8378495599c 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -64,6 +64,7 @@ pub enum DepNode { IntrinsicCheck(D), MatchCheck(D), MirMapConstruction(D), + MirPass(D), MirTypeck(D), BorrowCheck(D), RvalueCheck(D), @@ -186,6 +187,7 @@ impl DepNode { IntrinsicCheck(ref d) => op(d).map(IntrinsicCheck), MatchCheck(ref d) => op(d).map(MatchCheck), MirMapConstruction(ref d) => op(d).map(MirMapConstruction), + MirPass(ref d) => op(d).map(MirPass), MirTypeck(ref d) => op(d).map(MirTypeck), BorrowCheck(ref d) => op(d).map(BorrowCheck), RvalueCheck(ref d) => op(d).map(RvalueCheck), diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs index 9ec05a9b292..9f8a3dbfa8f 100644 --- a/src/librustc/mir/repr.rs +++ b/src/librustc/mir/repr.rs @@ -36,6 +36,11 @@ pub struct Mir<'tcx> { /// used (eventually) for debuginfo. Indexed by a `ScopeId`. pub scopes: Vec, + /// Rvalues promoted from this function, such as borrows of constants. + /// Each of them is the Mir of a constant with the fn's type parameters + /// in scope, but no vars or args and a separate set of temps. + pub promoted: Vec>, + /// Return type of the function. pub return_ty: FnOutput<'tcx>, @@ -987,6 +992,10 @@ pub enum Literal<'tcx> { Value { value: ConstVal, }, + Promoted { + // Index into the `promoted` vector of `Mir`. + index: usize + }, } impl<'tcx> Debug for Constant<'tcx> { @@ -1007,6 +1016,9 @@ impl<'tcx> Debug for Literal<'tcx> { write!(fmt, "const ")?; fmt_const_val(fmt, value) } + Promoted { index } => { + write!(fmt, "promoted{}", index) + } } } } diff --git a/src/librustc/mir/transform.rs b/src/librustc/mir/transform.rs index 410e3f9d066..520bfbddf9f 100644 --- a/src/librustc/mir/transform.rs +++ b/src/librustc/mir/transform.rs @@ -8,31 +8,102 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use dep_graph::DepNode; +use hir; +use hir::map::DefPathData; +use hir::def_id::DefId; use mir::mir_map::MirMap; use mir::repr::Mir; use ty::TyCtxt; use syntax::ast::NodeId; +/// Where a specific Mir comes from. +#[derive(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, usize) +} + +impl MirSource { + pub fn from_node(tcx: &TyCtxt, id: NodeId) -> MirSource { + use hir::*; + + // Handle constants in enum discriminants, types, and repeat expressions. + let def_id = tcx.map.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.map.get(id) { + map::NodeItem(&Item { node: ItemConst(..), .. }) | + map::NodeTraitItem(&TraitItem { node: ConstTraitItem(..), .. }) | + 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::Static(id, _) | + MirSource::Promoted(id, _) => id + } + } +} + /// Various information about pass. pub trait Pass { // fn name() for printouts of various sorts? // fn should_run(Session) to check if pass should run? + fn dep_node(&self, def_id: DefId) -> DepNode { + DepNode::MirPass(def_id) + } } /// A pass which inspects the whole MirMap. pub trait MirMapPass<'tcx>: Pass { - fn run_pass(&mut self, cx: &TyCtxt<'tcx>, map: &mut MirMap<'tcx>); + fn run_pass(&mut self, tcx: &TyCtxt<'tcx>, map: &mut MirMap<'tcx>); } /// A pass which inspects Mir of functions in isolation. pub trait MirPass<'tcx>: Pass { - fn run_pass(&mut self, cx: &TyCtxt<'tcx>, id: NodeId, mir: &mut Mir<'tcx>); + fn run_pass_on_promoted(&mut self, tcx: &TyCtxt<'tcx>, + item_id: NodeId, index: usize, + mir: &mut Mir<'tcx>) { + self.run_pass(tcx, MirSource::Promoted(item_id, index), mir); + } + fn run_pass(&mut self, tcx: &TyCtxt<'tcx>, src: MirSource, mir: &mut Mir<'tcx>); } impl<'tcx, T: MirPass<'tcx>> MirMapPass<'tcx> for T { fn run_pass(&mut self, tcx: &TyCtxt<'tcx>, map: &mut MirMap<'tcx>) { for (&id, mir) in &mut map.map { - MirPass::run_pass(self, tcx, id, mir); + let def_id = tcx.map.local_def_id(id); + let _task = tcx.dep_graph.in_task(self.dep_node(def_id)); + + let src = MirSource::from_node(tcx, id); + MirPass::run_pass(self, tcx, src, mir); + + for (i, mir) in mir.promoted.iter_mut().enumerate() { + self.run_pass_on_promoted(tcx, id, i, mir); + } } } } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 10afd3dd953..f6a241004b3 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -244,6 +244,7 @@ macro_rules! make_mir_visitor { let Mir { ref $($mutability)* basic_blocks, ref $($mutability)* scopes, + promoted: _, // Visited by passes separately. ref $($mutability)* return_ty, ref $($mutability)* var_decls, ref $($mutability)* arg_decls, @@ -649,10 +650,11 @@ macro_rules! make_mir_visitor { ref $($mutability)* substs } => { self.visit_def_id(def_id); self.visit_substs(substs); - }, + } Literal::Value { ref $($mutability)* value } => { self.visit_const_val(value); } + Literal::Promoted { index: _ } => {} } } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index b5b27586a7f..c911b20c2ab 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -855,6 +855,9 @@ pub fn maybe_get_item_mir<'tcx>(cdata: Cmd, }; def_id_and_span_translator.visit_mir(&mut mir); + for promoted in &mut mir.promoted { + def_id_and_span_translator.visit_mir(promoted); + } mir }); diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 89c89e6e2e3..4ce77d162e0 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -296,6 +296,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { (Mir { basic_blocks: self.cfg.basic_blocks, scopes: self.scope_datas, + promoted: vec![], var_decls: self.var_decls, arg_decls: arg_decls, temp_decls: self.temp_decls, diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index e6b795531d9..8f22f491455 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -19,6 +19,7 @@ use build; use rustc::dep_graph::DepNode; use rustc::mir::repr::Mir; +use rustc::mir::transform::MirSource; use pretty; use hair::cx::Cx; @@ -55,10 +56,10 @@ struct BuildMir<'a, 'tcx: 'a> { } impl<'a, 'tcx> BuildMir<'a, 'tcx> { - fn build(&mut self, id: ast::NodeId, f: F) + fn build(&mut self, src: MirSource, f: F) where F: for<'b> FnOnce(Cx<'b, 'tcx>) -> (Mir<'tcx>, build::ScopeAuxiliaryVec) { - let param_env = ty::ParameterEnvironment::for_item(self.tcx, id); + let param_env = ty::ParameterEnvironment::for_item(self.tcx, src.item_id()); let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, Some(param_env), @@ -66,9 +67,9 @@ impl<'a, 'tcx> BuildMir<'a, 'tcx> { let (mir, scope_auxiliary) = f(Cx::new(&infcx)); - pretty::dump_mir(self.tcx, "mir_map", &0, id, &mir, Some(&scope_auxiliary)); + pretty::dump_mir(self.tcx, "mir_map", &0, src, &mir, Some(&scope_auxiliary)); - assert!(self.map.map.insert(id, mir).is_none()) + assert!(self.map.map.insert(src.item_id(), mir).is_none()) } fn build_const_integer(&mut self, expr: &'tcx hir::Expr) { @@ -79,7 +80,9 @@ impl<'a, 'tcx> BuildMir<'a, 'tcx> { if let hir::ExprClosure(..) = expr.node { return; } - self.build(expr.id, |cx| build::construct_const(cx, expr.id, expr)); + self.build(MirSource::Const(expr.id), |cx| { + build::construct_const(cx, expr.id, expr) + }); } } @@ -87,9 +90,15 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { // Const and static items. fn visit_item(&mut self, item: &'tcx hir::Item) { match item.node { - hir::ItemConst(_, ref expr) | - hir::ItemStatic(_, _, ref expr) => { - self.build(item.id, |cx| build::construct_const(cx, item.id, expr)); + hir::ItemConst(_, ref expr) => { + self.build(MirSource::Const(item.id), |cx| { + build::construct_const(cx, item.id, expr) + }); + } + hir::ItemStatic(_, m, ref expr) => { + self.build(MirSource::Static(item.id, m), |cx| { + build::construct_const(cx, item.id, expr) + }); } _ => {} } @@ -99,7 +108,9 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { // Trait associated const defaults. fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) { if let hir::ConstTraitItem(_, Some(ref expr)) = item.node { - self.build(item.id, |cx| build::construct_const(cx, item.id, expr)); + self.build(MirSource::Const(item.id), |cx| { + build::construct_const(cx, item.id, expr) + }); } intravisit::walk_trait_item(self, item); } @@ -107,7 +118,9 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { // Impl associated const. fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) { if let hir::ImplItemKind::Const(_, ref expr) = item.node { - self.build(item.id, |cx| build::construct_const(cx, item.id, expr)); + self.build(MirSource::Const(item.id), |cx| { + build::construct_const(cx, item.id, expr) + }); } intravisit::walk_impl_item(self, item); } @@ -166,7 +179,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { (fn_sig.inputs[index], Some(&*arg.pat)) }); - self.build(id, |cx| { + self.build(MirSource::Fn(id), |cx| { let arguments = implicit_argument.into_iter().chain(explicit_arguments); build::construct_fn(cx, id, arguments, fn_sig.output, body) }); diff --git a/src/librustc_mir/pretty.rs b/src/librustc_mir/pretty.rs index 77e8e37ef74..0e082ac262e 100644 --- a/src/librustc_mir/pretty.rs +++ b/src/librustc_mir/pretty.rs @@ -9,7 +9,9 @@ // except according to those terms. use build::{Location, ScopeAuxiliaryVec}; +use rustc::hir; use rustc::mir::repr::*; +use rustc::mir::transform::MirSource; use rustc::ty::{self, TyCtxt}; use rustc_data_structures::fnv::FnvHashMap; use std::fmt::Display; @@ -37,13 +39,14 @@ const INDENT: &'static str = " "; pub fn dump_mir<'a, 'tcx>(tcx: &TyCtxt<'tcx>, pass_name: &str, disambiguator: &Display, - node_id: NodeId, + src: MirSource, mir: &Mir<'tcx>, auxiliary: Option<&ScopeAuxiliaryVec>) { let filters = match tcx.sess.opts.debugging_opts.dump_mir { None => return, Some(ref filters) => filters, }; + let node_id = src.item_id(); let node_path = tcx.item_path_str(tcx.map.local_def_id(node_id)); let is_matched = filters.split("&") @@ -64,7 +67,7 @@ pub fn dump_mir<'a, 'tcx>(tcx: &TyCtxt<'tcx>, try!(writeln!(file, "// pass_name = {}", pass_name)); try!(writeln!(file, "// disambiguator = {}", disambiguator)); try!(writeln!(file, "")); - try!(write_mir_fn(tcx, node_id, mir, &mut file, auxiliary)); + try!(write_mir_fn(tcx, src, mir, &mut file, auxiliary)); Ok(()) }); } @@ -76,8 +79,13 @@ pub fn write_mir_pretty<'a, 'tcx, I>(tcx: &TyCtxt<'tcx>, -> io::Result<()> where I: Iterator)>, 'tcx: 'a { - for (&node_id, mir) in iter { - write_mir_fn(tcx, node_id, mir, w, None)?; + for (&id, mir) in iter { + let src = MirSource::from_node(tcx, id); + write_mir_fn(tcx, src, mir, w, None)?; + + for (i, mir) in mir.promoted.iter().enumerate() { + write_mir_fn(tcx, MirSource::Promoted(id, i), mir, w, None)?; + } } Ok(()) } @@ -88,7 +96,7 @@ enum Annotation { } pub fn write_mir_fn<'tcx>(tcx: &TyCtxt<'tcx>, - node_id: NodeId, + src: MirSource, mir: &Mir<'tcx>, w: &mut Write, auxiliary: Option<&ScopeAuxiliaryVec>) @@ -111,7 +119,7 @@ pub fn write_mir_fn<'tcx>(tcx: &TyCtxt<'tcx>, } } - write_mir_intro(tcx, node_id, mir, w)?; + write_mir_intro(tcx, src, mir, w)?; for block in mir.all_basic_blocks() { write_basic_block(tcx, block, mir, w, &annotations)?; } @@ -214,24 +222,39 @@ fn write_scope_tree(tcx: &TyCtxt, /// Write out a human-readable textual representation of the MIR's `fn` type and the types of its /// local variables (both user-defined bindings and compiler temporaries). -fn write_mir_intro(tcx: &TyCtxt, nid: NodeId, mir: &Mir, w: &mut Write) +fn write_mir_intro(tcx: &TyCtxt, src: MirSource, mir: &Mir, w: &mut Write) -> io::Result<()> { - write!(w, "fn {}(", tcx.node_path_str(nid))?; - - // fn argument types. - for (i, arg) in mir.arg_decls.iter().enumerate() { - if i > 0 { - write!(w, ", ")?; - } - write!(w, "{:?}: {}", Lvalue::Arg(i as u32), arg.ty)?; + 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, "promoted{} in", i)? } - write!(w, ") -> ")?; + write!(w, " {}", tcx.node_path_str(src.item_id()))?; - // fn return type. - match mir.return_ty { - ty::FnOutput::FnConverging(ty) => write!(w, "{}", ty)?, - ty::FnOutput::FnDiverging => write!(w, "!")?, + if let MirSource::Fn(_) = src { + write!(w, "(")?; + + // fn argument types. + for (i, arg) in mir.arg_decls.iter().enumerate() { + if i > 0 { + write!(w, ", ")?; + } + write!(w, "{:?}: {}", Lvalue::Arg(i as u32), arg.ty)?; + } + + write!(w, ") -> ")?; + + // fn return type. + match mir.return_ty { + ty::FnOutput::FnConverging(ty) => write!(w, "{}", ty)?, + ty::FnOutput::FnDiverging => write!(w, "!")?, + } + } else { + assert!(mir.arg_decls.is_empty()); + write!(w, ": {} =", mir.return_ty.unwrap())?; } writeln!(w, " {{")?; diff --git a/src/librustc_mir/transform/break_critical_edges.rs b/src/librustc_mir/transform/break_critical_edges.rs index e1fb5dfd437..ee7c9015baa 100644 --- a/src/librustc_mir/transform/break_critical_edges.rs +++ b/src/librustc_mir/transform/break_critical_edges.rs @@ -10,8 +10,7 @@ use rustc::ty::TyCtxt; use rustc::mir::repr::*; -use rustc::mir::transform::{MirPass, Pass}; -use syntax::ast::NodeId; +use rustc::mir::transform::{MirPass, MirSource, Pass}; use rustc_data_structures::bitvec::BitVector; @@ -43,7 +42,7 @@ pub struct BreakCriticalEdges; */ impl<'tcx> MirPass<'tcx> for BreakCriticalEdges { - fn run_pass(&mut self, _: &TyCtxt<'tcx>, _: NodeId, mir: &mut Mir<'tcx>) { + fn run_pass(&mut self, _: &TyCtxt<'tcx>, _: MirSource, mir: &mut Mir<'tcx>) { break_critical_edges(mir); } } diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index 12bfa3aebc2..678d2c4614d 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -16,8 +16,7 @@ use rustc::ty::subst::Substs; use rustc::ty::{Ty, TyCtxt}; use rustc::mir::repr::*; use rustc::mir::visit::MutVisitor; -use rustc::mir::transform::{MirPass, Pass}; -use syntax::ast::NodeId; +use rustc::mir::transform::{MirPass, MirSource, Pass}; struct EraseRegionsVisitor<'a, 'tcx: 'a> { tcx: &'a TyCtxt<'tcx>, @@ -47,7 +46,7 @@ pub struct EraseRegions; impl Pass for EraseRegions {} impl<'tcx> MirPass<'tcx> for EraseRegions { - fn run_pass(&mut self, tcx: &TyCtxt<'tcx>, _: NodeId, mir: &mut Mir<'tcx>) { + fn run_pass(&mut self, tcx: &TyCtxt<'tcx>, _: MirSource, mir: &mut Mir<'tcx>) { EraseRegionsVisitor::new(tcx).visit_mir(mir); } } diff --git a/src/librustc_mir/transform/no_landing_pads.rs b/src/librustc_mir/transform/no_landing_pads.rs index edfe75b8430..9c9f95e2e63 100644 --- a/src/librustc_mir/transform/no_landing_pads.rs +++ b/src/librustc_mir/transform/no_landing_pads.rs @@ -14,8 +14,7 @@ use rustc::ty::TyCtxt; use rustc::mir::repr::*; use rustc::mir::visit::MutVisitor; -use rustc::mir::transform::{Pass, MirPass}; -use syntax::ast::NodeId; +use rustc::mir::transform::{Pass, MirPass, MirSource}; pub struct NoLandingPads; @@ -42,7 +41,7 @@ impl<'tcx> MutVisitor<'tcx> for NoLandingPads { } impl<'tcx> MirPass<'tcx> for NoLandingPads { - fn run_pass(&mut self, tcx: &TyCtxt<'tcx>, _: NodeId, mir: &mut Mir<'tcx>) { + fn run_pass(&mut self, tcx: &TyCtxt<'tcx>, _: MirSource, mir: &mut Mir<'tcx>) { if tcx.sess.no_landing_pads() { self.visit_mir(mir); } diff --git a/src/librustc_mir/transform/remove_dead_blocks.rs b/src/librustc_mir/transform/remove_dead_blocks.rs index 2099e9a435a..e0d05a17d43 100644 --- a/src/librustc_mir/transform/remove_dead_blocks.rs +++ b/src/librustc_mir/transform/remove_dead_blocks.rs @@ -35,13 +35,12 @@ use rustc_data_structures::bitvec::BitVector; use rustc::ty::TyCtxt; use rustc::mir::repr::*; -use rustc::mir::transform::{Pass, MirPass}; -use syntax::ast::NodeId; +use rustc::mir::transform::{Pass, MirPass, MirSource}; pub struct RemoveDeadBlocks; impl<'tcx> MirPass<'tcx> for RemoveDeadBlocks { - fn run_pass(&mut self, _: &TyCtxt<'tcx>, _: NodeId, mir: &mut Mir<'tcx>) { + fn run_pass(&mut self, _: &TyCtxt<'tcx>, _: MirSource, mir: &mut Mir<'tcx>) { let mut seen = BitVector::new(mir.basic_blocks.len()); // This block is always required. seen.insert(START_BLOCK.index()); diff --git a/src/librustc_mir/transform/simplify_cfg.rs b/src/librustc_mir/transform/simplify_cfg.rs index 00b8f5c0930..a137a812867 100644 --- a/src/librustc_mir/transform/simplify_cfg.rs +++ b/src/librustc_mir/transform/simplify_cfg.rs @@ -11,9 +11,8 @@ use rustc::middle::const_val::ConstVal; use rustc::ty::TyCtxt; use rustc::mir::repr::*; -use rustc::mir::transform::{MirPass, Pass}; +use rustc::mir::transform::{MirPass, MirSource, Pass}; use pretty; -use syntax::ast::NodeId; use super::remove_dead_blocks::RemoveDeadBlocks; @@ -112,15 +111,15 @@ impl SimplifyCfg { } impl<'tcx> MirPass<'tcx> for SimplifyCfg { - fn run_pass(&mut self, tcx: &TyCtxt<'tcx>, id: NodeId, mir: &mut Mir<'tcx>) { + fn run_pass(&mut self, tcx: &TyCtxt<'tcx>, src: MirSource, mir: &mut Mir<'tcx>) { let mut counter = 0; let mut changed = true; while changed { - pretty::dump_mir(tcx, "simplify_cfg", &counter, id, mir, None); + pretty::dump_mir(tcx, "simplify_cfg", &counter, src, mir, None); counter += 1; changed = self.simplify_branches(mir); changed |= self.remove_goto_chains(mir); - RemoveDeadBlocks.run_pass(tcx, id, mir); + RemoveDeadBlocks.run_pass(tcx, src, mir); } // FIXME: Should probably be moved into some kind of pass manager mir.basic_blocks.shrink_to_fit(); diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 11ac1fa8f82..18ebadf42d6 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -12,16 +12,16 @@ #![allow(unreachable_code)] use rustc::dep_graph::DepNode; +use rustc::hir::def_id::DefId; use rustc::infer::{self, InferCtxt, InferOk}; use rustc::traits::{self, ProjectionMode}; use rustc::ty::fold::TypeFoldable; use rustc::ty::{self, Ty, TyCtxt}; use rustc::mir::repr::*; use rustc::mir::tcx::LvalueTy; -use rustc::mir::transform::{MirPass, Pass}; +use rustc::mir::transform::{MirPass, MirSource, Pass}; use rustc::mir::visit::{self, Visitor}; use std::fmt; -use syntax::ast::NodeId; use syntax::codemap::{Span, DUMMY_SP}; macro_rules! span_mirbug { @@ -578,15 +578,13 @@ impl TypeckMir { } impl<'tcx> MirPass<'tcx> for TypeckMir { - fn run_pass(&mut self, tcx: &TyCtxt<'tcx>, id: NodeId, mir: &mut Mir<'tcx>) { + fn run_pass(&mut self, tcx: &TyCtxt<'tcx>, src: MirSource, mir: &mut Mir<'tcx>) { if tcx.sess.err_count() > 0 { // compiling a broken program can obviously result in a // broken MIR, so try not to report duplicate errors. return; } - let def_id = tcx.map.local_def_id(id); - let _task = tcx.dep_graph.in_task(DepNode::MirTypeck(def_id)); - let param_env = ty::ParameterEnvironment::for_item(tcx, id); + let param_env = ty::ParameterEnvironment::for_item(tcx, src.item_id()); let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env), @@ -605,4 +603,8 @@ impl<'tcx> MirPass<'tcx> for TypeckMir { } } -impl Pass for TypeckMir {} +impl Pass for TypeckMir { + fn dep_node(&self, def_id: DefId) -> DepNode { + DepNode::MirTypeck(def_id) + } +} diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index e8181579911..a0311ec6066 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -414,6 +414,9 @@ fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>, }; visitor.visit_mir(&mir); + for promoted in &mir.promoted { + visitor.visit_mir(promoted); + } } } diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 22e4ab1dd89..9c1dfb0fc8d 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -35,7 +35,7 @@ use syntax::codemap::{Span, DUMMY_SP}; use std::ptr; use super::operand::{OperandRef, OperandValue}; -use super::{CachedMir, MirContext}; +use super::MirContext; /// A sized constant rvalue. /// The LLVM type might not be the same for a single Rust type, @@ -179,7 +179,7 @@ impl<'tcx> ConstLvalue<'tcx> { /// FIXME(eddyb) use miri and lower its allocations to LLVM. struct MirConstContext<'a, 'tcx: 'a> { ccx: &'a CrateContext<'a, 'tcx>, - mir: CachedMir<'a, 'tcx>, + mir: &'a mir::Mir<'tcx>, /// Type parameters for const fn and associated constants. substs: &'tcx Substs<'tcx>, @@ -200,10 +200,25 @@ struct MirConstContext<'a, 'tcx: 'a> { impl<'a, 'tcx> MirConstContext<'a, 'tcx> { fn new(ccx: &'a CrateContext<'a, 'tcx>, - mut instance: Instance<'tcx>, + mir: &'a mir::Mir<'tcx>, + substs: &'tcx Substs<'tcx>, args: Vec>) -> MirConstContext<'a, 'tcx> { + MirConstContext { + ccx: ccx, + mir: mir, + substs: substs, + args: args, + vars: vec![None; mir.var_decls.len()], + temps: vec![None; mir.temp_decls.len()], + return_value: None + } + } + fn trans_def(ccx: &'a CrateContext<'a, 'tcx>, + mut instance: Instance<'tcx>, + args: Vec>) + -> Result, ConstEvalFailure> { // Try to resolve associated constants. if instance.substs.self_ty().is_some() { // Only trait items can have a Self parameter. @@ -226,15 +241,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { let mir = ccx.get_mir(instance.def).unwrap_or_else(|| { bug!("missing constant MIR for {}", instance) }); - MirConstContext { - ccx: ccx, - substs: instance.substs, - args: args, - vars: vec![None; mir.var_decls.len()], - temps: vec![None; mir.temp_decls.len()], - return_value: None, - mir: mir - } + MirConstContext::new(ccx, &mir, instance.substs, args).trans() } fn monomorphize(&self, value: &T) -> T @@ -247,10 +254,9 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { fn trans(&mut self) -> Result, ConstEvalFailure> { let tcx = self.ccx.tcx(); - let mir = self.mir.clone(); let mut bb = mir::START_BLOCK; loop { - let data = mir.basic_block_data(bb); + let data = self.mir.basic_block_data(bb); for statement in &data.statements { match statement.kind { mir::StatementKind::Assign(ref dest, ref rvalue) => { @@ -284,7 +290,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { } mir::TerminatorKind::Call { ref func, ref args, ref destination, .. } => { - let fn_ty = mir.operand_ty(tcx, func); + let fn_ty = self.mir.operand_ty(tcx, func); let fn_ty = self.monomorphize(&fn_ty); let instance = match fn_ty.sty { ty::TyFnDef(def_id, substs, _) => { @@ -304,7 +310,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { let args = args.iter().map(|arg| { self.const_operand(arg, span) }).collect::, _>>()?; - let value = MirConstContext::new(self.ccx, instance, args).trans()?; + let value = MirConstContext::trans_def(self.ccx, instance, args)?; if let Some((ref dest, target)) = *destination { self.store(dest, value, span); target @@ -432,7 +438,11 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { let substs = self.ccx.tcx().mk_substs(self.monomorphize(substs)); let instance = Instance::new(def_id, substs); - MirConstContext::new(self.ccx, instance, vec![]).trans() + MirConstContext::trans_def(self.ccx, instance, vec![]) + } + mir::Literal::Promoted { index } => { + let mir = &self.mir.promoted[index]; + MirConstContext::new(self.ccx, mir, self.substs, vec![]).trans() } mir::Literal::Value { value } => { Ok(Const::from_constval(self.ccx, value, ty)) @@ -792,7 +802,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { -> OperandRef<'tcx> { let ty = bcx.monomorphize(&constant.ty); - let val = match constant.literal.clone() { + let result = match constant.literal.clone() { mir::Literal::Item { def_id, substs } => { // Shortcut for zero-sized types, including function item // types, which would not work with MirConstContext. @@ -806,22 +816,28 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { let substs = bcx.tcx().mk_substs(bcx.monomorphize(substs)); let instance = Instance::new(def_id, substs); - match MirConstContext::new(bcx.ccx(), instance, vec![]).trans() { - Ok(v) => v, - Err(ConstEvalFailure::Compiletime(_)) => { - // We've errored, so we don't have to produce working code. - let llty = type_of::type_of(bcx.ccx(), ty); - Const::new(C_undef(llty), ty) - } - Err(ConstEvalFailure::Runtime(err)) => { - span_bug!(constant.span, - "MIR constant {:?} results in runtime panic: {}", - constant, err.description()) - } - } + MirConstContext::trans_def(bcx.ccx(), instance, vec![]) + } + mir::Literal::Promoted { index } => { + let mir = &self.mir.promoted[index]; + MirConstContext::new(bcx.ccx(), mir, bcx.fcx().param_substs, vec![]).trans() } mir::Literal::Value { value } => { - Const::from_constval(bcx.ccx(), value, ty) + Ok(Const::from_constval(bcx.ccx(), value, ty)) + } + }; + + let val = match result { + Ok(v) => v, + Err(ConstEvalFailure::Compiletime(_)) => { + // We've errored, so we don't have to produce working code. + let llty = type_of::type_of(bcx.ccx(), ty); + Const::new(C_undef(llty), ty) + } + Err(ConstEvalFailure::Runtime(err)) => { + span_bug!(constant.span, + "MIR constant {:?} results in runtime panic: {}", + constant, err.description()) } }; @@ -839,5 +855,5 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { pub fn trans_static_initializer(ccx: &CrateContext, def_id: DefId) -> Result { let instance = Instance::mono(ccx.tcx(), def_id); - MirConstContext::new(ccx, instance, vec![]).trans().map(|c| c.llval) + MirConstContext::trans_def(ccx, instance, vec![]).map(|c| c.llval) } diff --git a/src/test/run-pass-fulldeps/auxiliary/dummy_mir_pass.rs b/src/test/run-pass-fulldeps/auxiliary/dummy_mir_pass.rs index b5234af937b..600df1c778b 100644 --- a/src/test/run-pass-fulldeps/auxiliary/dummy_mir_pass.rs +++ b/src/test/run-pass-fulldeps/auxiliary/dummy_mir_pass.rs @@ -18,7 +18,7 @@ extern crate rustc_plugin; extern crate rustc_const_math; extern crate syntax; -use rustc::mir::transform::{self, MirPass}; +use rustc::mir::transform::{self, MirPass, MirSource}; use rustc::mir::repr::{Mir, Literal}; use rustc::mir::visit::MutVisitor; use rustc::ty; @@ -26,13 +26,11 @@ use rustc::middle::const_val::ConstVal; use rustc_const_math::ConstInt; use rustc_plugin::Registry; -use syntax::ast::NodeId; - struct Pass; impl transform::Pass for Pass {} impl<'tcx> MirPass<'tcx> for Pass { - fn run_pass(&mut self, _: &ty::TyCtxt<'tcx>, _: NodeId, mir: &mut Mir<'tcx>) { + fn run_pass(&mut self, _: &ty::TyCtxt<'tcx>, _: MirSource, mir: &mut Mir<'tcx>) { Visitor.visit_mir(mir) } }