OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [libgcov.c] - Blame information for rev 833

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 julius
/* Routines required for instrumenting a program.  */
2
/* Compile this one with gcc.  */
3
/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
4
   2000, 2001, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
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 2, or (at your option) any later
11
version.
12
 
13
In addition to the permissions in the GNU General Public License, the
14
Free Software Foundation gives you unlimited permission to link the
15
compiled version of this file into combinations with other programs,
16
and to distribute those combinations without any restriction coming
17
from the use of this file.  (The General Public License restrictions
18
do apply in other respects; for example, they cover modification of
19
the file, and distribution when not linked into a combine
20
executable.)
21
 
22
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
23
WARRANTY; without even the implied warranty of MERCHANTABILITY or
24
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
25
for more details.
26
 
27
You should have received a copy of the GNU General Public License
28
along with GCC; see the file COPYING.  If not, write to the Free
29
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
30
02110-1301, USA.  */
31
 
32
#include "tconfig.h"
33
#include "tsystem.h"
34
#include "coretypes.h"
35
#include "tm.h"
36
 
37
#if defined(inhibit_libc)
38
#define IN_LIBGCOV (-1)
39
#else
40
#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
41
#include <stdio.h>
42
#define IN_LIBGCOV 1
43
#if defined(L_gcov)
44
#define GCOV_LINKAGE /* nothing */
45
#endif
46
#endif
47
#include "gcov-io.h"
48
 
49
#if defined(inhibit_libc)
50
/* If libc and its header files are not available, provide dummy functions.  */
51
 
52
#ifdef L_gcov
53
void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {}
54
void __gcov_flush (void) {}
55
#endif
56
 
57
#ifdef L_gcov_merge_add
58
void __gcov_merge_add (gcov_type *counters  __attribute__ ((unused)),
59
                       unsigned n_counters __attribute__ ((unused))) {}
60
#endif
61
 
62
#ifdef L_gcov_merge_single
63
void __gcov_merge_single (gcov_type *counters  __attribute__ ((unused)),
64
                          unsigned n_counters __attribute__ ((unused))) {}
65
#endif
66
 
67
#ifdef L_gcov_merge_delta
68
void __gcov_merge_delta (gcov_type *counters  __attribute__ ((unused)),
69
                         unsigned n_counters __attribute__ ((unused))) {}
70
#endif
71
 
72
#else
73
 
74
#include <string.h>
75
#if GCOV_LOCKED
76
#include <fcntl.h>
77
#include <errno.h>
78
#include <sys/stat.h>
79
#endif
80
 
81
#ifdef L_gcov
82
#include "gcov-io.c"
83
 
84
/* Chain of per-object gcov structures.  */
85
static struct gcov_info *gcov_list;
86
 
87
/* A program checksum allows us to distinguish program data for an
88
   object file included in multiple programs.  */
89
static gcov_unsigned_t gcov_crc32;
90
 
91
/* Size of the longest file name. */
92
static size_t gcov_max_filename = 0;
93
 
94
#ifdef TARGET_POSIX_IO
95
/* Make sure path component of the given FILENAME exists, create
96
   missing directories. FILENAME must be writable.
97
   Returns zero on success, or -1 if an error occurred.  */
98
 
99
static int
100
create_file_directory (char *filename)
101
{
102
  char *s;
103
 
104
  for (s = filename + 1; *s != '\0'; s++)
105
    if (IS_DIR_SEPARATOR(*s))
106
      {
107
        char sep = *s;
108
        *s  = '\0';
109
 
110
        /* Try to make directory if it doesn't already exist.  */
111
        if (access (filename, F_OK) == -1
112
            && mkdir (filename, 0755) == -1
113
            /* The directory might have been made by another process.  */
114
            && errno != EEXIST)
115
          {
116
            fprintf (stderr, "profiling:%s:Cannot create directory\n",
117
                     filename);
118
            *s = sep;
119
            return -1;
120
          };
121
 
122
        *s = sep;
123
      };
124
  return 0;
125
}
126
#endif
127
 
