1 /* Dump infrastructure for optimizations and intermediate representation. 2 Copyright (C) 2012-2013 Free Software Foundation, Inc. 3 4 This file is part of GCC. 5 6 GCC is free software; you can redistribute it and/or modify it under 7 the terms of the GNU General Public License as published by the Free 8 Software Foundation; either version 3, or (at your option) any later 9 version. 10 11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12 WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GCC; see the file COPYING3. If not see 18 <http://www.gnu.org/licenses/>. */ 19 20 #include "config.h" 21 #include "system.h" 22 #include "coretypes.h" 23 #include "diagnostic-core.h" 24 #include "dumpfile.h" 25 #include "gimple-pretty-print.h" 26 #include "tree.h" 27 28 /* If non-NULL, return one past-the-end of the matching SUBPART of 29 the WHOLE string. */ 30 #define skip_leading_substring(whole, part) \ 31 (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part)) 32 33 static int pflags; /* current dump_flags */ 34 static int alt_flags; /* current opt_info flags */ 35 36 static void dump_loc (int, FILE *, source_location); 37 static int dump_phase_enabled_p (int); 38 static FILE *dump_open_alternate_stream (struct dump_file_info *); 39 40 /* These are currently used for communicating between passes. 41 However, instead of accessing them directly, the passes can use 42 dump_printf () for dumps. */ 43 FILE *dump_file = NULL; 44 FILE *alt_dump_file = NULL; 45 const char *dump_file_name; 46 int dump_flags; 47 48 /* Table of tree dump switches. This must be consistent with the 49 TREE_DUMP_INDEX enumeration in dumpfile.h. */ 50 static struct dump_file_info dump_files[TDI_end] = 51 { 52 {NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0}, 53 {".cgraph", "ipa-cgraph", NULL, NULL, NULL, NULL, NULL, TDF_IPA, 54 0, 0, 0, 0, 0}, 55 {".tu", "translation-unit", NULL, NULL, NULL, NULL, NULL, TDF_TREE, 56 0, 0, 0, 0, 1}, 57 {".class", "class-hierarchy", NULL, NULL, NULL, NULL, NULL, TDF_TREE, 58 0, 0, 0, 0, 2}, 59 {".original", "tree-original", NULL, NULL, NULL, NULL, NULL, TDF_TREE, 60 0, 0, 0, 0, 3}, 61 {".gimple", "tree-gimple", NULL, NULL, NULL, NULL, NULL, TDF_TREE, 62 0, 0, 0, 0, 4}, 63 {".nested", "tree-nested", NULL, NULL, NULL, NULL, NULL, TDF_TREE, 64 0, 0, 0, 0, 5}, 65 #define FIRST_AUTO_NUMBERED_DUMP 6 66 67 {NULL, "tree-all", NULL, NULL, NULL, NULL, NULL, TDF_TREE, 68 0, 0, 0, 0, 0}, 69 {NULL, "rtl-all", NULL, NULL, NULL, NULL, NULL, TDF_RTL, 70 0, 0, 0, 0, 0}, 71 {NULL, "ipa-all", NULL, NULL, NULL, NULL, NULL, TDF_IPA, 72 0, 0, 0, 0, 0}, 73 }; 74 75 /* Dynamically registered tree dump files and switches. */ 76 static struct dump_file_info *extra_dump_files; 77 static size_t extra_dump_files_in_use; 78 static size_t extra_dump_files_alloced; 79 80 /* Define a name->number mapping for a dump flag value. */ 81 struct dump_option_value_info 82 { 83 const char *const name; /* the name of the value */ 84 const int value; /* the value of the name */ 85 }; 86 87 /* Table of dump options. This must be consistent with the TDF_* flags 88 in dumpfile.h and opt_info_options below. */ 89 static const struct dump_option_value_info dump_options[] = 90 { 91 {"address", TDF_ADDRESS}, 92 {"asmname", TDF_ASMNAME}, 93 {"slim", TDF_SLIM}, 94 {"raw", TDF_RAW}, 95 {"graph", TDF_GRAPH}, 96 {"details", (TDF_DETAILS | MSG_OPTIMIZED_LOCATIONS 97 | MSG_MISSED_OPTIMIZATION 98 | MSG_NOTE)}, 99 {"cselib", TDF_CSELIB}, 100 {"stats", TDF_STATS}, 101 {"blocks", TDF_BLOCKS}, 102 {"vops", TDF_VOPS}, 103 {"lineno", TDF_LINENO}, 104 {"uid", TDF_UID}, 105 {"stmtaddr", TDF_STMTADDR}, 106 {"memsyms", TDF_MEMSYMS}, 107 {"verbose", TDF_VERBOSE}, 108 {"eh", TDF_EH}, 109 {"alias", TDF_ALIAS}, 110 {"nouid", TDF_NOUID}, 111 {"enumerate_locals", TDF_ENUMERATE_LOCALS}, 112 {"scev", TDF_SCEV}, 113 {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA 114 | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC | TDF_VERBOSE 115 | TDF_RHS_ONLY | TDF_NOUID | TDF_ENUMERATE_LOCALS | TDF_SCEV)}, 116 {NULL, 0} 117 }; 118 119 /* A subset of the dump_options table which is used for -fopt-info 120 types. This must be consistent with the MSG_* flags in dumpfile.h. 121 */ 122 static const struct dump_option_value_info optinfo_verbosity_options[] = 123 { 124 {"optimized", MSG_OPTIMIZED_LOCATIONS}, 125 {"missed", MSG_MISSED_OPTIMIZATION}, 126 {"note", MSG_NOTE}, 127 {"all", MSG_ALL}, 128 {NULL, 0} 129 }; 130 131 /* Flags used for -fopt-info groups. */ 132 static const struct dump_option_value_info optgroup_options[] = 133 { 134 {"ipa", OPTGROUP_IPA}, 135 {"loop", OPTGROUP_LOOP}, 136 {"inline", OPTGROUP_INLINE}, 137 {"vec", OPTGROUP_VEC}, 138 {"optall", OPTGROUP_ALL}, 139 {NULL, 0} 140 }; 141 142 unsigned int 143 dump_register (const char *suffix, const char *swtch, const char *glob, 144 int flags, int optgroup_flags) 145 { 146 static int next_dump = FIRST_AUTO_NUMBERED_DUMP; 147 int num = next_dump++; 148 149 size_t count = extra_dump_files_in_use++; 150 151 if (count >= extra_dump_files_alloced) 152 { 153 if (extra_dump_files_alloced == 0) 154 extra_dump_files_alloced = 32; 155 else 156 extra_dump_files_alloced *= 2; 157 extra_dump_files = XRESIZEVEC (struct dump_file_info, 158 extra_dump_files, 159 extra_dump_files_alloced); 160 } 161 162 memset (&extra_dump_files[count], 0, sizeof (struct dump_file_info)); 163 extra_dump_files[count].suffix = suffix; 164 extra_dump_files[count].swtch = swtch; 165 extra_dump_files[count].glob = glob; 166 extra_dump_files[count].pflags = flags; 167 extra_dump_files[count].optgroup_flags = optgroup_flags; 168 extra_dump_files[count].num = num; 169 170 return count + TDI_end; 171 } 172 173 174 /* Return the dump_file_info for the given phase. */ 175 176 struct dump_file_info * 177 get_dump_file_info (int phase) 178 { 179 if (phase < TDI_end) 180 return &dump_files[phase]; 181 else if ((size_t) (phase - TDI_end) >= extra_dump_files_in_use) 182 return NULL; 183 else 184 return extra_dump_files + (phase - TDI_end); 185 } 186 187 188 /* Return the name of the dump file for the given phase. 189 If the dump is not enabled, returns NULL. */ 190 191 char * 192 get_dump_file_name (int phase) 193 { 194 char dump_id[10]; 195 struct dump_file_info *dfi; 196 197 if (phase == TDI_none) 198 return NULL; 199 200 dfi = get_dump_file_info (phase); 201 if (dfi->pstate == 0) 202 return NULL; 203 204 /* If available, use the command line dump filename. */ 205 if (dfi->pfilename) 206 return xstrdup (dfi->pfilename); 207 208 if (dfi->num < 0) 209 dump_id[0] = '\0'; 210 else 211 { 212 char suffix; 213 if (dfi->pflags & TDF_TREE) 214 suffix = 't'; 215 else if (dfi->pflags & TDF_IPA) 216 suffix = 'i'; 217 else 218 suffix = 'r'; 219 220 if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0) 221 dump_id[0] = '\0'; 222 } 223 224 return concat (dump_base_name, dump_id, dfi->suffix, NULL); 225 } 226 227 /* For a given DFI, open an alternate dump filename (which could also 228 be a standard stream such as stdout/stderr). If the alternate dump 229 file cannot be opened, return NULL. */ 230 231 static FILE * 232 dump_open_alternate_stream (struct dump_file_info *dfi) 233 { 234 FILE *stream ; 235 if (!dfi->alt_filename) 236 return NULL; 237 238 if (dfi->alt_stream) 239 return dfi->alt_stream; 240 241 stream = strcmp("stderr", dfi->alt_filename) == 0 242 ? stderr 243 : strcmp("stdout", dfi->alt_filename) == 0 244 ? stdout 245 : fopen (dfi->alt_filename, dfi->alt_state < 0 ? "w" : "a"); 246 247 if (!stream) 248 error ("could not open dump file %qs: %m", dfi->alt_filename); 249 else 250 dfi->alt_state = 1; 251 252 return stream; 253 } 254 255 /* Print source location on DFILE if enabled. */ 256 257 void 258 dump_loc (int dump_kind, FILE *dfile, source_location loc) 259 { 260 /* Currently vectorization passes print location information. */ 261 if (dump_kind) 262 { 263 if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION) 264 fprintf (dfile, "\n%s:%d: note: ", LOCATION_FILE (loc), 265 LOCATION_LINE (loc)); 266 else if (current_function_decl) 267 fprintf (dfile, "\n%s:%d: note: ", 268 DECL_SOURCE_FILE (current_function_decl), 269 DECL_SOURCE_LINE (current_function_decl)); 270 } 271 } 272 273 /* Dump gimple statement GS with SPC indentation spaces and 274 EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */ 275 276 void 277 dump_gimple_stmt (int dump_kind, int extra_dump_flags, gimple gs, int spc) 278 { 279 if (dump_file && (dump_kind & pflags)) 280 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags); 281 282 if (alt_dump_file && (dump_kind & alt_flags)) 283 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags); 284 } 285 286 /* Similar to dump_gimple_stmt, except additionally print source location. */ 287 288 void 289 dump_gimple_stmt_loc (int dump_kind, source_location loc, int extra_dump_flags, 290 gimple gs, int spc) 291 { 292 if (dump_file && (dump_kind & pflags)) 293 { 294 dump_loc (dump_kind, dump_file, loc); 295 print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags); 296 } 297 298 if (alt_dump_file && (dump_kind & alt_flags)) 299 { 300 dump_loc (dump_kind, alt_dump_file, loc); 301 print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags); 302 } 303 } 304 305 /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if 306 DUMP_KIND is enabled. */ 307 308 void 309 dump_generic_expr (int dump_kind, int extra_dump_flags, tree t) 310 { 311 if (dump_file && (dump_kind & pflags)) 312 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags); 313 314 if (alt_dump_file && (dump_kind & alt_flags)) 315 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags); 316 } 317 318 319 /* Similar to dump_generic_expr, except additionally print the source 320 location. */ 321 322 void 323 dump_generic_expr_loc (int dump_kind, source_location loc, 324 int extra_dump_flags, tree t) 325 { 326 if (dump_file && (dump_kind & pflags)) 327 { 328 dump_loc (dump_kind, dump_file, loc); 329 print_generic_expr (dump_file, t, dump_flags | extra_dump_flags); 330 } 331 332 if (alt_dump_file && (dump_kind & alt_flags)) 333 { 334 dump_loc (dump_kind, alt_dump_file, loc); 335 print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags); 336 } 337 } 338 339 /* Output a formatted message using FORMAT on appropriate dump streams. */ 340 341 void 342 dump_printf (int dump_kind, const char *format, ...) 343 { 344 if (dump_file && (dump_kind & pflags)) 345 { 346 va_list ap; 347 va_start (ap, format); 348 vfprintf (dump_file, format, ap); 349 va_end (ap); 350 } 351 352 if (alt_dump_file && (dump_kind & alt_flags)) 353 { 354 va_list ap; 355 va_start (ap, format); 356 vfprintf (alt_dump_file, format, ap); 357 va_end (ap); 358 } 359 } 360 361 /* Similar to dump_printf, except source location is also printed. */ 362 363 void 364 dump_printf_loc (int dump_kind, source_location loc, const char *format, ...) 365 { 366 if (dump_file && (dump_kind & pflags)) 367 { 368 va_list ap; 369 dump_loc (dump_kind, dump_file, loc); 370 va_start (ap, format); 371 vfprintf (dump_file, format, ap); 372 va_end (ap); 373 } 374 375 if (alt_dump_file && (dump_kind & alt_flags)) 376 { 377 va_list ap; 378 dump_loc (dump_kind, alt_dump_file, loc); 379 va_start (ap, format); 380 vfprintf (alt_dump_file, format, ap); 381 va_end (ap); 382 } 383 } 384 385 /* Start a dump for PHASE. Store user-supplied dump flags in 386 *FLAG_PTR. Return the number of streams opened. Set globals 387 DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and 388 set dump_flags appropriately for both pass dump stream and 389 -fopt-info stream. */ 390 391 int 392 dump_start (int phase, int *flag_ptr) 393 { 394 int count = 0; 395 char *name; 396 struct dump_file_info *dfi; 397 FILE *stream; 398 if (phase == TDI_none || !dump_phase_enabled_p (phase)) 399 return 0; 400 401 dfi = get_dump_file_info (phase); 402 name = get_dump_file_name (phase); 403 if (name) 404 { 405 stream = strcmp("stderr", name) == 0 406 ? stderr 407 : strcmp("stdout", name) == 0 408 ? stdout 409 : fopen (name, dfi->pstate < 0 ? "w" : "a"); 410 if (!stream) 411 error ("could not open dump file %qs: %m", name); 412 else 413 { 414 dfi->pstate = 1; 415 count++; 416 } 417 free (name); 418 dfi->pstream = stream; 419 dump_file = dfi->pstream; 420 /* Initialize current dump flags. */ 421 pflags = dfi->pflags; 422 } 423 424 stream = dump_open_alternate_stream (dfi); 425 if (stream) 426 { 427 dfi->alt_stream = stream; 428 count++; 429 alt_dump_file = dfi->alt_stream; 430 /* Initialize current -fopt-info flags. */ 431 alt_flags = dfi->alt_flags; 432 } 433 434 if (flag_ptr) 435 *flag_ptr = dfi->pflags; 436 437 return count; 438 } 439 440 /* Finish a tree dump for PHASE and close associated dump streams. Also 441 reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */ 442 443 void 444 dump_finish (int phase) 445 { 446 struct dump_file_info *dfi; 447 448 if (phase < 0) 449 return; 450 dfi = get_dump_file_info (phase); 451 if (dfi->pstream) 452 fclose (dfi->pstream); 453 454 if (dfi->alt_stream && strcmp("stderr", dfi->alt_filename) != 0 455 && strcmp("stdout", dfi->alt_filename) != 0) 456 fclose (dfi->alt_stream); 457 458 dfi->alt_stream = NULL; 459 dfi->pstream = NULL; 460 dump_file = NULL; 461 alt_dump_file = NULL; 462 dump_flags = TDI_none; 463 alt_flags = 0; 464 pflags = 0; 465 } 466 467 /* Begin a tree dump for PHASE. Stores any user supplied flag in 468 *FLAG_PTR and returns a stream to write to. If the dump is not 469 enabled, returns NULL. 470 Multiple calls will reopen and append to the dump file. */ 471 472 FILE * 473 dump_begin (int phase, int *flag_ptr) 474 { 475 char *name; 476 struct dump_file_info *dfi; 477 FILE *stream; 478 479 if (phase == TDI_none || !dump_phase_enabled_p (phase)) 480 return NULL; 481 482 name = get_dump_file_name (phase); 483 if (!name) 484 return NULL; 485 dfi = get_dump_file_info (phase); 486 487 stream = strcmp("stderr", name) == 0 488 ? stderr 489 : strcmp("stdout", name) == 0 490 ? stdout 491 : fopen (name, dfi->pstate < 0 ? "w" : "a"); 492 493 if (!stream) 494 error ("could not open dump file %qs: %m", name); 495 else 496 dfi->pstate = 1; 497 free (name); 498 499 if (flag_ptr) 500 *flag_ptr = dfi->pflags; 501 502 /* Initialize current flags */ 503 pflags = dfi->pflags; 504 return stream; 505 } 506 507 /* Returns nonzero if dump PHASE is enabled for at least one stream. 508 If PHASE is TDI_tree_all, return nonzero if any dump is enabled for 509 any phase. */ 510 511 static int 512 dump_phase_enabled_p (int phase) 513 { 514 if (phase == TDI_tree_all) 515 { 516 size_t i; 517 for (i = TDI_none + 1; i < (size_t) TDI_end; i++) 518 if (dump_files[i].pstate || dump_files[i].alt_state) 519 return 1; 520 for (i = 0; i < extra_dump_files_in_use; i++) 521 if (extra_dump_files[i].pstate || extra_dump_files[i].alt_state) 522 return 1; 523 return 0; 524 } 525 else 526 { 527 struct dump_file_info *dfi = get_dump_file_info (phase); 528 return dfi->pstate || dfi->alt_state; 529 } 530 } 531 532 /* Returns nonzero if tree dump PHASE has been initialized. */ 533 534 int 535 dump_initialized_p (int phase) 536 { 537 struct dump_file_info *dfi = get_dump_file_info (phase); 538 return dfi->pstate > 0 || dfi->alt_state > 0; 539 } 540 541 /* Returns the switch name of PHASE. */ 542 543 const char * 544 dump_flag_name (int phase) 545 { 546 struct dump_file_info *dfi = get_dump_file_info (phase); 547 return dfi->swtch; 548 } 549 550 /* Finish a tree dump for PHASE. STREAM is the stream created by 551 dump_begin. */ 552 553 void 554 dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream) 555 { 556 if (stream != stderr && stream != stdout) 557 fclose (stream); 558 } 559 560 /* Enable all tree dumps with FLAGS on FILENAME. Return number of 561 enabled tree dumps. */ 562 563 static int 564 dump_enable_all (int flags, const char *filename) 565 { 566 int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA)); 567 int n = 0; 568 size_t i; 569 570 for (i = TDI_none + 1; i < (size_t) TDI_end; i++) 571 { 572 if ((dump_files[i].pflags & ir_dump_type)) 573 { 574 const char *old_filename = dump_files[i].pfilename; 575 dump_files[i].pstate = -1; 576 dump_files[i].pflags |= flags; 577 n++; 578 /* Override the existing filename. */ 579 if (filename) 580 { 581 dump_files[i].pfilename = xstrdup (filename); 582 /* Since it is a command-line provided file, which is 583 common to all the phases, use it in append mode. */ 584 dump_files[i].pstate = 1; 585 } 586 if (old_filename && filename != old_filename) 587 free (CONST_CAST (char *, old_filename)); 588 } 589 } 590 591 for (i = 0; i < extra_dump_files_in_use; i++) 592 { 593 if ((extra_dump_files[i].pflags & ir_dump_type)) 594 { 595 const char *old_filename = extra_dump_files[i].pfilename; 596 extra_dump_files[i].pstate = -1; 597 extra_dump_files[i].pflags |= flags; 598 n++; 599 /* Override the existing filename. */ 600 if (filename) 601 { 602 extra_dump_files[i].pfilename = xstrdup (filename); 603 /* Since it is a command-line provided file, which is 604 common to all the phases, use it in append mode. */ 605 extra_dump_files[i].pstate = 1; 606 } 607 if (old_filename && filename != old_filename) 608 free (CONST_CAST (char *, old_filename)); 609 } 610 } 611 612 return n; 613 } 614 615 /* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS. 616 Enable dumps with FLAGS on FILENAME. Return the number of enabled 617 dumps. */ 618 619 static int 620 opt_info_enable_passes (int optgroup_flags, int flags, const char *filename) 621 { 622 int n = 0; 623 size_t i; 624 625 for (i = TDI_none + 1; i < (size_t) TDI_end; i++) 626 { 627 if ((dump_files[i].optgroup_flags & optgroup_flags)) 628 { 629 const char *old_filename = dump_files[i].alt_filename; 630 /* Since this file is shared among different passes, it 631 should be opened in append mode. */ 632 dump_files[i].alt_state = 1; 633 dump_files[i].alt_flags |= flags; 634 n++; 635 /* Override the existing filename. */ 636 if (filename) 637 dump_files[i].alt_filename = xstrdup (filename); 638 if (old_filename && filename != old_filename) 639 free (CONST_CAST (char *, old_filename)); 640 } 641 } 642 643 for (i = 0; i < extra_dump_files_in_use; i++) 644 { 645 if ((extra_dump_files[i].optgroup_flags & optgroup_flags)) 646 { 647 const char *old_filename = extra_dump_files[i].alt_filename; 648 /* Since this file is shared among different passes, it 649 should be opened in append mode. */ 650 extra_dump_files[i].alt_state = 1; 651 extra_dump_files[i].alt_flags |= flags; 652 n++; 653 /* Override the existing filename. */ 654 if (filename) 655 extra_dump_files[i].alt_filename = xstrdup (filename); 656 if (old_filename && filename != old_filename) 657 free (CONST_CAST (char *, old_filename)); 658 } 659 } 660 661 return n; 662 } 663 664 /* Parse ARG as a dump switch. Return nonzero if it is, and store the 665 relevant details in the dump_files array. */ 666 667 static int 668 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob) 669 { 670 const char *option_value; 671 const char *ptr; 672 int flags; 673 674 if (doglob && !dfi->glob) 675 return 0; 676 677 option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch); 678 if (!option_value) 679 return 0; 680 681 if (*option_value && *option_value != '-' && *option_value != '=') 682 return 0; 683 684 ptr = option_value; 685 flags = 0; 686 687 while (*ptr) 688 { 689 const struct dump_option_value_info *option_ptr; 690 const char *end_ptr; 691 const char *eq_ptr; 692 unsigned length; 693 694 while (*ptr == '-') 695 ptr++; 696 end_ptr = strchr (ptr, '-'); 697 eq_ptr = strchr (ptr, '='); 698 699 if (eq_ptr && !end_ptr) 700 end_ptr = eq_ptr; 701 702 if (!end_ptr) 703 end_ptr = ptr + strlen (ptr); 704 length = end_ptr - ptr; 705 706 for (option_ptr = dump_options; option_ptr->name; option_ptr++) 707 if (strlen (option_ptr->name) == length 708 && !memcmp (option_ptr->name, ptr, length)) 709 { 710 flags |= option_ptr->value; 711 goto found; 712 } 713 714 if (*ptr == '=') 715 { 716 /* Interpret rest of the argument as a dump filename. This 717 filename overrides other command line filenames. */ 718 if (dfi->pfilename) 719 free (CONST_CAST (char *, dfi->pfilename)); 720 dfi->pfilename = xstrdup (ptr + 1); 721 break; 722 } 723 else 724 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>", 725 length, ptr, dfi->swtch); 726 found:; 727 ptr = end_ptr; 728 } 729 730 dfi->pstate = -1; 731 dfi->pflags |= flags; 732 733 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the 734 known dumps. */ 735 if (dfi->suffix == NULL) 736 dump_enable_all (dfi->pflags, dfi->pfilename); 737 738 return 1; 739 } 740 741 int 742 dump_switch_p (const char *arg) 743 { 744 size_t i; 745 int any = 0; 746 747 for (i = TDI_none + 1; i != TDI_end; i++) 748 any |= dump_switch_p_1 (arg, &dump_files[i], false); 749 750 /* Don't glob if we got a hit already */ 751 if (!any) 752 for (i = TDI_none + 1; i != TDI_end; i++) 753 any |= dump_switch_p_1 (arg, &dump_files[i], true); 754 755 for (i = 0; i < extra_dump_files_in_use; i++) 756 any |= dump_switch_p_1 (arg, &extra_dump_files[i], false); 757 758 if (!any) 759 for (i = 0; i < extra_dump_files_in_use; i++) 760 any |= dump_switch_p_1 (arg, &extra_dump_files[i], true); 761 762 763 return any; 764 } 765 766 /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags 767 and filename. Return non-zero if it is a recognized switch. */ 768 769 static int 770 opt_info_switch_p_1 (const char *arg, int *flags, int *optgroup_flags, 771 char **filename) 772 { 773 const char *option_value; 774 const char *ptr; 775 776 option_value = arg; 777 ptr = option_value; 778 779 *filename = NULL; 780 *flags = 0; 781 *optgroup_flags = 0; 782 783 if (!ptr) 784 return 1; /* Handle '-fopt-info' without any additional options. */ 785 786 while (*ptr) 787 { 788 const struct dump_option_value_info *option_ptr; 789 const char *end_ptr; 790 const char *eq_ptr; 791 unsigned length; 792 793 while (*ptr == '-') 794 ptr++; 795 end_ptr = strchr (ptr, '-'); 796 eq_ptr = strchr (ptr, '='); 797 798 if (eq_ptr && !end_ptr) 799 end_ptr = eq_ptr; 800 801 if (!end_ptr) 802 end_ptr = ptr + strlen (ptr); 803 length = end_ptr - ptr; 804 805 for (option_ptr = optinfo_verbosity_options; option_ptr->name; 806 option_ptr++) 807 if (strlen (option_ptr->name) == length 808 && !memcmp (option_ptr->name, ptr, length)) 809 { 810 *flags |= option_ptr->value; 811 goto found; 812 } 813 814 for (option_ptr = optgroup_options; option_ptr->name; option_ptr++) 815 if (strlen (option_ptr->name) == length 816 && !memcmp (option_ptr->name, ptr, length)) 817 { 818 *optgroup_flags |= option_ptr->value; 819 goto found; 820 } 821 822 if (*ptr == '=') 823 { 824 /* Interpret rest of the argument as a dump filename. This 825 filename overrides other command line filenames. */ 826 *filename = xstrdup (ptr + 1); 827 break; 828 } 829 else 830 { 831 warning (0, "unknown option %q.*s in %<-fopt-info-%s%>", 832 length, ptr, arg); 833 return 0; 834 } 835 found:; 836 ptr = end_ptr; 837 } 838 839 return 1; 840 } 841 842 /* Return non-zero if ARG is a recognized switch for 843 -fopt-info. Return zero otherwise. */ 844 845 int 846 opt_info_switch_p (const char *arg) 847 { 848 int flags; 849 int optgroup_flags; 850 char *filename; 851 static char *file_seen = NULL; 852 853 if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename)) 854 return 0; 855 856 if (!filename) 857 filename = xstrdup ("stderr"); 858 859 /* Bail out if a different filename has been specified. */ 860 if (file_seen && strcmp (file_seen, filename)) 861 { 862 warning (0, "ignoring possibly conflicting option %<-fopt-info-%s%>", 863 arg); 864 return 1; 865 } 866 867 file_seen = xstrdup (filename); 868 if (!flags) 869 flags = MSG_ALL; 870 if (!optgroup_flags) 871 optgroup_flags = OPTGROUP_ALL; 872 873 return opt_info_enable_passes (optgroup_flags, flags, filename); 874 } 875 876 /* Print basic block on the dump streams. */ 877 878 void 879 dump_basic_block (int dump_kind, basic_block bb, int indent) 880 { 881 if (dump_file && (dump_kind & pflags)) 882 dump_bb (dump_file, bb, indent, TDF_DETAILS); 883 if (alt_dump_file && (dump_kind & alt_flags)) 884 dump_bb (alt_dump_file, bb, indent, TDF_DETAILS); 885 } 886 887 /* Print information from the combine pass on dump_file. */ 888 889 void 890 print_combine_total_stats (void) 891 { 892 if (dump_file) 893 dump_combine_total_stats (dump_file); 894 } 895 896 /* Enable RTL dump for all the RTL passes. */ 897 898 bool 899 enable_rtl_dump_file (void) 900 { 901 return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0; 902 } 903