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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [gcc/] [tree-dump.c] - Blame information for rev 847

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

Line No. Rev Author Line
1 280 jeremybenn
/* Tree-dumping functionality for intermediate representation.
2
   Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
3
   Free Software Foundation, Inc.
4
   Written by Mark Mitchell <mark@codesourcery.com>
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 "tree.h"
27
#include "splay-tree.h"
28
#include "diagnostic.h"
29
#include "toplev.h"
30
#include "tree-dump.h"
31
#include "tree-pass.h"
32
#include "langhooks.h"
33
#include "tree-iterator.h"
34
#include "real.h"
35
#include "fixed-value.h"
36
 
37
static unsigned int queue (dump_info_p, const_tree, int);
38
static void dump_index (dump_info_p, unsigned int);
39
static void dequeue_and_dump (dump_info_p);
40
static void dump_new_line (dump_info_p);
41
static void dump_maybe_newline (dump_info_p);
42
 
43
/* Add T to the end of the queue of nodes to dump.  Returns the index
44
   assigned to T.  */
45
 
46
static unsigned int
47
queue (dump_info_p di, const_tree t, int flags)
48
{
49
  dump_queue_p dq;
50
  dump_node_info_p dni;
51
  unsigned int index;
52
 
53
  /* Assign the next available index to T.  */
54
  index = ++di->index;
55
 
56
  /* Obtain a new queue node.  */
57
  if (di->free_list)
58
    {
59
      dq = di->free_list;
60
      di->free_list = dq->next;
61
    }
62
  else
63
    dq = XNEW (struct dump_queue);
64
 
65
  /* Create a new entry in the splay-tree.  */
66
  dni = XNEW (struct dump_node_info);
67
  dni->index = index;
68
  dni->binfo_p = ((flags & DUMP_BINFO) != 0);
69
  dq->node = splay_tree_insert (di->nodes, (splay_tree_key) t,
70
                                (splay_tree_value) dni);
71
 
72
  /* Add it to the end of the queue.  */
73
  dq->next = 0;
74
  if (!di->queue_end)
75
    di->queue = dq;
76
  else
77
    di->queue_end->next = dq;
78
  di->queue_end = dq;
79
 
80
  /* Return the index.  */
81
  return index;
82
}
83
 
84
static void
85
dump_index (dump_info_p di, unsigned int index)
86
{
87
  fprintf (di->stream, "@%-6u ", index);
88
  di->column += 8;
89
}
90
 
91
/* If T has not already been output, queue it for subsequent output.
92
   FIELD is a string to print before printing the index.  Then, the
93
   index of T is printed.  */
94
 
95
void
96
queue_and_dump_index (dump_info_p di, const char *field, const_tree t, int flags)
97
{
98
  unsigned int index;
99
  splay_tree_node n;
100
 
101
  /* If there's no node, just return.  This makes for fewer checks in
102
     our callers.  */
103
  if (!t)
104
    return;
105
 
106
  /* See if we've already queued or dumped this node.  */
107
  n = splay_tree_lookup (di->nodes, (splay_tree_key) t);
108
  if (n)
109
    index = ((dump_node_info_p) n->value)->index;
110
  else
111
    /* If we haven't, add it to the queue.  */
112
    index = queue (di, t, flags);
113
 
114
  /* Print the index of the node.  */
115
  dump_maybe_newline (di);
116
  fprintf (di->stream, "%-4s: ", field);
117
  di->column += 6;
118
  dump_index (di, index);
119
}
120
 
121
/* Dump the type of T.  */
122
 
123
void
124
queue_and_dump_type (dump_info_p di, const_tree t)
125
{
126
  queue_and_dump_index (di, "type", TREE_TYPE (t), DUMP_NONE);
127
}
128
 
129
/* Dump column control */
130
#define SOL_COLUMN 25           /* Start of line column.  */
131
#define EOL_COLUMN 55           /* End of line column.  */
132
#define COLUMN_ALIGNMENT 15     /* Alignment.  */
133
 
134
/* Insert a new line in the dump output, and indent to an appropriate
135
   place to start printing more fields.  */
136
 
137
static void
138
dump_new_line (dump_info_p di)
139
{
140
  fprintf (di->stream, "\n%*s", SOL_COLUMN, "");
141
  di->column = SOL_COLUMN;
142
}
143
 
144
/* If necessary, insert a new line.  */
145
 
146
static void
147
dump_maybe_newline (dump_info_p di)
148
{
149
  int extra;
150
 
151
  /* See if we need a new line.  */
152
  if (di->column > EOL_COLUMN)
153
    dump_new_line (di);
154
  /* See if we need any padding.  */
155
  else if ((extra = (di->column - SOL_COLUMN) % COLUMN_ALIGNMENT) != 0)
156
    {
157
      fprintf (di->stream, "%*s", COLUMN_ALIGNMENT - extra, "");
158
      di->column += COLUMN_ALIGNMENT - extra;
159
    }
160
}
161
 
