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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [tree-dump.c] - Blame information for rev 20

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

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

powered by: WebSVN 2.1.0

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