Update change log
[platform/upstream/gcc48.git] / gcc / graph.c
1 /* Output routines for graphical representation.
2    Copyright (C) 1998-2013 Free Software Foundation, Inc.
3    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
4    Rewritten for DOT output by Steven Bosscher, 2012.
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3.  If not see
20 <http://www.gnu.org/licenses/>.  */
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "diagnostic-core.h" /* for fatal_error */
26 #include "sbitmap.h"
27 #include "basic-block.h"
28 #include "cfgloop.h"
29 #include "graph.h"
30 #include "dumpfile.h"
31 #include "pretty-print.h"
32
33 /* DOT files with the .dot extension are recognized as document templates
34    by a well-known piece of word processing software out of Redmond, WA.
35    Therefore some recommend using the .gv extension instead.  Obstinately
36    ignore that recommendation...  */
37 static const char *const graph_ext = ".dot";
38
39 /* Open a file with MODE for dumping our graph to.
40    Return the file pointer.  */
41 static FILE *
42 open_graph_file (const char *base, const char *mode)
43 {
44   size_t namelen = strlen (base);
45   size_t extlen = strlen (graph_ext) + 1;
46   char *buf = XALLOCAVEC (char, namelen + extlen);
47   FILE *fp;
48
49   memcpy (buf, base, namelen);
50   memcpy (buf + namelen, graph_ext, extlen);
51
52   fp = fopen (buf, mode);
53   if (fp == NULL)
54     fatal_error ("can%'t open %s: %m", buf);
55
56   return fp;
57 }
58
59 /* Return a pretty-print buffer for output to file FP.  */
60
61 static pretty_printer *
62 init_graph_slim_pretty_print (FILE *fp)
63 {
64   static bool initialized = false;
65   static pretty_printer graph_slim_pp;
66
67   if (! initialized)
68     {
69       pp_construct (&graph_slim_pp, /*prefix=*/NULL, /*linewidth=*/0);
70       initialized = true;
71     }
72   else
73     gcc_assert (! pp_last_position_in_text (&graph_slim_pp));
74
75   graph_slim_pp.buffer->stream = fp;
76   return &graph_slim_pp;
77 }
78
79 /* Draw a basic block BB belonging to the function with FUNCDEF_NO
80    as its unique number.  */
81 static void
82 draw_cfg_node (pretty_printer *pp, int funcdef_no, basic_block bb)
83 {
84   const char *shape;
85   const char *fillcolor;
86
87   if (bb->index == ENTRY_BLOCK || bb->index == EXIT_BLOCK)
88     {
89       shape = "Mdiamond";
90       fillcolor = "white";
91     }
92   else
93     {
94       shape = "record";
95       fillcolor =
96         BB_PARTITION (bb) == BB_HOT_PARTITION ? "lightpink"
97         : BB_PARTITION (bb) == BB_COLD_PARTITION ? "lightblue"
98         : "lightgrey";
99     }
100
101   pp_printf (pp,
102              "\tfn_%d_basic_block_%d "
103              "[shape=%s,style=filled,fillcolor=%s,label=\"",
104              funcdef_no, bb->index, shape, fillcolor);
105
106   if (bb->index == ENTRY_BLOCK)
107     pp_string (pp, "ENTRY");
108   else if (bb->index == EXIT_BLOCK)
109     pp_string (pp, "EXIT");
110   else
111     {
112       pp_character (pp, '{');
113       pp_write_text_to_stream (pp);
114       dump_bb_for_graph (pp, bb);
115       pp_character (pp, '}');
116     }
117
118   pp_string (pp, "\"];\n\n");
119   pp_flush (pp);
120 }
121
122 /* Draw all successor edges of a basic block BB belonging to the function
123    with FUNCDEF_NO as its unique number.  */
124 static void
125 draw_cfg_node_succ_edges (pretty_printer *pp, int funcdef_no, basic_block bb)
126 {
127   edge e;
128   edge_iterator ei;
129   FOR_EACH_EDGE (e, ei, bb->succs)
130     {
131       const char *style = "\"solid,bold\"";
132       const char *color = "black";
133       int weight = 10;
134
135       if (e->flags & EDGE_FAKE)
136         {
137           style = "dotted";
138           color = "green";
139           weight = 0;
140         }
141       else if (e->flags & EDGE_DFS_BACK)
142         {
143           style = "\"dotted,bold\"";
144           color = "blue";
145           weight = 10;
146         }
147       else if (e->flags & EDGE_FALLTHRU)
148         {
149           color = "blue";
150           weight = 100;
151         }
152
153       if (e->flags & EDGE_ABNORMAL)
154         color = "red";
155
156       pp_printf (pp,
157                  "\tfn_%d_basic_block_%d:s -> fn_%d_basic_block_%d:n "
158                  "[style=%s,color=%s,weight=%d,constraint=%s];\n",
159                  funcdef_no, e->src->index,
160                  funcdef_no, e->dest->index,
161                  style, color, weight,
162                  (e->flags & (EDGE_FAKE | EDGE_DFS_BACK)) ? "false" : "true");
163     }
164   pp_flush (pp);
165 }
166
167 /* Draw all the basic blocks in the CFG in case loops are not available.
168    First compute a topological order of the blocks to get a good ranking of
169    the nodes.  Then, if any nodes are not reachable from ENTRY, add them at
170    the end.  */
171
172 static void
173 draw_cfg_nodes_no_loops (pretty_printer *pp, struct function *fun)
174 {
175   int *rpo = XNEWVEC (int, n_basic_blocks_for_function (fun));
176   int i, n;
177   sbitmap visited;
178
179   visited = sbitmap_alloc (last_basic_block);
180   bitmap_clear (visited);
181
182   /* FIXME: pre_and_rev_post_order_compute only works if fun == cfun.  */
183   n = pre_and_rev_post_order_compute (NULL, rpo, true);
184   for (i = 0; i < n; i++)
185     {
186       basic_block bb = BASIC_BLOCK (rpo[i]);
187       draw_cfg_node (pp, fun->funcdef_no, bb);
188       bitmap_set_bit (visited, bb->index);
189     }
190   free (rpo);
191
192   if (n != n_basic_blocks_for_function (fun))
193     {
194       /* Some blocks are unreachable.  We still want to dump them.  */
195       basic_block bb;
196       FOR_ALL_BB_FN (bb, fun)
197         if (! bitmap_bit_p (visited, bb->index))
198           draw_cfg_node (pp, fun->funcdef_no, bb);
199     }
200
201   sbitmap_free (visited);
202 }
203
204 /* Draw all the basic blocks in LOOP.  Print the blocks in breath-first
205    order to get a good ranking of the nodes.  This function is recursive:
206    It first prints inner loops, then the body of LOOP itself.  */
207
208 static void
209 draw_cfg_nodes_for_loop (pretty_printer *pp, int funcdef_no,
210                          struct loop *loop)
211 {
212   basic_block *body;
213   unsigned int i;
214   const char *fillcolors[3] = { "grey88", "grey77", "grey66" };
215
216   if (loop->latch != EXIT_BLOCK_PTR)
217     pp_printf (pp,
218                "\tsubgraph cluster_%d_%d {\n"
219                "\tstyle=\"filled\";\n"
220                "\tcolor=\"darkgreen\";\n"
221                "\tfillcolor=\"%s\";\n"
222                "\tlabel=\"loop %d\";\n"
223                "\tlabeljust=l;\n"
224                "\tpenwidth=2;\n",
225                funcdef_no, loop->num,
226                fillcolors[(loop_depth (loop) - 1) % 3],
227                loop->num);
228
229   for (struct loop *inner = loop->inner; inner; inner = inner->next)
230     draw_cfg_nodes_for_loop (pp, funcdef_no, inner);
231
232   if (loop->latch == EXIT_BLOCK_PTR)
233     body = get_loop_body (loop);
234   else
235     body = get_loop_body_in_bfs_order (loop);
236
237   for (i = 0; i < loop->num_nodes; i++)
238     {
239       basic_block bb = body[i];
240       if (bb->loop_father == loop)
241         draw_cfg_node (pp, funcdef_no, bb);
242     }
243
244   free (body);
245
246   if (loop->latch != EXIT_BLOCK_PTR)
247     pp_printf (pp, "\t}\n");
248 }
249
250 /* Draw all the basic blocks in the CFG in case the loop tree is available.
251    All loop bodys are printed in clusters.  */
252
253 static void
254 draw_cfg_nodes (pretty_printer *pp, struct function *fun)
255 {
256   /* ??? This x_current_loops should be enapsulated.  */
257   if (fun->x_current_loops)
258     draw_cfg_nodes_for_loop (pp, fun->funcdef_no,
259                              fun->x_current_loops->tree_root);
260   else
261     draw_cfg_nodes_no_loops (pp, fun);
262 }
263
264 /* Draw all edges in the CFG.  Retreating edges are drawin as not
265    constraining, this makes the layout of the graph better.
266    (??? Calling mark_dfs_back may change the compiler's behavior when
267    dumping, but computing back edges here for ourselves is also not
268    desirable.)  */
269
270 static void
271 draw_cfg_edges (pretty_printer *pp, struct function *fun)
272 {
273   basic_block bb;
274   mark_dfs_back_edges ();
275   FOR_ALL_BB (bb)
276     draw_cfg_node_succ_edges (pp, fun->funcdef_no, bb);
277
278   /* Add an invisible edge from ENTRY to EXIT, to improve the graph layout.  */
279   pp_printf (pp,
280              "\tfn_%d_basic_block_%d:s -> fn_%d_basic_block_%d:n "
281              "[style=\"invis\",constraint=true];\n",
282              fun->funcdef_no, ENTRY_BLOCK,
283              fun->funcdef_no, EXIT_BLOCK);
284   pp_flush (pp);
285 }
286
287 /* Print a graphical representation of the CFG of function FUN.
288    First print all basic blocks.  Draw all edges at the end to get
289    subgraphs right for GraphViz, which requires nodes to be defined
290    before edges to cluster nodes properly.  */
291
292 void
293 print_graph_cfg (const char *base, struct function *fun)
294 {
295   const char *funcname = function_name (fun);
296   FILE *fp = open_graph_file (base, "a");
297   pretty_printer *pp = init_graph_slim_pretty_print (fp);
298   pp_printf (pp, "subgraph \"%s\" {\n"
299                  "\tcolor=\"black\";\n"
300                  "\tlabel=\"%s\";\n",
301                  funcname, funcname);
302   draw_cfg_nodes (pp, fun);
303   draw_cfg_edges (pp, fun);
304   pp_printf (pp, "}\n");
305   pp_flush (pp);
306   fclose (fp);
307 }
308
309 /* Start the dump of a graph.  */
310 static void
311 start_graph_dump (FILE *fp, const char *base)
312 {
313   pretty_printer *pp = init_graph_slim_pretty_print (fp);
314   pp_string (pp, "digraph \"");
315   pp_write_text_to_stream (pp);
316   pp_string (pp, base);
317   pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/false);
318   pp_string (pp, "\" {\n");
319   pp_string (pp, "overlap=false;\n");
320   pp_flush (pp);
321 }
322
323 /* End the dump of a graph.  */
324 static void
325 end_graph_dump (FILE *fp)
326 {
327   fputs ("}\n", fp);
328 }
329
330 /* Similar as clean_dump_file, but this time for graph output files.  */
331 void
332 clean_graph_dump_file (const char *base)
333 {
334   FILE *fp = open_graph_file (base, "w");
335   start_graph_dump (fp, base);
336   fclose (fp);
337 }
338
339
340 /* Do final work on the graph output file.  */
341 void
342 finish_graph_dump_file (const char *base)
343 {
344   FILE *fp = open_graph_file (base, "a");
345   end_graph_dump (fp);
346   fclose (fp);
347 }