162
/* Dump pointer PTR using FIELD to identify it.  */
163
 
164
void
165
dump_pointer (dump_info_p di, const char *field, void *ptr)
166
{
167
  dump_maybe_newline (di);
168
  fprintf (di->stream, "%-4s: %-8lx ", field, (unsigned long) ptr);
169
  di->column += 15;
170
}
171
 
172
/* Dump integer I using FIELD to identify it.  */
173
 
174
void
175
dump_int (dump_info_p di, const char *field, int i)
176
{
177
  dump_maybe_newline (di);
178
  fprintf (di->stream, "%-4s: %-7d ", field, i);
179
  di->column += 14;
180
}
181
 
182
/* Dump the floating point value R, using FIELD to identify it.  */
183
 
184
static void
185
dump_real (dump_info_p di, const char *field, const REAL_VALUE_TYPE *r)
186
{
187
  char buf[32];
188
  real_to_decimal (buf, r, sizeof (buf), 0, true);
189
  dump_maybe_newline (di);
190
  fprintf (di->stream, "%-4s: %s ", field, buf);
191
  di->column += strlen (buf) + 7;
192
}
193
 
194
/* Dump the fixed-point value F, using FIELD to identify it.  */
195
 
196
static void
197
dump_fixed (dump_info_p di, const char *field, const FIXED_VALUE_TYPE *f)
198
{
199
  char buf[32];
200
  fixed_to_decimal (buf, f, sizeof (buf));
201
  dump_maybe_newline (di);
202
  fprintf (di->stream, "%-4s: %s ", field, buf);
203
  di->column += strlen (buf) + 7;
204
}
205
 
206
 
207
/* Dump the string S.  */
208
 
209
void
210
dump_string (dump_info_p di, const char *string)
211
{
212
  dump_maybe_newline (di);
213
  fprintf (di->stream, "%-13s ", string);
214
  if (strlen (string) > 13)
215
    di->column += strlen (string) + 1;
216
  else
217
    di->column += 14;
218
}
219
 
220
/* Dump the string field S.  */
221
 
222
void
223
dump_string_field (dump_info_p di, const char *field, const char *string)
224
{
225
  dump_maybe_newline (di);
226
  fprintf (di->stream, "%-4s: %-7s ", field, string);
227
  if (strlen (string) > 7)
228
    di->column += 6 + strlen (string) + 1;
229
  else
230
    di->column += 14;
231
}
232
 
233
/* Dump the next node in the queue.  */
234
 
235
static void
236
dequeue_and_dump (dump_info_p di)
237
{
238
  dump_queue_p dq;
239
  splay_tree_node stn;
240
  dump_node_info_p dni;
241
  tree t;
242
  unsigned int index;
243
  enum tree_code code;
244
  enum tree_code_class code_class;
245
  const char* code_name;
246
 
247
  /* Get the next node from the queue.  */
248
  dq = di->queue;
249
  stn = dq->node;
250
  t = (tree) stn->key;
251
  dni = (dump_node_info_p) stn->value;
252
  index = dni->index;
253
 
254
  /* Remove the node from the queue, and put it on the free list.  */
255
  di->queue = dq->next;
256
  if (!di->queue)
257
    di->queue_end = 0;
258
  dq->next = di->free_list;
259
  di->free_list = dq;
260
 
261
  /* Print the node index.  */
262
  dump_index (di, index);
263
  /* And the type of node this is.  */
264
  if (dni->binfo_p)
265
    code_name = "binfo";
266
  else
267
    code_name = tree_code_name[(int) TREE_CODE (t)];
268
  fprintf (di->stream, "%-16s ", code_name);
269
  di->column = 25;
270
 
271
  /* Figure out what kind of node this is.  */
272
  code = TREE_CODE (t);
273
  code_class = TREE_CODE_CLASS (code);
274
 
275
  /* Although BINFOs are TREE_VECs, we dump them specially so as to be
276
     more informative.  */
277
  if (dni->binfo_p)
278
    {
279
      unsigned ix;
280
      tree base;
281
      VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (t);
282
 
283
      dump_child ("type", BINFO_TYPE (t));
284
 
285
      if (BINFO_VIRTUAL_P (t))
286
        dump_string_field (di, "spec", "virt");
287
 
288
      dump_int (di, "bases", BINFO_N_BASE_BINFOS (t));
289
      for (ix = 0; BINFO_BASE_ITERATE (t, ix, base); ix++)
290
        {
291
          tree access = (accesses ? VEC_index (tree, accesses, ix)
292
                         : access_public_node);
293
          const char *string = NULL;
294
 
295
          if (access == access_public_node)
296
            string = "pub";
297
          else if (access == access_protected_node)
298
            string = "prot";
299
          else if (access == access_private_node)
300
            string = "priv";
301
          else
302
            gcc_unreachable ();
303
 
304
          dump_string_field (di, "accs", string);
305
          queue_and_dump_index (di, "binf", base, DUMP_BINFO);
306
        }
307
 
308
      goto done;
309
    }
310
 
311
  /* We can knock off a bunch of expression nodes in exactly the same
312
     way.  */
313
  if (IS_EXPR_CODE_CLASS (code_class))
314
    {
315
      /* If we're dumping children, dump them now.  */
316
      queue_and_dump_type (di, t);
317
 
318
      switch (code_class)
319
        {
320
        case tcc_unary:
321
          dump_child ("op 0", TREE_OPERAND (t, 0));
322
          break;
323
 
324
        case tcc_binary:
325
        case tcc_comparison:
326
          dump_child ("op 0", TREE_OPERAND (t, 0));
327
          dump_child ("op 1", TREE_OPERAND (t, 1));
328
          break;
329
 
330
        case tcc_expression:
331
        case tcc_reference:
332
        case tcc_statement:
333
        case tcc_vl_exp:
334
          /* These nodes are handled explicitly below.  */
335
          break;
336
 
337
        default:
338
          gcc_unreachable ();
339
        }
340
    }
341
  else if (DECL_P (t))
342
    {
343
      expanded_location xloc;
344
      /* All declarations have names.  */
345
      if (DECL_NAME (t))
346
        dump_child ("name", DECL_NAME (t));
347
      if (DECL_ASSEMBLER_NAME_SET_P (t)
348
          && DECL_ASSEMBLER_NAME (t) != DECL_NAME (t))
349
        dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
350
      if (DECL_ABSTRACT_ORIGIN (t))
351
        dump_child ("orig", DECL_ABSTRACT_ORIGIN (t));
352
      /* And types.  */
353
      queue_and_dump_type (di, t);
354
      dump_child ("scpe", DECL_CONTEXT (t));
355
      /* And a source position.  */
356
      xloc = expand_location (DECL_SOURCE_LOCATION (t));
357
      if (xloc.file)
358
        {
359
          const char *filename = strrchr (xloc.file, '/');
360
          if (!filename)
361
            filename = xloc.file;
362
          else
363
            /* Skip the slash.  */
364
            ++filename;
365
 
366
          dump_maybe_newline (di);
367
          fprintf (di->stream, "srcp: %s:%-6d ", filename,
368
                   xloc.line);
369
          di->column += 6 + strlen (filename) + 8;
370
        }
371
      /* And any declaration can be compiler-generated.  */
372
      if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_COMMON)
373
          && DECL_ARTIFICIAL (t))
