00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "config.h"
00027 #include "system.h"
00028 #ifdef SGI_MONGOOSE
00029
00030 #include "rtl.h"
00031 #endif
00032 #include "tree.h"
00033 #include "splay-tree.h"
00034 #include "diagnostic.h"
00035 #include "toplev.h"
00036 #include "tree-dump.h"
00037 #include "langhooks.h"
00038
00039 static unsigned int queue PARAMS ((dump_info_p, tree, int));
00040 static void dump_index PARAMS ((dump_info_p, unsigned int));
00041 static void dequeue_and_dump PARAMS ((dump_info_p));
00042 static void dump_new_line PARAMS ((dump_info_p));
00043 static void dump_maybe_newline PARAMS ((dump_info_p));
00044 static void dump_string_field PARAMS ((dump_info_p, const char *, const char *));
00045
00046
00047
00048
00049 static unsigned int
00050 queue (di, t, flags)
00051 dump_info_p di;
00052 tree t;
00053 int flags;
00054 {
00055 dump_queue_p dq;
00056 dump_node_info_p dni;
00057 unsigned int index;
00058
00059
00060 index = ++di->index;
00061
00062
00063 if (di->free_list)
00064 {
00065 dq = di->free_list;
00066 di->free_list = dq->next;
00067 }
00068 else
00069 dq = (dump_queue_p) xmalloc (sizeof (struct dump_queue));
00070
00071
00072 dni = (dump_node_info_p) xmalloc (sizeof (struct dump_node_info));
00073 dni->index = index;
00074 dni->binfo_p = ((flags & DUMP_BINFO) != 0);
00075 dq->node = splay_tree_insert (di->nodes, (splay_tree_key) t,
00076 (splay_tree_value) dni);
00077
00078
00079 dq->next = 0;
00080 if (!di->queue_end)
00081 di->queue = dq;
00082 else
00083 di->queue_end->next = dq;
00084 di->queue_end = dq;
00085
00086
00087 return index;
00088 }
00089
00090 static void
00091 dump_index (di, index)
00092 dump_info_p di;
00093 unsigned int index;
00094 {
00095 fprintf (di->stream, "@%-6u ", index);
00096 di->column += 8;
00097 }
00098
00099
00100
00101
00102
00103 void
00104 queue_and_dump_index (di, field, t, flags)
00105 dump_info_p di;
00106 const char *field;
00107 tree t;
00108 int flags;
00109 {
00110 unsigned int index;
00111 splay_tree_node n;
00112
00113
00114
00115 if (!t)
00116 return;
00117
00118
00119 n = splay_tree_lookup (di->nodes, (splay_tree_key) t);
00120 if (n)
00121 index = ((dump_node_info_p) n->value)->index;
00122 else
00123
00124 index = queue (di, t, flags);
00125
00126
00127 dump_maybe_newline (di);
00128 fprintf (di->stream, "%-4s: ", field);
00129 di->column += 6;
00130 dump_index (di, index);
00131 }
00132
00133
00134
00135 void
00136 queue_and_dump_type (di, t)
00137 dump_info_p di;
00138 tree t;
00139 {
00140 queue_and_dump_index (di, "type", TREE_TYPE (t), DUMP_NONE);
00141 }
00142
00143
00144 #define SOL_COLUMN 25
00145 #define EOL_COLUMN 55
00146 #define COLUMN_ALIGNMENT 15
00147
00148
00149
00150
00151 static void
00152 dump_new_line (di)
00153 dump_info_p di;
00154 {
00155 fprintf (di->stream, "\n%*s", SOL_COLUMN, "");
00156 di->column = SOL_COLUMN;
00157 }
00158
00159
00160
00161 static void
00162 dump_maybe_newline (di)
00163 dump_info_p di;
00164 {
00165 int extra;
00166
00167
00168 if (di->column > EOL_COLUMN)
00169 dump_new_line (di);
00170
00171 else if ((extra = (di->column - SOL_COLUMN) % COLUMN_ALIGNMENT) != 0)
00172 {
00173 fprintf (di->stream, "%*s", COLUMN_ALIGNMENT - extra, "");
00174 di->column += COLUMN_ALIGNMENT - extra;
00175 }
00176 }
00177
00178
00179
00180 void
00181 dump_pointer (di, field, ptr)
00182 dump_info_p di;
00183 const char *field;
00184 void *ptr;
00185 {
00186 dump_maybe_newline (di);
00187 fprintf (di->stream, "%-4s: %-8lx ", field, (long) ptr);
00188 di->column += 15;
00189 }
00190
00191
00192
00193 void
00194 dump_int (di, field, i)
00195 dump_info_p di;
00196 const char *field;
00197 int i;
00198 {
00199 dump_maybe_newline (di);
00200 fprintf (di->stream, "%-4s: %-7d ", field, i);
00201 di->column += 14;
00202 }
00203
00204
00205
00206 void
00207 dump_string (di, string)
00208 dump_info_p di;
00209 const char *string;
00210 {
00211 dump_maybe_newline (di);
00212 fprintf (di->stream, "%-13s ", string);
00213 if (strlen (string) > 13)
00214 di->column += strlen (string) + 1;
00215 else
00216 di->column += 14;
00217 }
00218
00219
00220
00221 static void
00222 dump_string_field (di, field, string)
00223 dump_info_p di;
00224 const char *field;
00225 const char *string;
00226 {
00227 dump_maybe_newline (di);
00228 fprintf (di->stream, "%-4s: %-7s ", field, string);
00229 if (strlen (string) > 7)
00230 di->column += 6 + strlen (string) + 1;
00231 else
00232 di->column += 14;
00233 }
00234
00235
00236
00237 static void
00238 dequeue_and_dump (di)
00239 dump_info_p di;
00240 {
00241 dump_queue_p dq;
00242 splay_tree_node stn;
00243 dump_node_info_p dni;
00244 tree t;
00245 unsigned int index;
00246 enum tree_code code;
00247 char code_class;
00248 const char* code_name;
00249
00250
00251 dq = di->queue;
00252 stn = dq->node;
00253 t = (tree) stn->key;
00254 dni = (dump_node_info_p) stn->value;
00255 index = dni->index;
00256
00257
00258 di->queue = dq->next;
00259 if (!di->queue)
00260 di->queue_end = 0;
00261 dq->next = di->free_list;
00262 di->free_list = dq;
00263
00264
00265 dump_index (di, index);
00266
00267 #ifdef KEY
00268
00269 fprintf (di->stream, "%p ", t);
00270 #endif
00271
00272
00273 if (dni->binfo_p)
00274 code_name = "binfo";
00275 else
00276 code_name = tree_code_name[(int) TREE_CODE (t)];
00277 fprintf (di->stream, "%-16s ", code_name);
00278 di->column = 25;
00279
00280
00281 code = TREE_CODE (t);
00282 code_class = TREE_CODE_CLASS (code);
00283
00284
00285
00286 if (dni->binfo_p)
00287 {
00288 if (TREE_VIA_PUBLIC (t))
00289 dump_string (di, "pub");
00290 else if (TREE_VIA_PROTECTED (t))
00291 dump_string (di, "prot");
00292 else if (TREE_VIA_PRIVATE (t))
00293 dump_string (di, "priv");
00294 if (TREE_VIA_VIRTUAL (t))
00295 dump_string (di, "virt");
00296
00297 dump_child ("type", BINFO_TYPE (t));
00298 dump_child ("base", BINFO_BASETYPES (t));
00299
00300 goto done;
00301 }
00302
00303
00304
00305 if (IS_EXPR_CODE_CLASS (code_class))
00306 {
00307
00308 queue_and_dump_type (di, t);
00309
00310 switch (code_class)
00311 {
00312 case '1':
00313 dump_child ("op 0", TREE_OPERAND (t, 0));
00314 break;
00315
00316 case '2':
00317 case '<':
00318 dump_child ("op 0", TREE_OPERAND (t, 0));
00319 dump_child ("op 1", TREE_OPERAND (t, 1));
00320 break;
00321
00322 case 'e':
00323
00324 break;
00325
00326 default:
00327 abort ();
00328 }
00329 }
00330 else if (DECL_P (t))
00331 {
00332
00333 if (DECL_NAME (t))
00334 dump_child ("name", DECL_NAME (t));
00335 if (DECL_ASSEMBLER_NAME_SET_P (t)
00336 && DECL_ASSEMBLER_NAME (t) != DECL_NAME (t))
00337 dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
00338
00339 queue_and_dump_type (di, t);
00340 dump_child ("scpe", DECL_CONTEXT (t));
00341
00342 if (DECL_SOURCE_FILE (t))
00343 {
00344 const char *filename = strrchr (DECL_SOURCE_FILE (t), '/');
00345 if (!filename)
00346 filename = DECL_SOURCE_FILE (t);
00347 else
00348
00349 ++filename;
00350
00351 dump_maybe_newline (di);
00352 fprintf (di->stream, "srcp: %s:%-6d ", filename,
00353 DECL_SOURCE_LINE (t));
00354 di->column += 6 + strlen (filename) + 8;
00355 }
00356
00357 if (DECL_ARTIFICIAL (t))
00358 dump_string (di, "artificial");
00359 if (TREE_CHAIN (t) && !dump_flag (di, TDF_SLIM, NULL))
00360 dump_child ("chan", TREE_CHAIN (t));
00361 }
00362 else if (code_class == 't')
00363 {
00364
00365 int quals = (*lang_hooks.tree_dump.type_quals) (t);
00366
00367 if (quals != TYPE_UNQUALIFIED)
00368 {
00369 fprintf (di->stream, "qual: %c%c%c ",
00370 (quals & TYPE_QUAL_CONST) ? 'c' : ' ',
00371 (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ',
00372 (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' ');
00373 di->column += 14;
00374 }
00375
00376
00377 dump_child ("name", TYPE_NAME (t));
00378
00379
00380 if (TYPE_MAIN_VARIANT (t) != t)
00381 dump_child ("unql", TYPE_MAIN_VARIANT (t));
00382
00383
00384 dump_child ("size", TYPE_SIZE (t));
00385
00386
00387 dump_int (di, "algn", TYPE_ALIGN (t));
00388 }
00389 else if (code_class == 'c')
00390
00391 queue_and_dump_type (di, t);
00392
00393
00394
00395
00396 if ((*lang_hooks.tree_dump.dump_tree) (di, t))
00397 goto done;
00398
00399
00400 switch (code)
00401 {
00402 int i;
00403
00404 case IDENTIFIER_NODE:
00405 dump_string_field (di, "strg", IDENTIFIER_POINTER (t));
00406 dump_int (di, "lngt", IDENTIFIER_LENGTH (t));
00407 break;
00408
00409 case TREE_LIST:
00410 dump_child ("purp", TREE_PURPOSE (t));
00411 dump_child ("valu", TREE_VALUE (t));
00412 dump_child ("chan", TREE_CHAIN (t));
00413 break;
00414
00415 case TREE_VEC:
00416 dump_int (di, "lngt", TREE_VEC_LENGTH (t));
00417 for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
00418 {
00419 char buffer[32];
00420 sprintf (buffer, "%u", i);
00421 dump_child (buffer, TREE_VEC_ELT (t, i));
00422 }
00423 break;
00424
00425 case INTEGER_TYPE:
00426 case ENUMERAL_TYPE:
00427 dump_int (di, "prec", TYPE_PRECISION (t));
00428 if (TREE_UNSIGNED (t))
00429 dump_string (di, "unsigned");
00430 dump_child ("min", TYPE_MIN_VALUE (t));
00431 dump_child ("max", TYPE_MAX_VALUE (t));
00432
00433 if (code == ENUMERAL_TYPE)
00434 dump_child ("csts", TYPE_VALUES (t));
00435 break;
00436
00437 case REAL_TYPE:
00438 dump_int (di, "prec", TYPE_PRECISION (t));
00439 break;
00440
00441 case POINTER_TYPE:
00442 dump_child ("ptd", TREE_TYPE (t));
00443 break;
00444
00445 case REFERENCE_TYPE:
00446 dump_child ("refd", TREE_TYPE (t));
00447 break;
00448
00449 case METHOD_TYPE:
00450 dump_child ("clas", TYPE_METHOD_BASETYPE (t));
00451
00452
00453 case FUNCTION_TYPE:
00454 dump_child ("retn", TREE_TYPE (t));
00455 dump_child ("prms", TYPE_ARG_TYPES (t));
00456 break;
00457
00458 case ARRAY_TYPE:
00459 dump_child ("elts", TREE_TYPE (t));
00460 dump_child ("domn", TYPE_DOMAIN (t));
00461 break;
00462
00463 case RECORD_TYPE:
00464 case UNION_TYPE:
00465 if (TREE_CODE (t) == RECORD_TYPE)
00466 dump_string (di, "struct");
00467 else
00468 dump_string (di, "union");
00469
00470 dump_child ("flds", TYPE_FIELDS (t));
00471 dump_child ("fncs", TYPE_METHODS (t));
00472 queue_and_dump_index (di, "binf", TYPE_BINFO (t),
00473 DUMP_BINFO);
00474 break;
00475
00476 case CONST_DECL:
00477 dump_child ("cnst", DECL_INITIAL (t));
00478 break;
00479
00480 case VAR_DECL:
00481 case PARM_DECL:
00482 case FIELD_DECL:
00483 case RESULT_DECL:
00484 if (TREE_CODE (t) == PARM_DECL)
00485 dump_child ("argt", DECL_ARG_TYPE (t));
00486 else
00487 dump_child ("init", DECL_INITIAL (t));
00488 dump_child ("size", DECL_SIZE (t));
00489 dump_int (di, "algn", DECL_ALIGN (t));
00490
00491 if (TREE_CODE (t) == FIELD_DECL)
00492 {
00493 if (DECL_FIELD_OFFSET (t))
00494 dump_child ("bpos", bit_position (t));
00495 }
00496 else if (TREE_CODE (t) == VAR_DECL
00497 || TREE_CODE (t) == PARM_DECL)
00498 {
00499 dump_int (di, "used", TREE_USED (t));
00500 if (DECL_REGISTER (t))
00501 dump_string (di, "register");
00502 }
00503 break;
00504
00505 case FUNCTION_DECL:
00506 dump_child ("args", DECL_ARGUMENTS (t));
00507 if (DECL_EXTERNAL (t))
00508 dump_string (di, "undefined");
00509 if (TREE_PUBLIC (t))
00510 dump_string (di, "extern");
00511 else
00512 dump_string (di, "static");
00513 if (DECL_LANG_SPECIFIC (t) && !dump_flag (di, TDF_SLIM, t))
00514 dump_child ("body", DECL_SAVED_TREE (t));
00515 break;
00516
00517 case INTEGER_CST:
00518 if (TREE_INT_CST_HIGH (t))
00519 dump_int (di, "high", TREE_INT_CST_HIGH (t));
00520 dump_int (di, "low", TREE_INT_CST_LOW (t));
00521 break;
00522
00523 case STRING_CST:
00524 fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t));
00525 dump_int (di, "lngt", TREE_STRING_LENGTH (t));
00526 break;
00527
00528 case TRUTH_NOT_EXPR:
00529 case ADDR_EXPR:
00530 case INDIRECT_REF:
00531 case CLEANUP_POINT_EXPR:
00532 case SAVE_EXPR:
00533
00534 dump_child ("op 0", TREE_OPERAND (t, 0));
00535 break;
00536
00537 case TRUTH_ANDIF_EXPR:
00538 case TRUTH_ORIF_EXPR:
00539 case INIT_EXPR:
00540 case MODIFY_EXPR:
00541 case COMPONENT_REF:
00542 case COMPOUND_EXPR:
00543 case ARRAY_REF:
00544 case PREDECREMENT_EXPR:
00545 case PREINCREMENT_EXPR:
00546 case POSTDECREMENT_EXPR:
00547 case POSTINCREMENT_EXPR:
00548
00549 dump_child ("op 0", TREE_OPERAND (t, 0));
00550 dump_child ("op 1", TREE_OPERAND (t, 1));
00551 break;
00552
00553 case COND_EXPR:
00554 dump_child ("op 0", TREE_OPERAND (t, 0));
00555 dump_child ("op 1", TREE_OPERAND (t, 1));
00556 dump_child ("op 2", TREE_OPERAND (t, 2));
00557 break;
00558
00559 case CALL_EXPR:
00560 dump_child ("fn", TREE_OPERAND (t, 0));
00561 dump_child ("args", TREE_OPERAND (t, 1));
00562 break;
00563
00564 case CONSTRUCTOR:
00565 dump_child ("elts", TREE_OPERAND (t, 1));
00566 break;
00567
00568 case BIND_EXPR:
00569 dump_child ("vars", TREE_OPERAND (t, 0));
00570 dump_child ("body", TREE_OPERAND (t, 1));
00571 break;
00572
00573 case LOOP_EXPR:
00574 dump_child ("body", TREE_OPERAND (t, 0));
00575 break;
00576
00577 case EXIT_EXPR:
00578 dump_child ("cond", TREE_OPERAND (t, 0));
00579 break;
00580
00581 case TARGET_EXPR:
00582 dump_child ("decl", TREE_OPERAND (t, 0));
00583 dump_child ("init", TREE_OPERAND (t, 1));
00584 dump_child ("clnp", TREE_OPERAND (t, 2));
00585
00586
00587
00588
00589 dump_child ("init", TREE_OPERAND (t, 3));
00590 break;
00591
00592 case EXPR_WITH_FILE_LOCATION:
00593 dump_child ("expr", EXPR_WFL_NODE (t));
00594 break;
00595
00596 default:
00597
00598 break;
00599 }
00600
00601 done:
00602 if (dump_flag (di, TDF_ADDRESS, NULL))
00603 dump_pointer (di, "addr", (void *)t);
00604
00605
00606 fprintf (di->stream, "\n");
00607 }
00608
00609
00610
00611
00612 int dump_flag (di, flag, node)
00613 dump_info_p di;
00614 int flag;
00615 tree node;
00616 {
00617 return (di->flags & flag) && (node != di->node);
00618 }
00619
00620
00621
00622 void
00623 dump_node (t, flags, stream)
00624 tree t;
00625 int flags;
00626 FILE *stream;
00627 {
00628 struct dump_info di;
00629 dump_queue_p dq;
00630 dump_queue_p next_dq;
00631
00632
00633 di.stream = stream;
00634 di.index = 0;
00635 di.column = 0;
00636 di.queue = 0;
00637 di.queue_end = 0;
00638 di.free_list = 0;
00639 di.flags = flags;
00640 di.node = t;
00641 di.nodes = splay_tree_new (splay_tree_compare_pointers, 0,
00642 (splay_tree_delete_value_fn) &free);
00643
00644
00645 queue (&di, t, DUMP_NONE);
00646
00647
00648 while (di.queue)
00649 dequeue_and_dump (&di);
00650
00651
00652 for (dq = di.free_list; dq; dq = next_dq)
00653 {
00654 next_dq = dq->next;
00655 free (dq);
00656 }
00657 splay_tree_delete (di.nodes);
00658 }
00659
00660
00661 struct dump_file_info
00662 {
00663 const char *const suffix;
00664 const char *const swtch;
00665 int flags;
00666 int state;
00667 };
00668
00669
00670
00671 static struct dump_file_info dump_files[TDI_end] =
00672 {
00673 {".tu", "dump-translation-unit", 0, 0},
00674 {".class", "dump-class-hierarchy", 0, 0},
00675 {".original", "dump-tree-original", 0, 0},
00676 {".optimized", "dump-tree-optimized", 0, 0},
00677 {".inlined", "dump-tree-inlined", 0, 0},
00678 };
00679
00680
00681 struct dump_option_value_info
00682 {
00683 const char *const name;
00684 const int value;
00685 };
00686
00687
00688
00689 static const struct dump_option_value_info dump_options[] =
00690 {
00691 {"address", TDF_ADDRESS},
00692 {"slim", TDF_SLIM},
00693 {"all", ~0},
00694 {NULL, 0}
00695 };
00696
00697
00698
00699
00700
00701
00702 FILE *
00703 dump_begin (phase, flag_ptr)
00704 enum tree_dump_index phase;
00705 int *flag_ptr;
00706 {
00707 FILE *stream;
00708 char *name;
00709
00710 if (!dump_files[phase].state)
00711 return NULL;
00712
00713 name = concat (dump_base_name, dump_files[phase].suffix, NULL);
00714 stream = fopen (name, dump_files[phase].state < 0 ? "w" : "a");
00715 if (!stream)
00716 error ("could not open dump file `%s'", name);
00717 else
00718 dump_files[phase].state = 1;
00719 free (name);
00720 if (flag_ptr)
00721 *flag_ptr = dump_files[phase].flags;
00722
00723 return stream;
00724 }
00725
00726
00727
00728 int
00729 dump_enabled_p (phase)
00730 enum tree_dump_index phase;
00731 {
00732 return dump_files[phase].state;
00733 }
00734
00735
00736
00737 const char *
00738 dump_flag_name (phase)
00739 enum tree_dump_index phase;
00740 {
00741 return dump_files[phase].swtch;
00742 }
00743
00744
00745
00746
00747 void
00748 dump_end (phase, stream)
00749 enum tree_dump_index phase ATTRIBUTE_UNUSED;
00750 FILE *stream;
00751 {
00752 fclose (stream);
00753 }
00754
00755
00756
00757
00758 int
00759 dump_switch_p (arg)
00760 const char *arg;
00761 {
00762 unsigned ix;
00763 const char *option_value;
00764
00765 for (ix = 0; ix != TDI_end; ix++)
00766 if ((option_value = skip_leading_substring (arg, dump_files[ix].swtch)))
00767 {
00768 const char *ptr = option_value;
00769 int flags = 0;
00770
00771 while (*ptr)
00772 {
00773 const struct dump_option_value_info *option_ptr;
00774 const char *end_ptr;
00775 unsigned length;
00776
00777 while (*ptr == '-')
00778 ptr++;
00779 end_ptr = strchr (ptr, '-');
00780 if (!end_ptr)
00781 end_ptr = ptr + strlen (ptr);
00782 length = end_ptr - ptr;
00783
00784 for (option_ptr = dump_options; option_ptr->name;
00785 option_ptr++)
00786 if (strlen (option_ptr->name) == length
00787 && !memcmp (option_ptr->name, ptr, length))
00788 {
00789 flags |= option_ptr->value;
00790 goto found;
00791 }
00792 warning ("ignoring unknown option `%.*s' in `-f%s'",
00793 length, ptr, dump_files[ix].swtch);
00794 found:;
00795 ptr = end_ptr;
00796 }
00797
00798 dump_files[ix].state = -1;
00799 dump_files[ix].flags = flags;
00800
00801 return 1;
00802 }
00803 return 0;
00804 }