Home | History | Annotate | Line # | Download | only in libgcc
      1       1.1  mrg /* Utility functions for reading gcda files into in-memory
      2       1.1  mrg    gcov_info structures and offline profile processing. */
      3  1.1.1.10  mrg /* Copyright (C) 2014-2024 Free Software Foundation, Inc.
      4       1.1  mrg    Contributed by Rong Xu <xur (at) google.com>.
      5       1.1  mrg 
      6       1.1  mrg This file is part of GCC.
      7       1.1  mrg 
      8       1.1  mrg GCC is free software; you can redistribute it and/or modify it under
      9       1.1  mrg the terms of the GNU General Public License as published by the Free
     10       1.1  mrg Software Foundation; either version 3, or (at your option) any later
     11       1.1  mrg version.
     12       1.1  mrg 
     13       1.1  mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     14       1.1  mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
     15       1.1  mrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     16       1.1  mrg for more details.
     17       1.1  mrg 
     18       1.1  mrg Under Section 7 of GPL version 3, you are granted additional
     19       1.1  mrg permissions described in the GCC Runtime Library Exception, version
     20       1.1  mrg 3.1, as published by the Free Software Foundation.
     21       1.1  mrg 
     22       1.1  mrg You should have received a copy of the GNU General Public License and
     23       1.1  mrg a copy of the GCC Runtime Library Exception along with this program;
     24       1.1  mrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     25       1.1  mrg <http://www.gnu.org/licenses/>.  */
     26       1.1  mrg 
     27       1.1  mrg 
     28       1.1  mrg #define IN_GCOV_TOOL 1
     29       1.1  mrg 
     30       1.1  mrg #include "libgcov.h"
     31       1.1  mrg #include "intl.h"
     32       1.1  mrg #include "diagnostic.h"
     33       1.1  mrg #include "version.h"
     34       1.1  mrg #include "demangle.h"
     35   1.1.1.7  mrg #include "gcov-io.h"
     36       1.1  mrg 
     37       1.1  mrg /* Borrowed from basic-block.h.  */
     38       1.1  mrg #define RDIV(X,Y) (((X) + (Y) / 2) / (Y))
     39       1.1  mrg 
     40       1.1  mrg extern gcov_position_t gcov_position();
     41       1.1  mrg extern int gcov_is_error();
     42       1.1  mrg 
     43       1.1  mrg /* Verbose mode for debug.  */
     44       1.1  mrg static int verbose;
     45       1.1  mrg 
     46       1.1  mrg /* Set verbose flag.  */
     47       1.1  mrg void gcov_set_verbose (void)
     48       1.1  mrg {
     49       1.1  mrg   verbose = 1;
     50       1.1  mrg }
     51       1.1  mrg 
     52       1.1  mrg /* The following part is to read Gcda and reconstruct GCOV_INFO.  */
     53       1.1  mrg 
     54       1.1  mrg #include "obstack.h"
     55       1.1  mrg #include <unistd.h>
     56       1.1  mrg #ifdef HAVE_FTW_H
     57       1.1  mrg #include <ftw.h>
     58       1.1  mrg #endif
     59       1.1  mrg 
     60   1.1.1.9  mrg static void tag_function (unsigned, int);
     61   1.1.1.9  mrg static void tag_blocks (unsigned, int);
     62   1.1.1.9  mrg static void tag_arcs (unsigned, int);
     63   1.1.1.9  mrg static void tag_lines (unsigned, int);
     64   1.1.1.9  mrg static void tag_counters (unsigned, int);
     65   1.1.1.9  mrg static void tag_summary (unsigned, int);
     66       1.1  mrg 
     67       1.1  mrg /* The gcov_info for the first module.  */
     68       1.1  mrg static struct gcov_info *curr_gcov_info;
     69       1.1  mrg /* The gcov_info being processed.  */
     70       1.1  mrg static struct gcov_info *gcov_info_head;
     71       1.1  mrg /* This variable contains all the functions in current module.  */
     72       1.1  mrg static struct obstack fn_info;
     73       1.1  mrg /* The function being processed.  */
     74       1.1  mrg static struct gcov_fn_info *curr_fn_info;
     75       1.1  mrg /* The number of functions seen so far.  */
     76       1.1  mrg static unsigned num_fn_info;
     77       1.1  mrg /* This variable contains all the counters for current module.  */
     78       1.1  mrg static int k_ctrs_mask[GCOV_COUNTERS];
     79       1.1  mrg /* The kind of counters that have been seen.  */
     80       1.1  mrg static struct gcov_ctr_info k_ctrs[GCOV_COUNTERS];
     81       1.1  mrg /* Number of kind of counters that have been seen.  */
     82       1.1  mrg static int k_ctrs_types;
     83       1.1  mrg 
     84       1.1  mrg /* Merge functions for counters.  */
     85       1.1  mrg #define DEF_GCOV_COUNTER(COUNTER, NAME, FN_TYPE) __gcov_merge ## FN_TYPE,
     86       1.1  mrg static gcov_merge_fn ctr_merge_functions[GCOV_COUNTERS] = {
     87       1.1  mrg #include "gcov-counter.def"
     88       1.1  mrg };
     89       1.1  mrg #undef DEF_GCOV_COUNTER
     90       1.1  mrg 
     91       1.1  mrg /* Set the ctrs field in gcov_fn_info object FN_INFO.  */
     92       1.1  mrg 
     93       1.1  mrg static void
     94       1.1  mrg set_fn_ctrs (struct gcov_fn_info *fn_info)
     95       1.1  mrg {
     96       1.1  mrg   int j = 0, i;
     97       1.1  mrg 
     98       1.1  mrg   for (i = 0; i < GCOV_COUNTERS; i++)
     99       1.1  mrg     {
    100       1.1  mrg       if (k_ctrs_mask[i] == 0)
    101       1.1  mrg         continue;
    102       1.1  mrg       fn_info->ctrs[j].num = k_ctrs[i].num;
    103       1.1  mrg       fn_info->ctrs[j].values = k_ctrs[i].values;
    104       1.1  mrg       j++;
    105       1.1  mrg     }
    106       1.1  mrg   if (k_ctrs_types == 0)
    107       1.1  mrg     k_ctrs_types = j;
    108       1.1  mrg   else
    109       1.1  mrg     gcc_assert (j == k_ctrs_types);
    110       1.1  mrg }
    111       1.1  mrg 
    112       1.1  mrg /* For each tag in gcda file, we have an entry here.
    113       1.1  mrg    TAG is the tag value; NAME is the tag name; and
    114       1.1  mrg    PROC is the handler function.  */
    115       1.1  mrg 
    116       1.1  mrg typedef struct tag_format
    117       1.1  mrg {
    118       1.1  mrg     unsigned tag;
    119       1.1  mrg     char const *name;
    120   1.1.1.9  mrg     void (*proc) (unsigned, int);
    121       1.1  mrg } tag_format_t;
    122       1.1  mrg 
    123       1.1  mrg /* Handler table for various Tags.  */
    124       1.1  mrg 
    125       1.1  mrg static const tag_format_t tag_table[] =
    126       1.1  mrg {
    127       1.1  mrg   {0, "NOP", NULL},
    128       1.1  mrg   {0, "UNKNOWN", NULL},
    129       1.1  mrg   {0, "COUNTERS", tag_counters},
    130       1.1  mrg   {GCOV_TAG_FUNCTION, "FUNCTION", tag_function},
    131       1.1  mrg   {GCOV_TAG_BLOCKS, "BLOCKS", tag_blocks},
    132       1.1  mrg   {GCOV_TAG_ARCS, "ARCS", tag_arcs},
    133       1.1  mrg   {GCOV_TAG_LINES, "LINES", tag_lines},
    134       1.1  mrg   {GCOV_TAG_OBJECT_SUMMARY, "OBJECT_SUMMARY", tag_summary},
    135       1.1  mrg   {0, NULL, NULL}
    136       1.1  mrg };
    137       1.1  mrg 
    138       1.1  mrg /* Handler for reading function tag.  */
    139       1.1  mrg 
    140       1.1  mrg static void
    141   1.1.1.9  mrg tag_function (unsigned tag ATTRIBUTE_UNUSED, int length ATTRIBUTE_UNUSED)
    142       1.1  mrg {
    143       1.1  mrg   int i;
    144       1.1  mrg 
    145       1.1  mrg   /* write out previous fn_info.  */
    146       1.1  mrg   if (num_fn_info)
    147       1.1  mrg     {
    148       1.1  mrg       set_fn_ctrs (curr_fn_info);
    149       1.1  mrg       obstack_ptr_grow (&fn_info, curr_fn_info);
    150       1.1  mrg     }
    151       1.1  mrg 
    152       1.1  mrg   /* Here we over allocate a bit, using GCOV_COUNTERS instead of the actual active
    153       1.1  mrg      counter types.  */
    154       1.1  mrg   curr_fn_info = (struct gcov_fn_info *) xcalloc (sizeof (struct gcov_fn_info)
    155       1.1  mrg                    + GCOV_COUNTERS * sizeof (struct gcov_ctr_info), 1);
    156       1.1  mrg 
    157       1.1  mrg   for (i = 0; i < GCOV_COUNTERS; i++)
    158       1.1  mrg      k_ctrs[i].num = 0;
    159       1.1  mrg   k_ctrs_types = 0;
    160       1.1  mrg 
    161       1.1  mrg   curr_fn_info->key = curr_gcov_info;
    162       1.1  mrg   curr_fn_info->ident = gcov_read_unsigned ();
    163       1.1  mrg   curr_fn_info->lineno_checksum = gcov_read_unsigned ();
    164       1.1  mrg   curr_fn_info->cfg_checksum = gcov_read_unsigned ();
    165       1.1  mrg   num_fn_info++;
    166       1.1  mrg 
    167       1.1  mrg   if (verbose)
    168       1.1  mrg     fnotice (stdout, "tag one function id=%d\n", curr_fn_info->ident);
    169       1.1  mrg }
    170       1.1  mrg 
    171       1.1  mrg /* Handler for reading block tag.  */
    172       1.1  mrg 
    173       1.1  mrg static void
    174   1.1.1.9  mrg tag_blocks (unsigned tag ATTRIBUTE_UNUSED, int length ATTRIBUTE_UNUSED)
    175       1.1  mrg {
    176       1.1  mrg   /* TBD: gcov-tool currently does not handle gcno files. Assert here.  */
    177       1.1  mrg   gcc_unreachable ();
    178       1.1  mrg }
    179       1.1  mrg 
    180       1.1  mrg /* Handler for reading flow arc tag.  */
    181       1.1  mrg 
    182       1.1  mrg static void
    183   1.1.1.9  mrg tag_arcs (unsigned tag ATTRIBUTE_UNUSED, int length ATTRIBUTE_UNUSED)
    184       1.1  mrg {
    185       1.1  mrg   /* TBD: gcov-tool currently does not handle gcno files. Assert here.  */
    186       1.1  mrg   gcc_unreachable ();
    187       1.1  mrg }
    188       1.1  mrg 
    189       1.1  mrg /* Handler for reading line tag.  */
    190       1.1  mrg 
    191       1.1  mrg static void
    192   1.1.1.9  mrg tag_lines (unsigned tag ATTRIBUTE_UNUSED, int length ATTRIBUTE_UNUSED)
    193       1.1  mrg {
    194       1.1  mrg   /* TBD: gcov-tool currently does not handle gcno files. Assert here.  */
    195       1.1  mrg   gcc_unreachable ();
    196       1.1  mrg }
    197       1.1  mrg 
    198       1.1  mrg /* Handler for reading counters array tag with value as TAG and length of LENGTH.  */
    199       1.1  mrg 
    200       1.1  mrg static void
    201   1.1.1.9  mrg tag_counters (unsigned tag, int length)
    202       1.1  mrg {
    203   1.1.1.9  mrg   unsigned n_counts = GCOV_TAG_COUNTER_NUM (abs (length));
    204       1.1  mrg   gcov_type *values;
    205       1.1  mrg   unsigned ix;
    206       1.1  mrg   unsigned tag_ix;
    207       1.1  mrg 
    208       1.1  mrg   tag_ix = GCOV_COUNTER_FOR_TAG (tag);
    209       1.1  mrg   gcc_assert (tag_ix < GCOV_COUNTERS);
    210       1.1  mrg   k_ctrs_mask [tag_ix] = 1;
    211       1.1  mrg   gcc_assert (k_ctrs[tag_ix].num == 0);
    212       1.1  mrg   k_ctrs[tag_ix].num = n_counts;
    213       1.1  mrg 
    214   1.1.1.9  mrg   k_ctrs[tag_ix].values = values = (gcov_type *) xcalloc (sizeof (gcov_type),
    215   1.1.1.9  mrg 							  n_counts);
    216       1.1  mrg   gcc_assert (values);
    217       1.1  mrg 
    218   1.1.1.9  mrg   if (length > 0)
    219   1.1.1.9  mrg     for (ix = 0; ix != n_counts; ix++)
    220   1.1.1.9  mrg       values[ix] = gcov_read_counter ();
    221       1.1  mrg }
    222       1.1  mrg 
    223       1.1  mrg /* Handler for reading summary tag.  */
    224       1.1  mrg 
    225       1.1  mrg static void
    226   1.1.1.9  mrg tag_summary (unsigned tag ATTRIBUTE_UNUSED, int ATTRIBUTE_UNUSED)
    227       1.1  mrg {
    228   1.1.1.9  mrg   gcov_read_summary (&curr_gcov_info->summary);
    229       1.1  mrg }
    230       1.1  mrg 
    231       1.1  mrg /* This function is called at the end of reading a gcda file.
    232       1.1  mrg    It flushes the contents in curr_fn_info to gcov_info object OBJ_INFO.  */
    233       1.1  mrg 
    234       1.1  mrg static void
    235       1.1  mrg read_gcda_finalize (struct gcov_info *obj_info)
    236       1.1  mrg {
    237       1.1  mrg   int i;
    238       1.1  mrg 
    239       1.1  mrg   set_fn_ctrs (curr_fn_info);
    240       1.1  mrg   obstack_ptr_grow (&fn_info, curr_fn_info);
    241       1.1  mrg 
    242   1.1.1.7  mrg   /* We set the following fields: merge, n_functions, functions
    243   1.1.1.7  mrg      and summary.  */
    244       1.1  mrg   obj_info->n_functions = num_fn_info;
    245   1.1.1.9  mrg   obj_info->functions = (struct gcov_fn_info**) obstack_finish (&fn_info);
    246       1.1  mrg 
    247       1.1  mrg   /* wrap all the counter array.  */
    248       1.1  mrg   for (i=0; i< GCOV_COUNTERS; i++)
    249       1.1  mrg     {
    250       1.1  mrg       if (k_ctrs_mask[i])
    251       1.1  mrg         obj_info->merge[i] = ctr_merge_functions[i];
    252       1.1  mrg     }
    253       1.1  mrg }
    254       1.1  mrg 
    255       1.1  mrg /* Read the content of a gcda file FILENAME, and return a gcov_info data structure.
    256       1.1  mrg    Program level summary CURRENT_SUMMARY will also be updated.  */
    257       1.1  mrg 
    258       1.1  mrg static struct gcov_info *
    259       1.1  mrg read_gcda_file (const char *filename)
    260       1.1  mrg {
    261       1.1  mrg   unsigned tags[4];
    262       1.1  mrg   unsigned depth = 0;
    263   1.1.1.8  mrg   unsigned version;
    264       1.1  mrg   struct gcov_info *obj_info;
    265       1.1  mrg   int i;
    266       1.1  mrg 
    267       1.1  mrg   for (i=0; i< GCOV_COUNTERS; i++)
    268       1.1  mrg     k_ctrs_mask[i] = 0;
    269       1.1  mrg   k_ctrs_types = 0;
    270       1.1  mrg 
    271       1.1  mrg   /* Read magic.  */
    272   1.1.1.8  mrg   if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
    273       1.1  mrg     {
    274       1.1  mrg       fnotice (stderr, "%s:not a gcov data file\n", filename);
    275       1.1  mrg       return NULL;
    276       1.1  mrg     }
    277       1.1  mrg 
    278       1.1  mrg   /* Read version.  */
    279       1.1  mrg   version = gcov_read_unsigned ();
    280       1.1  mrg   if (version != GCOV_VERSION)
    281       1.1  mrg     {
    282       1.1  mrg       fnotice (stderr, "%s:incorrect gcov version %d vs %d \n", filename, version, GCOV_VERSION);
    283       1.1  mrg       return NULL;
    284       1.1  mrg     }
    285       1.1  mrg 
    286       1.1  mrg   /* Instantiate a gcov_info object.  */
    287       1.1  mrg   curr_gcov_info = obj_info = (struct gcov_info *) xcalloc (sizeof (struct gcov_info) +
    288       1.1  mrg              sizeof (struct gcov_ctr_info) * GCOV_COUNTERS, 1);
    289       1.1  mrg 
    290       1.1  mrg   obj_info->version = version;
    291  1.1.1.10  mrg   obj_info->filename = filename;
    292       1.1  mrg   obstack_init (&fn_info);
    293       1.1  mrg   num_fn_info = 0;
    294       1.1  mrg   curr_fn_info = 0;
    295       1.1  mrg 
    296  1.1.1.10  mrg   /* Prepend to global gcov info list.  */
    297  1.1.1.10  mrg   obj_info->next = gcov_info_head;
    298  1.1.1.10  mrg   gcov_info_head = obj_info;
    299       1.1  mrg 
    300       1.1  mrg   /* Read stamp.  */
    301       1.1  mrg   obj_info->stamp = gcov_read_unsigned ();
    302       1.1  mrg 
    303   1.1.1.9  mrg   /* Read checksum.  */
    304   1.1.1.9  mrg   obj_info->checksum = gcov_read_unsigned ();
    305   1.1.1.9  mrg 
    306       1.1  mrg   while (1)
    307       1.1  mrg     {
    308       1.1  mrg       gcov_position_t base;
    309       1.1  mrg       unsigned tag, length;
    310       1.1  mrg       tag_format_t const *format;
    311       1.1  mrg       unsigned tag_depth;
    312       1.1  mrg       int error;
    313       1.1  mrg       unsigned mask;
    314       1.1  mrg 
    315       1.1  mrg       tag = gcov_read_unsigned ();
    316       1.1  mrg       if (!tag)
    317       1.1  mrg         break;
    318   1.1.1.9  mrg       int read_length = (int)gcov_read_unsigned ();
    319   1.1.1.9  mrg       length = read_length > 0 ? read_length : 0;
    320       1.1  mrg       base = gcov_position ();
    321       1.1  mrg       mask = GCOV_TAG_MASK (tag) >> 1;
    322       1.1  mrg       for (tag_depth = 4; mask; mask >>= 8)
    323       1.1  mrg         {
    324       1.1  mrg           if (((mask & 0xff) != 0xff))
    325       1.1  mrg             {
    326   1.1.1.8  mrg 	      warning (0, "%s:tag %qx is invalid", filename, tag);
    327       1.1  mrg               break;
    328       1.1  mrg             }
    329       1.1  mrg           tag_depth--;
    330       1.1  mrg         }
    331       1.1  mrg       for (format = tag_table; format->name; format++)
    332       1.1  mrg         if (format->tag == tag)
    333       1.1  mrg           goto found;
    334       1.1  mrg       format = &tag_table[GCOV_TAG_IS_COUNTER (tag) ? 2 : 1];
    335       1.1  mrg     found:;
    336       1.1  mrg       if (tag)
    337       1.1  mrg         {
    338       1.1  mrg           if (depth && depth < tag_depth)
    339       1.1  mrg             {
    340       1.1  mrg               if (!GCOV_TAG_IS_SUBTAG (tags[depth - 1], tag))
    341   1.1.1.8  mrg 	        warning (0, "%s:tag %qx is incorrectly nested",
    342       1.1  mrg                          filename, tag);
    343       1.1  mrg             }
    344       1.1  mrg           depth = tag_depth;
    345       1.1  mrg           tags[depth - 1] = tag;
    346       1.1  mrg         }
    347       1.1  mrg 
    348       1.1  mrg       if (format->proc)
    349       1.1  mrg         {
    350       1.1  mrg           unsigned long actual_length;
    351       1.1  mrg 
    352   1.1.1.9  mrg 	  (*format->proc) (tag, read_length);
    353       1.1  mrg 
    354       1.1  mrg           actual_length = gcov_position () - base;
    355       1.1  mrg           if (actual_length > length)
    356   1.1.1.8  mrg 	    warning (0, "%s:record size mismatch %lu bytes overread",
    357       1.1  mrg                      filename, actual_length - length);
    358       1.1  mrg           else if (length > actual_length)
    359   1.1.1.8  mrg 	    warning (0, "%s:record size mismatch %lu bytes unread",
    360       1.1  mrg                      filename, length - actual_length);
    361       1.1  mrg        }
    362       1.1  mrg 
    363       1.1  mrg       gcov_sync (base, length);
    364       1.1  mrg       if ((error = gcov_is_error ()))
    365       1.1  mrg         {
    366   1.1.1.8  mrg 	  warning (0, error < 0 ? "%s:counter overflow at %lu" :
    367   1.1.1.8  mrg 	                          "%s:read error at %lu", filename,
    368       1.1  mrg                    (long unsigned) gcov_position ());
    369       1.1  mrg           break;
    370       1.1  mrg         }
    371       1.1  mrg     }
    372       1.1  mrg 
    373       1.1  mrg   read_gcda_finalize (obj_info);
    374       1.1  mrg 
    375       1.1  mrg   return obj_info;
    376       1.1  mrg }
    377       1.1  mrg 
    378       1.1  mrg #ifdef HAVE_FTW_H
    379       1.1  mrg /* This will be called by ftw(). It opens and read a gcda file FILENAME.
    380       1.1  mrg    Return a non-zero value to stop the tree walk.  */
    381       1.1  mrg 
    382       1.1  mrg static int
    383       1.1  mrg ftw_read_file (const char *filename,
    384       1.1  mrg                const struct stat *status ATTRIBUTE_UNUSED,
    385       1.1  mrg                int type)
    386       1.1  mrg {
    387  1.1.1.10  mrg   size_t filename_len;
    388  1.1.1.10  mrg   size_t suffix_len;
    389       1.1  mrg 
    390       1.1  mrg   /* Only read regular files.  */
    391       1.1  mrg   if (type != FTW_F)
    392       1.1  mrg     return 0;
    393       1.1  mrg 
    394       1.1  mrg   filename_len = strlen (filename);
    395       1.1  mrg   suffix_len = strlen (GCOV_DATA_SUFFIX);
    396       1.1  mrg 
    397       1.1  mrg   if (filename_len <= suffix_len)
    398       1.1  mrg     return 0;
    399       1.1  mrg 
    400       1.1  mrg   if (strcmp(filename + filename_len - suffix_len, GCOV_DATA_SUFFIX))
    401       1.1  mrg     return 0;
    402       1.1  mrg 
    403       1.1  mrg   if (verbose)
    404       1.1  mrg     fnotice (stderr, "reading file: %s\n", filename);
    405       1.1  mrg 
    406  1.1.1.10  mrg   if (!gcov_open (filename, 1))
    407  1.1.1.10  mrg     {
    408  1.1.1.10  mrg       fnotice (stderr, "%s:cannot open:%s\n", filename, xstrerror (errno));
    409  1.1.1.10  mrg       return 0;
    410  1.1.1.10  mrg     }
    411       1.1  mrg 
    412  1.1.1.10  mrg   (void)read_gcda_file (xstrdup (filename));
    413  1.1.1.10  mrg   gcov_close ();
    414       1.1  mrg 
    415       1.1  mrg   return 0;
    416       1.1  mrg }
    417       1.1  mrg #endif
    418       1.1  mrg 
    419       1.1  mrg /* Initializer for reading a profile dir.  */
    420       1.1  mrg 
    421       1.1  mrg static inline void
    422       1.1  mrg read_profile_dir_init (void)
    423       1.1  mrg {
    424       1.1  mrg   gcov_info_head = 0;
    425       1.1  mrg }
    426       1.1  mrg 
    427       1.1  mrg /* Driver for read a profile directory and convert into gcov_info list in memory.
    428       1.1  mrg    Return NULL on error,
    429       1.1  mrg    Return the head of gcov_info list on success.  */
    430       1.1  mrg 
    431       1.1  mrg struct gcov_info *
    432       1.1  mrg gcov_read_profile_dir (const char* dir_name, int recompute_summary ATTRIBUTE_UNUSED)
    433       1.1  mrg {
    434       1.1  mrg   char *pwd;
    435       1.1  mrg   int ret;
    436       1.1  mrg 
    437       1.1  mrg   read_profile_dir_init ();
    438       1.1  mrg 
    439       1.1  mrg   if (access (dir_name, R_OK) != 0)
    440       1.1  mrg     {
    441       1.1  mrg       fnotice (stderr, "cannot access directory %s\n", dir_name);
    442       1.1  mrg       return NULL;
    443       1.1  mrg     }
    444       1.1  mrg   pwd = getcwd (NULL, 0);
    445       1.1  mrg   gcc_assert (pwd);
    446       1.1  mrg   ret = chdir (dir_name);
    447       1.1  mrg   if (ret !=0)
    448       1.1  mrg     {
    449       1.1  mrg       fnotice (stderr, "%s is not a directory\n", dir_name);
    450       1.1  mrg       return NULL;
    451       1.1  mrg     }
    452       1.1  mrg #ifdef HAVE_FTW_H
    453       1.1  mrg   ftw (".", ftw_read_file, 50);
    454       1.1  mrg #endif
    455   1.1.1.8  mrg   chdir (pwd);
    456       1.1  mrg   free (pwd);
    457       1.1  mrg 
    458       1.1  mrg   return gcov_info_head;;
    459       1.1  mrg }
    460       1.1  mrg 
    461       1.1  mrg /* This part of the code is to merge profile counters. These
    462       1.1  mrg    variables are set in merge_wrapper and to be used by
    463       1.1  mrg    global function gcov_read_counter_mem() and gcov_get_merge_weight.  */
    464       1.1  mrg 
    465       1.1  mrg /* We save the counter value address to this variable.  */
    466       1.1  mrg static gcov_type *gcov_value_buf;
    467       1.1  mrg 
    468       1.1  mrg /* The number of counter values to be read by current merging.  */
    469       1.1  mrg static gcov_unsigned_t gcov_value_buf_size;
    470       1.1  mrg 
    471       1.1  mrg /* The index of counter values being read.  */
    472       1.1  mrg static gcov_unsigned_t gcov_value_buf_pos;
    473       1.1  mrg 
    474       1.1  mrg /* The weight of current merging.  */
    475       1.1  mrg static unsigned gcov_merge_weight;
    476       1.1  mrg 
    477       1.1  mrg /* Read a counter value from gcov_value_buf array.  */
    478       1.1  mrg 
    479       1.1  mrg gcov_type
    480       1.1  mrg gcov_read_counter_mem (void)
    481       1.1  mrg {
    482       1.1  mrg   gcov_type ret;
    483       1.1  mrg   gcc_assert (gcov_value_buf_pos < gcov_value_buf_size);
    484       1.1  mrg   ret = *(gcov_value_buf + gcov_value_buf_pos);
    485       1.1  mrg   ++gcov_value_buf_pos;
    486       1.1  mrg   return ret;
    487       1.1  mrg }
    488       1.1  mrg 
    489       1.1  mrg /* Return the recorded merge weight.  */
    490       1.1  mrg 
    491       1.1  mrg unsigned
    492       1.1  mrg gcov_get_merge_weight (void)
    493       1.1  mrg {
    494       1.1  mrg   return gcov_merge_weight;
    495       1.1  mrg }
    496       1.1  mrg 
    497       1.1  mrg /* A wrapper function for merge functions. It sets up the
    498       1.1  mrg    value buffer and weights and then calls the merge function.  */
    499       1.1  mrg 
    500       1.1  mrg static void
    501   1.1.1.9  mrg merge_wrapper (gcov_merge_fn f, gcov_type *v1, gcov_unsigned_t n1,
    502   1.1.1.9  mrg 	       gcov_type *v2, gcov_unsigned_t n2, unsigned w)
    503       1.1  mrg {
    504       1.1  mrg   gcov_value_buf = v2;
    505       1.1  mrg   gcov_value_buf_pos = 0;
    506   1.1.1.9  mrg   gcov_value_buf_size = n2;
    507       1.1  mrg   gcov_merge_weight = w;
    508   1.1.1.9  mrg   (*f) (v1, n1);
    509   1.1.1.9  mrg }
    510   1.1.1.9  mrg 
    511   1.1.1.9  mrg /* Convert on disk representation of a TOPN counter to in memory representation
    512   1.1.1.9  mrg    that is expected from __gcov_merge_topn function.  */
    513   1.1.1.9  mrg 
    514   1.1.1.9  mrg static void
    515   1.1.1.9  mrg topn_to_memory_representation (struct gcov_ctr_info *info)
    516   1.1.1.9  mrg {
    517   1.1.1.9  mrg   auto_vec<gcov_type> output;
    518   1.1.1.9  mrg   gcov_type *values = info->values;
    519   1.1.1.9  mrg   int count = info->num;
    520   1.1.1.9  mrg 
    521   1.1.1.9  mrg   while (count > 0)
    522   1.1.1.9  mrg     {
    523   1.1.1.9  mrg       output.safe_push (values[0]);
    524   1.1.1.9  mrg       gcov_type n = values[1];
    525   1.1.1.9  mrg       output.safe_push (n);
    526   1.1.1.9  mrg       if (n > 0)
    527   1.1.1.9  mrg 	{
    528   1.1.1.9  mrg 	  struct gcov_kvp *tuples
    529   1.1.1.9  mrg 	    = (struct gcov_kvp *)xcalloc (sizeof (struct gcov_kvp), n);
    530   1.1.1.9  mrg 	  for (unsigned i = 0; i < n - 1; i++)
    531   1.1.1.9  mrg 	    tuples[i].next = &tuples[i + 1];
    532   1.1.1.9  mrg 	  for (unsigned i = 0; i < n; i++)
    533   1.1.1.9  mrg 	    {
    534   1.1.1.9  mrg 	      tuples[i].value = values[2 + 2 * i];
    535   1.1.1.9  mrg 	      tuples[i].count = values[2 + 2 * i + 1];
    536   1.1.1.9  mrg 	    }
    537   1.1.1.9  mrg 	  output.safe_push ((intptr_t)&tuples[0]);
    538   1.1.1.9  mrg 	}
    539   1.1.1.9  mrg       else
    540   1.1.1.9  mrg 	output.safe_push (0);
    541   1.1.1.9  mrg 
    542   1.1.1.9  mrg       unsigned len = 2 * n + 2;
    543   1.1.1.9  mrg       values += len;
    544   1.1.1.9  mrg       count -= len;
    545   1.1.1.9  mrg     }
    546   1.1.1.9  mrg   gcc_assert (count == 0);
    547   1.1.1.9  mrg 
    548   1.1.1.9  mrg   /* Allocate new buffer and copy it there.  */
    549   1.1.1.9  mrg   info->num = output.length ();
    550   1.1.1.9  mrg   info->values = (gcov_type *)xmalloc (sizeof (gcov_type) * info->num);
    551   1.1.1.9  mrg   for (unsigned i = 0; i < info->num; i++)
    552   1.1.1.9  mrg     info->values[i] = output[i];
    553       1.1  mrg }
    554       1.1  mrg 
    555       1.1  mrg /* Offline tool to manipulate profile data.
    556       1.1  mrg    This tool targets on matched profiles. But it has some tolerance on
    557       1.1  mrg    unmatched profiles.
    558       1.1  mrg    When merging p1 to p2 (p2 is the dst),
    559       1.1  mrg    * m.gcda in p1 but not in p2: append m.gcda to p2 with specified weight;
    560       1.1  mrg      emit warning
    561       1.1  mrg    * m.gcda in p2 but not in p1: keep m.gcda in p2 and multiply by
    562       1.1  mrg      specified weight; emit warning.
    563       1.1  mrg    * m.gcda in both p1 and p2:
    564       1.1  mrg    ** p1->m.gcda->f checksum matches p2->m.gcda->f: simple merge.
    565       1.1  mrg    ** p1->m.gcda->f checksum does not matches p2->m.gcda->f: keep
    566       1.1  mrg       p2->m.gcda->f and
    567       1.1  mrg       drop p1->m.gcda->f. A warning is emitted.  */
    568       1.1  mrg 
    569       1.1  mrg /* Add INFO2's counter to INFO1, multiplying by weight W.  */
    570       1.1  mrg 
    571       1.1  mrg static int
    572       1.1  mrg gcov_merge (struct gcov_info *info1, struct gcov_info *info2, int w)
    573       1.1  mrg {
    574       1.1  mrg   unsigned f_ix;
    575       1.1  mrg   unsigned n_functions = info1->n_functions;
    576       1.1  mrg   int has_mismatch = 0;
    577       1.1  mrg 
    578       1.1  mrg   gcc_assert (info2->n_functions == n_functions);
    579   1.1.1.9  mrg 
    580   1.1.1.9  mrg   /* Merge summary.  */
    581   1.1.1.9  mrg   info1->summary.runs += info2->summary.runs;
    582   1.1.1.9  mrg   info1->summary.sum_max += info2->summary.sum_max;
    583   1.1.1.9  mrg 
    584       1.1  mrg   for (f_ix = 0; f_ix < n_functions; f_ix++)
    585       1.1  mrg     {
    586       1.1  mrg       unsigned t_ix;
    587   1.1.1.9  mrg       struct gcov_fn_info *gfi_ptr1 = info1->functions[f_ix];
    588   1.1.1.9  mrg       struct gcov_fn_info *gfi_ptr2 = info2->functions[f_ix];
    589   1.1.1.9  mrg       struct gcov_ctr_info *ci_ptr1, *ci_ptr2;
    590       1.1  mrg 
    591       1.1  mrg       if (!gfi_ptr1 || gfi_ptr1->key != info1)
    592       1.1  mrg         continue;
    593       1.1  mrg       if (!gfi_ptr2 || gfi_ptr2->key != info2)
    594       1.1  mrg         continue;
    595       1.1  mrg 
    596       1.1  mrg       if (gfi_ptr1->cfg_checksum != gfi_ptr2->cfg_checksum)
    597       1.1  mrg         {
    598       1.1  mrg           fnotice (stderr, "in %s, cfg_checksum mismatch, skipping\n",
    599       1.1  mrg                   info1->filename);
    600       1.1  mrg           has_mismatch = 1;
    601       1.1  mrg           continue;
    602       1.1  mrg         }
    603       1.1  mrg       ci_ptr1 = gfi_ptr1->ctrs;
    604       1.1  mrg       ci_ptr2 = gfi_ptr2->ctrs;
    605       1.1  mrg       for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
    606       1.1  mrg         {
    607       1.1  mrg           gcov_merge_fn merge1 = info1->merge[t_ix];
    608       1.1  mrg           gcov_merge_fn merge2 = info2->merge[t_ix];
    609       1.1  mrg 
    610       1.1  mrg           gcc_assert (merge1 == merge2);
    611       1.1  mrg           if (!merge1)
    612       1.1  mrg             continue;
    613   1.1.1.9  mrg 
    614   1.1.1.9  mrg 	  if (merge1 == __gcov_merge_topn)
    615   1.1.1.9  mrg 	    topn_to_memory_representation (ci_ptr1);
    616   1.1.1.9  mrg 	  else
    617   1.1.1.9  mrg 	    gcc_assert (ci_ptr1->num == ci_ptr2->num);
    618   1.1.1.9  mrg 
    619   1.1.1.9  mrg 	  merge_wrapper (merge1, ci_ptr1->values, ci_ptr1->num,
    620   1.1.1.9  mrg 			 ci_ptr2->values, ci_ptr2->num, w);
    621       1.1  mrg           ci_ptr1++;
    622       1.1  mrg           ci_ptr2++;
    623       1.1  mrg         }
    624       1.1  mrg     }
    625       1.1  mrg 
    626       1.1  mrg   return has_mismatch;
    627       1.1  mrg }
    628       1.1  mrg 
    629       1.1  mrg /* Find and return the match gcov_info object for INFO from ARRAY.
    630       1.1  mrg    SIZE is the length of ARRAY.
    631       1.1  mrg    Return NULL if there is no match.  */
    632       1.1  mrg 
    633       1.1  mrg static struct gcov_info *
    634       1.1  mrg find_match_gcov_info (struct gcov_info **array, int size,
    635       1.1  mrg 		      struct gcov_info *info)
    636       1.1  mrg {
    637       1.1  mrg   struct gcov_info *gi_ptr;
    638       1.1  mrg   struct gcov_info *ret = NULL;
    639       1.1  mrg   int i;
    640       1.1  mrg 
    641       1.1  mrg   for (i = 0; i < size; i++)
    642       1.1  mrg     {
    643       1.1  mrg       gi_ptr = array[i];
    644       1.1  mrg       if (gi_ptr == 0)
    645       1.1  mrg         continue;
    646       1.1  mrg       if (!strcmp (gi_ptr->filename, info->filename))
    647       1.1  mrg         {
    648       1.1  mrg           ret = gi_ptr;
    649       1.1  mrg           array[i] = 0;
    650       1.1  mrg           break;
    651       1.1  mrg         }
    652       1.1  mrg     }
    653       1.1  mrg 
    654       1.1  mrg   if (ret && ret->n_functions != info->n_functions)
    655       1.1  mrg     {
    656       1.1  mrg       fnotice (stderr, "mismatched profiles in %s (%d functions"
    657       1.1  mrg                        " vs %d functions)\n",
    658       1.1  mrg                        ret->filename,
    659       1.1  mrg                        ret->n_functions,
    660       1.1  mrg                        info->n_functions);
    661       1.1  mrg       ret = NULL;
    662       1.1  mrg     }
    663       1.1  mrg   return ret;
    664       1.1  mrg }
    665       1.1  mrg 
    666       1.1  mrg /* Merge the list of gcov_info objects from SRC_PROFILE to TGT_PROFILE.
    667  1.1.1.10  mrg    Return the list of merged gcov_info objects.  Return NULL if the list is
    668  1.1.1.10  mrg    empty.  */
    669       1.1  mrg 
    670  1.1.1.10  mrg struct gcov_info *
    671       1.1  mrg gcov_profile_merge (struct gcov_info *tgt_profile, struct gcov_info *src_profile,
    672       1.1  mrg                     int w1, int w2)
    673       1.1  mrg {
    674       1.1  mrg   struct gcov_info *gi_ptr;
    675       1.1  mrg   struct gcov_info **tgt_infos;
    676  1.1.1.10  mrg   struct gcov_info **tgt_tail;
    677       1.1  mrg   struct gcov_info **in_src_not_tgt;
    678       1.1  mrg   unsigned tgt_cnt = 0, src_cnt = 0;
    679       1.1  mrg   unsigned unmatch_info_cnt = 0;
    680       1.1  mrg   unsigned int i;
    681       1.1  mrg 
    682       1.1  mrg   for (gi_ptr = tgt_profile; gi_ptr; gi_ptr = gi_ptr->next)
    683       1.1  mrg     tgt_cnt++;
    684       1.1  mrg   for (gi_ptr = src_profile; gi_ptr; gi_ptr = gi_ptr->next)
    685       1.1  mrg     src_cnt++;
    686       1.1  mrg   tgt_infos = (struct gcov_info **) xmalloc (sizeof (struct gcov_info *)
    687       1.1  mrg                  * tgt_cnt);
    688       1.1  mrg   gcc_assert (tgt_infos);
    689       1.1  mrg   in_src_not_tgt = (struct gcov_info **) xmalloc (sizeof (struct gcov_info *)
    690       1.1  mrg                      * src_cnt);
    691       1.1  mrg   gcc_assert (in_src_not_tgt);
    692       1.1  mrg 
    693       1.1  mrg   for (gi_ptr = tgt_profile, i = 0; gi_ptr; gi_ptr = gi_ptr->next, i++)
    694       1.1  mrg     tgt_infos[i] = gi_ptr;
    695       1.1  mrg 
    696  1.1.1.10  mrg   if (tgt_cnt)
    697  1.1.1.10  mrg      tgt_tail = &tgt_infos[tgt_cnt - 1]->next;
    698  1.1.1.10  mrg   else
    699  1.1.1.10  mrg      tgt_tail = &tgt_profile;
    700       1.1  mrg 
    701       1.1  mrg   /* First pass on tgt_profile, we multiply w1 to all counters.  */
    702       1.1  mrg   if (w1 > 1)
    703       1.1  mrg     {
    704       1.1  mrg        for (i = 0; i < tgt_cnt; i++)
    705       1.1  mrg          gcov_merge (tgt_infos[i], tgt_infos[i], w1-1);
    706       1.1  mrg     }
    707       1.1  mrg 
    708       1.1  mrg   /* Second pass, add src_profile to the tgt_profile.  */
    709       1.1  mrg   for (gi_ptr = src_profile; gi_ptr; gi_ptr = gi_ptr->next)
    710       1.1  mrg     {
    711       1.1  mrg       struct gcov_info *gi_ptr1;
    712       1.1  mrg 
    713       1.1  mrg       gi_ptr1 = find_match_gcov_info (tgt_infos, tgt_cnt, gi_ptr);
    714       1.1  mrg       if (gi_ptr1 == NULL)
    715       1.1  mrg         {
    716       1.1  mrg           in_src_not_tgt[unmatch_info_cnt++] = gi_ptr;
    717       1.1  mrg           continue;
    718       1.1  mrg         }
    719       1.1  mrg       gcov_merge (gi_ptr1, gi_ptr, w2);
    720       1.1  mrg     }
    721       1.1  mrg 
    722       1.1  mrg   /* For modules in src but not in tgt. We adjust the counter and append.  */
    723       1.1  mrg   for (i = 0; i < unmatch_info_cnt; i++)
    724       1.1  mrg     {
    725       1.1  mrg       gi_ptr = in_src_not_tgt[i];
    726       1.1  mrg       gcov_merge (gi_ptr, gi_ptr, w2 - 1);
    727   1.1.1.3  mrg       gi_ptr->next = NULL;
    728  1.1.1.10  mrg       *tgt_tail = gi_ptr;
    729  1.1.1.10  mrg       tgt_tail = &gi_ptr->next;
    730       1.1  mrg     }
    731       1.1  mrg 
    732   1.1.1.8  mrg   free (in_src_not_tgt);
    733   1.1.1.8  mrg   free (tgt_infos);
    734   1.1.1.8  mrg 
    735  1.1.1.10  mrg   return tgt_profile;
    736  1.1.1.10  mrg }
    737  1.1.1.10  mrg 
    738  1.1.1.10  mrg /* Deserialize gcov_info objects and associated filenames from the file
    739  1.1.1.10  mrg    specified by FILENAME to create a profile list.  When FILENAME is NULL, read
    740  1.1.1.10  mrg    from stdin.  Return the profile list.  */
    741  1.1.1.10  mrg 
    742  1.1.1.10  mrg struct gcov_info *
    743  1.1.1.10  mrg deserialize_profiles (const char *filename)
    744  1.1.1.10  mrg {
    745  1.1.1.10  mrg   read_profile_dir_init ();
    746  1.1.1.10  mrg 
    747  1.1.1.10  mrg   while (true)
    748  1.1.1.10  mrg     {
    749  1.1.1.10  mrg       unsigned version;
    750  1.1.1.10  mrg       const char *filename_of_info;
    751  1.1.1.10  mrg       struct gcov_info *obj_info;
    752  1.1.1.10  mrg 
    753  1.1.1.10  mrg       if (!gcov_magic (gcov_read_unsigned (), GCOV_FILENAME_MAGIC))
    754  1.1.1.10  mrg 	{
    755  1.1.1.10  mrg 	  if (gcov_is_error () != 2)
    756  1.1.1.10  mrg 	    fnotice (stderr, "%s:not a gcfn stream\n", filename);
    757  1.1.1.10  mrg 	  break;
    758  1.1.1.10  mrg 	}
    759  1.1.1.10  mrg 
    760  1.1.1.10  mrg       version = gcov_read_unsigned ();
    761  1.1.1.10  mrg       if (version != GCOV_VERSION)
    762  1.1.1.10  mrg 	{
    763  1.1.1.10  mrg 	  fnotice (stderr, "%s:incorrect gcov version %d vs %d \n",
    764  1.1.1.10  mrg 		   filename, version, GCOV_VERSION);
    765  1.1.1.10  mrg 	  break;
    766  1.1.1.10  mrg 	}
    767  1.1.1.10  mrg 
    768  1.1.1.10  mrg       filename_of_info = gcov_read_string ();
    769  1.1.1.10  mrg       if (!filename_of_info)
    770  1.1.1.10  mrg 	{
    771  1.1.1.10  mrg 	  fnotice (stderr, "%s:no filename in gcfn stream\n",
    772  1.1.1.10  mrg 		   filename);
    773  1.1.1.10  mrg 	  break;
    774  1.1.1.10  mrg 	}
    775  1.1.1.10  mrg 
    776  1.1.1.10  mrg       obj_info = read_gcda_file (filename);
    777  1.1.1.10  mrg       if (!obj_info)
    778  1.1.1.10  mrg 	break;
    779  1.1.1.10  mrg 
    780  1.1.1.10  mrg       obj_info->filename = filename_of_info;
    781  1.1.1.10  mrg     }
    782  1.1.1.10  mrg 
    783  1.1.1.10  mrg   return gcov_info_head;
    784  1.1.1.10  mrg }
    785  1.1.1.10  mrg 
    786  1.1.1.10  mrg /* For each profile of the list specified by SRC_PROFILE, read the GCDA file of
    787  1.1.1.10  mrg    the profile.  If a GCDA file exists, add the profile to a list.  Return the
    788  1.1.1.10  mrg    profile list.  */
    789  1.1.1.10  mrg 
    790  1.1.1.10  mrg struct gcov_info *
    791  1.1.1.10  mrg get_target_profiles_for_merge (struct gcov_info *src_profile)
    792  1.1.1.10  mrg {
    793  1.1.1.10  mrg   struct gcov_info *gi_ptr;
    794  1.1.1.10  mrg 
    795  1.1.1.10  mrg   read_profile_dir_init ();
    796  1.1.1.10  mrg 
    797  1.1.1.10  mrg   for (gi_ptr = src_profile; gi_ptr; gi_ptr = gi_ptr->next)
    798  1.1.1.10  mrg     if (gcov_open (gi_ptr->filename, 1))
    799  1.1.1.10  mrg       {
    800  1.1.1.10  mrg 	(void)read_gcda_file (gi_ptr->filename);
    801  1.1.1.10  mrg 	gcov_close ();
    802  1.1.1.10  mrg       }
    803  1.1.1.10  mrg 
    804  1.1.1.10  mrg   return gcov_info_head;
    805  1.1.1.10  mrg }
    806  1.1.1.10  mrg 
    807  1.1.1.10  mrg /* Deserialize gcov_info objects and associated filenames from the file
    808  1.1.1.10  mrg    specified by FILENAME to create a source profile list.  When FILENAME is
    809  1.1.1.10  mrg    NULL, read from stdin.  Use the filenames of the source profile list to get
    810  1.1.1.10  mrg    a target profile list.  Merge the source profile list into the target
    811  1.1.1.10  mrg    profile list using weights W1 and W2.  Return the list of merged gcov_info
    812  1.1.1.10  mrg    objects.  Return NULL if the list is empty.  */
    813  1.1.1.10  mrg 
    814  1.1.1.10  mrg struct gcov_info *
    815  1.1.1.10  mrg gcov_profile_merge_stream (const char *filename, int w1, int w2)
    816  1.1.1.10  mrg {
    817  1.1.1.10  mrg   struct gcov_info *tgt_profile;
    818  1.1.1.10  mrg   struct gcov_info *src_profile;
    819  1.1.1.10  mrg 
    820  1.1.1.10  mrg   if (!gcov_open (filename, 1))
    821  1.1.1.10  mrg     {
    822  1.1.1.10  mrg       fnotice (stderr, "%s:cannot open:%s\n", filename, xstrerror (errno));
    823  1.1.1.10  mrg       return NULL;
    824  1.1.1.10  mrg     }
    825  1.1.1.10  mrg 
    826  1.1.1.10  mrg   src_profile = deserialize_profiles (filename ? filename : "<stdin>");
    827  1.1.1.10  mrg   gcov_close ();
    828  1.1.1.10  mrg   tgt_profile = get_target_profiles_for_merge (src_profile);
    829  1.1.1.10  mrg 
    830  1.1.1.10  mrg   return gcov_profile_merge (tgt_profile, src_profile, w1, w2);
    831       1.1  mrg }
    832       1.1  mrg 
    833       1.1  mrg typedef gcov_type (*counter_op_fn) (gcov_type, void*, void*);
    834       1.1  mrg 
    835       1.1  mrg /* Performing FN upon arc counters.  */
    836       1.1  mrg 
    837       1.1  mrg static void
    838       1.1  mrg __gcov_add_counter_op (gcov_type *counters, unsigned n_counters,
    839       1.1  mrg                        counter_op_fn fn, void *data1, void *data2)
    840       1.1  mrg {
    841       1.1  mrg   for (; n_counters; counters++, n_counters--)
    842       1.1  mrg     {
    843       1.1  mrg       gcov_type val = *counters;
    844       1.1  mrg       *counters = fn(val, data1, data2);
    845       1.1  mrg     }
    846       1.1  mrg }
    847       1.1  mrg 
    848       1.1  mrg /* Performing FN upon ior counters.  */
    849       1.1  mrg 
    850       1.1  mrg static void
    851       1.1  mrg __gcov_ior_counter_op (gcov_type *counters ATTRIBUTE_UNUSED,
    852       1.1  mrg                        unsigned n_counters ATTRIBUTE_UNUSED,
    853       1.1  mrg                        counter_op_fn fn ATTRIBUTE_UNUSED,
    854       1.1  mrg                        void *data1 ATTRIBUTE_UNUSED,
    855       1.1  mrg                        void *data2 ATTRIBUTE_UNUSED)
    856       1.1  mrg {
    857       1.1  mrg   /* Do nothing.  */
    858       1.1  mrg }
    859       1.1  mrg 
    860       1.1  mrg /* Performing FN upon time-profile counters.  */
    861       1.1  mrg 
    862       1.1  mrg static void
    863       1.1  mrg __gcov_time_profile_counter_op (gcov_type *counters ATTRIBUTE_UNUSED,
    864       1.1  mrg                                 unsigned n_counters ATTRIBUTE_UNUSED,
    865       1.1  mrg                                 counter_op_fn fn ATTRIBUTE_UNUSED,
    866       1.1  mrg                                 void *data1 ATTRIBUTE_UNUSED,
    867       1.1  mrg                                 void *data2 ATTRIBUTE_UNUSED)
    868       1.1  mrg {
    869       1.1  mrg   /* Do nothing.  */
    870       1.1  mrg }
    871       1.1  mrg 
    872   1.1.1.8  mrg /* Performing FN upon TOP N counters.  */
    873       1.1  mrg 
    874       1.1  mrg static void
    875   1.1.1.8  mrg __gcov_topn_counter_op (gcov_type *counters, unsigned n_counters,
    876   1.1.1.8  mrg 			counter_op_fn fn, void *data1, void *data2)
    877       1.1  mrg {
    878       1.1  mrg   unsigned i, n_measures;
    879       1.1  mrg 
    880       1.1  mrg   gcc_assert (!(n_counters % 3));
    881       1.1  mrg   n_measures = n_counters / 3;
    882       1.1  mrg   for (i = 0; i < n_measures; i++, counters += 3)
    883       1.1  mrg     {
    884       1.1  mrg       counters[1] = fn (counters[1], data1, data2);
    885       1.1  mrg       counters[2] = fn (counters[2], data1, data2);
    886       1.1  mrg     }
    887       1.1  mrg }
    888       1.1  mrg 
    889       1.1  mrg /* Scaling the counter value V by multiplying *(float*) DATA1.  */
    890       1.1  mrg 
    891       1.1  mrg static gcov_type
    892       1.1  mrg fp_scale (gcov_type v, void *data1, void *data2 ATTRIBUTE_UNUSED)
    893       1.1  mrg {
    894       1.1  mrg   float f = *(float *) data1;
    895       1.1  mrg   return (gcov_type) (v * f);
    896       1.1  mrg }
    897       1.1  mrg 
    898       1.1  mrg /* Scaling the counter value V by multiplying DATA2/DATA1.  */
    899       1.1  mrg 
    900       1.1  mrg static gcov_type
    901       1.1  mrg int_scale (gcov_type v, void *data1, void *data2)
    902       1.1  mrg {
    903       1.1  mrg   int n = *(int *) data1;
    904       1.1  mrg   int d = *(int *) data2;
    905       1.1  mrg   return (gcov_type) ( RDIV (v,d) * n);
    906       1.1  mrg }
    907       1.1  mrg 
    908       1.1  mrg /* Type of function used to process counters.  */
    909       1.1  mrg typedef void (*gcov_counter_fn) (gcov_type *, gcov_unsigned_t,
    910       1.1  mrg                           counter_op_fn, void *, void *);
    911       1.1  mrg 
    912       1.1  mrg /* Function array to process profile counters.  */
    913       1.1  mrg #define DEF_GCOV_COUNTER(COUNTER, NAME, FN_TYPE) \
    914       1.1  mrg   __gcov ## FN_TYPE ## _counter_op,
    915       1.1  mrg static gcov_counter_fn ctr_functions[GCOV_COUNTERS] = {
    916       1.1  mrg #include "gcov-counter.def"
    917       1.1  mrg };
    918       1.1  mrg #undef DEF_GCOV_COUNTER
    919       1.1  mrg 
    920       1.1  mrg /* Driver for scaling profile counters.  */
    921       1.1  mrg 
    922       1.1  mrg int
    923       1.1  mrg gcov_profile_scale (struct gcov_info *profile, float scale_factor, int n, int d)
    924       1.1  mrg {
    925       1.1  mrg   struct gcov_info *gi_ptr;
    926       1.1  mrg   unsigned f_ix;
    927       1.1  mrg 
    928       1.1  mrg   if (verbose)
    929       1.1  mrg     fnotice (stdout, "scale_factor is %f or %d/%d\n", scale_factor, n, d);
    930       1.1  mrg 
    931       1.1  mrg   /* Scaling the counters.  */
    932       1.1  mrg   for (gi_ptr = profile; gi_ptr; gi_ptr = gi_ptr->next)
    933       1.1  mrg     for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
    934       1.1  mrg       {
    935       1.1  mrg         unsigned t_ix;
    936       1.1  mrg         const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
    937       1.1  mrg         const struct gcov_ctr_info *ci_ptr;
    938       1.1  mrg 
    939       1.1  mrg         if (!gfi_ptr || gfi_ptr->key != gi_ptr)
    940       1.1  mrg           continue;
    941       1.1  mrg 
    942       1.1  mrg         ci_ptr = gfi_ptr->ctrs;
    943       1.1  mrg         for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
    944       1.1  mrg           {
    945       1.1  mrg             gcov_merge_fn merge = gi_ptr->merge[t_ix];
    946       1.1  mrg 
    947       1.1  mrg             if (!merge)
    948       1.1  mrg               continue;
    949       1.1  mrg             if (d == 0)
    950       1.1  mrg               (*ctr_functions[t_ix]) (ci_ptr->values, ci_ptr->num,
    951       1.1  mrg                                       fp_scale, &scale_factor, NULL);
    952       1.1  mrg             else
    953       1.1  mrg               (*ctr_functions[t_ix]) (ci_ptr->values, ci_ptr->num,
    954       1.1  mrg                                       int_scale, &n, &d);
    955       1.1  mrg             ci_ptr++;
    956       1.1  mrg           }
    957       1.1  mrg       }
    958       1.1  mrg 
    959       1.1  mrg   return 0;
    960       1.1  mrg }
    961       1.1  mrg 
    962       1.1  mrg /* Driver to normalize profile counters.  */
    963       1.1  mrg 
    964       1.1  mrg int
    965       1.1  mrg gcov_profile_normalize (struct gcov_info *profile, gcov_type max_val)
    966       1.1  mrg {
    967       1.1  mrg   struct gcov_info *gi_ptr;
    968       1.1  mrg   gcov_type curr_max_val = 0;
    969       1.1  mrg   unsigned f_ix;
    970       1.1  mrg   unsigned int i;
    971       1.1  mrg   float scale_factor;
    972       1.1  mrg 
    973       1.1  mrg   /* Find the largest count value.  */
    974       1.1  mrg   for (gi_ptr = profile; gi_ptr; gi_ptr = gi_ptr->next)
    975       1.1  mrg     for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
    976       1.1  mrg       {
    977       1.1  mrg         unsigned t_ix;
    978       1.1  mrg         const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
    979       1.1  mrg         const struct gcov_ctr_info *ci_ptr;
    980       1.1  mrg 
    981       1.1  mrg         if (!gfi_ptr || gfi_ptr->key != gi_ptr)
    982       1.1  mrg           continue;
    983       1.1  mrg 
    984       1.1  mrg         ci_ptr = gfi_ptr->ctrs;
    985       1.1  mrg         for (t_ix = 0; t_ix < 1; t_ix++)
    986       1.1  mrg           {
    987       1.1  mrg             for (i = 0; i < ci_ptr->num; i++)
    988       1.1  mrg               if (ci_ptr->values[i] > curr_max_val)
    989       1.1  mrg                 curr_max_val = ci_ptr->values[i];
    990       1.1  mrg             ci_ptr++;
    991       1.1  mrg           }
    992       1.1  mrg       }
    993       1.1  mrg 
    994       1.1  mrg   scale_factor = (float)max_val / curr_max_val;
    995       1.1  mrg   if (verbose)
    996   1.1.1.2  mrg     fnotice (stdout, "max_val is %" PRId64 "\n", curr_max_val);
    997       1.1  mrg 
    998       1.1  mrg   return gcov_profile_scale (profile, scale_factor, 0, 0);
    999       1.1  mrg }
   1000       1.1  mrg 
   1001       1.1  mrg /* The following variables are defined in gcc/gcov-tool.c.  */
   1002       1.1  mrg extern int overlap_func_level;
   1003       1.1  mrg extern int overlap_obj_level;
   1004       1.1  mrg extern int overlap_hot_only;
   1005       1.1  mrg extern int overlap_use_fullname;
   1006       1.1  mrg extern double overlap_hot_threshold;
   1007       1.1  mrg 
   1008       1.1  mrg /* Compute the overlap score of two values. The score is defined as:
   1009       1.1  mrg     min (V1/SUM_1, V2/SUM_2)  */
   1010       1.1  mrg 
   1011       1.1  mrg static double
   1012       1.1  mrg calculate_2_entries (const unsigned long v1, const unsigned long v2,
   1013       1.1  mrg                      const double sum_1, const double sum_2)
   1014       1.1  mrg {
   1015       1.1  mrg   double val1 = (sum_1 == 0.0 ? 0.0 : v1/sum_1);
   1016       1.1  mrg   double val2 = (sum_2 == 0.0 ? 0.0 : v2/sum_2);
   1017       1.1  mrg 
   1018       1.1  mrg   if (val2 < val1)
   1019       1.1  mrg     val1 = val2;
   1020       1.1  mrg 
   1021       1.1  mrg   return val1;
   1022       1.1  mrg }
   1023       1.1  mrg 
   1024       1.1  mrg /*  Compute the overlap score between GCOV_INFO1 and GCOV_INFO2.
   1025       1.1  mrg     This function also updates cumulative score CUM_1_RESULT and
   1026       1.1  mrg     CUM_2_RESULT.  */
   1027       1.1  mrg 
   1028       1.1  mrg static double
   1029       1.1  mrg compute_one_gcov (const struct gcov_info *gcov_info1,
   1030       1.1  mrg                   const struct gcov_info *gcov_info2,
   1031       1.1  mrg                   const double sum_1, const double sum_2,
   1032       1.1  mrg                   double *cum_1_result, double *cum_2_result)
   1033       1.1  mrg {
   1034       1.1  mrg   unsigned f_ix;
   1035       1.1  mrg   double ret = 0;
   1036       1.1  mrg   double cum_1 = 0, cum_2 = 0;
   1037       1.1  mrg   const struct gcov_info *gcov_info = 0;
   1038       1.1  mrg   double *cum_p;
   1039       1.1  mrg   double sum;
   1040       1.1  mrg 
   1041       1.1  mrg   gcc_assert (gcov_info1 || gcov_info2);
   1042       1.1  mrg   if (!gcov_info1)
   1043       1.1  mrg     {
   1044       1.1  mrg       gcov_info = gcov_info2;
   1045       1.1  mrg       cum_p = cum_2_result;
   1046       1.1  mrg       sum = sum_2;
   1047       1.1  mrg       *cum_1_result = 0;
   1048       1.1  mrg     } else
   1049       1.1  mrg   if (!gcov_info2)
   1050       1.1  mrg     {
   1051       1.1  mrg       gcov_info = gcov_info1;
   1052       1.1  mrg       cum_p = cum_1_result;
   1053       1.1  mrg       sum = sum_1;
   1054       1.1  mrg       *cum_2_result = 0;
   1055       1.1  mrg     }
   1056       1.1  mrg 
   1057       1.1  mrg   if (gcov_info)
   1058       1.1  mrg   {
   1059       1.1  mrg     for (f_ix = 0; f_ix < gcov_info->n_functions; f_ix++)
   1060       1.1  mrg       {
   1061       1.1  mrg         const struct gcov_fn_info *gfi_ptr = gcov_info->functions[f_ix];
   1062       1.1  mrg         if (!gfi_ptr || gfi_ptr->key != gcov_info)
   1063       1.1  mrg           continue;
   1064       1.1  mrg         const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
   1065   1.1.1.7  mrg 	unsigned c_num;
   1066   1.1.1.7  mrg 	for (c_num = 0; c_num < ci_ptr->num; c_num++)
   1067   1.1.1.7  mrg 	  cum_1 += ci_ptr->values[c_num] / sum;
   1068       1.1  mrg       }
   1069       1.1  mrg     *cum_p = cum_1;
   1070       1.1  mrg     return 0.0;
   1071       1.1  mrg   }
   1072       1.1  mrg 
   1073       1.1  mrg   for (f_ix = 0; f_ix < gcov_info1->n_functions; f_ix++)
   1074       1.1  mrg     {
   1075       1.1  mrg       double func_cum_1 = 0.0;
   1076       1.1  mrg       double func_cum_2 = 0.0;
   1077       1.1  mrg       double func_val = 0.0;
   1078       1.1  mrg       int nonzero = 0;
   1079       1.1  mrg       int hot = 0;
   1080       1.1  mrg       const struct gcov_fn_info *gfi_ptr1 = gcov_info1->functions[f_ix];
   1081       1.1  mrg       const struct gcov_fn_info *gfi_ptr2 = gcov_info2->functions[f_ix];
   1082       1.1  mrg 
   1083       1.1  mrg       if (!gfi_ptr1 || gfi_ptr1->key != gcov_info1)
   1084       1.1  mrg         continue;
   1085       1.1  mrg       if (!gfi_ptr2 || gfi_ptr2->key != gcov_info2)
   1086       1.1  mrg         continue;
   1087       1.1  mrg 
   1088       1.1  mrg       const struct gcov_ctr_info *ci_ptr1 = gfi_ptr1->ctrs;
   1089       1.1  mrg       const struct gcov_ctr_info *ci_ptr2 = gfi_ptr2->ctrs;
   1090   1.1.1.7  mrg       unsigned c_num;
   1091   1.1.1.7  mrg       for (c_num = 0; c_num < ci_ptr1->num; c_num++)
   1092   1.1.1.7  mrg 	{
   1093   1.1.1.7  mrg 	  if (ci_ptr1->values[c_num] | ci_ptr2->values[c_num])
   1094   1.1.1.7  mrg 	    {
   1095   1.1.1.7  mrg 	      func_val += calculate_2_entries (ci_ptr1->values[c_num],
   1096   1.1.1.7  mrg 					       ci_ptr2->values[c_num],
   1097   1.1.1.7  mrg 					       sum_1, sum_2);
   1098   1.1.1.7  mrg 
   1099   1.1.1.7  mrg 	      func_cum_1 += ci_ptr1->values[c_num] / sum_1;
   1100   1.1.1.7  mrg 	      func_cum_2 += ci_ptr2->values[c_num] / sum_2;
   1101   1.1.1.7  mrg 	      nonzero = 1;
   1102   1.1.1.7  mrg 	      if (ci_ptr1->values[c_num] / sum_1 >= overlap_hot_threshold
   1103   1.1.1.7  mrg 		  || ci_ptr2->values[c_num] / sum_2 >= overlap_hot_threshold)
   1104   1.1.1.7  mrg 		hot = 1;
   1105   1.1.1.7  mrg 	    }
   1106   1.1.1.7  mrg 	}
   1107       1.1  mrg 
   1108       1.1  mrg       ret += func_val;
   1109       1.1  mrg       cum_1 += func_cum_1;
   1110       1.1  mrg       cum_2 += func_cum_2;
   1111       1.1  mrg       if (overlap_func_level && nonzero && (!overlap_hot_only || hot))
   1112       1.1  mrg         {
   1113       1.1  mrg           printf("   \tfunc_id=%10d \toverlap =%6.5f%% (%5.5f%% %5.5f%%)\n",
   1114       1.1  mrg                  gfi_ptr1->ident, func_val*100, func_cum_1*100, func_cum_2*100);
   1115       1.1  mrg         }
   1116       1.1  mrg     }
   1117       1.1  mrg   *cum_1_result = cum_1;
   1118       1.1  mrg   *cum_2_result = cum_2;
   1119       1.1  mrg   return ret;
   1120       1.1  mrg }
   1121       1.1  mrg 
   1122       1.1  mrg /* Test if all counter values in this GCOV_INFO are cold.
   1123       1.1  mrg    "Cold" is defined as the counter value being less than
   1124       1.1  mrg    or equal to THRESHOLD.  */
   1125       1.1  mrg 
   1126       1.1  mrg static bool
   1127       1.1  mrg gcov_info_count_all_cold (const struct gcov_info *gcov_info,
   1128       1.1  mrg                           gcov_type threshold)
   1129       1.1  mrg {
   1130       1.1  mrg   unsigned f_ix;
   1131       1.1  mrg 
   1132       1.1  mrg   for (f_ix = 0; f_ix < gcov_info->n_functions; f_ix++)
   1133       1.1  mrg     {
   1134       1.1  mrg       const struct gcov_fn_info *gfi_ptr = gcov_info->functions[f_ix];
   1135       1.1  mrg 
   1136       1.1  mrg       if (!gfi_ptr || gfi_ptr->key != gcov_info)
   1137       1.1  mrg         continue;
   1138       1.1  mrg       const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
   1139   1.1.1.7  mrg       for (unsigned c_num = 0; c_num < ci_ptr->num; c_num++)
   1140   1.1.1.7  mrg 	if (ci_ptr->values[c_num] > threshold)
   1141   1.1.1.7  mrg 	  return false;
   1142       1.1  mrg     }
   1143       1.1  mrg 
   1144       1.1  mrg   return true;
   1145       1.1  mrg }
   1146       1.1  mrg 
   1147       1.1  mrg /* Test if all counter values in this GCOV_INFO are 0.  */
   1148       1.1  mrg 
   1149       1.1  mrg static bool
   1150       1.1  mrg gcov_info_count_all_zero (const struct gcov_info *gcov_info)
   1151       1.1  mrg {
   1152       1.1  mrg   return gcov_info_count_all_cold (gcov_info, 0);
   1153       1.1  mrg }
   1154       1.1  mrg 
   1155       1.1  mrg /* A pair of matched GCOV_INFO.
   1156       1.1  mrg    The flag is a bitvector:
   1157       1.1  mrg      b0: obj1's all counts are 0;
   1158       1.1  mrg      b1: obj1's all counts are cold (but no 0);
   1159       1.1  mrg      b2: obj1 is hot;
   1160       1.1  mrg      b3: no obj1 to match obj2;
   1161       1.1  mrg      b4: obj2's all counts are 0;
   1162       1.1  mrg      b5: obj2's all counts are cold (but no 0);
   1163       1.1  mrg      b6: obj2 is hot;
   1164       1.1  mrg      b7: no obj2 to match obj1;
   1165       1.1  mrg  */
   1166       1.1  mrg struct overlap_t {
   1167       1.1  mrg    const struct gcov_info *obj1;
   1168       1.1  mrg    const struct gcov_info *obj2;
   1169       1.1  mrg    char flag;
   1170       1.1  mrg };
   1171       1.1  mrg 
   1172       1.1  mrg #define FLAG_BOTH_ZERO(flag) ((flag & 0x1) && (flag & 0x10))
   1173       1.1  mrg #define FLAG_BOTH_COLD(flag) ((flag & 0x2) && (flag & 0x20))
   1174       1.1  mrg #define FLAG_ONE_HOT(flag) ((flag & 0x4) || (flag & 0x40))
   1175       1.1  mrg 
   1176       1.1  mrg /* Cumlative overlap dscore for profile1 and profile2.  */
   1177       1.1  mrg static double overlap_sum_1, overlap_sum_2;
   1178       1.1  mrg 
   1179       1.1  mrg /* The number of gcda files in the profiles.  */
   1180       1.1  mrg static unsigned gcda_files[2];
   1181       1.1  mrg 
   1182       1.1  mrg /* The number of unique gcda files in the profiles
   1183       1.1  mrg    (not existing in the other profile).  */
   1184       1.1  mrg static unsigned unique_gcda_files[2];
   1185       1.1  mrg 
   1186       1.1  mrg /* The number of gcda files that all counter values are 0.  */
   1187       1.1  mrg static unsigned zero_gcda_files[2];
   1188       1.1  mrg 
   1189       1.1  mrg /* The number of gcda files that all counter values are cold (but not 0).  */
   1190       1.1  mrg static unsigned cold_gcda_files[2];
   1191       1.1  mrg 
   1192       1.1  mrg /* The number of gcda files that includes hot counter values.  */
   1193       1.1  mrg static unsigned hot_gcda_files[2];
   1194       1.1  mrg 
   1195       1.1  mrg /* The number of gcda files with hot count value in either profiles.  */
   1196       1.1  mrg static unsigned both_hot_cnt;
   1197       1.1  mrg 
   1198       1.1  mrg /* The number of gcda files with all counts cold (but not 0) in
   1199       1.1  mrg    both profiles. */
   1200       1.1  mrg static unsigned both_cold_cnt;
   1201       1.1  mrg 
   1202       1.1  mrg /* The number of gcda files with all counts 0 in both profiles.  */
   1203       1.1  mrg static unsigned both_zero_cnt;
   1204       1.1  mrg 
   1205       1.1  mrg /* Extract the basename of the filename NAME.  */
   1206       1.1  mrg 
   1207       1.1  mrg static char *
   1208       1.1  mrg extract_file_basename (const char *name)
   1209       1.1  mrg {
   1210       1.1  mrg   char *str;
   1211       1.1  mrg   int len = 0;
   1212       1.1  mrg   char *path = xstrdup (name);
   1213       1.1  mrg   char sep_str[2];
   1214       1.1  mrg 
   1215       1.1  mrg   sep_str[0] = DIR_SEPARATOR;
   1216       1.1  mrg   sep_str[1] = 0;
   1217       1.1  mrg   str = strstr(path, sep_str);
   1218       1.1  mrg   do{
   1219       1.1  mrg       len = strlen(str) + 1;
   1220       1.1  mrg       path = &path[strlen(path) - len + 2];
   1221       1.1  mrg       str = strstr(path, sep_str);
   1222       1.1  mrg   } while(str);
   1223       1.1  mrg 
   1224       1.1  mrg   return path;
   1225       1.1  mrg }
   1226       1.1  mrg 
   1227       1.1  mrg /* Utility function to get the filename.  */
   1228       1.1  mrg 
   1229       1.1  mrg static const char *
   1230       1.1  mrg get_file_basename (const char *name)
   1231       1.1  mrg {
   1232       1.1  mrg   if (overlap_use_fullname)
   1233       1.1  mrg     return name;
   1234       1.1  mrg   return extract_file_basename (name);
   1235       1.1  mrg }
   1236       1.1  mrg 
   1237       1.1  mrg /* A utility function to set the flag for the gcda files.  */
   1238       1.1  mrg 
   1239       1.1  mrg static void
   1240       1.1  mrg set_flag (struct overlap_t *e)
   1241       1.1  mrg {
   1242       1.1  mrg   char flag = 0;
   1243       1.1  mrg 
   1244       1.1  mrg   if (!e->obj1)
   1245       1.1  mrg     {
   1246       1.1  mrg       unique_gcda_files[1]++;
   1247       1.1  mrg       flag = 0x8;
   1248       1.1  mrg     }
   1249       1.1  mrg   else
   1250       1.1  mrg     {
   1251       1.1  mrg       gcda_files[0]++;
   1252       1.1  mrg       if (gcov_info_count_all_zero (e->obj1))
   1253       1.1  mrg         {
   1254       1.1  mrg           zero_gcda_files[0]++;
   1255       1.1  mrg           flag = 0x1;
   1256       1.1  mrg         }
   1257       1.1  mrg       else
   1258       1.1  mrg       if (gcov_info_count_all_cold (e->obj1, overlap_sum_1
   1259       1.1  mrg 			      * overlap_hot_threshold))
   1260       1.1  mrg         {
   1261       1.1  mrg           cold_gcda_files[0]++;
   1262       1.1  mrg           flag = 0x2;
   1263       1.1  mrg         }
   1264       1.1  mrg       else
   1265       1.1  mrg         {
   1266       1.1  mrg           hot_gcda_files[0]++;
   1267       1.1  mrg           flag = 0x4;
   1268       1.1  mrg         }
   1269       1.1  mrg     }
   1270       1.1  mrg 
   1271       1.1  mrg   if (!e->obj2)
   1272       1.1  mrg     {
   1273       1.1  mrg       unique_gcda_files[0]++;
   1274       1.1  mrg       flag |= (0x8 << 4);
   1275       1.1  mrg     }
   1276       1.1  mrg   else
   1277       1.1  mrg     {
   1278       1.1  mrg       gcda_files[1]++;
   1279       1.1  mrg       if (gcov_info_count_all_zero (e->obj2))
   1280       1.1  mrg         {
   1281       1.1  mrg           zero_gcda_files[1]++;
   1282       1.1  mrg           flag |= (0x1 << 4);
   1283       1.1  mrg         }
   1284       1.1  mrg       else
   1285       1.1  mrg       if (gcov_info_count_all_cold (e->obj2, overlap_sum_2
   1286       1.1  mrg 			      * overlap_hot_threshold))
   1287       1.1  mrg         {
   1288       1.1  mrg           cold_gcda_files[1]++;
   1289       1.1  mrg           flag |= (0x2 << 4);
   1290       1.1  mrg         }
   1291       1.1  mrg       else
   1292       1.1  mrg         {
   1293       1.1  mrg           hot_gcda_files[1]++;
   1294       1.1  mrg           flag |= (0x4 << 4);
   1295       1.1  mrg         }
   1296       1.1  mrg     }
   1297       1.1  mrg 
   1298       1.1  mrg   gcc_assert (flag);
   1299       1.1  mrg   e->flag = flag;
   1300       1.1  mrg }
   1301       1.1  mrg 
   1302       1.1  mrg /* Test if INFO1 and INFO2 are from the matched source file.
   1303       1.1  mrg    Return 1 if they match; return 0 otherwise.  */
   1304       1.1  mrg 
   1305       1.1  mrg static int
   1306       1.1  mrg matched_gcov_info (const struct gcov_info *info1, const struct gcov_info *info2)
   1307       1.1  mrg {
   1308       1.1  mrg   /* For FDO, we have to match the name. This can be expensive.
   1309       1.1  mrg      Maybe we should use hash here.  */
   1310       1.1  mrg   if (strcmp (info1->filename, info2->filename))
   1311       1.1  mrg     return 0;
   1312       1.1  mrg 
   1313       1.1  mrg   if (info1->n_functions != info2->n_functions)
   1314       1.1  mrg     {
   1315       1.1  mrg       fnotice (stderr, "mismatched profiles in %s (%d functions"
   1316       1.1  mrg                        " vs %d functions)\n",
   1317       1.1  mrg                        info1->filename,
   1318       1.1  mrg                        info1->n_functions,
   1319       1.1  mrg                        info2->n_functions);
   1320       1.1  mrg       return 0;
   1321       1.1  mrg     }
   1322       1.1  mrg   return 1;
   1323       1.1  mrg }
   1324       1.1  mrg 
   1325       1.1  mrg /* Compute the overlap score of two profiles with the head of GCOV_LIST1 and
   1326       1.1  mrg    GCOV_LIST1. Return a number ranging from [0.0, 1.0], with 0.0 meaning no
   1327       1.1  mrg    match and 1.0 meaning a perfect match.  */
   1328       1.1  mrg 
   1329       1.1  mrg static double
   1330       1.1  mrg calculate_overlap (struct gcov_info *gcov_list1,
   1331       1.1  mrg                    struct gcov_info *gcov_list2)
   1332       1.1  mrg {
   1333       1.1  mrg   unsigned list1_cnt = 0, list2_cnt= 0, all_cnt;
   1334       1.1  mrg   unsigned int i, j;
   1335       1.1  mrg   const struct gcov_info *gi_ptr;
   1336       1.1  mrg   struct overlap_t *all_infos;
   1337       1.1  mrg 
   1338       1.1  mrg   for (gi_ptr = gcov_list1; gi_ptr; gi_ptr = gi_ptr->next)
   1339       1.1  mrg     list1_cnt++;
   1340       1.1  mrg   for (gi_ptr = gcov_list2; gi_ptr; gi_ptr = gi_ptr->next)
   1341       1.1  mrg     list2_cnt++;
   1342       1.1  mrg   all_cnt = list1_cnt + list2_cnt;
   1343       1.1  mrg   all_infos = (struct overlap_t *) xmalloc (sizeof (struct overlap_t)
   1344       1.1  mrg                * all_cnt * 2);
   1345       1.1  mrg   gcc_assert (all_infos);
   1346       1.1  mrg 
   1347       1.1  mrg   i = 0;
   1348       1.1  mrg   for (gi_ptr = gcov_list1; gi_ptr; gi_ptr = gi_ptr->next, i++)
   1349       1.1  mrg     {
   1350       1.1  mrg       all_infos[i].obj1 = gi_ptr;
   1351       1.1  mrg       all_infos[i].obj2 = 0;
   1352       1.1  mrg     }
   1353       1.1  mrg 
   1354       1.1  mrg   for (gi_ptr = gcov_list2; gi_ptr; gi_ptr = gi_ptr->next, i++)
   1355       1.1  mrg     {
   1356       1.1  mrg       all_infos[i].obj1 = 0;
   1357       1.1  mrg       all_infos[i].obj2 = gi_ptr;
   1358       1.1  mrg     }
   1359       1.1  mrg 
   1360       1.1  mrg   for (i = list1_cnt; i < all_cnt; i++)
   1361       1.1  mrg     {
   1362       1.1  mrg       if (all_infos[i].obj2 == 0)
   1363       1.1  mrg         continue;
   1364       1.1  mrg       for (j = 0; j < list1_cnt; j++)
   1365       1.1  mrg         {
   1366       1.1  mrg           if (all_infos[j].obj2 != 0)
   1367       1.1  mrg             continue;
   1368       1.1  mrg           if (matched_gcov_info (all_infos[i].obj2, all_infos[j].obj1))
   1369       1.1  mrg             {
   1370       1.1  mrg               all_infos[j].obj2 = all_infos[i].obj2;
   1371       1.1  mrg               all_infos[i].obj2 = 0;
   1372       1.1  mrg               break;
   1373       1.1  mrg             }
   1374       1.1  mrg         }
   1375       1.1  mrg     }
   1376       1.1  mrg 
   1377       1.1  mrg   for (i = 0; i < all_cnt; i++)
   1378       1.1  mrg     if (all_infos[i].obj1 || all_infos[i].obj2)
   1379       1.1  mrg       {
   1380       1.1  mrg         set_flag (all_infos + i);
   1381       1.1  mrg         if (FLAG_ONE_HOT (all_infos[i].flag))
   1382       1.1  mrg             both_hot_cnt++;
   1383       1.1  mrg         if (FLAG_BOTH_COLD(all_infos[i].flag))
   1384       1.1  mrg             both_cold_cnt++;
   1385       1.1  mrg         if (FLAG_BOTH_ZERO(all_infos[i].flag))
   1386       1.1  mrg             both_zero_cnt++;
   1387       1.1  mrg       }
   1388       1.1  mrg 
   1389       1.1  mrg   double prg_val = 0;
   1390       1.1  mrg   double sum_val = 0;
   1391       1.1  mrg   double sum_cum_1 = 0;
   1392       1.1  mrg   double sum_cum_2 = 0;
   1393       1.1  mrg 
   1394       1.1  mrg   for (i = 0; i < all_cnt; i++)
   1395       1.1  mrg     {
   1396       1.1  mrg       double val;
   1397       1.1  mrg       double cum_1, cum_2;
   1398       1.1  mrg       const char *filename;
   1399       1.1  mrg 
   1400       1.1  mrg       if (all_infos[i].obj1 == 0 && all_infos[i].obj2 == 0)
   1401       1.1  mrg         continue;
   1402       1.1  mrg       if (FLAG_BOTH_ZERO (all_infos[i].flag))
   1403       1.1  mrg           continue;
   1404       1.1  mrg 
   1405       1.1  mrg       if (all_infos[i].obj1)
   1406       1.1  mrg         filename = get_file_basename (all_infos[i].obj1->filename);
   1407       1.1  mrg       else
   1408       1.1  mrg         filename = get_file_basename (all_infos[i].obj2->filename);
   1409       1.1  mrg 
   1410       1.1  mrg       if (overlap_func_level)
   1411       1.1  mrg         printf("\n   processing %36s:\n", filename);
   1412       1.1  mrg 
   1413       1.1  mrg       val = compute_one_gcov (all_infos[i].obj1, all_infos[i].obj2,
   1414       1.1  mrg           overlap_sum_1, overlap_sum_2, &cum_1, &cum_2);
   1415       1.1  mrg 
   1416       1.1  mrg       if (overlap_obj_level && (!overlap_hot_only || FLAG_ONE_HOT (all_infos[i].flag)))
   1417       1.1  mrg         {
   1418       1.1  mrg           printf("   obj=%36s  overlap = %6.2f%% (%5.2f%% %5.2f%%)\n",
   1419       1.1  mrg                   filename, val*100, cum_1*100, cum_2*100);
   1420       1.1  mrg           sum_val += val;
   1421       1.1  mrg           sum_cum_1 += cum_1;
   1422       1.1  mrg           sum_cum_2 += cum_2;
   1423       1.1  mrg         }
   1424       1.1  mrg 
   1425       1.1  mrg       prg_val += val;
   1426       1.1  mrg 
   1427       1.1  mrg     }
   1428       1.1  mrg 
   1429   1.1.1.8  mrg   free (all_infos);
   1430   1.1.1.8  mrg 
   1431       1.1  mrg   if (overlap_obj_level)
   1432       1.1  mrg     printf("   SUM:%36s  overlap = %6.2f%% (%5.2f%% %5.2f%%)\n",
   1433       1.1  mrg            "", sum_val*100, sum_cum_1*100, sum_cum_2*100);
   1434       1.1  mrg 
   1435       1.1  mrg   printf ("  Statistics:\n"
   1436       1.1  mrg           "                    profile1_#     profile2_#       overlap_#\n");
   1437       1.1  mrg   printf ("    gcda files:  %12u\t%12u\t%12u\n", gcda_files[0], gcda_files[1],
   1438   1.1.1.2  mrg 	  gcda_files[0]-unique_gcda_files[0]);
   1439       1.1  mrg   printf ("  unique files:  %12u\t%12u\n", unique_gcda_files[0],
   1440   1.1.1.2  mrg 	  unique_gcda_files[1]);
   1441       1.1  mrg   printf ("     hot files:  %12u\t%12u\t%12u\n", hot_gcda_files[0],
   1442   1.1.1.2  mrg 	  hot_gcda_files[1], both_hot_cnt);
   1443       1.1  mrg   printf ("    cold files:  %12u\t%12u\t%12u\n", cold_gcda_files[0],
   1444   1.1.1.2  mrg 	  cold_gcda_files[1], both_cold_cnt);
   1445       1.1  mrg   printf ("    zero files:  %12u\t%12u\t%12u\n", zero_gcda_files[0],
   1446   1.1.1.2  mrg 	  zero_gcda_files[1], both_zero_cnt);
   1447       1.1  mrg 
   1448       1.1  mrg   return prg_val;
   1449       1.1  mrg }
   1450       1.1  mrg 
   1451   1.1.1.3  mrg /* Compute the overlap score of two lists of gcov_info objects PROFILE1 and
   1452   1.1.1.3  mrg    PROFILE2.
   1453       1.1  mrg    Return 0 on success: without mismatch. Reutrn 1 on error.  */
   1454       1.1  mrg 
   1455       1.1  mrg int
   1456       1.1  mrg gcov_profile_overlap (struct gcov_info *profile1, struct gcov_info *profile2)
   1457       1.1  mrg {
   1458       1.1  mrg   double result;
   1459       1.1  mrg 
   1460       1.1  mrg   result = calculate_overlap (profile1, profile2);
   1461       1.1  mrg 
   1462       1.1  mrg   if (result > 0)
   1463       1.1  mrg     {
   1464       1.1  mrg       printf("\nProgram level overlap result is %3.2f%%\n\n", result*100);
   1465       1.1  mrg       return 0;
   1466       1.1  mrg     }
   1467       1.1  mrg   return 1;
   1468       1.1  mrg }
   1469