1+ use gsgdt:: GraphvizSettings ;
12use rustc_graphviz as dot;
23use rustc_hir:: def_id:: DefId ;
3- use rustc_index:: vec:: Idx ;
44use rustc_middle:: mir:: * ;
55use rustc_middle:: ty:: TyCtxt ;
66use std:: fmt:: Debug ;
77use std:: io:: { self , Write } ;
88
9+ use super :: generic_graph:: mir_fn_to_generic_graph;
910use super :: pretty:: dump_mir_def_ids;
1011
1112/// Write a graphviz DOT graph of a list of MIRs.
3233 Ok ( ( ) )
3334}
3435
35- // Must match `[0-9A-Za-z_]*`. This does not appear in the rendered graph, so
36- // it does not have to be user friendly.
37- pub fn graphviz_safe_def_name ( def_id : DefId ) -> String {
38- format ! ( "{}_{}" , def_id. krate. index( ) , def_id. index. index( ) , )
39- }
40-
4136/// Write a graphviz DOT graph of the MIR.
4237pub fn write_mir_fn_graphviz < ' tcx , W > (
4338 tcx : TyCtxt < ' tcx > ,
@@ -48,12 +43,6 @@ pub fn write_mir_fn_graphviz<'tcx, W>(
4843where
4944 W : Write ,
5045{
51- let def_id = body. source . def_id ( ) ;
52- let kind = if subgraph { "subgraph" } else { "digraph" } ;
53- let cluster = if subgraph { "cluster_" } else { "" } ; // Prints a border around MIR
54- let def_name = graphviz_safe_def_name ( def_id) ;
55- writeln ! ( w, "{} {}Mir_{} {{" , kind, cluster, def_name) ?;
56-
5746 // Global graph properties
5847 let font = format ! ( r#"fontname="{}""# , tcx. sess. opts. debugging_opts. graphviz_font) ;
5948 let mut graph_attrs = vec ! [ & font[ ..] ] ;
@@ -67,168 +56,57 @@ where
6756 content_attrs. push ( r#"fontcolor="white""# ) ;
6857 }
6958
70- writeln ! ( w, r#" graph [{}];"# , graph_attrs. join( " " ) ) ?;
71- let content_attrs_str = content_attrs. join ( " " ) ;
72- writeln ! ( w, r#" node [{}];"# , content_attrs_str) ?;
73- writeln ! ( w, r#" edge [{}];"# , content_attrs_str) ?;
74-
7559 // Graph label
76- write_graph_label ( tcx, body, w) ?;
77-
78- // Nodes
79- for ( block, _) in body. basic_blocks ( ) . iter_enumerated ( ) {
80- write_node ( block, body, dark_mode, w) ?;
81- }
82-
83- // Edges
84- for ( source, _) in body. basic_blocks ( ) . iter_enumerated ( ) {
85- write_edges ( source, body, w) ?;
86- }
87- writeln ! ( w, "}}" )
88- }
89-
90- /// Write a graphviz HTML-styled label for the given basic block, with
91- /// all necessary escaping already performed. (This is suitable for
92- /// emitting directly, as is done in this module, or for use with the
93- /// LabelText::HtmlStr from librustc_graphviz.)
94- ///
95- /// `init` and `fini` are callbacks for emitting additional rows of
96- /// data (using HTML enclosed with `<tr>` in the emitted text).
97- pub fn write_node_label < W : Write , INIT , FINI > (
98- block : BasicBlock ,
99- body : & Body < ' _ > ,
100- dark_mode : bool ,
101- w : & mut W ,
102- num_cols : u32 ,
103- init : INIT ,
104- fini : FINI ,
105- ) -> io:: Result < ( ) >
106- where
107- INIT : Fn ( & mut W ) -> io:: Result < ( ) > ,
108- FINI : Fn ( & mut W ) -> io:: Result < ( ) > ,
109- {
110- let data = & body[ block] ;
111-
112- write ! ( w, r#"<table border="0" cellborder="1" cellspacing="0">"# ) ?;
113-
114- // Basic block number at the top.
115- let ( blk, bgcolor) = if data. is_cleanup {
116- let color = if dark_mode { "royalblue" } else { "lightblue" } ;
117- ( format ! ( "{} (cleanup)" , block. index( ) ) , color)
118- } else {
119- let color = if dark_mode { "dimgray" } else { "gray" } ;
120- ( format ! ( "{}" , block. index( ) ) , color)
60+ let label = get_graph_label ( tcx, body) ;
61+ let g = mir_fn_to_generic_graph ( tcx, body, subgraph) ;
62+ let settings = GraphvizSettings {
63+ graph_attrs : Some ( graph_attrs. join ( " " ) ) ,
64+ node_attrs : Some ( content_attrs. join ( " " ) ) ,
65+ edge_attrs : Some ( content_attrs. join ( " " ) ) ,
66+ graph_label : Some ( label) ,
12167 } ;
122- write ! (
123- w,
124- r#"<tr><td bgcolor="{bgcolor}" {attrs} colspan="{colspan}">{blk}</td></tr>"# ,
125- attrs = r#"align="center""# ,
126- colspan = num_cols,
127- blk = blk,
128- bgcolor = bgcolor
129- ) ?;
130-
131- init ( w) ?;
132-
133- // List of statements in the middle.
134- if !data. statements . is_empty ( ) {
135- write ! ( w, r#"<tr><td align="left" balign="left">"# ) ?;
136- for statement in & data. statements {
137- write ! ( w, "{}<br/>" , escape( statement) ) ?;
138- }
139- write ! ( w, "</td></tr>" ) ?;
140- }
141-
142- // Terminator head at the bottom, not including the list of successor blocks. Those will be
143- // displayed as labels on the edges between blocks.
144- let mut terminator_head = String :: new ( ) ;
145- data. terminator ( ) . kind . fmt_head ( & mut terminator_head) . unwrap ( ) ;
146- write ! ( w, r#"<tr><td align="left">{}</td></tr>"# , dot:: escape_html( & terminator_head) ) ?;
147-
148- fini ( w) ?;
149-
150- // Close the table
151- write ! ( w, "</table>" )
152- }
153-
154- /// Write a graphviz DOT node for the given basic block.
155- fn write_node < W : Write > (
156- block : BasicBlock ,
157- body : & Body < ' _ > ,
158- dark_mode : bool ,
159- w : & mut W ,
160- ) -> io:: Result < ( ) > {
161- let def_id = body. source . def_id ( ) ;
162- // Start a new node with the label to follow, in one of DOT's pseudo-HTML tables.
163- write ! ( w, r#" {} [shape="none", label=<"# , node( def_id, block) ) ?;
164- write_node_label ( block, body, dark_mode, w, 1 , |_| Ok ( ( ) ) , |_| Ok ( ( ) ) ) ?;
165- // Close the node label and the node itself.
166- writeln ! ( w, ">];" )
167- }
168-
169- /// Write graphviz DOT edges with labels between the given basic block and all of its successors.
170- fn write_edges < W : Write > ( source : BasicBlock , body : & Body < ' _ > , w : & mut W ) -> io:: Result < ( ) > {
171- let def_id = body. source . def_id ( ) ;
172- let terminator = body[ source] . terminator ( ) ;
173- let labels = terminator. kind . fmt_successor_labels ( ) ;
174-
175- for ( & target, label) in terminator. successors ( ) . zip ( labels) {
176- let src = node ( def_id, source) ;
177- let trg = node ( def_id, target) ;
178- writeln ! ( w, r#" {} -> {} [label="{}"];"# , src, trg, label) ?;
179- }
180-
181- Ok ( ( ) )
68+ g. to_dot ( w, & settings)
18269}
18370
18471/// Write the graphviz DOT label for the overall graph. This is essentially a block of text that
18572/// will appear below the graph, showing the type of the `fn` this MIR represents and the types of
18673/// all the variables and temporaries.
187- fn write_graph_label < ' tcx , W : Write > (
188- tcx : TyCtxt < ' tcx > ,
189- body : & Body < ' _ > ,
190- w : & mut W ,
191- ) -> io:: Result < ( ) > {
74+ fn get_graph_label < ' tcx > ( tcx : TyCtxt < ' tcx > , body : & Body < ' _ > ) -> String {
19275 let def_id = body. source . def_id ( ) ;
76+ let mut label: Vec < String > = Vec :: new ( ) ;
19377
194- write ! ( w , " label=< fn {}(", dot:: escape_html( & tcx. def_path_str( def_id) ) ) ? ;
78+ label . push ( format ! ( " fn {}(", dot:: escape_html( & tcx. def_path_str( def_id) ) ) ) ;
19579
19680 // fn argument types.
19781 for ( i, arg) in body. args_iter ( ) . enumerate ( ) {
19882 if i > 0 {
199- write ! ( w , ", " ) ? ;
83+ label . push ( ", " . to_owned ( ) ) ;
20084 }
201- write ! ( w , "{:?}: {}" , Place :: from( arg) , escape( & body. local_decls[ arg] . ty) ) ? ;
85+ label . push ( format ! ( "{:?}: {}" , Place :: from( arg) , escape( & body. local_decls[ arg] . ty) ) ) ;
20286 }
20387
204- write ! ( w , ") -> {}" , escape( & body. return_ty( ) ) ) ? ;
205- write ! ( w , r#"<br align="left"/>"# ) ? ;
88+ label . push ( format ! ( ") -> {}" , escape( & body. return_ty( ) ) ) ) ;
89+ label . push ( r#"<br align="left"/>"# . to_owned ( ) ) ;
20690
20791 for local in body. vars_and_temps_iter ( ) {
20892 let decl = & body. local_decls [ local] ;
20993
210- write ! ( w , "let " ) ? ;
94+ label . push ( "let " . to_owned ( ) ) ;
21195 if decl. mutability == Mutability :: Mut {
212- write ! ( w , "mut " ) ? ;
96+ label . push ( "mut " . to_owned ( ) ) ;
21397 }
21498
215- write ! ( w , r#"{:?}: {};<br align="left"/>"# , Place :: from( local) , escape( & decl. ty) ) ? ;
99+ label . push ( format ! ( r#"{:?}: {};<br align="left"/>"# , Place :: from( local) , escape( & decl. ty) ) ) ;
216100 }
217101
218102 for var_debug_info in & body. var_debug_info {
219- write ! (
220- w,
103+ label. push ( format ! (
221104 r#"debug {} => {};<br align="left"/>"# ,
222105 var_debug_info. name,
223106 escape( & var_debug_info. place)
224- ) ? ;
107+ ) ) ;
225108 }
226-
227- writeln ! ( w, ">;" )
228- }
229-
230- fn node ( def_id : DefId , block : BasicBlock ) -> String {
231- format ! ( "bb{}__{}" , block. index( ) , graphviz_safe_def_name( def_id) )
109+ label. join ( "" )
232110}
233111
234112fn escape < T : Debug > ( t : & T ) -> String {
0 commit comments