Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 483ee1f

Browse files
committed
Add a -Zdump-drop-tracking-cfg debugging flag
This is useful for debugging drop-tracking; previously, you had to recompile rustc from source and manually add a call to `write_graph_to_file`. This makes the option more discoverable and configurable at runtime. I also took the liberty of making the labels for the CFG nodes much easier to read: previously, they looked like `id(2), local_id: 48`, now they look like ``` expr from_config (hir_id=HirId { owner: DefId(0:10 ~ default_struct_update[79f9]::foo), local_id: 2}) ```
1 parent 0e1a6fb commit 483ee1f

File tree

4 files changed

+33
-19
lines changed

4 files changed

+33
-19
lines changed

compiler/rustc_interface/src/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,7 @@ fn test_debugging_options_tracking_hash() {
649649
untracked!(dlltool, Some(PathBuf::from("custom_dlltool.exe")));
650650
untracked!(dont_buffer_diagnostics, true);
651651
untracked!(dump_dep_graph, true);
652+
untracked!(dump_drop_tracking_cfg, Some("cfg.dot".to_string()));
652653
untracked!(dump_mir, Some(String::from("abc")));
653654
untracked!(dump_mir_dataflow, true);
654655
untracked!(dump_mir_dir, String::from("abc"));

compiler/rustc_session/src/options.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,6 +1245,8 @@ options! {
12451245
dump_dep_graph: bool = (false, parse_bool, [UNTRACKED],
12461246
"dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv) \
12471247
(default: no)"),
1248+
dump_drop_tracking_cfg: Option<String> = (None, parse_opt_string, [UNTRACKED],
1249+
"dump drop-tracking control-flow graph as a `.dot` file (default: no)"),
12481250
dump_mir: Option<String> = (None, parse_opt_string, [UNTRACKED],
12491251
"dump MIR state to file.
12501252
`val` is used to select which passes and functions to dump. For example:

compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ pub(super) fn build_control_flow_graph<'tcx>(
3333
intravisit::walk_body(&mut drop_range_visitor, body);
3434

3535
drop_range_visitor.drop_ranges.process_deferred_edges();
36+
if let Some(filename) = &tcx.sess.opts.debugging_opts.dump_drop_tracking_cfg {
37+
super::cfg_visualize::write_graph_to_file(&drop_range_visitor.drop_ranges, filename, tcx);
38+
}
3639

3740
(drop_range_visitor.drop_ranges, drop_range_visitor.places.borrowed_temporaries)
3841
}

compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_visualize.rs

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,43 @@
22
//! flow graph when needed for debugging.
33
44
use rustc_graphviz as dot;
5+
use rustc_middle::ty::TyCtxt;
56

67
use super::{DropRangesBuilder, PostOrderId};
78

89
/// Writes the CFG for DropRangesBuilder to a .dot file for visualization.
910
///
1011
/// It is not normally called, but is kept around to easily add debugging
1112
/// code when needed.
12-
#[allow(dead_code)]
13-
pub(super) fn write_graph_to_file(drop_ranges: &DropRangesBuilder, filename: &str) {
14-
dot::render(drop_ranges, &mut std::fs::File::create(filename).unwrap()).unwrap();
13+
pub(super) fn write_graph_to_file(
14+
drop_ranges: &DropRangesBuilder,
15+
filename: &str,
16+
tcx: TyCtxt<'_>,
17+
) {
18+
dot::render(
19+
&DropRangesGraph { drop_ranges, tcx },
20+
&mut std::fs::File::create(filename).unwrap(),
21+
)
22+
.unwrap();
1523
}
1624

17-
impl<'a> dot::GraphWalk<'a> for DropRangesBuilder {
25+
struct DropRangesGraph<'a, 'tcx> {
26+
drop_ranges: &'a DropRangesBuilder,
27+
tcx: TyCtxt<'tcx>,
28+
}
29+
30+
impl<'a> dot::GraphWalk<'a> for DropRangesGraph<'_, '_> {
1831
type Node = PostOrderId;
1932

2033
type Edge = (PostOrderId, PostOrderId);
2134

2235
fn nodes(&'a self) -> dot::Nodes<'a, Self::Node> {
23-
self.nodes.iter_enumerated().map(|(i, _)| i).collect()
36+
self.drop_ranges.nodes.iter_enumerated().map(|(i, _)| i).collect()
2437
}
2538

2639
fn edges(&'a self) -> dot::Edges<'a, Self::Edge> {
27-
self.nodes
40+
self.drop_ranges
41+
.nodes
2842
.iter_enumerated()
2943
.flat_map(|(i, node)| {
3044
if node.successors.len() == 0 {
@@ -45,7 +59,7 @@ impl<'a> dot::GraphWalk<'a> for DropRangesBuilder {
4559
}
4660
}
4761

48-
impl<'a> dot::Labeller<'a> for DropRangesBuilder {
62+
impl<'a> dot::Labeller<'a> for DropRangesGraph<'_, '_> {
4963
type Node = PostOrderId;
5064

5165
type Edge = (PostOrderId, PostOrderId);
@@ -60,18 +74,12 @@ impl<'a> dot::Labeller<'a> for DropRangesBuilder {
6074

6175
fn node_label(&'a self, n: &Self::Node) -> dot::LabelText<'a> {
6276
dot::LabelText::LabelStr(
63-
format!(
64-
"{:?}, local_id: {}",
65-
n,
66-
self.post_order_map
67-
.iter()
68-
.find(|(_hir_id, &post_order_id)| post_order_id == *n)
69-
.map_or("<unknown>".into(), |(hir_id, _)| format!(
70-
"{}",
71-
hir_id.local_id.index()
72-
))
73-
)
74-
.into(),
77+
self.drop_ranges
78+
.post_order_map
79+
.iter()
80+
.find(|(_hir_id, &post_order_id)| post_order_id == *n)
81+
.map_or("<unknown>".into(), |(hir_id, _)| self.tcx.hir().node_to_string(*hir_id))
82+
.into(),
7583
)
7684
}
7785
}

0 commit comments

Comments
 (0)