128
/* Check if VERSION of the info block PTR matches libgcov one.
129
   Return 1 on success, or zero in case of versions mismatch.
130
   If FILENAME is not NULL, its value used for reporting purposes
131
   instead of value from the info block.  */
132
 
133
static int
134
gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
135
              const char *filename)
136
{
137
  if (version != GCOV_VERSION)
138
    {
139
      char v[4], e[4];
140
 
141
      GCOV_UNSIGNED2STRING (v, version);
142
      GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
143
 
144
      fprintf (stderr,
145
               "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
146
               filename? filename : ptr->filename, e, v);
147
      return 0;
148
    }
149
  return 1;
150
}
151
 
152
/* Dump the coverage counts. We merge with existing counts when
153
   possible, to avoid growing the .da files ad infinitum. We use this
154
   program's checksum to make sure we only accumulate whole program
155
   statistics to the correct summary. An object file might be embedded
156
   in two separate programs, and we must keep the two program
157
   summaries separate.  */
158
 
159
static void
160
gcov_exit (void)
161
{
162
  struct gcov_info *gi_ptr;
163
  struct gcov_summary this_program;
164
  struct gcov_summary all;
165
  struct gcov_ctr_summary *cs_ptr;
166
  const struct gcov_ctr_info *ci_ptr;
167
  unsigned t_ix;
168
  gcov_unsigned_t c_num;
169
  const char *gcov_prefix;
170
  int gcov_prefix_strip = 0;
171
  size_t prefix_length;
172
  char *gi_filename, *gi_filename_up;
173
 
174
  memset (&all, 0, sizeof (all));
175
  /* Find the totals for this execution.  */
176
  memset (&this_program, 0, sizeof (this_program));
177
  for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
178
    {
179
      ci_ptr = gi_ptr->counts;
180
      for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
181
        {
182
          if (!((1 << t_ix) & gi_ptr->ctr_mask))
183
            continue;
184
 
185
          cs_ptr = &this_program.ctrs[t_ix];
186
          cs_ptr->num += ci_ptr->num;
187
          for (c_num = 0; c_num < ci_ptr->num; c_num++)
188
            {
189
              cs_ptr->sum_all += ci_ptr->values[c_num];
190
              if (cs_ptr->run_max < ci_ptr->values[c_num])
191
                cs_ptr->run_max = ci_ptr->values[c_num];
192
            }
193
          ci_ptr++;
194
        }
195
    }
196
 
197
  /* Get file name relocation prefix.  Non-absolute values are ignored. */
198
  gcov_prefix = getenv("GCOV_PREFIX");
199
  if (gcov_prefix && IS_ABSOLUTE_PATH (gcov_prefix))
200
    {
201
      /* Check if the level of dirs to strip off specified. */
202
      char *tmp = getenv("GCOV_PREFIX_STRIP");
203
      if (tmp)
204
        {
205
          gcov_prefix_strip = atoi (tmp);
206
          /* Do not consider negative values. */
207
          if (gcov_prefix_strip < 0)
208
            gcov_prefix_strip = 0;
209
        }
210
 
211
      prefix_length = strlen(gcov_prefix);
212
 
213
      /* Remove an unnecessary trailing '/' */
214
      if (IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1]))
215
        prefix_length--;
216
    }
217
  else
218
    prefix_length = 0;
219
 
220
  /* Allocate and initialize the filename scratch space.  */
221
  gi_filename = (char *) alloca (prefix_length + gcov_max_filename + 1);
222
  if (prefix_length)
223
    memcpy (gi_filename, gcov_prefix, prefix_length);
224
  gi_filename_up = gi_filename + prefix_length;
225
 
226
  /* Now merge each file.  */
227
  for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
