Skip to content

Commit 00fb9d9

Browse files
authored
Rollup merge of #59251 - matthewjasper:fix-graphviz, r=petrochenkov
Use a valid name for graphviz graphs Hiridification has broken graphviz output because `HirId` has a more complex display implemetation than `NodeId`. Since the id was just used to generate a distinct identifier, we just pull out the various constituent indexed.
2 parents 859c9a5 + 6430318 commit 00fb9d9

File tree

10 files changed

+85
-40
lines changed

10 files changed

+85
-40
lines changed

src/librustc_driver/pretty.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -633,10 +633,20 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec<borrowck_dot::Variant>,
633633
let body = tcx.hir().body(body_id);
634634
let cfg = cfg::CFG::new(tcx, &body);
635635
let labelled_edges = mode != PpFlowGraphMode::UnlabelledEdges;
636+
let hir_id = code.id();
637+
// We have to disassemble the hir_id because name must be ASCII
638+
// alphanumeric. This does not appear in the rendered graph, so it does not
639+
// have to be user friendly.
640+
let name = format!(
641+
"hir_id_{}_{}_{}",
642+
hir_id.owner.address_space().index(),
643+
hir_id.owner.as_array_index(),
644+
hir_id.local_id.index(),
645+
);
636646
let lcfg = LabelledCFG {
637647
tcx,
638648
cfg: &cfg,
639-
name: format!("node_{}", code.id()),
649+
name,
640650
labelled_edges,
641651
};
642652

