From effd52078c55c4e585010f6d1a322414c4979da6 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 20 Jan 2020 18:36:54 -0800 Subject: [PATCH 1/5] Print `after` effect in default graphviz formatter Now the line for each statement will show the diff resulting from the combination of `before_statement_effect` and `statement_effect`. It's still possible to observe each in isolation via `borrowck_graphviz_format = "two_phase"`. --- src/librustc_mir/dataflow/generic/graphviz.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/dataflow/generic/graphviz.rs b/src/librustc_mir/dataflow/generic/graphviz.rs index fdf86e7b53f60..2917807482cc8 100644 --- a/src/librustc_mir/dataflow/generic/graphviz.rs +++ b/src/librustc_mir/dataflow/generic/graphviz.rs @@ -418,7 +418,7 @@ where self.prev_loc = location; write!(w, r#""#, fmt = fmt)?; - results.seek_before(location); + results.seek_after(location); let curr_state = results.get(); write_diff(&mut w, results.analysis(), &self.prev_state, curr_state)?; self.prev_state.overwrite(curr_state); @@ -445,7 +445,7 @@ where A: Analysis<'tcx>, { fn column_names(&self) -> &[&str] { - &["ENTRY", " EXIT"] + &["BEFORE", " AFTER"] } fn write_state_for_location( @@ -465,7 +465,7 @@ where self.prev_loc = location; - // Entry + // Before write!(w, r#""#, fmt = fmt)?; results.seek_before(location); @@ -474,7 +474,7 @@ where self.prev_state.overwrite(curr_state); write!(w, "")?; - // Exit + // After write!(w, r#""#, fmt = fmt)?; results.seek_after(location); From 852afa2e88db4db01d6454c3150c975f9f897420 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 21 Jan 2020 13:35:17 -0800 Subject: [PATCH 2/5] Add option to `dot::render` for monospace font --- src/libgraphviz/lib.rs | 10 ++++++++++ src/librustc_mir/dataflow/generic/engine.rs | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index d04f5c1d4ee77..a53e0012ca221 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -597,6 +597,8 @@ pub enum RenderOption { NoNodeLabels, NoEdgeStyles, NoNodeStyles, + + Monospace, } /// Returns vec holding all the default render options. @@ -626,6 +628,14 @@ where W: Write, { writeln!(w, "digraph {} {{", g.graph_id().as_slice())?; + + // Global graph properties + if options.contains(&RenderOption::Monospace) { + writeln!(w, r#" graph[fontname="monospace"];"#)?; + writeln!(w, r#" node[fontname="monospace"];"#)?; + writeln!(w, r#" edge[fontname="monospace"];"#)?; + } + for n in g.nodes().iter() { write!(w, " ")?; let id = g.node_id(n); diff --git a/src/librustc_mir/dataflow/generic/engine.rs b/src/librustc_mir/dataflow/generic/engine.rs index c0152b0c7d504..718c1e9ae2043 100644 --- a/src/librustc_mir/dataflow/generic/engine.rs +++ b/src/librustc_mir/dataflow/generic/engine.rs @@ -331,7 +331,7 @@ where let mut buf = Vec::new(); let graphviz = graphviz::Formatter::new(body, def_id, results, &mut *formatter); - dot::render(&graphviz, &mut buf)?; + dot::render_opts(&graphviz, &mut buf, &[dot::RenderOption::Monospace])?; fs::write(&path, buf)?; Ok(()) } From fb14386de355c2bf437515f20975612cda04ef70 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 21 Jan 2020 13:36:34 -0800 Subject: [PATCH 3/5] Remove unnecessary allows --- src/librustc_mir/dataflow/generic/graphviz.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/librustc_mir/dataflow/generic/graphviz.rs b/src/librustc_mir/dataflow/generic/graphviz.rs index 2917807482cc8..8bf5852f003f1 100644 --- a/src/librustc_mir/dataflow/generic/graphviz.rs +++ b/src/librustc_mir/dataflow/generic/graphviz.rs @@ -387,7 +387,6 @@ pub struct SimpleDiff { } impl SimpleDiff { - #![allow(unused)] pub fn new(bits_per_block: usize) -> Self { SimpleDiff { prev_state: BitSet::new_empty(bits_per_block), prev_loc: Location::START } } @@ -434,7 +433,6 @@ pub struct TwoPhaseDiff { } impl TwoPhaseDiff { - #![allow(unused)] pub fn new(bits_per_block: usize) -> Self { TwoPhaseDiff { prev_state: BitSet::new_empty(bits_per_block), prev_loc: Location::START } } @@ -492,7 +490,6 @@ pub struct BlockTransferFunc<'a, 'tcx, T: Idx> { } impl BlockTransferFunc<'mir, 'tcx, T> { - #![allow(unused)] pub fn new( body: &'mir mir::Body<'tcx>, trans_for_block: IndexVec>, From 83dfb422fe71979914d3db67db135e160ab29dcd Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 21 Jan 2020 13:37:02 -0800 Subject: [PATCH 4/5] Don't break first line --- src/librustc_mir/dataflow/generic/graphviz.rs | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/librustc_mir/dataflow/generic/graphviz.rs b/src/librustc_mir/dataflow/generic/graphviz.rs index 8bf5852f003f1..f70564d401913 100644 --- a/src/librustc_mir/dataflow/generic/graphviz.rs +++ b/src/librustc_mir/dataflow/generic/graphviz.rs @@ -610,13 +610,6 @@ where let mut line_break_inserted = false; for idx in elems { - if first { - first = false; - } else { - write!(w, "{}", sep)?; - curr_line_width += sep_width; - } - buf.clear(); analysis.pretty_print_idx(&mut buf, idx)?; let idx_str = @@ -624,11 +617,18 @@ where let escaped = dot::escape_html(idx_str); let escaped_width = escaped.chars().count(); - if let Some(line_break) = &line_break { - if curr_line_width + sep_width + escaped_width > line_break.limit { - write!(w, "{}", line_break.sequence)?; - line_break_inserted = true; - curr_line_width = 0; + if first { + first = false; + } else { + write!(w, "{}", sep)?; + curr_line_width += sep_width; + + if let Some(line_break) = &line_break { + if curr_line_width + sep_width + escaped_width > line_break.limit { + write!(w, "{}", line_break.sequence)?; + line_break_inserted = true; + curr_line_width = 0; + } } } From 8d6208c39b5aa63c7bbda30e325fdffefc7b81b8 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 21 Jan 2020 13:37:59 -0800 Subject: [PATCH 5/5] Use nicer alignment when printing state vectors --- src/librustc_mir/dataflow/generic/graphviz.rs | 44 ++++++++++++------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/src/librustc_mir/dataflow/generic/graphviz.rs b/src/librustc_mir/dataflow/generic/graphviz.rs index f70564d401913..b805b13592f89 100644 --- a/src/librustc_mir/dataflow/generic/graphviz.rs +++ b/src/librustc_mir/dataflow/generic/graphviz.rs @@ -171,10 +171,19 @@ where // | | (on successful return) | +_4 | // +-+----------------------------------+------------+ - write!( - w, - r#""#, - )?; + // N.B., Some attributes (`align`, `balign`) are repeated on parent elements and their + // children. This is because `xdot` seemed to have a hard time correctly propagating + // attributes. Make sure to test the output before trying to remove the redundancy. + // Notably, `align` was found to have no effect when applied only to
. + + let table_fmt = concat!( + " border=\"1\"", + " cellborder=\"1\"", + " cellspacing=\"0\"", + " cellpadding=\"3\"", + " sides=\"rb\"", + ); + write!(w, r#""#, fmt = table_fmt)?; // A + B: Block header if self.state_formatter.column_names().is_empty() { @@ -186,7 +195,7 @@ where // C: Entry state self.bg = Background::Light; self.results.seek_to_block_start(block); - self.write_row_with_full_state(w, "", "(on_entry)")?; + self.write_row_with_full_state(w, "", "(on entry)")?; // D: Statement transfer functions for (i, statement) in body[block].statements.iter().enumerate() { @@ -212,7 +221,7 @@ where self.write_row(w, "", "(on successful return)", |this, w, fmt| { write!( w, - r#"") }) } @@ -416,7 +427,7 @@ where } self.prev_loc = location; - write!(w, r#"")?; } @@ -561,25 +572,28 @@ fn write_diff>( if !set.is_empty() { write!(w, r#"+"#)?; - pretty_print_state_elems(w, analysis, set.iter(), ",", LIMIT_40_ALIGN_1)?; + pretty_print_state_elems(w, analysis, set.iter(), ", ", LIMIT_30_ALIGN_1)?; write!(w, r#""#)?; } if !set.is_empty() && !clear.is_empty() { - write!(w, "
")?; + write!(w, "{}", BR_LEFT)?; } if !clear.is_empty() { write!(w, r#"-"#)?; - pretty_print_state_elems(w, analysis, clear.iter(), ",", LIMIT_40_ALIGN_1)?; + pretty_print_state_elems(w, analysis, clear.iter(), ", ", LIMIT_30_ALIGN_1)?; write!(w, r#""#)?; } Ok(()) } +const BR_LEFT: &'static str = r#"
"#; +const BR_LEFT_SPACE: &'static str = r#"
"#; + /// Line break policy that breaks at 40 characters and starts the next line with a single space. -const LIMIT_40_ALIGN_1: Option = Some(LineBreak { sequence: "
", limit: 40 }); +const LIMIT_30_ALIGN_1: Option = Some(LineBreak { sequence: BR_LEFT_SPACE, limit: 30 }); struct LineBreak { sequence: &'static str,
"#, + r#""#, colspan = num_state_columns, fmt = fmt, )?; @@ -311,7 +320,9 @@ where f: impl FnOnce(&mut Self, &mut W, &str) -> io::Result<()>, ) -> io::Result<()> { let bg = self.toggle_background(); - let fmt = format!("sides=\"tl\" {}", bg.attr()); + let valign = if mir.starts_with("(on ") && mir != "(on entry)" { "bottom" } else { "top" }; + + let fmt = format!("valign=\"{}\" sides=\"tl\" {}", valign, bg.attr()); write!( w, @@ -345,7 +356,7 @@ where colspan = this.num_state_columns(), fmt = fmt, )?; - pretty_print_state_elems(w, analysis, state.iter(), ",", LIMIT_40_ALIGN_1)?; + pretty_print_state_elems(w, analysis, state.iter(), ", ", LIMIT_30_ALIGN_1)?; write!(w, "}}"#, fmt = fmt)?; + write!(w, r#""#, fmt = fmt)?; results.seek_after(location); let curr_state = results.get(); write_diff(&mut w, results.analysis(), &self.prev_state, curr_state)?; @@ -524,12 +535,12 @@ where for set in &[&block_trans.gen, &block_trans.kill] { write!( w, - r#""#, + r#""#, fmt = fmt, rowspan = rowspan )?; - pretty_print_state_elems(&mut w, results.analysis(), set.iter(), "\n", None)?; + pretty_print_state_elems(&mut w, results.analysis(), set.iter(), BR_LEFT, None)?; write!(w, "