Skip to content

Commit 052e9b4

Browse files
committed
add NLL SCCs to polonius MIR dump
1 parent 1ee7582 commit 052e9b4

File tree

1 file changed

+49
-0
lines changed
  • compiler/rustc_borrowck/src/polonius

1 file changed

+49
-0
lines changed

compiler/rustc_borrowck/src/polonius/dump.rs

+49
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::io;
22

33
use rustc_data_structures::fx::FxHashSet;
4+
use rustc_index::IndexVec;
45
use rustc_middle::mir::pretty::{
56
PassWhere, PrettyPrintMirOptions, create_dump_file, dump_enabled, dump_mir_to_writer,
67
};
@@ -54,6 +55,7 @@ pub(crate) fn dump_polonius_mir<'tcx>(
5455
/// - the list of polonius localized constraints
5556
/// - a mermaid graph of the CFG
5657
/// - a mermaid graph of the NLL regions and the constraints between them
58+
/// - a mermaid graph of the NLL SCCs and the constraints between them
5759
fn emit_polonius_dump<'tcx>(
5860
tcx: TyCtxt<'tcx>,
5961
body: &Body<'tcx>,
@@ -101,6 +103,14 @@ fn emit_polonius_dump<'tcx>(
101103
writeln!(out, "</pre>")?;
102104
writeln!(out, "</div>")?;
103105

106+
// Section 4: mermaid visualization of the NLL SCC graph.
107+
writeln!(out, "<div>")?;
108+
writeln!(out, "NLL SCCs")?;
109+
writeln!(out, "<pre class='mermaid'>")?;
110+
emit_mermaid_nll_sccs(regioncx, out)?;
111+
writeln!(out, "</pre>")?;
112+
writeln!(out, "</div>")?;
113+
104114
// Finalize the dump with the HTML epilogue.
105115
writeln!(
106116
out,
@@ -343,3 +353,42 @@ fn emit_mermaid_nll_regions<'tcx>(
343353
}
344354
Ok(())
345355
}
356+
357+
/// Emits a mermaid flowchart of the NLL SCCs and the outlives constraints between them, similar
358+
/// to the graphviz version.
359+
fn emit_mermaid_nll_sccs<'tcx>(
360+
regioncx: &RegionInferenceContext<'tcx>,
361+
out: &mut dyn io::Write,
362+
) -> io::Result<()> {
363+
// The mermaid chart type: a top-down flowchart.
364+
writeln!(out, "flowchart TD")?;
365+
366+
// Gather and emit the SCC nodes.
367+
let mut nodes_per_scc: IndexVec<_, _> =
368+
regioncx.constraint_sccs().all_sccs().map(|_| Vec::new()).collect();
369+
for region in regioncx.var_infos.indices() {
370+
let scc = regioncx.constraint_sccs().scc(region);
371+
nodes_per_scc[scc].push(region);
372+
}
373+
for (scc, regions) in nodes_per_scc.iter_enumerated() {
374+
// The node label: the regions contained in the SCC.
375+
write!(out, "{scc}[\"SCC({scc}) = {{", scc = scc.as_usize())?;
376+
for (idx, &region) in regions.iter().enumerate() {
377+
render_region(region, regioncx, out)?;
378+
if idx < regions.len() - 1 {
379+
write!(out, ",")?;
380+
}
381+
}
382+
writeln!(out, "}}\"]")?;
383+
}
384+
385+
// Emit the edges between SCCs.
386+
let edges = regioncx.constraint_sccs().all_sccs().flat_map(|source| {
387+
regioncx.constraint_sccs().successors(source).iter().map(move |&target| (source, target))
388+
});
389+
for (source, target) in edges {
390+
writeln!(out, "{} --> {}", source.as_usize(), target.as_usize())?;
391+
}
392+
393+
Ok(())
394+
}

0 commit comments

Comments
 (0)