OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [graph.c] - Blame information for rev 20

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 jlechner
/* Output routines for graphical representation.
2
   Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004
3
   Free Software Foundation, Inc.
4
   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
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 2, 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 COPYING.  If not, write to the Free
20
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21
02110-1301, USA.  */
22
 
23
#include <config.h>
24
#include "system.h"
25
#include "coretypes.h"
26
#include "tm.h"
27
#include "rtl.h"
28
#include "flags.h"
29
#include "output.h"
30
#include "function.h"
31
#include "hard-reg-set.h"
32
#include "obstack.h"
33
#include "basic-block.h"
34
#include "toplev.h"
35
#include "graph.h"
36
 
37
static const char *const graph_ext[] =
38
{
39
  /* no_graph */ "",
40
  /* vcg */      ".vcg",
41
};
42
 
43
static void start_fct (FILE *);
44
static void start_bb (FILE *, int);
45
static void node_data (FILE *, rtx);
46
static void draw_edge (FILE *, int, int, int, int);
47
static void end_fct (FILE *);
48
static void end_bb (FILE *);
49
 
50
/* Output text for new basic block.  */
51
static void
52
start_fct (FILE *fp)
53
{
54
  switch (graph_dump_format)
55
    {
56
    case vcg:
57
      fprintf (fp, "\
58
graph: { title: \"%s\"\nfolding: 1\nhidden: 2\nnode: { title: \"%s.0\" }\n",
59
               current_function_name (), current_function_name ());
60
      break;
61
    case no_graph:
62
      break;
63
    }
64
}
65
 
66
static void
67
start_bb (FILE *fp, int bb)
68
{
69
#if 0
70
  reg_set_iterator rsi;
71
#endif
72
 
73
  switch (graph_dump_format)
74
    {
75
    case vcg:
76
      fprintf (fp, "\
77
graph: {\ntitle: \"%s.BB%d\"\nfolding: 1\ncolor: lightblue\n\
78
label: \"basic block %d",
79
               current_function_name (), bb, bb);
80
      break;
81
    case no_graph:
82
      break;
83
    }
84
 
85
#if 0
86
  /* FIXME Should this be printed?  It makes the graph significantly larger.  */
87
 
88
  /* Print the live-at-start register list.  */
89
  fputc ('\n', fp);
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
    }
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
 
108
static void
109
node_data (FILE *fp, rtx tmp_rtx)
110
{
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, "\
119
edge: { sourcename: \"%s.0\" targetname: \"%s.%d\" }\n",
120
                   current_function_name (),
121
                   current_function_name (), XINT (tmp_rtx, 0));
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  \
132
label: \"%s %d\n",
133
               current_function_name (), XINT (tmp_rtx, 0),
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) ?  "\
139
darkgrey\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.  */
147
  if (NOTE_P (tmp_rtx))
148
    {
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);
153
    }
154
  else if (INSN_P (tmp_rtx))
155
    print_rtl_single (fp, PATTERN (tmp_rtx));
156
  else
157
    print_rtl_single (fp, tmp_rtx);
158
 
159
  switch (graph_dump_format)
160
    {
161
    case vcg:
162
      fputs ("\"\n}\n", fp);
163
      break;
164
    case no_graph:
165
      break;
166
    }
167
}
168
 
169
static void
170
draw_edge (FILE *fp, int from, int to, int bb_edge, int class)
171
{
172
  const char * color;
173
  switch (graph_dump_format)
174
    {
175
    case vcg:
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 ";
183
      fprintf (fp,
184
               "edge: { sourcename: \"%s.%d\" targetname: \"%s.%d\" %s",
185
               current_function_name (), from,
186
               current_function_name (), to, color);
187
      if (class)
188
        fprintf (fp, "class: %d ", class);
189
      fputs ("}\n", fp);
190
      break;
191
    case no_graph:
192
      break;
193
    }
194
}
195
 
196
static void
197
end_bb (FILE *fp)
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
 
209
static void
210
end_fct (FILE *fp)
211
{
212
  switch (graph_dump_format)
213
    {
214
    case vcg:
215
      fprintf (fp, "node: { title: \"%s.999999\" label: \"END\" }\n}\n",
216
               current_function_name ());
217
      break;
218
    case no_graph:
219
      break;
220
    }
221
}
222
 
223
/* Like print_rtl, but also print out live information for the start of each
224
   basic block.  */
225
void
226
print_rtl_graph_with_bb (const char *base, rtx rtx_first)
227
{
228
  rtx tmp_rtx;
229
  size_t namelen = strlen (base);
230
  size_t extlen = strlen (graph_ext[graph_dump_format]) + 1;
231
  char *buf = alloca (namelen + extlen);
232
  FILE *fp;
233
 
234
  if (basic_block_info == NULL)
235
    return;
236
 
237
  memcpy (buf, base, namelen);
238
  memcpy (buf + namelen, graph_ext[graph_dump_format], extlen);
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
    {
248
      enum bb_state { NOT_IN_BB, IN_ONE_BB, IN_MULTIPLE_BB };
249
      int max_uid = get_max_uid ();
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));
253
      basic_block bb;
254
      int i;
255
 
256
      for (i = 0; i < max_uid; ++i)
