On Fri, May 11, 2012 at 8:11 PM, Xinliang David Li <davi...@google.com> wrote: > To be more specific, does the following match what your envisioned? > > 1) when multiple streams are specified for dumping, the information > will be dumped to all streams IF the new dumping interfaces are used > (see below). For legacy code, the default dump file will still be used > and the user specified file (including stderr) will be silently > ignored. This is of course temporary until all dumping sites are > converted
Yes, that sounds reasonable. > 2) Define the following new dumping interfaces which will honor all > streams specified > > dump_printf (const char*, ....); // for raw string dumping > dump_generic_expr (...); // wrapper to print_generic_expr without > taking FILE* > dump_node (...); // wrapper to print_node > dump_gimple_stmt(...); // wrapper to print_gimple_stmt Yes. Please add a classification argument to each of the wrappers to allow selective filtering (I'd simply use the existing TDF_* flags for now - in the future they should be made more granular than 0 vs. TDF_details). The existing if (dump_file && (dump_flags & ...)) checks need to be adjusted, of course. if (dump_enabled_p ()) or if (dump_enabled_p (flags)). > dump_inform (...); //wrapper to inform (..) method, but is aware of > of the dumping streams and modify global_dc appropriately. inform () is not part of the dumping infrastructure, thus passes should not use it. The dumping implementation, if re-directed via -fopt-report, might use inform () to print messages though. > 3) Implement -fopt-info=N, and take -ftree-vectorizer-verbose as the > first guinea pig to use the new dumping interfaces. Yes, I think all of 1) to 2) do not make sense without 3), so I'd prefer to see all that (well, the relevant bits of 2) to make 3) work) together. > After the infrastructure is ready, gradually deprecate the use of the > original dumper interfaces. Yes, passes can be converted independently. > what do you think? That plan sounds good to me. Thanks, Richard. > thanks, > > David > > On Fri, May 11, 2012 at 9:06 AM, Xinliang David Li <davi...@google.com> wrote: >> On Fri, May 11, 2012 at 1:49 AM, Richard Guenther >> <richard.guent...@gmail.com> wrote: >>> On Thu, May 10, 2012 at 6:28 PM, Xinliang David Li <davi...@google.com> >>> wrote: >>>> I like your suggestion and support the end goal you have. I don't >>>> like the -fopt-info behavior to interfere with regular -fdump-xxx >>>> options either. >>>> >>>> I think we should stage the changes in multiple steps as originally >>>> planned. Is Sharad's change good to be checked in for the first stage? >>> >>> Well - I don't think the change walks in the direction we want to go, so I >>> don't >>> see a good reason to make that change. >> >> Is your direction misunderstood or you want everything to be changed >> in one single patch (including replacement of all fprintf (dump_file, >> ...)? If the former, please clarify. If the latter, it can be done. >> >> thanks, >> >> David >> >>> >>>> After this one is checked in, the new dump interfaces will be worked >>>> on (and to allow multiple streams). Most of the remaining changes will >>>> be massive text replacement. >>>> >>>> thanks, >>>> >>>> David >>>> >>>> >>>> On Thu, May 10, 2012 at 1:18 AM, Richard Guenther >>>> <richard.guent...@gmail.com> wrote: >>>>> On Thu, May 10, 2012 at 2:31 AM, Xinliang David Li <davi...@google.com> >>>>> wrote: >>>>>> Bummer. I was thinking to reserve '=' for selective dumping: >>>>>> >>>>>> -fdump-tree-pre=<func_list_regexp> >>>>>> >>>>>> I guess this can be achieved via @ >>>>>> >>>>>> -fdump-tree-pre@<func_list> >>>>>> >>>>>> -fdump-tree-pre=<file_name>@<func_list> >>>>>> >>>>>> >>>>>> Another issue -- I don't think the current precedence rule is correct. >>>>>> Consider that -fopt-info=2 will be mapped to >>>>>> >>>>>> -fdump-tree-all-transform-verbose2=stderr >>>>>> -fdump-rtl-all-transform-verbose2=stderr >>>>>> >>>>>> then >>>>>> >>>>>> the current precedence rule will cause surprise when the following is >>>>>> used >>>>>> >>>>>> -fopt-info -fdump-tree-pre >>>>>> >>>>>> The PRE dump will be emitted to stderr which is not what user wants. >>>>>> In short, special streams should be treated as 'weak' the same way as >>>>>> your previous implementation. >>>>> >>>>> Hm, this raises a similar concern I have with the -fvectorizer-verbose >>>>> flag. >>>>> With -fopt-info -fdump-tree-pre I do not want some information to be >>>>> present only on stderr or in the dump file! I want it in _both_ places! >>>>> (-fvectorizer-verbose makes the -fdump-tree-vect dump contain less >>>>> information :() >>>>> >>>>> Thus, the information where dumping goes has to be done differently >>>>> (which is why I asked for some re-org originally, so that passes no >>>>> longer explicitely reference dump_file - dump_file may be different >>>>> for different kind of information it dumps!). Passes should, instead of >>>>> >>>>> fprintf (dump_file, "...", ...) >>>>> >>>>> do >>>>> >>>>> dump_printf (TDF_scev, "...", ...) >>>>> >>>>> thus, specify the kind of information they dump (would be mostly >>>>> TDF_details vs. 0 today I guess). The dump_printf routine would >>>>> then properly direct to one or more places to dump at. >>>>> >>>>> I realize this needs some more dispatchers for dumping expressions >>>>> and statements (but it should not be too many). Dumping to >>>>> dump_file would in any case dump to the passes private dump file >>>>> only (unqualified stuff would never be useful for -fopt-info). >>>>> >>>>> The perfect candidate to convert to this kind of scheme is obviously >>>>> the vectorizer with its existing -fvectorizer-verbose. >>>>> >>>>> If the patch doesn't work towards this kind of end-result I'd rather >>>>> not have it. >>>>> >>>>> Thanks, >>>>> Richard. >>>>> >>>>>> thanks, >>>>>> >>>>>> David >>>>>> >>>>>> >>>>>> >>>>>> On Wed, May 9, 2012 at 4:56 PM, Sharad Singhai <sing...@google.com> >>>>>> wrote: >>>>>>> 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