mir: prepare for rvalue promotion support.
This commit is contained in:
parent
e1eca0a110
commit
14efbf1481
@ -64,6 +64,7 @@ pub enum DepNode<D: Clone + Debug> {
|
||||
IntrinsicCheck(D),
|
||||
MatchCheck(D),
|
||||
MirMapConstruction(D),
|
||||
MirPass(D),
|
||||
MirTypeck(D),
|
||||
BorrowCheck(D),
|
||||
RvalueCheck(D),
|
||||
@ -186,6 +187,7 @@ impl<D: Clone + Debug> DepNode<D> {
|
||||
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),
|
||||
|
@ -36,6 +36,11 @@ pub struct Mir<'tcx> {
|
||||
/// used (eventually) for debuginfo. Indexed by a `ScopeId`.
|
||||
pub scopes: Vec<ScopeData>,
|
||||
|
||||
/// 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<Mir<'tcx>>,
|
||||
|
||||
/// 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<DefId> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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: _ } => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
});
|
||||
|
@ -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,
|
||||
|
@ -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<F>(&mut self, id: ast::NodeId, f: F)
|
||||
fn build<F>(&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)
|
||||
});
|
||||
|
@ -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<Item=(&'a NodeId, &'a Mir<'tcx>)>, '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, " {{")?;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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();
|
||||
|
@ -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<DefId> {
|
||||
DepNode::MirTypeck(def_id)
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<Const<'tcx>>)
|
||||
-> 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<Const<'tcx>>)
|
||||
-> Result<Const<'tcx>, 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<T>(&self, value: &T) -> T
|
||||
@ -247,10 +254,9 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||
|
||||
fn trans(&mut self) -> Result<Const<'tcx>, 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::<Result<Vec<_>, _>>()?;
|
||||
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<ValueRef, ConstEvalFailure> {
|
||||
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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user