257
        {
258
          start[i] = end[i] = -1;
259
          in_bb_p[i] = NOT_IN_BB;
260
        }
261
 
262
      FOR_EACH_BB_REVERSE (bb)
263
        {
264
          rtx x;
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))
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;
272
              if (x == BB_END (bb))
273
                break;
274
            }
275
        }
276
 
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
        {
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
            {
291
              if (BARRIER_P (tmp_rtx))
292
                continue;
293
              if (NOTE_P (tmp_rtx)
294
                  && (1 || in_bb_p[INSN_UID (tmp_rtx)] == NOT_IN_BB))
295
                continue;
296
            }
297
 
298
          if ((i = start[INSN_UID (tmp_rtx)]) >= 0)
299
            {
300
              /* We start a subgraph for each basic block.  */
301
              start_bb (fp, i);
302
 
303
              if (i == 0)
304
                draw_edge (fp, 0, INSN_UID (tmp_rtx), 1, 0);
305
            }
306
 
307
          /* Print the data for this node.  */
308
          node_data (fp, tmp_rtx);
309
          next_insn = next_nonnote_insn (tmp_rtx);
310
 
311
          if ((i = end[INSN_UID (tmp_rtx)]) >= 0)
312
            {
313
              edge e;
314
              edge_iterator ei;
315
 
316
              bb = BASIC_BLOCK (i);
317
 
318
              /* End of the basic block.  */
319
              end_bb (fp);
320
 
321
              /* Now specify the edges to all the successors of this
322
                 basic block.  */
323
              FOR_EACH_EDGE (e, ei, bb->succs)
324
                {
325
                  if (e->dest != EXIT_BLOCK_PTR)
326
                    {
327
                      rtx block_head = BB_HEAD (e->dest);
328
 
329
                      draw_edge (fp, INSN_UID (tmp_rtx),
330
                                 INSN_UID (block_head),
331
                                 next_insn != block_head,
332
                                 (e->flags & EDGE_ABNORMAL ? 2 : 0));
333
 
334
                      if (block_head == next_insn)
335
                        edge_printed = 1;
336
                    }
337
                  else
338
                    {
339
                      draw_edge (fp, INSN_UID (tmp_rtx), 999999,
340
                                 next_insn != 0,
341
                                 (e->flags & EDGE_ABNORMAL ? 2 : 0));
342
 
343
                      if (next_insn == 0)
344
                        edge_printed = 1;
345
                    }
346
                }
347
            }
348
 
349
          if (!edge_printed)
350
            {
351
              /* Don't print edges to barriers.  */
352
              if (next_insn == 0
353
                  || !BARRIER_P (next_insn))
354
                draw_edge (fp, XINT (tmp_rtx, 0),
355
                           next_insn ? INSN_UID (next_insn) : 999999, 0, 0);
356
              else
357
                {
358
                  /* We draw the remaining edges in class 3.  We have
359
                     to skip over the barrier since these nodes are
360
                     not printed at all.  */
361
                  do
362
                    next_insn = NEXT_INSN (next_insn);
363
                  while (next_insn
364
                         && (NOTE_P (next_insn)
365
                             || BARRIER_P (next_insn)));
366
 
367
                  draw_edge (fp, XINT (tmp_rtx, 0),
368
                             next_insn ? INSN_UID (next_insn) : 999999, 0, 3);
369
                }
370
            }
371
        }
372
 
373
      dump_for_graph = 0;
374
 
375
      end_fct (fp);
376
 
377
      /* Clean up.  */
378
      free (start);
379
      free (end);
380
      free (in_bb_p);
381
    }
382
 
383
  fclose (fp);
384
}
385
 
386
 
387
/* Similar as clean_dump_file, but this time for graph output files.  */
388
 
389
void
390
clean_graph_dump_file (const char *base)
391
{
392
  size_t namelen = strlen (base);
393
  size_t extlen = strlen (graph_ext[graph_dump_format]) + 1;
394
  char *buf = alloca (namelen + extlen);
395
  FILE *fp;
396
 
397
  memcpy (buf, base, namelen);
398
  memcpy (buf + namelen, graph_ext[graph_dump_format], extlen);
399
 
400
  fp = fopen (buf, "w");
401
 
402
  if (fp == NULL)
403
    fatal_error ("can't open %s: %m", buf);
404
 
405
  gcc_assert (graph_dump_format == vcg);
406
  fputs ("graph: {\nport_sharing: no\n", fp);
407
 
408
  fclose (fp);
409
}
410
 
411
 
412
/* Do final work on the graph output file.  */
413
void
414
finish_graph_dump_file (const char *base)
415
{
416
  size_t namelen = strlen (base);
417
  size_t extlen = strlen (graph_ext[graph_dump_format]) + 1;
418
  char *buf = alloca (namelen + extlen);
419
  FILE *fp;
420
 
421
  memcpy (buf, base, namelen);
422
  memcpy (buf + namelen, graph_ext[graph_dump_format], extlen);
423
 
424
  fp = fopen (buf, "a");
425
  if (fp != NULL)
426
    {
427
      gcc_assert (graph_dump_format == vcg);
428
      fputs ("}\n", fp);
429
      fclose (fp);
430
    }
431
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.