usr.sbin/makefs: Add -o c|C option to specify comp|check type
[dragonfly.git] / contrib / gcc-4.7 / libgcc / libgcov.c
blobd75ae6955ede5b5e5c91f7dc4d5af83ee8408439
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.
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 3, or (at your option) any later
12 version.
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.
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.
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/>. */
28 #include "tconfig.h"
29 #include "tsystem.h"
30 #include "coretypes.h"
31 #include "tm.h"
32 #include "libgcc_tm.h"
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"
46 #if defined(inhibit_libc)
47 /* If libc and its header files are not available, provide dummy functions. */
49 #ifdef L_gcov
50 void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {}
51 void __gcov_flush (void) {}
52 #endif
54 #ifdef L_gcov_merge_add
55 void __gcov_merge_add (gcov_type *counters __attribute__ ((unused)),
56 unsigned n_counters __attribute__ ((unused))) {}
57 #endif
59 #ifdef L_gcov_merge_single
60 void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)),
61 unsigned n_counters __attribute__ ((unused))) {}
62 #endif
64 #ifdef L_gcov_merge_delta
65 void __gcov_merge_delta (gcov_type *counters __attribute__ ((unused)),
66 unsigned n_counters __attribute__ ((unused))) {}
67 #endif
69 #else
71 #include <string.h>
72 #if GCOV_LOCKED
73 #include <fcntl.h>
74 #include <errno.h>
75 #include <sys/stat.h>
76 #endif
78 #ifdef L_gcov
79 #include "gcov-io.c"
81 struct gcov_fn_buffer
83 struct gcov_fn_buffer *next;
84 unsigned fn_ix;
85 struct gcov_fn_info info;
86 /* note gcov_fn_info ends in a trailing array. */
89 /* Chain of per-object gcov structures. */
90 static struct gcov_info *gcov_list;
92 /* Size of the longest file name. */
93 static size_t gcov_max_filename = 0;
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. */
99 static int
100 create_file_directory (char *filename)
102 #if !defined(TARGET_POSIX_IO) && !defined(_WIN32)
103 (void) filename;
104 return -1;
105 #else
106 char *s;
108 s = filename;
110 if (HAS_DRIVE_SPEC(s))
111 s += 2;
112 if (IS_DIR_SEPARATOR(*s))
113 ++s;
114 for (; *s != '\0'; s++)
115 if (IS_DIR_SEPARATOR(*s))
117 char sep = *s;
118 *s = '\0';
120 /* Try to make directory if it doesn't already exist. */
121 if (access (filename, F_OK) == -1
122 #ifdef TARGET_POSIX_IO
123 && mkdir (filename, 0755) == -1
124 #else
125 && mkdir (filename) == -1
126 #endif
127 /* The directory might have been made by another process. */
128 && errno != EEXIST)
130 fprintf (stderr, "profiling:%s:Cannot create directory\n",
131 filename);
132 *s = sep;
133 return -1;
136 *s = sep;
138 return 0;
139 #endif
142 static struct gcov_fn_buffer *
143 free_fn_data (const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer,
144 unsigned limit)
146 struct gcov_fn_buffer *next;
147 unsigned ix, n_ctr = 0;
149 if (!buffer)
150 return 0;
151 next = buffer->next;
153 for (ix = 0; ix != limit; ix++)
154 if (gi_ptr->merge[ix])
155 free (buffer->info.ctrs[n_ctr++].values);
156 free (buffer);
157 return next;
160 static struct gcov_fn_buffer **
161 buffer_fn_data (const char *filename, const struct gcov_info *gi_ptr,
162 struct gcov_fn_buffer **end_ptr, unsigned fn_ix)
164 unsigned n_ctrs = 0, ix = 0;
165 struct gcov_fn_buffer *fn_buffer;
166 unsigned len;
168 for (ix = GCOV_COUNTERS; ix--;)
169 if (gi_ptr->merge[ix])
170 n_ctrs++;
172 len = sizeof (*fn_buffer) + sizeof (fn_buffer->info.ctrs[0]) * n_ctrs;
173 fn_buffer = (struct gcov_fn_buffer *)malloc (len);
175 if (!fn_buffer)
176 goto fail;
178 fn_buffer->next = 0;
179 fn_buffer->fn_ix = fn_ix;
180 fn_buffer->info.ident = gcov_read_unsigned ();
181 fn_buffer->info.lineno_checksum = gcov_read_unsigned ();
182 fn_buffer->info.cfg_checksum = gcov_read_unsigned ();
184 for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++)
186 gcov_unsigned_t length;
187 gcov_type *values;
189 if (!gi_ptr->merge[ix])
190 continue;
192 if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix))
194 len = 0;
195 goto fail;
198 length = GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ());
199 len = length * sizeof (gcov_type);
200 values = (gcov_type *)malloc (len);
201 if (!values)
202 goto fail;
204 fn_buffer->info.ctrs[n_ctrs].num = length;
205 fn_buffer->info.ctrs[n_ctrs].values = values;
207 while (length--)
208 *values++ = gcov_read_counter ();
209 n_ctrs++;
212 *end_ptr = fn_buffer;
213 return &fn_buffer->next;
215 fail:
216 fprintf (stderr, "profiling:%s:Function %u %s %u \n", filename, fn_ix,
217 len ? "cannot allocate" : "counter mismatch", len ? len : ix);
219 return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix);
222 /* Add an unsigned value to the current crc */
224 static gcov_unsigned_t
225 crc32_unsigned (gcov_unsigned_t crc32, gcov_unsigned_t value)
227 unsigned ix;
229 for (ix = 32; ix--; value <<= 1)
231 unsigned feedback;
233 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
234 crc32 <<= 1;
235 crc32 ^= feedback;
238 return crc32;
241 /* Check if VERSION of the info block PTR matches libgcov one.
242 Return 1 on success, or zero in case of versions mismatch.
243 If FILENAME is not NULL, its value used for reporting purposes
244 instead of value from the info block. */
246 static int
247 gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
248 const char *filename)
250 if (version != GCOV_VERSION)
252 char v[4], e[4];
254 GCOV_UNSIGNED2STRING (v, version);
255 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
257 fprintf (stderr,
258 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
259 filename? filename : ptr->filename, e, v);
260 return 0;
262 return 1;
265 /* Dump the coverage counts. We merge with existing counts when
266 possible, to avoid growing the .da files ad infinitum. We use this
267 program's checksum to make sure we only accumulate whole program
268 statistics to the correct summary. An object file might be embedded
269 in two separate programs, and we must keep the two program
270 summaries separate. */
272 static void
273 gcov_exit (void)
275 struct gcov_info *gi_ptr;
276 const struct gcov_fn_info *gfi_ptr;
277 struct gcov_summary this_prg; /* summary for program. */
278 struct gcov_summary all_prg; /* summary for all instances of program. */
279 struct gcov_ctr_summary *cs_ptr;
280 const struct gcov_ctr_info *ci_ptr;
281 unsigned t_ix;
282 int f_ix;
283 gcov_unsigned_t c_num;
284 const char *gcov_prefix;
285 int gcov_prefix_strip = 0;
286 size_t prefix_length;
287 char *gi_filename, *gi_filename_up;
288 gcov_unsigned_t crc32 = 0;
290 memset (&all_prg, 0, sizeof (all_prg));
291 /* Find the totals for this execution. */
292 memset (&this_prg, 0, sizeof (this_prg));
293 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
295 crc32 = crc32_unsigned (crc32, gi_ptr->stamp);
296 crc32 = crc32_unsigned (crc32, gi_ptr->n_functions);
298 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
300 gfi_ptr = gi_ptr->functions[f_ix];
302 if (gfi_ptr && gfi_ptr->key != gi_ptr)
303 gfi_ptr = 0;
305 crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0);
306 crc32 = crc32_unsigned (crc32,
307 gfi_ptr ? gfi_ptr->lineno_checksum : 0);
308 if (!gfi_ptr)
309 continue;
311 ci_ptr = gfi_ptr->ctrs;
312 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
314 if (!gi_ptr->merge[t_ix])
315 continue;
317 cs_ptr = &this_prg.ctrs[t_ix];
318 cs_ptr->num += ci_ptr->num;
319 crc32 = crc32_unsigned (crc32, ci_ptr->num);
321 for (c_num = 0; c_num < ci_ptr->num; c_num++)
323 cs_ptr->sum_all += ci_ptr->values[c_num];
324 if (cs_ptr->run_max < ci_ptr->values[c_num])
325 cs_ptr->run_max = ci_ptr->values[c_num];
327 ci_ptr++;
333 /* Check if the level of dirs to strip off specified. */
334 char *tmp = getenv("GCOV_PREFIX_STRIP");
335 if (tmp)
337 gcov_prefix_strip = atoi (tmp);
338 /* Do not consider negative values. */
339 if (gcov_prefix_strip < 0)
340 gcov_prefix_strip = 0;
344 /* Get file name relocation prefix. Non-absolute values are ignored. */
345 gcov_prefix = getenv("GCOV_PREFIX");
346 if (gcov_prefix)
348 prefix_length = strlen(gcov_prefix);
350 /* Remove an unnecessary trailing '/' */
351 if (IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1]))
352 prefix_length--;
354 else
355 prefix_length = 0;
357 /* If no prefix was specified and a prefix stip, then we assume
358 relative. */
359 if (gcov_prefix_strip != 0 && prefix_length == 0)
361 gcov_prefix = ".";
362 prefix_length = 1;
364 /* Allocate and initialize the filename scratch space plus one. */
365 gi_filename = (char *) alloca (prefix_length + gcov_max_filename + 2);
366 if (prefix_length)
367 memcpy (gi_filename, gcov_prefix, prefix_length);
368 gi_filename_up = gi_filename + prefix_length;
370 /* Now merge each file. */
371 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
373 unsigned n_counts;
374 struct gcov_summary prg; /* summary for this object over all
375 program. */
376 struct gcov_ctr_summary *cs_prg, *cs_tprg, *cs_all;
377 int error = 0;
378 gcov_unsigned_t tag, length;
379 gcov_position_t summary_pos = 0;
380 gcov_position_t eof_pos = 0;
381 const char *fname, *s;
382 struct gcov_fn_buffer *fn_buffer = 0;
383 struct gcov_fn_buffer **fn_tail = &fn_buffer;
385 fname = gi_ptr->filename;
387 /* Avoid to add multiple drive letters into combined path. */
388 if (prefix_length != 0 && HAS_DRIVE_SPEC(fname))
389 fname += 2;
391 /* Build relocated filename, stripping off leading
392 directories from the initial filename if requested. */
393 if (gcov_prefix_strip > 0)
395 int level = 0;
396 s = fname;
397 if (IS_DIR_SEPARATOR(*s))
398 ++s;
400 /* Skip selected directory levels. */
401 for (; (*s != '\0') && (level < gcov_prefix_strip); s++)
402 if (IS_DIR_SEPARATOR(*s))
404 fname = s;
405 level++;
409 /* Update complete filename with stripped original. */
410 if (prefix_length != 0 && !IS_DIR_SEPARATOR (*fname))
412 /* If prefix is given, add directory separator. */
413 strcpy (gi_filename_up, "/");
414 strcpy (gi_filename_up + 1, fname);
416 else
417 strcpy (gi_filename_up, fname);
419 if (!gcov_open (gi_filename))
421 /* Open failed likely due to missed directory.
422 Create directory and retry to open file. */
423 if (create_file_directory (gi_filename))
425 fprintf (stderr, "profiling:%s:Skip\n", gi_filename);
426 continue;
428 if (!gcov_open (gi_filename))
430 fprintf (stderr, "profiling:%s:Cannot open\n", gi_filename);
431 continue;
435 tag = gcov_read_unsigned ();
436 if (tag)
438 /* Merge data from file. */
439 if (tag != GCOV_DATA_MAGIC)
441 fprintf (stderr, "profiling:%s:Not a gcov data file\n",
442 gi_filename);
443 goto read_fatal;
445 length = gcov_read_unsigned ();
446 if (!gcov_version (gi_ptr, length, gi_filename))
447 goto read_fatal;
449 length = gcov_read_unsigned ();
450 if (length != gi_ptr->stamp)
451 /* Read from a different compilation. Overwrite the file. */
452 goto rewrite;
454 /* Look for program summary. */
455 for (f_ix = 0;;)
457 struct gcov_summary tmp;
459 eof_pos = gcov_position ();
460 tag = gcov_read_unsigned ();
461 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
462 break;
464 f_ix--;
465 length = gcov_read_unsigned ();
466 if (length != GCOV_TAG_SUMMARY_LENGTH)
467 goto read_mismatch;
468 gcov_read_summary (&tmp);
469 if ((error = gcov_is_error ()))
470 goto read_error;
471 if (summary_pos || tmp.checksum != crc32)
472 goto next_summary;
474 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
475 if (tmp.ctrs[t_ix].num != this_prg.ctrs[t_ix].num)
476 goto next_summary;
477 prg = tmp;
478 summary_pos = eof_pos;
480 next_summary:;
483 /* Merge execution counts for each function. */
484 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions;
485 f_ix++, tag = gcov_read_unsigned ())
487 gfi_ptr = gi_ptr->functions[f_ix];
489 if (tag != GCOV_TAG_FUNCTION)
490 goto read_mismatch;
492 length = gcov_read_unsigned ();
493 if (!length)
494 /* This function did not appear in the other program.
495 We have nothing to merge. */
496 continue;
498 if (length != GCOV_TAG_FUNCTION_LENGTH)
499 goto read_mismatch;
501 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
503 /* This function appears in the other program. We
504 need to buffer the information in order to write
505 it back out -- we'll be inserting data before
506 this point, so cannot simply keep the data in the
507 file. */
508 fn_tail = buffer_fn_data (gi_filename,
509 gi_ptr, fn_tail, f_ix);
510 if (!fn_tail)
511 goto read_mismatch;
512 continue;
515 length = gcov_read_unsigned ();
516 if (length != gfi_ptr->ident)
517 goto read_mismatch;
519 length = gcov_read_unsigned ();
520 if (length != gfi_ptr->lineno_checksum)
521 goto read_mismatch;
523 length = gcov_read_unsigned ();
524 if (length != gfi_ptr->cfg_checksum)
525 goto read_mismatch;
527 ci_ptr = gfi_ptr->ctrs;
528 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
530 gcov_merge_fn merge = gi_ptr->merge[t_ix];
532 if (!merge)
533 continue;
535 tag = gcov_read_unsigned ();
536 length = gcov_read_unsigned ();
537 if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
538 || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num))
539 goto read_mismatch;
540 (*merge) (ci_ptr->values, ci_ptr->num);
541 ci_ptr++;
543 if ((error = gcov_is_error ()))
544 goto read_error;
547 if (tag)
549 read_mismatch:;
550 fprintf (stderr, "profiling:%s:Merge mismatch for %s %u\n",
551 gi_filename, f_ix >= 0 ? "function" : "summary",
552 f_ix < 0 ? -1 - f_ix : f_ix);
553 goto read_fatal;
556 goto rewrite;
558 read_error:;
559 fprintf (stderr, "profiling:%s:%s merging\n", gi_filename,
560 error < 0 ? "Overflow": "Error");
562 goto read_fatal;
564 rewrite:;
565 gcov_rewrite ();
566 if (!summary_pos)
568 memset (&prg, 0, sizeof (prg));
569 summary_pos = eof_pos;
572 /* Merge the summaries. */
573 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
575 cs_prg = &prg.ctrs[t_ix];
576 cs_tprg = &this_prg.ctrs[t_ix];
577 cs_all = &all_prg.ctrs[t_ix];
579 if (gi_ptr->merge[t_ix])
581 if (!cs_prg->runs++)
582 cs_prg->num = cs_tprg->num;
583 cs_prg->sum_all += cs_tprg->sum_all;
584 if (cs_prg->run_max < cs_tprg->run_max)
585 cs_prg->run_max = cs_tprg->run_max;
586 cs_prg->sum_max += cs_tprg->run_max;
588 else if (cs_prg->runs)
589 goto read_mismatch;
591 if (!cs_all->runs && cs_prg->runs)
592 memcpy (cs_all, cs_prg, sizeof (*cs_all));
593 else if (!all_prg.checksum
594 && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs)
595 && memcmp (cs_all, cs_prg, sizeof (*cs_all)))
597 fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s\n",
598 gi_filename, GCOV_LOCKED
599 ? "" : " or concurrently updated without locking support");
600 all_prg.checksum = ~0u;
604 prg.checksum = crc32;
606 /* Write out the data. */
607 if (!eof_pos)
609 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
610 gcov_write_unsigned (gi_ptr->stamp);
613 if (summary_pos)
614 gcov_seek (summary_pos);
616 /* Generate whole program statistics. */
617 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &prg);
619 if (summary_pos < eof_pos)
620 gcov_seek (eof_pos);
622 /* Write execution counts for each function. */
623 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
625 unsigned buffered = 0;
627 if (fn_buffer && fn_buffer->fn_ix == (unsigned)f_ix)
629 /* Buffered data from another program. */
630 buffered = 1;
631 gfi_ptr = &fn_buffer->info;
632 length = GCOV_TAG_FUNCTION_LENGTH;
634 else
636 gfi_ptr = gi_ptr->functions[f_ix];
637 if (gfi_ptr && gfi_ptr->key == gi_ptr)
638 length = GCOV_TAG_FUNCTION_LENGTH;
639 else
640 length = 0;
643 gcov_write_tag_length (GCOV_TAG_FUNCTION, length);
644 if (!length)
645 continue;
647 gcov_write_unsigned (gfi_ptr->ident);
648 gcov_write_unsigned (gfi_ptr->lineno_checksum);
649 gcov_write_unsigned (gfi_ptr->cfg_checksum);
651 ci_ptr = gfi_ptr->ctrs;
652 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
654 if (!gi_ptr->merge[t_ix])
655 continue;
657 n_counts = ci_ptr->num;
658 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
659 GCOV_TAG_COUNTER_LENGTH (n_counts));
660 gcov_type *c_ptr = ci_ptr->values;
661 while (n_counts--)
662 gcov_write_counter (*c_ptr++);
663 ci_ptr++;
665 if (buffered)
666 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
669 gcov_write_unsigned (0);
671 read_fatal:;
672 while (fn_buffer)
673 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
675 if ((error = gcov_close ()))
676 fprintf (stderr, error < 0 ?
677 "profiling:%s:Overflow writing\n" :
678 "profiling:%s:Error writing\n",
679 gi_filename);
683 /* Add a new object file onto the bb chain. Invoked automatically
684 when running an object file's global ctors. */
686 void
687 __gcov_init (struct gcov_info *info)
689 if (!info->version || !info->n_functions)
690 return;
691 if (gcov_version (info, info->version, 0))
693 size_t filename_length = strlen(info->filename);
695 /* Refresh the longest file name information */
696 if (filename_length > gcov_max_filename)
697 gcov_max_filename = filename_length;
699 if (!gcov_list)
700 atexit (gcov_exit);
702 info->next = gcov_list;
703 gcov_list = info;
705 info->version = 0;
708 /* Called before fork or exec - write out profile information gathered so
709 far and reset it to zero. This avoids duplication or loss of the
710 profile information gathered so far. */
712 void
713 __gcov_flush (void)
715 const struct gcov_info *gi_ptr;
717 gcov_exit ();
718 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
720 unsigned f_ix;
722 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
724 unsigned t_ix;
725 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
727 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
728 continue;
729 const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
730 for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
732 if (!gi_ptr->merge[t_ix])
733 continue;
735 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
736 ci_ptr++;
742 #endif /* L_gcov */
744 #ifdef L_gcov_merge_add
745 /* The profile merging function that just adds the counters. It is given
746 an array COUNTERS of N_COUNTERS old counters and it reads the same number
747 of counters from the gcov file. */
748 void
749 __gcov_merge_add (gcov_type *counters, unsigned n_counters)
751 for (; n_counters; counters++, n_counters--)
752 *counters += gcov_read_counter ();
754 #endif /* L_gcov_merge_add */
756 #ifdef L_gcov_merge_ior
757 /* The profile merging function that just adds the counters. It is given
758 an array COUNTERS of N_COUNTERS old counters and it reads the same number
759 of counters from the gcov file. */
760 void
761 __gcov_merge_ior (gcov_type *counters, unsigned n_counters)
763 for (; n_counters; counters++, n_counters--)
764 *counters |= gcov_read_counter ();
766 #endif
768 #ifdef L_gcov_merge_single
769 /* The profile merging function for choosing the most common value.
770 It is given an array COUNTERS of N_COUNTERS old counters and it
771 reads the same number of counters from the gcov file. The counters
772 are split into 3-tuples where the members of the tuple have
773 meanings:
775 -- the stored candidate on the most common value of the measured entity
776 -- counter
777 -- total number of evaluations of the value */
778 void
779 __gcov_merge_single (gcov_type *counters, unsigned n_counters)
781 unsigned i, n_measures;
782 gcov_type value, counter, all;
784 gcc_assert (!(n_counters % 3));
785 n_measures = n_counters / 3;
786 for (i = 0; i < n_measures; i++, counters += 3)
788 value = gcov_read_counter ();
789 counter = gcov_read_counter ();
790 all = gcov_read_counter ();
792 if (counters[0] == value)
793 counters[1] += counter;
794 else if (counter > counters[1])
796 counters[0] = value;
797 counters[1] = counter - counters[1];
799 else
800 counters[1] -= counter;
801 counters[2] += all;
804 #endif /* L_gcov_merge_single */
806 #ifdef L_gcov_merge_delta
807 /* The profile merging function for choosing the most common
808 difference between two consecutive evaluations of the value. It is
809 given an array COUNTERS of N_COUNTERS old counters and it reads the
810 same number of counters from the gcov file. The counters are split
811 into 4-tuples where the members of the tuple have meanings:
813 -- the last value of the measured entity
814 -- the stored candidate on the most common difference
815 -- counter
816 -- total number of evaluations of the value */
817 void
818 __gcov_merge_delta (gcov_type *counters, unsigned n_counters)
820 unsigned i, n_measures;
821 gcov_type value, counter, all;
823 gcc_assert (!(n_counters % 4));
824 n_measures = n_counters / 4;
825 for (i = 0; i < n_measures; i++, counters += 4)
827 /* last = */ gcov_read_counter ();
828 value = gcov_read_counter ();
829 counter = gcov_read_counter ();
830 all = gcov_read_counter ();
832 if (counters[1] == value)
833 counters[2] += counter;
834 else if (counter > counters[2])
836 counters[1] = value;
837 counters[2] = counter - counters[2];
839 else
840 counters[2] -= counter;
841 counters[3] += all;
844 #endif /* L_gcov_merge_delta */
846 #ifdef L_gcov_interval_profiler
847 /* If VALUE is in interval <START, START + STEPS - 1>, then increases the
848 corresponding counter in COUNTERS. If the VALUE is above or below
849 the interval, COUNTERS[STEPS] or COUNTERS[STEPS + 1] is increased
850 instead. */
852 void
853 __gcov_interval_profiler (gcov_type *counters, gcov_type value,
854 int start, unsigned steps)
856 gcov_type delta = value - start;
857 if (delta < 0)
858 counters[steps + 1]++;
859 else if (delta >= steps)
860 counters[steps]++;
861 else
862 counters[delta]++;
864 #endif
866 #ifdef L_gcov_pow2_profiler
867 /* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise
868 COUNTERS[0] is incremented. */
870 void
871 __gcov_pow2_profiler (gcov_type *counters, gcov_type value)
873 if (value & (value - 1))
874 counters[0]++;
875 else
876 counters[1]++;
878 #endif
880 /* Tries to determine the most common value among its inputs. Checks if the
881 value stored in COUNTERS[0] matches VALUE. If this is the case, COUNTERS[1]
882 is incremented. If this is not the case and COUNTERS[1] is not zero,
883 COUNTERS[1] is decremented. Otherwise COUNTERS[1] is set to one and
884 VALUE is stored to COUNTERS[0]. This algorithm guarantees that if this
885 function is called more than 50% of the time with one value, this value
886 will be in COUNTERS[0] in the end.
888 In any case, COUNTERS[2] is incremented. */
890 static inline void
891 __gcov_one_value_profiler_body (gcov_type *counters, gcov_type value)
893 if (value == counters[0])
894 counters[1]++;
895 else if (counters[1] == 0)
897 counters[1] = 1;
898 counters[0] = value;
900 else
901 counters[1]--;
902 counters[2]++;
905 #ifdef L_gcov_one_value_profiler
906 void
907 __gcov_one_value_profiler (gcov_type *counters, gcov_type value)
909 __gcov_one_value_profiler_body (counters, value);
911 #endif
913 #ifdef L_gcov_indirect_call_profiler
915 /* By default, the C++ compiler will use function addresses in the
916 vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero
917 tells the compiler to use function descriptors instead. The value
918 of this macro says how many words wide the descriptor is (normally 2),
919 but it may be dependent on target flags. Since we do not have access
920 to the target flags here we just check to see if it is set and use
921 that to set VTABLE_USES_DESCRIPTORS to 0 or 1.
923 It is assumed that the address of a function descriptor may be treated
924 as a pointer to a function. */
926 #ifdef TARGET_VTABLE_USES_DESCRIPTORS
927 #define VTABLE_USES_DESCRIPTORS 1
928 #else
929 #define VTABLE_USES_DESCRIPTORS 0
930 #endif
932 /* Tries to determine the most common value among its inputs. */
933 void
934 __gcov_indirect_call_profiler (gcov_type* counter, gcov_type value,
935 void* cur_func, void* callee_func)
937 /* If the C++ virtual tables contain function descriptors then one
938 function may have multiple descriptors and we need to dereference
939 the descriptors to see if they point to the same function. */
940 if (cur_func == callee_func
941 || (VTABLE_USES_DESCRIPTORS && callee_func
942 && *(void **) cur_func == *(void **) callee_func))
943 __gcov_one_value_profiler_body (counter, value);
945 #endif
948 #ifdef L_gcov_average_profiler
949 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
950 to saturate up. */
952 void
953 __gcov_average_profiler (gcov_type *counters, gcov_type value)
955 counters[0] += value;
956 counters[1] ++;
958 #endif
960 #ifdef L_gcov_ior_profiler
961 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
962 to saturate up. */
964 void
965 __gcov_ior_profiler (gcov_type *counters, gcov_type value)
967 *counters |= value;
969 #endif
971 #ifdef L_gcov_fork
972 /* A wrapper for the fork function. Flushes the accumulated profiling data, so
973 that they are not counted twice. */
975 pid_t
976 __gcov_fork (void)
978 __gcov_flush ();
979 return fork ();
981 #endif
983 #ifdef L_gcov_execl
984 /* A wrapper for the execl function. Flushes the accumulated profiling data, so
985 that they are not lost. */
988 __gcov_execl (const char *path, char *arg, ...)
990 va_list ap, aq;
991 unsigned i, length;
992 char **args;
994 __gcov_flush ();
996 va_start (ap, arg);
997 va_copy (aq, ap);
999 length = 2;
1000 while (va_arg (ap, char *))
1001 length++;
1002 va_end (ap);
1004 args = (char **) alloca (length * sizeof (void *));
1005 args[0] = arg;
1006 for (i = 1; i < length; i++)
1007 args[i] = va_arg (aq, char *);
1008 va_end (aq);
1010 return execv (path, args);
1012 #endif
1014 #ifdef L_gcov_execlp
1015 /* A wrapper for the execlp function. Flushes the accumulated profiling data, so
1016 that they are not lost. */
1019 __gcov_execlp (const char *path, char *arg, ...)
1021 va_list ap, aq;
1022 unsigned i, length;
1023 char **args;
1025 __gcov_flush ();
1027 va_start (ap, arg);
1028 va_copy (aq, ap);
1030 length = 2;
1031 while (va_arg (ap, char *))
1032 length++;
1033 va_end (ap);
1035 args = (char **) alloca (length * sizeof (void *));
1036 args[0] = arg;
1037 for (i = 1; i < length; i++)
1038 args[i] = va_arg (aq, char *);
1039 va_end (aq);
1041 return execvp (path, args);
1043 #endif
1045 #ifdef L_gcov_execle
1046 /* A wrapper for the execle function. Flushes the accumulated profiling data, so
1047 that they are not lost. */
1050 __gcov_execle (const char *path, char *arg, ...)
1052 va_list ap, aq;
1053 unsigned i, length;
1054 char **args;
1055 char **envp;
1057 __gcov_flush ();
1059 va_start (ap, arg);
1060 va_copy (aq, ap);
1062 length = 2;
1063 while (va_arg (ap, char *))
1064 length++;
1065 va_end (ap);
1067 args = (char **) alloca (length * sizeof (void *));
1068 args[0] = arg;
1069 for (i = 1; i < length; i++)
1070 args[i] = va_arg (aq, char *);
1071 envp = va_arg (aq, char **);
1072 va_end (aq);
1074 return execve (path, args, envp);
1076 #endif
1078 #ifdef L_gcov_execv
1079 /* A wrapper for the execv function. Flushes the accumulated profiling data, so
1080 that they are not lost. */
1083 __gcov_execv (const char *path, char *const argv[])
1085 __gcov_flush ();
1086 return execv (path, argv);
1088 #endif
1090 #ifdef L_gcov_execvp
1091 /* A wrapper for the execvp function. Flushes the accumulated profiling data, so
1092 that they are not lost. */
1095 __gcov_execvp (const char *path, char *const argv[])
1097 __gcov_flush ();
1098 return execvp (path, argv);
1100 #endif
1102 #ifdef L_gcov_execve
1103 /* A wrapper for the execve function. Flushes the accumulated profiling data, so
1104 that they are not lost. */
1107 __gcov_execve (const char *path, char *const argv[], char *const envp[])
1109 __gcov_flush ();
1110 return execve (path, argv, envp);
1112 #endif
1113 #endif /* inhibit_libc */