]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/graph.c
Allow automatics in equivalences
[thirdparty/gcc.git] / gcc / graph.c
CommitLineData
3eaf50a4 1/* Output routines for graphical representation.
fbd26352 2 Copyright (C) 1998-2019 Free Software Foundation, Inc.
3eaf50a4 3 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
f4b3647a 4 Rewritten for DOT output by Steven Bosscher, 2012.
3eaf50a4 5
f12b58b3 6This file is part of GCC.
3eaf50a4 7
f12b58b3 8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
8c4c00c1 10Software Foundation; either version 3, or (at your option) any later
f12b58b3 11version.
3eaf50a4 12
f12b58b3 13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
3eaf50a4 17
f060a027 18You should have received a copy of the GNU General Public License
8c4c00c1 19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
3eaf50a4 21
967958e4 22#include "config.h"
3eaf50a4 23#include "system.h"
805e22b2 24#include "coretypes.h"
9ef16211 25#include "backend.h"
7c29e30e 26#include "cfghooks.h"
27#include "pretty-print.h"
28#include "diagnostic-core.h" /* for fatal_error */
94ea8568 29#include "cfganal.h"
a1877047 30#include "cfgloop.h"
e5bd1365 31#include "graph.h"
2b5a3065 32#include "dumpfile.h"
3eaf50a4 33
f4b3647a 34/* DOT files with the .dot extension are recognized as document templates
35 by a well-known piece of word processing software out of Redmond, WA.
36 Therefore some recommend using the .gv extension instead. Obstinately
a1877047 37 ignore that recommendation... */
f4b3647a 38static const char *const graph_ext = ".dot";
d0c03912 39
f4b3647a 40/* Open a file with MODE for dumping our graph to.
41 Return the file pointer. */
42static FILE *
43open_graph_file (const char *base, const char *mode)
3eaf50a4 44{
f4b3647a 45 size_t namelen = strlen (base);
46 size_t extlen = strlen (graph_ext) + 1;
47 char *buf = XALLOCAVEC (char, namelen + extlen);
48 FILE *fp;
3eaf50a4 49
f4b3647a 50 memcpy (buf, base, namelen);
51 memcpy (buf + namelen, graph_ext, extlen);
3eaf50a4 52
f4b3647a 53 fp = fopen (buf, mode);
54 if (fp == NULL)
62c34df8 55 fatal_error (input_location, "cannot open %s: %m", buf);
3eaf50a4 56
f4b3647a 57 return fp;
3eaf50a4 58}
59
62c34df8 60/* Disable warnings about quoting issues in the pp_xxx calls below
61 that (intentionally) don't follow GCC diagnostic conventions. */
62#if __GNUC__ >= 10
63# pragma GCC diagnostic push
64# pragma GCC diagnostic ignored "-Wformat-diag"
65#endif
66
e079344a 67/* Draw a basic block BB belonging to the function with FUNCDEF_NO
f4b3647a 68 as its unique number. */
69static void
e079344a 70draw_cfg_node (pretty_printer *pp, int funcdef_no, basic_block bb)
f4b3647a 71{
f4b3647a 72 const char *shape;
73 const char *fillcolor;
3eaf50a4 74
f4b3647a 75 if (bb->index == ENTRY_BLOCK || bb->index == EXIT_BLOCK)
3eaf50a4 76 {
f4b3647a 77 shape = "Mdiamond";
78 fillcolor = "white";
3eaf50a4 79 }
3eaf50a4 80 else
3eaf50a4 81 {
f4b3647a 82 shape = "record";
83 fillcolor =
84 BB_PARTITION (bb) == BB_HOT_PARTITION ? "lightpink"
85 : BB_PARTITION (bb) == BB_COLD_PARTITION ? "lightblue"
86 : "lightgrey";
3eaf50a4 87 }
3eaf50a4 88
3d9a4504 89 pp_printf (pp,
90 "\tfn_%d_basic_block_%d "
91 "[shape=%s,style=filled,fillcolor=%s,label=\"",
e079344a 92 funcdef_no, bb->index, shape, fillcolor);
3eaf50a4 93
f4b3647a 94 if (bb->index == ENTRY_BLOCK)
3d9a4504 95 pp_string (pp, "ENTRY");
f4b3647a 96 else if (bb->index == EXIT_BLOCK)
3d9a4504 97 pp_string (pp, "EXIT");
f4b3647a 98 else
3eaf50a4 99 {
dda4f0ec 100 pp_left_brace (pp);
3d9a4504 101 pp_write_text_to_stream (pp);
e079344a 102 dump_bb_for_graph (pp, bb);
dda4f0ec 103 pp_right_brace (pp);
3eaf50a4 104 }
f4b3647a 105
3d9a4504 106 pp_string (pp, "\"];\n\n");
107 pp_flush (pp);
3eaf50a4 108}
109
f4b3647a 110/* Draw all successor edges of a basic block BB belonging to the function
e079344a 111 with FUNCDEF_NO as its unique number. */
3eaf50a4 112static void
e079344a 113draw_cfg_node_succ_edges (pretty_printer *pp, int funcdef_no, basic_block bb)
3eaf50a4 114{
f4b3647a 115 edge e;
116 edge_iterator ei;
117 FOR_EACH_EDGE (e, ei, bb->succs)
3eaf50a4 118 {
f4b3647a 119 const char *style = "\"solid,bold\"";
120 const char *color = "black";
121 int weight = 10;
3eaf50a4 122
f4b3647a 123 if (e->flags & EDGE_FAKE)
3eaf50a4 124 {
f4b3647a 125 style = "dotted";
126 color = "green";
127 weight = 0;
3eaf50a4 128 }
f4b3647a 129 else if (e->flags & EDGE_DFS_BACK)
3eaf50a4 130 {
f4b3647a 131 style = "\"dotted,bold\"";
132 color = "blue";
133 weight = 10;
3eaf50a4 134 }
f4b3647a 135 else if (e->flags & EDGE_FALLTHRU)
3eaf50a4 136 {
f4b3647a 137 color = "blue";
138 weight = 100;
3eaf50a4 139 }
140
f4b3647a 141 if (e->flags & EDGE_ABNORMAL)
142 color = "red";
3eaf50a4 143
3d9a4504 144 pp_printf (pp,
145 "\tfn_%d_basic_block_%d:s -> fn_%d_basic_block_%d:n "
3e7a76a6 146 "[style=%s,color=%s,weight=%d,constraint=%s",
e079344a 147 funcdef_no, e->src->index,
148 funcdef_no, e->dest->index,
3d9a4504 149 style, color, weight,
720cfc43 150 (e->flags & (EDGE_FAKE | EDGE_DFS_BACK)) ? "false" : "true");
151 if (e->probability.initialized_p ())
3e7a76a6 152 pp_printf (pp, ",label=\"[%i%%]\"",
720cfc43 153 e->probability.to_reg_br_prob_base ()
154 * 100 / REG_BR_PROB_BASE);
155 pp_printf (pp, "];\n");
3eaf50a4 156 }
3d9a4504 157 pp_flush (pp);
f4b3647a 158}
159
a1877047 160/* Draw all the basic blocks in the CFG in case loops are not available.
161 First compute a topological order of the blocks to get a good ranking of
162 the nodes. Then, if any nodes are not reachable from ENTRY, add them at
163 the end. */
229c964b 164
a1877047 165static void
166draw_cfg_nodes_no_loops (pretty_printer *pp, struct function *fun)
f4b3647a 167{
a28770e1 168 int *rpo = XNEWVEC (int, n_basic_blocks_for_fn (fun));
f4b3647a 169 int i, n;
170
3c6549f8 171 auto_sbitmap visited (last_basic_block_for_fn (cfun));
a1877047 172 bitmap_clear (visited);
f4b3647a 173
f484312f 174 n = pre_and_rev_post_order_compute_fn (fun, NULL, rpo, true);
a28770e1 175 for (i = n_basic_blocks_for_fn (fun) - n;
176 i < n_basic_blocks_for_fn (fun); i++)
a1877047 177 {
f5a6b05f 178 basic_block bb = BASIC_BLOCK_FOR_FN (cfun, rpo[i]);
a1877047 179 draw_cfg_node (pp, fun->funcdef_no, bb);
180 bitmap_set_bit (visited, bb->index);
181 }
182 free (rpo);
f4b3647a 183
a28770e1 184 if (n != n_basic_blocks_for_fn (fun))
a1877047 185 {
186 /* Some blocks are unreachable. We still want to dump them. */
187 basic_block bb;
188 FOR_ALL_BB_FN (bb, fun)
189 if (! bitmap_bit_p (visited, bb->index))
190 draw_cfg_node (pp, fun->funcdef_no, bb);
191 }
a1877047 192}
193
194/* Draw all the basic blocks in LOOP. Print the blocks in breath-first
195 order to get a good ranking of the nodes. This function is recursive:
196 It first prints inner loops, then the body of LOOP itself. */
f4b3647a 197
a1877047 198static void
199draw_cfg_nodes_for_loop (pretty_printer *pp, int funcdef_no,
2e966e2a 200 class loop *loop)
a1877047 201{
202 basic_block *body;
203 unsigned int i;
204 const char *fillcolors[3] = { "grey88", "grey77", "grey66" };
205
cd9916a9 206 if (loop->header != NULL
34154e27 207 && loop->latch != EXIT_BLOCK_PTR_FOR_FN (cfun))
a1877047 208 pp_printf (pp,
209 "\tsubgraph cluster_%d_%d {\n"
210 "\tstyle=\"filled\";\n"
211 "\tcolor=\"darkgreen\";\n"
212 "\tfillcolor=\"%s\";\n"
213 "\tlabel=\"loop %d\";\n"
214 "\tlabeljust=l;\n"
215 "\tpenwidth=2;\n",
216 funcdef_no, loop->num,
217 fillcolors[(loop_depth (loop) - 1) % 3],
218 loop->num);
219
2e966e2a 220 for (class loop *inner = loop->inner; inner; inner = inner->next)
a1877047 221 draw_cfg_nodes_for_loop (pp, funcdef_no, inner);
222
cd9916a9 223 if (loop->header == NULL)
224 return;
225
34154e27 226 if (loop->latch == EXIT_BLOCK_PTR_FOR_FN (cfun))
a1877047 227 body = get_loop_body (loop);
228 else
229 body = get_loop_body_in_bfs_order (loop);
230
231 for (i = 0; i < loop->num_nodes; i++)
232 {
233 basic_block bb = body[i];
234 if (bb->loop_father == loop)
235 draw_cfg_node (pp, funcdef_no, bb);
236 }
237
238 free (body);
239
34154e27 240 if (loop->latch != EXIT_BLOCK_PTR_FOR_FN (cfun))
a1877047 241 pp_printf (pp, "\t}\n");
242}
243
244/* Draw all the basic blocks in the CFG in case the loop tree is available.
245 All loop bodys are printed in clusters. */
246
247static void
248draw_cfg_nodes (pretty_printer *pp, struct function *fun)
249{
41f75a99 250 if (loops_for_fn (fun))
251 draw_cfg_nodes_for_loop (pp, fun->funcdef_no, get_loop (fun, 0));
a1877047 252 else
253 draw_cfg_nodes_no_loops (pp, fun);
254}
255
256/* Draw all edges in the CFG. Retreating edges are drawin as not
c7ef68fd 257 constraining, this makes the layout of the graph better. */
a1877047 258
259static void
260draw_cfg_edges (pretty_printer *pp, struct function *fun)
261{
262 basic_block bb;
c7ef68fd 263
264 /* Save EDGE_DFS_BACK flag to dfs_back. */
265 auto_bitmap dfs_back;
266 edge e;
267 edge_iterator ei;
268 unsigned int idx = 0;
269 FOR_EACH_BB_FN (bb, cfun)
270 FOR_EACH_EDGE (e, ei, bb->succs)
271 {
272 if (e->flags & EDGE_DFS_BACK)
273 bitmap_set_bit (dfs_back, idx);
274 idx++;
275 }
276
f4b3647a 277 mark_dfs_back_edges ();
ed7d889a 278 FOR_ALL_BB_FN (bb, cfun)
a1877047 279 draw_cfg_node_succ_edges (pp, fun->funcdef_no, bb);
280
c7ef68fd 281 /* Restore EDGE_DFS_BACK flag from dfs_back. */
282 idx = 0;
283 FOR_EACH_BB_FN (bb, cfun)
284 FOR_EACH_EDGE (e, ei, bb->succs)
285 {
286 if (bitmap_bit_p (dfs_back, idx))
287 e->flags |= EDGE_DFS_BACK;
288 else
289 e->flags &= ~EDGE_DFS_BACK;
290 idx++;
291 }
292
a1877047 293 /* Add an invisible edge from ENTRY to EXIT, to improve the graph layout. */
294 pp_printf (pp,
295 "\tfn_%d_basic_block_%d:s -> fn_%d_basic_block_%d:n "
296 "[style=\"invis\",constraint=true];\n",
297 fun->funcdef_no, ENTRY_BLOCK,
298 fun->funcdef_no, EXIT_BLOCK);
299 pp_flush (pp);
300}
3eaf50a4 301
a1877047 302/* Print a graphical representation of the CFG of function FUN.
303 First print all basic blocks. Draw all edges at the end to get
304 subgraphs right for GraphViz, which requires nodes to be defined
305 before edges to cluster nodes properly. */
306
2b5a3065 307void DEBUG_FUNCTION
308print_graph_cfg (FILE *fp, struct function *fun)
a1877047 309{
4e765d3c 310 pretty_printer graph_slim_pp;
4e765d3c 311 graph_slim_pp.buffer->stream = fp;
312 pretty_printer *const pp = &graph_slim_pp;
2b5a3065 313 const char *funcname = function_name (fun);
dccaa1c0 314 pp_printf (pp, "subgraph \"cluster_%s\" {\n"
315 "\tstyle=\"dashed\";\n"
316 "\tcolor=\"black\";\n"
317 "\tlabel=\"%s ()\";\n",
a1877047 318 funcname, funcname);
319 draw_cfg_nodes (pp, fun);
320 draw_cfg_edges (pp, fun);
321 pp_printf (pp, "}\n");
3d9a4504 322 pp_flush (pp);
2b5a3065 323}
324
325/* Overload with additional flag argument. */
326
327void DEBUG_FUNCTION
3f6e5ced 328print_graph_cfg (FILE *fp, struct function *fun, dump_flags_t flags)
2b5a3065 329{
3f6e5ced 330 dump_flags_t saved_dump_flags = dump_flags;
2b5a3065 331 dump_flags = flags;
332 print_graph_cfg (fp, fun);
333 dump_flags = saved_dump_flags;
334}
335
336
337/* Print a graphical representation of the CFG of function FUN.
338 First print all basic blocks. Draw all edges at the end to get
339 subgraphs right for GraphViz, which requires nodes to be defined
340 before edges to cluster nodes properly. */
341
342void
343print_graph_cfg (const char *base, struct function *fun)
344{
345 FILE *fp = open_graph_file (base, "a");
346 print_graph_cfg (fp, fun);
3eaf50a4 347 fclose (fp);
348}
349
f4b3647a 350/* Start the dump of a graph. */
351static void
69df7536 352start_graph_dump (FILE *fp, const char *base)
f4b3647a 353{
4e765d3c 354 pretty_printer graph_slim_pp;
4e765d3c 355 graph_slim_pp.buffer->stream = fp;
356 pretty_printer *const pp = &graph_slim_pp;
69df7536 357 pp_string (pp, "digraph \"");
358 pp_write_text_to_stream (pp);
359 pp_string (pp, base);
360 pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/false);
361 pp_string (pp, "\" {\n");
362 pp_string (pp, "overlap=false;\n");
363 pp_flush (pp);
f4b3647a 364}
365
366/* End the dump of a graph. */
367static void
368end_graph_dump (FILE *fp)
369{
370 fputs ("}\n", fp);
371}
3eaf50a4 372
373/* Similar as clean_dump_file, but this time for graph output files. */
374void
0f9005dd 375clean_graph_dump_file (const char *base)
3eaf50a4 376{
f4b3647a 377 FILE *fp = open_graph_file (base, "w");
69df7536 378 start_graph_dump (fp, base);
3eaf50a4 379 fclose (fp);
380}
381
382
383/* Do final work on the graph output file. */
384void
0f9005dd 385finish_graph_dump_file (const char *base)
3eaf50a4 386{
f4b3647a 387 FILE *fp = open_graph_file (base, "a");
388 end_graph_dump (fp);
389 fclose (fp);
3eaf50a4 390}
62c34df8 391
392#if __GNUC__ >= 10
393# pragma GCC diagnostic pop
394#endif