228
    {
229
      struct gcov_summary this_object;
230
      struct gcov_summary object, program;
231
      gcov_type *values[GCOV_COUNTERS];
232
      const struct gcov_fn_info *fi_ptr;
233
      unsigned fi_stride;
234
      unsigned c_ix, f_ix, n_counts;
235
      struct gcov_ctr_summary *cs_obj, *cs_tobj, *cs_prg, *cs_tprg, *cs_all;
236
      int error = 0;
237
      gcov_unsigned_t tag, length;
238
      gcov_position_t summary_pos = 0;
239
      gcov_position_t eof_pos = 0;
240
 
241
      memset (&this_object, 0, sizeof (this_object));
242
      memset (&object, 0, sizeof (object));
243
 
244
      /* Build relocated filename, stripping off leading
245
         directories from the initial filename if requested. */
246
      if (gcov_prefix_strip > 0)
247
        {
248
          int level = 0;
249
          const char *fname = gi_ptr->filename;
250
          const char *s;
251
 
252
          /* Skip selected directory levels. */
253
          for (s = fname + 1; (*s != '\0') && (level < gcov_prefix_strip); s++)
254
            if (IS_DIR_SEPARATOR(*s))
255
              {
256
                fname = s;
257
                level++;
258
              };
259
 
260
          /* Update complete filename with stripped original. */
261
          strcpy (gi_filename_up, fname);
262
        }
263
      else
264
        strcpy (gi_filename_up, gi_ptr->filename);
265
 
266
      /* Totals for this object file.  */
267
      ci_ptr = gi_ptr->counts;
268
      for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
269
        {
270
          if (!((1 << t_ix) & gi_ptr->ctr_mask))
271
            continue;
272
 
273
          cs_ptr = &this_object.ctrs[t_ix];
274
          cs_ptr->num += ci_ptr->num;
275
          for (c_num = 0; c_num < ci_ptr->num; c_num++)
276
            {
277
              cs_ptr->sum_all += ci_ptr->values[c_num];
278
              if (cs_ptr->run_max < ci_ptr->values[c_num])
279
                cs_ptr->run_max = ci_ptr->values[c_num];
280
            }
281
 
282
          ci_ptr++;
283
        }
284
 
285
      c_ix = 0;
286
      for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
287
        if ((1 << t_ix) & gi_ptr->ctr_mask)
288
          {
289
            values[c_ix] = gi_ptr->counts[c_ix].values;
290
            c_ix++;
291
          }
292
 
293
      /* Calculate the function_info stride. This depends on the
294
         number of counter types being measured.  */
295
      fi_stride = sizeof (struct gcov_fn_info) + c_ix * sizeof (unsigned);
296
      if (__alignof__ (struct gcov_fn_info) > sizeof (unsigned))
297
        {
298
          fi_stride += __alignof__ (struct gcov_fn_info) - 1;
299
          fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1);
300
        }
301
 
302
      if (!gcov_open (gi_filename))
303
        {
304
#ifdef TARGET_POSIX_IO
305
          /* Open failed likely due to missed directory.
306
             Create directory and retry to open file. */
307
          if (create_file_directory (gi_filename))
308
            {
309
              fprintf (stderr, "profiling:%s:Skip\n", gi_filename);
310
              continue;
311
            }
312
#endif
313
          if (!gcov_open (gi_filename))
314
            {
315
              fprintf (stderr, "profiling:%s:Cannot open\n", gi_filename);
316
              continue;
317
            }
318
        }
319
 
320
      tag = gcov_read_unsigned ();
321
      if (tag)
