]>
Commit | Line | Data |
---|---|---|
fc512014 | 1 | use gsgdt::GraphvizSettings; |
f035d41b | 2 | use rustc_graphviz as dot; |
dfeec247 | 3 | use rustc_hir::def_id::DefId; |
ba9703b0 | 4 | use rustc_middle::mir::*; |
6a06907d | 5 | use rustc_middle::ty::{self, TyCtxt}; |
9cc50fc6 SL |
6 | use std::fmt::Debug; |
7 | use std::io::{self, Write}; | |
8 | ||
fc512014 | 9 | use super::generic_graph::mir_fn_to_generic_graph; |
7cac9316 XL |
10 | use super::pretty::dump_mir_def_ids; |
11 | ||
54a0048b | 12 | /// Write a graphviz DOT graph of a list of MIRs. |
dfeec247 | 13 | pub fn write_mir_graphviz<W>(tcx: TyCtxt<'_>, single: Option<DefId>, w: &mut W) -> io::Result<()> |
dc9dc135 XL |
14 | where |
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 |
50 | pub 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<()> | |
56 | where | |
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 | 89 | fn 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, ") -> {}", 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 {} => {};<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 | ||
132 | fn escape<T: Debug>(t: &T) -> String { | |
133 | dot::escape_html(&format!("{:?}", t)) | |
134 | } |