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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [graph.c] - Blame information for rev 774

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

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

powered by: WebSVN 2.1.0

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