]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/mir/generic_graph.rs
Rollup merge of #87440 - twetzel59:fix-barrier-no-op, r=yaahc
[rust.git] / compiler / rustc_middle / src / mir / generic_graph.rs
1 use gsgdt::{Edge, Graph, Node, NodeStyle};
2 use rustc_hir::def_id::DefId;
3 use rustc_middle::mir::*;
4 use rustc_middle::ty::TyCtxt;
5
6 /// Convert an MIR function into a gsgdt Graph
7 pub fn mir_fn_to_generic_graph<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Graph {
8     let def_id = body.source.def_id();
9     let def_name = graphviz_safe_def_name(def_id);
10     let graph_name = format!("Mir_{}", def_name);
11     let dark_mode = tcx.sess.opts.debugging_opts.graphviz_dark_mode;
12
13     // Nodes
14     let nodes: Vec<Node> = body
15         .basic_blocks()
16         .iter_enumerated()
17         .map(|(block, _)| bb_to_graph_node(block, body, dark_mode))
18         .collect();
19
20     // Edges
21     let mut edges = Vec::new();
22     for (source, _) in body.basic_blocks().iter_enumerated() {
23         let def_id = body.source.def_id();
24         let terminator = body[source].terminator();
25         let labels = terminator.kind.fmt_successor_labels();
26
27         for (&target, label) in terminator.successors().zip(labels) {
28             let src = node(def_id, source);
29             let trg = node(def_id, target);
30             edges.push(Edge::new(src, trg, label.to_string()));
31         }
32     }
33
34     Graph::new(graph_name, nodes, edges)
35 }
36
37 fn bb_to_graph_node(block: BasicBlock, body: &Body<'_>, dark_mode: bool) -> Node {
38     let def_id = body.source.def_id();
39     let data = &body[block];
40     let label = node(def_id, block);
41
42     let (title, bgcolor) = if data.is_cleanup {
43         let color = if dark_mode { "royalblue" } else { "lightblue" };
44         (format!("{} (cleanup)", block.index()), color)
45     } else {
46         let color = if dark_mode { "dimgray" } else { "gray" };
47         (format!("{}", block.index()), color)
48     };
49
50     let style = NodeStyle { title_bg: Some(bgcolor.to_owned()), ..Default::default() };
51     let mut stmts: Vec<String> = data.statements.iter().map(|x| format!("{:?}", x)).collect();
52
53     // add the terminator to the stmts, gsgdt can print it out seperately
54     let mut terminator_head = String::new();
55     data.terminator().kind.fmt_head(&mut terminator_head).unwrap();
56     stmts.push(terminator_head);
57
58     Node::new(stmts, label, title, style)
59 }
60
61 // Must match `[0-9A-Za-z_]*`. This does not appear in the rendered graph, so
62 // it does not have to be user friendly.
63 pub fn graphviz_safe_def_name(def_id: DefId) -> String {
64     format!("{}_{}", def_id.krate.index(), def_id.index.index(),)
65 }
66
67 fn node(def_id: DefId, block: BasicBlock) -> String {
68     format!("bb{}__{}", block.index(), graphviz_safe_def_name(def_id))
69 }