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