322
        {
323
          /* Merge data from file.  */
324
          if (tag != GCOV_DATA_MAGIC)
325
            {
326
              fprintf (stderr, "profiling:%s:Not a gcov data file\n",
327
                       gi_filename);
328
              goto read_fatal;
329
            }
330
          length = gcov_read_unsigned ();
331
          if (!gcov_version (gi_ptr, length, gi_filename))
332
            goto read_fatal;
333
 
334
          length = gcov_read_unsigned ();
335
          if (length != gi_ptr->stamp)
336
            /* Read from a different compilation. Overwrite the file.  */
337
            goto rewrite;
338
 
339
          /* Merge execution counts for each function.  */
340
          for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
341
            {
342
              fi_ptr = (const struct gcov_fn_info *)
343
                      ((const char *) gi_ptr->functions + f_ix * fi_stride);
344
              tag = gcov_read_unsigned ();
345
              length = gcov_read_unsigned ();
346
 
347
              /* Check function.  */
348
              if (tag != GCOV_TAG_FUNCTION
349
                  || length != GCOV_TAG_FUNCTION_LENGTH
350
                  || gcov_read_unsigned () != fi_ptr->ident
351
                  || gcov_read_unsigned () != fi_ptr->checksum)
352
                {
353
                read_mismatch:;
354
                  fprintf (stderr, "profiling:%s:Merge mismatch for %s\n",
355
                           gi_filename,
356
                           f_ix + 1 ? "function" : "summaries");
357
                  goto read_fatal;
358
                }
359
 
360
              c_ix = 0;
361
              for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
362
                {
363
                  gcov_merge_fn merge;
364
 
365
                  if (!((1 << t_ix) & gi_ptr->ctr_mask))
366
                    continue;
367
 
368
                  n_counts = fi_ptr->n_ctrs[c_ix];
369
                  merge = gi_ptr->counts[c_ix].merge;
370
 
371
                  tag = gcov_read_unsigned ();
372
                  length = gcov_read_unsigned ();
373
                  if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
374
                      || length != GCOV_TAG_COUNTER_LENGTH (n_counts))
375
                    goto read_mismatch;
376
                  (*merge) (values[c_ix], n_counts);
377
                  values[c_ix] += n_counts;
378
                  c_ix++;
379
                }
380
              if ((error = gcov_is_error ()))
381
                goto read_error;
382
            }
383
 
384
          f_ix = ~0u;
385
          /* Check program & object summary */
386
          while (1)
387
            {
388
              int is_program;
389
 
390
              eof_pos = gcov_position ();
391
              tag = gcov_read_unsigned ();
392
              if (!tag)
393
                break;
394
 
395
              length = gcov_read_unsigned ();
396
              is_program = tag == GCOV_TAG_PROGRAM_SUMMARY;
397
              if (length != GCOV_TAG_SUMMARY_LENGTH
398
                  || (!is_program && tag != GCOV_TAG_OBJECT_SUMMARY))
399
                goto read_mismatch;
400
              gcov_read_summary (is_program ? &program : &object);
401
              if ((error = gcov_is_error ()))
402
                goto read_error;
403
              if (is_program && program.checksum == gcov_crc32)
404
                {
405
                  summary_pos = eof_pos;
406
                  goto rewrite;
407
                }
408
            }
409
        }
410
      goto rewrite;
411
 
412
    read_error:;
413
      fprintf (stderr, error < 0 ? "profiling:%s:Overflow merging\n"
414
               : "profiling:%s:Error merging\n", gi_filename);
415
 
416
    read_fatal:;
417
      gcov_close ();
418
      continue;
419
 
420
    rewrite:;
421
      gcov_rewrite ();
422
      if (!summary_pos)
423
        memset (&program, 0, sizeof (program));
424
 
425
      /* Merge the summaries.  */
426
      f_ix = ~0u;
427
      for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
