LCOV - code coverage report
Current view: top level - gcc - coverage.c (source / functions) Hit Total Coverage
Test: gcc.info Lines: 522 582 89.7 %
Date: 2020-03-28 11:57:23 Functions: 26 26 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

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

Generated by: LCOV version 1.0

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 --enable-host-shared. GCC test suite is run with the built compiler.