expr.c (convert_move): Use emit_store_flag instead of "emulating" it.
[official-gcc.git] / gcc / libgcov.c
blobcda71bcfbd956a247589459e57afded75114d2d2
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.
7 This file is part of GCC.
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.
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.)
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.
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. */
33 #include "tconfig.h"
34 #include "tsystem.h"
35 #include "coretypes.h"
36 #include "tm.h"
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"
50 #if defined(inhibit_libc)
51 /* If libc and its header files are not available, provide dummy functions. */
53 #ifdef L_gcov
54 void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {}
55 void __gcov_flush (void) {}
56 #endif
58 #ifdef L_gcov_merge_add
59 void __gcov_merge_add (gcov_type *counters __attribute__ ((unused)),
60 unsigned n_counters __attribute__ ((unused))) {}
61 #endif
63 #ifdef L_gcov_merge_single
64 void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)),
65 unsigned n_counters __attribute__ ((unused))) {}
66 #endif
68 #ifdef L_gcov_merge_delta
69 void __gcov_merge_delta (gcov_type *counters __attribute__ ((unused)),
70 unsigned n_counters __attribute__ ((unused))) {}
71 #endif
73 #else
75 #include <string.h>
76 #if GCOV_LOCKED
77 #include <fcntl.h>
78 #include <errno.h>
79 #include <sys/stat.h>
80 #endif
82 #ifdef L_gcov
83 #include "gcov-io.c"
85 /* Chain of per-object gcov structures. */
86 static struct gcov_info *gcov_list;
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;
92 /* Size of the longest file name. */
93 static size_t gcov_max_filename = 0;
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. */
100 static int
101 create_file_directory (char *filename)
103 char *s;
105 for (s = filename + 1; *s != '\0'; s++)
106 if (IS_DIR_SEPARATOR(*s))
108 char sep = *s;
109 *s = '\0';
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)
117 fprintf (stderr, "profiling:%s:Cannot create directory\n",
118 filename);
119 *s = sep;
120 return -1;
123 *s = sep;
125 return 0;
127 #endif
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. */
134 static int
135 gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
136 const char *filename)
138 if (version != GCOV_VERSION)
140 char v[4], e[4];
142 GCOV_UNSIGNED2STRING (v, version);
143 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
145 fprintf (stderr,
146 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
147 filename? filename : ptr->filename, e, v);
148 return 0;
150 return 1;
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. */
160 static void
161 gcov_exit (void)
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;
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)
180 ci_ptr = gi_ptr->counts;
181 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
183 if (!((1 << t_ix) & gi_ptr->ctr_mask))
184 continue;
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++)
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];
194 ci_ptr++;
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))
202 /* Check if the level of dirs to strip off specified. */
203 char *tmp = getenv("GCOV_PREFIX_STRIP");
204 if (tmp)
206 gcov_prefix_strip = atoi (tmp);
207 /* Do not consider negative values. */
208 if (gcov_prefix_strip < 0)
209 gcov_prefix_strip = 0;
212 prefix_length = strlen(gcov_prefix);
214 /* Remove an unnecessary trailing '/' */
215 if (IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1]))
216 prefix_length--;
218 else
219 prefix_length = 0;
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;
227 /* Now merge each file. */
228 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
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;
242 memset (&this_object, 0, sizeof (this_object));
243 memset (&object, 0, sizeof (object));
245 /* Build relocated filename, stripping off leading
246 directories from the initial filename if requested. */
247 if (gcov_prefix_strip > 0)
249 int level = 0;
250 const char *fname = gi_ptr->filename;
251 const char *s;
253 /* Skip selected directory levels. */
254 for (s = fname + 1; (*s != '\0') && (level < gcov_prefix_strip); s++)
255 if (IS_DIR_SEPARATOR(*s))
257 fname = s;
258 level++;
261 /* Update complete filename with stripped original. */
262 strcpy (gi_filename_up, fname);
264 else
265 strcpy (gi_filename_up, gi_ptr->filename);
267 /* Totals for this object file. */
268 ci_ptr = gi_ptr->counts;
269 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
271 if (!((1 << t_ix) & gi_ptr->ctr_mask))
272 continue;
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++)
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];
283 ci_ptr++;
286 c_ix = 0;
287 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
288 if ((1 << t_ix) & gi_ptr->ctr_mask)
290 values[c_ix] = gi_ptr->counts[c_ix].values;
291 c_ix++;
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))
299 fi_stride += __alignof__ (struct gcov_fn_info) - 1;
300 fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1);
303 if (!gcov_open (gi_filename))
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))
310 fprintf (stderr, "profiling:%s:Skip\n", gi_filename);
311 continue;
313 #endif
314 if (!gcov_open (gi_filename))
316 fprintf (stderr, "profiling:%s:Cannot open\n", gi_filename);
317 continue;
321 tag = gcov_read_unsigned ();
322 if (tag)
324 /* Merge data from file. */
325 if (tag != GCOV_DATA_MAGIC)
327 fprintf (stderr, "profiling:%s:Not a gcov data file\n",
328 gi_filename);
329 goto read_fatal;
331 length = gcov_read_unsigned ();
332 if (!gcov_version (gi_ptr, length, gi_filename))
333 goto read_fatal;
335 length = gcov_read_unsigned ();
336 if (length != gi_ptr->stamp)
337 /* Read from a different compilation. Overwrite the file. */
338 goto rewrite;
340 /* Merge execution counts for each function. */
341 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
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 ();
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)
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;
361 c_ix = 0;
362 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
364 gcov_merge_fn merge;
366 if (!((1 << t_ix) & gi_ptr->ctr_mask))
367 continue;
369 n_counts = fi_ptr->n_ctrs[c_ix];
370 merge = gi_ptr->counts[c_ix].merge;
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++;
381 if ((error = gcov_is_error ()))
382 goto read_error;
385 f_ix = ~0u;
386 /* Check program & object summary */
387 while (1)
389 int is_program;
391 eof_pos = gcov_position ();
392 tag = gcov_read_unsigned ();
393 if (!tag)
394 break;
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)
406 summary_pos = eof_pos;
407 goto rewrite;
411 goto rewrite;
413 read_error:;
414 fprintf (stderr, error < 0 ? "profiling:%s:Overflow merging\n"
415 : "profiling:%s:Error merging\n", gi_filename);
417 read_fatal:;
418 gcov_close ();
419 continue;
421 rewrite:;
422 gcov_rewrite ();
423 if (!summary_pos)
424 memset (&program, 0, sizeof (program));
426 /* Merge the summaries. */
427 f_ix = ~0u;
428 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
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];
436 if ((1 << t_ix) & gi_ptr->ctr_mask)
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;
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;
456 else if (cs_obj->num || cs_prg->num)
457 goto read_mismatch;
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)))
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;
472 c_ix = 0;
473 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
474 if ((1 << t_ix) & gi_ptr->ctr_mask)
476 values[c_ix] = gi_ptr->counts[c_ix].values;
477 c_ix++;
480 program.checksum = gcov_crc32;
482 /* Write out the data. */
483 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
484 gcov_write_unsigned (gi_ptr->stamp);
486 /* Write execution counts for each function. */
487 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
489 fi_ptr = (const struct gcov_fn_info *)
490 ((const char *) gi_ptr->functions + f_ix * fi_stride);
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);
497 c_ix = 0;
498 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
500 gcov_type *c_ptr;
502 if (!((1 << t_ix) & gi_ptr->ctr_mask))
503 continue;
505 n_counts = fi_ptr->n_ctrs[c_ix];
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++);
513 values[c_ix] = c_ptr;
514 c_ix++;
518 /* Object file summary. */
519 gcov_write_summary (GCOV_TAG_OBJECT_SUMMARY, &object);
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);
535 /* Add a new object file onto the bb chain. Invoked automatically
536 when running an object file's global ctors. */
538 void
539 __gcov_init (struct gcov_info *info)
541 if (!info->version)
542 return;
543 if (gcov_version (info, info->version, 0))
545 const char *ptr = info->filename;
546 gcov_unsigned_t crc32 = gcov_crc32;
547 size_t filename_length = strlen(info->filename);
549 /* Refresh the longest file name information */
550 if (filename_length > gcov_max_filename)
551 gcov_max_filename = filename_length;
555 unsigned ix;
556 gcov_unsigned_t value = *ptr << 24;
558 for (ix = 8; ix--; value <<= 1)
560 gcov_unsigned_t feedback;
562 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
563 crc32 <<= 1;
564 crc32 ^= feedback;
567 while (*ptr++);
569 gcov_crc32 = crc32;
571 if (!gcov_list)
572 atexit (gcov_exit);
574 info->next = gcov_list;
575 gcov_list = info;
577 info->version = 0;
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. */
584 void
585 __gcov_flush (void)
587 const struct gcov_info *gi_ptr;
589 gcov_exit ();
590 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
592 unsigned t_ix;
593 const struct gcov_ctr_info *ci_ptr;
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)
598 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
599 ci_ptr++;
604 #endif /* L_gcov */
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)
613 for (; n_counters; counters++, n_counters--)
614 *counters += gcov_read_counter ();
616 #endif /* L_gcov_merge_add */
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)
625 for (; n_counters; counters++, n_counters--)
626 *counters |= gcov_read_counter ();
628 #endif
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:
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)
643 unsigned i, n_measures;
644 gcov_type value, counter, all;
646 gcc_assert (!(n_counters % 3));
647 n_measures = n_counters / 3;
648 for (i = 0; i < n_measures; i++, counters += 3)
650 value = gcov_read_counter ();
651 counter = gcov_read_counter ();
652 all = gcov_read_counter ();
654 if (counters[0] == value)
655 counters[1] += counter;
656 else if (counter > counters[1])
658 counters[0] = value;
659 counters[1] = counter - counters[1];
661 else
662 counters[1] -= counter;
663 counters[2] += all;
666 #endif /* L_gcov_merge_single */
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:
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)
682 unsigned i, n_measures;
683 gcov_type last, value, counter, all;
685 gcc_assert (!(n_counters % 4));
686 n_measures = n_counters / 4;
687 for (i = 0; i < n_measures; i++, counters += 4)
689 last = gcov_read_counter ();
690 value = gcov_read_counter ();
691 counter = gcov_read_counter ();
692 all = gcov_read_counter ();
694 if (counters[1] == value)
695 counters[2] += counter;
696 else if (counter > counters[2])
698 counters[1] = value;
699 counters[2] = counter - counters[2];
701 else
702 counters[2] -= counter;
703 counters[3] += all;
706 #endif /* L_gcov_merge_delta */
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. */
714 void
715 __gcov_interval_profiler (gcov_type *counters, gcov_type value,
716 int start, unsigned steps)
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]++;
726 #endif
728 #ifdef L_gcov_pow2_profiler
729 /* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise
730 COUNTERS[0] is incremented. */
732 void
733 __gcov_pow2_profiler (gcov_type *counters, gcov_type value)
735 if (value & (value - 1))
736 counters[0]++;
737 else
738 counters[1]++;
740 #endif
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.
750 In any case, COUNTERS[2] is incremented. */
752 static inline void
753 __gcov_one_value_profiler_body (gcov_type *counters, gcov_type value)
755 if (value == counters[0])
756 counters[1]++;
757 else if (counters[1] == 0)
759 counters[1] = 1;
760 counters[0] = value;
762 else
763 counters[1]--;
764 counters[2]++;
767 #ifdef L_gcov_one_value_profiler
768 void
769 __gcov_one_value_profiler (gcov_type *counters, gcov_type value)
771 __gcov_one_value_profiler_body (counters, value);
773 #endif
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)
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);
789 #endif
792 #ifdef L_gcov_average_profiler
793 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
794 to saturate up. */
796 void
797 __gcov_average_profiler (gcov_type *counters, gcov_type value)
799 counters[0] += value;
800 counters[1] ++;
802 #endif
804 #ifdef L_gcov_ior_profiler
805 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
806 to saturate up. */
808 void
809 __gcov_ior_profiler (gcov_type *counters, gcov_type value)
811 *counters |= value;
813 #endif
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. */
819 pid_t
820 __gcov_fork (void)
822 __gcov_flush ();
823 return fork ();
825 #endif
827 #ifdef L_gcov_execl
828 /* A wrapper for the execl function. Flushes the accumulated profiling data, so
829 that they are not lost. */
832 __gcov_execl (const char *path, char *arg, ...)
834 va_list ap, aq;
835 unsigned i, length;
836 char **args;
838 __gcov_flush ();
840 va_start (ap, arg);
841 va_copy (aq, ap);
843 length = 2;
844 while (va_arg (ap, char *))
845 length++;
846 va_end (ap);
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);
854 return execv (path, args);
856 #endif
858 #ifdef L_gcov_execlp
859 /* A wrapper for the execlp function. Flushes the accumulated profiling data, so
860 that they are not lost. */
863 __gcov_execlp (const char *path, char *arg, ...)
865 va_list ap, aq;
866 unsigned i, length;
867 char **args;
869 __gcov_flush ();
871 va_start (ap, arg);
872 va_copy (aq, ap);
874 length = 2;
875 while (va_arg (ap, char *))
876 length++;
877 va_end (ap);
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);
885 return execvp (path, args);
887 #endif
889 #ifdef L_gcov_execle
890 /* A wrapper for the execle function. Flushes the accumulated profiling data, so
891 that they are not lost. */
894 __gcov_execle (const char *path, char *arg, ...)
896 va_list ap, aq;
897 unsigned i, length;
898 char **args;
899 char **envp;
901 __gcov_flush ();
903 va_start (ap, arg);
904 va_copy (aq, ap);
906 length = 2;
907 while (va_arg (ap, char *))
908 length++;
909 va_end (ap);
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);
918 return execve (path, args, envp);
920 #endif
922 #ifdef L_gcov_execv
923 /* A wrapper for the execv function. Flushes the accumulated profiling data, so
924 that they are not lost. */
927 __gcov_execv (const char *path, char *const argv[])
929 __gcov_flush ();
930 return execv (path, argv);
932 #endif
934 #ifdef L_gcov_execvp
935 /* A wrapper for the execvp function. Flushes the accumulated profiling data, so
936 that they are not lost. */
939 __gcov_execvp (const char *path, char *const argv[])
941 __gcov_flush ();
942 return execvp (path, argv);
944 #endif
946 #ifdef L_gcov_execve
947 /* A wrapper for the execve function. Flushes the accumulated profiling data, so
948 that they are not lost. */
951 __gcov_execve (const char *path, char *const argv[], char *const envp[])
953 __gcov_flush ();
954 return execve (path, argv, envp);
956 #endif
957 #endif /* inhibit_libc */