374
        dump_string_field (di, "note", "artificial");
375
      if (TREE_CHAIN (t) && !dump_flag (di, TDF_SLIM, NULL))
376
        dump_child ("chan", TREE_CHAIN (t));
377
    }
378
  else if (code_class == tcc_type)
379
    {
380
      /* All types have qualifiers.  */
381
      int quals = lang_hooks.tree_dump.type_quals (t);
382
 
383
      if (quals != TYPE_UNQUALIFIED)
384
        {
385
          fprintf (di->stream, "qual: %c%c%c     ",
386
                   (quals & TYPE_QUAL_CONST) ? 'c' : ' ',
387
                   (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ',
388
                   (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' ');
389
          di->column += 14;
390
        }
391
 
392
      /* All types have associated declarations.  */
393
      dump_child ("name", TYPE_NAME (t));
394
 
395
      /* All types have a main variant.  */
396
      if (TYPE_MAIN_VARIANT (t) != t)
397
        dump_child ("unql", TYPE_MAIN_VARIANT (t));
398
 
399
      /* And sizes.  */
400
      dump_child ("size", TYPE_SIZE (t));
401
 
402
      /* All types have alignments.  */
403
      dump_int (di, "algn", TYPE_ALIGN (t));
404
    }
405
  else if (code_class == tcc_constant)
406
    /* All constants can have types.  */
407
    queue_and_dump_type (di, t);
408
 
409
  /* Give the language-specific code a chance to print something.  If
410
     it's completely taken care of things, don't bother printing
411
     anything more ourselves.  */
412
  if (lang_hooks.tree_dump.dump_tree (di, t))
413
    goto done;
414
 
415
  /* Now handle the various kinds of nodes.  */
416
  switch (code)
417
    {
418
      int i;
419
 
420
    case IDENTIFIER_NODE:
421
      dump_string_field (di, "strg", IDENTIFIER_POINTER (t));
422
      dump_int (di, "lngt", IDENTIFIER_LENGTH (t));
423
      break;
424
 
425
    case TREE_LIST:
426
      dump_child ("purp", TREE_PURPOSE (t));
427
      dump_child ("valu", TREE_VALUE (t));
428
      dump_child ("chan", TREE_CHAIN (t));
429
      break;
430
 
431
    case STATEMENT_LIST:
432
      {
433
        tree_stmt_iterator it;
434
        for (i = 0, it = tsi_start (t); !tsi_end_p (it); tsi_next (&it), i++)
435
          {
436
            char buffer[32];
437
            sprintf (buffer, "%u", i);
438
            dump_child (buffer, tsi_stmt (it));
439
          }
440
      }
441
      break;
442
 
443
    case TREE_VEC:
444
      dump_int (di, "lngt", TREE_VEC_LENGTH (t));
445
      for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
446
        {
447
          char buffer[32];
448
          sprintf (buffer, "%u", i);
449
          dump_child (buffer, TREE_VEC_ELT (t, i));
450
        }
451
      break;
452
 
453
    case INTEGER_TYPE:
454
    case ENUMERAL_TYPE:
455
      dump_int (di, "prec", TYPE_PRECISION (t));
456
      dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed");
457
      dump_child ("min", TYPE_MIN_VALUE (t));
458
      dump_child ("max", TYPE_MAX_VALUE (t));
459
 
460
      if (code == ENUMERAL_TYPE)
461
        dump_child ("csts", TYPE_VALUES (t));
462
      break;
463
 
464
    case REAL_TYPE:
465
      dump_int (di, "prec", TYPE_PRECISION (t));
466
      break;
467
 
468
    case FIXED_POINT_TYPE:
469
      dump_int (di, "prec", TYPE_PRECISION (t));
470
      dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed");
471
      dump_string_field (di, "saturating",
472
                         TYPE_SATURATING (t) ? "saturating": "non-saturating");
473
      break;
474
 
475
    case POINTER_TYPE:
476
      dump_child ("ptd", TREE_TYPE (t));
477
      break;
478
 
479
    case REFERENCE_TYPE:
480
      dump_child ("refd", TREE_TYPE (t));
481
      break;
482
 
483
    case METHOD_TYPE:
484
      dump_child ("clas", TYPE_METHOD_BASETYPE (t));
485
      /* Fall through.  */
486
 
487
    case FUNCTION_TYPE:
488
      dump_child ("retn", TREE_TYPE (t));
489
      dump_child ("prms", TYPE_ARG_TYPES (t));
490
      break;
491
 
492
    case ARRAY_TYPE:
493
      dump_child ("elts", TREE_TYPE (t));
494
      dump_child ("domn", TYPE_DOMAIN (t));
495
      break;
496
 
497
    case RECORD_TYPE:
498
    case UNION_TYPE:
499
      if (TREE_CODE (t) == RECORD_TYPE)
500
        dump_string_field (di, "tag", "struct");
501
      else
502
        dump_string_field (di, "tag", "union");
503
 
504
      dump_child ("flds", TYPE_FIELDS (t));
505
      dump_child ("fncs", TYPE_METHODS (t));
506
      queue_and_dump_index (di, "binf", TYPE_BINFO (t),
507
                            DUMP_BINFO);
508
      break;
509
 
510
    case CONST_DECL:
511
      dump_child ("cnst", DECL_INITIAL (t));
512
      break;
513
 
514
    case DEBUG_EXPR_DECL:
515
      dump_int (di, "-uid", DEBUG_TEMP_UID (t));
516
      /* Fall through.  */
517
 
518
    case VAR_DECL:
519
    case PARM_DECL:
520
    case FIELD_DECL:
521
    case RESULT_DECL:
522
      if (TREE_CODE (t) == PARM_DECL)
523
        dump_child ("argt", DECL_ARG_TYPE (t));
524
      else
525
        dump_child ("init", DECL_INITIAL (t));
526
      dump_child ("size", DECL_SIZE (t));
527
      dump_int (di, "algn", DECL_ALIGN (t));
528
 
529
      if (TREE_CODE (t) == FIELD_DECL)
530
        {
531
          if (DECL_FIELD_OFFSET (t))
532
            dump_child ("bpos", bit_position (t));
533
        }
534
      else if (TREE_CODE (t) == VAR_DECL
535
               || TREE_CODE (t) == PARM_DECL)
536
        {
537
          dump_int (di, "used", TREE_USED (t));
538
          if (DECL_REGISTER (t))
539
            dump_string_field (di, "spec", "register");
540
        }
541
      break;
542
 
543
    case FUNCTION_DECL:
544
      dump_child ("args", DECL_ARGUMENTS (t));
545
      if (DECL_EXTERNAL (t))
546
        dump_string_field (di, "body", "undefined");
547
      if (TREE_PUBLIC (t))
548
        dump_string_field (di, "link", "extern");
549
      else
550
        dump_string_field (di, "link", "static");
551
      if (DECL_SAVED_TREE (t) && !dump_flag (di, TDF_SLIM, t))
552
        dump_child ("body", DECL_SAVED_TREE (t));
553
      break;
554
 
555
    case INTEGER_CST:
556
      if (TREE_INT_CST_HIGH (t))
557
        dump_int (di, "high", TREE_INT_CST_HIGH (t));
558
      dump_int (di, "low", TREE_INT_CST_LOW (t));
559
      break;
560
 
561
    case STRING_CST:
562
      fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t));
563
      dump_int (di, "lngt", TREE_STRING_LENGTH (t));
564
      break;
565
 
566
    case REAL_CST:
567
      dump_real (di, "valu", TREE_REAL_CST_PTR (t));
568
      break;
569
 
570
    case FIXED_CST:
571
      dump_fixed (di, "valu", TREE_FIXED_CST_PTR (t));
572
      break;
573
 
574
    case TRUTH_NOT_EXPR:
575
    case ADDR_EXPR:
576
    case INDIRECT_REF:
577
    case ALIGN_INDIRECT_REF:
578
    case MISALIGNED_INDIRECT_REF:
579
    case CLEANUP_POINT_EXPR:
580
    case SAVE_EXPR:
581
    case REALPART_EXPR:
582
    case IMAGPART_EXPR:
583
      /* These nodes are unary, but do not have code class `1'.  */
584
      dump_child ("op 0", TREE_OPERAND (t, 0));
585
      break;
586
 
587
    case TRUTH_ANDIF_EXPR:
588
    case TRUTH_ORIF_EXPR:
589
    case INIT_EXPR:
590
    case MODIFY_EXPR:
591
    case COMPOUND_EXPR:
592
    case PREDECREMENT_EXPR:
593
    case PREINCREMENT_EXPR:
594
    case POSTDECREMENT_EXPR:
595
    case POSTINCREMENT_EXPR:
596
      /* These nodes are binary, but do not have code class `2'.  */
597
      dump_child ("op 0", TREE_OPERAND (t, 0));
598
      dump_child ("op 1", TREE_OPERAND (t, 1));
599
      break;
600
 
601
    case COMPONENT_REF:
602
      dump_child ("op 0", TREE_OPERAND (t, 0));
603
      dump_child ("op 1", TREE_OPERAND (t, 1));
604
      dump_child ("op 2", TREE_OPERAND (t, 2));
605
      break;
606
 
607
    case ARRAY_REF:
608
    case ARRAY_RANGE_REF:
609
      dump_child ("op 0", TREE_OPERAND (t, 0));
610
      dump_child ("op 1", TREE_OPERAND (t, 1));
611
      dump_child ("op 2", TREE_OPERAND (t, 2));
612
      dump_child ("op 3", TREE_OPERAND (t, 3));
613
      break;
614
 
615
    case COND_EXPR:
616
      dump_child ("op 0", TREE_OPERAND (t, 0));
617
      dump_child ("op 1", TREE_OPERAND (t, 1));
618
      dump_child ("op 2", TREE_OPERAND (t, 2));
619
      break;
620
 
621
    case TRY_FINALLY_EXPR:
622
      dump_child ("op 0", TREE_OPERAND (t, 0));
623
      dump_child ("op 1", TREE_OPERAND (t, 1));
624
      break;
625
 
626
    case CALL_EXPR:
627
      {
628
        int i = 0;
629
        tree arg;
630
        call_expr_arg_iterator iter;
631
        dump_child ("fn", CALL_EXPR_FN (t));
632
        FOR_EACH_CALL_EXPR_ARG (arg, iter, t)
633
          {
634
            char buffer[32];
635
            sprintf (buffer, "%u", i);
636
            dump_child (buffer, arg);
637
            i++;
638
          }
639
      }
640
      break;
641
 
642
    case CONSTRUCTOR:
643
      {
644
        unsigned HOST_WIDE_INT cnt;
645
        tree index, value;
646
        dump_int (di, "lngt", VEC_length (constructor_elt,
647
                                          CONSTRUCTOR_ELTS (t)));
648
        FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), cnt, index, value)
