OSDN Git Service

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