OSDN Git Service

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