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