1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
  | 
use std::io::{self, Write};
use gsgdt::GraphvizSettings;
use rustc_graphviz as dot;
use super::generic_graph::mir_fn_to_generic_graph;
use super::pretty::dump_mir_def_ids;
use crate::mir::*;
/// Write a graphviz DOT graph of a list of MIRs.
pub fn write_mir_graphviz<W>(tcx: TyCtxt<'_>, single: Option<DefId>, w: &mut W) -> io::Result<()>
where
    W: Write,
{
    let def_ids = dump_mir_def_ids(tcx, single);
    let mirs = def_ids
        .iter()
        .flat_map(|def_id| {
            if tcx.is_const_fn(*def_id) {
                vec![tcx.optimized_mir(*def_id), tcx.mir_for_ctfe(*def_id)]
            } else {
                vec![tcx.instance_mir(ty::InstanceKind::Item(*def_id))]
            }
        })
        .collect::<Vec<_>>();
    let use_subgraphs = mirs.len() > 1;
    if use_subgraphs {
        writeln!(w, "digraph __crate__ {{")?;
    }
    for mir in mirs {
        write_mir_fn_graphviz(tcx, mir, use_subgraphs, w)?;
    }
    if use_subgraphs {
        writeln!(w, "}}")?;
    }
    Ok(())
}
/// Write a graphviz DOT graph of the MIR.
pub fn write_mir_fn_graphviz<'tcx, W>(
    tcx: TyCtxt<'tcx>,
    body: &Body<'_>,
    subgraph: bool,
    w: &mut W,
) -> io::Result<()>
where
    W: Write,
{
    // Global graph properties
    let font = format!(r#"fontname="{}""#, tcx.sess.opts.unstable_opts.graphviz_font);
    let mut graph_attrs = vec![&font[..]];
    let mut content_attrs = vec![&font[..]];
    let dark_mode = tcx.sess.opts.unstable_opts.graphviz_dark_mode;
    if dark_mode {
        graph_attrs.push(r#"bgcolor="black""#);
        graph_attrs.push(r#"fontcolor="white""#);
        content_attrs.push(r#"color="white""#);
        content_attrs.push(r#"fontcolor="white""#);
    }
    // Graph label
    let mut label = String::from("");
    // FIXME: remove this unwrap
    write_graph_label(tcx, body, &mut label).unwrap();
    let g = mir_fn_to_generic_graph(tcx, body);
    let settings = GraphvizSettings {
        graph_attrs: Some(graph_attrs.join(" ")),
        node_attrs: Some(content_attrs.join(" ")),
        edge_attrs: Some(content_attrs.join(" ")),
        graph_label: Some(label),
    };
    g.to_dot(w, &settings, subgraph)
}
/// Write the graphviz DOT label for the overall graph. This is essentially a block of text that
/// will appear below the graph, showing the type of the `fn` this MIR represents and the types of
/// all the variables and temporaries.
fn write_graph_label<'tcx, W: std::fmt::Write>(
    tcx: TyCtxt<'tcx>,
    body: &Body<'_>,
    w: &mut W,
) -> std::fmt::Result {
    let def_id = body.source.def_id();
    write!(w, "fn {}(", dot::escape_html(&tcx.def_path_str(def_id)))?;
    // fn argument types.
    for (i, arg) in body.args_iter().enumerate() {
        if i > 0 {
            write!(w, ", ")?;
        }
        write!(w, "{:?}: {}", Place::from(arg), escape(&body.local_decls[arg].ty))?;
    }
    write!(w, ") -> {}", escape(&body.return_ty()))?;
    write!(w, r#"<br align="left"/>"#)?;
    for local in body.vars_and_temps_iter() {
        let decl = &body.local_decls[local];
        write!(w, "let ")?;
        if decl.mutability.is_mut() {
            write!(w, "mut ")?;
        }
        write!(w, r#"{:?}: {};<br align="left"/>"#, Place::from(local), escape(&decl.ty))?;
    }
    for var_debug_info in &body.var_debug_info {
        write!(
            w,
            r#"debug {} => {};<br align="left"/>"#,
            var_debug_info.name,
            escape(&var_debug_info.value),
        )?;
    }
    Ok(())
}
fn escape<T: Debug>(t: &T) -> String {
    dot::escape_html(&format!("{t:?}"))
}
 
  |