Revised graphviz rendering API to avoid requiring borrowed state.
Made `do_dataflow` and related API `pub(crate)`.
This commit is contained in:
parent
691f022767
commit
93c4ffe72f
@ -28,7 +28,7 @@ use rustc_data_structures::indexed_vec::Idx;
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
|
||||
use dataflow::do_dataflow;
|
||||
use dataflow::{do_dataflow, DebugFormatted};
|
||||
use dataflow::MoveDataParamEnv;
|
||||
use dataflow::DataflowResultsConsumer;
|
||||
use dataflow::{FlowAtLocation, FlowsAtLocation};
|
||||
@ -157,7 +157,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
|
||||
&attributes,
|
||||
&dead_unwinds,
|
||||
MaybeInitializedLvals::new(tcx, mir, &mdpe),
|
||||
|bd, i| &bd.move_data().move_paths[i],
|
||||
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]),
|
||||
));
|
||||
let flow_uninits = FlowAtLocation::new(do_dataflow(
|
||||
tcx,
|
||||
@ -166,7 +166,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
|
||||
&attributes,
|
||||
&dead_unwinds,
|
||||
MaybeUninitializedLvals::new(tcx, mir, &mdpe),
|
||||
|bd, i| &bd.move_data().move_paths[i],
|
||||
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]),
|
||||
));
|
||||
let flow_move_outs = FlowAtLocation::new(do_dataflow(
|
||||
tcx,
|
||||
@ -175,7 +175,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
|
||||
&attributes,
|
||||
&dead_unwinds,
|
||||
MovingOutStatements::new(tcx, mir, &mdpe),
|
||||
|bd, i| &bd.move_data().moves[i],
|
||||
|bd, i| DebugFormatted::new(&bd.move_data().moves[i]),
|
||||
));
|
||||
let flow_ever_inits = FlowAtLocation::new(do_dataflow(
|
||||
tcx,
|
||||
@ -184,7 +184,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
|
||||
&attributes,
|
||||
&dead_unwinds,
|
||||
EverInitializedLvals::new(tcx, mir, &mdpe),
|
||||
|bd, i| &bd.move_data().inits[i],
|
||||
|bd, i| DebugFormatted::new(&bd.move_data().inits[i]),
|
||||
));
|
||||
|
||||
// If we are in non-lexical mode, compute the non-lexical lifetimes.
|
||||
@ -212,7 +212,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
|
||||
&attributes,
|
||||
&dead_unwinds,
|
||||
Borrows::new(tcx, mir, opt_regioncx, def_id, body_id),
|
||||
|bd, i| bd.location(i),
|
||||
|bd, i| DebugFormatted::new(bd.location(i)),
|
||||
));
|
||||
|
||||
let mut state = Flows::new(
|
||||
|
@ -18,7 +18,6 @@ use rustc_data_structures::indexed_vec::Idx;
|
||||
use dot;
|
||||
use dot::IntoCow;
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
@ -29,6 +28,7 @@ use util;
|
||||
|
||||
use super::{BitDenotation, DataflowState};
|
||||
use super::DataflowBuilder;
|
||||
use super::DebugFormatted;
|
||||
|
||||
pub trait MirWithFlowState<'tcx> {
|
||||
type BD: BitDenotation;
|
||||
@ -60,9 +60,9 @@ pub(crate) fn print_borrowck_graph_to<'a, 'tcx, BD, P>(
|
||||
render_idx: P)
|
||||
-> io::Result<()>
|
||||
where BD: BitDenotation,
|
||||
P: Fn(&BD, BD::Idx) -> &Debug
|
||||
P: Fn(&BD, BD::Idx) -> DebugFormatted
|
||||
{
|
||||
let g = Graph { mbcx: mbcx, phantom: PhantomData, render_idx: render_idx };
|
||||
let g = Graph { mbcx, phantom: PhantomData, render_idx };
|
||||
let mut v = Vec::new();
|
||||
dot::render(&g, &mut v)?;
|
||||
debug!("print_borrowck_graph_to path: {} node_id: {}",
|
||||
@ -82,7 +82,7 @@ fn outgoing(mir: &Mir, bb: BasicBlock) -> Vec<Edge> {
|
||||
|
||||
impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P>
|
||||
where MWF: MirWithFlowState<'tcx>,
|
||||
P: for <'b> Fn(&'b MWF::BD, <MWF::BD as BitDenotation>::Idx) -> &'b Debug,
|
||||
P: Fn(&MWF::BD, <MWF::BD as BitDenotation>::Idx) -> DebugFormatted,
|
||||
{
|
||||
type Node = Node;
|
||||
type Edge = Edge;
|
||||
@ -142,7 +142,7 @@ impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P>
|
||||
const ALIGN_RIGHT: &'static str = r#"align="right""#;
|
||||
const FACE_MONOSPACE: &'static str = r#"FACE="Courier""#;
|
||||
fn chunked_present_left<W:io::Write>(w: &mut W,
|
||||
interpreted: &[&Debug],
|
||||
interpreted: &[DebugFormatted],
|
||||
chunk_size: usize)
|
||||
-> io::Result<()>
|
||||
{
|
||||
|
@ -19,7 +19,7 @@ use rustc::mir::{self, Mir, BasicBlock, BasicBlockData, Location, Statement, Ter
|
||||
use rustc::session::Session;
|
||||
|
||||
use std::borrow::Borrow;
|
||||
use std::fmt::{self, Debug};
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::path::PathBuf;
|
||||
@ -51,10 +51,29 @@ pub(crate) struct DataflowBuilder<'a, 'tcx: 'a, BD> where BD: BitDenotation
|
||||
print_postflow_to: Option<String>,
|
||||
}
|
||||
|
||||
pub trait Dataflow<BD: BitDenotation> {
|
||||
/// `DebugFormatted` encapsulates the "{:?}" rendering of some
|
||||
/// arbitrary value. This way: you pay cost of allocating an extra
|
||||
/// string (as well as that of rendering up-front); in exchange, you
|
||||
/// don't have to hand over ownership of your value or deal with
|
||||
/// borrowing it.
|
||||
pub(crate) struct DebugFormatted(String);
|
||||
|
||||
impl DebugFormatted {
|
||||
pub fn new(input: &fmt::Debug) -> DebugFormatted {
|
||||
DebugFormatted(format!("{:?}", input))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for DebugFormatted {
|
||||
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(w, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait Dataflow<BD: BitDenotation> {
|
||||
/// Sets up and runs the dataflow problem, using `p` to render results if
|
||||
/// implementation so chooses.
|
||||
fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug {
|
||||
fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> DebugFormatted {
|
||||
let _ = p; // default implementation does not instrument process.
|
||||
self.build_sets();
|
||||
self.propagate();
|
||||
@ -69,7 +88,7 @@ pub trait Dataflow<BD: BitDenotation> {
|
||||
|
||||
impl<'a, 'tcx: 'a, BD> Dataflow<BD> for DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation
|
||||
{
|
||||
fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug {
|
||||
fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> DebugFormatted {
|
||||
self.flow_state.build_sets();
|
||||
self.pre_dataflow_instrumentation(|c,i| p(c,i)).unwrap();
|
||||
self.flow_state.propagate();
|
||||
@ -109,7 +128,7 @@ pub(crate) fn do_dataflow<'a, 'gcx, 'tcx, BD, P>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
p: P)
|
||||
-> DataflowResults<BD>
|
||||
where BD: BitDenotation,
|
||||
P: Fn(&BD, BD::Idx) -> &fmt::Debug
|
||||
P: Fn(&BD, BD::Idx) -> DebugFormatted
|
||||
{
|
||||
let name_found = |sess: &Session, attrs: &[ast::Attribute], name| -> Option<String> {
|
||||
if let Some(item) = has_rustc_mir_with(attrs, name) {
|
||||
@ -231,7 +250,7 @@ fn dataflow_path(context: &str, prepost: &str, path: &str) -> PathBuf {
|
||||
impl<'a, 'tcx: 'a, BD> DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation
|
||||
{
|
||||
fn pre_dataflow_instrumentation<P>(&self, p: P) -> io::Result<()>
|
||||
where P: Fn(&BD, BD::Idx) -> &Debug
|
||||
where P: Fn(&BD, BD::Idx) -> DebugFormatted
|
||||
{
|
||||
if let Some(ref path_str) = self.print_preflow_to {
|
||||
let path = dataflow_path(BD::name(), "preflow", path_str);
|
||||
@ -242,7 +261,7 @@ impl<'a, 'tcx: 'a, BD> DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation
|
||||
}
|
||||
|
||||
fn post_dataflow_instrumentation<P>(&self, p: P) -> io::Result<()>
|
||||
where P: Fn(&BD, BD::Idx) -> &Debug
|
||||
where P: Fn(&BD, BD::Idx) -> DebugFormatted
|
||||
{
|
||||
if let Some(ref path_str) = self.print_postflow_to {
|
||||
let path = dataflow_path(BD::name(), "postflow", path_str);
|
||||
@ -403,12 +422,12 @@ impl<O: BitDenotation> DataflowState<O> {
|
||||
words.each_bit(bits_per_block, f)
|
||||
}
|
||||
|
||||
pub fn interpret_set<'c, P>(&self,
|
||||
o: &'c O,
|
||||
words: &IdxSet<O::Idx>,
|
||||
render_idx: &P)
|
||||
-> Vec<&'c Debug>
|
||||
where P: Fn(&O, O::Idx) -> &Debug
|
||||
pub(crate) fn interpret_set<'c, P>(&self,
|
||||
o: &'c O,
|
||||
words: &IdxSet<O::Idx>,
|
||||
render_idx: &P)
|
||||
-> Vec<DebugFormatted>
|
||||
where P: Fn(&O, O::Idx) -> DebugFormatted
|
||||
{
|
||||
let mut v = Vec::new();
|
||||
self.each_bit(words, |i| {
|
||||
|
@ -14,7 +14,7 @@ use dataflow::{DataflowResults};
|
||||
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 dataflow::{self, do_dataflow, DebugFormatted};
|
||||
use rustc::hir;
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::mir::*;
|
||||
@ -59,13 +59,13 @@ impl MirPass for ElaborateDrops {
|
||||
};
|
||||
let dead_unwinds = find_dead_unwinds(tcx, mir, id, &env);
|
||||
let flow_inits =
|
||||
dataflow::do_dataflow(tcx, mir, id, &[], &dead_unwinds,
|
||||
MaybeInitializedLvals::new(tcx, mir, &env),
|
||||
|bd, p| &bd.move_data().move_paths[p]);
|
||||
do_dataflow(tcx, mir, id, &[], &dead_unwinds,
|
||||
MaybeInitializedLvals::new(tcx, mir, &env),
|
||||
|bd, p| DebugFormatted::new(&bd.move_data().move_paths[p]));
|
||||
let flow_uninits =
|
||||
dataflow::do_dataflow(tcx, mir, id, &[], &dead_unwinds,
|
||||
MaybeUninitializedLvals::new(tcx, mir, &env),
|
||||
|bd, p| &bd.move_data().move_paths[p]);
|
||||
do_dataflow(tcx, mir, id, &[], &dead_unwinds,
|
||||
MaybeUninitializedLvals::new(tcx, mir, &env),
|
||||
|bd, p| DebugFormatted::new(&bd.move_data().move_paths[p]));
|
||||
|
||||
ElaborateDropsCtxt {
|
||||
tcx,
|
||||
@ -96,9 +96,9 @@ fn find_dead_unwinds<'a, 'tcx>(
|
||||
// reach cleanup blocks, which can't have unwind edges themselves.
|
||||
let mut dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
|
||||
let flow_inits =
|
||||
dataflow::do_dataflow(tcx, mir, id, &[], &dead_unwinds,
|
||||
MaybeInitializedLvals::new(tcx, mir, &env),
|
||||
|bd, p| &bd.move_data().move_paths[p]);
|
||||
do_dataflow(tcx, mir, id, &[], &dead_unwinds,
|
||||
MaybeInitializedLvals::new(tcx, mir, &env),
|
||||
|bd, p| DebugFormatted::new(&bd.move_data().move_paths[p]));
|
||||
for (bb, bb_data) in mir.basic_blocks().iter_enumerated() {
|
||||
let location = match bb_data.terminator().kind {
|
||||
TerminatorKind::Drop { ref location, unwind: Some(_), .. } |
|
||||
|
@ -78,7 +78,7 @@ 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};
|
||||
use dataflow::{do_dataflow, DebugFormatted, MaybeStorageLive, state_for_location};
|
||||
|
||||
pub struct StateTransform;
|
||||
|
||||
@ -341,8 +341,8 @@ fn locals_live_across_suspend_points<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
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,
|
||||
|bd, p| &bd.mir().local_decls[p]);
|
||||
do_dataflow(tcx, mir, node_id, &[], &dead_unwinds, analysis,
|
||||
|bd, p| DebugFormatted::new(&bd.mir().local_decls[p]));
|
||||
|
||||
let mut ignored = StorageIgnored(IdxSetBuf::new_filled(mir.local_decls.len()));
|
||||
ignored.visit_mir(mir);
|
||||
|
@ -18,7 +18,7 @@ use rustc_data_structures::indexed_set::IdxSetBuf;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use transform::{MirPass, MirSource};
|
||||
|
||||
use dataflow::do_dataflow;
|
||||
use dataflow::{do_dataflow, DebugFormatted};
|
||||
use dataflow::MoveDataParamEnv;
|
||||
use dataflow::BitDenotation;
|
||||
use dataflow::DataflowResults;
|
||||
@ -51,15 +51,15 @@ impl MirPass for SanityCheck {
|
||||
let flow_inits =
|
||||
do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
|
||||
MaybeInitializedLvals::new(tcx, mir, &mdpe),
|
||||
|bd, i| &bd.move_data().move_paths[i]);
|
||||
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]));
|
||||
let flow_uninits =
|
||||
do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
|
||||
MaybeUninitializedLvals::new(tcx, mir, &mdpe),
|
||||
|bd, i| &bd.move_data().move_paths[i]);
|
||||
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]));
|
||||
let flow_def_inits =
|
||||
do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
|
||||
DefinitelyInitializedLvals::new(tcx, mir, &mdpe),
|
||||
|bd, i| &bd.move_data().move_paths[i]);
|
||||
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]));
|
||||
|
||||
if has_rustc_mir_with(&attributes, "rustc_peek_maybe_init").is_some() {
|
||||
sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_inits);
|
||||
|
Loading…
Reference in New Issue
Block a user