OSDN Git Service

* final.c (insn_default_length, insn_min_length): In !HAVE_ATTR_length
[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  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 = 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 = 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 = 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 = 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 */