summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_dataflow/src/framework/graphviz.rs')
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/graphviz.rs98
1 files changed, 52 insertions, 46 deletions
diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index 707729f8f..e331533c3 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -1,6 +1,7 @@
//! A helpful diagram for debugging dataflow problems.
use std::borrow::Cow;
+use std::cell::RefCell;
use std::sync::OnceLock;
use std::{io, ops, str};
@@ -28,23 +29,27 @@ impl OutputStyle {
}
}
-pub struct Formatter<'a, 'tcx, A>
+pub struct Formatter<'res, 'mir, 'tcx, A>
where
A: Analysis<'tcx>,
{
- body: &'a Body<'tcx>,
- results: &'a Results<'tcx, A>,
+ body: &'mir Body<'tcx>,
+ results: RefCell<&'res mut Results<'tcx, A>>,
style: OutputStyle,
reachable: BitSet<BasicBlock>,
}
-impl<'a, 'tcx, A> Formatter<'a, 'tcx, A>
+impl<'res, 'mir, 'tcx, A> Formatter<'res, 'mir, 'tcx, A>
where
A: Analysis<'tcx>,
{
- pub fn new(body: &'a Body<'tcx>, results: &'a Results<'tcx, A>, style: OutputStyle) -> Self {
+ pub fn new(
+ body: &'mir Body<'tcx>,
+ results: &'res mut Results<'tcx, A>,
+ style: OutputStyle,
+ ) -> Self {
let reachable = mir::traversal::reachable_as_bitset(body);
- Formatter { body, results, style, reachable }
+ Formatter { body, results: results.into(), style, reachable }
}
}
@@ -64,7 +69,7 @@ fn dataflow_successors(body: &Body<'_>, bb: BasicBlock) -> Vec<CfgEdge> {
.collect()
}
-impl<'tcx, A> dot::Labeller<'_> for Formatter<'_, 'tcx, A>
+impl<'tcx, A> dot::Labeller<'_> for Formatter<'_, '_, 'tcx, A>
where
A: Analysis<'tcx>,
A::Domain: DebugWithContext<A>,
@@ -83,13 +88,14 @@ where
fn node_label(&self, block: &Self::Node) -> dot::LabelText<'_> {
let mut label = Vec::new();
+ let mut results = self.results.borrow_mut();
let mut fmt = BlockFormatter {
- results: ResultsRefCursor::new(self.body, self.results),
+ results: results.as_results_cursor(self.body),
style: self.style,
bg: Background::Light,
};
- fmt.write_node_label(&mut label, self.body, *block).unwrap();
+ fmt.write_node_label(&mut label, *block).unwrap();
dot::LabelText::html(String::from_utf8(label).unwrap())
}
@@ -103,7 +109,7 @@ where
}
}
-impl<'a, 'tcx, A> dot::GraphWalk<'a> for Formatter<'a, 'tcx, A>
+impl<'mir, 'tcx, A> dot::GraphWalk<'mir> for Formatter<'_, 'mir, 'tcx, A>
where
A: Analysis<'tcx>,
{
@@ -137,16 +143,16 @@ where
}
}
-struct BlockFormatter<'a, 'tcx, A>
+struct BlockFormatter<'res, 'mir, 'tcx, A>
where
A: Analysis<'tcx>,
{
- results: ResultsRefCursor<'a, 'a, 'tcx, A>,
+ results: ResultsRefCursor<'res, 'mir, 'tcx, A>,
bg: Background,
style: OutputStyle,
}
-impl<'a, 'tcx, A> BlockFormatter<'a, 'tcx, A>
+impl<'res, 'mir, 'tcx, A> BlockFormatter<'res, 'mir, 'tcx, A>
where
A: Analysis<'tcx>,
A::Domain: DebugWithContext<A>,
@@ -159,12 +165,7 @@ where
bg
}
- fn write_node_label(
- &mut self,
- w: &mut impl io::Write,
- body: &'a Body<'tcx>,
- block: BasicBlock,
- ) -> io::Result<()> {
+ fn write_node_label(&mut self, w: &mut impl io::Write, block: BasicBlock) -> io::Result<()> {
// Sample output:
// +-+-----------------------------------------------+
// A | bb4 |
@@ -215,11 +216,11 @@ where
self.write_row_with_full_state(w, "", "(on start)")?;
// D + E: Statement and terminator transfer functions
- self.write_statements_and_terminator(w, body, block)?;
+ self.write_statements_and_terminator(w, block)?;
// F: State at end of block
- let terminator = body[block].terminator();
+ let terminator = self.results.body()[block].terminator();
// Write the full dataflow state immediately after the terminator if it differs from the
// state at block entry.
@@ -389,10 +390,14 @@ where
fn write_statements_and_terminator(
&mut self,
w: &mut impl io::Write,
- body: &'a Body<'tcx>,
block: BasicBlock,
) -> io::Result<()> {
- let diffs = StateDiffCollector::run(body, block, self.results.results(), self.style);
+ let diffs = StateDiffCollector::run(
+ self.results.body(),
+ block,
+ self.results.mut_results(),
+ self.style,
+ );
let mut diffs_before = diffs.before.map(|v| v.into_iter());
let mut diffs_after = diffs.after.into_iter();
@@ -401,7 +406,7 @@ where
if A::Direction::IS_FORWARD { it.next().unwrap() } else { it.next_back().unwrap() }
};
- for (i, statement) in body[block].statements.iter().enumerate() {
+ for (i, statement) in self.results.body()[block].statements.iter().enumerate() {
let statement_str = format!("{statement:?}");
let index_str = format!("{i}");
@@ -423,7 +428,7 @@ where
assert!(diffs_after.is_empty());
assert!(diffs_before.as_ref().map_or(true, ExactSizeIterator::is_empty));
- let terminator = body[block].terminator();
+ let terminator = self.results.body()[block].terminator();
let mut terminator_str = String::new();
terminator.kind.fmt_head(&mut terminator_str).unwrap();
@@ -492,29 +497,24 @@ where
}
}
-struct StateDiffCollector<'a, 'tcx, A>
-where
- A: Analysis<'tcx>,
-{
- analysis: &'a A,
- prev_state: A::Domain,
+struct StateDiffCollector<D> {
+ prev_state: D,
before: Option<Vec<String>>,
after: Vec<String>,
}
-impl<'a, 'tcx, A> StateDiffCollector<'a, 'tcx, A>
-where
- A: Analysis<'tcx>,
- A::Domain: DebugWithContext<A>,
-{
- fn run(
- body: &'a mir::Body<'tcx>,
+impl<D> StateDiffCollector<D> {
+ fn run<'tcx, A>(
+ body: &mir::Body<'tcx>,
block: BasicBlock,
- results: &'a Results<'tcx, A>,
+ results: &mut Results<'tcx, A>,
style: OutputStyle,
- ) -> Self {
+ ) -> Self
+ where
+ A: Analysis<'tcx, Domain = D>,
+ D: DebugWithContext<A>,
+ {
let mut collector = StateDiffCollector {
- analysis: &results.analysis,
prev_state: results.analysis.bottom_value(body),
after: vec![],
before: (style == OutputStyle::BeforeAndAfter).then_some(vec![]),
@@ -525,7 +525,7 @@ where
}
}
-impl<'a, 'tcx, A> ResultsVisitor<'a, 'tcx> for StateDiffCollector<'a, 'tcx, A>
+impl<'tcx, A> ResultsVisitor<'_, 'tcx, Results<'tcx, A>> for StateDiffCollector<A::Domain>
where
A: Analysis<'tcx>,
A::Domain: DebugWithContext<A>,
@@ -534,6 +534,7 @@ where
fn visit_block_start(
&mut self,
+ _results: &Results<'tcx, A>,
state: &Self::FlowState,
_block_data: &mir::BasicBlockData<'tcx>,
_block: BasicBlock,
@@ -545,6 +546,7 @@ where
fn visit_block_end(
&mut self,
+ _results: &Results<'tcx, A>,
state: &Self::FlowState,
_block_data: &mir::BasicBlockData<'tcx>,
_block: BasicBlock,
@@ -556,45 +558,49 @@ where
fn visit_statement_before_primary_effect(
&mut self,
+ results: &Results<'tcx, A>,
state: &Self::FlowState,
_statement: &mir::Statement<'tcx>,
_location: Location,
) {
if let Some(before) = self.before.as_mut() {
- before.push(diff_pretty(state, &self.prev_state, self.analysis));
+ before.push(diff_pretty(state, &self.prev_state, &results.analysis));
self.prev_state.clone_from(state)
}
}
fn visit_statement_after_primary_effect(
&mut self,
+ results: &Results<'tcx, A>,
state: &Self::FlowState,
_statement: &mir::Statement<'tcx>,
_location: Location,
) {
- self.after.push(diff_pretty(state, &self.prev_state, self.analysis));
+ self.after.push(diff_pretty(state, &self.prev_state, &results.analysis));
self.prev_state.clone_from(state)
}
fn visit_terminator_before_primary_effect(
&mut self,
+ results: &Results<'tcx, A>,
state: &Self::FlowState,
_terminator: &mir::Terminator<'tcx>,
_location: Location,
) {
if let Some(before) = self.before.as_mut() {
- before.push(diff_pretty(state, &self.prev_state, self.analysis));
+ before.push(diff_pretty(state, &self.prev_state, &results.analysis));
self.prev_state.clone_from(state)
}
}
fn visit_terminator_after_primary_effect(
&mut self,
+ results: &Results<'tcx, A>,
state: &Self::FlowState,
_terminator: &mir::Terminator<'tcx>,
_location: Location,
) {
- self.after.push(diff_pretty(state, &self.prev_state, self.analysis));
+ self.after.push(diff_pretty(state, &self.prev_state, &results.analysis));
self.prev_state.clone_from(state)
}
}