LCOV - code coverage report
Current view: top level - gcc - dumpfile.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 93.3 % 1198 1118
Test Date: 2026-02-28 14:20:25 Functions: 88.3 % 120 106
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Dump infrastructure for optimizations and intermediate representation.
       2              :    Copyright (C) 2012-2026 Free Software Foundation, Inc.
       3              : 
       4              : This file is part of GCC.
       5              : 
       6              : GCC is free software; you can redistribute it and/or modify it under
       7              : the terms of the GNU General Public License as published by the Free
       8              : Software Foundation; either version 3, or (at your option) any later
       9              : version.
      10              : 
      11              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14              : for more details.
      15              : 
      16              : You should have received a copy of the GNU General Public License
      17              : along with GCC; see the file COPYING3.  If not see
      18              : <http://www.gnu.org/licenses/>.  */
      19              : 
      20              : #include "config.h"
      21              : #include "system.h"
      22              : #include "coretypes.h"
      23              : #include "options.h"
      24              : #include "tree.h"
      25              : #include "gimple-pretty-print.h"
      26              : #include "diagnostic-core.h"
      27              : #include "dumpfile.h"
      28              : #include "context.h"
      29              : #include "profile-count.h"
      30              : #include "tree-cfg.h"
      31              : #include "langhooks.h"
      32              : #include "backend.h" /* for gimple.h.  */
      33              : #include "gimple.h" /* for dump_user_location_t ctor.  */
      34              : #include "rtl.h" /* for dump_user_location_t ctor.  */
      35              : #include "selftest.h"
      36              : #include "optinfo.h"
      37              : #include "dump-context.h"
      38              : #include "cgraph.h"
      39              : #include "tree-pass.h" /* for "current_pass".  */
      40              : #include "optinfo-emit-json.h"
      41              : #include "stringpool.h" /* for get_identifier.  */
      42              : #include "spellcheck.h"
      43              : #include "pretty-print-format-impl.h"
      44              : 
      45              : /* If non-NULL, return one past-the-end of the matching SUBPART of
      46              :    the WHOLE string.  */
      47              : #define skip_leading_substring(whole,  part) \
      48              :    (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part))
      49              : 
      50              : static dump_flags_t pflags;                   /* current dump_flags */
      51              : 
      52              : static void dump_loc (dump_flags_t, FILE *, location_t);
      53              : 
      54              : /* Current -fopt-info output stream, if any, and flags.  */
      55              : static FILE *alt_dump_file = NULL;
      56              : static dump_flags_t alt_flags;
      57              : 
      58              : static FILE *dump_open_alternate_stream (struct dump_file_info *);
      59              : 
      60              : /* These are currently used for communicating between passes.
      61              :    However, instead of accessing them directly, the passes can use
      62              :    dump_printf () for dumps.  */
      63              : FILE *dump_file = NULL;
      64              : const char *dump_file_name;
      65              : dump_flags_t dump_flags;
      66              : bool dumps_are_enabled = false;
      67              : 
      68              : 
      69              : /* Set global "dump_file" to NEW_DUMP_FILE, refreshing the "dumps_are_enabled"
      70              :    global.  */
      71              : 
      72              : void
      73    293560110 : set_dump_file (FILE *new_dump_file)
      74              : {
      75    293560110 :   dumpfile_ensure_any_optinfo_are_flushed ();
      76    293560110 :   dump_file = new_dump_file;
      77    293560110 :   dump_context::get ().refresh_dumps_are_enabled ();
      78    293560110 : }
      79              : 
      80              : /* Set "alt_dump_file" to NEW_ALT_DUMP_FILE, refreshing the "dumps_are_enabled"
      81              :    global.  */
      82              : 
      83              : static void
      84    292540078 : set_alt_dump_file (FILE *new_alt_dump_file)
      85              : {
      86    292540078 :   dumpfile_ensure_any_optinfo_are_flushed ();
      87    292540078 :   alt_dump_file = new_alt_dump_file;
      88    292540078 :   dump_context::get ().refresh_dumps_are_enabled ();
      89    292540078 : }
      90              : 
      91              : #define DUMP_FILE_INFO(suffix, swtch, dkind, num) \
      92              :   {suffix, swtch, NULL, NULL, NULL, NULL, NULL, dkind, TDF_NONE, TDF_NONE, \
      93              :    OPTGROUP_NONE, 0, 0, num, false, false}
      94              : 
      95              : /* Table of tree dump switches. This must be consistent with the
      96              :    TREE_DUMP_INDEX enumeration in dumpfile.h.  */
      97              : static struct dump_file_info dump_files[TDI_end] =
      98              : {
      99              :   DUMP_FILE_INFO (NULL, NULL, DK_none, 0),
     100              :   DUMP_FILE_INFO (".cgraph", "ipa-cgraph", DK_ipa, 0),
     101              :   DUMP_FILE_INFO (".type-inheritance", "ipa-type-inheritance", DK_ipa, 0),
     102              :   DUMP_FILE_INFO (".ipa-clones", "ipa-clones", DK_ipa, 0),
     103              :   DUMP_FILE_INFO (".original", "tree-original", DK_tree, 0),
     104              :   DUMP_FILE_INFO (".gimple", "tree-gimple", DK_tree, 0),
     105              :   DUMP_FILE_INFO (".nested", "tree-nested", DK_tree, 0),
     106              :   DUMP_FILE_INFO (".lto-stream-out", "ipa-lto-stream-out", DK_ipa, 0),
     107              :   DUMP_FILE_INFO (".profile-report", "profile-report", DK_ipa, 0),
     108              : #define FIRST_AUTO_NUMBERED_DUMP 1
     109              : #define FIRST_ME_AUTO_NUMBERED_DUMP 6
     110              : 
     111              :   DUMP_FILE_INFO (NULL, "lang-all", DK_lang, 0),
     112              :   DUMP_FILE_INFO (NULL, "tree-all", DK_tree, 0),
     113              :   DUMP_FILE_INFO (NULL, "rtl-all", DK_rtl, 0),
     114              :   DUMP_FILE_INFO (NULL, "ipa-all", DK_ipa, 0),
     115              : };
     116              : 
     117              : /* Table of dump options. This must be consistent with the TDF_* flags
     118              :    in dumpfile.h and opt_info_options below. */
     119              : static const kv_pair<dump_flags_t> dump_options[] =
     120              : {
     121              :   {"none", TDF_NONE},
     122              :   {"address", TDF_ADDRESS},
     123              :   {"asmname", TDF_ASMNAME},
     124              :   {"slim", TDF_SLIM},
     125              :   {"raw", TDF_RAW},
     126              :   {"graph", TDF_GRAPH},
     127              :   {"details", (TDF_DETAILS | MSG_OPTIMIZED_LOCATIONS
     128              :                | MSG_MISSED_OPTIMIZATION
     129              :                | MSG_NOTE)},
     130              :   {"cselib", TDF_CSELIB},
     131              :   {"stats", TDF_STATS},
     132              :   {"blocks", TDF_BLOCKS},
     133              :   {"vops", TDF_VOPS},
     134              :   {"lineno", TDF_LINENO},
     135              :   {"uid", TDF_UID},
     136              :   {"stmtaddr", TDF_STMTADDR},
     137              :   {"memsyms", TDF_MEMSYMS},
     138              :   {"eh", TDF_EH},
     139              :   {"alias", TDF_ALIAS},
     140              :   {"nouid", TDF_NOUID},
     141              :   {"enumerate_locals", TDF_ENUMERATE_LOCALS},
     142              :   {"scev", TDF_SCEV},
     143              :   {"gimple", TDF_GIMPLE},
     144              :   {"folding", TDF_FOLDING},
     145              :   {"optimized", MSG_OPTIMIZED_LOCATIONS},
     146              :   {"missed", MSG_MISSED_OPTIMIZATION},
     147              :   {"note", MSG_NOTE},
     148              :   {"optall", MSG_ALL_KINDS},
     149              :   {"all", dump_flags_t (TDF_ALL_VALUES
     150              :                         & ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_GRAPH
     151              :                             | TDF_STMTADDR | TDF_RHS_ONLY | TDF_NOUID
     152              :                             | TDF_ENUMERATE_LOCALS | TDF_SCEV | TDF_GIMPLE))},
     153              :   {NULL, TDF_NONE}
     154              : };
     155              : 
     156              : /* A subset of the dump_options table which is used for -fopt-info
     157              :    types. This must be consistent with the MSG_* flags in dumpfile.h.
     158              :  */
     159              : static const kv_pair<dump_flags_t> optinfo_verbosity_options[] =
     160              : {
     161              :   {"optimized", MSG_OPTIMIZED_LOCATIONS},
     162              :   {"missed", MSG_MISSED_OPTIMIZATION},
     163              :   {"note", MSG_NOTE},
     164              :   {"all", MSG_ALL_KINDS},
     165              :   {"internals", MSG_PRIORITY_INTERNALS},
     166              :   {NULL, TDF_NONE}
     167              : };
     168              : 
     169              : /* Flags used for -fopt-info groups.  */
     170              : const kv_pair<optgroup_flags_t> optgroup_options[] =
     171              : {
     172              :   {"ipa", OPTGROUP_IPA},
     173              :   {"loop", OPTGROUP_LOOP},
     174              :   {"inline", OPTGROUP_INLINE},
     175              :   {"omp", OPTGROUP_OMP},
     176              :   {"vec", OPTGROUP_VEC},
     177              :   {"optall", OPTGROUP_ALL},
     178              :   {NULL, OPTGROUP_NONE}
     179              : };
     180              : 
     181       285722 : gcc::dump_manager::dump_manager ():
     182       285722 :   m_next_dump (FIRST_AUTO_NUMBERED_DUMP),
     183       285722 :   m_extra_dump_files (NULL),
     184       285722 :   m_extra_dump_files_in_use (0),
     185       285722 :   m_extra_dump_files_alloced (0),
     186       285722 :   m_optgroup_flags (OPTGROUP_NONE),
     187       285722 :   m_optinfo_flags (TDF_NONE),
     188       285722 :   m_optinfo_filename (NULL)
     189              : {
     190       285722 : }
     191              : 
     192       256621 : gcc::dump_manager::~dump_manager ()
     193              : {
     194       256621 :   free (m_optinfo_filename);
     195     94631269 :   for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
     196              :     {
     197     94374648 :       dump_file_info *dfi = &m_extra_dump_files[i];
     198              :       /* suffix, swtch, glob are statically allocated for the entries
     199              :          in dump_files, and for statistics, but are dynamically allocated
     200              :          for those for passes.  */
     201     94374648 :       if (dfi->owns_strings)
     202              :         {
     203     93153479 :           XDELETEVEC (const_cast <char *> (dfi->suffix));
     204     93153479 :           XDELETEVEC (const_cast <char *> (dfi->swtch));
     205     93153479 :           XDELETEVEC (const_cast <char *> (dfi->glob));
     206              :         }
     207              :       /* These, if non-NULL, are always dynamically allocated.  */
     208     94374648 :       XDELETEVEC (const_cast <char *> (dfi->pfilename));
     209     94374648 :       XDELETEVEC (const_cast <char *> (dfi->alt_filename));
     210              :     }
     211       256621 :   XDELETEVEC (m_extra_dump_files);
     212       256621 : }
     213              : 
     214              : unsigned int
     215    105123041 : gcc::dump_manager::
     216              : dump_register (const char *suffix, const char *swtch, const char *glob,
     217              :                dump_kind dkind, optgroup_flags_t optgroup_flags,
     218              :                bool take_ownership)
     219              : {
     220    105123041 :   int num = m_next_dump++;
     221              : 
     222    105123041 :   size_t count = m_extra_dump_files_in_use++;
     223              : 
     224    105123041 :   if (count >= m_extra_dump_files_alloced)
     225              :     {
     226       285722 :       if (m_extra_dump_files_alloced == 0)
     227       285722 :         m_extra_dump_files_alloced = 512;
     228              :       else
     229            0 :         m_extra_dump_files_alloced *= 2;
     230       285722 :       m_extra_dump_files = XRESIZEVEC (struct dump_file_info,
     231              :                                        m_extra_dump_files,
     232              :                                        m_extra_dump_files_alloced);
     233              : 
     234              :       /* Construct a new object in the space allocated above.  */
     235       285722 :       new (m_extra_dump_files + count) dump_file_info ();
     236              :     }
     237              :   else
     238              :     {
     239              :       /* Zero out the already constructed object.  */
     240    104837319 :       m_extra_dump_files[count] = dump_file_info ();
     241              :     }
     242              : 
     243    105123041 :   m_extra_dump_files[count].suffix = suffix;
     244    105123041 :   m_extra_dump_files[count].swtch = swtch;
     245    105123041 :   m_extra_dump_files[count].glob = glob;
     246    105123041 :   m_extra_dump_files[count].dkind = dkind;
     247    105123041 :   m_extra_dump_files[count].optgroup_flags = optgroup_flags;
     248    105123041 :   m_extra_dump_files[count].num = num;
     249    105123041 :   m_extra_dump_files[count].owns_strings = take_ownership;
     250              : 
     251    105123041 :   return count + TDI_end;
     252              : }
     253              : 
     254              : 
     255              : /* Allow languages and middle-end to register their dumps before the
     256              :    optimization passes.  */
     257              : 
     258              : void
     259       285722 : gcc::dump_manager::
     260              : register_dumps ()
     261              : {
     262       285722 :   lang_hooks.register_dumps (this);
     263              :   /* If this assert fails, some FE registered more than
     264              :      FIRST_ME_AUTO_NUMBERED_DUMP - FIRST_AUTO_NUMBERED_DUMP
     265              :      dump files.  Bump FIRST_ME_AUTO_NUMBERED_DUMP accordingly.  */
     266       285722 :   gcc_assert (m_next_dump <= FIRST_ME_AUTO_NUMBERED_DUMP);
     267       285722 :   m_next_dump = FIRST_ME_AUTO_NUMBERED_DUMP;
     268       285722 :   dump_files[TDI_original].num = m_next_dump++;
     269       285722 :   dump_files[TDI_gimple].num = m_next_dump++;
     270       285722 :   dump_files[TDI_nested].num = m_next_dump++;
     271       285722 : }
     272              : 
     273              : 
     274              : /* Return the dump_file_info for the given phase.  */
     275              : 
     276              : struct dump_file_info *
     277   2673132252 : gcc::dump_manager::
     278              : get_dump_file_info (int phase) const
     279              : {
     280   2673132252 :   if (phase < TDI_end)
     281    111417007 :     return &dump_files[phase];
     282   2561715245 :   else if ((size_t) (phase - TDI_end) >= m_extra_dump_files_in_use)
     283              :     return NULL;
     284              :   else
     285   2561438483 :     return m_extra_dump_files + (phase - TDI_end);
     286              : }
     287              : 
     288              : /* Locate the dump_file_info with swtch equal to SWTCH,
     289              :    or return NULL if no such dump_file_info exists.  */
     290              : 
     291              : struct dump_file_info *
     292           50 : gcc::dump_manager::
     293              : get_dump_file_info_by_switch (const char *swtch) const
     294              : {
     295        12035 :   for (unsigned i = 0; i < m_extra_dump_files_in_use; i++)
     296        12030 :     if (strcmp (m_extra_dump_files[i].swtch, swtch) == 0)
     297              :       return &m_extra_dump_files[i];
     298              : 
     299              :   /* Not found.  */
     300              :   return NULL;
     301              : }
     302              : 
     303              : 
     304              : /* Return the name of the dump file for the given phase.
     305              :    The caller is responsible for calling free on the returned
     306              :    buffer.
     307              :    If the dump is not enabled, returns NULL.  */
     308              : 
     309              : char *
     310    292153184 : gcc::dump_manager::
     311              : get_dump_file_name (int phase, int part) const
     312              : {
     313    292153184 :   struct dump_file_info *dfi;
     314              : 
     315    292153184 :   if (phase == TDI_none)
     316              :     return NULL;
     317              : 
     318    284367081 :   dfi = get_dump_file_info (phase);
     319              : 
     320    284367081 :   return get_dump_file_name (dfi, part);
     321              : }
     322              : 
     323              : /* Return the name of the dump file for the given dump_file_info.
     324              :    The caller is responsible for calling free on the returned
     325              :    buffer.
     326              :    If the dump is not enabled, returns NULL.  */
     327              : 
     328              : char *
     329    284367291 : gcc::dump_manager::
     330              : get_dump_file_name (struct dump_file_info *dfi, int part) const
     331              : {
     332    284367291 :   char dump_id[10];
     333              : 
     334    284367291 :   gcc_assert (dfi);
     335              : 
     336    284367291 :   if (dfi->pstate == 0)
     337              :     return NULL;
     338              : 
     339              :   /* If available, use the command line dump filename. */
     340       128187 :   if (dfi->pfilename)
     341            4 :     return xstrdup (dfi->pfilename);
     342              : 
     343       128183 :   if (dfi->num < 0)
     344            0 :     dump_id[0] = '\0';
     345              :   else
     346              :     {
     347              :       /* (null), LANG, TREE, RTL, IPA.  */
     348       128183 :       char suffix = " ltri"[dfi->dkind];
     349              : 
     350       128183 :       if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
     351            0 :         dump_id[0] = '\0';
     352              :     }
     353              : 
     354       128183 :   if (part != -1)
     355              :     {
     356            0 :        char part_id[8];
     357            0 :        snprintf (part_id, sizeof (part_id), ".%i", part);
     358            0 :        return concat (dump_base_name, dump_id, part_id, dfi->suffix, NULL);
     359              :     }
     360              :   else
     361       128183 :     return concat (dump_base_name, dump_id, dfi->suffix, NULL);
     362              : }
     363              : 
     364              : /* Open a dump file called FILENAME.  Some filenames are special and
     365              :    refer to the standard streams.  TRUNC indicates whether this is the
     366              :    first open (so the file should be truncated, rather than appended).
     367              :    An error message is emitted in the event of failure.  */
     368              : 
     369              : static FILE *
     370        88142 : dump_open (const char *filename, bool trunc)
     371              : {
     372        88142 :   if (strcmp ("stderr", filename) == 0)
     373        15555 :     return stderr;
     374              : 
     375        72587 :   if (strcmp ("stdout", filename) == 0
     376        72587 :       || strcmp ("-", filename) == 0)
     377            0 :     return stdout;
     378              : 
     379       119150 :   FILE *stream = fopen (filename, trunc ? "w" : "a");
     380              : 
     381        72587 :   if (!stream)
     382            0 :     error ("could not open dump file %qs: %m", filename);
     383              :   return stream;
     384              : }
     385              : 
     386              : /* For a given DFI, open an alternate dump filename (which could also
     387              :    be a standard stream such as stdout/stderr). If the alternate dump
     388              :    file cannot be opened, return NULL.  */
     389              : 
     390              : static FILE *
     391        71465 : dump_open_alternate_stream (struct dump_file_info *dfi)
     392              : {
     393        71465 :   if (!dfi->alt_filename)
     394              :     return NULL;
     395              : 
     396        15553 :   if (dfi->alt_stream)
     397              :     return dfi->alt_stream;
     398              : 
     399        15553 :   FILE *stream = dump_open (dfi->alt_filename, dfi->alt_state < 0);
     400              : 
     401        15553 :   if (stream)
     402        15553 :     dfi->alt_state = 1;
     403              : 
     404              :   return stream;
     405              : }
     406              : 
     407              : /* Construct a dump_user_location_t from STMT (using its location and
     408              :    hotness).  */
     409              : 
     410     42564791 : dump_user_location_t::dump_user_location_t (const gimple *stmt)
     411     42564791 : : m_count (), m_loc (UNKNOWN_LOCATION)
     412              : {
     413     42564791 :   if (stmt)
     414              :     {
     415     42564753 :       if (stmt->bb)
     416     42558192 :         m_count = stmt->bb->count;
     417     42564753 :       m_loc = gimple_location (stmt);
     418              :     }
     419     42564791 : }
     420              : 
     421              : /* Construct a dump_user_location_t from an RTL instruction (using its
     422              :    location and hotness).  */
     423              : 
     424       579933 : dump_user_location_t::dump_user_location_t (const rtx_insn *insn)
     425       579933 : : m_count (), m_loc (UNKNOWN_LOCATION)
     426              : {
     427       579933 :   if (insn)
     428              :     {
     429       579929 :       basic_block bb = BLOCK_FOR_INSN (insn);
     430       579929 :       if (bb)
     431       579929 :         m_count = bb->count;
     432       579929 :       m_loc = INSN_LOCATION (insn);
     433              :     }
     434       579933 : }
     435              : 
     436              : /* Construct from a function declaration.  This one requires spelling out
     437              :    to avoid accidentally constructing from other kinds of tree.  */
     438              : 
     439              : dump_user_location_t
     440      1048510 : dump_user_location_t::from_function_decl (tree fndecl)
     441              : {
     442      1048510 :   gcc_assert (fndecl);
     443              : 
     444              :   // FIXME: profile count for function?
     445      1048510 :   return dump_user_location_t (profile_count (),
     446      1048510 :                                DECL_SOURCE_LOCATION (fndecl));
     447              : }
     448              : 
     449              : /* Extract the MSG_* component from DUMP_KIND and return a string for use
     450              :    as a prefix to dump messages.
     451              :    These match the strings in optinfo_verbosity_options and thus the
     452              :    "OPTIONS" within "-fopt-info-OPTIONS".  */
     453              : 
     454              : static const char *
     455      6697354 : kind_as_string (dump_flags_t dump_kind)
     456              : {
     457      6697354 :   switch (dump_kind & MSG_ALL_KINDS)
     458              :     {
     459            0 :     default:
     460            0 :       gcc_unreachable ();
     461              :     case MSG_OPTIMIZED_LOCATIONS:
     462              :       return "optimized";
     463       160905 :     case MSG_MISSED_OPTIMIZATION:
     464       160905 :       return "missed";
     465      6520908 :     case MSG_NOTE:
     466      6520908 :       return "note";
     467              :     }
     468              : }
     469              : 
     470              : /* Print source location on DFILE if enabled.  */
     471              : 
     472              : static void
     473      6694890 : dump_loc (dump_flags_t dump_kind, FILE *dfile, location_t loc)
     474              : {
     475      6694890 :   if (dump_kind)
     476              :     {
     477      6694890 :       if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
     478      6643584 :         fprintf (dfile, "%s:%d:%d: ", LOCATION_FILE (loc),
     479     13287168 :                  LOCATION_LINE (loc), LOCATION_COLUMN (loc));
     480        51306 :       else if (current_function_decl)
     481        51293 :         fprintf (dfile, "%s:%d:%d: ",
     482        51293 :                  DECL_SOURCE_FILE (current_function_decl),
     483        51293 :                  DECL_SOURCE_LINE (current_function_decl),
     484       102586 :                  DECL_SOURCE_COLUMN (current_function_decl));
     485      6694890 :       fprintf (dfile, "%s: ", kind_as_string (dump_kind));
     486              :       /* Indentation based on scope depth.  */
     487      6694890 :       fprintf (dfile, "%*s", get_dump_scope_depth (), "");
     488              :     }
     489      6694890 : }
     490              : 
     491              : /* Print source location to PP if enabled.  */
     492              : 
     493              : static void
     494         2464 : dump_loc (dump_flags_t dump_kind, pretty_printer *pp, location_t loc)
     495              : {
     496              :   /* Disable warnings about missing quoting in GCC diagnostics for
     497              :      the pp_printf calls.  Their format strings aren't used to format
     498              :      diagnostics so don't need to follow GCC diagnostic conventions.  */
     499              : #if __GNUC__ >= 10
     500         2464 : #  pragma GCC diagnostic push
     501         2464 : #  pragma GCC diagnostic ignored "-Wformat-diag"
     502              : #endif
     503              : 
     504         2464 :   if (dump_kind)
     505              :     {
     506         2464 :       if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
     507         2464 :         pp_printf (pp, "%s:%d:%d: ", LOCATION_FILE (loc),
     508         4928 :                    LOCATION_LINE (loc), LOCATION_COLUMN (loc));
     509            0 :       else if (current_function_decl)
     510            0 :         pp_printf (pp, "%s:%d:%d: ",
     511            0 :                    DECL_SOURCE_FILE (current_function_decl),
     512            0 :                    DECL_SOURCE_LINE (current_function_decl),
     513            0 :                    DECL_SOURCE_COLUMN (current_function_decl));
     514         2464 :       pp_printf (pp, "%s: ", kind_as_string (dump_kind));
     515              :       /* Indentation based on scope depth.  */
     516         5068 :       for (unsigned i = 0; i < get_dump_scope_depth (); i++)
     517         2604 :         pp_character (pp, ' ');
     518              :     }
     519              : 
     520              : #if __GNUC__ >= 10
     521         2464 : #  pragma GCC diagnostic pop
     522              : #endif
     523         2464 : }
     524              : 
     525              : /* Implementation of dump_context member functions.  */
     526              : 
     527              : /* dump_context's dtor.  */
     528              : 
     529       287013 : dump_context::~dump_context ()
     530              : {
     531       287013 :   delete m_pending;
     532       287013 : }
     533              : 
     534              : void
     535         3706 : dump_context::set_json_writer (optrecord_json_writer *writer)
     536              : {
     537         3706 :   delete m_json_writer;
     538         3706 :   m_json_writer = writer;
     539         3706 : }
     540              : 
     541              : /* Perform cleanup activity for -fsave-optimization-record.
     542              :    Currently, the file is written out here in one go, before cleaning
     543              :    up.  */
     544              : 
     545              : void
     546       268250 : dump_context::finish_any_json_writer ()
     547              : {
     548       268250 :   if (!m_json_writer)
     549              :     return;
     550              : 
     551           41 :   m_json_writer->write ();
     552           41 :   delete m_json_writer;
     553           41 :   m_json_writer = NULL;
     554              : }
     555              : 
     556              : /* Update the "dumps_are_enabled" global; to be called whenever dump_file
     557              :    or alt_dump_file change, or when changing dump_context in selftests.  */
     558              : 
     559              : void
     560    586105032 : dump_context::refresh_dumps_are_enabled ()
     561              : {
     562    586048624 :   dumps_are_enabled = (dump_file || alt_dump_file || optinfo_enabled_p ()
     563   1172050340 :                        || m_test_pp);
     564    586105032 : }
     565              : 
     566              : /* Determine if a message of kind DUMP_KIND and at the current scope depth
     567              :    should be printed.
     568              : 
     569              :    Only show messages that match FILTER both on their kind *and*
     570              :    their priority.  */
     571              : 
     572              : bool
     573     23518227 : dump_context::apply_dump_filter_p (dump_flags_t dump_kind,
     574              :                                    dump_flags_t filter) const
     575              : {
     576              :   /* Few messages, if any, have an explicit MSG_PRIORITY.
     577              :      If DUMP_KIND does, we'll use it.
     578              :      Otherwise, generate an implicit priority value for the message based
     579              :      on the current scope depth.
     580              :      Messages at the top-level scope are MSG_PRIORITY_USER_FACING,
     581              :      whereas those in nested scopes are MSG_PRIORITY_INTERNALS.  */
     582     23518227 :   if (!(dump_kind & MSG_ALL_PRIORITIES))
     583              :     {
     584       468197 :       dump_flags_t implicit_priority
     585     23475871 :         =  (m_scope_depth > 0
     586     23475871 :             ? MSG_PRIORITY_INTERNALS
     587              :             : MSG_PRIORITY_USER_FACING);
     588     23475871 :       dump_kind |= implicit_priority;
     589              :     }
     590              : 
     591     23518227 :   return (dump_kind & (filter & MSG_ALL_KINDS)
     592     23518227 :           && dump_kind & (filter & MSG_ALL_PRIORITIES));
     593              : }
     594              : 
     595              : /* Print LOC to the appropriate dump destinations, given DUMP_KIND.
     596              :    If optinfos are enabled, begin a new optinfo.  */
     597              : 
     598              : void
     599      6365917 : dump_context::dump_loc (const dump_metadata_t &metadata,
     600              :                         const dump_user_location_t &loc)
     601              : {
     602      6365917 :   end_any_optinfo ();
     603              : 
     604      6365917 :   dump_loc_immediate (metadata.get_dump_flags (), loc);
     605              : 
     606      6365917 :   if (optinfo_enabled_p ())
     607        39017 :     begin_next_optinfo (metadata, loc);
     608      6365917 : }
     609              : 
     610              : /* As dump_loc above, but without starting a new optinfo. */
     611              : 
     612              : void
     613      6371849 : dump_context::dump_loc_immediate (dump_flags_t dump_kind,
     614              :                                   const dump_user_location_t &loc)
     615              : {
     616      6371849 :   location_t srcloc = loc.get_location_t ();
     617              : 
     618      6371849 :   if (dump_file && apply_dump_filter_p (dump_kind, pflags))
     619      6268930 :     ::dump_loc (dump_kind, dump_file, srcloc);
     620              : 
     621      6371849 :   if (alt_dump_file && apply_dump_filter_p (dump_kind, alt_flags))
     622        22460 :     ::dump_loc (dump_kind, alt_dump_file, srcloc);
     623              : 
     624              :   /* Support for temp_dump_context in selftests.  */
     625      6371849 :   if (m_test_pp && apply_dump_filter_p (dump_kind, m_test_pp_flags))
     626         1960 :     ::dump_loc (dump_kind, m_test_pp, srcloc);
     627      6371849 : }
     628              : 
     629              : /* Make an item for the given dump call, equivalent to print_gimple_stmt.  */
     630              : 
     631              : static std::unique_ptr<optinfo_item>
     632      2468820 : make_item_for_dump_gimple_stmt (gimple *stmt, int spc, dump_flags_t dump_flags)
     633              : {
     634      2468820 :   pretty_printer pp;
     635      2468820 :   pp_needs_newline (&pp) = true;
     636      2468820 :   pp_gimple_stmt_1 (&pp, stmt, spc, dump_flags);
     637      2468820 :   pp_newline (&pp);
     638              : 
     639      2468820 :   auto item
     640      4937640 :     = std::make_unique<optinfo_item> (optinfo_item::kind::gimple,
     641      2468820 :                                       gimple_location (stmt),
     642      2468820 :                                       xstrdup (pp_formatted_text (&pp)));
     643      4937640 :   return item;
     644      2468820 : }
     645              : 
     646              : /* Dump gimple statement GS with SPC indentation spaces and
     647              :    EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled.  */
     648              : 
     649              : void
     650          224 : dump_context::dump_gimple_stmt (const dump_metadata_t &metadata,
     651              :                                 dump_flags_t extra_dump_flags,
     652              :                                 gimple *gs, int spc)
     653              : {
     654          224 :   auto item
     655          224 :     = make_item_for_dump_gimple_stmt (gs, spc, dump_flags | extra_dump_flags);
     656          224 :   emit_item (*item.get (), metadata.get_dump_flags ());
     657              : 
     658          224 :   if (optinfo_enabled_p ())
     659              :     {
     660          112 :       optinfo &info = ensure_pending_optinfo (metadata);
     661          112 :       info.add_item (std::move (item));
     662              :     }
     663          224 : }
     664              : 
     665              : /* Similar to dump_gimple_stmt, except additionally print source location.  */
     666              : 
     667              : void
     668          112 : dump_context::dump_gimple_stmt_loc (const dump_metadata_t &metadata,
     669              :                                     const dump_user_location_t &loc,
     670              :                                     dump_flags_t extra_dump_flags,
     671              :                                     gimple *gs, int spc)
     672              : {
     673          112 :   dump_loc (metadata, loc);
     674          112 :   dump_gimple_stmt (metadata, extra_dump_flags, gs, spc);
     675          112 : }
     676              : 
     677              : /* Make an item for the given dump call, equivalent to print_gimple_expr.  */
     678              : 
     679              : static std::unique_ptr<optinfo_item>
     680       687520 : make_item_for_dump_gimple_expr (gimple *stmt, int spc, dump_flags_t dump_flags)
     681              : {
     682       687520 :   dump_flags |= TDF_RHS_ONLY;
     683       687520 :   pretty_printer pp;
     684       687520 :   pp_needs_newline (&pp) = true;
     685       687520 :   pp_gimple_stmt_1 (&pp, stmt, spc, dump_flags);
     686              : 
     687       687520 :   auto item
     688      1375040 :     = std::make_unique<optinfo_item> (optinfo_item::kind::gimple,
     689       687520 :                                       gimple_location (stmt),
     690       687520 :                                       xstrdup (pp_formatted_text (&pp)));
     691      1375040 :   return item;
     692       687520 : }
     693              : 
     694              : /* Dump gimple statement GS with SPC indentation spaces and
     695              :    EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled.
     696              :    Do not terminate with a newline or semicolon.  */
     697              : 
     698              : void
     699       687184 : dump_context::dump_gimple_expr (const dump_metadata_t &metadata,
     700              :                                 dump_flags_t extra_dump_flags,
     701              :                                 gimple *gs, int spc)
     702              : {
     703       687184 :   std::unique_ptr<optinfo_item> item
     704       687184 :     = make_item_for_dump_gimple_expr (gs, spc, dump_flags | extra_dump_flags);
     705       687184 :   emit_item (*item.get (), metadata.get_dump_flags ());
     706              : 
     707       687184 :   if (optinfo_enabled_p ())
     708              :     {
     709         6522 :       optinfo &info = ensure_pending_optinfo (metadata);
     710         6522 :       info.add_item (std::move (item));
     711              :     }
     712       687184 : }
     713              : 
     714              : /* Similar to dump_gimple_expr, except additionally print source location.  */
     715              : 
     716              : void
     717          112 : dump_context::dump_gimple_expr_loc (const dump_metadata_t &metadata,
     718              :                                     const dump_user_location_t &loc,
     719              :                                     dump_flags_t extra_dump_flags,
     720              :                                     gimple *gs,
     721              :                                     int spc)
     722              : {
     723          112 :   dump_loc (metadata, loc);
     724          112 :   dump_gimple_expr (metadata, extra_dump_flags, gs, spc);
     725          112 : }
     726              : 
     727              : /* Make an item for the given dump call, equivalent to print_generic_expr.  */
     728              : 
     729              : static std::unique_ptr<optinfo_item>
     730      1475121 : make_item_for_dump_generic_expr (tree node, dump_flags_t dump_flags)
     731              : {
     732      1475121 :   pretty_printer pp;
     733      1475121 :   pp_needs_newline (&pp) = true;
     734      1475121 :   pp_translate_identifiers (&pp) = false;
     735      1475121 :   dump_generic_node (&pp, node, 0, dump_flags, false);
     736              : 
     737      1475121 :   location_t loc = UNKNOWN_LOCATION;
     738      1475121 :   if (EXPR_HAS_LOCATION (node))
     739       147266 :     loc = EXPR_LOCATION (node);
     740              : 
     741      1475121 :   auto item
     742      2950242 :     = std::make_unique<optinfo_item> (optinfo_item::kind::tree, loc,
     743      1475121 :                                       xstrdup (pp_formatted_text (&pp)));
     744      2950242 :   return item;
     745      1475121 : }
     746              : 
     747              : /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
     748              :    DUMP_KIND is enabled.  */
     749              : 
     750              : void
     751       217439 : dump_context::dump_generic_expr (const dump_metadata_t &metadata,
     752              :                                  dump_flags_t extra_dump_flags,
     753              :                                  tree t)
     754              : {
     755       217439 :   std::unique_ptr<optinfo_item> item
     756       217439 :     = make_item_for_dump_generic_expr (t, dump_flags | extra_dump_flags);
     757       217439 :   emit_item (*item.get (), metadata.get_dump_flags ());
     758              : 
     759       217439 :   if (optinfo_enabled_p ())
     760              :     {
     761         4113 :       optinfo &info = ensure_pending_optinfo (metadata);
     762         4113 :       info.add_item (std::move (item));
     763              :     }
     764       217439 : }
     765              : 
     766              : 
     767              : /* Similar to dump_generic_expr, except additionally print the source
     768              :    location.  */
     769              : 
     770              : void
     771       151400 : dump_context::dump_generic_expr_loc (const dump_metadata_t &metadata,
     772              :                                      const dump_user_location_t &loc,
     773              :                                      dump_flags_t extra_dump_flags,
     774              :                                      tree t)
     775              : {
     776       151400 :   dump_loc (metadata, loc);
     777       151400 :   dump_generic_expr (metadata, extra_dump_flags, t);
     778       151400 : }
     779              : 
     780              : /* Make an item for the given dump call.  */
     781              : 
     782              : static std::unique_ptr<optinfo_item>
     783         7955 : make_item_for_dump_symtab_node (symtab_node *node)
     784              : {
     785         7955 :   location_t loc = DECL_SOURCE_LOCATION (node->decl);
     786         7955 :   auto item
     787        15910 :     = std::make_unique<optinfo_item> (optinfo_item::kind::symtab_node, loc,
     788         7955 :                                       xstrdup (node->dump_name ()));
     789         7955 :   return item;
     790              : }
     791              : 
     792              : struct wrapped_optinfo_item : public pp_token_custom_data::value
     793              : {
     794      3734455 :   wrapped_optinfo_item (std::unique_ptr<optinfo_item> item)
     795      3734455 :   : m_optinfo_item (std::move (item))
     796              :   {
     797      3734455 :     gcc_assert (m_optinfo_item.get ());
     798      3734455 :   }
     799              : 
     800            0 :   void dump (FILE *out) const final override
     801              :   {
     802            0 :     fprintf (out, "OPTINFO(\"%s\")", m_optinfo_item->get_text ());
     803            0 :   }
     804              : 
     805      3734455 :   bool as_standard_tokens (pp_token_list &) final override
     806              :   {
     807              :     /* Keep as a custom token.  */
     808      3734455 :     return false;
     809              :   }
     810              : 
     811              :   std::unique_ptr<optinfo_item> m_optinfo_item;
     812              : };
     813              : 
     814              : /* dump_pretty_printer's ctor.  */
     815              : 
     816     11046345 : dump_pretty_printer::dump_pretty_printer (dump_context *context,
     817     11046345 :                                           dump_flags_t dump_kind)
     818              : : pretty_printer (),
     819     11046345 :   m_context (context),
     820     11046345 :   m_dump_kind (dump_kind),
     821     11046345 :   m_token_printer (*this)
     822              : {
     823     11046345 :   pp_format_decoder (this) = format_decoder_cb;
     824     11046345 :   set_token_printer (&m_token_printer);
     825     11046345 : }
     826              : 
     827              : /* Emit ITEM and take ownership of it.  If DEST is non-NULL, add ITEM
     828              :    to DEST; otherwise delete ITEM.  */
     829              : 
     830              : void
     831     15067161 : dump_pretty_printer::emit_item (std::unique_ptr<optinfo_item> item,
     832              :                                 optinfo *dest)
     833              : {
     834     15067161 :   m_context->emit_item (*item.get (), m_dump_kind);
     835     15067161 :   if (dest)
     836       132341 :     dest->add_item (std::move (item));
     837     15067161 : }
     838              : 
     839              : /* Append a custom pp_token for ITEM (generated in phase 2 of formatting)
     840              :    into FORMATTTED_TOK_LIST, so that it can be emitted in phase 2.  */
     841              : 
     842              : void
     843      3734455 : dump_pretty_printer::stash_item (pp_token_list &formatted_tok_list,
     844              :                                  std::unique_ptr<optinfo_item> item)
     845              : {
     846      3734455 :   gcc_assert (item.get ());
     847              : 
     848      3734455 :   auto custom_data
     849      3734455 :     = std::make_unique<wrapped_optinfo_item> (std::move (item));
     850      3734455 :   formatted_tok_list.push_back<pp_token_custom_data> (std::move (custom_data));
     851      3734455 : }
     852              : 
     853              : /* pp_format_decoder callback for dump_pretty_printer, and thus for
     854              :    dump_printf and dump_printf_loc.
     855              : 
     856              :    A wrapper around decode_format, for type-safety.  */
     857              : 
     858              : bool
     859      3734455 : dump_pretty_printer::format_decoder_cb (pretty_printer *pp, text_info *text,
     860              :                                         const char *spec, int /*precision*/,
     861              :                                         bool /*wide*/, bool /*set_locus*/,
     862              :                                         bool /*verbose*/, bool */*quoted*/,
     863              :                                         pp_token_list &formatted_tok_list)
     864              : {
     865      3734455 :   dump_pretty_printer *opp = static_cast <dump_pretty_printer *> (pp);
     866      3734455 :   return opp->decode_format (text, spec, formatted_tok_list);
     867              : }
     868              : 
     869              : /* Format decoder for dump_pretty_printer, and thus for dump_printf and
     870              :    dump_printf_loc.
     871              : 
     872              :    Supported format codes (in addition to the standard pretty_printer ones)
     873              :    are:
     874              : 
     875              :    %C: cgraph_node *:
     876              :        Equivalent to: dump_symtab_node (MSG_*, node)
     877              :    %E: gimple *:
     878              :        Equivalent to: dump_gimple_expr (MSG_*, TDF_SLIM, stmt, 0)
     879              :    %G: gimple *:
     880              :        Equivalent to: dump_gimple_stmt (MSG_*, TDF_SLIM, stmt, 0)
     881              :    %T: tree:
     882              :        Equivalent to: dump_generic_expr (MSG_*, arg, TDF_SLIM).
     883              : 
     884              :    TODO: add a format code that can handle (symtab_node*) *and* both
     885              :    subclasses (presumably means teaching -Wformat about non-virtual
     886              :    subclasses).
     887              : 
     888              :    These format codes build optinfo_item instances, thus capturing metadata
     889              :    about the arguments being dumped, as well as the textual output.  */
     890              : 
     891              : bool
     892      3734455 : dump_pretty_printer::decode_format (text_info *text, const char *spec,
     893              :                                     pp_token_list &formatted_tok_list)
     894              : {
     895              :   /* Various format codes that imply making an optinfo_item and stashed it
     896              :      for later use (to capture metadata, rather than plain text).  */
     897      3734455 :   switch (*spec)
     898              :     {
     899         7841 :     case 'C':
     900         7841 :       {
     901         7841 :         cgraph_node *node = va_arg (*text->m_args_ptr, cgraph_node *);
     902              : 
     903              :         /* Make an item for the node, and stash it.  */
     904         7841 :         auto item = make_item_for_dump_symtab_node (node);
     905         7841 :         stash_item (formatted_tok_list, std::move (item));
     906         7841 :         return true;
     907         7841 :       }
     908              : 
     909          336 :     case 'E':
     910          336 :       {
     911          336 :         gimple *stmt = va_arg (*text->m_args_ptr, gimple *);
     912              : 
     913              :         /* Make an item for the stmt, and stash it.  */
     914          336 :         auto item = make_item_for_dump_gimple_expr (stmt, 0, TDF_SLIM);
     915          336 :         stash_item (formatted_tok_list, std::move (item));
     916          336 :         return true;
     917          336 :       }
     918              : 
     919      2468596 :     case 'G':
     920      2468596 :       {
     921      2468596 :         gimple *stmt = va_arg (*text->m_args_ptr, gimple *);
     922              : 
     923              :         /* Make an item for the stmt, and stash it.  */
     924      2468596 :         auto item = make_item_for_dump_gimple_stmt (stmt, 0, TDF_SLIM);
     925      2468596 :         stash_item (formatted_tok_list, std::move (item));
     926      2468596 :         return true;
     927      2468596 :       }
     928              : 
     929      1257682 :     case 'T':
     930      1257682 :       {
     931      1257682 :         tree t = va_arg (*text->m_args_ptr, tree);
     932              : 
     933              :         /* Make an item for the tree, and stash it.  */
     934      1257682 :         auto item = make_item_for_dump_generic_expr (t, TDF_SLIM);
     935      1257682 :         stash_item (formatted_tok_list, std::move (item));
     936      1257682 :         return true;
     937      1257682 :       }
     938              : 
     939              :     default:
     940              :       return false;
     941              :     }
     942              : }
     943              : 
     944              : void
     945     11046345 : dump_pretty_printer::custom_token_printer::
     946              : print_tokens (pretty_printer *pp,
     947              :               const pp_token_list &tokens)
     948              : {
     949              :   /* Accumulate text whilst emitting items.  */
     950     26214234 :   for (auto iter = tokens.m_first; iter; iter = iter->m_next)
     951     15167889 :     switch (iter->m_kind)
     952              :       {
     953            0 :       default:
     954            0 :         gcc_unreachable ();
     955              : 
     956     11362904 :       case pp_token::kind::text:
     957     11362904 :         {
     958     11362904 :           pp_token_text *sub = as_a <pp_token_text *> (iter);
     959     11362904 :           gcc_assert (sub->m_value.get ());
     960     11362904 :           pp_string (pp, sub->m_value.get ());
     961              :         }
     962     11362904 :         break;
     963              : 
     964              :       case pp_token::kind::begin_color:
     965              :       case pp_token::kind::end_color:
     966              :         /* No-op for dumpfiles.  */
     967              :         break;
     968              : 
     969        26337 :       case pp_token::kind::begin_quote:
     970        26337 :         pp_begin_quote (pp, pp_show_color (pp));
     971        26337 :         break;
     972        44193 :       case pp_token::kind::end_quote:
     973        44193 :         pp_end_quote (pp, pp_show_color (pp));
     974        44193 :         break;
     975              : 
     976              :       case pp_token::kind::begin_url:
     977              :       case pp_token::kind::end_url:
     978              :         /* No-op for dumpfiles.  */
     979              :         break;
     980              : 
     981      3734455 :       case pp_token::kind::custom_data:
     982      3734455 :         {
     983      3734455 :           emit_any_pending_textual_chunks ();
     984      3734455 :           pp_token_custom_data *sub = as_a <pp_token_custom_data *> (iter);
     985      3734455 :           gcc_assert (sub->m_value.get ());
     986      3734455 :           wrapped_optinfo_item *custom_data
     987      3734455 :             = static_cast<wrapped_optinfo_item *> (sub->m_value.get ());
     988      3734455 :           m_dump_pp.emit_item (std::move (custom_data->m_optinfo_item),
     989              :                                m_optinfo);
     990              :         }
     991      3734455 :         break;
     992              :       }
     993              : 
     994     11046345 :   emit_any_pending_textual_chunks ();
     995     11046345 : }
     996              : 
     997              : /* Subroutine of dump_pretty_printer::custom_token_printer::print_tokens
     998              :    for consolidating multiple adjacent pure-text chunks into single
     999              :    optinfo_items (in phase 3).  */
    1000              : 
    1001              : void
    1002     14780800 : dump_pretty_printer::custom_token_printer::
    1003              : emit_any_pending_textual_chunks ()
    1004              : {
    1005     14780800 :   dump_pretty_printer *pp = &m_dump_pp;
    1006     14780800 :   output_buffer *const buffer = pp_buffer (pp);
    1007     14780800 :   gcc_assert (buffer->m_obstack == &buffer->m_formatted_obstack);
    1008              : 
    1009              :   /* Don't emit an item if the pending text is empty.  */
    1010     14780800 :   if (output_buffer_last_position_in_text (buffer) == nullptr)
    1011      3448094 :     return;
    1012              : 
    1013     11332706 :   char *formatted_text = xstrdup (pp_formatted_text (pp));
    1014     11332706 :   auto item
    1015     22665412 :     = std::make_unique<optinfo_item> (optinfo_item::kind::text,
    1016     22665412 :                                       UNKNOWN_LOCATION,
    1017     11332706 :                                       formatted_text);
    1018     11332706 :   pp->emit_item (std::move (item), m_optinfo);
    1019              : 
    1020              :   /* Clear the pending text by unwinding formatted_text back to the start
    1021              :      of the buffer (without deallocating).  */
    1022     11332706 :   obstack_free (&buffer->m_formatted_obstack,
    1023              :                 buffer->m_formatted_obstack.object_base);
    1024     11332706 : }
    1025              : 
    1026              : /* Output a formatted message using FORMAT on appropriate dump streams.  */
    1027              : 
    1028              : void
    1029     11019648 : dump_context::dump_printf_va (const dump_metadata_t &metadata,
    1030              :                               const char *format,
    1031              :                               va_list *ap)
    1032              : {
    1033     11019648 :   dump_pretty_printer pp (this, metadata.get_dump_flags ());
    1034              : 
    1035     11019648 :   text_info text (format, ap, errno);
    1036              : 
    1037              :   /* Phases 1 and 2, using pp_format.  */
    1038     11019648 :   pp_format (&pp, &text);
    1039              : 
    1040              :   /* Phase 3: update the custom token_printer with any active optinfo.  */
    1041     11019648 :   if (optinfo_enabled_p ())
    1042              :     {
    1043        68560 :       optinfo &info = ensure_pending_optinfo (metadata);
    1044        68560 :       pp.set_optinfo (&info);
    1045              :     }
    1046              :   else
    1047     10951088 :     pp.set_optinfo (nullptr);
    1048              : 
    1049     11019648 :   pp_output_formatted_text (&pp, nullptr);
    1050     11019648 : }
    1051              : 
    1052              : /* Similar to dump_printf, except source location is also printed, and
    1053              :    dump location captured.  */
    1054              : 
    1055              : void
    1056      6187596 : dump_context::dump_printf_loc_va (const dump_metadata_t &metadata,
    1057              :                                   const dump_user_location_t &loc,
    1058              :                                   const char *format, va_list *ap)
    1059              : {
    1060      6187596 :   dump_loc (metadata, loc);
    1061      6187596 :   dump_printf_va (metadata, format, ap);
    1062      6187596 : }
    1063              : 
    1064              : /* Make an item for the given dump call, equivalent to print_dec.  */
    1065              : 
    1066              : template<unsigned int N, typename C>
    1067              : static std::unique_ptr<optinfo_item>
    1068       281724 : make_item_for_dump_dec (const poly_int<N, C> &value)
    1069              : {
    1070              :   STATIC_ASSERT (poly_coeff_traits<C>::signedness >= 0);
    1071       281724 :   signop sgn = poly_coeff_traits<C>::signedness ? SIGNED : UNSIGNED;
    1072              : 
    1073       281724 :   pretty_printer pp;
    1074              : 
    1075              :   if (value.is_constant ())
    1076       281724 :     pp_wide_int (&pp, value.coeffs[0], sgn);
    1077              :   else
    1078              :     {
    1079              :       pp_character (&pp, '[');
    1080              :       for (unsigned int i = 0; i < N; ++i)
    1081              :         {
    1082              :           pp_wide_int (&pp, value.coeffs[i], sgn);
    1083              :           pp_character (&pp, i == N - 1 ? ']' : ',');
    1084              :         }
    1085              :     }
    1086              : 
    1087       281724 :   auto item
    1088       563448 :     = std::make_unique<optinfo_item> (optinfo_item::kind::text,
    1089       563448 :                                       UNKNOWN_LOCATION,
    1090       281724 :                                       xstrdup (pp_formatted_text (&pp)));
    1091       281724 :   return item;
    1092       281724 : }
    1093              : 
    1094              : /* Output VALUE in decimal to appropriate dump streams.  */
    1095              : 
    1096              : template<unsigned int N, typename C>
    1097              : void
    1098       281724 : dump_context::dump_dec (const dump_metadata_t &metadata,
    1099              :                         const poly_int<N, C> &value)
    1100              : {
    1101       281724 :   auto item = make_item_for_dump_dec (value);
    1102       281724 :   emit_item (*item.get (), metadata.get_dump_flags ());
    1103              : 
    1104       281724 :   if (optinfo_enabled_p ())
    1105              :     {
    1106         1091 :       optinfo &info = ensure_pending_optinfo (metadata);
    1107         1091 :       info.add_item (std::move (item));
    1108              :     }
    1109       281724 : }
    1110              : 
    1111              : /* Output the name of NODE on appropriate dump streams.  */
    1112              : 
    1113              : void
    1114          114 : dump_context::dump_symtab_node (const dump_metadata_t &metadata,
    1115              :                                 symtab_node *node)
    1116              : {
    1117          114 :   auto item = make_item_for_dump_symtab_node (node);
    1118          114 :   emit_item (*item.get (), metadata.get_dump_flags ());
    1119              : 
    1120          114 :   if (optinfo_enabled_p ())
    1121              :     {
    1122           56 :       optinfo &info = ensure_pending_optinfo (metadata);
    1123           56 :       info.add_item (std::move (item));
    1124              :     }
    1125          114 : }
    1126              : 
    1127              : /* Get the current dump scope-nesting depth.
    1128              :    For use by -fopt-info (for showing nesting via indentation).  */
    1129              : 
    1130              : unsigned int
    1131      6699958 : dump_context::get_scope_depth () const
    1132              : {
    1133      6699958 :   return m_scope_depth;
    1134              : }
    1135              : 
    1136              : /* Push a nested dump scope.
    1137              :    Increment the scope depth.
    1138              :    Print "=== NAME ===\n" to the dumpfile, if any, and to the -fopt-info
    1139              :    destination, if any.
    1140              :    Emit a "scope" optinfo if optinfos are enabled.  */
    1141              : 
    1142              : void
    1143       410647 : dump_context::begin_scope (const char *name,
    1144              :                            const dump_user_location_t &user_location,
    1145              :                            const dump_impl_location_t &impl_location)
    1146              : {
    1147       410647 :   m_scope_depth++;
    1148              : 
    1149       410647 :   location_t src_loc = user_location.get_location_t ();
    1150              : 
    1151       410647 :   if (dump_file && apply_dump_filter_p (MSG_NOTE, pflags))
    1152       403497 :     ::dump_loc (MSG_NOTE, dump_file, src_loc);
    1153              : 
    1154       410647 :   if (alt_dump_file && apply_dump_filter_p (MSG_NOTE, alt_flags))
    1155            3 :     ::dump_loc (MSG_NOTE, alt_dump_file, src_loc);
    1156              : 
    1157              :   /* Support for temp_dump_context in selftests.  */
    1158       410647 :   if (m_test_pp && apply_dump_filter_p (MSG_NOTE, m_test_pp_flags))
    1159          504 :     ::dump_loc (MSG_NOTE, m_test_pp, src_loc);
    1160              : 
    1161              :   /* Format multiple consecutive punctuation characters via %s to
    1162              :      avoid -Wformat-diag in the pp_printf call below whose output
    1163              :      isn't used for diagnostic output.  */
    1164       410647 :   pretty_printer pp;
    1165       410647 :   pp_printf (&pp, "%s %s %s", "===", name, "===");
    1166       410647 :   pp_newline (&pp);
    1167       410647 :   auto item
    1168       821294 :     = std::make_unique<optinfo_item> (optinfo_item::kind::text,
    1169       821294 :                                       UNKNOWN_LOCATION,
    1170       410647 :                                       xstrdup (pp_formatted_text (&pp)));
    1171       410647 :   emit_item (*item.get (), MSG_NOTE);
    1172              : 
    1173       410647 :   if (optinfo_enabled_p ())
    1174              :     {
    1175         3916 :       optinfo &info
    1176         3916 :         = begin_next_optinfo (dump_metadata_t (MSG_NOTE, impl_location),
    1177              :                               user_location);
    1178         3916 :       info.m_kind = optinfo::kind::scope;
    1179         3916 :       info.add_item (std::move (item));
    1180         3916 :       end_any_optinfo ();
    1181              :     }
    1182       410647 : }
    1183              : 
    1184              : /* Pop a nested dump scope.  */
    1185              : 
    1186              : void
    1187       410647 : dump_context::end_scope ()
    1188              : {
    1189       410647 :   end_any_optinfo ();
    1190       410647 :   m_scope_depth--;
    1191              : 
    1192       410647 :   if (m_json_writer)
    1193         3916 :     m_json_writer->pop_scope ();
    1194       410647 : }
    1195              : 
    1196              : /* Should optinfo instances be created?
    1197              :    All creation of optinfos should be guarded by this predicate.
    1198              :    Return true if any optinfo destinations are active.  */
    1199              : 
    1200              : bool
    1201    605000592 : dump_context::optinfo_enabled_p () const
    1202              : {
    1203    605000592 :   return (optimization_records_enabled_p ());
    1204              : }
    1205              : 
    1206              : /* Return the optinfo currently being accumulated, creating one if
    1207              :    necessary.  */
    1208              : 
    1209              : optinfo &
    1210        80454 : dump_context::ensure_pending_optinfo (const dump_metadata_t &metadata)
    1211              : {
    1212        80454 :   if (!m_pending)
    1213          848 :     return begin_next_optinfo (metadata, dump_user_location_t ());
    1214              :   return *m_pending;
    1215              : }
    1216              : 
    1217              : /* Start a new optinfo and return it, ending any optinfo that was already
    1218              :    accumulated.  */
    1219              : 
    1220              : optinfo &
    1221        43781 : dump_context::begin_next_optinfo (const dump_metadata_t &metadata,
    1222              :                                   const dump_user_location_t &user_loc)
    1223              : {
    1224        43781 :   end_any_optinfo ();
    1225        43781 :   gcc_assert (m_pending == NULL);
    1226        43781 :   dump_location_t loc (user_loc, metadata.get_impl_location ());
    1227        43781 :   m_pending = new optinfo (loc, optinfo::kind::note, current_pass);
    1228        43781 :   m_pending->handle_dump_file_kind (metadata.get_dump_flags ());
    1229        43781 :   return *m_pending;
    1230              : }
    1231              : 
    1232              : /* End any optinfo that has been accumulated within this context; emitting
    1233              :    it to any destinations as appropriate, such as optimization records.  */
    1234              : 
    1235              : void
    1236    592924449 : dump_context::end_any_optinfo ()
    1237              : {
    1238    592924449 :   if (m_pending)
    1239        42545 :     emit_optinfo (m_pending);
    1240    592924449 :   delete m_pending;
    1241    592924449 :   m_pending = NULL;
    1242    592924449 : }
    1243              : 
    1244              : /* Emit the optinfo to all of the "non-immediate" destinations
    1245              :    (emission to "immediate" destinations is done by
    1246              :    dump_context::emit_item).  */
    1247              : 
    1248              : void
    1249        48477 : dump_context::emit_optinfo (const optinfo *info)
    1250              : {
    1251              :   /* -fsave-optimization-record.  */
    1252        48477 :   if (m_json_writer)
    1253        42776 :     m_json_writer->add_record (info);
    1254        48477 : }
    1255              : 
    1256              : /* Emit ITEM to all item destinations (those that don't require
    1257              :    consolidation into optinfo instances).  */
    1258              : 
    1259              : void
    1260     16674967 : dump_context::emit_item (const optinfo_item &item, dump_flags_t dump_kind)
    1261              : {
    1262     16674967 :   if (dump_file && apply_dump_filter_p (dump_kind, pflags))
    1263     16364850 :     fprintf (dump_file, "%s", item.get_text ());
    1264              : 
    1265     16674967 :   if (alt_dump_file && apply_dump_filter_p (dump_kind, alt_flags))
    1266        98737 :     fprintf (alt_dump_file, "%s", item.get_text ());
    1267              : 
    1268              :   /* Support for temp_dump_context in selftests.  */
    1269     16674967 :   if (m_test_pp && apply_dump_filter_p (dump_kind, m_test_pp_flags))
    1270         5320 :     pp_string (m_test_pp, item.get_text ());
    1271     16674967 : }
    1272              : 
    1273              : /* The current singleton dump_context, and its default.  */
    1274              : 
    1275              : dump_context *dump_context::s_current = &dump_context::s_default;
    1276              : dump_context dump_context::s_default;
    1277              : 
    1278              : /* Implementation of dump_* API calls, calling into dump_context
    1279              :    member functions.  */
    1280              : 
    1281              : /* Calls to the dump_* functions do non-trivial work, so they ought
    1282              :    to be guarded by:
    1283              :      if (dump_enabled_p ())
    1284              :    Assert that they are guarded, and, if assertions are disabled,
    1285              :    bail out if the calls weren't properly guarded.  */
    1286              : 
    1287              : #define VERIFY_DUMP_ENABLED_P \
    1288              :   do {                                  \
    1289              :     gcc_assert (dump_enabled_p ());     \
    1290              :     if (!dump_enabled_p ())             \
    1291              :       return;                           \
    1292              :   } while (0)
    1293              : 
    1294              : /* Dump gimple statement GS with SPC indentation spaces and
    1295              :    EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled.  */
    1296              : 
    1297              : void
    1298          112 : dump_gimple_stmt (const dump_metadata_t &metadata, dump_flags_t extra_dump_flags,
    1299              :                   gimple *gs, int spc)
    1300              : {
    1301          112 :   VERIFY_DUMP_ENABLED_P;
    1302          112 :   dump_context::get ().dump_gimple_stmt (metadata, extra_dump_flags, gs, spc);
    1303              : }
    1304              : 
    1305              : /* Similar to dump_gimple_stmt, except additionally print source location.  */
    1306              : 
    1307              : void
    1308          112 : dump_gimple_stmt_loc (const dump_metadata_t &metadata,
    1309              :                       const dump_user_location_t &loc,
    1310              :                       dump_flags_t extra_dump_flags, gimple *gs, int spc)
    1311              : {
    1312          112 :   VERIFY_DUMP_ENABLED_P;
    1313          112 :   dump_context::get ().dump_gimple_stmt_loc (metadata, loc, extra_dump_flags,
    1314              :                                              gs, spc);
    1315              : }
    1316              : 
    1317              : /* Dump gimple statement GS with SPC indentation spaces and
    1318              :    EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled.
    1319              :    Do not terminate with a newline or semicolon.  */
    1320              : 
    1321              : void
    1322       687072 : dump_gimple_expr (const dump_metadata_t &metadata,
    1323              :                   dump_flags_t extra_dump_flags,
    1324              :                   gimple *gs, int spc)
    1325              : {
    1326       687072 :   VERIFY_DUMP_ENABLED_P;
    1327       687072 :   dump_context::get ().dump_gimple_expr (metadata, extra_dump_flags, gs, spc);
    1328              : }
    1329              : 
    1330              : /* Similar to dump_gimple_expr, except additionally print source location.  */
    1331              : 
    1332              : void
    1333          112 : dump_gimple_expr_loc (const dump_metadata_t &metadata,
    1334              :                       const dump_user_location_t &loc,
    1335              :                       dump_flags_t extra_dump_flags, gimple *gs, int spc)
    1336              : {
    1337          112 :   VERIFY_DUMP_ENABLED_P;
    1338          112 :   dump_context::get ().dump_gimple_expr_loc (metadata, loc, extra_dump_flags,
    1339              :                                              gs, spc);
    1340              : }
    1341              : 
    1342              : /* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
    1343              :    DUMP_KIND is enabled.  */
    1344              : 
    1345              : void
    1346        66039 : dump_generic_expr (const dump_metadata_t &metadata, dump_flags_t extra_dump_flags,
    1347              :                    tree t)
    1348              : {
    1349        66039 :   VERIFY_DUMP_ENABLED_P;
    1350        66039 :   dump_context::get ().dump_generic_expr (metadata, extra_dump_flags, t);
    1351              : }
    1352              : 
    1353              : /* Similar to dump_generic_expr, except additionally print the source
    1354              :    location.  */
    1355              : 
    1356              : void
    1357       151400 : dump_generic_expr_loc (const dump_metadata_t &metadata,
    1358              :                        const dump_user_location_t &loc,
    1359              :                        dump_flags_t extra_dump_flags, tree t)
    1360              : {
    1361       151400 :   VERIFY_DUMP_ENABLED_P;
    1362       151400 :   dump_context::get ().dump_generic_expr_loc (metadata, loc, extra_dump_flags,
    1363              :                                               t);
    1364              : }
    1365              : 
    1366              : /* Output a formatted message using FORMAT on appropriate dump streams.  */
    1367              : 
    1368              : void
    1369      4832052 : dump_printf (const dump_metadata_t &metadata, const char *format, ...)
    1370              : {
    1371      4832052 :   VERIFY_DUMP_ENABLED_P;
    1372      4832052 :   va_list ap;
    1373      4832052 :   va_start (ap, format);
    1374      4832052 :   dump_context::get ().dump_printf_va (metadata, format, &ap);
    1375      4832052 :   va_end (ap);
    1376              : }
    1377              : 
    1378              : /* Similar to dump_printf, except source location is also printed, and
    1379              :    dump location captured.  */
    1380              : 
    1381              : void
    1382      6187596 : dump_printf_loc (const dump_metadata_t &metadata,
    1383              :                  const dump_user_location_t &loc,
    1384              :                  const char *format, ...)
    1385              : {
    1386      6187596 :   VERIFY_DUMP_ENABLED_P;
    1387      6187596 :   va_list ap;
    1388      6187596 :   va_start (ap, format);
    1389      6187596 :   dump_context::get ().dump_printf_loc_va (metadata, loc, format, &ap);
    1390      6187596 :   va_end (ap);
    1391              : }
    1392              : 
    1393              : /* Output VALUE in decimal to appropriate dump streams.  */
    1394              : 
    1395              : template<unsigned int N, typename C>
    1396              : void
    1397       281724 : dump_dec (const dump_metadata_t &metadata, const poly_int<N, C> &value)
    1398              : {
    1399       281724 :   VERIFY_DUMP_ENABLED_P;
    1400       281724 :   dump_context::get ().dump_dec (metadata, value);
    1401              : }
    1402              : 
    1403              : template void dump_dec (const dump_metadata_t &metadata, const poly_uint16 &);
    1404              : template void dump_dec (const dump_metadata_t &metadata, const poly_int64 &);
    1405              : template void dump_dec (const dump_metadata_t &metadata, const poly_uint64 &);
    1406              : template void dump_dec (const dump_metadata_t &metadata, const poly_offset_int &);
    1407              : template void dump_dec (const dump_metadata_t &metadata, const poly_widest_int &);
    1408              : 
    1409              : void
    1410            0 : dump_dec (dump_flags_t dump_kind, const poly_wide_int &value, signop sgn)
    1411              : {
    1412            0 :   VERIFY_DUMP_ENABLED_P;
    1413            0 :   if (dump_file
    1414            0 :       && dump_context::get ().apply_dump_filter_p (dump_kind, pflags))
    1415            0 :     print_dec (value, dump_file, sgn);
    1416              : 
    1417            0 :   if (alt_dump_file
    1418            0 :       && dump_context::get ().apply_dump_filter_p (dump_kind, alt_flags))
    1419            0 :     print_dec (value, alt_dump_file, sgn);
    1420              : }
    1421              : 
    1422              : /* Output VALUE in hexadecimal to appropriate dump streams.  */
    1423              : 
    1424              : void
    1425       170858 : dump_hex (dump_flags_t dump_kind, const poly_wide_int &value)
    1426              : {
    1427       170858 :   VERIFY_DUMP_ENABLED_P;
    1428       170858 :   if (dump_file
    1429       170858 :       && dump_context::get ().apply_dump_filter_p (dump_kind, pflags))
    1430       168238 :     print_hex (value, dump_file);
    1431              : 
    1432       170858 :   if (alt_dump_file
    1433       170858 :       && dump_context::get ().apply_dump_filter_p (dump_kind, alt_flags))
    1434            0 :     print_hex (value, alt_dump_file);
    1435              : }
    1436              : 
    1437              : /* Emit and delete the currently pending optinfo, if there is one,
    1438              :    without the caller needing to know about class dump_context.  */
    1439              : 
    1440              : void
    1441    586100188 : dumpfile_ensure_any_optinfo_are_flushed ()
    1442              : {
    1443    586100188 :   dump_context::get().end_any_optinfo ();
    1444    586100188 : }
    1445              : 
    1446              : /* Output the name of NODE on appropriate dump streams.  */
    1447              : 
    1448              : void
    1449          114 : dump_symtab_node (const dump_metadata_t &metadata, symtab_node *node)
    1450              : {
    1451          114 :   VERIFY_DUMP_ENABLED_P;
    1452          114 :   dump_context::get ().dump_symtab_node (metadata, node);
    1453              : }
    1454              : 
    1455              : /* Get the current dump scope-nesting depth.
    1456              :    For use by -fopt-info (for showing nesting via indentation).  */
    1457              : 
    1458              : unsigned int
    1459      6699958 : get_dump_scope_depth ()
    1460              : {
    1461      6699958 :   return dump_context::get ().get_scope_depth ();
    1462              : }
    1463              : 
    1464              : /* Push a nested dump scope.
    1465              :    Print "=== NAME ===\n" to the dumpfile, if any, and to the -fopt-info
    1466              :    destination, if any.
    1467              :    Emit a "scope" opinfo if optinfos are enabled.
    1468              :    Increment the scope depth.  */
    1469              : 
    1470              : void
    1471       410647 : dump_begin_scope (const char *name,
    1472              :                   const dump_user_location_t &user_location,
    1473              :                   const dump_impl_location_t &impl_location)
    1474              : {
    1475       410647 :   dump_context::get ().begin_scope (name, user_location, impl_location);
    1476       410647 : }
    1477              : 
    1478              : /* Pop a nested dump scope.  */
    1479              : 
    1480              : void
    1481       410647 : dump_end_scope ()
    1482              : {
    1483       410647 :   dump_context::get ().end_scope ();
    1484       410647 : }
    1485              : 
    1486              : /* Start a dump for PHASE. Store user-supplied dump flags in
    1487              :    *FLAG_PTR.  Return the number of streams opened.  Set globals
    1488              :    DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
    1489              :    set dump_flags appropriately for both pass dump stream and
    1490              :    -fopt-info stream. */
    1491              : 
    1492              : int
    1493    292524854 : gcc::dump_manager::
    1494              : dump_start (int phase, dump_flags_t *flag_ptr)
    1495              : {
    1496    292524854 :   int count = 0;
    1497    292524854 :   char *name;
    1498    292524854 :   struct dump_file_info *dfi;
    1499    292524854 :   FILE *stream;
    1500    292524854 :   if (phase == TDI_none || !dump_phase_enabled_p (phase))
    1501    292453389 :     return 0;
    1502              : 
    1503        71465 :   dfi = get_dump_file_info (phase);
    1504        71465 :   name = get_dump_file_name (phase);
    1505        71465 :   if (name)
    1506              :     {
    1507        56080 :       stream = dump_open (name, dfi->pstate < 0);
    1508        56080 :       if (stream)
    1509              :         {
    1510        56080 :           dfi->pstate = 1;
    1511        56080 :           count++;
    1512              :         }
    1513        56080 :       free (name);
    1514        56080 :       dfi->pstream = stream;
    1515        56080 :       set_dump_file (dfi->pstream);
    1516              :       /* Initialize current dump flags. */
    1517        56080 :       pflags = dfi->pflags;
    1518              :     }
    1519              : 
    1520        71465 :   stream = dump_open_alternate_stream (dfi);
    1521        71465 :   if (stream)
    1522              :     {
    1523        15553 :       dfi->alt_stream = stream;
    1524        15553 :       count++;
    1525        15553 :       set_alt_dump_file (dfi->alt_stream);
    1526              :       /* Initialize current -fopt-info flags. */
    1527        15553 :       alt_flags = dfi->alt_flags;
    1528              :     }
    1529              : 
    1530        71465 :   if (flag_ptr)
    1531        71345 :     *flag_ptr = dfi->pflags;
    1532              : 
    1533              :   return count;
    1534              : }
    1535              : 
    1536              : /* Finish a tree dump for PHASE and close associated dump streams.  Also
    1537              :    reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS.  */
    1538              : 
    1539              : void
    1540    321913482 : gcc::dump_manager::
    1541              : dump_finish (int phase)
    1542              : {
    1543    321913482 :   struct dump_file_info *dfi;
    1544              : 
    1545    321913482 :   if (phase < 0)
    1546              :     return;
    1547    292524525 :   dfi = get_dump_file_info (phase);
    1548    292524525 :   if (dfi->pstream && dfi->pstream != stdout && dfi->pstream != stderr)
    1549        56078 :     fclose (dfi->pstream);
    1550              : 
    1551    292524525 :   if (dfi->alt_stream && dfi->alt_stream != stdout && dfi->alt_stream != stderr)
    1552            0 :     fclose (dfi->alt_stream);
    1553              : 
    1554    292524525 :   dfi->alt_stream = NULL;
    1555    292524525 :   dfi->pstream = NULL;
    1556    292524525 :   set_dump_file (NULL);
    1557    292524525 :   set_alt_dump_file (NULL);
    1558    292524525 :   dump_flags = TDF_NONE;
    1559    292524525 :   alt_flags = TDF_NONE;
    1560    292524525 :   pflags = TDF_NONE;
    1561              : }
    1562              : 
    1563              : /* Begin a tree dump for PHASE. Stores any user supplied flag in
    1564              :    *FLAG_PTR and returns a stream to write to. If the dump is not
    1565              :    enabled, returns NULL.
    1566              :    PART can be used for dump files which should be split to multiple
    1567              :    parts. PART == -1 indicates dump file with no parts.
    1568              :    If PART is -1, multiple calls will reopen and append to the dump file.  */
    1569              : 
    1570              : FILE *
    1571   1325118878 : dump_begin (int phase, dump_flags_t *flag_ptr, int part)
    1572              : {
    1573   1325118878 :   return g->get_dumps ()->dump_begin (phase, flag_ptr, part);
    1574              : }
    1575              : 
    1576              : FILE *
    1577   1325118878 : gcc::dump_manager::
    1578              : dump_begin (int phase, dump_flags_t *flag_ptr, int part)
    1579              : {
    1580   1325118878 :   if (phase == TDI_none || !dump_phase_enabled_p (phase))
    1581   1325102369 :     return NULL;
    1582              : 
    1583        16509 :   char *name = get_dump_file_name (phase, part);
    1584        16509 :   if (!name)
    1585              :     return NULL;
    1586        16509 :   struct dump_file_info *dfi = get_dump_file_info (phase);
    1587              : 
    1588              :   /* We do not support re-opening of dump files with parts.  This would require
    1589              :      tracking pstate per part of the dump file.  */
    1590        20046 :   FILE *stream = dump_open (name, part != -1 || dfi->pstate < 0);
    1591        16509 :   if (stream)
    1592        16509 :     dfi->pstate = 1;
    1593        16509 :   free (name);
    1594              : 
    1595        16509 :   if (flag_ptr)
    1596        16212 :     *flag_ptr = dfi->pflags;
    1597              : 
    1598              :   /* Initialize current flags */
    1599        16509 :   pflags = dfi->pflags;
    1600        16509 :   return stream;
    1601              : }
    1602              : 
    1603              : /* Returns nonzero if dump PHASE is enabled for at least one stream.
    1604              :    If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
    1605              :    any phase.  */
    1606              : 
    1607              : int
    1608   1609857629 : gcc::dump_manager::
    1609              : dump_phase_enabled_p (int phase) const
    1610              : {
    1611   1609857629 :   if (phase == TDI_tree_all)
    1612              :     {
    1613              :       size_t i;
    1614            0 :       for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
    1615            0 :         if (dump_files[i].pstate || dump_files[i].alt_state)
    1616              :           return 1;
    1617            0 :       for (i = 0; i < m_extra_dump_files_in_use; i++)
    1618            0 :         if (m_extra_dump_files[i].pstate || m_extra_dump_files[i].alt_state)
    1619              :           return 1;
    1620              :       return 0;
    1621              :     }
    1622              :   else
    1623              :     {
    1624   1609857629 :       struct dump_file_info *dfi = get_dump_file_info (phase);
    1625   1609945603 :       return dfi->pstate || dfi->alt_state;
    1626              :     }
    1627              : }
    1628              : 
    1629              : /* Returns nonzero if tree dump PHASE has been initialized.  */
    1630              : 
    1631              : int
    1632    292065210 : gcc::dump_manager::
    1633              : dump_initialized_p (int phase) const
    1634              : {
    1635    292065210 :   struct dump_file_info *dfi = get_dump_file_info (phase);
    1636    292065210 :   return dfi->pstate > 0 || dfi->alt_state > 0;
    1637              : }
    1638              : 
    1639              : /* Returns the switch name of PHASE.  */
    1640              : 
    1641              : const char *
    1642         7419 : dump_flag_name (int phase)
    1643              : {
    1644         7419 :   return g->get_dumps ()->dump_flag_name (phase);
    1645              : }
    1646              : 
    1647              : const char *
    1648         7419 : gcc::dump_manager::
    1649              : dump_flag_name (int phase) const
    1650              : {
    1651         7419 :   struct dump_file_info *dfi = get_dump_file_info (phase);
    1652         7419 :   return dfi->swtch;
    1653              : }
    1654              : 
    1655              : /* Handle -fdump-* and -fopt-info for a pass added after
    1656              :    command-line options are parsed (those from plugins and
    1657              :    those from backends).
    1658              : 
    1659              :    Because the registration of plugin/backend passes happens after the
    1660              :    command-line options are parsed, the options that specify single
    1661              :    pass dumping (e.g. -fdump-tree-PASSNAME) cannot be used for new
    1662              :    passes. Therefore we currently can only enable dumping of
    1663              :    new passes when the 'dump-all' flags (e.g. -fdump-tree-all)
    1664              :    are specified.  This is done here.
    1665              : 
    1666              :    Similarly, the saved -fopt-info options are wired up to the new pass.  */
    1667              : 
    1668              : void
    1669          173 : gcc::dump_manager::register_pass (opt_pass *pass)
    1670              : {
    1671          173 :   gcc_assert (pass);
    1672              : 
    1673          173 :   register_one_dump_file (pass);
    1674              : 
    1675          173 :   dump_file_info *pass_dfi = get_dump_file_info (pass->static_pass_number);
    1676          173 :   gcc_assert (pass_dfi);
    1677              : 
    1678          173 :   enum tree_dump_index tdi;
    1679          173 :   if (pass->type == SIMPLE_IPA_PASS
    1680          173 :       || pass->type == IPA_PASS)
    1681              :     tdi = TDI_ipa_all;
    1682          160 :   else if (pass->type == GIMPLE_PASS)
    1683              :     tdi = TDI_tree_all;
    1684              :   else
    1685            0 :     tdi = TDI_rtl_all;
    1686          173 :   const dump_file_info *tdi_dfi = get_dump_file_info (tdi);
    1687          173 :   gcc_assert (tdi_dfi);
    1688              : 
    1689              :   /* Check if dump-all flag is specified.  */
    1690          173 :   if (tdi_dfi->pstate)
    1691              :     {
    1692            0 :       pass_dfi->pstate = tdi_dfi->pstate;
    1693            0 :       pass_dfi->pflags = tdi_dfi->pflags;
    1694              :     }
    1695              : 
    1696          173 :   update_dfi_for_opt_info (pass_dfi);
    1697          173 : }
    1698              : 
    1699              : /* Finish a tree dump for PHASE. STREAM is the stream created by
    1700              :    dump_begin.  */
    1701              : 
    1702              : void
    1703        16380 : dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
    1704              : {
    1705        16380 :   if (stream != stderr && stream != stdout)
    1706        16380 :     fclose (stream);
    1707        16380 : }
    1708              : 
    1709              : /* Enable all tree dumps with FLAGS on FILENAME.  Return number of
    1710              :    enabled tree dumps.  */
    1711              : 
    1712              : int
    1713          180 : gcc::dump_manager::
    1714              : dump_enable_all (dump_kind dkind, dump_flags_t flags, const char *filename)
    1715              : {
    1716          180 :   int n = 0;
    1717          180 :   size_t i;
    1718              : 
    1719         2340 :   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
    1720              :     {
    1721         2160 :       if (dump_files[i].dkind == dkind)
    1722              :         {
    1723          577 :           const char *old_filename = dump_files[i].pfilename;
    1724          577 :           dump_files[i].pstate = -1;
    1725          577 :           dump_files[i].pflags |= flags;
    1726          577 :           n++;
    1727              :           /* Override the existing filename.  */
    1728          577 :           if (filename)
    1729              :             {
    1730            0 :               dump_files[i].pfilename = xstrdup (filename);
    1731              :               /* Since it is a command-line provided file, which is
    1732              :                  common to all the phases, use it in append mode.  */
    1733            0 :               dump_files[i].pstate = 1;
    1734              :             }
    1735          577 :           if (old_filename && filename != old_filename)
    1736            0 :             free (const_cast<char *> (old_filename));
    1737              :         }
    1738              :     }
    1739              : 
    1740        66120 :   for (i = 0; i < m_extra_dump_files_in_use; i++)
    1741              :     {
    1742        65940 :       if (m_extra_dump_files[i].dkind == dkind)
    1743              :         {
    1744        18185 :           const char *old_filename = m_extra_dump_files[i].pfilename;
    1745        18185 :           m_extra_dump_files[i].pstate = -1;
    1746        18185 :           m_extra_dump_files[i].pflags |= flags;
    1747        18185 :           n++;
    1748              :           /* Override the existing filename.  */
    1749        18185 :           if (filename)
    1750              :             {
    1751            0 :               m_extra_dump_files[i].pfilename = xstrdup (filename);
    1752              :               /* Since it is a command-line provided file, which is
    1753              :                  common to all the phases, use it in append mode.  */
    1754            0 :               m_extra_dump_files[i].pstate = 1;
    1755              :             }
    1756        18185 :           if (old_filename && filename != old_filename)
    1757            0 :             free (const_cast<char *> (old_filename));
    1758              :         }
    1759              :     }
    1760              : 
    1761          180 :   return n;
    1762              : }
    1763              : 
    1764              : /* Enable -fopt-info dumps on all dump files matching OPTGROUP_FLAGS.
    1765              :    Enable dumps with FLAGS on FILENAME.  Return the number of enabled
    1766              :    dumps.  */
    1767              : 
    1768              : int
    1769          675 : gcc::dump_manager::
    1770              : opt_info_enable_passes (optgroup_flags_t optgroup_flags, dump_flags_t flags,
    1771              :                         const char *filename)
    1772              : {
    1773          675 :   int n = 0;
    1774              : 
    1775          675 :   m_optgroup_flags = optgroup_flags;
    1776          675 :   m_optinfo_flags = flags;
    1777          675 :   m_optinfo_filename = xstrdup (filename);
    1778              : 
    1779         8775 :   for (size_t i = TDI_none + 1; i < (size_t) TDI_end; i++)
    1780         8100 :     if (update_dfi_for_opt_info (&dump_files[i]))
    1781            0 :       n++;
    1782              : 
    1783       248890 :   for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
    1784       248215 :     if (update_dfi_for_opt_info (&m_extra_dump_files[i]))
    1785        12857 :       n++;
    1786              : 
    1787          675 :   return n;
    1788              : }
    1789              : 
    1790              : /* Use the saved -fopt-info options to update DFI.
    1791              :    Return true if the dump is enabled.  */
    1792              : 
    1793              : bool
    1794       256488 : gcc::dump_manager::update_dfi_for_opt_info (dump_file_info *dfi) const
    1795              : {
    1796       256488 :   gcc_assert (dfi);
    1797              : 
    1798       256488 :   if (!(dfi->optgroup_flags & m_optgroup_flags))
    1799              :     return false;
    1800              : 
    1801        12859 :   const char *old_filename = dfi->alt_filename;
    1802              :   /* Since this file is shared among different passes, it
    1803              :      should be opened in append mode.  */
    1804        12859 :   dfi->alt_state = 1;
    1805        12859 :   dfi->alt_flags |= m_optinfo_flags;
    1806              :   /* Override the existing filename.  */
    1807        12859 :   if (m_optinfo_filename)
    1808        12859 :     dfi->alt_filename = xstrdup (m_optinfo_filename);
    1809        12859 :   if (old_filename && m_optinfo_filename != old_filename)
    1810            0 :     free (const_cast<char *> (old_filename));
    1811              : 
    1812              :   return true;
    1813              : }
    1814              : 
    1815              : /* Helper routine to parse -<dump format>[=filename]
    1816              :    and return the corresponding dump flag.  If POS_P is non-NULL,
    1817              :    assign start of filename into *POS_P.  */
    1818              : 
    1819              : dump_flags_t
    1820        23699 : parse_dump_option (const char *option_value, const char **pos_p)
    1821              : {
    1822        23699 :   const char *ptr;
    1823        23699 :   dump_flags_t flags;
    1824              : 
    1825        23699 :   ptr = option_value;
    1826        23699 :   if (pos_p)
    1827        23699 :     *pos_p = NULL;
    1828              : 
    1829              :   /* Retain "user-facing" and "internals" messages, but filter out
    1830              :      those from an opt_problem being re-emitted at the top level
    1831              :      (MSG_PRIORITY_REEMITTED), so as to avoid duplicate messages
    1832              :      messing up scan-tree-dump-times" in DejaGnu tests.  */
    1833              :   flags = MSG_PRIORITY_USER_FACING | MSG_PRIORITY_INTERNALS;
    1834              : 
    1835        36819 :   while (*ptr)
    1836              :     {
    1837              :       const struct kv_pair<dump_flags_t> *option_ptr;
    1838              :       const char *end_ptr;
    1839              :       const char *eq_ptr;
    1840              :       unsigned length;
    1841        26241 :       while (*ptr == '-')
    1842        13120 :         ptr++;
    1843        13121 :       end_ptr = strchr (ptr, '-');
    1844        13121 :       eq_ptr = strchr (ptr, '=');
    1845              : 
    1846        13121 :       if (eq_ptr && (!end_ptr || end_ptr > eq_ptr))
    1847              :         end_ptr = eq_ptr;
    1848              : 
    1849        13121 :       if (!end_ptr)
    1850        12294 :         end_ptr = ptr + strlen (ptr);
    1851        13121 :       length = end_ptr - ptr;
    1852              : 
    1853       112325 :       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
    1854       112324 :         if (strlen (option_ptr->name) == length
    1855        37061 :             && !memcmp (option_ptr->name, ptr, length))
    1856              :           {
    1857        13120 :             flags |= option_ptr->value;
    1858        13120 :             goto found;
    1859              :           }
    1860              : 
    1861            1 :       if (*ptr == '=')
    1862              :         {
    1863              :           /* Interpret rest of the argument as a dump filename.  This
    1864              :              filename overrides other command line filenames.  */
    1865            1 :           if (pos_p)
    1866            1 :             *pos_p = ptr + 1;
    1867              :           break;
    1868              :         }
    1869              :       else
    1870              :       {
    1871            0 :         warning (0, "ignoring unknown option %q.*s",
    1872              :                  length, ptr);
    1873            0 :         flags = TDF_ERROR;
    1874              :       }
    1875              :     found:
    1876              :       ptr = end_ptr;
    1877              :   }
    1878              : 
    1879        23699 :   return flags;
    1880              : }
    1881              : 
    1882              : /* Parse ARG as a dump switch.  Return nonzero if it is, and store the
    1883              :    relevant details in the dump_files array.  */
    1884              : 
    1885              : int
    1886      9011927 : gcc::dump_manager::
    1887              : dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
    1888              : {
    1889      9011927 :   const char *option_value;
    1890      9011927 :   dump_flags_t flags = TDF_NONE;
    1891              : 
    1892      9011927 :   if (doglob && !dfi->glob)
    1893              :     return 0;
    1894              : 
    1895      8783987 :   option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
    1896        23859 :   if (!option_value)
    1897              :     return 0;
    1898              : 
    1899        23859 :   if (*option_value && *option_value != '-' && *option_value != '=')
    1900              :     return 0;
    1901              : 
    1902        23699 :   const char *filename;
    1903        23699 :   flags = parse_dump_option (option_value, &filename);
    1904        23699 :   if (filename)
    1905              :     {
    1906            1 :       if (dfi->pfilename)
    1907            0 :         free (const_cast<char *> (dfi->pfilename));
    1908            1 :       dfi->pfilename = xstrdup (filename);
    1909              :     }
    1910              : 
    1911        23699 :   dfi->pstate = -1;
    1912        23699 :   dfi->pflags |= flags;
    1913              : 
    1914              :   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
    1915              :      known dumps.  */
    1916        23699 :   if (dfi->suffix == NULL)
    1917          176 :     dump_enable_all (dfi->dkind, dfi->pflags, dfi->pfilename);
    1918              : 
    1919              :   return 1;
    1920              : }
    1921              : 
    1922              : void
    1923        22341 : gcc::dump_manager::
    1924              : dump_switch_p (const char *arg)
    1925              : {
    1926        22341 :   size_t i;
    1927        22341 :   int any = 0;
    1928              : 
    1929       290433 :   for (i = TDI_none + 1; i != TDI_end; i++)
    1930       268092 :     any |= dump_switch_p_1 (arg, &dump_files[i], false);
    1931              : 
    1932              :   /* Don't glob if we got a hit already */
    1933        22341 :   if (!any)
    1934       246935 :     for (i = TDI_none + 1; i != TDI_end; i++)
    1935       227940 :       any |= dump_switch_p_1 (arg, &dump_files[i], true);
    1936              : 
    1937      8233733 :   for (i = 0; i < m_extra_dump_files_in_use; i++)
    1938      8211392 :     any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], false);
    1939              : 
    1940        22341 :   if (!any)
    1941       305333 :     for (i = 0; i < m_extra_dump_files_in_use; i++)
    1942       304503 :       any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], true);
    1943              : 
    1944          830 :   if (!any)
    1945              :     {
    1946            6 :       auto_vec<const char *> candidates;
    1947           78 :       for (size_t i = TDI_none + 1; i != TDI_end; i++)
    1948           72 :         candidates.safe_push (dump_files[i].swtch);
    1949         2202 :       for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
    1950         2196 :         candidates.safe_push (m_extra_dump_files[i].swtch);
    1951            6 :       const char *hint = find_closest_string (arg, &candidates);
    1952            6 :       if (hint)
    1953            1 :         error ("unrecognized command-line option %<-fdump-%s%>; "
    1954              :                "did you mean %<-fdump-%s%>?", arg, hint);
    1955              :       else
    1956            5 :         error ("unrecognized command-line option %<-fdump-%s%>", arg);
    1957            6 :     }
    1958        22341 : }
    1959              : 
    1960              : /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
    1961              :    and filename.  Return non-zero if it is a recognized switch.  */
    1962              : 
    1963              : static int
    1964          675 : opt_info_switch_p_1 (const char *arg, dump_flags_t *flags,
    1965              :                      optgroup_flags_t *optgroup_flags, char **filename)
    1966              : {
    1967          675 :   const char *option_value;
    1968          675 :   const char *ptr;
    1969              : 
    1970          675 :   option_value = arg;
    1971          675 :   ptr = option_value;
    1972              : 
    1973          675 :   *filename = NULL;
    1974              : 
    1975              :   /* Default to filtering out "internals" messages, and retaining
    1976              :      "user-facing" messages, and those from an opt_problem being
    1977              :      re-emitted at the top level.  */
    1978          675 :   *flags = MSG_PRIORITY_USER_FACING | MSG_PRIORITY_REEMITTED;
    1979              : 
    1980          675 :   *optgroup_flags = OPTGROUP_NONE;
    1981              : 
    1982          675 :   if (!ptr)
    1983              :     return 1;       /* Handle '-fopt-info' without any additional options.  */
    1984              : 
    1985         1999 :   while (*ptr)
    1986              :     {
    1987              :       const char *end_ptr;
    1988              :       const char *eq_ptr;
    1989              :       unsigned length;
    1990              : 
    1991         1977 :       while (*ptr == '-')
    1992          651 :         ptr++;
    1993         1326 :       end_ptr = strchr (ptr, '-');
    1994         1326 :       eq_ptr = strchr (ptr, '=');
    1995              : 
    1996         1326 :       if (eq_ptr && (!end_ptr || eq_ptr < end_ptr))
    1997              :         end_ptr = eq_ptr;
    1998         1323 :       else if (!end_ptr)
    1999          673 :         end_ptr = ptr + strlen (ptr);
    2000         1326 :       length = end_ptr - ptr;
    2001              : 
    2002         6219 :       for (const kv_pair<dump_flags_t> *option_ptr = optinfo_verbosity_options;
    2003         6219 :            option_ptr->name; option_ptr++)
    2004         5558 :         if (strlen (option_ptr->name) == length
    2005         1326 :             && !memcmp (option_ptr->name, ptr, length))
    2006              :           {
    2007          665 :             *flags |= option_ptr->value;
    2008          665 :             goto found;
    2009              :           }
    2010              : 
    2011         1977 :       for (const kv_pair<optgroup_flags_t> *option_ptr = optgroup_options;
    2012         2638 :            option_ptr->name; option_ptr++)
    2013         2637 :         if (strlen (option_ptr->name) == length
    2014         1325 :             && !memcmp (option_ptr->name, ptr, length))
    2015              :           {
    2016          660 :             *optgroup_flags |= option_ptr->value;
    2017          660 :             goto found;
    2018              :           }
    2019              : 
    2020            1 :       if (*ptr == '=')
    2021              :         {
    2022              :           /* Interpret rest of the argument as a dump filename.  This
    2023              :              filename overrides other command line filenames.  */
    2024            1 :           *filename = xstrdup (ptr + 1);
    2025            1 :           break;
    2026              :         }
    2027              :       else
    2028              :         {
    2029            0 :           warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
    2030              :                    length, ptr, arg);
    2031            0 :           return 0;
    2032              :         }
    2033              :     found:;
    2034              :       ptr = end_ptr;
    2035              :     }
    2036              : 
    2037              :   return 1;
    2038              : }
    2039              : 
    2040              : /* Return non-zero if ARG is a recognized switch for
    2041              :    -fopt-info. Return zero otherwise.  */
    2042              : 
    2043              : int
    2044          675 : opt_info_switch_p (const char *arg)
    2045              : {
    2046          675 :   dump_flags_t flags;
    2047          675 :   optgroup_flags_t optgroup_flags;
    2048          675 :   char *filename;
    2049          675 :   static char *file_seen = NULL;
    2050          675 :   gcc::dump_manager *dumps = g->get_dumps ();
    2051              : 
    2052          675 :   if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename))
    2053              :     return 0;
    2054              : 
    2055          675 :   if (!filename)
    2056          674 :     filename = xstrdup ("stderr");
    2057              : 
    2058              :   /* Bail out if a different filename has been specified.  */
    2059          675 :   if (file_seen && strcmp (file_seen, filename))
    2060              :     {
    2061            0 :       warning (0, "ignoring possibly conflicting option %<-fopt-info-%s%>",
    2062              :                arg);
    2063            0 :       return 1;
    2064              :     }
    2065              : 
    2066          675 :   file_seen = xstrdup (filename);
    2067          675 :   if (!(flags & MSG_ALL_KINDS))
    2068           12 :     flags |= MSG_OPTIMIZED_LOCATIONS;
    2069          675 :   if (!optgroup_flags)
    2070           15 :     optgroup_flags = OPTGROUP_ALL;
    2071              : 
    2072          675 :   return dumps->opt_info_enable_passes (optgroup_flags, flags, filename);
    2073              : }
    2074              : 
    2075              : /* Print basic block on the dump streams.  */
    2076              : 
    2077              : void
    2078            0 : dump_basic_block (dump_flags_t dump_kind, basic_block bb, int indent)
    2079              : {
    2080            0 :   if (dump_file
    2081            0 :       && dump_context::get ().apply_dump_filter_p (dump_kind, pflags))
    2082            0 :     dump_bb (dump_file, bb, indent, TDF_DETAILS);
    2083            0 :   if (alt_dump_file
    2084            0 :       && dump_context::get ().apply_dump_filter_p (dump_kind, alt_flags))
    2085            0 :     dump_bb (alt_dump_file, bb, indent, TDF_DETAILS);
    2086            0 : }
    2087              : 
    2088              : /* Dump FUNCTION_DECL FN as tree dump PHASE.  */
    2089              : 
    2090              : void
    2091      2996934 : dump_function (int phase, tree fn)
    2092              : {
    2093      2996934 :   FILE *stream;
    2094      2996934 :   dump_flags_t flags;
    2095              : 
    2096      2996934 :   stream = dump_begin (phase, &flags);
    2097      2996934 :   if (stream)
    2098              :     {
    2099        10529 :       dump_function_to_file (fn, stream, flags);
    2100        10529 :       dump_end (phase, stream);
    2101              :     }
    2102      2996934 : }
    2103              : 
    2104              : /* Enable RTL dump for all the RTL passes.  */
    2105              : 
    2106              : bool
    2107            4 : enable_rtl_dump_file (void)
    2108              : {
    2109            4 :   gcc::dump_manager *dumps = g->get_dumps ();
    2110            4 :   int num_enabled =
    2111            4 :     dumps->dump_enable_all (DK_rtl, dump_flags_t (TDF_DETAILS) | TDF_BLOCKS,
    2112              :                             NULL);
    2113            4 :   return num_enabled > 0;
    2114              : }
    2115              : 
    2116              : /* debug_dump_context's ctor.  Temporarily override the dump_context
    2117              :    (to forcibly enable output to stderr).  */
    2118              : 
    2119            0 : debug_dump_context::debug_dump_context (FILE *f)
    2120            0 : : m_context (),
    2121            0 :   m_saved (&dump_context::get ()),
    2122            0 :   m_saved_flags (dump_flags),
    2123            0 :   m_saved_pflags (pflags),
    2124            0 :   m_saved_file (dump_file)
    2125              : {
    2126            0 :   set_dump_file (f);
    2127            0 :   dump_context::s_current = &m_context;
    2128            0 :   pflags = dump_flags = MSG_ALL_KINDS | MSG_ALL_PRIORITIES;
    2129            0 :   dump_context::get ().refresh_dumps_are_enabled ();
    2130            0 : }
    2131              : 
    2132              : /* debug_dump_context's dtor.  Restore the saved dump_context.  */
    2133              : 
    2134            0 : debug_dump_context::~debug_dump_context ()
    2135              : {
    2136            0 :   set_dump_file (m_saved_file);
    2137            0 :   dump_context::s_current = m_saved;
    2138            0 :   dump_flags = m_saved_flags;
    2139            0 :   pflags = m_saved_pflags;
    2140            0 :   dump_context::get ().refresh_dumps_are_enabled ();
    2141            0 : }
    2142              : 
    2143              : 
    2144              : #if CHECKING_P
    2145              : 
    2146              : namespace selftest {
    2147              : 
    2148              : /* temp_dump_context's ctor.  Temporarily override the dump_context
    2149              :    (to forcibly enable optinfo-generation).  */
    2150              : 
    2151         2422 : temp_dump_context::temp_dump_context (bool forcibly_enable_optinfo,
    2152              :                                       bool forcibly_enable_dumping,
    2153         2422 :                                       dump_flags_t test_pp_flags)
    2154         2422 : : m_context (),
    2155         2422 :   m_saved (&dump_context::get ())
    2156              : {
    2157         2422 :   dump_context::s_current = &m_context;
    2158         2422 :   if (forcibly_enable_optinfo)
    2159         1243 :     m_context.set_json_writer (new optrecord_json_writer ());
    2160              :   /* Conditionally enable the test dump, so that we can verify both the
    2161              :      dump_enabled_p and the !dump_enabled_p cases in selftests.  */
    2162         2422 :   if (forcibly_enable_dumping)
    2163              :     {
    2164         2251 :       m_context.m_test_pp = &m_pp;
    2165         2251 :       m_context.m_test_pp_flags = test_pp_flags;
    2166              :     }
    2167              : 
    2168         2422 :   dump_context::get ().refresh_dumps_are_enabled ();
    2169         2422 : }
    2170              : 
    2171              : /* temp_dump_context's dtor.  Restore the saved dump_context.  */
    2172              : 
    2173         2422 : temp_dump_context::~temp_dump_context ()
    2174              : {
    2175         2422 :   m_context.set_json_writer (NULL);
    2176              : 
    2177         2422 :   dump_context::s_current = m_saved;
    2178              : 
    2179         2422 :   dump_context::get ().refresh_dumps_are_enabled ();
    2180         2422 : }
    2181              : 
    2182              : /* 0-terminate the text dumped so far, and return it.  */
    2183              : 
    2184              : const char *
    2185         2302 : temp_dump_context::get_dumped_text ()
    2186              : {
    2187         2302 :   return pp_formatted_text (&m_pp);
    2188              : }
    2189              : 
    2190              : /* Verify that IMPL_LOC is within EXPECTED_FILE at EXPECTED_LINE,
    2191              :    from EXPECTED_FUNCTION, using LOC for the location of any failure,
    2192              :    provided that the build compiler is sufficiently recent.  */
    2193              : 
    2194              : static void
    2195          908 : assert_impl_location_eq (const location &loc ATTRIBUTE_UNUSED,
    2196              :                          const dump_impl_location_t &impl_loc ATTRIBUTE_UNUSED,
    2197              :                          const char *expected_file ATTRIBUTE_UNUSED,
    2198              :                          int expected_line ATTRIBUTE_UNUSED,
    2199              :                          const char *expected_function ATTRIBUTE_UNUSED)
    2200              : {
    2201              : #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
    2202          908 :   ASSERT_STR_CONTAINS_AT (loc, impl_loc.m_file, expected_file);
    2203          908 :   ASSERT_EQ_AT (loc, impl_loc.m_line, expected_line);
    2204          908 :   ASSERT_STR_CONTAINS_AT (loc, impl_loc.m_function, expected_function);
    2205              : #endif
    2206          908 : }
    2207              : 
    2208              : /* Verify that IMPL_LOC is within EXPECTED_FILE at EXPECTED_LINE,
    2209              :    from EXPECTED_FUNCTION, provided that the build compiler is
    2210              :    sufficiently recent.  */
    2211              : 
    2212              : #define ASSERT_IMPL_LOCATION_EQ(IMPL_LOC, EXPECTED_FILE, EXPECTED_LINE, \
    2213              :                                 EXPECTED_FUNCTION)                      \
    2214              :   SELFTEST_BEGIN_STMT                                                   \
    2215              :     assert_impl_location_eq (SELFTEST_LOCATION, IMPL_LOC,               \
    2216              :                              EXPECTED_FILE, EXPECTED_LINE,              \
    2217              :                              EXPECTED_FUNCTION);                        \
    2218              :   SELFTEST_END_STMT
    2219              : 
    2220              : /* Verify that the dump_location_t constructors capture the source location
    2221              :    at which they were called (provided that the build compiler is sufficiently
    2222              :    recent).  */
    2223              : 
    2224              : static void
    2225            4 : test_impl_location ()
    2226              : {
    2227              :   /* Default ctor.  */
    2228            4 :   {
    2229            4 :     dump_location_t loc;
    2230            4 :     const int expected_line = __LINE__ - 1;
    2231            4 :     ASSERT_IMPL_LOCATION_EQ (loc.get_impl_location (),
    2232              :                              "dumpfile.cc", expected_line, "test_impl_location");
    2233              :   }
    2234              : 
    2235              :   /* Constructing from a gimple.  */
    2236            4 :   {
    2237            4 :     dump_location_t loc ((gimple *)NULL);
    2238            4 :     const int expected_line = __LINE__ - 1;
    2239            4 :     ASSERT_IMPL_LOCATION_EQ (loc.get_impl_location (),
    2240              :                              "dumpfile.cc", expected_line, "test_impl_location");
    2241              :   }
    2242              : 
    2243              :   /* Constructing from an rtx_insn.  */
    2244            4 :   {
    2245            4 :     dump_location_t loc ((rtx_insn *)NULL);
    2246            4 :     const int expected_line = __LINE__ - 1;
    2247            4 :     ASSERT_IMPL_LOCATION_EQ (loc.get_impl_location (),
    2248              :                              "dumpfile.cc", expected_line, "test_impl_location");
    2249              :   }
    2250            4 : }
    2251              : 
    2252              : /* Verify that the text dumped so far in CONTEXT equals
    2253              :    EXPECTED_TEXT, using LOC for the location of any failure.
    2254              :    As a side-effect, the internal buffer is 0-terminated.  */
    2255              : 
    2256              : void
    2257         2302 : verify_dumped_text (const location &loc,
    2258              :                     temp_dump_context *context,
    2259              :                     const char *expected_text)
    2260              : {
    2261         2302 :   gcc_assert (context);
    2262         2302 :   ASSERT_STREQ_AT (loc, context->get_dumped_text (),
    2263              :                    expected_text);
    2264         2302 : }
    2265              : 
    2266              : /* Verify that ITEM has the expected values.  */
    2267              : 
    2268              : void
    2269         2296 : verify_item (const location &loc,
    2270              :              const optinfo_item *item,
    2271              :              enum optinfo_item::kind expected_kind,
    2272              :              location_t expected_location,
    2273              :              const char *expected_text)
    2274              : {
    2275         2296 :   ASSERT_EQ_AT (loc, item->get_kind (), expected_kind);
    2276         2296 :   ASSERT_EQ_AT (loc, item->get_location (), expected_location);
    2277         2296 :   ASSERT_STREQ_AT (loc, item->get_text (), expected_text);
    2278         2296 : }
    2279              : 
    2280              : /* Verify that calls to the dump_* API are captured and consolidated into
    2281              :    optimization records. */
    2282              : 
    2283              : static void
    2284           96 : test_capture_of_dump_calls (const line_table_case &case_)
    2285              : {
    2286              :   /* Generate a location_t for testing.  */
    2287           96 :   line_table_test ltt (case_);
    2288           96 :   linemap_add (line_table, LC_ENTER, false, "test.txt", 0);
    2289           96 :   linemap_line_start (line_table, 5, 100);
    2290           96 :   linemap_add (line_table, LC_LEAVE, false, NULL, 0);
    2291           96 :   location_t decl_loc = linemap_position_for_column (line_table, 8);
    2292           96 :   location_t stmt_loc = linemap_position_for_column (line_table, 10);
    2293           96 :   if (stmt_loc > LINE_MAP_MAX_LOCATION_WITH_COLS)
    2294           40 :     return;
    2295              : 
    2296           56 :   dump_user_location_t loc = dump_user_location_t::from_location_t (stmt_loc);
    2297              : 
    2298           56 :   gimple *stmt = gimple_build_return (NULL);
    2299           56 :   gimple_set_location (stmt, stmt_loc);
    2300              : 
    2301           56 :   tree test_decl = build_decl (decl_loc, FUNCTION_DECL,
    2302              :                                get_identifier ("test_decl"),
    2303              :                                build_function_type_list (void_type_node,
    2304              :                                                          NULL_TREE));
    2305              : 
    2306           56 :   symbol_table_test tmp_symtab;
    2307              : 
    2308           56 :   cgraph_node *node = cgraph_node::get_create (test_decl);
    2309           56 :   gcc_assert (node);
    2310              : 
    2311              :   /* Run all tests twice, with and then without optinfo enabled, to ensure
    2312              :      that immediate destinations vs optinfo-based destinations both
    2313              :      work, independently of each other, with no leaks.  */
    2314          168 :   for (int i = 0 ; i < 2; i++)
    2315              :     {
    2316          112 :       bool with_optinfo = (i == 0);
    2317              : 
    2318              :       /* Test of dump_printf.  */
    2319          112 :       {
    2320          112 :         temp_dump_context tmp (with_optinfo, true,
    2321          112 :                                MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
    2322          112 :         dump_printf (MSG_NOTE, "int: %i str: %s", 42, "foo");
    2323          112 :         const int expected_impl_line = __LINE__ - 1;
    2324              : 
    2325          112 :         ASSERT_DUMPED_TEXT_EQ (tmp, "int: 42 str: foo");
    2326          112 :         if (with_optinfo)
    2327              :           {
    2328           56 :             optinfo *info = tmp.get_pending_optinfo ();
    2329           56 :             ASSERT_TRUE (info != NULL);
    2330           56 :             ASSERT_EQ (info->get_kind (), optinfo::kind::note);
    2331           56 :             ASSERT_EQ (info->num_items (), 1);
    2332           56 :             ASSERT_IS_TEXT (info->get_item (0), "int: 42 str: foo");
    2333           56 :             ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
    2334              :                                      "dumpfile.cc", expected_impl_line,
    2335              :                                      "test_capture_of_dump_calls");
    2336              :           }
    2337          112 :       }
    2338              : 
    2339              :       /* Test of dump_printf with %T.  */
    2340          112 :       {
    2341          112 :         temp_dump_context tmp (with_optinfo, true,
    2342          112 :                                MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
    2343          112 :         dump_printf (MSG_NOTE, "tree: %T", integer_zero_node);
    2344          112 :         const int expected_impl_line = __LINE__ - 1;
    2345              : 
    2346          112 :         ASSERT_DUMPED_TEXT_EQ (tmp, "tree: 0");
    2347          112 :         if (with_optinfo)
    2348              :           {
    2349           56 :             optinfo *info = tmp.get_pending_optinfo ();
    2350           56 :             ASSERT_TRUE (info != NULL);
    2351           56 :             ASSERT_EQ (info->get_kind (), optinfo::kind::note);
    2352           56 :             ASSERT_EQ (info->num_items (), 2);
    2353           56 :             ASSERT_IS_TEXT (info->get_item (0), "tree: ");
    2354           56 :             ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
    2355           56 :             ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
    2356              :                                      "dumpfile.cc", expected_impl_line,
    2357              :                                      "test_capture_of_dump_calls");
    2358              :           }
    2359          112 :       }
    2360              : 
    2361              :       /* Test of dump_printf with %E.  */
    2362          112 :       {
    2363          112 :         temp_dump_context tmp (with_optinfo, true,
    2364          112 :                                MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
    2365          112 :         dump_printf (MSG_NOTE, "gimple: %E", stmt);
    2366          112 :         const int expected_impl_line = __LINE__ - 1;
    2367              : 
    2368          112 :         ASSERT_DUMPED_TEXT_EQ (tmp, "gimple: return;");
    2369          112 :         if (with_optinfo)
    2370              :           {
    2371           56 :             optinfo *info = tmp.get_pending_optinfo ();
    2372           56 :             ASSERT_TRUE (info != NULL);
    2373           56 :             ASSERT_EQ (info->get_kind (), optinfo::kind::note);
    2374           56 :             ASSERT_EQ (info->num_items (), 2);
    2375           56 :             ASSERT_IS_TEXT (info->get_item (0), "gimple: ");
    2376           56 :             ASSERT_IS_GIMPLE (info->get_item (1), stmt_loc, "return;");
    2377           56 :             ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
    2378              :                                      "dumpfile.cc", expected_impl_line,
    2379              :                                      "test_capture_of_dump_calls");
    2380              :           }
    2381          112 :       }
    2382              : 
    2383              :       /* Test of dump_printf with %G.  */
    2384          112 :       {
    2385          112 :         temp_dump_context tmp (with_optinfo, true,
    2386          112 :                                MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
    2387          112 :         dump_printf (MSG_NOTE, "gimple: %G", stmt);
    2388          112 :         const int expected_impl_line = __LINE__ - 1;
    2389              : 
    2390          112 :         ASSERT_DUMPED_TEXT_EQ (tmp, "gimple: return;\n");
    2391          112 :         if (with_optinfo)
    2392              :           {
    2393           56 :             optinfo *info = tmp.get_pending_optinfo ();
    2394           56 :             ASSERT_TRUE (info != NULL);
    2395           56 :             ASSERT_EQ (info->get_kind (), optinfo::kind::note);
    2396           56 :             ASSERT_EQ (info->num_items (), 2);
    2397           56 :             ASSERT_IS_TEXT (info->get_item (0), "gimple: ");
    2398           56 :             ASSERT_IS_GIMPLE (info->get_item (1), stmt_loc, "return;\n");
    2399           56 :             ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
    2400              :                                      "dumpfile.cc", expected_impl_line,
    2401              :                                      "test_capture_of_dump_calls");
    2402              :           }
    2403          112 :       }
    2404              : 
    2405              :       /* Test of dump_printf with %C.  */
    2406          112 :       {
    2407          112 :         temp_dump_context tmp (with_optinfo, true,
    2408          112 :                                MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
    2409          112 :         dump_printf (MSG_NOTE, "node: %C", node);
    2410          112 :         const int expected_impl_line = __LINE__ - 1;
    2411              : 
    2412          112 :         ASSERT_DUMPED_TEXT_EQ (tmp, "node: test_decl/1");
    2413          112 :         if (with_optinfo)
    2414              :           {
    2415           56 :             optinfo *info = tmp.get_pending_optinfo ();
    2416           56 :             ASSERT_TRUE (info != NULL);
    2417           56 :             ASSERT_EQ (info->get_kind (), optinfo::kind::note);
    2418           56 :             ASSERT_EQ (info->num_items (), 2);
    2419           56 :             ASSERT_IS_TEXT (info->get_item (0), "node: ");
    2420           56 :             ASSERT_IS_SYMTAB_NODE (info->get_item (1), decl_loc, "test_decl/1");
    2421           56 :             ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
    2422              :                                      "dumpfile.cc", expected_impl_line,
    2423              :                                      "test_capture_of_dump_calls");
    2424              :           }
    2425          112 :       }
    2426              : 
    2427              :       /* dump_print_loc with multiple format codes.  This tests various
    2428              :          things:
    2429              :          - intermingling of text, format codes handled by the base
    2430              :          pretty_printer, and dump-specific format codes
    2431              :          - multiple dump-specific format codes: some consecutive, others
    2432              :          separated by text, trailing text after the final one.  */
    2433          112 :       {
    2434          112 :         temp_dump_context tmp (with_optinfo, true,
    2435          112 :                                MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
    2436          112 :         dump_printf_loc (MSG_NOTE, loc, "before %T and %T"
    2437              :                          " %i consecutive %E%E after\n",
    2438              :                          integer_zero_node, test_decl, 42, stmt, stmt);
    2439              : 
    2440          112 :         ASSERT_DUMPED_TEXT_EQ (tmp,
    2441              :                                "test.txt:5:10: note: before 0 and test_decl"
    2442              :                                " 42 consecutive return;return; after\n");
    2443          112 :         if (with_optinfo)
    2444              :           {
    2445           56 :             optinfo *info = tmp.get_pending_optinfo ();
    2446           56 :             ASSERT_TRUE (info != NULL);
    2447           56 :             ASSERT_EQ (info->get_kind (), optinfo::kind::note);
    2448           56 :             ASSERT_EQ (info->num_items (), 8);
    2449           56 :             ASSERT_IS_TEXT (info->get_item (0), "before ");
    2450           56 :             ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
    2451           56 :             ASSERT_IS_TEXT (info->get_item (2), " and ");
    2452           56 :             ASSERT_IS_TREE (info->get_item (3), UNKNOWN_LOCATION, "test_decl");
    2453           56 :             ASSERT_IS_TEXT (info->get_item (4), " 42 consecutive ");
    2454           56 :             ASSERT_IS_GIMPLE (info->get_item (5), stmt_loc, "return;");
    2455           56 :             ASSERT_IS_GIMPLE (info->get_item (6), stmt_loc, "return;");
    2456           56 :             ASSERT_IS_TEXT (info->get_item (7), " after\n");
    2457              :             /* We don't ASSERT_IMPL_LOCATION_EQ here, to avoid having to
    2458              :                enforce at which exact line the multiline dump_printf_loc
    2459              :                occurred.  */
    2460              :           }
    2461          112 :       }
    2462              : 
    2463              :       /* Tree, via dump_generic_expr.  */
    2464          112 :       {
    2465          112 :         temp_dump_context tmp (with_optinfo, true,
    2466          112 :                                MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
    2467          112 :         dump_printf_loc (MSG_NOTE, loc, "test of tree: ");
    2468          112 :         const int expected_impl_line = __LINE__ - 1;
    2469          112 :         dump_generic_expr (MSG_NOTE, TDF_SLIM, integer_zero_node);
    2470              : 
    2471          112 :         ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: test of tree: 0");
    2472          112 :         if (with_optinfo)
    2473              :           {
    2474           56 :             optinfo *info = tmp.get_pending_optinfo ();
    2475           56 :             ASSERT_TRUE (info != NULL);
    2476           56 :             ASSERT_EQ (info->get_location_t (), stmt_loc);
    2477           56 :             ASSERT_EQ (info->get_kind (), optinfo::kind::note);
    2478           56 :             ASSERT_EQ (info->num_items (), 2);
    2479           56 :             ASSERT_IS_TEXT (info->get_item (0), "test of tree: ");
    2480           56 :             ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
    2481           56 :             ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
    2482              :                                      "dumpfile.cc", expected_impl_line,
    2483              :                                      "test_capture_of_dump_calls");
    2484              :           }
    2485          112 :       }
    2486              : 
    2487              :       /* Tree, via dump_generic_expr_loc.  */
    2488          112 :       {
    2489          112 :         temp_dump_context tmp (with_optinfo, true,
    2490          112 :                                MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
    2491          112 :         dump_generic_expr_loc (MSG_NOTE, loc, TDF_SLIM, integer_one_node);
    2492          112 :         const int expected_impl_line = __LINE__ - 1;
    2493              : 
    2494          112 :         ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: 1");
    2495          112 :         if (with_optinfo)
    2496              :           {
    2497           56 :             optinfo *info = tmp.get_pending_optinfo ();
    2498           56 :             ASSERT_TRUE (info != NULL);
    2499           56 :             ASSERT_EQ (info->get_location_t (), stmt_loc);
    2500           56 :             ASSERT_EQ (info->get_kind (), optinfo::kind::note);
    2501           56 :             ASSERT_EQ (info->num_items (), 1);
    2502           56 :             ASSERT_IS_TREE (info->get_item (0), UNKNOWN_LOCATION, "1");
    2503           56 :             ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
    2504              :                                      "dumpfile.cc", expected_impl_line,
    2505              :                                      "test_capture_of_dump_calls");
    2506              :           }
    2507          112 :       }
    2508              : 
    2509              :       /* Gimple.  */
    2510          112 :       {
    2511              :         /* dump_gimple_stmt_loc.  */
    2512          112 :         {
    2513          112 :           temp_dump_context tmp (with_optinfo, true,
    2514          112 :                                  MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
    2515          112 :           dump_gimple_stmt_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 2);
    2516          112 :           const int expected_impl_line = __LINE__ - 1;
    2517              : 
    2518          112 :           ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: return;\n");
    2519          112 :           if (with_optinfo)
    2520              :             {
    2521           56 :               optinfo *info = tmp.get_pending_optinfo ();
    2522           56 :               ASSERT_TRUE (info != NULL);
    2523           56 :               ASSERT_EQ (info->num_items (), 1);
    2524           56 :               ASSERT_IS_GIMPLE (info->get_item (0), stmt_loc, "return;\n");
    2525           56 :               ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
    2526              :                                        "dumpfile.cc", expected_impl_line,
    2527              :                                        "test_capture_of_dump_calls");
    2528              :             }
    2529          112 :         }
    2530              : 
    2531              :         /* dump_gimple_stmt.  */
    2532          112 :         {
    2533          112 :           temp_dump_context tmp (with_optinfo, true,
    2534          112 :                                  MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
    2535          112 :           dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 2);
    2536          112 :           const int expected_impl_line = __LINE__ - 1;
    2537              : 
    2538          112 :           ASSERT_DUMPED_TEXT_EQ (tmp, "return;\n");
    2539          112 :           if (with_optinfo)
    2540              :             {
    2541           56 :               optinfo *info = tmp.get_pending_optinfo ();
    2542           56 :               ASSERT_TRUE (info != NULL);
    2543           56 :               ASSERT_EQ (info->num_items (), 1);
    2544           56 :               ASSERT_IS_GIMPLE (info->get_item (0), stmt_loc, "return;\n");
    2545           56 :               ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
    2546              :                                        "dumpfile.cc", expected_impl_line,
    2547              :                                        "test_capture_of_dump_calls");
    2548              :             }
    2549          112 :         }
    2550              : 
    2551              :         /* dump_gimple_expr_loc.  */
    2552          112 :         {
    2553          112 :           temp_dump_context tmp (with_optinfo, true,
    2554          112 :                                  MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
    2555          112 :           dump_gimple_expr_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 2);
    2556          112 :           const int expected_impl_line = __LINE__ - 1;
    2557              : 
    2558          112 :           ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: return;");
    2559          112 :           if (with_optinfo)
    2560              :             {
    2561           56 :               optinfo *info = tmp.get_pending_optinfo ();
    2562           56 :               ASSERT_TRUE (info != NULL);
    2563           56 :               ASSERT_EQ (info->num_items (), 1);
    2564           56 :               ASSERT_IS_GIMPLE (info->get_item (0), stmt_loc, "return;");
    2565           56 :               ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
    2566              :                                        "dumpfile.cc", expected_impl_line,
    2567              :                                        "test_capture_of_dump_calls");
    2568              :             }
    2569          112 :         }
    2570              : 
    2571              :         /* dump_gimple_expr.  */
    2572          112 :         {
    2573          112 :           temp_dump_context tmp (with_optinfo, true,
    2574          112 :                                  MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
    2575          112 :           dump_gimple_expr (MSG_NOTE, TDF_SLIM, stmt, 2);
    2576          112 :           const int expected_impl_line = __LINE__ - 1;
    2577              : 
    2578          112 :           ASSERT_DUMPED_TEXT_EQ (tmp, "return;");
    2579          112 :           if (with_optinfo)
    2580              :             {
    2581           56 :               optinfo *info = tmp.get_pending_optinfo ();
    2582           56 :               ASSERT_TRUE (info != NULL);
    2583           56 :               ASSERT_EQ (info->num_items (), 1);
    2584           56 :               ASSERT_IS_GIMPLE (info->get_item (0), stmt_loc, "return;");
    2585           56 :               ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
    2586              :                                        "dumpfile.cc", expected_impl_line,
    2587              :                                        "test_capture_of_dump_calls");
    2588              :             }
    2589          112 :         }
    2590              :       }
    2591              : 
    2592              :       /* symtab_node.  */
    2593          112 :       {
    2594          112 :         temp_dump_context tmp (with_optinfo, true,
    2595          112 :                                MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
    2596          112 :         dump_symtab_node (MSG_NOTE, node);
    2597          112 :         const int expected_impl_line = __LINE__ - 1;
    2598              : 
    2599          112 :         ASSERT_DUMPED_TEXT_EQ (tmp, "test_decl/1");
    2600          112 :         if (with_optinfo)
    2601              :           {
    2602           56 :             optinfo *info = tmp.get_pending_optinfo ();
    2603           56 :             ASSERT_TRUE (info != NULL);
    2604           56 :             ASSERT_EQ (info->get_kind (), optinfo::kind::note);
    2605           56 :             ASSERT_EQ (info->num_items (), 1);
    2606           56 :             ASSERT_IS_SYMTAB_NODE (info->get_item (0), decl_loc, "test_decl/1");
    2607           56 :             ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
    2608              :                                      "dumpfile.cc", expected_impl_line,
    2609              :                                      "test_capture_of_dump_calls");
    2610              :           }
    2611          112 :       }
    2612              : 
    2613              :       /* poly_int.  */
    2614          112 :       {
    2615          112 :         temp_dump_context tmp (with_optinfo, true,
    2616          112 :                                MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
    2617          112 :         dump_dec (MSG_NOTE, poly_int64 (42));
    2618          112 :         const int expected_impl_line = __LINE__ - 1;
    2619              : 
    2620          112 :         ASSERT_DUMPED_TEXT_EQ (tmp, "42");
    2621          112 :         if (with_optinfo)
    2622              :           {
    2623           56 :             optinfo *info = tmp.get_pending_optinfo ();
    2624           56 :             ASSERT_TRUE (info != NULL);
    2625           56 :             ASSERT_EQ (info->num_items (), 1);
    2626           56 :             ASSERT_IS_TEXT (info->get_item (0), "42");
    2627           56 :             ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
    2628              :                                      "dumpfile.cc", expected_impl_line,
    2629              :                                      "test_capture_of_dump_calls");
    2630              :           }
    2631          112 :       }
    2632              : 
    2633              :       /* Scopes.  Test with all 4 combinations of
    2634              :          filtering by MSG_PRIORITY_USER_FACING
    2635              :          and/or filtering by MSG_PRIORITY_INTERNALS.  */
    2636          448 :       for (int j = 0; j < 3; j++)
    2637              :         {
    2638          336 :           dump_flags_t dump_filter = MSG_ALL_KINDS;
    2639          336 :           if (j % 2)
    2640          112 :             dump_filter |= MSG_PRIORITY_USER_FACING;
    2641          336 :           if (j / 2)
    2642          112 :             dump_filter |= MSG_PRIORITY_INTERNALS;
    2643              : 
    2644          336 :           temp_dump_context tmp (with_optinfo, true, dump_filter);
    2645              :           /* Emit various messages, mostly with implicit priority.  */
    2646          336 :           dump_printf_loc (MSG_NOTE, stmt, "msg 1\n");
    2647          336 :           dump_printf_loc (MSG_NOTE | MSG_PRIORITY_INTERNALS, stmt,
    2648              :                            "explicitly internal msg\n");
    2649          336 :           {
    2650          336 :             AUTO_DUMP_SCOPE ("outer scope", stmt);
    2651          336 :             dump_printf_loc (MSG_NOTE, stmt, "msg 2\n");
    2652          336 :             {
    2653          336 :               AUTO_DUMP_SCOPE ("middle scope", stmt);
    2654          336 :               dump_printf_loc (MSG_NOTE, stmt, "msg 3\n");
    2655          336 :               {
    2656          336 :                 AUTO_DUMP_SCOPE ("inner scope", stmt);
    2657          336 :                 dump_printf_loc (MSG_NOTE, stmt, "msg 4\n");
    2658          336 :                 dump_printf_loc (MSG_NOTE | MSG_PRIORITY_USER_FACING, stmt,
    2659              :                                  "explicitly user-facing msg\n");
    2660              :               }
    2661          336 :               dump_printf_loc (MSG_NOTE, stmt, "msg 5\n");
    2662              :             }
    2663          336 :             dump_printf_loc (MSG_NOTE, stmt, "msg 6\n");
    2664              :           }
    2665          336 :           dump_printf_loc (MSG_NOTE, stmt, "msg 7\n");
    2666          336 :           const int expected_impl_line = __LINE__ - 1;
    2667              : 
    2668          336 :           switch (dump_filter & MSG_ALL_PRIORITIES)
    2669              :             {
    2670            0 :             default:
    2671            0 :               gcc_unreachable ();
    2672          112 :             case 0:
    2673          112 :               ASSERT_DUMPED_TEXT_EQ (tmp, "");
    2674          112 :               break;
    2675          112 :             case MSG_PRIORITY_USER_FACING:
    2676          112 :               ASSERT_DUMPED_TEXT_EQ
    2677              :                 (tmp,
    2678              :                  "test.txt:5:10: note: msg 1\n"
    2679              :                  "test.txt:5:10: note:    explicitly user-facing msg\n"
    2680              :                  "test.txt:5:10: note: msg 7\n");
    2681          112 :               break;
    2682          112 :             case MSG_PRIORITY_INTERNALS:
    2683          112 :               ASSERT_DUMPED_TEXT_EQ
    2684              :                 (tmp,
    2685              :                  "test.txt:5:10: note: explicitly internal msg\n"
    2686              :                  "test.txt:5:10: note:  === outer scope ===\n"
    2687              :                  "test.txt:5:10: note:  msg 2\n"
    2688              :                  "test.txt:5:10: note:   === middle scope ===\n"
    2689              :                  "test.txt:5:10: note:   msg 3\n"
    2690              :                  "test.txt:5:10: note:    === inner scope ===\n"
    2691              :                  "test.txt:5:10: note:    msg 4\n"
    2692              :                  "test.txt:5:10: note:   msg 5\n"
    2693              :                  "test.txt:5:10: note:  msg 6\n");
    2694          112 :               break;
    2695              :             case MSG_ALL_PRIORITIES:
    2696              :               ASSERT_DUMPED_TEXT_EQ
    2697              :                 (tmp,
    2698              :                  "test.txt:5:10: note: msg 1\n"
    2699              :                  "test.txt:5:10: note: explicitly internal msg\n"
    2700              :                  "test.txt:5:10: note: === outer scope ===\n"
    2701              :                  "test.txt:5:10: note:  msg 2\n"
    2702              :                  "test.txt:5:10: note:  === middle scope ===\n"
    2703              :                  "test.txt:5:10: note:   msg 3\n"
    2704              :                  "test.txt:5:10: note:   === inner scope ===\n"
    2705              :                  "test.txt:5:10: note:    msg 4\n"
    2706              :                  "test.txt:5:10: note:    explicitly user-facing msg\n"
    2707              :                  "test.txt:5:10: note:   msg 5\n"
    2708              :                  "test.txt:5:10: note:  msg 6\n"
    2709              :                  "test.txt:5:10: note: msg 7\n");
    2710              :               break;
    2711              :             }
    2712          336 :           if (with_optinfo)
    2713              :             {
    2714          168 :               optinfo *info = tmp.get_pending_optinfo ();
    2715          168 :               ASSERT_TRUE (info != NULL);
    2716          168 :               ASSERT_EQ (info->num_items (), 1);
    2717          168 :               ASSERT_IS_TEXT (info->get_item (0), "msg 7\n");
    2718          168 :               ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
    2719              :                                        "dumpfile.cc", expected_impl_line,
    2720              :                                        "test_capture_of_dump_calls");
    2721              :             }
    2722          336 :         }
    2723              :     }
    2724              : 
    2725              :   /* Verify that MSG_* affects optinfo->get_kind (); we tested MSG_NOTE
    2726              :      above.  */
    2727           56 :   {
    2728              :     /* MSG_OPTIMIZED_LOCATIONS.  */
    2729           56 :     {
    2730           56 :       temp_dump_context tmp (true, true, MSG_ALL_KINDS);
    2731           56 :       dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc, "test");
    2732           56 :       ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (),
    2733              :                  optinfo::kind::success);
    2734           56 :     }
    2735              : 
    2736              :     /* MSG_MISSED_OPTIMIZATION.  */
    2737           56 :     {
    2738           56 :       temp_dump_context tmp (true, true, MSG_ALL_KINDS);
    2739           56 :       dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc, "test");
    2740           56 :       ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (),
    2741              :                  optinfo::kind::failure);
    2742           56 :     }
    2743              :   }
    2744              : 
    2745              :   /* Verify that MSG_* affect AUTO_DUMP_SCOPE and the dump calls.  */
    2746           56 :   {
    2747           56 :     temp_dump_context tmp (false, true,
    2748           56 :                            MSG_OPTIMIZED_LOCATIONS | MSG_ALL_PRIORITIES);
    2749           56 :     dump_printf_loc (MSG_NOTE, stmt, "msg 1\n");
    2750           56 :     {
    2751           56 :       AUTO_DUMP_SCOPE ("outer scope", stmt);
    2752           56 :       dump_printf_loc (MSG_NOTE, stmt, "msg 2\n");
    2753           56 :       {
    2754           56 :         AUTO_DUMP_SCOPE ("middle scope", stmt);
    2755           56 :         dump_printf_loc (MSG_NOTE, stmt, "msg 3\n");
    2756           56 :         {
    2757           56 :           AUTO_DUMP_SCOPE ("inner scope", stmt);
    2758           56 :           dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, stmt, "msg 4\n");
    2759              :         }
    2760           56 :         dump_printf_loc (MSG_NOTE, stmt, "msg 5\n");
    2761              :       }
    2762           56 :       dump_printf_loc (MSG_NOTE, stmt, "msg 6\n");
    2763              :     }
    2764           56 :     dump_printf_loc (MSG_NOTE, stmt, "msg 7\n");
    2765              : 
    2766           56 :     ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: optimized:    msg 4\n");
    2767           56 :   }
    2768           96 : }
    2769              : 
    2770              : static void
    2771            4 : test_pr87025 ()
    2772              : {
    2773            4 :   dump_user_location_t loc
    2774            4 :     = dump_user_location_t::from_location_t (UNKNOWN_LOCATION);
    2775              : 
    2776            4 :   temp_dump_context tmp (true, true,
    2777            4 :                          MSG_ALL_KINDS | MSG_PRIORITY_USER_FACING);
    2778            4 :   {
    2779            4 :     AUTO_DUMP_SCOPE ("outer scope", loc);
    2780            4 :     dump_printf (MSG_NOTE, "msg1\n");
    2781              :   }
    2782            4 : }
    2783              : 
    2784              : /* Run all of the selftests within this file.  */
    2785              : 
    2786              : void
    2787            4 : dumpfile_cc_tests ()
    2788              : {
    2789            4 :   test_impl_location ();
    2790            4 :   for_each_line_table_case (test_capture_of_dump_calls);
    2791            4 :   test_pr87025 ();
    2792            4 : }
    2793              : 
    2794              : } // namespace selftest
    2795              : 
    2796              : #endif /* CHECKING_P */
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.