Skip to content

Commit bcb134e

Browse files
authored
Unrolled build for rust-lang#132346
Rollup merge of rust-lang#132346 - nnethercote:some-graphviz-tweaks, r=cjgillot Some graphviz tweaks r? `@cjgillot`
2 parents 298c746 + d921be9 commit bcb134e

File tree

1 file changed

+58
-53
lines changed

1 file changed

+58
-53
lines changed

compiler/rustc_mir_dataflow/src/framework/graphviz.rs

+58-53
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,11 @@ pub(crate) struct Formatter<'mir, 'tcx, A>
3232
where
3333
A: Analysis<'tcx>,
3434
{
35-
body: &'mir Body<'tcx>,
36-
results: RefCell<Option<Results<'tcx, A>>>,
35+
// The `RefCell` is used because `<Formatter as Labeller>::node_label`
36+
// takes `&self`, but it needs to modify the cursor. This is also the
37+
// reason for the `Formatter`/`BlockFormatter` split; `BlockFormatter` has
38+
// the operations that involve the mutation, i.e. within the `borrow_mut`.
39+
cursor: RefCell<ResultsCursor<'mir, 'tcx, A>>,
3740
style: OutputStyle,
3841
reachable: BitSet<BasicBlock>,
3942
}
@@ -48,11 +51,15 @@ where
4851
style: OutputStyle,
4952
) -> Self {
5053
let reachable = mir::traversal::reachable_as_bitset(body);
51-
Formatter { body, results: Some(results).into(), style, reachable }
54+
Formatter { cursor: results.into_results_cursor(body).into(), style, reachable }
55+
}
56+
57+
fn body(&self) -> &'mir Body<'tcx> {
58+
self.cursor.borrow().body()
5259
}
5360

5461
pub(crate) fn into_results(self) -> Results<'tcx, A> {
55-
self.results.into_inner().unwrap()
62+
self.cursor.into_inner().into_results()
5663
}
5764
}
5865

@@ -81,7 +88,7 @@ where
8188
type Edge = CfgEdge;
8289

8390
fn graph_id(&self) -> dot::Id<'_> {
84-
let name = graphviz_safe_def_name(self.body.source.def_id());
91+
let name = graphviz_safe_def_name(self.body().source.def_id());
8592
dot::Id::new(format!("graph_for_def_id_{name}")).unwrap()
8693
}
8794

@@ -90,20 +97,11 @@ where
9097
}
9198

9299
fn node_label(&self, block: &Self::Node) -> dot::LabelText<'_> {
93-
let mut label = Vec::new();
94-
self.results.replace_with(|results| {
95-
// `Formatter::result` is a `RefCell<Option<_>>` so we can replace
96-
// the value with `None`, move it into the results cursor, move it
97-
// back out, and return it to the refcell wrapped in `Some`.
98-
let mut fmt = BlockFormatter {
99-
results: results.take().unwrap().into_results_cursor(self.body),
100-
style: self.style,
101-
bg: Background::Light,
102-
};
100+
let mut cursor = self.cursor.borrow_mut();
101+
let mut fmt =
102+
BlockFormatter { cursor: &mut cursor, style: self.style, bg: Background::Light };
103+
let label = fmt.write_node_label(*block).unwrap();
103104

104-
fmt.write_node_label(&mut label, *block).unwrap();
105-
Some(fmt.results.into_results())
106-
});
107105
dot::LabelText::html(String::from_utf8(label).unwrap())
108106
}
109107

@@ -112,20 +110,20 @@ where
112110
}
113111

114112
fn edge_label(&self, e: &Self::Edge) -> dot::LabelText<'_> {
115-
let label = &self.body[e.source].terminator().kind.fmt_successor_labels()[e.index];
113+
let label = &self.body()[e.source].terminator().kind.fmt_successor_labels()[e.index];
116114
dot::LabelText::label(label.clone())
117115
}
118116
}
119117

120-
impl<'mir, 'tcx, A> dot::GraphWalk<'mir> for Formatter<'mir, 'tcx, A>
118+
impl<'tcx, A> dot::GraphWalk<'_> for Formatter<'_, 'tcx, A>
121119
where
122120
A: Analysis<'tcx>,
123121
{
124122
type Node = BasicBlock;
125123
type Edge = CfgEdge;
126124

127125
fn nodes(&self) -> dot::Nodes<'_, Self::Node> {
128-
self.body
126+
self.body()
129127
.basic_blocks
130128
.indices()
131129
.filter(|&idx| self.reachable.contains(idx))
@@ -134,10 +132,10 @@ where
134132
}
135133

