1 use gsgdt
::{Edge, Graph, Node, NodeStyle}
;
2 use rustc_hir
::def_id
::DefId
;
3 use rustc_index
::vec
::Idx
;
4 use rustc_middle
::mir
::*;
5 use rustc_middle
::ty
::TyCtxt
;
7 /// Convert an MIR function into a gsgdt Graph
8 pub fn mir_fn_to_generic_graph
<'tcx
>(tcx
: TyCtxt
<'tcx
>, body
: &Body
<'_
>) -> Graph
{
9 let def_id
= body
.source
.def_id();
10 let def_name
= graphviz_safe_def_name(def_id
);
11 let graph_name
= format
!("Mir_{}", def_name
);
12 let dark_mode
= tcx
.sess
.opts
.debugging_opts
.graphviz_dark_mode
;
15 let nodes
: Vec
<Node
> = body
18 .map(|(block
, _
)| bb_to_graph_node(block
, body
, dark_mode
))
22 let mut edges
= Vec
::new();
23 for (source
, _
) in body
.basic_blocks().iter_enumerated() {
24 let def_id
= body
.source
.def_id();
25 let terminator
= body
[source
].terminator();
26 let labels
= terminator
.kind
.fmt_successor_labels();
28 for (&target
, label
) in terminator
.successors().zip(labels
) {
29 let src
= node(def_id
, source
);
30 let trg
= node(def_id
, target
);
31 edges
.push(Edge
::new(src
, trg
, label
.to_string()));
35 Graph
::new(graph_name
, nodes
, edges
)
38 fn bb_to_graph_node(block
: BasicBlock
, body
: &Body
<'_
>, dark_mode
: bool
) -> Node
{
39 let def_id
= body
.source
.def_id();
40 let data
= &body
[block
];
41 let label
= node(def_id
, block
);
43 let (title
, bgcolor
) = if data
.is_cleanup
{
44 let color
= if dark_mode { "royalblue" }
else { "lightblue" }
;
45 (format
!("{} (cleanup)", block
.index()), color
)
47 let color
= if dark_mode { "dimgray" }
else { "gray" }
;
48 (format
!("{}", block
.index()), color
)
51 let style
= NodeStyle { title_bg: Some(bgcolor.to_owned()), ..Default::default() }
;
52 let mut stmts
: Vec
<String
> = data
.statements
.iter().map(|x
| format
!("{:?}", x
)).collect();
54 // add the terminator to the stmts, gsgdt can print it out seperately
55 let mut terminator_head
= String
::new();
56 data
.terminator().kind
.fmt_head(&mut terminator_head
).unwrap();
57 stmts
.push(terminator_head
);
59 Node
::new(stmts
, label
, title
, style
)
62 // Must match `[0-9A-Za-z_]*`. This does not appear in the rendered graph, so
63 // it does not have to be user friendly.
64 pub fn graphviz_safe_def_name(def_id
: DefId
) -> String
{
65 format
!("{}_{}", def_id
.krate
.index(), def_id
.index
.index(),)
68 fn node(def_id
: DefId
, block
: BasicBlock
) -> String
{
69 format
!("bb{}__{}", block
.index(), graphviz_safe_def_name(def_id
))