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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [tree-dump.c] - Blame information for rev 816

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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