136134
fn edges(&self) -> dot::Edges<'_, Self::Edge> {
137-
self.body
138-
.basic_blocks
135+
let body = self.body();
136+
body.basic_blocks
139137
.indices()
140-
.flat_map(|bb| dataflow_successors(self.body, bb))
138+
.flat_map(|bb| dataflow_successors(body, bb))
141139
.collect::<Vec<_>>()
142140
.into()
143141
}
@@ -147,20 +145,20 @@ where
147145
}
148146

149147
fn target(&self, edge: &Self::Edge) -> Self::Node {
150-
self.body[edge.source].terminator().successors().nth(edge.index).unwrap()
148+
self.body()[edge.source].terminator().successors().nth(edge.index).unwrap()
151149
}
152150
}
153151

154-
struct BlockFormatter<'mir, 'tcx, A>
152+
struct BlockFormatter<'a, 'mir, 'tcx, A>
155153
where
156154
A: Analysis<'tcx>,
157155
{
158-
results: ResultsCursor<'mir, 'tcx, A>,
156+
cursor: &'a mut ResultsCursor<'mir, 'tcx, A>,
159157
bg: Background,
160158
style: OutputStyle,
161159
}
162160

163-
impl<'mir, 'tcx, A> BlockFormatter<'mir, 'tcx, A>
161+
impl<'tcx, A> BlockFormatter<'_, '_, 'tcx, A>
164162
where
165163
A: Analysis<'tcx>,
166164
A::Domain: DebugWithContext<A>,
@@ -173,7 +171,9 @@ where
173171
bg
174172
}
175173

