Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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