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