00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "system.h"
00025 #include "coretypes.h"
00026 #include "tm.h"
00027 #include "tree.h"
00028 #include "splay-tree.h"
00029 #include "diagnostic.h"
00030 #include "toplev.h"
00031 #include "tree-dump.h"
00032 #include "tree-pass.h"
00033 #include "langhooks.h"
00034 #include "tree-iterator.h"
00035 #include "real.h"
00036
00037 static unsigned int queue (dump_info_p, tree, int);
00038 static void dump_index (dump_info_p, unsigned int);
00039 static void dequeue_and_dump (dump_info_p);
00040 static void dump_new_line (dump_info_p);
00041 static void dump_maybe_newline (dump_info_p);
00042 static int dump_enable_all (int, int);
00043
00044
00045
00046
00047 static unsigned int
00048 queue (dump_info_p di, tree t, int flags)
00049 {
00050 dump_queue_p dq;
00051 dump_node_info_p dni;
00052 unsigned int index;
00053
00054
00055 index = ++di->index;
00056
00057
00058 if (di->free_list)
00059 {
00060 dq = di->free_list;
00061 di->free_list = dq->next;
00062 }
00063 else
00064 dq = XNEW (struct dump_queue);
00065
00066
00067 dni = XNEW (struct dump_node_info);
00068 dni->index = index;
00069 dni->binfo_p = ((flags & DUMP_BINFO) != 0);
00070 dq->node = splay_tree_insert (di->nodes, (splay_tree_key) t,
00071 (splay_tree_value) dni);
00072
00073
00074 dq->next = 0;
00075 if (!di->queue_end)
00076 di->queue = dq;
00077 else
00078 di->queue_end->next = dq;
00079 di->queue_end = dq;
00080
00081
00082 return index;
00083 }
00084
00085 static void
00086 dump_index (dump_info_p di, unsigned int index)
00087 {
00088 fprintf (di->stream, "@%-6u ", index);
00089 di->column += 8;
00090 }
00091
00092
00093
00094
00095
00096 void
00097 queue_and_dump_index (dump_info_p di, const char *field, tree t, int flags)
00098 {
00099 unsigned int index;
00100 splay_tree_node n;
00101
00102
00103
00104 if (!t)
00105 return;
00106
00107
00108 n = splay_tree_lookup (di->nodes, (splay_tree_key) t);
00109 if (n)
00110 index = ((dump_node_info_p) n->value)->index;
00111 else
00112
00113 index = queue (di, t, flags);
00114
00115
00116 dump_maybe_newline (di);
00117 fprintf (di->stream, "%-4s: ", field);
00118 di->column += 6;
00119 dump_index (di, index);
00120 }
00121
00122
00123
00124 void
00125 queue_and_dump_type (dump_info_p di, tree t)
00126 {
00127 queue_and_dump_index (di, "type", TREE_TYPE (t), DUMP_NONE);
00128 }
00129
00130
00131 #define SOL_COLUMN 25
00132 #define EOL_COLUMN 55
00133 #define COLUMN_ALIGNMENT 15
00134
00135
00136
00137
00138 static void
00139 dump_new_line (dump_info_p di)
00140 {
00141 fprintf (di->stream, "\n%*s", SOL_COLUMN, "");
00142 di->column = SOL_COLUMN;
00143 }
00144
00145
00146
00147 static void
00148 dump_maybe_newline (dump_info_p di)
00149 {
00150 int extra;
00151
00152
00153 if (di->column > EOL_COLUMN)
00154 dump_new_line (di);
00155
00156 else if ((extra = (di->column - SOL_COLUMN) % COLUMN_ALIGNMENT) != 0)
00157 {
00158 fprintf (di->stream, "%*s", COLUMN_ALIGNMENT - extra, "");
00159 di->column += COLUMN_ALIGNMENT - extra;
00160 }
00161 }
00162
00163
00164
00165 void
00166 dump_pointer (dump_info_p di, const char *field, void *ptr)
00167 {
00168 dump_maybe_newline (di);
00169 fprintf (di->stream, "%-4s: %-8lx ", field, (long) ptr);
00170 di->column += 15;
00171 }
00172
00173
00174
00175 void
00176 dump_int (dump_info_p di, const char *field, int i)
00177 {
00178 dump_maybe_newline (di);
00179 fprintf (di->stream, "%-4s: %-7d ", field, i);
00180 di->column += 14;
00181 }
00182
00183
00184
00185 static void
00186 dump_real (dump_info_p di, const char *field, const REAL_VALUE_TYPE *r)
00187 {
00188 char buf[32];
00189 real_to_decimal (buf, r, sizeof (buf), 0, true);
00190 dump_maybe_newline (di);
00191 fprintf (di->stream, "%-4s: %s ", field, buf);
00192 di->column += strlen (buf) + 7;
00193 }
00194
00195
00196
00197
00198 void
00199 dump_string (dump_info_p di, const char *string)
00200 {
00201 dump_maybe_newline (di);
00202 fprintf (di->stream, "%-13s ", string);
00203 if (strlen (string) > 13)
00204 di->column += strlen (string) + 1;
00205 else
00206 di->column += 14;
00207 }
00208
00209
00210
00211 void
00212 dump_string_field (dump_info_p di, const char *field, const char *string)
00213 {
00214 dump_maybe_newline (di);
00215 fprintf (di->stream, "%-4s: %-7s ", field, string);
00216 if (strlen (string) > 7)
00217 di->column += 6 + strlen (string) + 1;
00218 else
00219 di->column += 14;
00220 }
00221
00222
00223
00224 static void
00225 dequeue_and_dump (dump_info_p di)
00226 {
00227 dump_queue_p dq;
00228 splay_tree_node stn;
00229 dump_node_info_p dni;
00230 tree t;
00231 unsigned int index;
00232 enum tree_code code;
00233 enum tree_code_class code_class;
00234 const char* code_name;
00235
00236
00237 dq = di->queue;
00238 stn = dq->node;
00239 t = (tree) stn->key;
00240 dni = (dump_node_info_p) stn->value;
00241 index = dni->index;
00242
00243
00244 di->queue = dq->next;
00245 if (!di->queue)
00246 di->queue_end = 0;
00247 dq->next = di->free_list;
00248 di->free_list = dq;
00249
00250
00251 dump_index (di, index);
00252
00253 if (dni->binfo_p)
00254 code_name = "binfo";
00255 else
00256 code_name = tree_code_name[(int) TREE_CODE (t)];
00257 fprintf (di->stream, "%-16s ", code_name);
00258 di->column = 25;
00259
00260
00261 code = TREE_CODE (t);
00262 code_class = TREE_CODE_CLASS (code);
00263
00264
00265
00266 if (dni->binfo_p)
00267 {
00268 unsigned ix;
00269 tree base;
00270 VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (t);
00271
00272 dump_child ("type", BINFO_TYPE (t));
00273
00274 if (BINFO_VIRTUAL_P (t))
00275 dump_string_field (di, "spec", "virt");
00276
00277 dump_int (di, "bases", BINFO_N_BASE_BINFOS (t));
00278 for (ix = 0; BINFO_BASE_ITERATE (t, ix, base); ix++)
00279 {
00280 tree access = (accesses ? VEC_index (tree, accesses, ix)
00281 : access_public_node);
00282 const char *string = NULL;
00283
00284 if (access == access_public_node)
00285 string = "pub";
00286 else if (access == access_protected_node)
00287 string = "prot";
00288 else if (access == access_private_node)
00289 string = "priv";
00290 else
00291 gcc_unreachable ();
00292
00293 dump_string_field (di, "accs", string);
00294 queue_and_dump_index (di, "binf", base, DUMP_BINFO);
00295 }
00296
00297 goto done;
00298 }
00299
00300
00301
00302 if (IS_EXPR_CODE_CLASS (code_class))
00303 {
00304
00305 queue_and_dump_type (di, t);
00306
00307 switch (code_class)
00308 {
00309 case tcc_unary:
00310 dump_child ("op 0", TREE_OPERAND (t, 0));
00311 break;
00312
00313 case tcc_binary:
00314 case tcc_comparison:
00315 dump_child ("op 0", TREE_OPERAND (t, 0));
00316 dump_child ("op 1", TREE_OPERAND (t, 1));
00317 break;
00318
00319 case tcc_expression:
00320 case tcc_reference:
00321 case tcc_statement:
00322
00323 break;
00324
00325 default:
00326 gcc_unreachable ();
00327 }
00328 }
00329 else if (DECL_P (t))
00330 {
00331 expanded_location xloc;
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 if (DECL_ABSTRACT_ORIGIN (t))
00339 dump_child ("orig", DECL_ABSTRACT_ORIGIN (t));
00340
00341 queue_and_dump_type (di, t);
00342 dump_child ("scpe", DECL_CONTEXT (t));
00343
00344 xloc = expand_location (DECL_SOURCE_LOCATION (t));
00345 if (xloc.file)
00346 {
00347 const char *filename = strrchr (xloc.file, '/');
00348 if (!filename)
00349 filename = xloc.file;
00350 else
00351
00352 ++filename;
00353
00354 dump_maybe_newline (di);
00355 fprintf (di->stream, "srcp: %s:%-6d ", filename,
00356 xloc.line);
00357 di->column += 6 + strlen (filename) + 8;
00358 }
00359
00360 if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_COMMON)
00361 && DECL_ARTIFICIAL (t))
00362 dump_string_field (di, "note", "artificial");
00363 if (TREE_CHAIN (t) && !dump_flag (di, TDF_SLIM, NULL))
00364 dump_child ("chan", TREE_CHAIN (t));
00365 }
00366 else if (code_class == tcc_type)
00367 {
00368
00369 int quals = lang_hooks.tree_dump.type_quals (t);
00370
00371 if (quals != TYPE_UNQUALIFIED)
00372 {
00373 fprintf (di->stream, "qual: %c%c%c ",
00374 (quals & TYPE_QUAL_CONST) ? 'c' : ' ',
00375 (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ',
00376 (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' ');
00377 di->column += 14;
00378 }
00379
00380
00381 dump_child ("name", TYPE_NAME (t));
00382
00383
00384 if (TYPE_MAIN_VARIANT (t) != t)
00385 dump_child ("unql", TYPE_MAIN_VARIANT (t));
00386
00387
00388 dump_child ("size", TYPE_SIZE (t));
00389
00390
00391 dump_int (di, "algn", TYPE_ALIGN (t));
00392 }
00393 else if (code_class == tcc_constant)
00394
00395 queue_and_dump_type (di, t);
00396
00397
00398
00399
00400 if (lang_hooks.tree_dump.dump_tree (di, t))
00401 goto done;
00402
00403
00404 switch (code)
00405 {
00406 int i;
00407
00408 case IDENTIFIER_NODE:
00409 dump_string_field (di, "strg", IDENTIFIER_POINTER (t));
00410 dump_int (di, "lngt", IDENTIFIER_LENGTH (t));
00411 break;
00412
00413 case TREE_LIST:
00414 dump_child ("purp", TREE_PURPOSE (t));
00415 dump_child ("valu", TREE_VALUE (t));
00416 dump_child ("chan", TREE_CHAIN (t));
00417 break;
00418
00419 case STATEMENT_LIST:
00420 {
00421 tree_stmt_iterator it;
00422 for (i = 0, it = tsi_start (t); !tsi_end_p (it); tsi_next (&it), i++)
00423 {
00424 char buffer[32];
00425 sprintf (buffer, "%u", i);
00426 dump_child (buffer, tsi_stmt (it));
00427 }
00428 }
00429 break;
00430
00431 case TREE_VEC:
00432 dump_int (di, "lngt", TREE_VEC_LENGTH (t));
00433 for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
00434 {
00435 char buffer[32];
00436 sprintf (buffer, "%u", i);
00437 dump_child (buffer, TREE_VEC_ELT (t, i));
00438 }
00439 break;
00440
00441 case INTEGER_TYPE:
00442 case ENUMERAL_TYPE:
00443 dump_int (di, "prec", TYPE_PRECISION (t));
00444 dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed");
00445 dump_child ("min", TYPE_MIN_VALUE (t));
00446 dump_child ("max", TYPE_MAX_VALUE (t));
00447
00448 if (code == ENUMERAL_TYPE)
00449 dump_child ("csts", TYPE_VALUES (t));
00450 break;
00451
00452 case REAL_TYPE:
00453 dump_int (di, "prec", TYPE_PRECISION (t));
00454 break;
00455
00456 case POINTER_TYPE:
00457 dump_child ("ptd", TREE_TYPE (t));
00458 break;
00459
00460 case REFERENCE_TYPE:
00461 dump_child ("refd", TREE_TYPE (t));
00462 break;
00463
00464 case METHOD_TYPE:
00465 dump_child ("clas", TYPE_METHOD_BASETYPE (t));
00466
00467
00468 case FUNCTION_TYPE:
00469 dump_child ("retn", TREE_TYPE (t));
00470 dump_child ("prms", TYPE_ARG_TYPES (t));
00471 break;
00472
00473 case ARRAY_TYPE:
00474 dump_child ("elts", TREE_TYPE (t));
00475 dump_child ("domn", TYPE_DOMAIN (t));
00476 break;
00477
00478 case RECORD_TYPE:
00479 case UNION_TYPE:
00480 if (TREE_CODE (t) == RECORD_TYPE)
00481 dump_string_field (di, "tag", "struct");
00482 else
00483 dump_string_field (di, "tag", "union");
00484
00485 dump_child ("flds", TYPE_FIELDS (t));
00486 dump_child ("fncs", TYPE_METHODS (t));
00487 queue_and_dump_index (di, "binf", TYPE_BINFO (t),
00488 DUMP_BINFO);
00489 break;
00490
00491 case CONST_DECL:
00492 dump_child ("cnst", DECL_INITIAL (t));
00493 break;
00494
00495 case SYMBOL_MEMORY_TAG:
00496 case NAME_MEMORY_TAG:
00497 case STRUCT_FIELD_TAG:
00498 break;
00499
00500 case VAR_DECL:
00501 case PARM_DECL:
00502 case FIELD_DECL:
00503 case RESULT_DECL:
00504 if (TREE_CODE (t) == PARM_DECL)
00505 dump_child ("argt", DECL_ARG_TYPE (t));
00506 else
00507 dump_child ("init", DECL_INITIAL (t));
00508 dump_child ("size", DECL_SIZE (t));
00509 dump_int (di, "algn", DECL_ALIGN (t));
00510
00511 if (TREE_CODE (t) == FIELD_DECL)
00512 {
00513 if (DECL_FIELD_OFFSET (t))
00514 dump_child ("bpos", bit_position (t));
00515 }
00516 else if (TREE_CODE (t) == VAR_DECL
00517 || TREE_CODE (t) == PARM_DECL)
00518 {
00519 dump_int (di, "used", TREE_USED (t));
00520 if (DECL_REGISTER (t))
00521 dump_string_field (di, "spec", "register");
00522 }
00523 break;
00524
00525 case FUNCTION_DECL:
00526 dump_child ("args", DECL_ARGUMENTS (t));
00527 if (DECL_EXTERNAL (t))
00528 dump_string_field (di, "body", "undefined");
00529 if (TREE_PUBLIC (t))
00530 dump_string_field (di, "link", "extern");
00531 else
00532 dump_string_field (di, "link", "static");
00533 if (DECL_LANG_SPECIFIC (t) && !dump_flag (di, TDF_SLIM, t))
00534 dump_child ("body", DECL_SAVED_TREE (t));
00535 break;
00536
00537 case INTEGER_CST:
00538 if (TREE_INT_CST_HIGH (t))
00539 dump_int (di, "high", TREE_INT_CST_HIGH (t));
00540 dump_int (di, "low", TREE_INT_CST_LOW (t));
00541 break;
00542
00543 case STRING_CST:
00544 fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t));
00545 dump_int (di, "lngt", TREE_STRING_LENGTH (t));
00546 break;
00547
00548 case REAL_CST:
00549 dump_real (di, "valu", TREE_REAL_CST_PTR (t));
00550 break;
00551
00552 case TRUTH_NOT_EXPR:
00553 case ADDR_EXPR:
00554 case INDIRECT_REF:
00555 case ALIGN_INDIRECT_REF:
00556 case MISALIGNED_INDIRECT_REF:
00557 case CLEANUP_POINT_EXPR:
00558 case SAVE_EXPR:
00559 case REALPART_EXPR:
00560 case IMAGPART_EXPR:
00561
00562 dump_child ("op 0", TREE_OPERAND (t, 0));
00563 break;
00564
00565 case TRUTH_ANDIF_EXPR:
00566 case TRUTH_ORIF_EXPR:
00567 case INIT_EXPR:
00568 case MODIFY_EXPR:
00569 case COMPOUND_EXPR:
00570 case PREDECREMENT_EXPR:
00571 case PREINCREMENT_EXPR:
00572 case POSTDECREMENT_EXPR:
00573 case POSTINCREMENT_EXPR:
00574
00575 dump_child ("op 0", TREE_OPERAND (t, 0));
00576 dump_child ("op 1", TREE_OPERAND (t, 1));
00577 break;
00578
00579 case COMPONENT_REF:
00580 dump_child ("op 0", TREE_OPERAND (t, 0));
00581 dump_child ("op 1", TREE_OPERAND (t, 1));
00582 dump_child ("op 2", TREE_OPERAND (t, 2));
00583 break;
00584
00585 case ARRAY_REF:
00586 case ARRAY_RANGE_REF:
00587 dump_child ("op 0", TREE_OPERAND (t, 0));
00588 dump_child ("op 1", TREE_OPERAND (t, 1));
00589 dump_child ("op 2", TREE_OPERAND (t, 2));
00590 dump_child ("op 3", TREE_OPERAND (t, 3));
00591 break;
00592
00593 case COND_EXPR:
00594 dump_child ("op 0", TREE_OPERAND (t, 0));
00595 dump_child ("op 1", TREE_OPERAND (t, 1));
00596 dump_child ("op 2", TREE_OPERAND (t, 2));
00597 break;
00598
00599 case TRY_FINALLY_EXPR:
00600 dump_child ("op 0", TREE_OPERAND (t, 0));
00601 dump_child ("op 1", TREE_OPERAND (t, 1));
00602 break;
00603
00604 case CALL_EXPR:
00605 dump_child ("fn", TREE_OPERAND (t, 0));
00606 dump_child ("args", TREE_OPERAND (t, 1));
00607 break;
00608
00609 case CONSTRUCTOR:
00610 {
00611 unsigned HOST_WIDE_INT cnt;
00612 tree index, value;
00613 dump_int (di, "lngt", VEC_length (constructor_elt,
00614 CONSTRUCTOR_ELTS (t)));
00615 FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), cnt, index, value)
00616 {
00617 dump_child ("idx", index);
00618 dump_child ("val", value);
00619 }
00620 }
00621 break;
00622
00623 case BIND_EXPR:
00624 dump_child ("vars", TREE_OPERAND (t, 0));
00625 dump_child ("body", TREE_OPERAND (t, 1));
00626 break;
00627
00628 case LOOP_EXPR:
00629 dump_child ("body", TREE_OPERAND (t, 0));
00630 break;
00631
00632 case EXIT_EXPR:
00633 dump_child ("cond", TREE_OPERAND (t, 0));
00634 break;
00635
00636 case RETURN_EXPR:
00637 dump_child ("expr", TREE_OPERAND (t, 0));
00638 break;
00639
00640 case TARGET_EXPR:
00641 dump_child ("decl", TREE_OPERAND (t, 0));
00642 dump_child ("init", TREE_OPERAND (t, 1));
00643 dump_child ("clnp", TREE_OPERAND (t, 2));
00644
00645
00646
00647
00648 dump_child ("init", TREE_OPERAND (t, 3));
00649 break;
00650
00651 case CASE_LABEL_EXPR:
00652 dump_child ("name", CASE_LABEL (t));
00653 if (CASE_LOW (t)) {
00654 dump_child ("low ", CASE_LOW (t));
00655 if (CASE_HIGH (t)) {
00656 dump_child ("high", CASE_HIGH (t));
00657 }
00658 }
00659 break;
00660 case LABEL_EXPR:
00661 dump_child ("name", TREE_OPERAND (t,0));
00662 break;
00663 case GOTO_EXPR:
00664 dump_child ("labl", TREE_OPERAND (t, 0));
00665 break;
00666 case SWITCH_EXPR:
00667 dump_child ("cond", TREE_OPERAND (t, 0));
00668 dump_child ("body", TREE_OPERAND (t, 1));
00669 if (TREE_OPERAND (t, 2))
00670 {
00671 dump_child ("labl", TREE_OPERAND (t,2));
00672 }
00673 break;
00674 case OMP_CLAUSE:
00675 {
00676 int i;
00677 fprintf (di->stream, "%s\n", omp_clause_code_name[OMP_CLAUSE_CODE (t)]);
00678 for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (t)]; i++)
00679 dump_child ("op: ", OMP_CLAUSE_OPERAND (t, i));
00680 }
00681 break;
00682 default:
00683
00684 break;
00685 }
00686
00687 done:
00688 if (dump_flag (di, TDF_ADDRESS, NULL))
00689 dump_pointer (di, "addr", (void *)t);
00690
00691
00692 fprintf (di->stream, "\n");
00693 }
00694
00695
00696
00697
00698 int dump_flag (dump_info_p di, int flag, tree node)
00699 {
00700 return (di->flags & flag) && (node != di->node);
00701 }
00702
00703
00704
00705 void
00706 dump_node (tree t, int flags, FILE *stream)
00707 {
00708 struct dump_info di;
00709 dump_queue_p dq;
00710 dump_queue_p next_dq;
00711
00712
00713 di.stream = stream;
00714 di.index = 0;
00715 di.column = 0;
00716 di.queue = 0;
00717 di.queue_end = 0;
00718 di.free_list = 0;
00719 di.flags = flags;
00720 di.node = t;
00721 di.nodes = splay_tree_new (splay_tree_compare_pointers, 0,
00722 (splay_tree_delete_value_fn) &free);
00723
00724
00725 queue (&di, t, DUMP_NONE);
00726
00727
00728 while (di.queue)
00729 dequeue_and_dump (&di);
00730
00731
00732 for (dq = di.free_list; dq; dq = next_dq)
00733 {
00734 next_dq = dq->next;
00735 free (dq);
00736 }
00737 splay_tree_delete (di.nodes);
00738 }
00739
00740
00741
00742
00743 static struct dump_file_info dump_files[TDI_end] =
00744 {
00745 {NULL, NULL, NULL, 0, 0, 0, 0},
00746 {".cgraph", "ipa-cgraph", NULL, TDF_IPA, 0, 0, 0},
00747 {".tu", "translation-unit", NULL, TDF_TREE, 0, 1, 0},
00748 {".class", "class-hierarchy", NULL, TDF_TREE, 0, 2, 0},
00749 {".original", "tree-original", NULL, TDF_TREE, 0, 3, 0},
00750 {".gimple", "tree-gimple", NULL, TDF_TREE, 0, 4, 0},
00751 {".nested", "tree-nested", NULL, TDF_TREE, 0, 5, 0},
00752 {".inlined", "tree-inlined", NULL, TDF_TREE, 0, 6, 0},
00753 {".vcg", "tree-vcg", NULL, TDF_TREE, 0, 7, 0},
00754 #define FIRST_AUTO_NUMBERED_DUMP 8
00755
00756 {NULL, "tree-all", NULL, TDF_TREE, 0, 0, 0},
00757 {NULL, "rtl-all", NULL, TDF_RTL, 0, 0, 0},
00758 {NULL, "ipa-all", NULL, TDF_IPA, 0, 0, 0},
00759 };
00760
00761
00762 static struct dump_file_info *extra_dump_files;
00763 static size_t extra_dump_files_in_use;
00764 static size_t extra_dump_files_alloced;
00765
00766
00767 struct dump_option_value_info
00768 {
00769 const char *const name;
00770 const int value;
00771 };
00772
00773
00774
00775 static const struct dump_option_value_info dump_options[] =
00776 {
00777 {"address", TDF_ADDRESS},
00778 {"slim", TDF_SLIM},
00779 {"raw", TDF_RAW},
00780 {"details", TDF_DETAILS},
00781 {"stats", TDF_STATS},
00782 {"blocks", TDF_BLOCKS},
00783 {"vops", TDF_VOPS},
00784 {"lineno", TDF_LINENO},
00785 {"uid", TDF_UID},
00786 {"stmtaddr", TDF_STMTADDR},
00787 {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA
00788 | TDF_STMTADDR | TDF_GRAPH)},
00789 {NULL, 0}
00790 };
00791
00792 unsigned int
00793 dump_register (const char *suffix, const char *swtch, const char *glob,
00794 int flags, int letter)
00795 {
00796 static int next_dump = FIRST_AUTO_NUMBERED_DUMP;
00797 int num = next_dump++;
00798
00799 size_t this = extra_dump_files_in_use++;
00800
00801 if (this >= extra_dump_files_alloced)
00802 {
00803 if (extra_dump_files_alloced == 0)
00804 extra_dump_files_alloced = 32;
00805 else
00806 extra_dump_files_alloced *= 2;
00807 extra_dump_files = xrealloc (extra_dump_files,
00808 sizeof (struct dump_file_info)
00809 * extra_dump_files_alloced);
00810 }
00811
00812 memset (&extra_dump_files[this], 0, sizeof (struct dump_file_info));
00813 extra_dump_files[this].suffix = suffix;
00814 extra_dump_files[this].swtch = swtch;
00815 extra_dump_files[this].glob = glob;
00816 extra_dump_files[this].flags = flags;
00817 extra_dump_files[this].num = num;
00818 extra_dump_files[this].letter = letter;
00819
00820 return this + TDI_end;
00821 }
00822
00823
00824
00825
00826 struct dump_file_info *
00827 get_dump_file_info (enum tree_dump_index phase)
00828 {
00829 if (phase < TDI_end)
00830 return &dump_files[phase];
00831 else if (phase - TDI_end >= extra_dump_files_in_use)
00832 return NULL;
00833 else
00834 return extra_dump_files + (phase - TDI_end);
00835 }
00836
00837
00838
00839
00840
00841 char *
00842 get_dump_file_name (enum tree_dump_index phase)
00843 {
00844 char dump_id[10];
00845 struct dump_file_info *dfi;
00846
00847 if (phase == TDI_none)
00848 return NULL;
00849
00850 dfi = get_dump_file_info (phase);
00851 if (dfi->state == 0)
00852 return NULL;
00853
00854 if (dfi->num < 0)
00855 dump_id[0] = '\0';
00856 else
00857 {
00858 char suffix;
00859 if (dfi->flags & TDF_TREE)
00860 suffix = 't';
00861 else if (dfi->flags & TDF_IPA)
00862 suffix = 'i';
00863 else
00864 suffix = 'r';
00865
00866 if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
00867 dump_id[0] = '\0';
00868 }
00869
00870 return concat (dump_base_name, dump_id, dfi->suffix, NULL);
00871 }
00872
00873
00874
00875
00876
00877
00878 FILE *
00879 dump_begin (enum tree_dump_index phase, int *flag_ptr)
00880 {
00881 char *name;
00882 struct dump_file_info *dfi;
00883 FILE *stream;
00884
00885 if (phase == TDI_none || !dump_enabled_p (phase))
00886 return NULL;
00887
00888 name = get_dump_file_name (phase);
00889 dfi = get_dump_file_info (phase);
00890 stream = fopen (name, dfi->state < 0 ? "w" : "a");
00891 if (!stream)
00892 error ("could not open dump file %qs: %s", name, strerror (errno));
00893 else
00894 dfi->state = 1;
00895 free (name);
00896
00897 if (flag_ptr)
00898 *flag_ptr = dfi->flags;
00899
00900 return stream;
00901 }
00902
00903
00904
00905
00906 int
00907 dump_enabled_p (enum tree_dump_index phase)
00908 {
00909 if (phase == TDI_tree_all)
00910 {
00911 size_t i;
00912 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
00913 if (dump_files[i].state)
00914 return 1;
00915 for (i = 0; i < extra_dump_files_in_use; i++)
00916 if (extra_dump_files[i].state)
00917 return 1;
00918 return 0;
00919 }
00920 else
00921 {
00922 struct dump_file_info *dfi = get_dump_file_info (phase);
00923 return dfi->state;
00924 }
00925 }
00926
00927
00928
00929 int
00930 dump_initialized_p (enum tree_dump_index phase)
00931 {
00932 struct dump_file_info *dfi = get_dump_file_info (phase);
00933 return dfi->state > 0;
00934 }
00935
00936
00937
00938 const char *
00939 dump_flag_name (enum tree_dump_index phase)
00940 {
00941 struct dump_file_info *dfi = get_dump_file_info (phase);
00942 return dfi->swtch;
00943 }
00944
00945
00946
00947
00948 void
00949 dump_end (enum tree_dump_index phase ATTRIBUTE_UNUSED, FILE *stream)
00950 {
00951 fclose (stream);
00952 }
00953
00954
00955
00956 static int
00957 dump_enable_all (int flags, int letter)
00958 {
00959 int ir_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
00960 int n = 0;
00961 size_t i;
00962
00963 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
00964 if ((dump_files[i].flags & ir_type)
00965 && (letter == 0 || letter == dump_files[i].letter))
00966 {
00967 dump_files[i].state = -1;
00968 dump_files[i].flags |= flags;
00969 n++;
00970 }
00971
00972 for (i = 0; i < extra_dump_files_in_use; i++)
00973 if ((extra_dump_files[i].flags & ir_type)
00974 && (letter == 0 || letter == extra_dump_files[i].letter))
00975 {
00976 extra_dump_files[i].state = -1;
00977 extra_dump_files[i].flags |= flags;
00978 n++;
00979 }
00980
00981 return n;
00982 }
00983
00984
00985
00986
00987 static int
00988 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
00989 {
00990 const char *option_value;
00991 const char *ptr;
00992 int flags;
00993
00994 if (doglob && !dfi->glob)
00995 return 0;
00996
00997 option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
00998 if (!option_value)
00999 return 0;
01000
01001 ptr = option_value;
01002 flags = 0;
01003
01004 while (*ptr)
01005 {
01006 const struct dump_option_value_info *option_ptr;
01007 const char *end_ptr;
01008 unsigned length;
01009
01010 while (*ptr == '-')
01011 ptr++;
01012 end_ptr = strchr (ptr, '-');
01013 if (!end_ptr)
01014 end_ptr = ptr + strlen (ptr);
01015 length = end_ptr - ptr;
01016
01017 for (option_ptr = dump_options; option_ptr->name; option_ptr++)
01018 if (strlen (option_ptr->name) == length
01019 && !memcmp (option_ptr->name, ptr, length))
01020 {
01021 flags |= option_ptr->value;
01022 goto found;
01023 }
01024 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
01025 length, ptr, dfi->swtch);
01026 found:;
01027 ptr = end_ptr;
01028 }
01029
01030 dfi->state = -1;
01031 dfi->flags |= flags;
01032
01033
01034
01035 if (dfi->suffix == NULL)
01036 dump_enable_all (dfi->flags, 0);
01037
01038 return 1;
01039 }
01040
01041 int
01042 dump_switch_p (const char *arg)
01043 {
01044 size_t i;
01045 int any = 0;
01046
01047 for (i = TDI_none + 1; i != TDI_end; i++)
01048 any |= dump_switch_p_1 (arg, &dump_files[i], false);
01049
01050
01051 if (!any)
01052 for (i = TDI_none + 1; i != TDI_end; i++)
01053 any |= dump_switch_p_1 (arg, &dump_files[i], true);
01054
01055 for (i = 0; i < extra_dump_files_in_use; i++)
01056 any |= dump_switch_p_1 (arg, &extra_dump_files[i], false);
01057
01058 if (!any)
01059 for (i = 0; i < extra_dump_files_in_use; i++)
01060 any |= dump_switch_p_1 (arg, &extra_dump_files[i], true);
01061
01062
01063 return any;
01064 }
01065
01066
01067
01068 void
01069 dump_function (enum tree_dump_index phase, tree fn)
01070 {
01071 FILE *stream;
01072 int flags;
01073
01074 stream = dump_begin (phase, &flags);
01075 if (stream)
01076 {
01077 dump_function_to_file (fn, stream, flags);
01078 dump_end (phase, stream);
01079 }
01080 }
01081
01082 bool
01083 enable_rtl_dump_file (int letter)
01084 {
01085 if (letter == 'a')
01086 letter = 0;
01087
01088 return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, letter) > 0;
01089 }
01090
01091