649
          {
650
            dump_child ("idx", index);
651
            dump_child ("val", value);
652
          }
653
      }
654
      break;
655
 
656
    case BIND_EXPR:
657
      dump_child ("vars", TREE_OPERAND (t, 0));
658
      dump_child ("body", TREE_OPERAND (t, 1));
659
      break;
660
 
661
    case LOOP_EXPR:
662
      dump_child ("body", TREE_OPERAND (t, 0));
663
      break;
664
 
665
    case EXIT_EXPR:
666
      dump_child ("cond", TREE_OPERAND (t, 0));
667
      break;
668
 
669
    case RETURN_EXPR:
670
      dump_child ("expr", TREE_OPERAND (t, 0));
671
      break;
672
 
673
    case TARGET_EXPR:
674
      dump_child ("decl", TREE_OPERAND (t, 0));
675
      dump_child ("init", TREE_OPERAND (t, 1));
676
      dump_child ("clnp", TREE_OPERAND (t, 2));
677
      /* There really are two possible places the initializer can be.
678
         After RTL expansion, the second operand is moved to the
679
         position of the fourth operand, and the second operand
680
         becomes NULL.  */
681
      dump_child ("init", TREE_OPERAND (t, 3));
682
      break;
683
 
684
    case CASE_LABEL_EXPR:
