]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/graph.c
Fix ada enabled "make html".
[thirdparty/gcc.git] / gcc / graph.c
CommitLineData
735a0e33 1/* Output routines for graphical representation.
d9221e01
KH
2 Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004
3 Free Software Foundation, Inc.
735a0e33
UD
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
5
1322177d 6This file is part of GCC.
735a0e33 7
1322177d
LB
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
10Software Foundation; either version 2, or (at your option) any later
11version.
735a0e33 12
1322177d
LB
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.
735a0e33 17
400500c4 18You should have received a copy of the GNU General Public License
1322177d
LB
19along with GCC; see the file COPYING. If not, write to the Free
20Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2102111-1307, USA. */
735a0e33
UD
22
23#include <config.h>
24#include "system.h"
4977bab6
ZW
25#include "coretypes.h"
26#include "tm.h"
735a0e33
UD
27#include "rtl.h"
28#include "flags.h"
29#include "output.h"
49ad7cfa 30#include "function.h"
735a0e33 31#include "hard-reg-set.h"
7932a3db 32#include "obstack.h"
735a0e33
UD
33#include "basic-block.h"
34#include "toplev.h"
6a2cc2ac 35#include "graph.h"
735a0e33 36
27c38fbe 37static const char *const graph_ext[] =
735a0e33
UD
38{
39 /* no_graph */ "",
40 /* vcg */ ".vcg",
41};
42
1d088dee
AJ
43static void start_fct (FILE *);
44static void start_bb (FILE *, int);
45static void node_data (FILE *, rtx);
46static void draw_edge (FILE *, int, int, int, int);
47static void end_fct (FILE *);
48static void end_bb (FILE *);
5f06c983 49
735a0e33
UD
50/* Output text for new basic block. */
51static void
1d088dee 52start_fct (FILE *fp)
735a0e33 53{
735a0e33
UD
54 switch (graph_dump_format)
55 {
56 case vcg:
57 fprintf (fp, "\
58graph: { title: \"%s\"\nfolding: 1\nhidden: 2\nnode: { title: \"%s.0\" }\n",
faed5cc3 59 current_function_name (), current_function_name ());
735a0e33
UD
60 break;
61 case no_graph:
62 break;
63 }
64}
65
66static void
1d088dee 67start_bb (FILE *fp, int bb)
735a0e33 68{
a2041967
KH
69#if 0
70 reg_set_iterator rsi;
71#endif
72
735a0e33
UD
73 switch (graph_dump_format)
74 {
75 case vcg:
76 fprintf (fp, "\
77graph: {\ntitle: \"%s.BB%d\"\nfolding: 1\ncolor: lightblue\n\
78label: \"basic block %d",
faed5cc3 79 current_function_name (), bb, bb);
735a0e33
UD
80 break;
81 case no_graph:
82 break;
83 }
84
85#if 0
dc297297 86 /* FIXME Should this be printed? It makes the graph significantly larger. */
735a0e33
UD
87
88 /* Print the live-at-start register list. */
89 fputc ('\n', fp);
a2041967
KH
90 EXECUTE_IF_SET_IN_REG_SET (basic_block_live_at_start[bb], 0, i, rsi)
91 {
92 fprintf (fp, " %d", i);
93 if (i < FIRST_PSEUDO_REGISTER)
94 fprintf (fp, " [%s]", reg_names[i]);
95 }
735a0e33
UD
96#endif
97
98 switch (graph_dump_format)
99 {
100 case vcg:
101 fputs ("\"\n\n", fp);
102 break;
103 case no_graph:
104 break;
105 }
106}
107
a30d557c 108static void
1d088dee 109node_data (FILE *fp, rtx tmp_rtx)
735a0e33 110{
735a0e33
UD
111 if (PREV_INSN (tmp_rtx) == 0)
112 {
113 /* This is the first instruction. Add an edge from the starting
114 block. */
115 switch (graph_dump_format)
116 {
117 case vcg:
118 fprintf (fp, "\
119edge: { sourcename: \"%s.0\" targetname: \"%s.%d\" }\n",
faed5cc3
SB
120 current_function_name (),
121 current_function_name (), XINT (tmp_rtx, 0));
735a0e33
UD
122 break;
123 case no_graph:
124 break;
125 }
126 }
127
128 switch (graph_dump_format)
129 {
130 case vcg:
131 fprintf (fp, "node: {\n title: \"%s.%d\"\n color: %s\n \
132label: \"%s %d\n",
faed5cc3 133 current_function_name (), XINT (tmp_rtx, 0),
4b4bf941
JQ
134 NOTE_P (tmp_rtx) ? "lightgrey"
135 : NONJUMP_INSN_P (tmp_rtx) ? "green"
136 : JUMP_P (tmp_rtx) ? "darkgreen"
137 : CALL_P (tmp_rtx) ? "darkgreen"
138 : LABEL_P (tmp_rtx) ? "\
735a0e33
UD
139darkgrey\n shape: ellipse" : "white",
140 GET_RTX_NAME (GET_CODE (tmp_rtx)), XINT (tmp_rtx, 0));
141 break;
142 case no_graph:
143 break;
144 }
145
146 /* Print the RTL. */
4b4bf941 147 if (NOTE_P (tmp_rtx))
735a0e33 148 {
0a2287bf
RH
149 const char *name = "";
150 if (NOTE_LINE_NUMBER (tmp_rtx) < 0)
151 name = GET_NOTE_INSN_NAME (NOTE_LINE_NUMBER (tmp_rtx));
152 fprintf (fp, " %s", name);
735a0e33 153 }
2c3c49de 154 else if (INSN_P (tmp_rtx))
a30d557c 155 print_rtl_single (fp, PATTERN (tmp_rtx));
735a0e33 156 else
a30d557c 157 print_rtl_single (fp, tmp_rtx);
735a0e33
UD
158
159 switch (graph_dump_format)
160 {
161 case vcg:
162 fputs ("\"\n}\n", fp);
163 break;
164 case no_graph:
165 break;
166 }
735a0e33
UD
167}
168
169static void
1d088dee 170draw_edge (FILE *fp, int from, int to, int bb_edge, int class)
735a0e33 171{
5f06c983 172 const char * color;
735a0e33
UD
173 switch (graph_dump_format)
174 {
175 case vcg:
e881bb1b
RH
176 color = "";
177 if (class == 2)
178 color = "color: red ";
179 else if (bb_edge)
180 color = "color: blue ";
181 else if (class == 3)
182 color = "color: green ";
735a0e33
UD
183 fprintf (fp,
184 "edge: { sourcename: \"%s.%d\" targetname: \"%s.%d\" %s",
faed5cc3
SB
185 current_function_name (), from,
186 current_function_name (), to, color);
735a0e33
UD
187 if (class)
188 fprintf (fp, "class: %d ", class);
189 fputs ("}\n", fp);
190 break;
191 case no_graph:
192 break;
193 }
194}
195
196static void
1d088dee 197end_bb (FILE *fp)
735a0e33
UD
198{
199 switch (graph_dump_format)
200 {
201 case vcg:
202 fputs ("}\n", fp);
203 break;
204 case no_graph:
205 break;
206 }
207}
208
209static void
1d088dee 210end_fct (FILE *fp)
735a0e33
UD
211{
212 switch (graph_dump_format)
213 {
214 case vcg:
215 fprintf (fp, "node: { title: \"%s.999999\" label: \"END\" }\n}\n",
faed5cc3 216 current_function_name ());
735a0e33
UD
217 break;
218 case no_graph:
219 break;
220 }
221}
222\f
223/* Like print_rtl, but also print out live information for the start of each
224 basic block. */
225void
9f8628ba 226print_rtl_graph_with_bb (const char *base, rtx rtx_first)
735a0e33 227{
b3694847 228 rtx tmp_rtx;
735a0e33 229 size_t namelen = strlen (base);
735a0e33 230 size_t extlen = strlen (graph_ext[graph_dump_format]) + 1;
9f8628ba 231 char *buf = alloca (namelen + extlen);
735a0e33
UD
232 FILE *fp;
233
e881bb1b
RH
234 if (basic_block_info == NULL)
235 return;
735a0e33
UD
236
237 memcpy (buf, base, namelen);
9f8628ba 238 memcpy (buf + namelen, graph_ext[graph_dump_format], extlen);
735a0e33
UD
239
240 fp = fopen (buf, "a");
241 if (fp == NULL)
242 return;
243
244 if (rtx_first == 0)
245 fprintf (fp, "(nil)\n");
246 else
247 {
735a0e33
UD
248 enum bb_state { NOT_IN_BB, IN_ONE_BB, IN_MULTIPLE_BB };
249 int max_uid = get_max_uid ();
703ad42b
KG
250 int *start = xmalloc (max_uid * sizeof (int));
251 int *end = xmalloc (max_uid * sizeof (int));
252 enum bb_state *in_bb_p = xmalloc (max_uid * sizeof (enum bb_state));
e881bb1b 253 basic_block bb;
e0082a72 254 int i;
735a0e33 255
0b17ab2f 256 for (i = 0; i < max_uid; ++i)
735a0e33 257 {
0b17ab2f
RH
258 start[i] = end[i] = -1;
259 in_bb_p[i] = NOT_IN_BB;
735a0e33
UD
260 }
261
e0082a72 262 FOR_EACH_BB_REVERSE (bb)
735a0e33
UD
263 {
264 rtx x;
a813c111
SB
265 start[INSN_UID (BB_HEAD (bb))] = bb->index;
266 end[INSN_UID (BB_END (bb))] = bb->index;
267 for (x = BB_HEAD (bb); x != NULL_RTX; x = NEXT_INSN (x))
735a0e33
UD
268 {
269 in_bb_p[INSN_UID (x)]
270 = (in_bb_p[INSN_UID (x)] == NOT_IN_BB)
271 ? IN_ONE_BB : IN_MULTIPLE_BB;
a813c111 272 if (x == BB_END (bb))
735a0e33
UD
273 break;
274 }
275 }
276
735a0e33
UD
277 /* Tell print-rtl that we want graph output. */
278 dump_for_graph = 1;
279
280 /* Start new function. */
281 start_fct (fp);
282
283 for (tmp_rtx = NEXT_INSN (rtx_first); NULL != tmp_rtx;
284 tmp_rtx = NEXT_INSN (tmp_rtx))
285 {
735a0e33
UD
286 int edge_printed = 0;
287 rtx next_insn;
288
289 if (start[INSN_UID (tmp_rtx)] < 0 && end[INSN_UID (tmp_rtx)] < 0)
290 {
4b4bf941 291 if (BARRIER_P (tmp_rtx))
735a0e33 292 continue;
4b4bf941 293 if (NOTE_P (tmp_rtx)
735a0e33
UD
294 && (1 || in_bb_p[INSN_UID (tmp_rtx)] == NOT_IN_BB))
295 continue;
296 }
297
0b17ab2f 298 if ((i = start[INSN_UID (tmp_rtx)]) >= 0)
735a0e33
UD
299 {
300 /* We start a subgraph for each basic block. */
0b17ab2f 301 start_bb (fp, i);
735a0e33 302
0b17ab2f 303 if (i == 0)
735a0e33
UD
304 draw_edge (fp, 0, INSN_UID (tmp_rtx), 1, 0);
305 }
306
307 /* Print the data for this node. */
a30d557c 308 node_data (fp, tmp_rtx);
735a0e33
UD
309 next_insn = next_nonnote_insn (tmp_rtx);
310
0b17ab2f 311 if ((i = end[INSN_UID (tmp_rtx)]) >= 0)
735a0e33 312 {
e881bb1b 313 edge e;
628f6a4e 314 edge_iterator ei;
e881bb1b 315
0b17ab2f 316 bb = BASIC_BLOCK (i);
735a0e33
UD
317
318 /* End of the basic block. */
5f06c983 319 end_bb (fp);
735a0e33
UD
320
321 /* Now specify the edges to all the successors of this
322 basic block. */
628f6a4e 323 FOR_EACH_EDGE (e, ei, bb->succs)
735a0e33 324 {
e881bb1b 325 if (e->dest != EXIT_BLOCK_PTR)
735a0e33 326 {
a813c111 327 rtx block_head = BB_HEAD (e->dest);
735a0e33
UD
328
329 draw_edge (fp, INSN_UID (tmp_rtx),
330 INSN_UID (block_head),
e881bb1b
RH
331 next_insn != block_head,
332 (e->flags & EDGE_ABNORMAL ? 2 : 0));
735a0e33 333
e881bb1b 334 if (block_head == next_insn)
735a0e33
UD
335 edge_printed = 1;
336 }
e881bb1b 337 else
735a0e33
UD
338 {
339 draw_edge (fp, INSN_UID (tmp_rtx), 999999,
e881bb1b
RH
340 next_insn != 0,
341 (e->flags & EDGE_ABNORMAL ? 2 : 0));
735a0e33
UD
342
343 if (next_insn == 0)
344 edge_printed = 1;
345 }
735a0e33
UD
346 }
347 }
348
349 if (!edge_printed)
350 {
351 /* Don't print edges to barriers. */
352 if (next_insn == 0
4b4bf941 353 || !BARRIER_P (next_insn))
735a0e33
UD
354 draw_edge (fp, XINT (tmp_rtx, 0),
355 next_insn ? INSN_UID (next_insn) : 999999, 0, 0);
356 else
357 {
e881bb1b
RH
358 /* We draw the remaining edges in class 3. We have
359 to skip over the barrier since these nodes are
735a0e33
UD
360 not printed at all. */
361 do
362 next_insn = NEXT_INSN (next_insn);
363 while (next_insn
4b4bf941
JQ
364 && (NOTE_P (next_insn)
365 || BARRIER_P (next_insn)));
735a0e33
UD
366
367 draw_edge (fp, XINT (tmp_rtx, 0),
e881bb1b 368 next_insn ? INSN_UID (next_insn) : 999999, 0, 3);
735a0e33
UD
369 }
370 }
371 }
372
373 dump_for_graph = 0;
374
375 end_fct (fp);
4da896b2
MM
376
377 /* Clean up. */
378 free (start);
379 free (end);
380 free (in_bb_p);
735a0e33
UD
381 }
382
383 fclose (fp);
384}
385
386
387/* Similar as clean_dump_file, but this time for graph output files. */
400500c4 388
735a0e33 389void
9f8628ba 390clean_graph_dump_file (const char *base)
735a0e33
UD
391{
392 size_t namelen = strlen (base);
735a0e33 393 size_t extlen = strlen (graph_ext[graph_dump_format]) + 1;
9f8628ba 394 char *buf = alloca (namelen + extlen);
735a0e33
UD
395 FILE *fp;
396
397 memcpy (buf, base, namelen);
9f8628ba 398 memcpy (buf + namelen, graph_ext[graph_dump_format], extlen);
735a0e33
UD
399
400 fp = fopen (buf, "w");
401
402 if (fp == NULL)
fa6ef813 403 fatal_error ("can't open %s: %m", buf);
735a0e33 404
282899df
NS
405 gcc_assert (graph_dump_format == vcg);
406 fputs ("graph: {\nport_sharing: no\n", fp);
735a0e33
UD
407
408 fclose (fp);
409}
410
411
412/* Do final work on the graph output file. */
413void
9f8628ba 414finish_graph_dump_file (const char *base)
735a0e33
UD
415{
416 size_t namelen = strlen (base);
735a0e33 417 size_t extlen = strlen (graph_ext[graph_dump_format]) + 1;
9f8628ba 418 char *buf = alloca (namelen + extlen);
735a0e33
UD
419 FILE *fp;
420
421 memcpy (buf, base, namelen);
9f8628ba 422 memcpy (buf + namelen, graph_ext[graph_dump_format], extlen);
735a0e33
UD
423
424 fp = fopen (buf, "a");
425 if (fp != NULL)
426 {
282899df
NS
427 gcc_assert (graph_dump_format == vcg);
428 fputs ("}\n", fp);
735a0e33
UD
429 fclose (fp);
430 }
431}