dumpfile.c 27 KB

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