685
      dump_child ("name", CASE_LABEL (t));
686
      if (CASE_LOW (t))
687
        {
688
          dump_child ("low ", CASE_LOW (t));
689
          if (CASE_HIGH (t))
690
            dump_child ("high", CASE_HIGH (t));
691
        }
692
      break;
693
    case LABEL_EXPR:
694
      dump_child ("name", TREE_OPERAND (t,0));
695
      break;
696
    case GOTO_EXPR:
697
      dump_child ("labl", TREE_OPERAND (t, 0));
698
      break;
699
    case SWITCH_EXPR:
700
      dump_child ("cond", TREE_OPERAND (t, 0));
701
      dump_child ("body", TREE_OPERAND (t, 1));
702
      if (TREE_OPERAND (t, 2))
703
        {
704
          dump_child ("labl", TREE_OPERAND (t,2));
705
        }
706
      break;
707
    case OMP_CLAUSE:
708
      {
709
        int i;
710
        fprintf (di->stream, "%s\n", omp_clause_code_name[OMP_CLAUSE_CODE (t)]);
711
        for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (t)]; i++)
712
          dump_child ("op: ", OMP_CLAUSE_OPERAND (t, i));
713
      }
714
      break;
715
    default:
716
      /* There are no additional fields to print.  */
717
      break;
