OSDN Git Service

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