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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [graph.c] - Blame information for rev 280

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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