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