428
        {
429
          cs_obj = &object.ctrs[t_ix];
430
          cs_tobj = &this_object.ctrs[t_ix];
431
          cs_prg = &program.ctrs[t_ix];
432
          cs_tprg = &this_program.ctrs[t_ix];
433
          cs_all = &all.ctrs[t_ix];
434
 
435
          if ((1 << t_ix) & gi_ptr->ctr_mask)
436
            {
437
              if (!cs_obj->runs++)
438
                cs_obj->num = cs_tobj->num;
439
              else if (cs_obj->num != cs_tobj->num)
440
                goto read_mismatch;
441
              cs_obj->sum_all += cs_tobj->sum_all;
442
              if (cs_obj->run_max < cs_tobj->run_max)
443
                cs_obj->run_max = cs_tobj->run_max;
444
              cs_obj->sum_max += cs_tobj->run_max;
445
 
446
              if (!cs_prg->runs++)
447
                cs_prg->num = cs_tprg->num;
448
              else if (cs_prg->num != cs_tprg->num)
449
                goto read_mismatch;
450
              cs_prg->sum_all += cs_tprg->sum_all;
451
              if (cs_prg->run_max < cs_tprg->run_max)
452
                cs_prg->run_max = cs_tprg->run_max;
453
              cs_prg->sum_max += cs_tprg->run_max;
454
            }
455
          else if (cs_obj->num || cs_prg->num)
456
            goto read_mismatch;
457
 
458
          if (!cs_all->runs && cs_prg->runs)
459
            memcpy (cs_all, cs_prg, sizeof (*cs_all));
460
          else if (!all.checksum
461
                   && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs)
462
                   && memcmp (cs_all, cs_prg, sizeof (*cs_all)))
463
            {
464
              fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s",
465
                       gi_filename, GCOV_LOCKED
466
                       ? "" : " or concurrent update without locking support");
467
              all.checksum = ~0u;
468
            }
469
        }
470
 
471
      c_ix = 0;
472
      for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
473
        if ((1 << t_ix) & gi_ptr->ctr_mask)
474
          {
475
            values[c_ix] = gi_ptr->counts[c_ix].values;
476
            c_ix++;
477
          }
478
 
479
      program.checksum = gcov_crc32;
480
 
481
      /* Write out the data.  */
482
      gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
483
      gcov_write_unsigned (gi_ptr->stamp);
484
 
485
      /* Write execution counts for each function.  */
486
      for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
487
        {
488
          fi_ptr = (const struct gcov_fn_info *)
489
                  ((const char *) gi_ptr->functions + f_ix * fi_stride);
490
 
491
          /* Announce function.  */
492
          gcov_write_tag_length (GCOV_TAG_FUNCTION, GCOV_TAG_FUNCTION_LENGTH);
493
          gcov_write_unsigned (fi_ptr->ident);
494
          gcov_write_unsigned (fi_ptr->checksum);
495
 
496
          c_ix = 0;
497
          for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
498
            {
499
              gcov_type *c_ptr;
500
 
501
              if (!((1 << t_ix) & gi_ptr->ctr_mask))
502
                continue;
503
 
504
              n_counts = fi_ptr->n_ctrs[c_ix];
505
 
506
              gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
507
                                     GCOV_TAG_COUNTER_LENGTH (n_counts));
508
              c_ptr = values[c_ix];
509
              while (n_counts--)
510
                gcov_write_counter (*c_ptr++);
511
 
512
              values[c_ix] = c_ptr;
513
              c_ix++;
514
            }
515
        }
516
 
517
      /* Object file summary.  */
518
      gcov_write_summary (GCOV_TAG_OBJECT_SUMMARY, &object);
519
 
520
      /* Generate whole program statistics.  */
521
      if (eof_pos)
522
        gcov_seek (eof_pos);
523
      gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &program);
524
      if (!summary_pos)
525
        gcov_write_unsigned (0);
526
      if ((error = gcov_close ()))
527
          fprintf (stderr, error  < 0 ?
528
                   "profiling:%s:Overflow writing\n" :
529
                   "profiling:%s:Error writing\n",
530
                   gi_filename);
531
    }
532
}
533
 
534
/* Add a new object file onto the bb chain.  Invoked automatically
535
   when running an object file's global ctors.  */
