On Tue, May 8, 2012 at 11:46 PM, Sharad Singhai <sing...@google.com> wrote: > In response to comments, I have updated the patch to support dumps in > user provided files via the option -fdump-xxx=<filename>. The > filenames stdout/stderr are treated specially, and are considered > standard streams.
I think - should also be treated as special (or maybe the only one which should be treated as special). Thanks, Andrew Pinski > > Also updated documentation and a testcase. Okay for trunk? > > Thanks, > Sharad > > 2012-05-08 Sharad Singhai <sing...@google.com> > > * doc/invoke.texi: Add documentation for new option. > * tree-dump.c (dump_stream_p): New function. > (dump_files): Update for new field. > (dump_switch_p_1): Handle user provided filenames. > (dump_begin): Likewise. > (get_dump_file_name): Likewise. > (dump_enable_all): Add new parameter USER_FILENAME. > All callers updated. > (dump_end): Remove attribute. > * tree-pass.h (enum tree_dump_index): Add new constant. > (struct dump_file_info): Add new field USER_FILENAME. > * testsuite/g++.dg/other/dump-userfile-1.C: New test. > > Index: doc/invoke.texi > =================================================================== > --- doc/invoke.texi (revision 187265) > +++ doc/invoke.texi (working copy) > @@ -5322,20 +5322,24 @@ 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. The filenames stdout and stderr are treated specially. 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 > @@ -5599,6 +5603,10 @@ These dumps are defined but always produce empty f > @opindex fdump-rtl-all > Produce all the dumps listed above. > > +@item -fdump-rtl-all=stderr > +@opindex fdump-rtl-all=stderr > +Produce all RTL dumps on stderr. > + > @item -dA > @opindex dA > Annotate the assembler output with miscellaneous debugging information. > @@ -5719,15 +5727,19 @@ 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}}, the dump output is on the given file. Note > +that the filenames stdout and stderr are treated specially and dumps > +are done on standard streams. 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 +5777,56 @@ 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 name for a dump file, use the > +provided name. For example: > + > +@smallexample > +gcc -O2 -fdump-tree-pre=foobar.dump > +@end smallexample > + > +produces PRE dump in a file named foobar.dump. Similarly > + > +@smallexample > +gcc -O2 -fdump-tree-all=all.dump > +@end smallexample > + > +produces all tree dumps in a file named all.dump. > + > +Note that stdout and stderr are treated specially, and the dumps are > +done on standard streams. In case of any conflicts, the user provided > +filename takes precedence. For example: > + > +@smallexample > +gcc -O2 -fdump-tree-pre=stderr -fdump-tree-pre ... > +gcc -O2 -fdump-tree-pre -fdump-tree-pre=stderr ... > +@end smallexample > + > +Both invocations produce the PRE dump on stderr. Similarly, for the > +following > + > +@smallexample > +gcc -O2 -fdump-tree-all=stderr -fdump-tree-pre ... > +@end smallexample > + > +All the dumps are output on stderr. In the following example, > + > +@smallexample > +gcc -fdump-tree-all -fdump-tree-pre=stderr ... > +@end smallexample > + > +all the dumps are written into named files except the PRE dump, which > +is output on stderr, because @option{-fdump-tree-pre=stderr} takes > +precedence. > + > @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 +5972,10 @@ 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. > + > +@item all=stderr > +@opindex fdump-tree-all=stderr > +Enable all the available tree dumps on the stderr. > @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->user_filename) > + return xstrdup (dfi->user_filename); > + > if (dfi->num < 0) > dump_id[0] = '\0'; > else > @@ -911,6 +914,19 @@ get_dump_file_name (int phase) > return concat (dump_base_name, dump_id, dfi->suffix, NULL); > } > > +/* 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; > +} > + > /* 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 +942,28 @@ 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); > + 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. */ > int flags; /* user flags */ > int state; /* state of play */ > int num; /* dump file number */ > Index: testsuite/g++.dg/other/dump-userfile-1.C > =================================================================== > --- testsuite/g++.dg/other/dump-userfile-1.C (revision 0) > +++ testsuite/g++.dg/other/dump-userfile-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" } } */ > > -- > This patch is available for review at http://codereview.appspot.com/6190057