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