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