LCOV - code coverage report
Current view: top level - gcc - coverage.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 89.9 % 631 567
Test Date: 2026-02-28 14:20:25 Functions: 96.4 % 28 27
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Read and write coverage files, and associated functionality.
       2              :    Copyright (C) 1990-2026 Free Software Foundation, Inc.
       3              :    Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
       4              :    based on some ideas from Dain Samples of UC Berkeley.
       5              :    Further mangling by Bob Manson, Cygnus Support.
       6              :    Further mangled by Nathan Sidwell, CodeSourcery
       7              : 
       8              : This file is part of GCC.
       9              : 
      10              : GCC is free software; you can redistribute it and/or modify it under
      11              : the terms of the GNU General Public License as published by the Free
      12              : Software Foundation; either version 3, or (at your option) any later
      13              : version.
      14              : 
      15              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      16              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      17              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      18              : for more details.
      19              : 
      20              : You should have received a copy of the GNU General Public License
      21              : along with GCC; see the file COPYING3.  If not see
      22              : <http://www.gnu.org/licenses/>.  */
      23              : 
      24              : 
      25              : #define GCOV_LINKAGE
      26              : 
      27              : #include "config.h"
      28              : #include "system.h"
      29              : #include "coretypes.h"
      30              : #include "backend.h"
      31              : #include "target.h"
      32              : #include "rtl.h"
      33              : #include "tree.h"
      34              : #include "tree-pass.h"
      35              : #include "memmodel.h"
      36              : #include "tm_p.h"
      37              : #include "stringpool.h"
      38              : #include "cgraph.h"
      39              : #include "coverage.h"
      40              : #include "diagnostic-core.h"
      41              : #include "fold-const.h"
      42              : #include "stor-layout.h"
      43              : #include "output.h"
      44              : #include "toplev.h"
      45              : #include "langhooks.h"
      46              : #include "tree-iterator.h"
      47              : #include "context.h"
      48              : #include "pass_manager.h"
      49              : #include "intl.h"
      50              : #include "auto-profile.h"
      51              : #include "profile.h"
      52              : #include "diagnostic.h"
      53              : #include "varasm.h"
      54              : #include "file-prefix-map.h"
      55              : 
      56              : #include "gcov-io.cc"
      57              : 
      58              : struct GTY((chain_next ("%h.next"))) coverage_data
      59              : {
      60              :   struct coverage_data *next;    /* next function */
      61              :   unsigned ident;                /* function ident */
      62              :   unsigned lineno_checksum;      /* function lineno checksum */
      63              :   unsigned cfg_checksum;         /* function cfg checksum */
      64              :   tree fn_decl;                  /* the function decl */
      65              :   tree ctr_vars[GCOV_COUNTERS];  /* counter variables.  */
      66              : };
      67              : 
      68              : /* Counts information for a function.  */
      69              : struct counts_entry : pointer_hash <counts_entry>
      70              : {
      71              :   /* We hash by  */
      72              :   unsigned ident;
      73              :   unsigned ctr;
      74              : 
      75              :   /* Store  */
      76              :   unsigned lineno_checksum;
      77              :   unsigned cfg_checksum;
      78              :   gcov_type *counts;
      79              :   unsigned n_counts;
      80              : 
      81              :   /* hash_table support.  */
      82              :   static inline hashval_t hash (const counts_entry *);
      83              :   static int equal (const counts_entry *, const counts_entry *);
      84              :   static void remove (counts_entry *);
      85              : };
      86              : 
      87              : static GTY(()) struct coverage_data *functions_head = 0;
      88              : static struct coverage_data **functions_tail = &functions_head;
      89              : static unsigned no_coverage = 0;
      90              : 
      91              : /* Cumulative counter information for whole program.  */
      92              : static unsigned prg_ctr_mask; /* Mask of counter types generated.  */
      93              : 
      94              : /* Counter information for current function.  */
      95              : static unsigned fn_ctr_mask; /* Mask of counters used.  */
      96              : static GTY(()) tree fn_v_ctrs[GCOV_COUNTERS];   /* counter variables.  */
      97              : static unsigned fn_n_ctrs[GCOV_COUNTERS]; /* Counters allocated.  */
      98              : static unsigned fn_b_ctrs[GCOV_COUNTERS]; /* Allocation base.  */
      99              : 
     100              : /* Coverage info VAR_DECL and function info type nodes.  */
     101              : static GTY(()) tree gcov_info_var;
     102              : static GTY(()) tree gcov_fn_info_type;
     103              : static GTY(()) tree gcov_fn_info_ptr_type;
     104              : 
     105              : /* Name of the notes (gcno) output file.  The "bbg" prefix is for
     106              :    historical reasons, when the notes file contained only the
     107              :    basic block graph notes.
     108              :    If this is NULL we're not writing to the notes file.  */
     109              : static char *bbg_file_name;
     110              : 
     111              : /* File stamp for notes file.  */
     112              : static unsigned bbg_file_stamp;
     113              : 
     114              : /* Name of the count data (gcda) file.  */
     115              : static char *da_file_name;
     116              : 
     117              : /* The names of merge functions for counters.  */
     118              : #define STR(str) #str
     119              : #define DEF_GCOV_COUNTER(COUNTER, NAME, FN_TYPE) STR(__gcov_merge ## FN_TYPE),
     120              : static const char *const ctr_merge_functions[GCOV_COUNTERS] = {
     121              : #include "gcov-counter.def"
     122              : };
     123              : #undef DEF_GCOV_COUNTER
     124              : #undef STR
     125              : 
     126              : #define DEF_GCOV_COUNTER(COUNTER, NAME, FN_TYPE) NAME,
     127              : static const char *const ctr_names[GCOV_COUNTERS] = {
     128              : #include "gcov-counter.def"
     129              : };
     130              : #undef DEF_GCOV_COUNTER
     131              : 
     132              : /* Forward declarations.  */
     133              : static tree build_var (tree, tree, int);
     134              : 
     135              : /* Return the type node for gcov_type.  */
     136              : 
     137              : tree
     138        18425 : get_gcov_type (void)
     139              : {
     140        18425 :   scalar_int_mode mode
     141              :     = smallest_int_mode_for_size
     142        18425 :       (LONG_LONG_TYPE_SIZE > 32 ? 64 : 32).require ();
     143        18425 :   return lang_hooks.types.type_for_mode (mode, false);
     144              : }
     145              : 
     146              : /* Return the type node for gcov_unsigned_t.  */
     147              : 
     148              : static tree
     149        12680 : get_gcov_unsigned_t (void)
     150              : {
     151        12680 :   scalar_int_mode mode = smallest_int_mode_for_size (32).require ();
     152        12680 :   return lang_hooks.types.type_for_mode (mode, true);
     153              : }
     154              : 
     155              : inline hashval_t
     156        11060 : counts_entry::hash (const counts_entry *entry)
     157              : {
     158        11060 :   return entry->ident * GCOV_COUNTERS + entry->ctr;
     159              : }
     160              : 
     161              : inline int
     162         9927 : counts_entry::equal (const counts_entry *entry1, const counts_entry *entry2)
     163              : {
     164         9927 :   return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
     165              : }
     166              : 
     167              : inline void
     168            0 : counts_entry::remove (counts_entry *entry)
     169              : {
     170            0 :   free (entry->counts);
     171            0 :   free (entry);
     172            0 : }
     173              : 
     174              : /* Hash table of count data.  */
     175              : static hash_table<counts_entry> *counts_hash;
     176              : 
     177              : /* Read in the counts file, if available.  */
     178              : 
     179              : static void
     180          166 : read_counts_file (void)
     181              : {
     182          166 :   gcov_unsigned_t fn_ident = 0;
     183          166 :   gcov_unsigned_t tag;
     184          166 :   int is_error = 0;
     185          166 :   unsigned lineno_checksum = 0;
     186          166 :   unsigned cfg_checksum = 0;
     187              : 
     188          166 :   if (!gcov_open (da_file_name, 1))
     189              :     return;
     190              : 
     191          115 :   if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
     192              :     {
     193            0 :       warning (0, "%qs is not a gcov data file", da_file_name);
     194            0 :       gcov_close ();
     195            0 :       return;
     196              :     }
     197          115 :   else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
     198              :     {
     199            0 :       char v[4], e[4];
     200              : 
     201            0 :       GCOV_UNSIGNED2STRING (v, tag);
     202            0 :       GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
     203              : 
     204            0 :       warning (0, "%qs is version %q.*s, expected version %q.*s",
     205              :                da_file_name, 4, v, 4, e);
     206            0 :       gcov_close ();
     207            0 :       return;
     208              :     }
     209              : 
     210              :   /* Read the stamp, used for creating a generation count.  */
     211          115 :   tag = gcov_read_unsigned ();
     212          115 :   bbg_file_stamp = crc32_unsigned (bbg_file_stamp, tag);
     213              : 
     214              :   /* Read checksum.  */
     215          115 :   gcov_read_unsigned ();
     216              : 
     217          115 :   counts_hash = new hash_table<counts_entry> (10);
     218         1770 :   while ((tag = gcov_read_unsigned ()))
     219              :     {
     220         1655 :       gcov_unsigned_t length;
     221         1655 :       gcov_position_t offset;
     222              : 
     223         1655 :       length = gcov_read_unsigned ();
     224         1655 :       offset = gcov_position ();
     225         1655 :       if (tag == GCOV_TAG_FUNCTION)
     226              :         {
     227          484 :           if (length)
     228              :             {
     229          484 :               fn_ident = gcov_read_unsigned ();
     230          484 :               lineno_checksum = gcov_read_unsigned ();
     231          484 :               cfg_checksum = gcov_read_unsigned ();
     232              :             }
     233              :           else
     234              :             fn_ident = lineno_checksum = cfg_checksum = 0;
     235              :         }
     236         1171 :       else if (tag == GCOV_TAG_OBJECT_SUMMARY)
     237              :         {
     238          115 :           gcov_profile_info = profile_info = XCNEW (gcov_summary);
     239          115 :           profile_info->runs = gcov_read_unsigned ();
     240          115 :           profile_info->sum_max = gcov_read_unsigned ();
     241          115 :           profile_info->cutoff = 1;
     242              :         }
     243         1056 :       else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
     244              :         {
     245         1056 :           counts_entry **slot, *entry, elt;
     246         1056 :           int read_length = (int)length;
     247         1056 :           length = read_length > 0 ? read_length : 0;
     248         1056 :           unsigned n_counts = GCOV_TAG_COUNTER_NUM (abs (read_length));
     249         1056 :           unsigned ix;
     250              : 
     251         1056 :           elt.ident = fn_ident;
     252         1056 :           elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
     253              : 
     254         1056 :           slot = counts_hash->find_slot (&elt, INSERT);
     255         1056 :           entry = *slot;
     256         1056 :           if (!entry)
     257              :             {
     258         1056 :               *slot = entry = XCNEW (counts_entry);
     259         1056 :               entry->ident = fn_ident;
     260         1056 :               entry->ctr = elt.ctr;
     261         1056 :               entry->lineno_checksum = lineno_checksum;
     262         1056 :               entry->cfg_checksum = cfg_checksum;
     263         1056 :               entry->counts = XCNEWVEC (gcov_type, n_counts);
     264         1056 :               entry->n_counts = n_counts;
     265              :             }
     266            0 :           else if (entry->lineno_checksum != lineno_checksum
     267            0 :                    || entry->cfg_checksum != cfg_checksum)
     268              :             {
     269            0 :               error ("profile data for function %u is corrupted", fn_ident);
     270            0 :               error ("checksum is (%x,%x) instead of (%x,%x)",
     271              :                      entry->lineno_checksum, entry->cfg_checksum,
     272              :                      lineno_checksum, cfg_checksum);
     273            0 :               delete counts_hash;
     274            0 :               counts_hash = NULL;
     275            0 :               break;
     276              :             }
     277         1056 :           if (read_length > 0)
     278         2854 :             for (ix = 0; ix != n_counts; ix++)
     279         2136 :               entry->counts[ix] = gcov_read_counter ();
     280              :         }
     281         1655 :       gcov_sync (offset, length);
     282         1655 :       if ((is_error = gcov_is_error ()))
     283              :         {
     284            0 :           error (is_error < 0
     285              :                  ? G_("%qs has overflowed")
     286              :                  : G_("%qs is corrupted"),
     287              :                  da_file_name);
     288            0 :           delete counts_hash;
     289            0 :           counts_hash = NULL;
     290            0 :           break;
     291              :         }
     292              :     }
     293              : 
     294          115 :   gcov_close ();
     295              : }
     296              : 
     297              : /* Returns the counters for a particular tag.  */
     298              : 
     299              : gcov_type *
     300         1130 : get_coverage_counts (unsigned counter, unsigned cfg_checksum,
     301              :                      unsigned lineno_checksum, unsigned int n_counts)
     302              : {
     303         1130 :   counts_entry *entry, elt;
     304              : 
     305              :   /* No hash table, no counts.  */
     306         1130 :   if (!counts_hash)
     307              :     {
     308          189 :       static int warned = 0;
     309              : 
     310          189 :       if (!warned++)
     311              :         {
     312           47 :           warning (OPT_Wmissing_profile,
     313              :                    "%qs profile count data file not found",
     314              :                    da_file_name);
     315           47 :           if (dump_enabled_p ())
     316              :             {
     317            6 :               dump_user_location_t loc
     318            6 :                 = dump_user_location_t::from_location_t (input_location);
     319            6 :               dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
     320              :                                "file %s not found, %s\n", da_file_name,
     321            6 :                                (flag_guess_branch_prob
     322              :                                 ? "execution counts estimated"
     323              :                                 : "execution counts assumed to be zero"));
     324              :             }
     325              :         }
     326          189 :       return NULL;
     327              :     }
     328          941 :   if (param_profile_func_internal_id)
     329            0 :     elt.ident = current_function_funcdef_no + 1;
     330              :   else
     331              :     {
     332          941 :       gcc_assert (coverage_node_map_initialized_p ());
     333          941 :       elt.ident = cgraph_node::get (current_function_decl)->profile_id;
     334              :     }
     335          941 :   elt.ctr = counter;
     336          941 :   entry = counts_hash->find (&elt);
     337          941 :   if (!entry)
     338              :     {
     339           21 :       if (counter == GCOV_COUNTER_ARCS)
     340            1 :         warning_at (DECL_SOURCE_LOCATION (current_function_decl),
     341            1 :                     OPT_Wmissing_profile,
     342              :                     "profile for function %qD not found in profile data",
     343              :                     current_function_decl);
     344              :       /* The function was not emitted, or is weak and not chosen in the
     345              :          final executable.  Silently fail, because there's nothing we
     346              :          can do about it.  */
     347           21 :       return NULL;
     348              :     }
     349              : 
     350          920 :   if (entry->cfg_checksum != cfg_checksum
     351          918 :       || (counter != GCOV_COUNTER_V_INDIR
     352          918 :           && counter != GCOV_COUNTER_V_TOPN
     353          851 :           && entry->n_counts != n_counts))
     354              :     {
     355            2 :       static int warned = 0;
     356            2 :       bool warning_printed = false;
     357              : 
     358            2 :       if (entry->n_counts != n_counts)
     359            1 :         warning_printed =
     360            1 :           warning_at (DECL_SOURCE_LOCATION (current_function_decl),
     361            1 :                       OPT_Wcoverage_mismatch,
     362              :                       "number of counters in profile data for function %qD "
     363              :                       "does not match "
     364              :                       "its profile data (counter %qs, expected %i and have %i)",
     365              :                       current_function_decl,
     366            1 :                       ctr_names[counter], entry->n_counts, n_counts);
     367              :       else
     368            1 :         warning_printed =
     369            1 :           warning_at (DECL_SOURCE_LOCATION (current_function_decl),
     370            1 :                       OPT_Wcoverage_mismatch,
     371              :                       "the control flow of function %qD does not match "
     372              :                       "its profile data (counter %qs)", current_function_decl,
     373            1 :                       ctr_names[counter]);
     374            2 :       if (warning_printed && dump_enabled_p ())
     375              :         {
     376            0 :           dump_user_location_t loc
     377            0 :             = dump_user_location_t::from_function_decl (current_function_decl);
     378            0 :           dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
     379              :                            "use -Wno-error=coverage-mismatch to tolerate "
     380              :                            "the mismatch but performance may drop if the "
     381              :                            "function is hot\n");
     382              : 
     383            0 :           if (!seen_error ()
     384            0 :               && !warned++)
     385              :             {
     386            0 :               dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
     387              :                                "coverage mismatch ignored\n");
     388            0 :               dump_printf (MSG_MISSED_OPTIMIZATION,
     389            0 :                            flag_guess_branch_prob
     390              :                            ? G_("execution counts estimated\n")
     391              :                            : G_("execution counts assumed to be zero\n"));
     392            0 :               if (!flag_guess_branch_prob)
     393            0 :                 dump_printf (MSG_MISSED_OPTIMIZATION,
     394              :                              "this can result in poorly optimized code\n");
     395              :             }
     396              :         }
     397              : 
     398            2 :       return NULL;
     399              :     }
     400          918 :   else if (entry->lineno_checksum != lineno_checksum)
     401              :     {
     402            8 :       warning_at (DECL_SOURCE_LOCATION (current_function_decl),
     403            8 :                   OPT_Wcoverage_mismatch,
     404              :                   "source locations for function %qD have changed,"
     405              :                   " the profile data may be out of date",
     406              :                   current_function_decl);
     407              :     }
     408              : 
     409          918 :   return entry->counts;
     410              : }
     411              : 
     412              : /* Allocate NUM counters of type COUNTER. Returns nonzero if the
     413              :    allocation succeeded.  */
     414              : 
     415              : int
     416         2870 : coverage_counter_alloc (unsigned counter, unsigned num)
     417              : {
     418         2870 :   if (no_coverage)
     419              :     return 0;
     420              : 
     421         2870 :   if (!num)
     422              :     return 1;
     423              : 
     424         2844 :   if (!fn_v_ctrs[counter])
     425              :     {
     426         2840 :       tree array_type = build_array_type (get_gcov_type (), NULL_TREE);
     427              : 
     428         2840 :       fn_v_ctrs[counter]
     429         2840 :         = build_var (current_function_decl, array_type, counter);
     430              :     }
     431              : 
     432         2844 :   fn_b_ctrs[counter] = fn_n_ctrs[counter];
     433         2844 :   fn_n_ctrs[counter] += num;
     434              : 
     435         2844 :   fn_ctr_mask |= 1 << counter;
     436         2844 :   return 1;
     437              : }
     438              : 
     439              : /* Generate a tree to access COUNTER NO.  */
     440              : 
     441              : tree
     442         8958 : tree_coverage_counter_ref (unsigned counter, unsigned no)
     443              : {
     444         8958 :   tree gcov_type_node = get_gcov_type ();
     445              : 
     446         8958 :   gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
     447              : 
     448         8958 :   no += fn_b_ctrs[counter];
     449              : 
     450              :   /* "no" here is an array index, scaled to bytes later.  */
     451         8958 :   return build4 (ARRAY_REF, gcov_type_node, fn_v_ctrs[counter],
     452         8958 :                  build_int_cst (integer_type_node, no), NULL, NULL);
     453              : }
     454              : 
     455              : /* Generate a tree to access the address of COUNTER NO.  */
     456              : 
     457              : tree
     458          154 : tree_coverage_counter_addr (unsigned counter, unsigned no)
     459              : {
     460          154 :   tree gcov_type_node = get_gcov_type ();
     461              : 
     462          154 :   gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
     463          154 :   no += fn_b_ctrs[counter];
     464              : 
     465              :   /* "no" here is an array index, scaled to bytes later.  */
     466          154 :   return build_fold_addr_expr (build4 (ARRAY_REF, gcov_type_node,
     467              :                                        fn_v_ctrs[counter],
     468              :                                        build_int_cst (integer_type_node, no),
     469              :                                        NULL, NULL));
     470              : }
     471              : 
     472              : 
     473              : /* Generate a checksum for a string.  CHKSUM is the current
     474              :    checksum.  */
     475              : 
     476              : static unsigned
     477         8071 : coverage_checksum_string (unsigned chksum, const char *string)
     478              : {
     479         8071 :   int i;
     480         8071 :   char *dup = NULL;
     481              : 
     482              :   /* Look for everything that looks if it were produced by
     483              :      get_file_function_name and zero out the second part
     484              :      that may result from flag_random_seed.  This is not critical
     485              :      as the checksums are used only for sanity checking.  */
     486       334624 :   for (i = 0; string[i]; i++)
     487              :     {
     488       326625 :       int offset = 0;
     489       326625 :       if (startswith (string + i, "_GLOBAL__N_"))
     490           28 :       offset = 11;
     491       326625 :       if (startswith (string + i, "_GLOBAL__"))
     492              :       offset = 9;
     493              : 
     494              :       /* C++ namespaces do have scheme:
     495              :          _GLOBAL__N_<filename>_<wrongmagicnumber>_<magicnumber>functionname
     496              :        since filename might contain extra underscores there seems
     497              :        to be no better chance then walk all possible offsets looking
     498              :        for magicnumber.  */
     499       326553 :       if (offset)
     500              :         {
     501          770 :           for (i = i + offset; string[i]; i++)
     502          698 :             if (string[i]=='_')
     503              :               {
     504              :                 int y;
     505              : 
     506          164 :                 for (y = 1; y < 9; y++)
     507          164 :                   if (!(string[i + y] >= '0' && string[i + y] <= '9')
     508          128 :                       && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
     509              :                     break;
     510          126 :                 if (y != 9 || string[i + 9] != '_')
     511          126 :                   continue;
     512            0 :                 for (y = 10; y < 18; y++)
     513            0 :                   if (!(string[i + y] >= '0' && string[i + y] <= '9')
     514            0 :                       && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
     515              :                     break;
     516            0 :                 if (y != 18)
     517            0 :                   continue;
     518            0 :                 if (!dup)
     519            0 :                   string = dup = xstrdup (string);
     520            0 :                 for (y = 10; y < 18; y++)
     521            0 :                   dup[i + y] = '0';
     522              :               }
     523              :           break;
     524              :         }
     525              :     }
     526              : 
     527         8071 :   chksum = crc32_string (chksum, string);
     528         8071 :   free (dup);
     529              : 
     530         8071 :   return chksum;
     531              : }
     532              : 
     533              : /* Compute checksum for the current function.  We generate a CRC32.  */
     534              : 
     535              : unsigned
     536         2539 : coverage_compute_lineno_checksum (void)
     537              : {
     538         2539 :   expanded_location xloc
     539         2539 :     = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
     540         2539 :   unsigned chksum = xloc.line;
     541              : 
     542         2539 :   if (xloc.file)
     543         2539 :     chksum = coverage_checksum_string (chksum, xloc.file);
     544         2539 :   chksum = coverage_checksum_string
     545         2539 :     (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
     546              : 
     547         2539 :   return chksum;
     548              : }
     549              : 
     550              : /* Compute profile ID.  This is better to be unique in whole program.  */
     551              : 
     552              : unsigned
     553         2565 : coverage_compute_profile_id (struct cgraph_node *n)
     554              : {
     555         2565 :   unsigned chksum;
     556              : 
     557              :   /* Externally visible symbols have unique name.  */
     558         2565 :   if (TREE_PUBLIC (n->decl) || DECL_EXTERNAL (n->decl) || n->unique_name)
     559              :     {
     560         2351 :       chksum = coverage_checksum_string
     561         2351 :         (0, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (n->decl)));
     562              :     }
     563              :   else
     564              :     {
     565          214 :       expanded_location xloc
     566          214 :         = expand_location (DECL_SOURCE_LOCATION (n->decl));
     567          214 :       bool use_name_only = (param_profile_func_internal_id == 0);
     568              : 
     569          214 :       chksum = (use_name_only ? 0 : xloc.line);
     570          214 :       if (xloc.file)
     571          214 :         chksum = coverage_checksum_string (chksum, xloc.file);
     572          214 :       chksum = coverage_checksum_string
     573          214 :         (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (n->decl)));
     574          214 :       if (!use_name_only && first_global_object_name)
     575            0 :         chksum = coverage_checksum_string
     576            0 :           (chksum, first_global_object_name);
     577          214 :       char *base_name = xstrdup (aux_base_name);
     578          214 :       if (endswith (base_name, ".gk"))
     579            1 :         base_name[strlen (base_name) - 3] = '\0';
     580          214 :       chksum = coverage_checksum_string (chksum, base_name);
     581          214 :       free (base_name);
     582              :     }
     583              : 
     584              :   /* Non-negative integers are hopefully small enough to fit in all targets.
     585              :      Gcov file formats wants non-zero function IDs.  */
     586         2565 :   chksum = chksum & 0x7fffffff;
     587         2565 :   return chksum + (!chksum);
     588              : }
     589              : 
     590              : /* Compute cfg checksum for the function FN given as argument.
     591              :    The checksum is calculated carefully so that
     592              :    source code changes that doesn't affect the control flow graph
     593              :    won't change the checksum.
     594              :    This is to make the profile data useable across source code change.
     595              :    The downside of this is that the compiler may use potentially
     596              :    wrong profile data - that the source code change has non-trivial impact
     597              :    on the validity of profile data (e.g. the reversed condition)
     598              :    but the compiler won't detect the change and use the wrong profile data.  */
     599              : 
     600              : unsigned
     601      1089591 : coverage_compute_cfg_checksum (struct function *fn)
     602              : {
     603      1089591 :   basic_block bb;
     604      1089591 :   unsigned chksum = n_basic_blocks_for_fn (fn);
     605              : 
     606      7704600 :   FOR_EACH_BB_FN (bb, fn)
     607              :     {
     608      6615009 :       edge e;
     609      6615009 :       edge_iterator ei;
     610      6615009 :       chksum = crc32_byte (chksum, bb->index);
     611     15385215 :       FOR_EACH_EDGE (e, ei, bb->succs)
     612              :         {
     613      8770206 :           chksum = crc32_byte (chksum, e->dest->index);
     614              :         }
     615              :     }
     616              : 
     617      1089591 :   return chksum;
     618              : }
     619              : 
     620              : /* Begin output to the notes file for the current function.
     621              :    Writes the function header. Returns nonzero if data should be output.  */
     622              : 
     623              : int
     624         2546 : coverage_begin_function (unsigned lineno_checksum, unsigned cfg_checksum)
     625              : {
     626              :   /* We don't need to output .gcno file unless we're under -ftest-coverage
     627              :      (e.g. -fprofile-arcs/generate/use don't need .gcno to work). */
     628         2546 :   if (no_coverage || !bbg_file_name)
     629              :     return 0;
     630              : 
     631         1076 :   expanded_location startloc
     632         1076 :     = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
     633              : 
     634              :   /* Announce function */
     635         1076 :   unsigned long offset = gcov_write_tag (GCOV_TAG_FUNCTION);
     636         1076 :   if (param_profile_func_internal_id)
     637            0 :     gcov_write_unsigned (current_function_funcdef_no + 1);
     638              :   else
     639              :     {
     640         1076 :       gcc_assert (coverage_node_map_initialized_p ());
     641         2152 :       gcov_write_unsigned (
     642         1076 :         cgraph_node::get (current_function_decl)->profile_id);
     643              :     }
     644              : 
     645         1076 :   gcov_write_unsigned (lineno_checksum);
     646         1076 :   gcov_write_unsigned (cfg_checksum);
     647         1076 :   gcov_write_string (IDENTIFIER_POINTER
     648              :                      (DECL_ASSEMBLER_NAME (current_function_decl)));
     649         2152 :   gcov_write_unsigned (DECL_ARTIFICIAL (current_function_decl)
     650           53 :                        && !DECL_FUNCTION_VERSIONED (current_function_decl)
     651         1129 :                        && !DECL_LAMBDA_FUNCTION_P (current_function_decl));
     652         1076 :   gcov_write_filename (remap_profile_filename (startloc.file));
     653         1076 :   gcov_write_unsigned (startloc.line);
     654         1076 :   gcov_write_unsigned (startloc.column);
     655              : 
     656         1076 :   expanded_location endloc = expand_location (cfun->function_end_locus);
     657              : 
     658              :   /* Function can start in a single file and end in another one.  */
     659         1076 :   int end_line
     660         1076 :     = endloc.file == startloc.file ? endloc.line : startloc.line;
     661         1076 :   int end_column
     662         1076 :     = endloc.file == startloc.file ? endloc.column : startloc.column;
     663              : 
     664         1076 :   if (startloc.line > end_line)
     665              :     {
     666            1 :       warning_at (DECL_SOURCE_LOCATION (current_function_decl),
     667            1 :                   OPT_Wcoverage_invalid_line_number,
     668              :                   "function starts on a higher line number than it ends");
     669            1 :       end_line = startloc.line;
     670            1 :       end_column = startloc.column;
     671              :     }
     672              : 
     673         1076 :   gcov_write_unsigned (end_line);
     674         1076 :   gcov_write_unsigned (end_column);
     675         1076 :   gcov_write_length (offset);
     676              : 
     677         1076 :   return !gcov_is_error ();
     678              : }
     679              : 
     680              : /* Finish coverage data for the current function. Verify no output
     681              :    error has occurred.  Save function coverage counts.  */
     682              : 
     683              : void
     684         2546 : coverage_end_function (unsigned lineno_checksum, unsigned cfg_checksum)
     685              : {
     686         2546 :   unsigned i;
     687              : 
     688         2546 :   if (bbg_file_name && gcov_is_error ())
     689              :     {
     690            0 :       warning (0, "error writing %qs", bbg_file_name);
     691            0 :       unlink (bbg_file_name);
     692            0 :       bbg_file_name = NULL;
     693              :     }
     694              : 
     695         2546 :   if (fn_ctr_mask)
     696              :     {
     697         1950 :       struct coverage_data *item = 0;
     698              : 
     699         1950 :       item = ggc_alloc<coverage_data> ();
     700              : 
     701         1950 :       if (param_profile_func_internal_id)
     702            0 :         item->ident = current_function_funcdef_no + 1;
     703              :       else
     704              :         {
     705         1950 :           gcc_assert (coverage_node_map_initialized_p ());
     706         1950 :           item->ident = cgraph_node::get (cfun->decl)->profile_id;
     707              :         }
     708              : 
     709         1950 :       item->lineno_checksum = lineno_checksum;
     710         1950 :       item->cfg_checksum = cfg_checksum;
     711              : 
     712         1950 :       item->fn_decl = current_function_decl;
     713         1950 :       item->next = 0;
     714         1950 :       *functions_tail = item;
     715         1950 :       functions_tail = &item->next;
     716              : 
     717        21450 :       for (i = 0; i != GCOV_COUNTERS; i++)
     718              :         {
     719        19500 :           tree var = fn_v_ctrs[i];
     720              : 
     721        19500 :           if (item)
     722        19500 :             item->ctr_vars[i] = var;
     723        19500 :           if (var)
     724              :             {
     725         2840 :               tree array_type = build_index_type (size_int (fn_n_ctrs[i] - 1));
     726         2840 :               array_type = build_array_type (get_gcov_type (), array_type);
     727         2840 :               TREE_TYPE (var) = array_type;
     728         2840 :               DECL_SIZE (var) = TYPE_SIZE (array_type);
     729         2840 :               DECL_SIZE_UNIT (var) = TYPE_SIZE_UNIT (array_type);
     730         2840 :               varpool_node::finalize_decl (var);
     731              :             }
     732              : 
     733        19500 :           fn_b_ctrs[i] = fn_n_ctrs[i] = 0;
     734        19500 :           fn_v_ctrs[i] = NULL_TREE;
     735              :         }
     736         1950 :       prg_ctr_mask |= fn_ctr_mask;
     737         1950 :       fn_ctr_mask = 0;
     738              :     }
     739         2546 : }
     740              : 
     741              : /* Remove coverage file if opened.  */
     742              : 
     743              : void
     744        26735 : coverage_remove_note_file (void)
     745              : {
     746        26735 :   if (bbg_file_name)
     747              :     {
     748            0 :       gcov_close ();
     749            0 :       unlink (bbg_file_name);
     750              :     }
     751        26735 : }
     752              : 
     753              : /* Build a coverage variable of TYPE for function FN_DECL.  If COUNTER
     754              :    >= 0 it is a counter array, otherwise it is the function structure.  */
     755              : 
     756              : static tree
     757         4790 : build_var (tree fn_decl, tree type, int counter)
     758              : {
     759         4790 :   tree var = build_decl (BUILTINS_LOCATION, VAR_DECL, NULL_TREE, type);
     760         4790 :   const char *fn_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fn_decl));
     761         4790 :   char *buf;
     762         4790 :   size_t fn_name_len, len;
     763              : 
     764         4790 :   fn_name = targetm.strip_name_encoding (fn_name);
     765         4790 :   fn_name_len = strlen (fn_name);
     766         4790 :   buf = XALLOCAVEC (char, fn_name_len + 8 + sizeof (int) * 3);
     767              : 
     768         4790 :   if (counter < 0)
     769         1950 :     strcpy (buf, "__gcov__");
     770              :   else
     771         2840 :     sprintf (buf, "__gcov%u_", counter);
     772         4790 :   len = strlen (buf);
     773         4790 :   buf[len - 1] = symbol_table::symbol_suffix_separator ();
     774         4790 :   memcpy (buf + len, fn_name, fn_name_len + 1);
     775         4790 :   DECL_NAME (var) = get_identifier (buf);
     776         4790 :   TREE_STATIC (var) = 1;
     777         4790 :   TREE_ADDRESSABLE (var) = 1;
     778         4790 :   DECL_NONALIASED (var) = 1;
     779         4790 :   SET_DECL_ALIGN (var, TYPE_ALIGN (type));
     780              : 
     781         4790 :   return var;
     782              : }
     783              : 
     784              : /* Creates the gcov_fn_info RECORD_TYPE.  */
     785              : 
     786              : static void
     787          423 : build_fn_info_type (tree type, unsigned counters, tree gcov_info_type)
     788              : {
     789          423 :   tree ctr_info = lang_hooks.types.make_type (RECORD_TYPE);
     790          423 :   tree field, fields;
     791          423 :   tree array_type;
     792              : 
     793          423 :   gcc_assert (counters);
     794              : 
     795              :   /* ctr_info::num */
     796          423 :   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
     797              :                       get_gcov_unsigned_t ());
     798          423 :   fields = field;
     799              : 
     800              :   /* ctr_info::values */
     801          423 :   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
     802              :                       build_pointer_type (get_gcov_type ()));
     803          423 :   DECL_CHAIN (field) = fields;
     804          423 :   fields = field;
     805              : 
     806          423 :   finish_builtin_struct (ctr_info, "__gcov_ctr_info", fields, NULL_TREE);
     807              : 
     808              :   /* key */
     809          423 :   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
     810              :                       build_pointer_type (build_qualified_type
     811              :                                           (gcov_info_type, TYPE_QUAL_CONST)));
     812          423 :   fields = field;
     813              : 
     814              :   /* ident */
     815          423 :   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
     816              :                       get_gcov_unsigned_t ());
     817          423 :   DECL_CHAIN (field) = fields;
     818          423 :   fields = field;
     819              : 
     820              :   /* lineno_checksum */
     821          423 :   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
     822              :                       get_gcov_unsigned_t ());
     823          423 :   DECL_CHAIN (field) = fields;
     824          423 :   fields = field;
     825              : 
     826              :   /* cfg checksum */
     827          423 :   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
     828              :                       get_gcov_unsigned_t ());
     829          423 :   DECL_CHAIN (field) = fields;
     830          423 :   fields = field;
     831              : 
     832          423 :   array_type = build_index_type (size_int (counters - 1));
     833          423 :   array_type = build_array_type (ctr_info, array_type);
     834              : 
     835              :   /* counters */
     836          423 :   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, array_type);
     837          423 :   DECL_CHAIN (field) = fields;
     838          423 :   fields = field;
     839              : 
     840          423 :   finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
     841          423 : }
     842              : 
     843              : /* Returns a CONSTRUCTOR for a gcov_fn_info.  DATA is
     844              :    the coverage data for the function and TYPE is the gcov_fn_info
     845              :    RECORD_TYPE.  KEY is the object file key.  */
     846              : 
     847              : static tree
     848         1950 : build_fn_info (const struct coverage_data *data, tree type, tree key)
     849              : {
     850         1950 :   tree fields = TYPE_FIELDS (type);
     851         1950 :   tree ctr_type;
     852         1950 :   unsigned ix;
     853         1950 :   vec<constructor_elt, va_gc> *v1 = NULL;
     854         1950 :   vec<constructor_elt, va_gc> *v2 = NULL;
     855              : 
     856              :   /* key */
     857         1950 :   CONSTRUCTOR_APPEND_ELT (v1, fields,
     858              :                           build1 (ADDR_EXPR, TREE_TYPE (fields), key));
     859         1950 :   fields = DECL_CHAIN (fields);
     860              : 
     861              :   /* ident */
     862         1950 :   CONSTRUCTOR_APPEND_ELT (v1, fields,
     863              :                           build_int_cstu (get_gcov_unsigned_t (),
     864              :                                           data->ident));
     865         1950 :   fields = DECL_CHAIN (fields);
     866              : 
     867              :   /* lineno_checksum */
     868         1950 :   CONSTRUCTOR_APPEND_ELT (v1, fields,
     869              :                           build_int_cstu (get_gcov_unsigned_t (),
     870              :                                           data->lineno_checksum));
     871         1950 :   fields = DECL_CHAIN (fields);
     872              : 
     873              :   /* cfg_checksum */
     874         1950 :   CONSTRUCTOR_APPEND_ELT (v1, fields,
     875              :                           build_int_cstu (get_gcov_unsigned_t (),
     876              :                                           data->cfg_checksum));
     877         1950 :   fields = DECL_CHAIN (fields);
     878              : 
     879              :   /* counters */
     880         1950 :   ctr_type = TREE_TYPE (TREE_TYPE (fields));
     881        21450 :   for (ix = 0; ix != GCOV_COUNTERS; ix++)
     882        19500 :     if (prg_ctr_mask & (1 << ix))
     883              :       {
     884         3023 :         vec<constructor_elt, va_gc> *ctr = NULL;
     885         3023 :         tree var = data->ctr_vars[ix];
     886         3023 :         unsigned count = 0;
     887              : 
     888         3023 :         if (var)
     889         2840 :           count
     890         2840 :             = tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (var))))
     891         2840 :             + 1;
     892              : 
     893         3023 :         CONSTRUCTOR_APPEND_ELT (ctr, TYPE_FIELDS (ctr_type),
     894              :                                 build_int_cstu (get_gcov_unsigned_t (),
     895              :                                                 count));
     896              : 
     897         3023 :         if (var)
     898         2840 :           CONSTRUCTOR_APPEND_ELT (ctr, DECL_CHAIN (TYPE_FIELDS (ctr_type)),
     899              :                                   build_fold_addr_expr (var));
     900              : 
     901         3023 :         CONSTRUCTOR_APPEND_ELT (v2, NULL, build_constructor (ctr_type, ctr));
     902              :       }
     903              : 
     904         1950 :   CONSTRUCTOR_APPEND_ELT (v1, fields,
     905              :                           build_constructor (TREE_TYPE (fields), v2));
     906              : 
     907         1950 :   return build_constructor (type, v1);
     908              : }
     909              : 
     910              : /* Create gcov_info struct.  TYPE is the incomplete RECORD_TYPE to be
     911              :    completed, and FN_INFO_PTR_TYPE is a pointer to the function info type.  */
     912              : 
     913              : static void
     914          423 : build_info_type (tree type, tree fn_info_ptr_type)
     915              : {
     916          423 :   tree field, fields = NULL_TREE;
     917          423 :   tree merge_fn_type;
     918              : 
     919              :   /* Version ident */
     920          423 :   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
     921              :                       get_gcov_unsigned_t ());
     922          423 :   DECL_CHAIN (field) = fields;
     923          423 :   fields = field;
     924              : 
     925              :   /* next pointer */
     926          423 :   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
     927              :                       build_pointer_type (build_qualified_type
     928              :                                           (type, TYPE_QUAL_CONST)));
     929          423 :   DECL_CHAIN (field) = fields;
     930          423 :   fields = field;
     931              : 
     932              :   /* stamp */
     933          423 :   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
     934              :                       get_gcov_unsigned_t ());
     935          423 :   DECL_CHAIN (field) = fields;
     936          423 :   fields = field;
     937              : 
     938              :   /* Checksum.  */
     939          423 :   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
     940              :                       get_gcov_unsigned_t ());
     941          423 :   DECL_CHAIN (field) = fields;
     942          423 :   fields = field;
     943              : 
     944              :   /* Filename */
     945          423 :   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
     946              :                       build_pointer_type (build_qualified_type
     947              :                                           (char_type_node, TYPE_QUAL_CONST)));
     948          423 :   DECL_CHAIN (field) = fields;
     949          423 :   fields = field;
     950              : 
     951              :   /* merge fn array */
     952          423 :   merge_fn_type
     953          423 :     = build_function_type_list (void_type_node,
     954              :                                 build_pointer_type (get_gcov_type ()),
     955              :                                 get_gcov_unsigned_t (), NULL_TREE);
     956          423 :   merge_fn_type
     957          423 :     = build_array_type (build_pointer_type (merge_fn_type),
     958              :                         build_index_type (size_int (GCOV_COUNTERS - 1)));
     959          423 :   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
     960              :                       merge_fn_type);
     961          423 :   DECL_CHAIN (field) = fields;
     962          423 :   fields = field;
     963              : 
     964              :   /* n_functions */
     965          423 :   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
     966              :                       get_gcov_unsigned_t ());
     967          423 :   DECL_CHAIN (field) = fields;
     968          423 :   fields = field;
     969              : 
     970              :   /* function_info pointer pointer */
     971          423 :   fn_info_ptr_type = build_pointer_type
     972          423 :     (build_qualified_type (fn_info_ptr_type, TYPE_QUAL_CONST));
     973          423 :   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
     974              :                       fn_info_ptr_type);
     975          423 :   DECL_CHAIN (field) = fields;
     976          423 :   fields = field;
     977              : 
     978          423 :   finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
     979          423 : }
     980              : 
     981              : /* Returns a CONSTRUCTOR for the gcov_info object.  INFO_TYPE is the
     982              :    gcov_info structure type, FN_ARY is the array of pointers to
     983              :    function info objects.  */
     984              : 
     985              : static tree
     986          423 : build_info (tree info_type, tree fn_ary, unsigned object_checksum)
     987              : {
     988          423 :   tree info_fields = TYPE_FIELDS (info_type);
     989          423 :   tree merge_fn_type, n_funcs;
     990          423 :   unsigned ix;
     991          423 :   tree filename_string;
     992          423 :   int da_file_name_len;
     993          423 :   vec<constructor_elt, va_gc> *v1 = NULL;
     994          423 :   vec<constructor_elt, va_gc> *v2 = NULL;
     995              : 
     996              :   /* Version ident */
     997          423 :   CONSTRUCTOR_APPEND_ELT (v1, info_fields,
     998              :                           build_int_cstu (TREE_TYPE (info_fields),
     999              :                                           GCOV_VERSION));
    1000          423 :   info_fields = DECL_CHAIN (info_fields);
    1001              : 
    1002              :   /* next -- NULL */
    1003          423 :   CONSTRUCTOR_APPEND_ELT (v1, info_fields, null_pointer_node);
    1004          423 :   info_fields = DECL_CHAIN (info_fields);
    1005              : 
    1006              :   /* stamp */
    1007          423 :   CONSTRUCTOR_APPEND_ELT (v1, info_fields,
    1008              :                           build_int_cstu (TREE_TYPE (info_fields),
    1009              :                                           bbg_file_stamp));
    1010          423 :   info_fields = DECL_CHAIN (info_fields);
    1011              : 
    1012              :   /* Checksum.  */
    1013          423 :   CONSTRUCTOR_APPEND_ELT (v1, info_fields,
    1014              :                           build_int_cstu (TREE_TYPE (info_fields),
    1015              :                                           object_checksum));
    1016          423 :   info_fields = DECL_CHAIN (info_fields);
    1017              : 
    1018              :   /* Filename */
    1019          423 :   da_file_name_len = strlen (da_file_name);
    1020          423 :   filename_string = build_string (da_file_name_len + 1, da_file_name);
    1021          846 :   TREE_TYPE (filename_string) = build_array_type
    1022          423 :     (char_type_node, build_index_type (size_int (da_file_name_len)));
    1023          423 :   CONSTRUCTOR_APPEND_ELT (v1, info_fields,
    1024              :                           build1 (ADDR_EXPR, TREE_TYPE (info_fields),
    1025              :                                   filename_string));
    1026          423 :   info_fields = DECL_CHAIN (info_fields);
    1027              : 
    1028              :   /* merge fn array -- NULL slots indicate unmeasured counters */
    1029          423 :   merge_fn_type = TREE_TYPE (TREE_TYPE (info_fields));
    1030         4653 :   for (ix = 0; ix != GCOV_COUNTERS; ix++)
    1031              :     {
    1032         4230 :       tree ptr = null_pointer_node;
    1033              : 
    1034         4230 :       if ((1u << ix) & prg_ctr_mask)
    1035              :         {
    1036          766 :           tree merge_fn = build_decl (BUILTINS_LOCATION,
    1037              :                                       FUNCTION_DECL,
    1038          766 :                                       get_identifier (ctr_merge_functions[ix]),
    1039          766 :                                       TREE_TYPE (merge_fn_type));
    1040          766 :           DECL_EXTERNAL (merge_fn) = 1;
    1041          766 :           TREE_PUBLIC (merge_fn) = 1;
    1042          766 :           DECL_ARTIFICIAL (merge_fn) = 1;
    1043          766 :           TREE_NOTHROW (merge_fn) = 1;
    1044              :           /* Initialize assembler name so we can stream out. */
    1045          766 :           DECL_ASSEMBLER_NAME (merge_fn);
    1046          766 :           ptr = build1 (ADDR_EXPR, merge_fn_type, merge_fn);
    1047              :         }
    1048         4230 :       CONSTRUCTOR_APPEND_ELT (v2, NULL, ptr);
    1049              :     }
    1050          423 :   CONSTRUCTOR_APPEND_ELT (v1, info_fields,
    1051              :                           build_constructor (TREE_TYPE (info_fields), v2));
    1052          423 :   info_fields = DECL_CHAIN (info_fields);
    1053              : 
    1054              :   /* n_functions */
    1055          423 :   n_funcs = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (fn_ary)));
    1056          423 :   n_funcs = fold_build2 (PLUS_EXPR, TREE_TYPE (info_fields),
    1057              :                          n_funcs, size_one_node);
    1058          423 :   CONSTRUCTOR_APPEND_ELT (v1, info_fields, n_funcs);
    1059          423 :   info_fields = DECL_CHAIN (info_fields);
    1060              : 
    1061              :   /* functions */
    1062          423 :   CONSTRUCTOR_APPEND_ELT (v1, info_fields,
    1063              :                           build1 (ADDR_EXPR, TREE_TYPE (info_fields), fn_ary));
    1064          423 :   info_fields = DECL_CHAIN (info_fields);
    1065              : 
    1066          423 :   gcc_assert (!info_fields);
    1067          423 :   return build_constructor (info_type, v1);
    1068              : }
    1069              : 
    1070              : /* Generate the constructor function to call __gcov_init.  */
    1071              : 
    1072              : static void
    1073          421 : build_init_ctor (tree gcov_info_type)
    1074              : {
    1075          421 :   tree ctor, stmt, init_fn;
    1076              : 
    1077              :   /* Build a decl for __gcov_init.  */
    1078          421 :   init_fn = build_pointer_type (gcov_info_type);
    1079          421 :   init_fn = build_function_type_list (void_type_node, init_fn, NULL);
    1080          421 :   init_fn = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
    1081              :                         get_identifier ("__gcov_init"), init_fn);
    1082          421 :   TREE_PUBLIC (init_fn) = 1;
    1083          421 :   DECL_EXTERNAL (init_fn) = 1;
    1084          421 :   DECL_ASSEMBLER_NAME (init_fn);
    1085              : 
    1086              :   /* Generate a call to __gcov_init(&gcov_info).  */
    1087          421 :   ctor = NULL;
    1088          421 :   stmt = build_fold_addr_expr (gcov_info_var);
    1089          421 :   stmt = build_call_expr (init_fn, 1, stmt);
    1090          421 :   append_to_statement_list (stmt, &ctor);
    1091              : 
    1092              :   /* Generate a constructor to run it.  */
    1093          421 :   int priority = (SUPPORTS_INIT_PRIORITY
    1094              :                   ? MAX_RESERVED_INIT_PRIORITY : DEFAULT_INIT_PRIORITY);
    1095          421 :   cgraph_build_static_cdtor ('I', ctor, priority);
    1096          421 : }
    1097              : 
    1098              : /* Generate the destructor function to call __gcov_exit.  */
    1099              : 
    1100              : static void
    1101          421 : build_gcov_exit_decl (void)
    1102              : {
    1103          421 :   tree init_fn = build_function_type_list (void_type_node, NULL);
    1104          421 :   init_fn = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
    1105              :                         get_identifier ("__gcov_exit"), init_fn);
    1106          421 :   TREE_PUBLIC (init_fn) = 1;
    1107          421 :   DECL_EXTERNAL (init_fn) = 1;
    1108          421 :   DECL_ASSEMBLER_NAME (init_fn);
    1109              : 
    1110              :   /* Generate a call to __gcov_exit ().  */
    1111          421 :   tree dtor = NULL;
    1112          421 :   tree stmt = build_call_expr (init_fn, 0);
    1113          421 :   append_to_statement_list (stmt, &dtor);
    1114              : 
    1115              :   /* Generate a destructor to run it.  */
    1116          421 :   int priority = (SUPPORTS_INIT_PRIORITY
    1117              :                   ? MAX_RESERVED_INIT_PRIORITY : DEFAULT_INIT_PRIORITY);
    1118              : 
    1119          421 :   cgraph_build_static_cdtor ('D', dtor, priority);
    1120          421 : }
    1121              : 
    1122              : /* Generate the pointer to the gcov_info_var in a dedicated section.  */
    1123              : 
    1124              : static void
    1125            2 : build_gcov_info_var_registration (tree gcov_info_type)
    1126              : {
    1127            2 :   tree var = build_decl (BUILTINS_LOCATION,
    1128              :                          VAR_DECL, NULL_TREE,
    1129              :                          build_pointer_type (gcov_info_type));
    1130            2 :   TREE_STATIC (var) = 1;
    1131            2 :   TREE_READONLY (var) = 1;
    1132            2 :   char name_buf[32];
    1133            2 :   ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 2);
    1134            2 :   DECL_NAME (var) = get_identifier (name_buf);
    1135            2 :   get_section (profile_info_section, SECTION_UNNAMED, NULL);
    1136            2 :   set_decl_section_name (var, profile_info_section);
    1137            2 :   mark_decl_referenced (var);
    1138            2 :   DECL_INITIAL (var) = build_fold_addr_expr (gcov_info_var);
    1139            2 :   varpool_node::finalize_decl (var);
    1140            2 : }
    1141              : 
    1142              : /* Create the gcov_info types and object.  Generate the constructor
    1143              :    function to call __gcov_init.  Does not generate the initializer
    1144              :    for the object.  Returns TRUE if coverage data is being emitted.  */
    1145              : 
    1146              : static bool
    1147       229806 : coverage_obj_init (void)
    1148              : {
    1149       229806 :   tree gcov_info_type;
    1150       229806 :   unsigned n_counters = 0;
    1151       229806 :   unsigned ix;
    1152       229806 :   struct coverage_data *fn;
    1153       229806 :   struct coverage_data **fn_prev;
    1154       229806 :   char name_buf[32];
    1155              : 
    1156       229806 :   no_coverage = 1; /* Disable any further coverage.  */
    1157              : 
    1158       229806 :   if (!prg_ctr_mask)
    1159              :     return false;
    1160              : 
    1161          423 :   if (symtab->dump_file)
    1162            3 :     fprintf (symtab->dump_file, "Using data file %s\n", da_file_name);
    1163              : 
    1164              :   /* Prune functions.  */
    1165         2373 :   for (fn_prev = &functions_head; (fn = *fn_prev);)
    1166         1950 :     if (DECL_STRUCT_FUNCTION (fn->fn_decl))
    1167         1950 :       fn_prev = &fn->next;
    1168              :     else
    1169              :       /* The function is not being emitted, remove from list.  */
    1170            0 :       *fn_prev = fn->next;
    1171              : 
    1172          423 :   if (functions_head == NULL)
    1173              :     return false;
    1174              : 
    1175         4653 :   for (ix = 0; ix != GCOV_COUNTERS; ix++)
    1176         4230 :     if ((1u << ix) & prg_ctr_mask)
    1177          766 :       n_counters++;
    1178              : 
    1179              :   /* Build the info and fn_info types.  These are mutually recursive.  */
    1180          423 :   gcov_info_type = lang_hooks.types.make_type (RECORD_TYPE);
    1181          423 :   gcov_fn_info_type = lang_hooks.types.make_type (RECORD_TYPE);
    1182          423 :   build_fn_info_type (gcov_fn_info_type, n_counters, gcov_info_type);
    1183          423 :   gcov_info_type = lang_hooks.types.make_type (RECORD_TYPE);
    1184          846 :   gcov_fn_info_ptr_type = build_pointer_type
    1185          423 :     (build_qualified_type (gcov_fn_info_type, TYPE_QUAL_CONST));
    1186          423 :   build_info_type (gcov_info_type, gcov_fn_info_ptr_type);
    1187              : 
    1188              :   /* Build the gcov info var, this is referred to in its own
    1189              :      initializer.  */
    1190          423 :   gcov_info_var = build_decl (BUILTINS_LOCATION,
    1191              :                               VAR_DECL, NULL_TREE, gcov_info_type);
    1192          423 :   TREE_STATIC (gcov_info_var) = 1;
    1193          423 :   ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
    1194          423 :   DECL_NAME (gcov_info_var) = get_identifier (name_buf);
    1195              : 
    1196          423 :   if (profile_info_section)
    1197            2 :     build_gcov_info_var_registration (gcov_info_type);
    1198              :   else
    1199              :     {
    1200          421 :       build_init_ctor (gcov_info_type);
    1201          421 :       build_gcov_exit_decl ();
    1202              :     }
    1203              : 
    1204              :   return true;
    1205              : }
    1206              : 
    1207              : /* Generate the coverage function info for FN and DATA.  Append a
    1208              :    pointer to that object to CTOR and return the appended CTOR.  */
    1209              : 
    1210              : static vec<constructor_elt, va_gc> *
    1211         1950 : coverage_obj_fn (vec<constructor_elt, va_gc> *ctor, tree fn,
    1212              :                  struct coverage_data const *data)
    1213              : {
    1214         1950 :   tree init = build_fn_info (data, gcov_fn_info_type, gcov_info_var);
    1215         1950 :   tree var = build_var (fn, gcov_fn_info_type, -1);
    1216              : 
    1217         1950 :   DECL_INITIAL (var) = init;
    1218         1950 :   varpool_node::finalize_decl (var);
    1219              : 
    1220         1950 :   CONSTRUCTOR_APPEND_ELT (ctor, NULL,
    1221              :                           build1 (ADDR_EXPR, gcov_fn_info_ptr_type, var));
    1222         1950 :   return ctor;
    1223              : }
    1224              : 
    1225              : /* Finalize the coverage data.  Generates the array of pointers to
    1226              :    function objects from CTOR.  Generate the gcov_info initializer.  */
    1227              : 
    1228              : static void
    1229          423 : coverage_obj_finish (vec<constructor_elt, va_gc> *ctor,
    1230              :                      unsigned object_checksum)
    1231              : {
    1232          423 :   unsigned n_functions = vec_safe_length (ctor);
    1233          423 :   tree fn_info_ary_type = build_array_type
    1234          423 :     (build_qualified_type (gcov_fn_info_ptr_type, TYPE_QUAL_CONST),
    1235          423 :      build_index_type (size_int (n_functions - 1)));
    1236          423 :   tree fn_info_ary = build_decl (BUILTINS_LOCATION, VAR_DECL, NULL_TREE,
    1237              :                                  fn_info_ary_type);
    1238          423 :   char name_buf[32];
    1239              : 
    1240          423 :   TREE_STATIC (fn_info_ary) = 1;
    1241          423 :   ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 1);
    1242          423 :   DECL_NAME (fn_info_ary) = get_identifier (name_buf);
    1243          423 :   DECL_INITIAL (fn_info_ary) = build_constructor (fn_info_ary_type, ctor);
    1244          423 :   varpool_node::finalize_decl (fn_info_ary);
    1245              : 
    1246          423 :   DECL_INITIAL (gcov_info_var)
    1247          423 :     = build_info (TREE_TYPE (gcov_info_var), fn_info_ary, object_checksum);
    1248          423 :   varpool_node::finalize_decl (gcov_info_var);
    1249          423 : }
    1250              : 
    1251              : /* Perform file-level initialization. Read in data file, generate name
    1252              :    of notes file.  */
    1253              : 
    1254              : void
    1255       278638 : coverage_init (const char *filename)
    1256              : {
    1257              :   /* If we are in LTO, the profile will be read from object files.  */
    1258       278638 :   if (in_lto_p)
    1259              :     return;
    1260       258246 :   const char *original_filename = filename;
    1261       258246 :   int original_len = strlen (original_filename);
    1262              : #if HAVE_DOS_BASED_FILE_SYSTEM
    1263              :   const char *separator = "\\";
    1264              : #else
    1265       258246 :   const char *separator = "/";
    1266              : #endif
    1267       258246 :   int len = strlen (filename);
    1268       258246 :   int prefix_len = 0;
    1269              : 
    1270              :   /* Since coverage_init is invoked very early, before the pass
    1271              :      manager, we need to set up the dumping explicitly. This is
    1272              :      similar to the handling in finish_optimization_passes.  */
    1273       258246 :   int profile_pass_num =
    1274       258246 :     g->get_passes ()->get_pass_profile ()->static_pass_number;
    1275       258246 :   g->get_dumps ()->dump_start (profile_pass_num, NULL);
    1276              : 
    1277       258246 :   if (!IS_ABSOLUTE_PATH (filename))
    1278              :     {
    1279              :       /* When a profile_data_prefix is provided, then mangle full path
    1280              :          of filename in order to prevent file path clashing.  */
    1281       238601 :       if (profile_data_prefix)
    1282              :         {
    1283            3 :           filename = concat (getpwd (), separator, filename, NULL);
    1284            3 :           if (profile_prefix_path)
    1285              :             {
    1286            0 :               if (startswith (filename, profile_prefix_path))
    1287              :                 {
    1288            0 :                   filename += strlen (profile_prefix_path);
    1289            0 :                   while (*filename == *separator)
    1290            0 :                     filename++;
    1291              :                 }
    1292              :               else
    1293            0 :                 warning (0, "filename %qs does not start with profile "
    1294              :                          "prefix %qs", filename, profile_prefix_path);
    1295              :             }
    1296            3 :           filename = mangle_path (filename);
    1297            3 :           len = strlen (filename);
    1298              :         }
    1299              :       else
    1300       238598 :         profile_data_prefix = getpwd ();
    1301              :     }
    1302              : 
    1303       258246 :   if (profile_data_prefix)
    1304       238601 :     prefix_len = strlen (profile_data_prefix);
    1305              : 
    1306              :   /* Name of da file.  */
    1307       258246 :   da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX)
    1308              :                           + prefix_len + 2);
    1309              : 
    1310       258246 :   if (profile_data_prefix)
    1311              :     {
    1312       238601 :       memcpy (da_file_name, profile_data_prefix, prefix_len);
    1313       238601 :       da_file_name[prefix_len++] = *separator;
    1314              :     }
    1315       258246 :   memcpy (da_file_name + prefix_len, filename, len);
    1316       258246 :   strcpy (da_file_name + prefix_len + len, GCOV_DATA_SUFFIX);
    1317              : 
    1318       258246 :   bbg_file_stamp = local_tick;
    1319       258246 :   if (flag_branch_probabilities)
    1320          166 :     read_counts_file ();
    1321              : 
    1322              :   /* Name of bbg file.  */
    1323       258246 :   if (flag_test_coverage && !flag_compare_debug)
    1324              :     {
    1325          160 :       if (profile_note_location)
    1326            0 :         bbg_file_name = xstrdup (profile_note_location);
    1327              :       else
    1328              :         {
    1329          160 :           bbg_file_name = XNEWVEC (char, original_len + strlen (GCOV_NOTE_SUFFIX) + 1);
    1330          160 :           memcpy (bbg_file_name, original_filename, original_len);
    1331          160 :           strcpy (bbg_file_name + original_len, GCOV_NOTE_SUFFIX);
    1332              :         }
    1333              : 
    1334          160 :       if (!gcov_open (bbg_file_name, -1))
    1335              :         {
    1336            0 :           error ("cannot open %s", bbg_file_name);
    1337            0 :           bbg_file_name = NULL;
    1338              :         }
    1339              :       else
    1340              :         {
    1341          160 :           gcov_write_unsigned (GCOV_NOTE_MAGIC);
    1342          160 :           gcov_write_unsigned (GCOV_VERSION);
    1343          160 :           gcov_write_unsigned (bbg_file_stamp);
    1344              :           /* Use an arbitrary checksum */
    1345          160 :           gcov_write_unsigned (0);
    1346          160 :           gcov_write_string (remap_profile_filename (getpwd ()));
    1347              : 
    1348              :           /* Do not support has_unexecuted_blocks for Ada.  */
    1349          160 :           gcov_write_unsigned (strcmp (lang_hooks.name, "GNU Ada") != 0);
    1350              :         }
    1351              :     }
    1352              : 
    1353       258246 :   g->get_dumps ()->dump_finish (profile_pass_num);
    1354              : }
    1355              : 
    1356              : /* Performs file-level cleanup.  Close notes file, generate coverage
    1357              :    variables and constructor.  */
    1358              : 
    1359              : void
    1360       229806 : coverage_finish (void)
    1361              : {
    1362       229806 :   if (bbg_file_name && gcov_close ())
    1363            0 :     unlink (bbg_file_name);
    1364              : 
    1365       229806 :   if (!flag_branch_probabilities && flag_test_coverage
    1366          160 :       && (!local_tick || local_tick == (unsigned)-1))
    1367              :     /* Only remove the da file, if we're emitting coverage code and
    1368              :        cannot uniquely stamp it.  If we can stamp it, libgcov will DTRT.  */
    1369            0 :     unlink (da_file_name);
    1370              : 
    1371              :   /* Global GCDA checksum that aggregates all functions.  */
    1372       229806 :   unsigned object_checksum = 0;
    1373              : 
    1374       229806 :   if (coverage_obj_init ())
    1375              :     {
    1376          423 :       vec<constructor_elt, va_gc> *fn_ctor = NULL;
    1377          423 :       struct coverage_data *fn;
    1378              : 
    1379         2373 :       for (fn = functions_head; fn; fn = fn->next)
    1380              :         {
    1381         1950 :           fn_ctor = coverage_obj_fn (fn_ctor, fn->fn_decl, fn);
    1382              : 
    1383         1950 :           object_checksum = crc32_unsigned (object_checksum, fn->ident);
    1384         1950 :           object_checksum = crc32_unsigned (object_checksum,
    1385              :                                             fn->lineno_checksum);
    1386         1950 :           object_checksum = crc32_unsigned (object_checksum, fn->cfg_checksum);
    1387              :         }
    1388          423 :       coverage_obj_finish (fn_ctor, object_checksum);
    1389              :     }
    1390              : 
    1391       229806 :   XDELETEVEC (da_file_name);
    1392       229806 :   da_file_name = NULL;
    1393       229806 : }
    1394              : 
    1395              : #include "gt-coverage.h"
        

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.