536
 
537
void
538
__gcov_init (struct gcov_info *info)
539
{
540
  if (!info->version)
541
    return;
542
  if (gcov_version (info, info->version, 0))
543
    {
544
      const char *ptr = info->filename;
545
      gcov_unsigned_t crc32 = gcov_crc32;
546
      size_t filename_length =  strlen(info->filename);
547
 
548
      /* Refresh the longest file name information */
549
      if (filename_length > gcov_max_filename)
550
        gcov_max_filename = filename_length;
551
 
552
      do
553
        {
554
          unsigned ix;
555
          gcov_unsigned_t value = *ptr << 24;
556
 
557
          for (ix = 8; ix--; value <<= 1)
558
            {
559
              gcov_unsigned_t feedback;
560
 
561
              feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
562
              crc32 <<= 1;
563
              crc32 ^= feedback;
564
            }
565
        }
566
      while (*ptr++);
567
 
568
      gcov_crc32 = crc32;
569
 
570
      if (!gcov_list)
571
        atexit (gcov_exit);
572
 
573
      info->next = gcov_list;
574
      gcov_list = info;
575
    }
576
  info->version = 0;
577
}
578
 
579
/* Called before fork or exec - write out profile information gathered so
580
   far and reset it to zero.  This avoids duplication or loss of the
581
   profile information gathered so far.  */
582
 
583
void
584
__gcov_flush (void)
585
{
586
  const struct gcov_info *gi_ptr;
587
 
588
  gcov_exit ();
589
  for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
590
    {
591
      unsigned t_ix;
592
      const struct gcov_ctr_info *ci_ptr;
593
 
594
      for (t_ix = 0, ci_ptr = gi_ptr->counts; t_ix != GCOV_COUNTERS; t_ix++)
595
        if ((1 << t_ix) & gi_ptr->ctr_mask)
596
          {
597
            memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
598
            ci_ptr++;
599
          }
600
    }
601
}
602
 
603
#endif /* L_gcov */
604
 
605
#ifdef L_gcov_merge_add
606
/* The profile merging function that just adds the counters.  It is given
607
   an array COUNTERS of N_COUNTERS old counters and it reads the same number
608
   of counters from the gcov file.  */
609
void
610
__gcov_merge_add (gcov_type *counters, unsigned n_counters)
611
{
612
  for (; n_counters; counters++, n_counters--)
613
    *counters += gcov_read_counter ();
614
}
615
#endif /* L_gcov_merge_add */
616
 
617
#ifdef L_gcov_merge_single
618
/* The profile merging function for choosing the most common value.
619
   It is given an array COUNTERS of N_COUNTERS old counters and it
620
   reads the same number of counters from the gcov file.  The counters
621
   are split into 3-tuples where the members of the tuple have
622
   meanings:
623
 
624
   -- the stored candidate on the most common value of the measured entity
625
   -- counter
626
   -- total number of evaluations of the value  */
627
void
628
__gcov_merge_single (gcov_type *counters, unsigned n_counters)
629
{
630
  unsigned i, n_measures;
631
  gcov_type value, counter, all;
632
 
633
  gcc_assert (!(n_counters % 3));
634
  n_measures = n_counters / 3;
635
  for (i = 0; i < n_measures; i++, counters += 3)
636
    {
637
      value = gcov_read_counter ();
638
      counter = gcov_read_counter ();
639
      all = gcov_read_counter ();
640
 
641
      if (counters[0] == value)
642
        counters[1] += counter;
643
      else if (counter > counters[1])
644
        {
645
          counters[0] = value;
646
          counters[1] = counter - counters[1];
647
        }
648
      else
649
        counters[1] -= counter;
650
      counters[2] += all;
651
    }
652
}
653
#endif /* L_gcov_merge_single */
654
 
