]> gcc.gnu.org Git - gcc.git/blame - gcc/libgcov.c
tree.c (build_common_builtin_nodes): Fix the return type on __builtin_memcmp.
[gcc.git] / gcc / libgcov.c
CommitLineData
23af32e6
NS
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,
fe9565ed 4 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
23af32e6
NS
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 2, or (at your option) any later
11version.
12
13In addition to the permissions in the GNU General Public License, the
14Free Software Foundation gives you unlimited permission to link the
15compiled version of this file into combinations with other programs,
16and to distribute those combinations without any restriction coming
17from the use of this file. (The General Public License restrictions
18do apply in other respects; for example, they cover modification of
19the file, and distribution when not linked into a combine
20executable.)
21
22GCC is distributed in the hope that it will be useful, but WITHOUT ANY
23WARRANTY; without even the implied warranty of MERCHANTABILITY or
24FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25for more details.
26
27You should have received a copy of the GNU General Public License
28along with GCC; see the file COPYING. If not, write to the Free
29Software Foundation, 59 Temple Place - Suite 330, Boston, MA
3002111-1307, USA. */
31
23af32e6
NS
32#include "tconfig.h"
33#include "tsystem.h"
34#include "coretypes.h"
35#include "tm.h"
36
474f141e
NS
37#if defined(inhibit_libc)
38#define IN_LIBGCOV (-1)
39#else
23af32e6
NS
40#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
41#include <stdio.h>
474f141e
NS
42#define IN_LIBGCOV 1
43#if defined(L_gcov)
44#define GCOV_LINKAGE /* nothing */
45#endif
46#endif
47#include "gcov-io.h"
48
49#if defined(inhibit_libc)
50/* If libc and its header files are not available, provide dummy functions. */
51
52#ifdef L_gcov
53void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {}
54void __gcov_flush (void) {}
55#endif
56
57#ifdef L_gcov_merge_add
58void __gcov_merge_add (gcov_type *counters __attribute__ ((unused)),
59 unsigned n_counters __attribute__ ((unused))) {}
60#endif
61
af166e5d
ZD
62#ifdef L_gcov_merge_single
63void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)),
64 unsigned n_counters __attribute__ ((unused))) {}
65#endif
66
67#ifdef L_gcov_merge_delta
68void __gcov_merge_delta (gcov_type *counters __attribute__ ((unused)),
69 unsigned n_counters __attribute__ ((unused))) {}
70#endif
71
474f141e 72#else
23af32e6 73
23af32e6 74#include <string.h>
474f141e 75#if GCOV_LOCKED
23af32e6
NS
76#include <fcntl.h>
77#include <errno.h>
c2cd64b5 78#include <sys/stat.h>
23af32e6 79#endif
09780dfb
ZD
80
81#ifdef L_gcov
ca29da43 82#include "gcov-io.c"
23af32e6
NS
83
84/* Chain of per-object gcov structures. */
85static struct gcov_info *gcov_list;
86
87/* A program checksum allows us to distinguish program data for an
88 object file included in multiple programs. */
9b514d25 89static gcov_unsigned_t gcov_crc32;
23af32e6 90
992f396f
GZ
91/* Size of the longest file name. */
92static size_t gcov_max_filename = 0;
93
9d6aab7e 94/* Make sure path component of the given FILENAME exists, create
992f396f
GZ
95 missing directories. FILENAME must be writable.
96 Returns zero on success, or -1 if an error occurred. */
97
160e2e4f 98static int
992f396f
GZ
99create_file_directory (char *filename)
100{
101 char *s;
102
103 for (s = filename + 1; *s != '\0'; s++)
104 if (IS_DIR_SEPARATOR(*s))
105 {
106 char sep = *s;
107 *s = '\0';
108
109 /* Try to make directory if it doesn't already exist. */
110 if (access (filename, F_OK) == -1
111 && mkdir (filename, 0755) == -1
112 /* The directory might have been made by another process. */
113 && errno != EEXIST)
114 {
115 fprintf (stderr, "profiling:%s:Cannot create directory\n",
116 filename);
117 *s = sep;
118 return -1;
119 };
120
121 *s = sep;
122 };
123 return 0;
124}
125
126/* Check if VERSION of the info block PTR matches libgcov one.
127 Return 1 on success, or zero in case of versions mismatch.
128 If FILENAME is not NULL, its value used for reporting purposes
129 instead of value from the info block. */
130
131static int
132gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
133 const char *filename)
23af32e6 134{
160e2e4f 135 if (version != GCOV_VERSION)
23af32e6 136 {
330d2e2a
NS
137 char v[4], e[4];
138
139 GCOV_UNSIGNED2STRING (v, version);
140 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
141
160e2e4f
NS
142 fprintf (stderr,
143 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
992f396f 144 filename? filename : ptr->filename, e, v);
160e2e4f 145 return 0;
23af32e6 146 }
160e2e4f 147 return 1;
23af32e6
NS
148}
149
150/* Dump the coverage counts. We merge with existing counts when
151 possible, to avoid growing the .da files ad infinitum. We use this
152 program's checksum to make sure we only accumulate whole program
153 statistics to the correct summary. An object file might be embedded
154 in two separate programs, and we must keep the two program
155 summaries separate. */
156
157static void
158gcov_exit (void)
159{
cdb23767
NS
160 struct gcov_info *gi_ptr;
161 struct gcov_summary this_program;
162 struct gcov_summary all;
50612a04
ZD
163 struct gcov_ctr_summary *cs_ptr;
164 const struct gcov_ctr_info *ci_ptr;
165 unsigned t_ix;
166 gcov_unsigned_t c_num;
992f396f
GZ
167 const char *gcov_prefix;
168 int gcov_prefix_strip = 0;
169 size_t prefix_length;
170 char *gi_filename, *gi_filename_up;
cdb23767
NS
171
172 memset (&all, 0, sizeof (all));
173 /* Find the totals for this execution. */
174 memset (&this_program, 0, sizeof (this_program));
175 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
d101590b 176 {
50612a04
ZD
177 ci_ptr = gi_ptr->counts;
178 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
179 {
180 if (!((1 << t_ix) & gi_ptr->ctr_mask))
181 continue;
182
183 cs_ptr = &this_program.ctrs[t_ix];
184 cs_ptr->num += ci_ptr->num;
185 for (c_num = 0; c_num < ci_ptr->num; c_num++)
186 {
187 cs_ptr->sum_all += ci_ptr->values[c_num];
188 if (cs_ptr->run_max < ci_ptr->values[c_num])
189 cs_ptr->run_max = ci_ptr->values[c_num];
190 }
191 ci_ptr++;
192 }
d101590b 193 }
cdb23767 194
992f396f
GZ
195 /* Get file name relocation prefix. Non-absolute values are ignored. */
196 gcov_prefix = getenv("GCOV_PREFIX");
197 if (gcov_prefix && IS_ABSOLUTE_PATH (gcov_prefix))
198 {
199 /* Check if the level of dirs to strip off specified. */
200 char *tmp = getenv("GCOV_PREFIX_STRIP");
201 if (tmp)
202 {
203 gcov_prefix_strip = atoi (tmp);
204 /* Do not consider negative values. */
205 if (gcov_prefix_strip < 0)
206 gcov_prefix_strip = 0;
207 }
208
209 prefix_length = strlen(gcov_prefix);
210
9d6aab7e 211 /* Remove an unnecessary trailing '/' */
992f396f
GZ
212 if (IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1]))
213 prefix_length--;
214 }
3ca48b3e
L
215 else
216 prefix_length = 0;
992f396f
GZ
217
218 /* Allocate and initialize the filename scratch space. */
219 gi_filename = alloca (prefix_length + gcov_max_filename + 1);
220 if (prefix_length)
221 memcpy (gi_filename, gcov_prefix, prefix_length);
222 gi_filename_up = gi_filename + prefix_length;
223
f9da5064 224 /* Now merge each file. */
cdb23767 225 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
23af32e6 226 {
cdb23767
NS
227 struct gcov_summary this_object;
228 struct gcov_summary object, program;
229 gcov_type *values[GCOV_COUNTERS];
230 const struct gcov_fn_info *fi_ptr;
231 unsigned fi_stride;
50612a04 232 unsigned c_ix, f_ix, n_counts;
cdb23767 233 struct gcov_ctr_summary *cs_obj, *cs_tobj, *cs_prg, *cs_tprg, *cs_all;
7d63a2fa 234 int error = 0;
9b514d25 235 gcov_unsigned_t tag, length;
7d63a2fa 236 gcov_position_t summary_pos = 0;
00cf2913 237 gcov_position_t eof_pos = 0;
cdb23767 238
cdb23767 239 memset (&this_object, 0, sizeof (this_object));
dd486eb2
NS
240 memset (&object, 0, sizeof (object));
241
992f396f
GZ
242 /* Build relocated filename, stripping off leading
243 directories from the initial filename if requested. */
244 if (gcov_prefix_strip > 0)
245 {
246 int level = 0;
247 const char *fname = gi_ptr->filename;
248 const char *s;
249
250 /* Skip selected directory levels. */
251 for (s = fname + 1; (*s != '\0') && (level < gcov_prefix_strip); s++)
252 if (IS_DIR_SEPARATOR(*s))
253 {
254 fname = s;
255 level++;
256 };
257
258 /* Update complete filename with stripped original. */
259 strcpy (gi_filename_up, fname);
260 }
261 else
262 strcpy (gi_filename_up, gi_ptr->filename);
263
dd486eb2 264 /* Totals for this object file. */
50612a04
ZD
265 ci_ptr = gi_ptr->counts;
266 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
267 {
268 if (!((1 << t_ix) & gi_ptr->ctr_mask))
269 continue;
270
43ac2623 271 cs_ptr = &this_object.ctrs[t_ix];
50612a04
ZD
272 cs_ptr->num += ci_ptr->num;
273 for (c_num = 0; c_num < ci_ptr->num; c_num++)
274 {
275 cs_ptr->sum_all += ci_ptr->values[c_num];
276 if (cs_ptr->run_max < ci_ptr->values[c_num])
277 cs_ptr->run_max = ci_ptr->values[c_num];
278 }
279
280 ci_ptr++;
281 }
282
283 c_ix = 0;
284 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
cdb23767
NS
285 if ((1 << t_ix) & gi_ptr->ctr_mask)
286 {
50612a04 287 values[c_ix] = gi_ptr->counts[c_ix].values;
cdb23767 288 c_ix++;
cdb23767
NS
289 }
290
291 /* Calculate the function_info stride. This depends on the
292 number of counter types being measured. */
293 fi_stride = sizeof (struct gcov_fn_info) + c_ix * sizeof (unsigned);
294 if (__alignof__ (struct gcov_fn_info) > sizeof (unsigned))
cb9e4555 295 {
cdb23767
NS
296 fi_stride += __alignof__ (struct gcov_fn_info) - 1;
297 fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1);
cb9e4555 298 }
546d2adb 299
992f396f 300 if (!gcov_open (gi_filename))
23af32e6 301 {
992f396f
GZ
302 /* Open failed likely due to missed directory.
303 Create directory and retry to open file. */
304 if (create_file_directory (gi_filename))
305 {
306 fprintf (stderr, "profiling:%s:Skip\n", gi_filename);
307 continue;
308 }
309 if (!gcov_open (gi_filename))
310 {
311 fprintf (stderr, "profiling:%s:Cannot open\n", gi_filename);
312 continue;
313 }
23af32e6 314 }
160e2e4f
NS
315
316 tag = gcov_read_unsigned ();
317 if (tag)
23af32e6
NS
318 {
319 /* Merge data from file. */
160e2e4f 320 if (tag != GCOV_DATA_MAGIC)
23af32e6
NS
321 {
322 fprintf (stderr, "profiling:%s:Not a gcov data file\n",
992f396f 323 gi_filename);
00cf2913 324 goto read_fatal;
23af32e6 325 }
94de45d9 326 length = gcov_read_unsigned ();
992f396f 327 if (!gcov_version (gi_ptr, length, gi_filename))
160e2e4f 328 goto read_fatal;
dd486eb2
NS
329
330 length = gcov_read_unsigned ();
331 if (length != gi_ptr->stamp)
00cf2913
NS
332 /* Read from a different compilation. Overwrite the file. */
333 goto rewrite;
23af32e6
NS
334
335 /* Merge execution counts for each function. */
50612a04 336 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
23af32e6 337 {
50612a04
ZD
338 fi_ptr = (const struct gcov_fn_info *)
339 ((const char *) gi_ptr->functions + f_ix * fi_stride);
94de45d9
NS
340 tag = gcov_read_unsigned ();
341 length = gcov_read_unsigned ();
23af32e6 342
f9da5064 343 /* Check function. */
796621e8 344 if (tag != GCOV_TAG_FUNCTION
474f141e 345 || length != GCOV_TAG_FUNCTION_LENGTH
796621e8
NS
346 || gcov_read_unsigned () != fi_ptr->ident
347 || gcov_read_unsigned () != fi_ptr->checksum)
23af32e6
NS
348 {
349 read_mismatch:;
cdb23767 350 fprintf (stderr, "profiling:%s:Merge mismatch for %s\n",
992f396f 351 gi_filename,
796621e8 352 f_ix + 1 ? "function" : "summaries");
23af32e6
NS
353 goto read_fatal;
354 }
cb9e4555 355
50612a04
ZD
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;
cdb23767 366
50612a04
ZD
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++;
cb9e4555 375 }
94de45d9
NS
376 if ((error = gcov_is_error ()))
377 goto read_error;
23af32e6
NS
378 }
379
50612a04 380 f_ix = ~0u;
474f141e 381 /* Check program & object summary */
7d63a2fa 382 while (1)
23af32e6 383 {
474f141e
NS
384 int is_program;
385
00cf2913 386 eof_pos = gcov_position ();
94de45d9 387 tag = gcov_read_unsigned ();
7d63a2fa
NS
388 if (!tag)
389 break;
00cf2913 390
474f141e
NS
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))
23af32e6 395 goto read_mismatch;
474f141e 396 gcov_read_summary (is_program ? &program : &object);
94de45d9 397 if ((error = gcov_is_error ()))
7d63a2fa
NS
398 goto read_error;
399 if (is_program && program.checksum == gcov_crc32)
94de45d9 400 {
00cf2913 401 summary_pos = eof_pos;
7d63a2fa 402 goto rewrite;
94de45d9 403 }
23af32e6 404 }
23af32e6 405 }
00cf2913 406 goto rewrite;
160e2e4f 407
00cf2913
NS
408 read_error:;
409 fprintf (stderr, error < 0 ? "profiling:%s:Overflow merging\n"
992f396f 410 : "profiling:%s:Error merging\n", gi_filename);
00cf2913
NS
411
412 read_fatal:;
413 gcov_close ();
414 continue;
415
160e2e4f
NS
416 rewrite:;
417 gcov_rewrite ();
7d63a2fa 418 if (!summary_pos)
cdb23767 419 memset (&program, 0, sizeof (program));
23af32e6 420
cdb23767 421 /* Merge the summaries. */
796621e8 422 f_ix = ~0u;
50612a04 423 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
cdb23767 424 {
50612a04
ZD
425 cs_obj = &object.ctrs[t_ix];
426 cs_tobj = &this_object.ctrs[t_ix];
427 cs_prg = &program.ctrs[t_ix];
43ac2623 428 cs_tprg = &this_program.ctrs[t_ix];
50612a04
ZD
429 cs_all = &all.ctrs[t_ix];
430
cdb23767
NS
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;
cdb23767
NS
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",
992f396f 461 gi_filename, GCOV_LOCKED
cdb23767
NS
462 ? "" : " or concurrent update without locking support");
463 all.checksum = ~0u;
464 }
465 }
466
50612a04
ZD
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
cdb23767 475 program.checksum = gcov_crc32;
23af32e6
NS
476
477 /* Write out the data. */
9b514d25 478 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
dd486eb2 479 gcov_write_unsigned (gi_ptr->stamp);
23af32e6
NS
480
481 /* Write execution counts for each function. */
50612a04 482 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
23af32e6 483 {
50612a04
ZD
484 fi_ptr = (const struct gcov_fn_info *)
485 ((const char *) gi_ptr->functions + f_ix * fi_stride);
486
23af32e6 487 /* Announce function. */
474f141e 488 gcov_write_tag_length (GCOV_TAG_FUNCTION, GCOV_TAG_FUNCTION_LENGTH);
796621e8 489 gcov_write_unsigned (fi_ptr->ident);
cdb23767 490 gcov_write_unsigned (fi_ptr->checksum);
cb9e4555 491
50612a04
ZD
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];
cdb23767 501
50612a04
ZD
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 }
23af32e6
NS
511 }
512
513 /* Object file summary. */
94de45d9 514 gcov_write_summary (GCOV_TAG_OBJECT_SUMMARY, &object);
23af32e6 515
d101590b 516 /* Generate whole program statistics. */
00cf2913
NS
517 if (eof_pos)
518 gcov_seek (eof_pos);
cdb23767 519 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &program);
00cf2913
NS
520 if (!summary_pos)
521 gcov_write_unsigned (0);
cdb23767 522 if ((error = gcov_close ()))
cdb23767
NS
523 fprintf (stderr, error < 0 ?
524 "profiling:%s:Overflow writing\n" :
525 "profiling:%s:Error writing\n",
992f396f 526 gi_filename);
23af32e6 527 }
23af32e6
NS
528}
529
530/* Add a new object file onto the bb chain. Invoked automatically
531 when running an object file's global ctors. */
532
533void
534__gcov_init (struct gcov_info *info)
535{
536 if (!info->version)
537 return;
992f396f 538 if (gcov_version (info, info->version, 0))
23af32e6
NS
539 {
540 const char *ptr = info->filename;
9b514d25 541 gcov_unsigned_t crc32 = gcov_crc32;
992f396f
GZ
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
23af32e6
NS
548 do
549 {
550 unsigned ix;
9b514d25 551 gcov_unsigned_t value = *ptr << 24;
23af32e6
NS
552
553 for (ix = 8; ix--; value <<= 1)
554 {
9b514d25 555 gcov_unsigned_t feedback;
23af32e6
NS
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
579void
580__gcov_flush (void)
581{
cdb23767 582 const struct gcov_info *gi_ptr;
23af32e6
NS
583
584 gcov_exit ();
cdb23767 585 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
23af32e6 586 {
cdb23767
NS
587 unsigned t_ix;
588 const struct gcov_ctr_info *ci_ptr;
23af32e6 589
cdb23767
NS
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 }
23af32e6
NS
596 }
597}
01e60c33 598
09780dfb
ZD
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. */
605void
9b514d25 606__gcov_merge_add (gcov_type *counters, unsigned n_counters)
09780dfb
ZD
607{
608 for (; n_counters; counters++, n_counters--)
609 *counters += gcov_read_counter ();
610}
611#endif /* L_gcov_merge_add */
612
af166e5d 613#ifdef L_gcov_merge_single
330d2e2a
NS
614/* The profile merging function for choosing the most common value.
615 It is given an array COUNTERS of N_COUNTERS old counters and it
616 reads the same number of counters from the gcov file. The counters
617 are split into 3-tuples where the members of the tuple have
618 meanings:
619
af166e5d
ZD
620 -- the stored candidate on the most common value of the measured entity
621 -- counter
622 -- total number of evaluations of the value */
623void
624__gcov_merge_single (gcov_type *counters, unsigned n_counters)
625{
626 unsigned i, n_measures;
627 gcov_type value, counter, all;
628
cccd217d 629 gcc_assert (!(n_counters % 3));
af166e5d
ZD
630 n_measures = n_counters / 3;
631 for (i = 0; i < n_measures; i++, counters += 3)
632 {
633 value = gcov_read_counter ();
634 counter = gcov_read_counter ();
635 all = gcov_read_counter ();
636
637 if (counters[0] == value)
638 counters[1] += counter;
639 else if (counter > counters[1])
640 {
641 counters[0] = value;
642 counters[1] = counter - counters[1];
643 }
644 else
645 counters[1] -= counter;
646 counters[2] += all;
647 }
648}
649#endif /* L_gcov_merge_single */
650
651#ifdef L_gcov_merge_delta
330d2e2a
NS
652/* The profile merging function for choosing the most common
653 difference between two consecutive evaluations of the value. It is
654 given an array COUNTERS of N_COUNTERS old counters and it reads the
655 same number of counters from the gcov file. The counters are split
656 into 4-tuples where the members of the tuple have meanings:
657
af166e5d
ZD
658 -- the last value of the measured entity
659 -- the stored candidate on the most common difference
660 -- counter
661 -- total number of evaluations of the value */
662void
663__gcov_merge_delta (gcov_type *counters, unsigned n_counters)
664{
665 unsigned i, n_measures;
666 gcov_type last, value, counter, all;
667
cccd217d 668 gcc_assert (!(n_counters % 4));
af166e5d
ZD
669 n_measures = n_counters / 4;
670 for (i = 0; i < n_measures; i++, counters += 4)
671 {
672 last = gcov_read_counter ();
673 value = gcov_read_counter ();
674 counter = gcov_read_counter ();
675 all = gcov_read_counter ();
676
677 if (counters[1] == value)
678 counters[2] += counter;
679 else if (counter > counters[2])
680 {
681 counters[1] = value;
682 counters[2] = counter - counters[2];
683 }
684 else
685 counters[2] -= counter;
686 counters[3] += all;
687 }
688}
689#endif /* L_gcov_merge_delta */
690
9885da8e
ZD
691#ifdef L_gcov_interval_profiler
692/* If VALUE is in interval <START, START + STEPS - 1>, then increases the
693 corresponding counter in COUNTERS. If the VALUE is above or below
694 the interval, COUNTERS[STEPS] or COUNTERS[STEPS + 1] is increased
695 instead. */
696
697void
698__gcov_interval_profiler (gcov_type *counters, gcov_type value,
699 int start, unsigned steps)
700{
701 gcov_type delta = value - start;
702 if (delta < 0)
703 counters[steps + 1]++;
704 else if (delta >= steps)
705 counters[steps]++;
706 else
707 counters[delta]++;
708}
709#endif
710
711#ifdef L_gcov_pow2_profiler
712/* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise
713 COUNTERS[0] is incremented. */
714
715void
716__gcov_pow2_profiler (gcov_type *counters, gcov_type value)
717{
718 if (value & (value - 1))
719 counters[0]++;
720 else
721 counters[1]++;
722}
723#endif
724
725#ifdef L_gcov_one_value_profiler
726/* Tries to determine the most common value among its inputs. Checks if the
727 value stored in COUNTERS[0] matches VALUE. If this is the case, COUNTERS[1]
728 is incremented. If this is not the case and COUNTERS[1] is not zero,
729 COUNTERS[1] is decremented. Otherwise COUNTERS[1] is set to one and
730 VALUE is stored to COUNTERS[0]. This algorithm guarantees that if this
731 function is called more than 50% of the time with one value, this value
732 will be in COUNTERS[0] in the end.
733
734 In any case, COUNTERS[2] is incremented. */
735
736void
737__gcov_one_value_profiler (gcov_type *counters, gcov_type value)
738{
739 if (value == counters[0])
740 counters[1]++;
741 else if (counters[1] == 0)
742 {
743 counters[1] = 1;
744 counters[0] = value;
745 }
746 else
747 counters[1]--;
748 counters[2]++;
749}
750#endif
751
d1c38823
ZD
752#ifdef L_gcov_fork
753/* A wrapper for the fork function. Flushes the accumulated profiling data, so
754 that they are not counted twice. */
755
756pid_t
757__gcov_fork (void)
758{
759 __gcov_flush ();
760 return fork ();
761}
762#endif
763
764#ifdef L_gcov_execl
765/* A wrapper for the execl function. Flushes the accumulated profiling data, so
766 that they are not lost. */
767
768int
769__gcov_execl (const char *path, const char *arg, ...)
770{
771 va_list ap, aq;
772 unsigned i, length;
773 char **args;
774
775 __gcov_flush ();
776
777 va_start (ap, arg);
778 va_copy (aq, ap);
779
780 length = 2;
781 while (va_arg (ap, char *))
782 length++;
783 va_end (ap);
784
785 args = alloca (length * sizeof (void *));
786 args[0] = (char *) arg;
787 for (i = 1; i < length; i++)
788 args[i] = va_arg (aq, char *);
789 va_end (aq);
790
791 return execv (path, args);
792}
793#endif
794
795#ifdef L_gcov_execlp
796/* A wrapper for the execlp function. Flushes the accumulated profiling data, so
797 that they are not lost. */
798
799int
800__gcov_execlp (const char *path, const char *arg, ...)
801{
802 va_list ap, aq;
803 unsigned i, length;
804 char **args;
805
806 __gcov_flush ();
807
808 va_start (ap, arg);
809 va_copy (aq, ap);
810
811 length = 2;
812 while (va_arg (ap, char *))
813 length++;
814 va_end (ap);
815
816 args = alloca (length * sizeof (void *));
817 args[0] = (char *) arg;
818 for (i = 1; i < length; i++)
819 args[i] = va_arg (aq, char *);
820 va_end (aq);
821
822 return execvp (path, args);
823}
824#endif
825
826#ifdef L_gcov_execle
827/* A wrapper for the execle function. Flushes the accumulated profiling data, so
828 that they are not lost. */
829
830int
831__gcov_execle (const char *path, const char *arg, ...)
832{
833 va_list ap, aq;
834 unsigned i, length;
835 char **args;
836 char **envp;
837
838 __gcov_flush ();
839
840 va_start (ap, arg);
841 va_copy (aq, ap);
842
843 length = 2;
844 while (va_arg (ap, char *))
845 length++;
846 va_end (ap);
847
848 args = alloca (length * sizeof (void *));
849 args[0] = (char *) arg;
850 for (i = 1; i < length; i++)
851 args[i] = va_arg (aq, char *);
852 envp = va_arg (aq, char **);
853 va_end (aq);
854
855 return execve (path, args, envp);
856}
857#endif
858
859#ifdef L_gcov_execv
860/* A wrapper for the execv function. Flushes the accumulated profiling data, so
861 that they are not lost. */
862
863int
864__gcov_execv (const char *path, char *const argv[])
865{
866 __gcov_flush ();
867 return execv (path, argv);
868}
869#endif
870
871#ifdef L_gcov_execvp
872/* A wrapper for the execvp function. Flushes the accumulated profiling data, so
873 that they are not lost. */
874
875int
876__gcov_execvp (const char *path, char *const argv[])
877{
878 __gcov_flush ();
879 return execvp (path, argv);
880}
881#endif
882
883#ifdef L_gcov_execve
884/* A wrapper for the execve function. Flushes the accumulated profiling data, so
885 that they are not lost. */
886
887int
888__gcov_execve (const char *path, char *const argv[], char *const envp[])
889{
890 __gcov_flush ();
891 return execve (path, argv, envp);
892}
893#endif
01e60c33 894#endif /* inhibit_libc */
This page took 0.964278 seconds and 5 git commands to generate.