From 8ae8ae1bddd5aa022d09a91b5776f8de34e3eaaf Mon Sep 17 00:00:00 2001 From: singhai Date: Mon, 1 Oct 2012 06:10:29 +0000 Subject: 2012-09-30 Sharad Singhai * dumpfile.c: New file with parts moved from tree-dump.c. (pflags): New variable. (alt_flags): Ditto. (alt_dump_file): Ditto. (dump_files): Update to include additional fields. (struct dump_option_value_info): Add additional entries. (get_dump_file_name): Use command line filename if available. (dump_open_alternate_stream): New function. (dump_loc): Ditto. (dump_gimple_stmt): Ditto. (dump_gimple_stmt_loc): Ditto. (dump_generic_expr): Ditto. (dump_generic_expr_loc): Ditto. (dump_printf): Ditto. (dump_printf_loc): Ditto. (dump_start): Ditto. (dump_finish): Ditto. (dump_begin): Ditto. (dump_enabled_p): Return true if either of the dump types is enabled. (dump_initialized_p): Return true if either type of dump is initialized. (dump_end): Do not close standard streams. (dump_enable_all): Handle filenames for regular dumps. (dump_switch_p_1): Handle command-line dump filenames. (opt_info_enable_all): New function. (opt_info_switch_p_1): Ditto. (opt_info_switch_p): Ditto. (dump_kind_p): Ditto. (dump_basic_block): Ditto. (dump_combine_total_stats): Ditto. (dump_remap_tree_vectorizer_verbose): Ditto. * gimple-pretty-print.h: Rename dump_gimple_stmt to pp_gimple_stmt_1. All callers updated. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@191884 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/dumpfile.c | 869 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 869 insertions(+) create mode 100644 gcc/dumpfile.c (limited to 'gcc/dumpfile.c') diff --git a/gcc/dumpfile.c b/gcc/dumpfile.c new file mode 100644 index 00000000000..92d1409be08 --- /dev/null +++ b/gcc/dumpfile.c @@ -0,0 +1,869 @@ +/* Dump infrastructure for optimizations and intermediate representation. + Copyright (C) 2012 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "diagnostic-core.h" +#include "dumpfile.h" +#include "gimple-pretty-print.h" +#include "tree.h" + +/* If non-NULL, return one past-the-end of the matching SUBPART of + the WHOLE string. */ +#define skip_leading_substring(whole, part) \ + (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part)) + +static int pflags; /* current dump_flags */ +static int alt_flags; /* current opt_info flags */ +static FILE *alt_dump_file = NULL; + +static void dump_loc (int, FILE *, source_location); +static int dump_enabled_p (int); +static FILE *dump_open_alternate_stream (struct dump_file_info *); + +/* Table of tree dump switches. This must be consistent with the + TREE_DUMP_INDEX enumeration in dumpfile.h. */ +static struct dump_file_info dump_files[TDI_end] = +{ + {NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}, + {".cgraph", "ipa-cgraph", NULL, NULL, NULL, NULL, NULL, TDF_IPA, + 0, 0, 0, 0}, + {".tu", "translation-unit", NULL, NULL, NULL, NULL, NULL, TDF_TREE, + 0, 0, 0, 1}, + {".class", "class-hierarchy", NULL, NULL, NULL, NULL, NULL, TDF_TREE, + 0, 0, 0, 2}, + {".original", "tree-original", NULL, NULL, NULL, NULL, NULL, TDF_TREE, + 0, 0, 0, 3}, + {".gimple", "tree-gimple", NULL, NULL, NULL, NULL, NULL, TDF_TREE, + 0, 0, 0, 4}, + {".nested", "tree-nested", NULL, NULL, NULL, NULL, NULL, TDF_TREE, + 0, 0, 0, 5}, + {".vcg", "tree-vcg", NULL, NULL, NULL, NULL, NULL, TDF_TREE, + 0, 0, 0, 6}, + {".ads", "ada-spec", NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 7}, +#define FIRST_AUTO_NUMBERED_DUMP 8 + + {NULL, "tree-all", NULL, NULL, NULL, NULL, NULL, TDF_TREE, + 0, 0, 0, 0}, + {NULL, "rtl-all", NULL, NULL, NULL, NULL, NULL, TDF_RTL, + 0, 0, 0, 0}, + {NULL, "ipa-all", NULL, NULL, NULL, NULL, NULL, TDF_IPA, + 0, 0, 0, 0}, +}; + +/* Dynamically registered tree dump files and switches. */ +static struct dump_file_info *extra_dump_files; +static size_t extra_dump_files_in_use; +static size_t extra_dump_files_alloced; + +/* Define a name->number mapping for a dump flag value. */ +struct dump_option_value_info +{ + const char *const name; /* the name of the value */ + const int value; /* the value of the name */ +}; + +/* Table of dump options. This must be consistent with the TDF_* flags + in dumpfile.h and opt_info_options below. */ +static const struct dump_option_value_info dump_options[] = +{ + {"address", TDF_ADDRESS}, + {"asmname", TDF_ASMNAME}, + {"slim", TDF_SLIM}, + {"raw", TDF_RAW}, + {"graph", TDF_GRAPH}, + {"details", (TDF_DETAILS | MSG_OPTIMIZED_LOCATIONS + | MSG_MISSED_OPTIMIZATION + | MSG_NOTE)}, + {"cselib", TDF_CSELIB}, + {"stats", TDF_STATS}, + {"blocks", TDF_BLOCKS}, + {"vops", TDF_VOPS}, + {"lineno", TDF_LINENO}, + {"uid", TDF_UID}, + {"stmtaddr", TDF_STMTADDR}, + {"memsyms", TDF_MEMSYMS}, + {"verbose", TDF_VERBOSE}, + {"eh", TDF_EH}, + {"alias", TDF_ALIAS}, + {"nouid", TDF_NOUID}, + {"enumerate_locals", TDF_ENUMERATE_LOCALS}, + {"scev", TDF_SCEV}, + {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA + | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC | TDF_VERBOSE + | TDF_RHS_ONLY | TDF_NOUID | TDF_ENUMERATE_LOCALS | TDF_SCEV)}, + {NULL, 0} +}; + +/* A subset of the dump_options table which is used for opt-info + options. This must be consistent with the MSG_* flags in + dump_options. + */ +static const struct dump_option_value_info opt_info_options[] = +{ + {"optimized", MSG_OPTIMIZED_LOCATIONS}, + {"missed", MSG_MISSED_OPTIMIZATION}, + {"note", MSG_NOTE}, + {"optall", (MSG_OPTIMIZED_LOCATIONS + | MSG_MISSED_OPTIMIZATION + | MSG_NOTE)}, + {NULL, 0} +}; + +unsigned int +dump_register (const char *suffix, const char *swtch, const char *glob, + int flags) +{ + static int next_dump = FIRST_AUTO_NUMBERED_DUMP; + int num = next_dump++; + + size_t count = extra_dump_files_in_use++; + + if (count >= extra_dump_files_alloced) + { + if (extra_dump_files_alloced == 0) + extra_dump_files_alloced = 32; + else + extra_dump_files_alloced *= 2; + extra_dump_files = XRESIZEVEC (struct dump_file_info, + extra_dump_files, + extra_dump_files_alloced); + } + + memset (&extra_dump_files[count], 0, sizeof (struct dump_file_info)); + extra_dump_files[count].suffix = suffix; + extra_dump_files[count].swtch = swtch; + extra_dump_files[count].glob = glob; + extra_dump_files[count].pflags = flags; + extra_dump_files[count].num = num; + + return count + TDI_end; +} + + +/* Return the dump_file_info for the given phase. */ + +struct dump_file_info * +get_dump_file_info (int phase) +{ + if (phase < TDI_end) + return &dump_files[phase]; + else if ((size_t) (phase - TDI_end) >= extra_dump_files_in_use) + return NULL; + else + return extra_dump_files + (phase - TDI_end); +} + + +/* Return the name of the dump file for the given phase. + If the dump is not enabled, returns NULL. */ + +char * +get_dump_file_name (int phase) +{ + char dump_id[10]; + struct dump_file_info *dfi; + + if (phase == TDI_none) + return NULL; + + dfi = get_dump_file_info (phase); + if (dfi->pstate == 0) + return NULL; + + /* If available, use the command line dump filename. */ + if (dfi->pfilename) + return xstrdup (dfi->pfilename); + + if (dfi->num < 0) + dump_id[0] = '\0'; + else + { + char suffix; + if (dfi->pflags & TDF_TREE) + suffix = 't'; + else if (dfi->pflags & TDF_IPA) + suffix = 'i'; + else + suffix = 'r'; + + if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0) + dump_id[0] = '\0'; + } + + return concat (dump_base_name, dump_id, dfi->suffix, NULL); +} + +/* For a given DFI, open an alternate dump filename (which could also + be a standard stream such as stdout/stderr). If the alternate dump + file cannot be opened, return NULL. */ + +static FILE * +dump_open_alternate_stream (struct dump_file_info *dfi) +{ + FILE *stream ; + if (!dfi->alt_filename) + return NULL; + + if (dfi->alt_stream) + return dfi->alt_stream; + + stream = strcmp("stderr", dfi->alt_filename) == 0 + ? stderr + : strcmp("stdout", dfi->alt_filename) == 0 + ? stdout + : fopen (dfi->alt_filename, dfi->alt_state < 0 ? "w" : "a"); + + if (!stream) + error ("could not open dump file %qs: %m", dfi->alt_filename); + else + dfi->alt_state = 1; + + return stream; +} + +/* Print source location on DFILE if enabled. */ + +void +dump_loc (int dump_kind, FILE *dfile, source_location loc) +{ + /* Currently vectorization passes print location information. */ + if (dump_kind) + { + if (loc == UNKNOWN_LOCATION) + fprintf (dfile, "\n%s:%d: note: ", + DECL_SOURCE_FILE (current_function_decl), + DECL_SOURCE_LINE (current_function_decl)); + else + fprintf (dfile, "\n%d: ", LOCATION_LINE (loc)); + } +} + +/* Dump gimple statement GS with SPC indentation spaces and + EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */ + +void +dump_gimple_stmt (int dump_kind, int extra_dump_flags, gimple gs, int spc) +{ + if (dump_file && (dump_kind & pflags)) + print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags); + + if (alt_dump_file && (dump_kind & alt_flags)) + print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags); +} + +/* Similar to dump_gimple_stmt, except additionally print source location. */ + +void +dump_gimple_stmt_loc (int dump_kind, source_location loc, int extra_dump_flags, + gimple gs, int spc) +{ + if (dump_file && (dump_kind & pflags)) + { + dump_loc (dump_kind, dump_file, loc); + print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags); + } + + if (alt_dump_file && (dump_kind & alt_flags)) + { + dump_loc (dump_kind, alt_dump_file, loc); + print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags); + } +} + +/* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if + DUMP_KIND is enabled. */ + +void +dump_generic_expr (int dump_kind, int extra_dump_flags, tree t) +{ + if (dump_file && (dump_kind & pflags)) + print_generic_expr (dump_file, t, dump_flags | extra_dump_flags); + + if (alt_dump_file && (dump_kind & alt_flags)) + print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags); +} + + +/* Similar to dump_generic_expr, except additionally print the source + location. */ + +void +dump_generic_expr_loc (int dump_kind, source_location loc, + int extra_dump_flags, tree t) +{ + if (dump_file && (dump_kind & pflags)) + { + dump_loc (dump_kind, dump_file, loc); + print_generic_expr (dump_file, t, dump_flags | extra_dump_flags); + } + + if (alt_dump_file && (dump_kind & alt_flags)) + { + dump_loc (dump_kind, alt_dump_file, loc); + print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags); + } +} + +/* Output a formatted message using FORMAT on appropriate dump streams. */ + +void +dump_printf (int dump_kind, const char *format, ...) +{ + if (dump_file && (dump_kind & pflags)) + { + va_list ap; + va_start (ap, format); + vfprintf (dump_file, format, ap); + va_end (ap); + } + + if (alt_dump_file && (dump_kind & alt_flags)) + { + va_list ap; + va_start (ap, format); + vfprintf (alt_dump_file, format, ap); + va_end (ap); + } +} + +/* Similar to dump_printf, except source location is also printed. */ + +void +dump_printf_loc (int dump_kind, source_location loc, const char *format, ...) +{ + if (dump_file && (dump_kind & pflags)) + { + va_list ap; + dump_loc (dump_kind, dump_file, loc); + va_start (ap, format); + vfprintf (dump_file, format, ap); + va_end (ap); + } + + if (alt_dump_file && (dump_kind & alt_flags)) + { + va_list ap; + dump_loc (dump_kind, alt_dump_file, loc); + va_start (ap, format); + vfprintf (alt_dump_file, format, ap); + va_end (ap); + } +} + +/* Start a dump for PHASE. Store user-supplied dump flags in + *FLAG_PTR. Return the number of streams opened. Set globals + DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and + set dump_flags appropriately for both pass dump stream and opt-info + stream. */ + +int +dump_start (int phase, int *flag_ptr) +{ + int count = 0; + char *name; + struct dump_file_info *dfi; + FILE *stream; + if (phase == TDI_none || !dump_enabled_p (phase)) + return 0; + + dfi = get_dump_file_info (phase); + name = get_dump_file_name (phase); + if (name) + { + stream = strcmp("stderr", name) == 0 + ? stderr + : strcmp("stdout", name) == 0 + ? stdout + : fopen (name, dfi->pstate < 0 ? "w" : "a"); + if (!stream) + error ("could not open dump file %qs: %m", name); + else + { + dfi->pstate = 1; + count++; + } + free (name); + dfi->pstream = stream; + dump_file = dfi->pstream; + /* Initialize current dump flags. */ + pflags = dfi->pflags; + } + + stream = dump_open_alternate_stream (dfi); + if (stream) + { + dfi->alt_stream = stream; + count++; + alt_dump_file = dfi->alt_stream; + /* Initialize current opt-info flags. */ + alt_flags = dfi->alt_flags; + } + + if (flag_ptr) + *flag_ptr = dfi->pflags; + + return count; +} + +/* Finish a tree dump for PHASE and close associated dump streams. Also + reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */ + +void +dump_finish (int phase) +{ + struct dump_file_info *dfi; + + if (phase < 0) + return; + dfi = get_dump_file_info (phase); + if (dfi->pstream) + fclose (dfi->pstream); + + if (dfi->alt_stream && strcmp("stderr", dfi->alt_filename) != 0 + && strcmp("stdout", dfi->alt_filename) != 0) + fclose (dfi->alt_stream); + + dfi->alt_stream = NULL; + dfi->pstream = NULL; + dump_file = NULL; + alt_dump_file = NULL; + dump_flags = TDI_none; + alt_flags = 0; + pflags = 0; +} + +/* Begin a tree dump for PHASE. Stores any user supplied flag in + *FLAG_PTR and returns a stream to write to. If the dump is not + enabled, returns NULL. + Multiple calls will reopen and append to the dump file. */ + +FILE * +dump_begin (int phase, int *flag_ptr) +{ + char *name; + struct dump_file_info *dfi; + FILE *stream; + + if (phase == TDI_none || !dump_enabled_p (phase)) + return NULL; + + name = get_dump_file_name (phase); + if (!name) + return NULL; + dfi = get_dump_file_info (phase); + + stream = strcmp("stderr", name) == 0 + ? stderr + : strcmp("stdout", name) == 0 + ? stdout + : fopen (name, dfi->pstate < 0 ? "w" : "a"); + + if (!stream) + error ("could not open dump file %qs: %m", name); + else + dfi->pstate = 1; + free (name); + + if (flag_ptr) + *flag_ptr = dfi->pflags; + + /* Initialize current flags */ + pflags = dfi->pflags; + return stream; +} + +/* Returns nonzero if dump PHASE is enabled for at least one stream. + If PHASE is TDI_tree_all, return nonzero if any dump is enabled for + any phase. */ + +int +dump_enabled_p (int phase) +{ + if (phase == TDI_tree_all) + { + size_t i; + for (i = TDI_none + 1; i < (size_t) TDI_end; i++) + if (dump_files[i].pstate || dump_files[i].alt_state) + return 1; + for (i = 0; i < extra_dump_files_in_use; i++) + if (extra_dump_files[i].pstate || extra_dump_files[i].alt_state) + return 1; + return 0; + } + else + { + struct dump_file_info *dfi = get_dump_file_info (phase); + return dfi->pstate || dfi->alt_state; + } +} + +/* Returns nonzero if tree dump PHASE has been initialized. */ + +int +dump_initialized_p (int phase) +{ + struct dump_file_info *dfi = get_dump_file_info (phase); + return dfi->pstate > 0 || dfi->alt_state > 0; +} + +/* Returns the switch name of PHASE. */ + +const char * +dump_flag_name (int phase) +{ + struct dump_file_info *dfi = get_dump_file_info (phase); + return dfi->swtch; +} + +/* Finish a tree dump for PHASE. STREAM is the stream created by + dump_begin. */ + +void +dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream) +{ + if (stream != stderr && stream != stdout) + fclose (stream); +} + +/* Enable all tree dumps with FLAGS on FILENAME. Return number of + enabled tree dumps. */ + +static int +dump_enable_all (int flags, const char *filename) +{ + int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA)); + int n = 0; + size_t i; + + for (i = TDI_none + 1; i < (size_t) TDI_end; i++) + { + if ((dump_files[i].pflags & ir_dump_type)) + { + const char *old_filename = dump_files[i].pfilename; + dump_files[i].pstate = -1; + dump_files[i].pflags |= flags; + n++; + /* Override the existing filename. */ + if (filename) + { + dump_files[i].pfilename = xstrdup (filename); + /* Since it is a command-line provided file, which is + common to all the phases, use it in append mode. */ + dump_files[i].pstate = 1; + } + if (old_filename && filename != old_filename) + free (CONST_CAST (char *, old_filename)); + } + } + + for (i = 0; i < extra_dump_files_in_use; i++) + { + if ((extra_dump_files[i].pflags & ir_dump_type)) + { + const char *old_filename = extra_dump_files[i].pfilename; + extra_dump_files[i].pstate = -1; + extra_dump_files[i].pflags |= flags; + n++; + /* Override the existing filename. */ + if (filename) + { + extra_dump_files[i].pfilename = xstrdup (filename); + /* Since it is a command-line provided file, which is + common to all the phases, use it in append mode. */ + extra_dump_files[i].pstate = 1; + } + if (old_filename && filename != old_filename) + free (CONST_CAST (char *, old_filename)); + } + } + + return n; +} + +/* Enable opt-info dumps on all IR_DUMP_TYPE passes with FLAGS on + FILENAME. Return the number of enabled dumps. */ + +static int +opt_info_enable_all (int ir_dump_type, int flags, const char *filename) +{ + int n = 0; + size_t i; + + for (i = TDI_none + 1; i < (size_t) TDI_end; i++) + { + if ((dump_files[i].pflags & ir_dump_type)) + { + const char *old_filename = dump_files[i].alt_filename; + /* Since this file is shared among different passes, it + should be opened in append mode. */ + dump_files[i].alt_state = 1; + dump_files[i].alt_flags |= flags; + n++; + /* Override the existing filename. */ + if (filename) + dump_files[i].alt_filename = xstrdup (filename); + if (old_filename && filename != old_filename) + free (CONST_CAST (char *, old_filename)); + } + } + + for (i = 0; i < extra_dump_files_in_use; i++) + { + if ((extra_dump_files[i].pflags & ir_dump_type)) + { + const char *old_filename = extra_dump_files[i].alt_filename; + /* Since this file is shared among different passes, it + should be opened in append mode. */ + extra_dump_files[i].alt_state = 1; + extra_dump_files[i].alt_flags |= flags; + n++; + /* Override the existing filename. */ + if (filename) + extra_dump_files[i].alt_filename = xstrdup (filename); + if (old_filename && filename != old_filename) + free (CONST_CAST (char *, old_filename)); + } + } + + return n; +} + +/* Parse ARG as a dump switch. Return nonzero if it is, and store the + relevant details in the dump_files array. */ + +static int +dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob) +{ + const char *option_value; + const char *ptr; + int flags; + + if (doglob && !dfi->glob) + return 0; + + option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch); + if (!option_value) + return 0; + + if (*option_value && *option_value != '-' && *option_value != '=') + return 0; + + ptr = option_value; + flags = 0; + + while (*ptr) + { + const struct dump_option_value_info *option_ptr; + const char *end_ptr; + const char *eq_ptr; + unsigned length; + + while (*ptr == '-') + ptr++; + end_ptr = strchr (ptr, '-'); + eq_ptr = strchr (ptr, '='); + + if (eq_ptr && !end_ptr) + end_ptr = eq_ptr; + + if (!end_ptr) + end_ptr = ptr + strlen (ptr); + length = end_ptr - ptr; + + for (option_ptr = dump_options; option_ptr->name; option_ptr++) + if (strlen (option_ptr->name) == length + && !memcmp (option_ptr->name, ptr, length)) + { + flags |= option_ptr->value; + goto found; + } + + if (*ptr == '=') + { + /* Interpret rest of the argument as a dump filename. This + filename overrides other command line filenames. */ + if (dfi->pfilename) + free (CONST_CAST (char *, dfi->pfilename)); + dfi->pfilename = xstrdup (ptr + 1); + break; + } + else + warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>", + length, ptr, dfi->swtch); + found:; + ptr = end_ptr; + } + + dfi->pstate = -1; + dfi->pflags |= flags; + + /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the + known dumps. */ + if (dfi->suffix == NULL) + dump_enable_all (dfi->pflags, dfi->pfilename); + + return 1; +} + +int +dump_switch_p (const char *arg) +{ + size_t i; + int any = 0; + + for (i = TDI_none + 1; i != TDI_end; i++) + any |= dump_switch_p_1 (arg, &dump_files[i], false); + + /* Don't glob if we got a hit already */ + if (!any) + for (i = TDI_none + 1; i != TDI_end; i++) + any |= dump_switch_p_1 (arg, &dump_files[i], true); + + for (i = 0; i < extra_dump_files_in_use; i++) + any |= dump_switch_p_1 (arg, &extra_dump_files[i], false); + + if (!any) + for (i = 0; i < extra_dump_files_in_use; i++) + any |= dump_switch_p_1 (arg, &extra_dump_files[i], true); + + + return any; +} + +/* Parse ARG as a -fopt-info switch and store flags and filename. + Return non-zero if it is a recognized switch. */ + +static int +opt_info_switch_p_1 (const char *arg, int *flags, char **filename) +{ + const char *option_value; + const char *ptr; + + option_value = arg; + ptr = option_value; + + *filename = NULL; + *flags = 0; + + if (!ptr) + return 1; + + while (*ptr) + { + const struct dump_option_value_info *option_ptr; + const char *end_ptr; + const char *eq_ptr; + unsigned length; + + while (*ptr == '-') + ptr++; + end_ptr = strchr (ptr, '-'); + eq_ptr = strchr (ptr, '='); + + if (eq_ptr && !end_ptr) + end_ptr = eq_ptr; + + if (!end_ptr) + end_ptr = ptr + strlen (ptr); + length = end_ptr - ptr; + + for (option_ptr = opt_info_options; option_ptr->name; option_ptr++) + if (strlen (option_ptr->name) == length + && !memcmp (option_ptr->name, ptr, length)) + { + *flags |= option_ptr->value; + goto found; + } + + if (*ptr == '=') + { + /* Interpret rest of the argument as a dump filename. This + filename overrides other command line filenames. */ + *filename = xstrdup (ptr + 1); + break; + } + else + warning (0, "ignoring unknown option %q.*s in %<-fopt-info=%s%>", + length, ptr, arg); + found:; + ptr = end_ptr; + } + + return 1; +} + +/* Return non-zero if ARG is a recognized switch for + -fopt-info. Return zero otherwise. */ + +int +opt_info_switch_p (const char *arg) +{ + int flags; + char *filename; + + opt_info_switch_p_1 (arg, &flags, &filename); + + if (!filename) + filename = xstrdup ("stderr"); + if (!flags) + flags = MSG_ALL; + + return opt_info_enable_all ((TDF_TREE | TDF_RTL | TDF_IPA), flags, filename); +} + +/* Return true if any dumps are enabled for the given MSG_TYPE, false + otherwise. */ + +bool +dump_kind_p (int msg_type) +{ + if (!current_function_decl) + return 0; + return ((msg_type & pflags) || (msg_type & alt_flags)); +} + +/* Print basic block on the dump streams. */ + +void +dump_basic_block (int dump_kind, basic_block bb, int indent) +{ + if (dump_file && (dump_kind & pflags)) + dump_bb (dump_file, bb, indent, TDF_DETAILS); + if (alt_dump_file && (dump_kind & alt_flags)) + dump_bb (alt_dump_file, bb, indent, TDF_DETAILS); +} + +/* Print information from the combine pass on dump_file. */ + +void +print_combine_total_stats (void) +{ + if (dump_file) + dump_combine_total_stats (dump_file); +} + +/* Enable RTL dump for all the RTL passes. */ + +bool +enable_rtl_dump_file (void) +{ + return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0; +} -- cgit v1.2.1