655
#ifdef L_gcov_merge_delta
656
/* The profile merging function for choosing the most common
657
   difference between two consecutive evaluations of the value.  It is
658
   given an array COUNTERS of N_COUNTERS old counters and it reads the
659
   same number of counters from the gcov file.  The counters are split
660
   into 4-tuples where the members of the tuple have meanings:
661
 
662
   -- the last value of the measured entity
663
   -- the stored candidate on the most common difference
664
   -- counter
665
   -- total number of evaluations of the value  */
666
void
667
__gcov_merge_delta (gcov_type *counters, unsigned n_counters)
668
{
669
  unsigned i, n_measures;
670
  gcov_type last, value, counter, all;
671
 
672
  gcc_assert (!(n_counters % 4));
673
  n_measures = n_counters / 4;
674
  for (i = 0; i < n_measures; i++, counters += 4)
675
    {
676
      last = gcov_read_counter ();
677
      value = gcov_read_counter ();
678
      counter = gcov_read_counter ();
679
      all = gcov_read_counter ();
680
 
681
      if (counters[1] == value)
682
        counters[2] += counter;
683
      else if (counter > counters[2])
684
        {
685
          counters[1] = value;
686
          counters[2] = counter - counters[2];
687
        }
688
      else
689
        counters[2] -= counter;
690
      counters[3] += all;
691
    }
692
}
693
#endif /* L_gcov_merge_delta */
694
 
695
#ifdef L_gcov_interval_profiler
696
/* If VALUE is in interval <START, START + STEPS - 1>, then increases the
697
   corresponding counter in COUNTERS.  If the VALUE is above or below
698
   the interval, COUNTERS[STEPS] or COUNTERS[STEPS + 1] is increased
699
   instead.  */
700
 
701
void
702
__gcov_interval_profiler (gcov_type *counters, gcov_type value,
703
                          int start, unsigned steps)
704
{
705
  gcov_type delta = value - start;
706
  if (delta < 0)
707
    counters[steps + 1]++;
708
  else if (delta >= steps)
709
    counters[steps]++;
710
  else
711
    counters[delta]++;
712
}
713
#endif
714
 
715
#ifdef L_gcov_pow2_profiler
716
/* If VALUE is a power of two, COUNTERS[1] is incremented.  Otherwise
717
   COUNTERS[0] is incremented.  */
718
 
719
void
720
__gcov_pow2_profiler (gcov_type *counters, gcov_type value)
721
{
722
  if (value & (value - 1))
723
    counters[0]++;
724
  else
725
    counters[1]++;
726
}
727
#endif
728
 
729
#ifdef L_gcov_one_value_profiler
730
/* Tries to determine the most common value among its inputs.  Checks if the
731
   value stored in COUNTERS[0] matches VALUE.  If this is the case, COUNTERS[1]
732
   is incremented.  If this is not the case and COUNTERS[1] is not zero,
733
   COUNTERS[1] is decremented.  Otherwise COUNTERS[1] is set to one and
734
   VALUE is stored to COUNTERS[0].  This algorithm guarantees that if this
735
   function is called more than 50% of the time with one value, this value
736
   will be in COUNTERS[0] in the end.
737
 
738
   In any case, COUNTERS[2] is incremented.  */
739
 
740
void
741
__gcov_one_value_profiler (gcov_type *counters, gcov_type value)
742
{
743
  if (value == counters[0])
744
    counters[1]++;
745
  else if (counters[1] == 0)
746
    {
747
      counters[1] = 1;
748
      counters[0] = value;
749
    }
750
  else
751
    counters[1]--;
752
  counters[2]++;
753
}
754
#endif
755
 
756
#ifdef L_gcov_fork
757
/* A wrapper for the fork function.  Flushes the accumulated profiling data, so
758
   that they are not counted twice.  */
759
 
760
pid_t
761
__gcov_fork (void)
762
{
763
  __gcov_flush ();
764
  return fork ();
765
}
766
#endif
767
 