718
    }
719
 
720
 done:
721
  if (dump_flag (di, TDF_ADDRESS, NULL))
722
    dump_pointer (di, "addr", (void *)t);
723
 
724
  /* Terminate the line.  */
725
  fprintf (di->stream, "\n");
726
}
727
 
728
/* Return nonzero if FLAG has been specified for the dump, and NODE
729
   is not the root node of the dump.  */
730
 
731
int dump_flag (dump_info_p di, int flag, const_tree node)
732
{
733
  return (di->flags & flag) && (node != di->node);
734
}
735
 
736
/* Dump T, and all its children, on STREAM.  */
737
 
738
void
739
dump_node (const_tree t, int flags, FILE *stream)
740
{
741
  struct dump_info di;
742
  dump_queue_p dq;
743
  dump_queue_p next_dq;
744
 
745
  /* Initialize the dump-information structure.  */
746
  di.stream = stream;
747
  di.index = 0;
748
  di.column = 0;
749
  di.queue = 0;
750
  di.queue_end = 0;
751
  di.free_list = 0;
752
  di.flags = flags;
753
  di.node = t;
754
  di.nodes = splay_tree_new (splay_tree_compare_pointers, 0,
755
                             (splay_tree_delete_value_fn) &free);
756
 
757
  /* Queue up the first node.  */
758
  queue (&di, t, DUMP_NONE);
759
 
760
  /* Until the queue is empty, keep dumping nodes.  */
761
  while (di.queue)
762
    dequeue_and_dump (&di);
763
 
764
  /* Now, clean up.  */
765
  for (dq = di.free_list; dq; dq = next_dq)
766
    {
767
      next_dq = dq->next;
768
      free (dq);
769
    }
770
  splay_tree_delete (di.nodes);
771
}
772
 
773
 
774
/* Table of tree dump switches. This must be consistent with the
775
   tree_dump_index enumeration in tree-pass.h.  */
776
static struct dump_file_info dump_files[TDI_end] =
777
{
778
  {NULL, NULL, NULL, 0, 0, 0},
779
  {".cgraph", "ipa-cgraph", NULL, TDF_IPA, 0,  0},
780
  {".tu", "translation-unit", NULL, TDF_TREE, 0, 1},
781
  {".class", "class-hierarchy", NULL, TDF_TREE, 0, 2},
782
  {".original", "tree-original", NULL, TDF_TREE, 0, 3},
783
  {".gimple", "tree-gimple", NULL, TDF_TREE, 0, 4},
784
  {".nested", "tree-nested", NULL, TDF_TREE, 0, 5},
785
  {".vcg", "tree-vcg", NULL, TDF_TREE, 0, 6},
786
#define FIRST_AUTO_NUMBERED_DUMP 7
787
 
788
  {NULL, "tree-all", NULL, TDF_TREE, 0, 0},
789
  {NULL, "rtl-all", NULL, TDF_RTL, 0, 0},
790
  {NULL, "ipa-all", NULL, TDF_IPA, 0, 0},
791
};
792
 
793
/* Dynamically registered tree dump files and switches.  */
794
static struct dump_file_info *extra_dump_files;
795
static size_t extra_dump_files_in_use;
796
static size_t extra_dump_files_alloced;
797
 
798
/* Define a name->number mapping for a dump flag value.  */
799
struct dump_option_value_info
800
{
801
  const char *const name;       /* the name of the value */
802
  const int value;              /* the value of the name */
803
};
804
 
805
/* Table of dump options. This must be consistent with the TDF_* flags
806
   in tree.h */
