rockchip/rk3399: Fix rkclk_init() to actually use PERILP1_PCLK_HZ
[coreboot.git] / src / lib / libgcov.c
blob1ad14c9c90b7892bfc9027b58d895e9d509a88ea
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.
24 #define __COREBOOT__
25 #ifdef __COREBOOT__
26 #include <stdlib.h>
27 #include <string.h>
28 #include <console/console.h>
29 #include <assert.h>
30 typedef s32 pid_t;
31 #define gcc_assert(x) ASSERT(x)
32 #define fprintf(file, x...) printk(BIOS_ERR, x)
33 #define alloca(size) __builtin_alloca (size)
34 #include "gcov-glue.c"
36 /* Define MACROs to be used by coreboot compilation. */
37 # define L_gcov
38 # define L_gcov_interval_profiler
39 # define L_gcov_pow2_profiler
40 # define L_gcov_one_value_profiler
41 # define L_gcov_indirect_call_profiler
42 # define L_gcov_average_profiler
43 # define L_gcov_ior_profiler
45 # define HAVE_CC_TLS 0
46 # define __GCOV_KERNEL__
48 # define IN_LIBGCOV 1
49 # define IN_GCOV 0
50 #else /* __COREBOOT__ */
51 #include "tconfig.h"
52 #include "tsystem.h"
53 #include "coretypes.h"
54 #include "tm.h"
55 #include "libgcc_tm.h"
56 #endif /* __COREBOOT__ */
58 #ifndef __COREBOOT__
59 #if defined(inhibit_libc)
60 #define IN_LIBGCOV (-1)
61 #else
62 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
63 #include <stdio.h>
64 #define IN_LIBGCOV 1
65 #if defined(L_gcov)
66 #define GCOV_LINKAGE /* nothing */
67 #endif
68 #endif
69 #endif /* __COREBOOT__ */
70 #include "gcov-io.h"
72 #if defined(inhibit_libc)
73 /* If libc and its header files are not available, provide dummy functions. */
75 #ifdef L_gcov
76 void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {}
77 void __gcov_flush (void) {}
78 #endif
80 #ifdef L_gcov_merge_add
81 void __gcov_merge_add (gcov_type *counters __attribute__ ((unused)),
82 unsigned n_counters __attribute__ ((unused))) {}
83 #endif
85 #ifdef L_gcov_merge_single
86 void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)),
87 unsigned n_counters __attribute__ ((unused))) {}
88 #endif
90 #ifdef L_gcov_merge_delta
91 void __gcov_merge_delta (gcov_type *counters __attribute__ ((unused)),
92 unsigned n_counters __attribute__ ((unused))) {}
93 #endif
95 #else
97 #ifndef __COREBOOT__
98 #include <string.h>
99 #if GCOV_LOCKED
100 #include <fcntl.h>
101 #include <errno.h>
102 #include <sys/stat.h>
103 #endif
104 #else
105 void __gcov_merge_add(gcov_type *counters __attribute__ ((unused)),
106 unsigned n_counters __attribute__ ((unused))) {}
107 #endif /* __COREBOOT__ */
109 #ifdef L_gcov
110 #include "gcov-io.c"
112 struct gcov_fn_buffer
114 struct gcov_fn_buffer *next;
115 unsigned fn_ix;
116 struct gcov_fn_info info;
117 /* note gcov_fn_info ends in a trailing array. */
120 /* Chain of per-object gcov structures. */
121 static struct gcov_info *gcov_list;
123 /* Size of the longest file name. */
124 static size_t gcov_max_filename = 0;
126 /* Make sure path component of the given FILENAME exists, create
127 missing directories. FILENAME must be writable.
128 Returns zero on success, or -1 if an error occurred. */
130 static int
131 create_file_directory (char *filename)
133 #ifdef __COREBOOT__
134 (void) filename;
135 return 0;
136 #else
137 #if !defined(TARGET_POSIX_IO) && !defined(_WIN32)
138 (void) filename;
139 return -1;
140 #else
141 char *s;
143 s = filename;
145 if (HAS_DRIVE_SPEC(s))
146 s += 2;
147 if (IS_DIR_SEPARATOR(*s))
148 ++s;
149 for (; *s != '\0'; s++)
150 if (IS_DIR_SEPARATOR(*s))
152 char sep = *s;
153 *s = '\0';
155 /* Try to make directory if it doesn't already exist. */
156 if (access (filename, F_OK) == -1
157 #ifdef TARGET_POSIX_IO
158 && mkdir (filename, 0755) == -1
159 #else
160 && mkdir (filename) == -1
161 #endif
162 /* The directory might have been made by another process. */
163 && errno != EEXIST)
165 fprintf (stderr, "profiling:%s:Cannot create directory\n",
166 filename);
167 *s = sep;
168 return -1;
171 *s = sep;
173 return 0;
174 #endif
175 #endif
178 static struct gcov_fn_buffer *
179 free_fn_data (const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer,
180 unsigned limit)
182 struct gcov_fn_buffer *next;
183 unsigned ix, n_ctr = 0;
185 if (!buffer)
186 return 0;
187 next = buffer->next;
189 for (ix = 0; ix != limit; ix++)
190 if (gi_ptr->merge[ix])
191 free (buffer->info.ctrs[n_ctr++].values);
192 free (buffer);
193 return next;
196 static struct gcov_fn_buffer **
197 buffer_fn_data (const char *filename, const struct gcov_info *gi_ptr,
198 struct gcov_fn_buffer **end_ptr, unsigned fn_ix)
200 unsigned n_ctrs = 0, ix = 0;
201 struct gcov_fn_buffer *fn_buffer;
202 unsigned len;
204 for (ix = GCOV_COUNTERS; ix--;)
205 if (gi_ptr->merge[ix])
206 n_ctrs++;
208 len = sizeof (*fn_buffer) + sizeof (fn_buffer->info.ctrs[0]) * n_ctrs;
209 fn_buffer = (struct gcov_fn_buffer *)malloc (len);
211 if (!fn_buffer)
212 goto fail;
214 fn_buffer->next = 0;
215 fn_buffer->fn_ix = fn_ix;
216 fn_buffer->info.ident = gcov_read_unsigned ();
217 fn_buffer->info.lineno_checksum = gcov_read_unsigned ();
218 fn_buffer->info.cfg_checksum = gcov_read_unsigned ();
220 for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++)
222 gcov_unsigned_t length;
223 gcov_type *values;
225 if (!gi_ptr->merge[ix])
226 continue;
228 if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix))
230 len = 0;
231 goto fail;
234 length = GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ());
235 len = length * sizeof (gcov_type);
236 values = (gcov_type *)malloc (len);
237 if (!values)
238 goto fail;
240 fn_buffer->info.ctrs[n_ctrs].num = length;
241 fn_buffer->info.ctrs[n_ctrs].values = values;
243 while (length--)
244 *values++ = gcov_read_counter ();
245 n_ctrs++;
248 *end_ptr = fn_buffer;
249 return &fn_buffer->next;
251 fail:
252 fprintf (stderr, "profiling:%s:Function %u %s %u \n", filename, fn_ix,
253 len ? "cannot allocate" : "counter mismatch", len ? len : ix);
255 return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix);
258 /* Add an unsigned value to the current crc */
260 static gcov_unsigned_t
261 crc32_unsigned (gcov_unsigned_t crc32, gcov_unsigned_t value)
263 unsigned ix;
265 for (ix = 32; ix--; value <<= 1)
267 unsigned feedback;
269 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
270 crc32 <<= 1;
271 crc32 ^= feedback;
274 return crc32;
277 /* Check if VERSION of the info block PTR matches libgcov one.
278 Return 1 on success, or zero in case of versions mismatch.
279 If FILENAME is not NULL, its value used for reporting purposes
280 instead of value from the info block. */
282 static int
283 gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
284 const char *filename)
286 if (version != GCOV_VERSION)
288 char v[4], e[4];
290 GCOV_UNSIGNED2STRING (v, version);
291 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
293 fprintf (stderr,
294 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
295 filename? filename : ptr->filename, e, v);
296 return 0;
298 return 1;
301 /* Dump the coverage counts. We merge with existing counts when
302 possible, to avoid growing the .da files ad infinitum. We use this
303 program's checksum to make sure we only accumulate whole program
304 statistics to the correct summary. An object file might be embedded
305 in two separate programs, and we must keep the two program
306 summaries separate. */
308 static void
309 gcov_exit (void)
311 struct gcov_info *gi_ptr;
312 const struct gcov_fn_info *gfi_ptr;
313 struct gcov_summary this_prg; /* summary for program. */
314 struct gcov_summary all_prg; /* summary for all instances of program. */
315 struct gcov_ctr_summary *cs_ptr;
316 const struct gcov_ctr_info *ci_ptr;
317 unsigned t_ix;
318 int f_ix = 0;
319 gcov_unsigned_t c_num;
320 const char *gcov_prefix;
321 int gcov_prefix_strip = 0;
322 size_t prefix_length;
323 char *gi_filename, *gi_filename_up;
324 gcov_unsigned_t crc32 = 0;
326 memset (&all_prg, 0, sizeof (all_prg));
327 /* Find the totals for this execution. */
328 memset (&this_prg, 0, sizeof (this_prg));
329 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
331 crc32 = crc32_unsigned (crc32, gi_ptr->stamp);
332 crc32 = crc32_unsigned (crc32, gi_ptr->n_functions);
334 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
336 gfi_ptr = gi_ptr->functions[f_ix];
338 if (gfi_ptr && gfi_ptr->key != gi_ptr)
339 gfi_ptr = 0;
341 crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0);
342 crc32 = crc32_unsigned (crc32,
343 gfi_ptr ? gfi_ptr->lineno_checksum : 0);
344 if (!gfi_ptr)
345 continue;
347 ci_ptr = gfi_ptr->ctrs;
348 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
350 if (!gi_ptr->merge[t_ix])
351 continue;
353 cs_ptr = &this_prg.ctrs[t_ix];
354 cs_ptr->num += ci_ptr->num;
355 crc32 = crc32_unsigned (crc32, ci_ptr->num);
357 for (c_num = 0; c_num < ci_ptr->num; c_num++)
359 cs_ptr->sum_all += ci_ptr->values[c_num];
360 if (cs_ptr->run_max < ci_ptr->values[c_num])
361 cs_ptr->run_max = ci_ptr->values[c_num];
363 ci_ptr++;
368 #ifndef __COREBOOT__
370 /* Check if the level of dirs to strip off specified. */
371 char *tmp = getenv("GCOV_PREFIX_STRIP");
372 if (tmp)
374 gcov_prefix_strip = atoi (tmp);
375 /* Do not consider negative values. */
376 if (gcov_prefix_strip < 0)
377 gcov_prefix_strip = 0;
381 /* Get file name relocation prefix. Non-absolute values are ignored. */
382 gcov_prefix = getenv("GCOV_PREFIX");
383 if (gcov_prefix)
385 prefix_length = strlen(gcov_prefix);
387 /* Remove an unnecessary trailing '/' */
388 if (IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1]))
389 prefix_length--;
391 else
392 #endif
393 prefix_length = 0;
395 /* If no prefix was specified and a prefix strip, then we assume
396 relative. */
397 if (gcov_prefix_strip != 0 && prefix_length == 0)
399 gcov_prefix = ".";
400 prefix_length = 1;
402 /* Allocate and initialize the filename scratch space plus one. */
403 gi_filename = (char *) alloca (prefix_length + gcov_max_filename + 2);
404 if (prefix_length)
405 memcpy (gi_filename, gcov_prefix, prefix_length);
406 gi_filename_up = gi_filename + prefix_length;
408 /* Now merge each file. */
409 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
411 unsigned n_counts;
412 struct gcov_summary prg; /* summary for this object over all
413 program. */
414 struct gcov_ctr_summary *cs_prg, *cs_tprg, *cs_all;
415 int error = 0;
416 gcov_unsigned_t tag, length;
417 gcov_position_t summary_pos = 0;
418 gcov_position_t eof_pos = 0;
419 const char *fname, *s;
420 struct gcov_fn_buffer *fn_buffer = 0;
421 struct gcov_fn_buffer **fn_tail = &fn_buffer;
423 fname = gi_ptr->filename;
425 /* Avoid to add multiple drive letters into combined path. */
426 if (prefix_length != 0 && HAS_DRIVE_SPEC(fname))
427 fname += 2;
429 /* Build relocated filename, stripping off leading
430 directories from the initial filename if requested. */
431 if (gcov_prefix_strip > 0)
433 int level = 0;
434 s = fname;
435 if (IS_DIR_SEPARATOR(*s))
436 ++s;
438 /* Skip selected directory levels. */
439 for (; (*s != '\0') && (level < gcov_prefix_strip); s++)
440 if (IS_DIR_SEPARATOR(*s))
442 fname = s;
443 level++;
447 /* Update complete filename with stripped original. */
448 if (prefix_length != 0 && !IS_DIR_SEPARATOR (*fname))
450 /* If prefix is given, add directory separator. */
451 strcpy (gi_filename_up, "/");
452 strcpy (gi_filename_up + 1, fname);
454 else
455 strcpy (gi_filename_up, fname);
457 if (!gcov_open (gi_filename))
459 /* Open failed likely due to missed directory.
460 Create directory and retry to open file. */
461 if (create_file_directory (gi_filename))
463 fprintf (stderr, "profiling:%s:Skip\n", gi_filename);
464 continue;
466 if (!gcov_open (gi_filename))
468 fprintf (stderr, "profiling:%s:Cannot open\n", gi_filename);
469 continue;
473 tag = gcov_read_unsigned ();
474 if (tag)
476 /* Merge data from file. */
477 if (tag != GCOV_DATA_MAGIC)
479 fprintf (stderr, "profiling:%s:Not a gcov data file\n",
480 gi_filename);
481 goto read_fatal;
483 length = gcov_read_unsigned ();
484 if (!gcov_version (gi_ptr, length, gi_filename))
485 goto read_fatal;
487 length = gcov_read_unsigned ();
488 if (length != gi_ptr->stamp)
489 /* Read from a different compilation. Overwrite the file. */
490 goto rewrite;
492 /* Look for program summary. */
493 for (f_ix = 0;;)
495 struct gcov_summary tmp;
497 eof_pos = gcov_position ();
498 tag = gcov_read_unsigned ();
499 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
500 break;
502 f_ix--;
503 length = gcov_read_unsigned ();
504 if (length != GCOV_TAG_SUMMARY_LENGTH)
505 goto read_mismatch;
506 gcov_read_summary (&tmp);
507 if ((error = gcov_is_error ()))
508 goto read_error;
509 if (summary_pos || tmp.checksum != crc32)
510 goto next_summary;
512 for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
513 if (tmp.ctrs[t_ix].num != this_prg.ctrs[t_ix].num)
514 goto next_summary;
515 prg = tmp;
516 summary_pos = eof_pos;
518 next_summary:;
521 /* Merge execution counts for each function. */
522 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions;
523 f_ix++, tag = gcov_read_unsigned ())
525 gfi_ptr = gi_ptr->functions[f_ix];
527 if (tag != GCOV_TAG_FUNCTION)
528 goto read_mismatch;
530 length = gcov_read_unsigned ();
531 if (!length)
532 /* This function did not appear in the other program.
533 We have nothing to merge. */
534 continue;
536 if (length != GCOV_TAG_FUNCTION_LENGTH)
537 goto read_mismatch;
539 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
541 /* This function appears in the other program. We
542 need to buffer the information in order to write
543 it back out -- we'll be inserting data before
544 this point, so cannot simply keep the data in the
545 file. */
546 fn_tail = buffer_fn_data (gi_filename,
547 gi_ptr, fn_tail, f_ix);
548 if (!fn_tail)
549 goto read_mismatch;
550 continue;
553 length = gcov_read_unsigned ();
554 if (length != gfi_ptr->ident)
555 goto read_mismatch;
557 length = gcov_read_unsigned ();
558 if (length != gfi_ptr->lineno_checksum)
559 goto read_mismatch;
561 length = gcov_read_unsigned ();
562 if (length != gfi_ptr->cfg_checksum)
563 goto read_mismatch;
565 ci_ptr = gfi_ptr->ctrs;
566 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
568 gcov_merge_fn merge = gi_ptr->merge[t_ix];
570 if (!merge)
571 continue;
573 tag = gcov_read_unsigned ();
574 length = gcov_read_unsigned ();
575 if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
576 || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num))
577 goto read_mismatch;
578 (*merge) (ci_ptr->values, ci_ptr->num);
579 ci_ptr++;
581 if ((error = gcov_is_error ()))
582 goto read_error;
585 if (tag)
587 read_mismatch:;
588 fprintf (stderr, "profiling:%s:Merge mismatch for %s %u\n",
589 gi_filename, f_ix >= 0 ? "function" : "summary",
590 f_ix < 0 ? -1 - f_ix : f_ix);
591 goto read_fatal;
594 goto rewrite;
596 read_error:;
597 fprintf (stderr, "profiling:%s:%s merging\n", gi_filename,
598 error < 0 ? "Overflow": "Error");
600 goto read_fatal;
602 rewrite:;
603 gcov_rewrite ();
604 if (!summary_pos)
606 memset (&prg, 0, sizeof (prg));
607 summary_pos = eof_pos;
610 /* Merge the summaries. */
611 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
613 cs_prg = &prg.ctrs[t_ix];
614 cs_tprg = &this_prg.ctrs[t_ix];
615 cs_all = &all_prg.ctrs[t_ix];
617 if (gi_ptr->merge[t_ix])
619 if (!cs_prg->runs++)
620 cs_prg->num = cs_tprg->num;
621 cs_prg->sum_all += cs_tprg->sum_all;
622 if (cs_prg->run_max < cs_tprg->run_max)
623 cs_prg->run_max = cs_tprg->run_max;
624 cs_prg->sum_max += cs_tprg->run_max;
626 else if (cs_prg->runs)
627 goto read_mismatch;
629 if (!cs_all->runs && cs_prg->runs)
630 memcpy (cs_all, cs_prg, sizeof (*cs_all));
631 else if (!all_prg.checksum
632 && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs)
633 && memcmp (cs_all, cs_prg, sizeof (*cs_all)))
635 fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s\n",
636 gi_filename, GCOV_LOCKED
637 ? "" : " or concurrently updated without locking support");
638 all_prg.checksum = ~0u;
642 prg.checksum = crc32;
644 /* Write out the data. */
645 if (!eof_pos)
647 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
648 gcov_write_unsigned (gi_ptr->stamp);
651 if (summary_pos)
652 gcov_seek (summary_pos);
654 /* Generate whole program statistics. */
655 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &prg);
657 if (summary_pos < eof_pos)
658 gcov_seek (eof_pos);
660 /* Write execution counts for each function. */
661 for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
663 unsigned buffered = 0;
665 if (fn_buffer && fn_buffer->fn_ix == (unsigned)f_ix)
667 /* Buffered data from another program. */
668 buffered = 1;
669 gfi_ptr = &fn_buffer->info;
670 length = GCOV_TAG_FUNCTION_LENGTH;
672 else
674 gfi_ptr = gi_ptr->functions[f_ix];
675 if (gfi_ptr && gfi_ptr->key == gi_ptr)
676 length = GCOV_TAG_FUNCTION_LENGTH;
677 else
678 length = 0;
681 gcov_write_tag_length (GCOV_TAG_FUNCTION, length);
682 if (!length)
683 continue;
685 gcov_write_unsigned (gfi_ptr->ident);
686 gcov_write_unsigned (gfi_ptr->lineno_checksum);
687 gcov_write_unsigned (gfi_ptr->cfg_checksum);
689 ci_ptr = gfi_ptr->ctrs;
690 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
692 if (!gi_ptr->merge[t_ix])
693 continue;
695 n_counts = ci_ptr->num;
696 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
697 GCOV_TAG_COUNTER_LENGTH (n_counts));
698 gcov_type *c_ptr = ci_ptr->values;
699 while (n_counts--)
700 gcov_write_counter (*c_ptr++);
701 ci_ptr++;
703 if (buffered)
704 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
707 gcov_write_unsigned (0);
709 read_fatal:;
710 while (fn_buffer)
711 fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
713 if ((error = gcov_close ()))
714 fprintf (stderr, error < 0 ?
715 "profiling:%s:Overflow writing\n" :
716 "profiling:%s:Error writing\n",
717 gi_filename);
721 /* Add a new object file onto the bb chain. Invoked automatically
722 when running an object file's global ctors. */
724 void
725 __gcov_init (struct gcov_info *info)
727 if (!info->version || !info->n_functions)
728 return;
729 if (gcov_version (info, info->version, 0))
731 size_t filename_length = strlen(info->filename);
733 /* Refresh the longest file name information */
734 if (filename_length > gcov_max_filename)
735 gcov_max_filename = filename_length;
737 #ifndef __COREBOOT__
738 if (!gcov_list)
739 atexit (gcov_exit);
740 #endif
742 info->next = gcov_list;
743 gcov_list = info;
745 info->version = 0;
748 /* Called before fork or exec - write out profile information gathered so
749 far and reset it to zero. This avoids duplication or loss of the
750 profile information gathered so far. */
752 void
753 __gcov_flush (void)
755 const struct gcov_info *gi_ptr;
757 gcov_exit ();
758 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
760 unsigned f_ix;
762 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
764 unsigned t_ix;
765 const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
767 if (!gfi_ptr || gfi_ptr->key != gi_ptr)
768 continue;
769 const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
770 for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
772 if (!gi_ptr->merge[t_ix])
773 continue;
775 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
776 ci_ptr++;
782 #endif /* L_gcov */
784 #ifdef L_gcov_merge_add
785 /* The profile merging function that just adds the counters. It is given
786 an array COUNTERS of N_COUNTERS old counters and it reads the same number
787 of counters from the gcov file. */
788 void
789 __gcov_merge_add (gcov_type *counters, unsigned n_counters)
791 for (; n_counters; counters++, n_counters--)
792 *counters += gcov_read_counter ();
794 #endif /* L_gcov_merge_add */
796 #ifdef L_gcov_merge_ior
797 /* The profile merging function that just adds the counters. It is given
798 an array COUNTERS of N_COUNTERS old counters and it reads the same number
799 of counters from the gcov file. */
800 void
801 __gcov_merge_ior (gcov_type *counters, unsigned n_counters)
803 for (; n_counters; counters++, n_counters--)
804 *counters |= gcov_read_counter ();
806 #endif
808 #ifdef L_gcov_merge_single
809 /* The profile merging function for choosing the most common value.
810 * It is given an array COUNTERS of N_COUNTERS old counters and it
811 * reads the same number of counters from the gcov file. The counters
812 * are split into 3-tuples where the members of the tuple have
813 * meanings:
815 * -- the stored candidate on the most common value of the measured entity
816 * -- counter
817 * -- total number of evaluations of the value
819 void
820 __gcov_merge_single (gcov_type *counters, unsigned n_counters)
822 unsigned i, n_measures;
823 gcov_type value, counter, all;
825 gcc_assert (!(n_counters % 3));
826 n_measures = n_counters / 3;
827 for (i = 0; i < n_measures; i++, counters += 3)
829 value = gcov_read_counter ();
830 counter = gcov_read_counter ();
831 all = gcov_read_counter ();
833 if (counters[0] == value)
834 counters[1] += counter;
835 else if (counter > counters[1])
837 counters[0] = value;
838 counters[1] = counter - counters[1];
840 else
841 counters[1] -= counter;
842 counters[2] += all;
845 #endif /* L_gcov_merge_single */
847 #ifdef L_gcov_merge_delta
848 /* The profile merging function for choosing the most common
849 * difference between two consecutive evaluations of the value. It is
850 * given an array COUNTERS of N_COUNTERS old counters and it reads the
851 * same number of counters from the gcov file. The counters are split
852 * into 4-tuples where the members of the tuple have meanings:
854 * -- the last value of the measured entity
855 * -- the stored candidate on the most common difference
856 * -- counter
857 * -- total number of evaluations of the value
859 void
860 __gcov_merge_delta (gcov_type *counters, unsigned n_counters)
862 unsigned i, n_measures;
863 gcov_type value, counter, all;
865 gcc_assert (!(n_counters % 4));
866 n_measures = n_counters / 4;
867 for (i = 0; i < n_measures; i++, counters += 4)
869 /* last = */ gcov_read_counter ();
870 value = gcov_read_counter ();
871 counter = gcov_read_counter ();
872 all = gcov_read_counter ();
874 if (counters[1] == value)
875 counters[2] += counter;
876 else if (counter > counters[2])
878 counters[1] = value;
879 counters[2] = counter - counters[2];
881 else
882 counters[2] -= counter;
883 counters[3] += all;
886 #endif /* L_gcov_merge_delta */
888 #ifdef L_gcov_interval_profiler
889 /* If VALUE is in interval <START, START + STEPS - 1>, then increases the
890 corresponding counter in COUNTERS. If the VALUE is above or below
891 the interval, COUNTERS[STEPS] or COUNTERS[STEPS + 1] is increased
892 instead. */
894 void
895 __gcov_interval_profiler (gcov_type *counters, gcov_type value,
896 int start, unsigned steps)
898 gcov_type delta = value - start;
899 if (delta < 0)
900 counters[steps + 1]++;
901 else if (delta >= steps)
902 counters[steps]++;
903 else
904 counters[delta]++;
906 #endif
908 #ifdef L_gcov_pow2_profiler
909 /* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise
910 COUNTERS[0] is incremented. */
912 void
913 __gcov_pow2_profiler (gcov_type *counters, gcov_type value)
915 if (value & (value - 1))
916 counters[0]++;
917 else
918 counters[1]++;
920 #endif
922 /* Tries to determine the most common value among its inputs. Checks if the
923 value stored in COUNTERS[0] matches VALUE. If this is the case, COUNTERS[1]
924 is incremented. If this is not the case and COUNTERS[1] is not zero,
925 COUNTERS[1] is decremented. Otherwise COUNTERS[1] is set to one and
926 VALUE is stored to COUNTERS[0]. This algorithm guarantees that if this
927 function is called more than 50% of the time with one value, this value
928 will be in COUNTERS[0] in the end.
930 In any case, COUNTERS[2] is incremented. */
932 static inline void
933 __gcov_one_value_profiler_body (gcov_type *counters, gcov_type value)
935 if (value == counters[0])
936 counters[1]++;
937 else if (counters[1] == 0)
939 counters[1] = 1;
940 counters[0] = value;
942 else
943 counters[1]--;
944 counters[2]++;
947 #ifdef L_gcov_one_value_profiler
948 void
949 __gcov_one_value_profiler (gcov_type *counters, gcov_type value)
951 __gcov_one_value_profiler_body (counters, value);
953 #endif
955 #ifdef L_gcov_indirect_call_profiler
957 /* By default, the C++ compiler will use function addresses in the
958 vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero
959 tells the compiler to use function descriptors instead. The value
960 of this macro says how many words wide the descriptor is (normally 2),
961 but it may be dependent on target flags. Since we do not have access
962 to the target flags here we just check to see if it is set and use
963 that to set VTABLE_USES_DESCRIPTORS to 0 or 1.
965 It is assumed that the address of a function descriptor may be treated
966 as a pointer to a function. */
968 #ifdef TARGET_VTABLE_USES_DESCRIPTORS
969 #define VTABLE_USES_DESCRIPTORS 1
970 #else
971 #define VTABLE_USES_DESCRIPTORS 0
972 #endif
974 /* Tries to determine the most common value among its inputs. */
975 void
976 __gcov_indirect_call_profiler (gcov_type* counter, gcov_type value,
977 void* cur_func, void* callee_func)
979 /* If the C++ virtual tables contain function descriptors then one
980 function may have multiple descriptors and we need to dereference
981 the descriptors to see if they point to the same function. */
982 if (cur_func == callee_func
983 || (VTABLE_USES_DESCRIPTORS && callee_func
984 && *(void **) cur_func == *(void **) callee_func))
985 __gcov_one_value_profiler_body (counter, value);
987 #endif
990 #ifdef L_gcov_average_profiler
991 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
992 to saturate up. */
994 void
995 __gcov_average_profiler (gcov_type *counters, gcov_type value)
997 counters[0] += value;
998 counters[1] ++;
1000 #endif
1002 #ifdef L_gcov_ior_profiler
1003 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
1004 to saturate up. */
1006 void
1007 __gcov_ior_profiler (gcov_type *counters, gcov_type value)
1009 *counters |= value;
1011 #endif
1013 #ifdef L_gcov_fork
1014 /* A wrapper for the fork function. Flushes the accumulated profiling data, so
1015 that they are not counted twice. */
1017 pid_t
1018 __gcov_fork (void)
1020 __gcov_flush ();
1021 return fork ();
1023 #endif
1025 #ifdef L_gcov_execl
1026 /* A wrapper for the execl function. Flushes the accumulated profiling data, so
1027 that they are not lost. */
1030 __gcov_execl (const char *path, char *arg, ...)
1032 va_list ap, aq;
1033 unsigned i, length;
1034 char **args;
1036 __gcov_flush ();
1038 va_start (ap, arg);
1039 va_copy (aq, ap);
1041 length = 2;
1042 while (va_arg (ap, char *))
1043 length++;
1044 va_end (ap);
1046 args = (char **) alloca (length * sizeof (void *));
1047 args[0] = arg;
1048 for (i = 1; i < length; i++)
1049 args[i] = va_arg (aq, char *);
1050 va_end (aq);
1052 return execv (path, args);
1054 #endif
1056 #ifdef L_gcov_execlp
1057 /* A wrapper for the execlp function. Flushes the accumulated profiling data, so
1058 that they are not lost. */
1061 __gcov_execlp (const char *path, char *arg, ...)
1063 va_list ap, aq;
1064 unsigned i, length;
1065 char **args;
1067 __gcov_flush ();
1069 va_start (ap, arg);
1070 va_copy (aq, ap);
1072 length = 2;
1073 while (va_arg (ap, char *))
1074 length++;
1075 va_end (ap);
1077 args = (char **) alloca (length * sizeof (void *));
1078 args[0] = arg;
1079 for (i = 1; i < length; i++)
1080 args[i] = va_arg (aq, char *);
1081 va_end (aq);
1083 return execvp (path, args);
1085 #endif
1087 #ifdef L_gcov_execle
1088 /* A wrapper for the execle function. Flushes the accumulated profiling data, so
1089 that they are not lost. */
1092 __gcov_execle (const char *path, char *arg, ...)
1094 va_list ap, aq;
1095 unsigned i, length;
1096 char **args;
1097 char **envp;
1099 __gcov_flush ();
1101 va_start (ap, arg);
1102 va_copy (aq, ap);
1104 length = 2;
1105 while (va_arg (ap, char *))
1106 length++;
1107 va_end (ap);
1109 args = (char **) alloca (length * sizeof (void *));
1110 args[0] = arg;
1111 for (i = 1; i < length; i++)
1112 args[i] = va_arg (aq, char *);
1113 envp = va_arg (aq, char **);
1114 va_end (aq);
1116 return execve (path, args, envp);
1118 #endif
1120 #ifdef L_gcov_execv
1121 /* A wrapper for the execv function. Flushes the accumulated profiling data, so
1122 that they are not lost. */
1125 __gcov_execv (const char *path, char *const argv[])
1127 __gcov_flush ();
1128 return execv (path, argv);
1130 #endif
1132 #ifdef L_gcov_execvp
1133 /* A wrapper for the execvp function. Flushes the accumulated profiling data, so
1134 that they are not lost. */
1137 __gcov_execvp (const char *path, char *const argv[])
1139 __gcov_flush ();
1140 return execvp (path, argv);
1142 #endif
1144 #ifdef L_gcov_execve
1145 /* A wrapper for the execve function. Flushes the accumulated profiling data, so
1146 that they are not lost. */
1149 __gcov_execve (const char *path, char *const argv[], char *const envp[])
1151 __gcov_flush ();
1152 return execve (path, argv, envp);
1154 #endif
1155 #endif /* inhibit_libc */