Thanks for your suggestions/comments. I have updated the patch and documentation. It supports the following usage:
gcc .... -fdump-tree-all=tree.dump -fdump-tree-pre=stdout -fdump-rtl-ira=ira.dump Here all tree dumps except the PRE are output into tree.dump, PRE dump goes to stdout and the IRA dump goes to ira.dump. Thanks, Sharad 2012-05-09 Sharad Singhai <sing...@google.com> * doc/invoke.texi: Add documentation for the new option. * tree-dump.c (dump_get_standard_stream): New function. (dump_files): Update for new field. (dump_switch_p_1): Handle dump filenames. (dump_begin): Likewise. (get_dump_file_name): Likewise. (dump_end): Remove attribute. (dump_enable_all): Add new parameter FILENAME. All callers updated. (enable_rtl_dump_file): * tree-pass.h (enum tree_dump_index): Add new constant. (struct dump_file_info): Add new field FILENAME. * testsuite/g++.dg/other/dump-filename-1.C: New test. Index: doc/invoke.texi =================================================================== --- doc/invoke.texi (revision 187265) +++ doc/invoke.texi (working copy) @@ -5322,20 +5322,23 @@ Here are some examples showing uses of these optio @item -d@var{letters} @itemx -fdump-rtl-@var{pass} +@itemx -fdump-rtl-@var{pass}=@var{filename} @opindex d Says to make debugging dumps during compilation at times specified by @var{letters}. This is used for debugging the RTL-based passes of the compiler. The file names for most of the dumps are made by appending a pass number and a word to the @var{dumpname}, and the files are -created in the directory of the output file. Note that the pass -number is computed statically as passes get registered into the pass -manager. Thus the numbering is not related to the dynamic order of -execution of passes. In particular, a pass installed by a plugin -could have a number over 200 even if it executed quite early. -@var{dumpname} is generated from the name of the output file, if -explicitly specified and it is not an executable, otherwise it is the -basename of the source file. These switches may have different effects -when @option{-E} is used for preprocessing. +created in the directory of the output file. If the +@option{=@var{filename}} is appended to the longer form of the dump +option then the dump is done on that file instead of numbered +files. Note that the pass number is computed statically as passes get +registered into the pass manager. Thus the numbering is not related +to the dynamic order of execution of passes. In particular, a pass +installed by a plugin could have a number over 200 even if it executed +quite early. @var{dumpname} is generated from the name of the output +file, if explicitly specified and it is not an executable, otherwise +it is the basename of the source file. These switches may have +different effects when @option{-E} is used for preprocessing. Debug dumps can be enabled with a @option{-fdump-rtl} switch or some @option{-d} option @var{letters}. Here are the possible @@ -5719,15 +5722,18 @@ counters for each function compiled. @item -fdump-tree-@var{switch} @itemx -fdump-tree-@var{switch}-@var{options} +@itemx -fdump-tree-@var{switch}-@var{options}=@var{filename} @opindex fdump-tree Control the dumping at various stages of processing the intermediate language tree to a file. The file name is generated by appending a switch specific suffix to the source file name, and the file is -created in the same directory as the output file. If the -@samp{-@var{options}} form is used, @var{options} is a list of -@samp{-} separated options which control the details of the dump. Not -all options are applicable to all dumps; those that are not -meaningful are ignored. The following options are available +created in the same directory as the output file. In case of +@option{=@var{filename}} option, the dump is output on the given file +name instead. If the @samp{-@var{options}} form is used, +@var{options} is a list of @samp{-} separated options which control +the details or location of the dump. Not all options are applicable +to all dumps; those that are not meaningful are ignored. The +following options are available @table @samp @item address @@ -5765,9 +5771,46 @@ Enable showing the tree dump for each statement. Enable showing the EH region number holding each statement. @item scev Enable showing scalar evolution analysis details. +@item slim +Inhibit dumping of members of a scope or body of a function merely +because that scope has been reached. Only dump such items when they +are directly reachable by some other path. When dumping pretty-printed +trees, this option inhibits dumping the bodies of control structures. +@item =@var{filename} +Instead of using an auto generated dump file name, use the given file +name. The file names @file{stdout} and @file{stderr} are treated +specially and are considered already open standard streams. For +example: + +@smallexample +gcc -O2 -fdump-tree-pre=stderr -fdump-rtl-ira=ira.txt ... +@end smallexample + +outputs PRE dump on @file{stderr}, while the IRA dump is output in a +file named @file{ira.txt}. + +In case of any conflicts, the command line file name takes precedence +over generated file names. For example: + +@smallexample +gcc -O2 -fdump-tree-pre=stdout -fdump-tree-pre ... +gcc -O2 -fdump-tree-pre -fdump-tree-pre=stdout ... +@end smallexample + +Both of the above output the PRE dump on @file{stdout}. However, if +there are multiple command line file names are applicable then the +last one is used. Thus the command + +@smallexample +gcc -O2 -fdump-tree-pre=stderr -fdump-tree-all=all.txt +@end smallexample + +outputs all the dumps in @file{all.txt} because the stderr option for +PRE dump is overridden by a later option. + @item all -Turn on all options, except @option{raw}, @option{slim}, @option{verbose} -and @option{lineno}. +Turn on all options, except @option{raw}, @option{slim}, @option{verbose}, +@option{lineno}. @end table The following tree dumps are possible: @@ -5913,6 +5956,7 @@ is made by appending @file{.vrp} to the source fil @item all @opindex fdump-tree-all Enable all the available tree dumps with the flags provided in this option. + @end table @item -ftree-vectorizer-verbose=@var{n} Index: tree-dump.c =================================================================== --- tree-dump.c (revision 187265) +++ tree-dump.c (working copy) @@ -773,20 +773,20 @@ dump_node (const_tree t, int flags, FILE *stream) tree_dump_index enumeration in tree-pass.h. */ static struct dump_file_info dump_files[TDI_end] = { - {NULL, NULL, NULL, 0, 0, 0}, - {".cgraph", "ipa-cgraph", NULL, TDF_IPA, 0, 0}, - {".tu", "translation-unit", NULL, TDF_TREE, 0, 1}, - {".class", "class-hierarchy", NULL, TDF_TREE, 0, 2}, - {".original", "tree-original", NULL, TDF_TREE, 0, 3}, - {".gimple", "tree-gimple", NULL, TDF_TREE, 0, 4}, - {".nested", "tree-nested", NULL, TDF_TREE, 0, 5}, - {".vcg", "tree-vcg", NULL, TDF_TREE, 0, 6}, - {".ads", "ada-spec", NULL, 0, 0, 7}, + {NULL, NULL, NULL, NULL, 0, 0, 0}, + {".cgraph", "ipa-cgraph", NULL, NULL, TDF_IPA, 0, 0}, + {".tu", "translation-unit", NULL, NULL, TDF_TREE, 0, 1}, + {".class", "class-hierarchy", NULL, NULL, TDF_TREE, 0, 2}, + {".original", "tree-original", NULL, NULL, TDF_TREE, 0, 3}, + {".gimple", "tree-gimple", NULL, NULL, TDF_TREE, 0, 4}, + {".nested", "tree-nested", NULL, NULL, TDF_TREE, 0, 5}, + {".vcg", "tree-vcg", NULL, NULL, TDF_TREE, 0, 6}, + {".ads", "ada-spec", NULL, NULL, 0, 0, 7}, #define FIRST_AUTO_NUMBERED_DUMP 8 - {NULL, "tree-all", NULL, TDF_TREE, 0, 0}, - {NULL, "rtl-all", NULL, TDF_RTL, 0, 0}, - {NULL, "ipa-all", NULL, TDF_IPA, 0, 0}, + {NULL, "tree-all", NULL, NULL, TDF_TREE, 0, 0}, + {NULL, "rtl-all", NULL, NULL, TDF_RTL, 0, 0}, + {NULL, "ipa-all", NULL, NULL, TDF_IPA, 0, 0}, }; /* Dynamically registered tree dump files and switches. */ @@ -802,7 +802,7 @@ struct dump_option_value_info }; /* Table of dump options. This must be consistent with the TDF_* flags - in tree.h */ + in tree-pass.h */ static const struct dump_option_value_info dump_options[] = { {"address", TDF_ADDRESS}, @@ -892,6 +892,9 @@ get_dump_file_name (int phase) if (dfi->state == 0) return NULL; + if (dfi->filename) + return xstrdup (dfi->filename); + if (dfi->num < 0) dump_id[0] = '\0'; else @@ -911,6 +914,22 @@ get_dump_file_name (int phase) return concat (dump_base_name, dump_id, dfi->suffix, NULL); } +/* If the DFI dump output corresponds to stdout or stderr stream, + return that stream, NULL otherwise. */ + +static FILE * +dump_get_standard_stream (struct dump_file_info *dfi) +{ + if (!dfi->filename) + return NULL; + + return strcmp("stderr", dfi->filename) == 0 + ? stderr + : strcmp("stdout", dfi->filename) == 0 + ? stdout + : NULL; +} + /* 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. @@ -926,14 +945,20 @@ dump_begin (int phase, int *flag_ptr) if (phase == TDI_none || !dump_enabled_p (phase)) return NULL; - name = get_dump_file_name (phase); dfi = get_dump_file_info (phase); - stream = fopen (name, dfi->state < 0 ? "w" : "a"); - if (!stream) - error ("could not open dump file %qs: %m", name); + stream = dump_get_standard_stream (dfi); + if (stream) + dfi->state = 1; else - dfi->state = 1; - free (name); + { + name = get_dump_file_name (phase); + stream = fopen (name, dfi->state < 0 ? "w" : "a"); + if (!stream) + error ("could not open dump file %qs: %m", name); + else + dfi->state = 1; + free (name); + } if (flag_ptr) *flag_ptr = dfi->flags; @@ -987,35 +1012,46 @@ dump_flag_name (int phase) dump_begin. */ void -dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream) +dump_end (int phase, FILE *stream) { - fclose (stream); + struct dump_file_info *dfi = get_dump_file_info (phase); + if (!dump_get_standard_stream (dfi)) + fclose (stream); } -/* Enable all tree dumps. Return number of enabled tree dumps. */ +/* Enable all tree dumps with FLAGS on FILENAME. Return number of + enabled tree dumps. */ static int -dump_enable_all (int flags) +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].flags & ir_dump_type)) - { - dump_files[i].state = -1; - dump_files[i].flags |= flags; - n++; - } + { + if ((dump_files[i].flags & ir_dump_type)) + { + dump_files[i].state = -1; + dump_files[i].flags |= flags; + n++; + if (filename) + dump_files[i].filename = xstrdup (filename); + } + } for (i = 0; i < extra_dump_files_in_use; i++) - if ((extra_dump_files[i].flags & ir_dump_type)) - { - extra_dump_files[i].state = -1; - extra_dump_files[i].flags |= flags; - n++; - } + { + if ((extra_dump_files[i].flags & ir_dump_type)) + { + extra_dump_files[i].state = -1; + extra_dump_files[i].flags |= flags; + n++; + if (filename) + extra_dump_files[i].filename = xstrdup (filename); + } + } return n; } @@ -1037,7 +1073,7 @@ dump_switch_p_1 (const char *arg, struct dump_file if (!option_value) return 0; - if (*option_value && *option_value != '-') + if (*option_value && *option_value != '-' && *option_value != '=') return 0; ptr = option_value; @@ -1052,17 +1088,30 @@ dump_switch_p_1 (const char *arg, struct dump_file while (*ptr == '-') ptr++; end_ptr = strchr (ptr, '-'); + if (!end_ptr) end_ptr = ptr + strlen (ptr); length = end_ptr - ptr; + if (*ptr == '=') + { + /* Interpret rest of the argument as a dump filename. This + filename overrides generated dump names as well as other + command line filenames. */ + flags |= TDF_FILENAME; + if (dfi->filename) + free (dfi->filename); + dfi->filename = xstrdup (ptr + 1); + break; + } + 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; + { + flags |= option_ptr->value; goto found; - } + } warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>", length, ptr, dfi->swtch); found:; @@ -1075,7 +1124,7 @@ dump_switch_p_1 (const char *arg, struct dump_file /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the known dumps. */ if (dfi->suffix == NULL) - dump_enable_all (dfi->flags); + dump_enable_all (dfi->flags, dfi->filename); return 1; } @@ -1124,5 +1173,5 @@ dump_function (int phase, tree fn) bool enable_rtl_dump_file (void) { - return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0; + return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0; } Index: tree-pass.h =================================================================== --- tree-pass.h (revision 187265) +++ tree-pass.h (working copy) @@ -84,8 +84,9 @@ enum tree_dump_index #define TDF_ENUMERATE_LOCALS (1 << 22) /* Enumerate locals by uid. */ #define TDF_CSELIB (1 << 23) /* Dump cselib details. */ #define TDF_SCEV (1 << 24) /* Dump SCEV details. */ +#define TDF_FILENAME (1 << 25) /* Dump on provided filename + instead of constructing one. */ - /* In tree-dump.c */ extern char *get_dump_file_name (int); @@ -222,6 +223,8 @@ struct dump_file_info const char *suffix; /* suffix to give output file. */ const char *swtch; /* command line switch */ const char *glob; /* command line glob */ + const char *filename; /* use this filename instead of making + up one using dump_base_name + suffix. */ int flags; /* user flags */ int state; /* state of play */ int num; /* dump file number */ Index: testsuite/g++.dg/other/dump-filename-1.C =================================================================== --- testsuite/g++.dg/other/dump-filename-1.C (revision 0) +++ testsuite/g++.dg/other/dump-filename-1.C (revision 0) @@ -0,0 +1,11 @@ +// Test that the dump to a user-defined file works correctly. +/* { dg-options "-O2 -fdump-tree-original=foobar.dump" } */ + +void test (int *b, int *e, int stride) + { + for (int *p = b; p != e; p += stride) + *p = 1; + } + +/* { dg-final { scan-file foobar.dump ";; Function void test" } } */ +/* { dg-final { remove-build-file "foobar.dump" } } */ On Wed, May 9, 2012 at 12:22 AM, Gabriel Dos Reis <g...@integrable-solutions.net> wrote: > On Wed, May 9, 2012 at 1:46 AM, Sharad Singhai <sing...@google.com> wrote: > [...] > >> +@item -fdump-rtl-all=stderr >> +@opindex fdump-rtl-all=stderr > > You do not need to have a separate index entry for '=stderr' or '=stdout'. > Rather, expand the description to state this in all the documentation > for -fdump-xxx=yyy. > > [...] > >> +/* Return non-zero iff the USER_FILENAME corresponds to stdout or >> + stderr stream. */ >> + >> +static int >> +dump_stream_p (const char *user_filename) >> +{ >> + if (user_filename) >> + return !strncmp ("stderr", user_filename, 6) || >> + !strncmp ("stdout", user_filename, 6); >> + else >> + return 0; >> +} > > The name is ambiguous. > This function is testing whether its string argument designates one of > the *standard* output streams. Name it to reflect that.. > Have it take the dump state context. Also the coding convention: the binary > operator "||" should be on next line. In fact the thing could be > simpler. Instead of > testing over and over again against "stderr" (once in this function, then > again > later), just return the corresponding standard FILE* pointer. > Also, this is a case of overuse of strncmp. If you name the function > dump_get_standard_stream: > > return strcmp("stderr", dfi->user_filename) == 0 > ? stderr > : stdcmp("stdout", dfi->use_filename) > ? stdout > : NULL; > > you can simplify: > >> - name = get_dump_file_name (phase); >> dfi = get_dump_file_info (phase); >> - stream = fopen (name, dfi->state < 0 ? "w" : "a"); >> - if (!stream) >> - error ("could not open dump file %qs: %m", name); >> + if (dump_stream_p (dfi->user_filename)) >> + { >> + if (!strncmp ("stderr", dfi->user_filename, 6)) >> + stream = stderr; >> + else >> + if (!strncmp ("stdout", dfi->user_filename, 6)) >> + stream = stdout; >> + else >> + error ("unknown stream: %qs: %m", dfi->user_filename); >> + dfi->state = 1; >> + } >> else >> - dfi->state = 1; >> - free (name); >> + { >> + name = get_dump_file_name (phase); >> + stream = fopen (name, dfi->state < 0 ? "w" : "a"); >> + if (!stream) >> + error ("could not open dump file %qs: %m", name); >> + else >> + dfi->state = 1; >> + free (name); >> + } >> >> if (flag_ptr) >> *flag_ptr = dfi->flags; >> @@ -987,35 +1017,45 @@ dump_flag_name (int phase) >> dump_begin. */ >> >> void >> -dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream) >> +dump_end (int phase, FILE *stream) >> { >> - fclose (stream); >> + struct dump_file_info *dfi = get_dump_file_info (phase); >> + if (!dump_stream_p (dfi->user_filename)) >> + fclose (stream); >> } >> >> /* Enable all tree dumps. Return number of enabled tree dumps. */ >> >> static int >> -dump_enable_all (int flags) >> +dump_enable_all (int flags, const char *user_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].flags & ir_dump_type)) >> - { >> - dump_files[i].state = -1; >> - dump_files[i].flags |= flags; >> - n++; >> - } >> + { >> + if ((dump_files[i].flags & ir_dump_type)) >> + { >> + dump_files[i].state = -1; >> + dump_files[i].flags |= flags; >> + n++; >> + } >> + if (user_filename) >> + dump_files[i].user_filename = user_filename; >> + } >> >> for (i = 0; i < extra_dump_files_in_use; i++) >> - if ((extra_dump_files[i].flags & ir_dump_type)) >> - { >> - extra_dump_files[i].state = -1; >> - extra_dump_files[i].flags |= flags; >> - n++; >> - } >> + { >> + if ((extra_dump_files[i].flags & ir_dump_type)) >> + { >> + extra_dump_files[i].state = -1; >> + extra_dump_files[i].flags |= flags; >> + n++; >> + } >> + if (user_filename) >> + extra_dump_files[i].user_filename = user_filename; >> + } >> >> return n; >> } >> @@ -1037,7 +1077,7 @@ dump_switch_p_1 (const char *arg, struct dump_file >> if (!option_value) >> return 0; >> >> - if (*option_value && *option_value != '-') >> + if (*option_value && *option_value != '-' && *option_value != '=') >> return 0; >> >> ptr = option_value; >> @@ -1052,17 +1092,30 @@ dump_switch_p_1 (const char *arg, struct dump_file >> while (*ptr == '-') >> ptr++; >> end_ptr = strchr (ptr, '-'); >> + >> if (!end_ptr) >> end_ptr = ptr + strlen (ptr); >> length = end_ptr - ptr; >> >> + if (*ptr == '=') >> + { >> + /* Interpret rest of the argument as a dump filename. The >> + user provided filename overrides generated dump names as >> + well as other command line filenames. */ >> + flags |= TDF_USER_FILENAME; >> + if (dfi->user_filename) >> + free (dfi->user_filename); >> + dfi->user_filename = xstrdup (ptr + 1); >> + break; >> + } >> + >> 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; >> + { >> + flags |= option_ptr->value; >> goto found; >> - } >> + } >> warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>", >> length, ptr, dfi->swtch); >> found:; >> @@ -1075,7 +1128,7 @@ dump_switch_p_1 (const char *arg, struct dump_file >> /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the >> known dumps. */ >> if (dfi->suffix == NULL) >> - dump_enable_all (dfi->flags); >> + dump_enable_all (dfi->flags, dfi->user_filename); >> >> return 1; >> } >> @@ -1124,5 +1177,5 @@ dump_function (int phase, tree fn) >> bool >> enable_rtl_dump_file (void) >> { >> - return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0; >> + return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0; >> } >> Index: tree-pass.h >> =================================================================== >> --- tree-pass.h (revision 187265) >> +++ tree-pass.h (working copy) >> @@ -84,8 +84,9 @@ enum tree_dump_index >> #define TDF_ENUMERATE_LOCALS (1 << 22) /* Enumerate locals by uid. */ >> #define TDF_CSELIB (1 << 23) /* Dump cselib details. */ >> #define TDF_SCEV (1 << 24) /* Dump SCEV details. */ >> +#define TDF_USER_FILENAME (1 << 25) /* Dump on user provided filename, >> + instead of constructing one. */ >> >> - >> /* In tree-dump.c */ >> >> extern char *get_dump_file_name (int); >> @@ -222,6 +223,8 @@ struct dump_file_info >> const char *suffix; /* suffix to give output file. */ >> const char *swtch; /* command line switch */ >> const char *glob; /* command line glob */ >> + const char *user_filename; /* user provided filename instead of making >> + up one using dump_base_name + suffix. */ > > There is "no user" here: we are the users :-) Just call it "filename". > > -- Gaby