807
static const struct dump_option_value_info dump_options[] =
808
{
809
  {"address", TDF_ADDRESS},
810
  {"asmname", TDF_ASMNAME},
811
  {"slim", TDF_SLIM},
812
  {"raw", TDF_RAW},
813
  {"graph", TDF_GRAPH},
814
  {"details", TDF_DETAILS},
815
  {"stats", TDF_STATS},
816
  {"blocks", TDF_BLOCKS},
817
  {"vops", TDF_VOPS},
818
  {"lineno", TDF_LINENO},
819
  {"uid", TDF_UID},
820
  {"stmtaddr", TDF_STMTADDR},
821
  {"memsyms", TDF_MEMSYMS},
822
  {"verbose", TDF_VERBOSE},
823
  {"eh", TDF_EH},
824
  {"nouid", TDF_NOUID},
825
  {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA
826
            | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC | TDF_VERBOSE
827
            | TDF_RHS_ONLY | TDF_NOUID)},
828
  {NULL, 0}
829
};
830
 
831
unsigned int
832
dump_register (const char *suffix, const char *swtch, const char *glob,
833
               int flags)
834
{
835
  static int next_dump = FIRST_AUTO_NUMBERED_DUMP;
836
  int num = next_dump++;
837
 
838
  size_t count = extra_dump_files_in_use++;
839
 
840
  if (count >= extra_dump_files_alloced)
841
    {
842
      if (extra_dump_files_alloced == 0)
843
        extra_dump_files_alloced = 32;
844
      else
845
        extra_dump_files_alloced *= 2;
846
      extra_dump_files = XRESIZEVEC (struct dump_file_info,
847
                                     extra_dump_files,
848
                                     extra_dump_files_alloced);
849
    }
850
 
851
  memset (&extra_dump_files[count], 0, sizeof (struct dump_file_info));
852
  extra_dump_files[count].suffix = suffix;
853
  extra_dump_files[count].swtch = swtch;
854
  extra_dump_files[count].glob = glob;
855
  extra_dump_files[count].flags = flags;
856
  extra_dump_files[count].num = num;
857
 
858
  return count + TDI_end;
859
}
860
 
861
 
862
/* Return the dump_file_info for the given phase.  */
863
 
864
struct dump_file_info *
865
get_dump_file_info (int phase)
866
{
867
  if (phase < TDI_end)
868
    return &dump_files[phase];
869
  else if ((size_t) (phase - TDI_end) >= extra_dump_files_in_use)
870
    return NULL;
871
  else
872
    return extra_dump_files + (phase - TDI_end);
873
}
874
 
875
 
876
/* Return the name of the dump file for the given phase.
877
   If the dump is not enabled, returns NULL.  */
878
 
879
char *
880
get_dump_file_name (int phase)
881
{
882
  char dump_id[10];
883
  struct dump_file_info *dfi;
884
 
885
  if (phase == TDI_none)
886
    return NULL;
887
 
888
  dfi = get_dump_file_info (phase);
889
  if (dfi->state == 0)
890
    return NULL;
891
 
892
  if (dfi->num < 0)
893
    dump_id[0] = '\0';
894
  else
895
    {
896
      char suffix;
897
      if (dfi->flags & TDF_TREE)
898
        suffix = 't';
899
      else if (dfi->flags & TDF_IPA)
900
        suffix = 'i';
901
      else
902
        suffix = 'r';
903
 
904
      if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
905
        dump_id[0] = '\0';
906
    }
907
 
908
  return concat (dump_base_name, dump_id, dfi->suffix, NULL);
909
}
910
 
911
/* Begin a tree dump for PHASE. Stores any user supplied flag in
912
   *FLAG_PTR and returns a stream to write to. If the dump is not
913
   enabled, returns NULL.
914
   Multiple calls will reopen and append to the dump file.  */
915
 
916
FILE *
917
dump_begin (int phase, int *flag_ptr)
918
{
919
  char *name;
920
  struct dump_file_info *dfi;
921
  FILE *stream;
922
 
923
  if (phase == TDI_none || !dump_enabled_p (phase))
924
    return NULL;
925
 
926
  name = get_dump_file_name (phase);
927
  dfi = get_dump_file_info (phase);
928
  stream = fopen (name, dfi->state < 0 ? "w" : "a");
929
  if (!stream)
930
    error ("could not open dump file %qs: %s", name, strerror (errno));
931
  else
932
    dfi->state = 1;
933
  free (name);
934
 
935
  if (flag_ptr)
936
    *flag_ptr = dfi->flags;
937
 
938
  return stream;
939
}
940
 
941
/* Returns nonzero if tree dump PHASE is enabled.  If PHASE is
942
   TDI_tree_all, return nonzero if any dump is enabled.  */
943
 
944
int
945
dump_enabled_p (int phase)
946
{
947
  if (phase == TDI_tree_all)
948
    {
949
      size_t i;
950
      for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
951
        if (dump_files[i].state)
952
          return 1;
953
      for (i = 0; i < extra_dump_files_in_use; i++)
954
        if (extra_dump_files[i].state)
955
          return 1;
956
      return 0;
957
    }
958
  else
959
    {
960
      struct dump_file_info *dfi = get_dump_file_info (phase);
961
      return dfi->state;
962
    }
963
}
964
 