176-
fn write_node_label(&mut self, w: &mut impl io::Write, block: BasicBlock) -> io::Result<()> {
174+
fn write_node_label(&mut self, block: BasicBlock) -> io::Result<Vec<u8>> {
175+
use std::io::Write;
176+
177177
// Sample output:
178178
// +-+-----------------------------------------------+
179179
// A | bb4 |
@@ -200,6 +200,9 @@ where
200200
// attributes. Make sure to test the output before trying to remove the redundancy.
201201
// Notably, `align` was found to have no effect when applied only to <table>.
202202

203+
let mut v = vec![];
204+
let w = &mut v;
205+
203206
let table_fmt = concat!(
204207
" border=\"1\"",
205208
" cellborder=\"1\"",
@@ -219,21 +222,21 @@ where
219222

220223
// C: State at start of block
221224
self.bg = Background::Light;
222-
self.results.seek_to_block_start(block);
223-
let block_start_state = self.results.get().clone();
225+
self.cursor.seek_to_block_start(block);
226+
let block_start_state = self.cursor.get().clone();
224227
self.write_row_with_full_state(w, "", "(on start)")?;
225228

226229
// D + E: Statement and terminator transfer functions
227230
self.write_statements_and_terminator(w, block)?;
228231

229232
// F: State at end of block
230233

231-
let terminator = self.results.body()[block].terminator();
234+
let terminator = self.cursor.body()[block].terminator();
232235

233236
// Write the full dataflow state immediately after the terminator if it differs from the
234237
// state at block entry.
235-
self.results.seek_to_block_end(block);
236-
if self.results.get() != &block_start_state || A::Direction::IS_BACKWARD {
238+
self.cursor.seek_to_block_end(block);
239+
if self.cursor.get() != &block_start_state || A::Direction::IS_BACKWARD {
237240
let after_terminator_name = match terminator.kind {
238241
mir::TerminatorKind::Call { target: Some(_), .. } => "(on unwind)",
239242
_ => "(on end)",
@@ -250,8 +253,8 @@ where
250253
match terminator.kind {
251254
mir::TerminatorKind::Call { destination, .. } => {
252255
self.write_row(w, "", "(on successful return)", |this, w, fmt| {
253-
let state_on_unwind = this.results.get().clone();
254-
this.results.apply_custom_effect(|analysis, state| {
256+
let state_on_unwind = this.cursor.get().clone();
257+
this.cursor.apply_custom_effect(|analysis, state| {
255258
analysis.apply_call_return_effect(
256259
state,
257260
block,
@@ -265,18 +268,18 @@ where
265268
colspan = this.style.num_state_columns(),
266269
fmt = fmt,
267270
diff = diff_pretty(
268-
this.results.get(),
271+
this.cursor.get(),
269272
&state_on_unwind,
270-
this.results.analysis()
273+
this.cursor.analysis()
271274
),
272275
)
273276
})?;
274277
}
275278

276279
mir::TerminatorKind::Yield { resume, resume_arg, .. } => {
277280
self.write_row(w, "", "(on yield resume)", |this, w, fmt| {
278-
let state_on_coroutine_drop = this.results.get().clone();
279-
this.results.apply_custom_effect(|analysis, state| {
281+
let state_on_coroutine_drop = this.cursor.get().clone();
282+
this.cursor.apply_custom_effect(|analysis, state| {
280283
analysis.apply_call_return_effect(
281284
state,
282285
resume,
@@ -290,9 +293,9 @@ where
290293
colspan = this.style.num_state_columns(),
291294
fmt = fmt,
292295
diff = diff_pretty(
293-
this.results.get(),
296+
this.cursor.get(),
294297
&state_on_coroutine_drop,
295-
this.results.analysis()
298+
this.cursor.analysis()
296299
),
297300
)
298301
})?;
@@ -302,8 +305,8 @@ where
302305
if !targets.is_empty() =>
303306
{
304307
self.write_row(w, "", "(on successful return)", |this, w, fmt| {
305-
let state_on_unwind = this.results.get().clone();
306-
this.results.apply_custom_effect(|analysis, state| {
308+
let state_on_unwind = this.cursor.get().clone();
309+
this.cursor.apply_custom_effect(|analysis, state| {
307310
analysis.apply_call_return_effect(
308311
state,
309312
block,
@@ -317,9 +320,9 @@ where
317320
colspan = this.style.num_state_columns(),
318321
fmt = fmt,
319322
diff = diff_pretty(
320-
this.results.get(),
323+
this.cursor.get(),
321324
&state_on_unwind,
322-
this.results.analysis()
325+
this.cursor.analysis()
323326
),
324327
)
325328
})?;
@@ -328,7 +331,9 @@ where
328331
_ => {}
329332
};
330333

331-
write!(w, "</table>")
334+
write!(w, "</table>")?;
335+
336+
Ok(v)
332337
}
333338

334339
fn write_block_header_simple(
@@ -407,9 +412,9 @@ where
407412
block: BasicBlock,
408413
) -> io::Result<()> {
409414
let diffs = StateDiffCollector::run(
410-
self.results.body(),
415+
self.cursor.body(),
411416
block,
412-
self.results.mut_results(),
417+
self.cursor.mut_results(),
413418
self.style,
414419
);
415420

@@ -420,7 +425,7 @@ where
420425
if A::Direction::IS_FORWARD { it.next().unwrap() } else { it.next_back().unwrap() }
421426
};
422427

423-
for (i, statement) in self.results.body()[block].statements.iter().enumerate() {
428+
for (i, statement) in self.cursor.body()[block].statements.iter().enumerate() {
424429
let statement_str = format!("{statement:?}");
425430
let index_str = format!("{i}");
426431

@@ -442,7 +447,7 @@ where
442447
assert!(diffs_after.is_empty());
443448
assert!(diffs_before.as_ref().map_or(true, ExactSizeIterator::is_empty));
444449

445-
let terminator = self.results.body()[block].terminator();
450+
let terminator = self.cursor.body()[block].terminator();
446451
let mut terminator_str = String::new();
447452
terminator.kind.fmt_head(&mut terminator_str).unwrap();
448453

@@ -492,8 +497,8 @@ where
492497
mir: &str,
493498
) -> io::Result<()> {
494499
self.write_row(w, i, mir, |this, w, fmt| {
495-
let state = this.results.get();
496-
let analysis = this.results.analysis();
500+
let state = this.cursor.get();
501+
let analysis = this.cursor.analysis();
497502

498503
// FIXME: The full state vector can be quite long. It would be nice to split on commas
499504
// and use some text wrapping algorithm.

0 commit comments

Comments
 (0)