768
#ifdef L_gcov_execl
769
/* A wrapper for the execl function.  Flushes the accumulated profiling data, so
770
   that they are not lost.  */
771
 
772
int
773
__gcov_execl (const char *path, const char *arg, ...)
774
{
775
  va_list ap, aq;
776
  unsigned i, length;
777
  char **args;
778
 
779
  __gcov_flush ();
780
 
781
  va_start (ap, arg);
782
  va_copy (aq, ap);
783
 
784
  length = 2;
785
  while (va_arg (ap, char *))
786
    length++;
787
  va_end (ap);
788
 
789
  args = (char **) alloca (length * sizeof (void *));
790
  args[0] = (char *) arg;
791
  for (i = 1; i < length; i++)
792
    args[i] = va_arg (aq, char *);
793
  va_end (aq);
794
 
795
  return execv (path, args);
796
}
797
#endif
798
 
799
#ifdef L_gcov_execlp
800
/* A wrapper for the execlp function.  Flushes the accumulated profiling data, so
801
   that they are not lost.  */
802
 
803
int
804
__gcov_execlp (const char *path, const char *arg, ...)
805
{
806
  va_list ap, aq;
807
  unsigned i, length;
808
  char **args;
809
 
810
  __gcov_flush ();
811
 
812
  va_start (ap, arg);
813
  va_copy (aq, ap);
814
 
815
  length = 2;
816
  while (va_arg (ap, char *))
817
    length++;
818
  va_end (ap);
819
 
820
  args = (char **) alloca (length * sizeof (void *));
821
  args[0] = (char *) arg;
822
  for (i = 1; i < length; i++)
823
    args[i] = va_arg (aq, char *);
824
  va_end (aq);
825
 
826
  return execvp (path, args);
827
}
828
#endif
829
 
830
#ifdef L_gcov_execle
831
/* A wrapper for the execle function.  Flushes the accumulated profiling data, so
832
   that they are not lost.  */
833
 
834
int
835
__gcov_execle (const char *path, const char *arg, ...)
836
{
837
  va_list ap, aq;
838
  unsigned i, length;
839
  char **args;
840
  char **envp;
841
 
842
  __gcov_flush ();
843
 
844
  va_start (ap, arg);
845
  va_copy (aq, ap);
846
 
847
  length = 2;
848
  while (va_arg (ap, char *))
849
    length++;
850
  va_end (ap);
851
 
852
  args = (char **) alloca (length * sizeof (void *));
853
  args[0] = (char *) arg;
854
  for (i = 1; i < length; i++)
855
    args[i] = va_arg (aq, char *);
856
  envp = va_arg (aq, char **);
857
  va_end (aq);
858
 
859
  return execve (path, args, envp);
860
}
861
#endif
862
 
863
#ifdef L_gcov_execv
864
/* A wrapper for the execv function.  Flushes the accumulated profiling data, so
865
   that they are not lost.  */
866
 
867
int
868
__gcov_execv (const char *path, char *const argv[])
869
{
870
  __gcov_flush ();
871
  return execv (path, argv);
872
}
873
#endif
874
 
875
#ifdef L_gcov_execvp
876
/* A wrapper for the execvp function.  Flushes the accumulated profiling data, so
877
   that they are not lost.  */
878
 
879
int
880
__gcov_execvp (const char *path, char *const argv[])
881
{
882
  __gcov_flush ();
883
  return execvp (path, argv);
884
}
885
#endif
886
 
887
#ifdef L_gcov_execve
888
/* A wrapper for the execve function.  Flushes the accumulated profiling data, so
889
   that they are not lost.  */
890
 
891
int
892
__gcov_execve (const char *path, char *const argv[], char *const envp[])
893
{
894
  __gcov_flush ();
895
  return execve (path, argv, envp);
896
}
897
#endif
898
#endif /* inhibit_libc */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.