965
/* Returns nonzero if tree dump PHASE has been initialized.  */
966
 
967
int
968
dump_initialized_p (int phase)
969
{
970
  struct dump_file_info *dfi = get_dump_file_info (phase);
971
  return dfi->state > 0;
972
}
973
 
974
/* Returns the switch name of PHASE.  */
975
 
976
const char *
977
dump_flag_name (int phase)
978
{
979
  struct dump_file_info *dfi = get_dump_file_info (phase);
980
  return dfi->swtch;
981
}
982
 
983
/* Finish a tree dump for PHASE. STREAM is the stream created by
984
   dump_begin.  */
985
 
986
void
987
dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
988
{
989
  fclose (stream);
990
}
991
 
992
/* Enable all tree dumps.  Return number of enabled tree dumps.  */
993
 
994
static int
995
dump_enable_all (int flags)
996
{
997
  int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
998
  int n = 0;
999
  size_t i;
1000
 
1001
  for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
1002
    if ((dump_files[i].flags & ir_dump_type))
1003
      {
1004
        dump_files[i].state = -1;
1005
        dump_files[i].flags |= flags;
1006
        n++;
1007
      }
1008
 
1009
  for (i = 0; i < extra_dump_files_in_use; i++)
1010
    if ((extra_dump_files[i].flags & ir_dump_type))
1011
      {
1012
        extra_dump_files[i].state = -1;
1013
        extra_dump_files[i].flags |= flags;
1014
        n++;
1015
      }
1016
 
1017
  return n;
1018
}
1019
 
1020
/* Parse ARG as a dump switch. Return nonzero if it is, and store the
1021
   relevant details in the dump_files array.  */
1022
 
1023
static int
1024
dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
1025
{
1026
  const char *option_value;
1027
  const char *ptr;
1028
  int flags;
1029
 
1030
  if (doglob && !dfi->glob)
1031
    return 0;
1032
 
1033
  option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
1034
  if (!option_value)
1035
    return 0;
1036
 
1037
  if (*option_value && *option_value != '-')
1038
    return 0;
1039
 
1040
  ptr = option_value;
1041
  flags = 0;
1042
 
1043
  while (*ptr)
1044
    {
1045
      const struct dump_option_value_info *option_ptr;
1046
      const char *end_ptr;
1047
      unsigned length;
1048
 
1049
      while (*ptr == '-')
1050
        ptr++;
1051
      end_ptr = strchr (ptr, '-');
1052
      if (!end_ptr)
1053
        end_ptr = ptr + strlen (ptr);
1054
      length = end_ptr - ptr;
1055
 
1056
      for (option_ptr = dump_options; option_ptr->name; option_ptr++)
1057
        if (strlen (option_ptr->name) == length
1058
            && !memcmp (option_ptr->name, ptr, length))
1059
          {
1060
            flags |= option_ptr->value;
1061
            goto found;
1062
          }
1063
      warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
1064
               length, ptr, dfi->swtch);
1065
    found:;
1066
      ptr = end_ptr;
1067
    }
1068
 
1069
  dfi->state = -1;
1070
  dfi->flags |= flags;
1071
 
1072
  /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
1073
     known dumps.  */
1074
  if (dfi->suffix == NULL)
1075
    dump_enable_all (dfi->flags);
1076
 
1077
  return 1;
1078
}
1079
 
1080
int
1081
dump_switch_p (const char *arg)
1082
{
1083
  size_t i;
1084
  int any = 0;
1085
 
1086
  for (i = TDI_none + 1; i != TDI_end; i++)
1087
    any |= dump_switch_p_1 (arg, &dump_files[i], false);
1088
 
1089
  /* Don't glob if we got a hit already */
1090
  if (!any)
1091
    for (i = TDI_none + 1; i != TDI_end; i++)
1092
      any |= dump_switch_p_1 (arg, &dump_files[i], true);
1093
 
1094
  for (i = 0; i < extra_dump_files_in_use; i++)
1095
    any |= dump_switch_p_1 (arg, &extra_dump_files[i], false);
1096
 
1097
  if (!any)
1098
    for (i = 0; i < extra_dump_files_in_use; i++)
1099
      any |= dump_switch_p_1 (arg, &extra_dump_files[i], true);
1100
 
1101
 
1102
  return any;
1103
}
1104
 
1105
/* Dump FUNCTION_DECL FN as tree dump PHASE.  */
1106
 
1107
void
1108
dump_function (int phase, tree fn)
1109
{
1110
  FILE *stream;
1111
  int flags;
1112
 
1113
  stream = dump_begin (phase, &flags);
1114
  if (stream)
1115
    {
1116
      dump_function_to_file (fn, stream, flags);
1117
      dump_end (phase, stream);
1118
    }
1119
}
1120
 
1121
bool
1122
enable_rtl_dump_file (void)
1123
{
1124
  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0;
1125
}

powered by: WebSVN 2.1.0

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