src/librustc_mir/borrow_check/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
156156
let mut flow_inits = FlowAtLocation::new(do_dataflow(
157157
tcx,
158158
mir,
159-
id,
159+
def_id,
160160
&attributes,
161161
&dead_unwinds,
162162
MaybeInitializedPlaces::new(tcx, mir, &mdpe),
@@ -191,7 +191,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
191191
let flow_borrows = FlowAtLocation::new(do_dataflow(
192192
tcx,
193193
mir,
194-
id,
194+
def_id,
195195
&attributes,
196196
&dead_unwinds,
197197
Borrows::new(tcx, mir, regioncx.clone(), &borrow_set),
@@ -200,7 +200,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
200200
let flow_uninits = FlowAtLocation::new(do_dataflow(
201201
tcx,
202202
mir,
203-
id,
203+
def_id,
204204
&attributes,
205205
&dead_unwinds,
206206
MaybeUninitializedPlaces::new(tcx, mir, &mdpe),
@@ -209,7 +209,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
209209
let flow_ever_inits = FlowAtLocation::new(do_dataflow(
210210
tcx,
211211
mir,
212-
id,
212+
def_id,
213213
&attributes,
214214
&dead_unwinds,
215215
EverInitializedPlaces::new(tcx, mir, &mdpe),

src/librustc_mir/dataflow/graphviz.rs

+9-8
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
//! Hook into libgraphviz for rendering dataflow graphs for MIR.
22
3-
use rustc::hir::HirId;
3+
use rustc::hir::def_id::DefId;
44
use rustc::mir::{BasicBlock, Mir};
55

66
use std::fs;
77
use std::io;
88
use std::marker::PhantomData;
99
use std::path::Path;
1010

11+
use crate::util::graphviz_safe_def_name;
12+
1113
use super::{BitDenotation, DataflowState};
1214
use super::DataflowBuilder;
1315
use super::DebugFormatted;
1416

1517
pub trait MirWithFlowState<'tcx> {
1618
type BD: BitDenotation<'tcx>;
17-
fn hir_id(&self) -> HirId;
19+
fn def_id(&self) -> DefId;
1820
fn mir(&self) -> &Mir<'tcx>;
1921
fn flow_state(&self) -> &DataflowState<'tcx, Self::BD>;
2022
}
@@ -23,7 +25,7 @@ impl<'a, 'tcx, BD> MirWithFlowState<'tcx> for DataflowBuilder<'a, 'tcx, BD>
2325
where BD: BitDenotation<'tcx>
2426
{
2527
type BD = BD;
26-
fn hir_id(&self) -> HirId { self.hir_id }
28+
fn def_id(&self) -> DefId { self.def_id }
2729
fn mir(&self) -> &Mir<'tcx> { self.flow_state.mir() }
2830
fn flow_state(&self) -> &DataflowState<'tcx, Self::BD> { &self.flow_state.flow_state }
2931
}
@@ -47,8 +49,8 @@ pub(crate) fn print_borrowck_graph_to<'a, 'tcx, BD, P>(
4749
let g = Graph { mbcx, phantom: PhantomData, render_idx };
4850
let mut v = Vec::new();
4951
dot::render(&g, &mut v)?;
50-
debug!("print_borrowck_graph_to path: {} hir_id: {}",
51-
path.display(), mbcx.hir_id);
52+
debug!("print_borrowck_graph_to path: {} def_id: {:?}",
53+
path.display(), mbcx.def_id);
5254
fs::write(path, v)
5355
}
5456

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

7778
fn node_id(&self, n: &Node) -> dot::Id<'_> {

src/librustc_mir/dataflow/mod.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_data_structures::bit_set::{BitSet, BitSetOperator, HybridBitSet};
44
use rustc_data_structures::indexed_vec::Idx;
55
use rustc_data_structures::work_queue::WorkQueue;
66

7-
use rustc::hir::HirId;
7+
use rustc::hir::def_id::DefId;
88
use rustc::ty::{self, TyCtxt};
99
use rustc::mir::{self, Mir, BasicBlock, BasicBlockData, Location, Statement, Terminator};
1010
use rustc::mir::traversal;
@@ -39,7 +39,7 @@ pub(crate) struct DataflowBuilder<'a, 'tcx: 'a, BD>
3939
where
4040
BD: BitDenotation<'tcx>
4141
{
42-
hir_id: HirId,
42+
def_id: DefId,
4343
flow_state: DataflowAnalysis<'a, 'tcx, BD>,
4444
print_preflow_to: Option<String>,
4545
print_postflow_to: Option<String>,
@@ -117,7 +117,7 @@ pub struct MoveDataParamEnv<'gcx, 'tcx> {
117117

118118
pub(crate) fn do_dataflow<'a, 'gcx, 'tcx, BD, P>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
119119
mir: &'a Mir<'tcx>,
120-
hir_id: HirId,
120+
def_id: DefId,
121121
attributes: &[ast::Attribute],
122122
dead_unwinds: &BitSet<BasicBlock>,
123123
bd: BD,
@@ -127,14 +127,14 @@ pub(crate) fn do_dataflow<'a, 'gcx, 'tcx, BD, P>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
127127
P: Fn(&BD, BD::Idx) -> DebugFormatted
128128
{
129129
let flow_state = DataflowAnalysis::new(mir, dead_unwinds, bd);
130-
flow_state.run(tcx, hir_id, attributes, p)
130+
flow_state.run(tcx, def_id, attributes, p)
131131
}
132132

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

161161
let mut mbcx = DataflowBuilder {
162-
hir_id,
162+
def_id,
163163
print_preflow_to, print_postflow_to, flow_state: self,
164164
};
165165

src/librustc_mir/transform/elaborate_drops.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ impl MirPass for ElaborateDrops {
2828
{
2929
debug!("elaborate_drops({:?} @ {:?})", src, mir.span);
3030

31-
let id = tcx.hir().as_local_hir_id(src.def_id()).unwrap();
31+
let def_id = src.def_id();
3232
let param_env = tcx.param_env(src.def_id()).with_reveal_all();
3333
let move_data = match MoveData::gather_moves(mir, tcx) {
3434
Ok(move_data) => move_data,
@@ -50,13 +50,13 @@ impl MirPass for ElaborateDrops {
5050
move_data,
5151
param_env,
5252
};
53-
let dead_unwinds = find_dead_unwinds(tcx, mir, id, &env);
53+
let dead_unwinds = find_dead_unwinds(tcx, mir, def_id, &env);
5454
let flow_inits =
55-
do_dataflow(tcx, mir, id, &[], &dead_unwinds,
55+
do_dataflow(tcx, mir, def_id, &[], &dead_unwinds,
5656
MaybeInitializedPlaces::new(tcx, mir, &env),
5757
|bd, p| DebugFormatted::new(&bd.move_data().move_paths[p]));
5858
let flow_uninits =
59-
do_dataflow(tcx, mir, id, &[], &dead_unwinds,
59+
do_dataflow(tcx, mir, def_id, &[], &dead_unwinds,
6060
MaybeUninitializedPlaces::new(tcx, mir, &env),
6161
|bd, p| DebugFormatted::new(&bd.move_data().move_paths[p]));
6262

@@ -80,7 +80,7 @@ impl MirPass for ElaborateDrops {
8080
fn find_dead_unwinds<'a, 'tcx>(
8181
tcx: TyCtxt<'a, 'tcx, 'tcx>,
8282
mir: &Mir<'tcx>,
83-
id: hir::HirId,
83+
def_id: hir::def_id::DefId,
8484
env: &MoveDataParamEnv<'tcx, 'tcx>)
8585
-> BitSet<BasicBlock>
8686
{
@@ -89,7 +89,7 @@ fn find_dead_unwinds<'a, 'tcx>(
8989
// reach cleanup blocks, which can't have unwind edges themselves.
9090
let mut dead_unwinds = BitSet::new_empty(mir.basic_blocks().len());
9191
let flow_inits =
92-
do_dataflow(tcx, mir, id, &[], &dead_unwinds,
92+
do_dataflow(tcx, mir, def_id, &[], &dead_unwinds,
9393
MaybeInitializedPlaces::new(tcx, mir, &env),
9494
|bd, p| DebugFormatted::new(&bd.move_data().move_paths[p]));
9595
for (bb, bb_data) in mir.basic_blocks().iter_enumerated() {

src/librustc_mir/transform/generator.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -383,13 +383,13 @@ fn locals_live_across_suspend_points(
383383
FxHashMap<BasicBlock, liveness::LiveVarSet>,
384384
) {
385385
let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len());
386-
let hir_id = tcx.hir().as_local_hir_id(source.def_id()).unwrap();
386+
let def_id = source.def_id();
387387

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

395395
// Find the MIR locals which do not use StorageLive/StorageDead statements.
@@ -403,7 +403,7 @@ fn locals_live_across_suspend_points(
403403
let borrowed_locals = if !movable {
404404
let analysis = HaveBeenBorrowedLocals::new(mir);
405405
let result =
406-
do_dataflow(tcx, mir, hir_id, &[], &dead_unwinds, analysis,
406+
do_dataflow(tcx, mir, def_id, &[], &dead_unwinds, analysis,
407407
|bd, p| DebugFormatted::new(&bd.mir().local_decls[p]));
408408
Some((analysis, result))
409409
} else {

src/librustc_mir/transform/rustc_peek.rs

+9-10
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use syntax::ast;
33
use syntax_pos::Span;
44

55
use rustc::ty::{self, TyCtxt};
6-
use rustc::hir;
6+
use rustc::hir::def_id::DefId;
77
use rustc::mir::{self, Mir, Location};
88
use rustc_data_structures::bit_set::BitSet;
99
use crate::transform::{MirPass, MirSource};
@@ -27,7 +27,6 @@ impl MirPass for SanityCheck {
2727
fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
2828
src: MirSource<'tcx>, mir: &mut Mir<'tcx>) {
2929
let def_id = src.def_id();
30-
let id = tcx.hir().as_local_hir_id(def_id).unwrap();
3130
if !tcx.has_attr(def_id, "rustc_mir") {
3231
debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id));
3332
return;
@@ -41,26 +40,26 @@ impl MirPass for SanityCheck {
4140
let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
4241
let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len());
4342
let flow_inits =
44-
do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
43+
do_dataflow(tcx, mir, def_id, &attributes, &dead_unwinds,
4544
MaybeInitializedPlaces::new(tcx, mir, &mdpe),
4645
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]));
4746
let flow_uninits =
48-
do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
47+
do_dataflow(tcx, mir, def_id, &attributes, &dead_unwinds,
4948
MaybeUninitializedPlaces::new(tcx, mir, &mdpe),
5049
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]));
5150
let flow_def_inits =
52-
do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
51+
do_dataflow(tcx, mir, def_id, &attributes, &dead_unwinds,
5352
DefinitelyInitializedPlaces::new(tcx, mir, &mdpe),
5453
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]));
5554

5655
if has_rustc_mir_with(&attributes, "rustc_peek_maybe_init").is_some() {
57-
sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_inits);
56+
sanity_check_via_rustc_peek(tcx, mir, def_id, &attributes, &flow_inits);
5857
}
5958
if has_rustc_mir_with(&attributes, "rustc_peek_maybe_uninit").is_some() {
60-
sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_uninits);
59+
sanity_check_via_rustc_peek(tcx, mir, def_id, &attributes, &flow_uninits);
6160
}
6261
if has_rustc_mir_with(&attributes, "rustc_peek_definite_init").is_some() {
63-
sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_def_inits);
62+
sanity_check_via_rustc_peek(tcx, mir, def_id, &attributes, &flow_def_inits);
6463
}
6564
if has_rustc_mir_with(&attributes, "stop_after_dataflow").is_some() {
6665
tcx.sess.fatal("stop_after_dataflow ended compilation");
@@ -86,12 +85,12 @@ impl MirPass for SanityCheck {
8685
/// errors are not intended to be used for unit tests.)
8786
pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
8887
mir: &Mir<'tcx>,
89-
id: hir::HirId,
88+
def_id: DefId,
9089
_attributes: &[ast::Attribute],
9190
results: &DataflowResults<'tcx, O>)
9291
where O: BitDenotation<'tcx, Idx=MovePathIndex> + HasMoveData<'tcx>
9392
{
94-
debug!("sanity_check_via_rustc_peek id: {:?}", id);
93+
debug!("sanity_check_via_rustc_peek def_id: {:?}", def_id);
9594
// FIXME: this is not DRY. Figure out way to abstract this and
9695
// `dataflow::build_sets`. (But note it is doing non-standard
9796
// stuff, so such generalization may not be realistic.)

src/librustc_mir/util/graphviz.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use rustc::hir::def_id::DefId;
22
use rustc::mir::*;
33
use rustc::ty::TyCtxt;
4+
use rustc_data_structures::indexed_vec::Idx;
45
use std::fmt::Debug;
56
use std::io::{self, Write};
67

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

24+
// Must match `[0-9A-Za-z_]*`. This does not appear in the rendered graph, so
25+
// it does not have to be user friendly.
26+
pub fn graphviz_safe_def_name(def_id: DefId) -> String {
27+
format!(
28+
"{}_{}_{}",
29+
def_id.krate.index(),
30+
def_id.index.address_space().index(),
31+
def_id.index.as_array_index(),
32+
)
33+
}
34+
2335
/// Write a graphviz DOT graph of the MIR.
2436
pub fn write_mir_fn_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>,
2537
def_id: DefId,
2638
mir: &Mir<'_>,
2739
w: &mut W) -> io::Result<()>
2840
where W: Write
2941
{
30-
writeln!(w, "digraph Mir_{} {{", tcx.hir().as_local_hir_id(def_id).unwrap())?;
42+
writeln!(w, "digraph Mir_{} {{", graphviz_safe_def_name(def_id))?;
3143

3244
// Global graph properties
3345
writeln!(w, r#" graph [fontname="monospace"];"#)?;

src/librustc_mir/util/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub mod collect_writes;
1515

1616
pub use self::alignment::is_disaligned;
1717
pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty, PassWhere};
18-
pub use self::graphviz::{write_mir_graphviz};
18+
pub use self::graphviz::{graphviz_safe_def_name, write_mir_graphviz};
1919
pub use self::graphviz::write_node_label as write_graphviz_node_label;
2020

2121
/// If possible, suggest replacing `ref` with `ref mut`.

src/test/mir-opt/graphviz.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Test graphviz output
2+
// compile-flags: -Z dump-mir-graphviz
3+
4+
// ignore-tidy-linelength
5+
6+
fn main() {}
7+
8+
// END RUST SOURCE
9+
// START rustc.main.mir_map.0.dot
10+
// digraph Mir_0_0_3 { // The name here MUST be an ASCII identifier.
11+
// graph [fontname="monospace"];
12+
// node [fontname="monospace"];
13+
// edge [fontname="monospace"];
14+
// label=<fn main() -&gt; ()<br align="left"/>>;
15+
// 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>
16+
// >];
17+
// 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>
18+
// >];
19+
// 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>
20+
// >];
21+
// bb0 -> bb2 [label=""];
22+
// }
23+
// END rustc.main.mir_map.0.dot

0 commit comments

Comments
 (0)