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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [tree-dump.c] - Blame information for rev 775

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

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

powered by: WebSVN 2.1.0

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