Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use a valid name for graphviz graphs #59251

Merged
merged 1 commit into from
Mar 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/librustc_driver/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -633,10 +633,20 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec<borrowck_dot::Variant>,
let body = tcx.hir().body(body_id);
let cfg = cfg::CFG::new(tcx, &body);
let labelled_edges = mode != PpFlowGraphMode::UnlabelledEdges;
let hir_id = code.id();
// We have to disassemble the hir_id because name must be ASCII
// alphanumeric. This does not appear in the rendered graph, so it does not
// have to be user friendly.
let name = format!(
"hir_id_{}_{}_{}",
hir_id.owner.address_space().index(),
hir_id.owner.as_array_index(),
hir_id.local_id.index(),
);
let lcfg = LabelledCFG {
tcx,
cfg: &cfg,
name: format!("node_{}", code.id()),
name,
labelled_edges,
};

Expand Down
8 changes: 4 additions & 4 deletions src/librustc_mir/borrow_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
let mut flow_inits = FlowAtLocation::new(do_dataflow(
tcx,
mir,
id,
def_id,
&attributes,
&dead_unwinds,
MaybeInitializedPlaces::new(tcx, mir, &mdpe),
Expand Down Expand Up @@ -191,7 +191,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
let flow_borrows = FlowAtLocation::new(do_dataflow(
tcx,
mir,
id,
def_id,
&attributes,
&dead_unwinds,
Borrows::new(tcx, mir, regioncx.clone(), &borrow_set),
Expand All @@ -200,7 +200,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
let flow_uninits = FlowAtLocation::new(do_dataflow(
tcx,
mir,
id,
def_id,
&attributes,
&dead_unwinds,
MaybeUninitializedPlaces::new(tcx, mir, &mdpe),
Expand All @@ -209,7 +209,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
let flow_ever_inits = FlowAtLocation::new(do_dataflow(
tcx,
mir,
id,
def_id,
&attributes,
&dead_unwinds,
EverInitializedPlaces::new(tcx, mir, &mdpe),
Expand Down
17 changes: 9 additions & 8 deletions src/librustc_mir/dataflow/graphviz.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
//! Hook into libgraphviz for rendering dataflow graphs for MIR.

use rustc::hir::HirId;
use rustc::hir::def_id::DefId;
use rustc::mir::{BasicBlock, Mir};

use std::fs;
use std::io;
use std::marker::PhantomData;
use std::path::Path;

use crate::util::graphviz_safe_def_name;

use super::{BitDenotation, DataflowState};
use super::DataflowBuilder;
use super::DebugFormatted;

pub trait MirWithFlowState<'tcx> {
type BD: BitDenotation<'tcx>;
fn hir_id(&self) -> HirId;
fn def_id(&self) -> DefId;
fn mir(&self) -> &Mir<'tcx>;
fn flow_state(&self) -> &DataflowState<'tcx, Self::BD>;
}
Expand All @@ -23,7 +25,7 @@ impl<'a, 'tcx, BD> MirWithFlowState<'tcx> for DataflowBuilder<'a, 'tcx, BD>
where BD: BitDenotation<'tcx>
{
type BD = BD;
fn hir_id(&self) -> HirId { self.hir_id }
fn def_id(&self) -> DefId { self.def_id }
fn mir(&self) -> &Mir<'tcx> { self.flow_state.mir() }
fn flow_state(&self) -> &DataflowState<'tcx, Self::BD> { &self.flow_state.flow_state }
}
Expand All @@ -47,8 +49,8 @@ pub(crate) fn print_borrowck_graph_to<'a, 'tcx, BD, P>(
let g = Graph { mbcx, phantom: PhantomData, render_idx };
let mut v = Vec::new();
dot::render(&g, &mut v)?;
debug!("print_borrowck_graph_to path: {} hir_id: {}",
path.display(), mbcx.hir_id);
debug!("print_borrowck_graph_to path: {} def_id: {:?}",
path.display(), mbcx.def_id);
fs::write(path, v)
}

Expand All @@ -69,9 +71,8 @@ impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P>
type Node = Node;
type Edge = Edge;
fn graph_id(&self) -> dot::Id<'_> {
dot::Id::new(format!("graph_for_node_{}",
self.mbcx.hir_id()))
.unwrap()
let name = graphviz_safe_def_name(self.mbcx.def_id());
dot::Id::new(format!("graph_for_def_id_{}", name)).unwrap()
}

fn node_id(&self, n: &Node) -> dot::Id<'_> {
Expand Down
12 changes: 6 additions & 6 deletions src/librustc_mir/dataflow/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use rustc_data_structures::bit_set::{BitSet, BitSetOperator, HybridBitSet};
use rustc_data_structures::indexed_vec::Idx;
use rustc_data_structures::work_queue::WorkQueue;

use rustc::hir::HirId;
use rustc::hir::def_id::DefId;
use rustc::ty::{self, TyCtxt};
use rustc::mir::{self, Mir, BasicBlock, BasicBlockData, Location, Statement, Terminator};
use rustc::mir::traversal;
Expand Down Expand Up @@ -39,7 +39,7 @@ pub(crate) struct DataflowBuilder<'a, 'tcx: 'a, BD>
where
BD: BitDenotation<'tcx>
{
hir_id: HirId,
def_id: DefId,
flow_state: DataflowAnalysis<'a, 'tcx, BD>,
print_preflow_to: Option<String>,
print_postflow_to: Option<String>,
Expand Down Expand Up @@ -117,7 +117,7 @@ pub struct MoveDataParamEnv<'gcx, 'tcx> {

pub(crate) fn do_dataflow<'a, 'gcx, 'tcx, BD, P>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
mir: &'a Mir<'tcx>,
hir_id: HirId,
def_id: DefId,
attributes: &[ast::Attribute],
dead_unwinds: &BitSet<BasicBlock>,
bd: BD,
Expand All @@ -127,14 +127,14 @@ pub(crate) fn do_dataflow<'a, 'gcx, 'tcx, BD, P>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
P: Fn(&BD, BD::Idx) -> DebugFormatted
{
let flow_state = DataflowAnalysis::new(mir, dead_unwinds, bd);
flow_state.run(tcx, hir_id, attributes, p)
flow_state.run(tcx, def_id, attributes, p)
}

impl<'a, 'gcx: 'tcx, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitDenotation<'tcx>
{
pub(crate) fn run<P>(self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
hir_id: HirId,
def_id: DefId,
attributes: &[ast::Attribute],
p: P) -> DataflowResults<'tcx, BD>
where P: Fn(&BD, BD::Idx) -> DebugFormatted
Expand All @@ -159,7 +159,7 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitD
name_found(tcx.sess, attributes, "borrowck_graphviz_postflow");

let mut mbcx = DataflowBuilder {
hir_id,
def_id,
print_preflow_to, print_postflow_to, flow_state: self,
};

Expand Down
12 changes: 6 additions & 6 deletions src/librustc_mir/transform/elaborate_drops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl MirPass for ElaborateDrops {
{
debug!("elaborate_drops({:?} @ {:?})", src, mir.span);

let id = tcx.hir().as_local_hir_id(src.def_id()).unwrap();
let def_id = src.def_id();
let param_env = tcx.param_env(src.def_id()).with_reveal_all();
let move_data = match MoveData::gather_moves(mir, tcx) {
Ok(move_data) => move_data,
Expand All @@ -50,13 +50,13 @@ impl MirPass for ElaborateDrops {
move_data,
param_env,
};
let dead_unwinds = find_dead_unwinds(tcx, mir, id, &env);
let dead_unwinds = find_dead_unwinds(tcx, mir, def_id, &env);
let flow_inits =
do_dataflow(tcx, mir, id, &[], &dead_unwinds,
do_dataflow(tcx, mir, def_id, &[], &dead_unwinds,
MaybeInitializedPlaces::new(tcx, mir, &env),
|bd, p| DebugFormatted::new(&bd.move_data().move_paths[p]));
let flow_uninits =
do_dataflow(tcx, mir, id, &[], &dead_unwinds,
do_dataflow(tcx, mir, def_id, &[], &dead_unwinds,
MaybeUninitializedPlaces::new(tcx, mir, &env),
|bd, p| DebugFormatted::new(&bd.move_data().move_paths[p]));

Expand All @@ -80,7 +80,7 @@ impl MirPass for ElaborateDrops {
fn find_dead_unwinds<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
mir: &Mir<'tcx>,
id: hir::HirId,
def_id: hir::def_id::DefId,
env: &MoveDataParamEnv<'tcx, 'tcx>)
-> BitSet<BasicBlock>
{
Expand All @@ -89,7 +89,7 @@ fn find_dead_unwinds<'a, 'tcx>(
// reach cleanup blocks, which can't have unwind edges themselves.
let mut dead_unwinds = BitSet::new_empty(mir.basic_blocks().len());
let flow_inits =
do_dataflow(tcx, mir, id, &[], &dead_unwinds,
do_dataflow(tcx, mir, def_id, &[], &dead_unwinds,
MaybeInitializedPlaces::new(tcx, mir, &env),
|bd, p| DebugFormatted::new(&bd.move_data().move_paths[p]));
for (bb, bb_data) in mir.basic_blocks().iter_enumerated() {
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_mir/transform/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,13 +383,13 @@ fn locals_live_across_suspend_points(
FxHashMap<BasicBlock, liveness::LiveVarSet>,
) {
let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len());
let hir_id = tcx.hir().as_local_hir_id(source.def_id()).unwrap();
let def_id = source.def_id();

// Calculate when MIR locals have live storage. This gives us an upper bound of their
// lifetimes.
let storage_live_analysis = MaybeStorageLive::new(mir);
let storage_live =
do_dataflow(tcx, mir, hir_id, &[], &dead_unwinds, storage_live_analysis,
do_dataflow(tcx, mir, def_id, &[], &dead_unwinds, storage_live_analysis,
|bd, p| DebugFormatted::new(&bd.mir().local_decls[p]));

// Find the MIR locals which do not use StorageLive/StorageDead statements.
Expand All @@ -403,7 +403,7 @@ fn locals_live_across_suspend_points(
let borrowed_locals = if !movable {
let analysis = HaveBeenBorrowedLocals::new(mir);
let result =
do_dataflow(tcx, mir, hir_id, &[], &dead_unwinds, analysis,
do_dataflow(tcx, mir, def_id, &[], &dead_unwinds, analysis,
|bd, p| DebugFormatted::new(&bd.mir().local_decls[p]));
Some((analysis, result))
} else {
Expand Down
19 changes: 9 additions & 10 deletions src/librustc_mir/transform/rustc_peek.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use syntax::ast;
use syntax_pos::Span;

use rustc::ty::{self, TyCtxt};
use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::mir::{self, Mir, Location};
use rustc_data_structures::bit_set::BitSet;
use crate::transform::{MirPass, MirSource};
Expand All @@ -27,7 +27,6 @@ impl MirPass for SanityCheck {
fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
src: MirSource<'tcx>, mir: &mut Mir<'tcx>) {
let def_id = src.def_id();
let id = tcx.hir().as_local_hir_id(def_id).unwrap();
if !tcx.has_attr(def_id, "rustc_mir") {
debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id));
return;
Expand All @@ -41,26 +40,26 @@ impl MirPass for SanityCheck {
let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len());
let flow_inits =
do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
do_dataflow(tcx, mir, def_id, &attributes, &dead_unwinds,
MaybeInitializedPlaces::new(tcx, mir, &mdpe),
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]));
let flow_uninits =
do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
do_dataflow(tcx, mir, def_id, &attributes, &dead_unwinds,
MaybeUninitializedPlaces::new(tcx, mir, &mdpe),
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]));
let flow_def_inits =
do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
do_dataflow(tcx, mir, def_id, &attributes, &dead_unwinds,
DefinitelyInitializedPlaces::new(tcx, mir, &mdpe),
|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);
sanity_check_via_rustc_peek(tcx, mir, def_id, &attributes, &flow_inits);
}
if has_rustc_mir_with(&attributes, "rustc_peek_maybe_uninit").is_some() {
sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_uninits);
sanity_check_via_rustc_peek(tcx, mir, def_id, &attributes, &flow_uninits);
}
if has_rustc_mir_with(&attributes, "rustc_peek_definite_init").is_some() {
sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_def_inits);
sanity_check_via_rustc_peek(tcx, mir, def_id, &attributes, &flow_def_inits);
}
if has_rustc_mir_with(&attributes, "stop_after_dataflow").is_some() {
tcx.sess.fatal("stop_after_dataflow ended compilation");
Expand All @@ -86,12 +85,12 @@ impl MirPass for SanityCheck {
/// errors are not intended to be used for unit tests.)
pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
mir: &Mir<'tcx>,
id: hir::HirId,
def_id: DefId,
_attributes: &[ast::Attribute],
results: &DataflowResults<'tcx, O>)
where O: BitDenotation<'tcx, Idx=MovePathIndex> + HasMoveData<'tcx>
{
debug!("sanity_check_via_rustc_peek id: {:?}", id);
debug!("sanity_check_via_rustc_peek def_id: {:?}", def_id);
// FIXME: this is not DRY. Figure out way to abstract this and
// `dataflow::build_sets`. (But note it is doing non-standard
// stuff, so such generalization may not be realistic.)
Expand Down
14 changes: 13 additions & 1 deletion src/librustc_mir/util/graphviz.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use rustc::hir::def_id::DefId;
use rustc::mir::*;
use rustc::ty::TyCtxt;
use rustc_data_structures::indexed_vec::Idx;
use std::fmt::Debug;
use std::io::{self, Write};

Expand All @@ -20,14 +21,25 @@ pub fn write_mir_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>,
Ok(())
}

// Must match `[0-9A-Za-z_]*`. This does not appear in the rendered graph, so
// it does not have to be user friendly.
pub fn graphviz_safe_def_name(def_id: DefId) -> String {
format!(
"{}_{}_{}",
def_id.krate.index(),
def_id.index.address_space().index(),
def_id.index.as_array_index(),
)
}

/// Write a graphviz DOT graph of the MIR.
pub fn write_mir_fn_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>,
def_id: DefId,
mir: &Mir<'_>,
w: &mut W) -> io::Result<()>
where W: Write
{
writeln!(w, "digraph Mir_{} {{", tcx.hir().as_local_hir_id(def_id).unwrap())?;
writeln!(w, "digraph Mir_{} {{", graphviz_safe_def_name(def_id))?;

// Global graph properties
writeln!(w, r#" graph [fontname="monospace"];"#)?;
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub mod collect_writes;

pub use self::alignment::is_disaligned;
pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty, PassWhere};
pub use self::graphviz::{write_mir_graphviz};
pub use self::graphviz::{graphviz_safe_def_name, write_mir_graphviz};
pub use self::graphviz::write_node_label as write_graphviz_node_label;

/// If possible, suggest replacing `ref` with `ref mut`.
Expand Down
23 changes: 23 additions & 0 deletions src/test/mir-opt/graphviz.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Test graphviz output
// compile-flags: -Z dump-mir-graphviz

// ignore-tidy-linelength

fn main() {}

// END RUST SOURCE
// START rustc.main.mir_map.0.dot
// digraph Mir_0_0_3 { // The name here MUST be an ASCII identifier.
// graph [fontname="monospace"];
// node [fontname="monospace"];
// edge [fontname="monospace"];
// label=<fn main() -&gt; ()<br align="left"/>>;
// bb0 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">0</td></tr><tr><td align="left" balign="left">_0 = ()<br/></td></tr><tr><td align="left">goto</td></tr></table>
// >];
// bb1 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">1</td></tr><tr><td align="left">resume</td></tr></table>
// >];
// bb2 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">2</td></tr><tr><td align="left">return</td></tr></table>
// >];
// bb0 -> bb2 [label=""];
// }
// END rustc.main.mir_map.0.dot