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