* fixinc/inclhack.def (avoid_bool_define, avoid_bool_type): Bypass
[official-gcc.git] / gcc / libgcov.c
blob140ab05bf1c68242cadcef7c07e6f759d0d733a0
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 Free Software Foundation, Inc.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
13 In addition to the permissions in the GNU General Public License, the
14 Free Software Foundation gives you unlimited permission to link the
15 compiled version of this file into combinations with other programs,
16 and to distribute those combinations without any restriction coming
17 from the use of this file. (The General Public License restrictions
18 do apply in other respects; for example, they cover modification of
19 the file, and distribution when not linked into a combine
20 executable.)
22 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
23 WARRANTY; without even the implied warranty of MERCHANTABILITY or
24 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 for more details.
27 You should have received a copy of the GNU General Public License
28 along with GCC; see the file COPYING. If not, write to the Free
29 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
30 02111-1307, USA. */
32 /* It is incorrect to include config.h here, because this file is being
33 compiled for the target, and hence definitions concerning only the host
34 do not apply. */
36 #include "tconfig.h"
37 #include "tsystem.h"
38 #include "coretypes.h"
39 #include "tm.h"
41 #if defined(inhibit_libc)
42 #define IN_LIBGCOV (-1)
43 #else
44 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
45 #include <stdio.h>
46 #define IN_LIBGCOV 1
47 #if defined(L_gcov)
48 #define GCOV_LINKAGE /* nothing */
49 #endif
50 #endif
51 #include "gcov-io.h"
53 #if defined(inhibit_libc)
54 /* If libc and its header files are not available, provide dummy functions. */
56 #ifdef L_gcov
57 void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {}
58 void __gcov_flush (void) {}
59 #endif
61 #ifdef L_gcov_merge_add
62 void __gcov_merge_add (gcov_type *counters __attribute__ ((unused)),
63 unsigned n_counters __attribute__ ((unused))) {}
64 #endif
66 #ifdef L_gcov_merge_single
67 void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)),
68 unsigned n_counters __attribute__ ((unused))) {}
69 #endif
71 #ifdef L_gcov_merge_delta
72 void __gcov_merge_delta (gcov_type *counters __attribute__ ((unused)),
73 unsigned n_counters __attribute__ ((unused))) {}
74 #endif
76 #else
78 #include <string.h>
79 #if GCOV_LOCKED
80 #include <fcntl.h>
81 #include <errno.h>
82 #endif
84 #ifdef L_gcov
85 #include "gcov-io.c"
87 /* Chain of per-object gcov structures. */
88 static struct gcov_info *gcov_list;
90 /* A program checksum allows us to distinguish program data for an
91 object file included in multiple programs. */
92 static gcov_unsigned_t gcov_crc32;
94 static int
95 gcov_version (struct gcov_info *ptr, gcov_unsigned_t version)
97 if (version != GCOV_VERSION)
99 char v[4], e[4];
101 GCOV_UNSIGNED2STRING (v, version);
102 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
104 fprintf (stderr,
105 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
106 ptr->filename, e, v);
107 return 0;
109 return 1;
112 /* Dump the coverage counts. We merge with existing counts when
113 possible, to avoid growing the .da files ad infinitum. We use this
114 program's checksum to make sure we only accumulate whole program
115 statistics to the correct summary. An object file might be embedded
116 in two separate programs, and we must keep the two program
117 summaries separate. */
119 static void
120 gcov_exit (void)
122 struct gcov_info *gi_ptr;
123 struct gcov_summary this_program;
124 struct gcov_summary all;
126 memset (&all, 0, sizeof (all));
127 /* Find the totals for this execution. */
128 memset (&this_program, 0, sizeof (this_program));
129 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
131 const struct gcov_ctr_info *ci_ptr;
132 struct gcov_ctr_summary *cs_ptr;
133 unsigned t_ix;
135 for (t_ix = 0, ci_ptr = gi_ptr->counts, cs_ptr = this_program.ctrs;
136 t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++, cs_ptr++)
137 if ((1 << t_ix) & gi_ptr->ctr_mask)
139 const gcov_type *c_ptr;
140 gcov_unsigned_t c_num;
142 cs_ptr->num += ci_ptr->num;
143 for (c_num = ci_ptr->num, c_ptr = ci_ptr->values; c_num--; c_ptr++)
145 cs_ptr->sum_all += *c_ptr;
146 if (cs_ptr->run_max < *c_ptr)
147 cs_ptr->run_max = *c_ptr;
149 ci_ptr++;
153 /* Now merge each file. */
154 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
156 struct gcov_summary this_object;
157 struct gcov_summary object, program;
158 gcov_type *values[GCOV_COUNTERS];
159 const struct gcov_fn_info *fi_ptr;
160 unsigned fi_stride;
161 unsigned c_ix, t_ix, f_ix;
162 const struct gcov_ctr_info *ci_ptr;
163 struct gcov_ctr_summary *cs_ptr;
164 struct gcov_ctr_summary *cs_obj, *cs_tobj, *cs_prg, *cs_tprg, *cs_all;
165 int error = 0;
166 gcov_unsigned_t tag, length;
167 gcov_position_t summary_pos = 0;
169 memset (&this_object, 0, sizeof (this_object));
170 memset (&object, 0, sizeof (object));
172 /* Totals for this object file. */
173 for (t_ix = c_ix = 0,
174 ci_ptr = gi_ptr->counts, cs_ptr = this_object.ctrs;
175 t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++, cs_ptr++)
176 if ((1 << t_ix) & gi_ptr->ctr_mask)
178 const gcov_type *c_ptr;
179 gcov_unsigned_t c_num;
181 cs_ptr->num += ci_ptr->num;
182 values[c_ix] = ci_ptr->values;
183 for (c_num = ci_ptr->num, c_ptr = ci_ptr->values; c_num--; c_ptr++)
185 cs_ptr->sum_all += *c_ptr;
186 if (cs_ptr->run_max < *c_ptr)
187 cs_ptr->run_max = *c_ptr;
189 c_ix++;
190 ci_ptr++;
193 /* Calculate the function_info stride. This depends on the
194 number of counter types being measured. */
195 fi_stride = sizeof (struct gcov_fn_info) + c_ix * sizeof (unsigned);
196 if (__alignof__ (struct gcov_fn_info) > sizeof (unsigned))
198 fi_stride += __alignof__ (struct gcov_fn_info) - 1;
199 fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1);
202 if (!gcov_open (gi_ptr->filename))
204 fprintf (stderr, "profiling:%s:Cannot open\n", gi_ptr->filename);
205 continue;
208 tag = gcov_read_unsigned ();
209 if (tag)
211 /* Merge data from file. */
212 if (tag != GCOV_DATA_MAGIC)
214 fprintf (stderr, "profiling:%s:Not a gcov data file\n",
215 gi_ptr->filename);
216 read_fatal:;
217 gcov_close ();
218 continue;
220 length = gcov_read_unsigned ();
221 if (!gcov_version (gi_ptr, length))
222 goto read_fatal;
224 length = gcov_read_unsigned ();
225 if (length != gi_ptr->stamp)
227 /* Read from a different compilation. Overwrite the
228 file. */
229 gcov_truncate ();
230 goto rewrite;
233 /* Merge execution counts for each function. */
234 for (f_ix = gi_ptr->n_functions, fi_ptr = gi_ptr->functions;
235 f_ix--;
236 fi_ptr = (const struct gcov_fn_info *)
237 ((const char *) fi_ptr + fi_stride))
239 tag = gcov_read_unsigned ();
240 length = gcov_read_unsigned ();
242 /* Check function. */
243 if (tag != GCOV_TAG_FUNCTION
244 || length != GCOV_TAG_FUNCTION_LENGTH
245 || gcov_read_unsigned () != fi_ptr->ident
246 || gcov_read_unsigned () != fi_ptr->checksum)
248 read_mismatch:;
249 fprintf (stderr, "profiling:%s:Merge mismatch for %s\n",
250 gi_ptr->filename,
251 f_ix + 1 ? "function" : "summaries");
252 goto read_fatal;
255 for (c_ix = t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
256 if ((1 << t_ix) & gi_ptr->ctr_mask)
258 unsigned n_counts = fi_ptr->n_ctrs[c_ix];
259 gcov_merge_fn merge = gi_ptr->counts[c_ix].merge;
261 tag = gcov_read_unsigned ();
262 length = gcov_read_unsigned ();
263 if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
264 || length != GCOV_TAG_COUNTER_LENGTH (n_counts))
265 goto read_mismatch;
266 (*merge) (values[c_ix], n_counts);
267 values[c_ix] += n_counts;
268 c_ix++;
270 if ((error = gcov_is_error ()))
271 goto read_error;
274 /* Check program & object summary */
275 while (1)
277 gcov_position_t base = gcov_position ();
278 int is_program;
280 tag = gcov_read_unsigned ();
281 if (!tag)
282 break;
283 length = gcov_read_unsigned ();
284 is_program = tag == GCOV_TAG_PROGRAM_SUMMARY;
285 if (length != GCOV_TAG_SUMMARY_LENGTH
286 || (!is_program && tag != GCOV_TAG_OBJECT_SUMMARY))
287 goto read_mismatch;
288 gcov_read_summary (is_program ? &program : &object);
289 if ((error = gcov_is_error ()))
290 goto read_error;
291 if (is_program && program.checksum == gcov_crc32)
293 summary_pos = base;
294 goto rewrite;
299 if (!gcov_is_eof ())
301 read_error:;
302 fprintf (stderr, error < 0 ? "profiling:%s:Overflow merging\n"
303 : "profiling:%s:Error merging\n", gi_ptr->filename);
304 goto read_fatal;
306 rewrite:;
307 gcov_rewrite ();
308 if (!summary_pos)
309 memset (&program, 0, sizeof (program));
311 /* Merge the summaries. */
312 f_ix = ~0u;
313 for (t_ix = c_ix = 0,
314 cs_obj = object.ctrs, cs_tobj = this_object.ctrs,
315 cs_prg = program.ctrs, cs_tprg = this_program.ctrs,
316 cs_all = all.ctrs;
317 t_ix != GCOV_COUNTERS_SUMMABLE;
318 t_ix++, cs_obj++, cs_tobj++, cs_prg++, cs_tprg++, cs_all++)
320 if ((1 << t_ix) & gi_ptr->ctr_mask)
322 if (!cs_obj->runs++)
323 cs_obj->num = cs_tobj->num;
324 else if (cs_obj->num != cs_tobj->num)
325 goto read_mismatch;
326 cs_obj->sum_all += cs_tobj->sum_all;
327 if (cs_obj->run_max < cs_tobj->run_max)
328 cs_obj->run_max = cs_tobj->run_max;
329 cs_obj->sum_max += cs_tobj->run_max;
331 if (!cs_prg->runs++)
332 cs_prg->num = cs_tprg->num;
333 else if (cs_prg->num != cs_tprg->num)
334 goto read_mismatch;
335 cs_prg->sum_all += cs_tprg->sum_all;
336 if (cs_prg->run_max < cs_tprg->run_max)
337 cs_prg->run_max = cs_tprg->run_max;
338 cs_prg->sum_max += cs_tprg->run_max;
340 values[c_ix] = gi_ptr->counts[c_ix].values;
341 c_ix++;
343 else if (cs_obj->num || cs_prg->num)
344 goto read_mismatch;
346 if (!cs_all->runs && cs_prg->runs)
347 memcpy (cs_all, cs_prg, sizeof (*cs_all));
348 else if (!all.checksum
349 && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs)
350 && memcmp (cs_all, cs_prg, sizeof (*cs_all)))
352 fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s",
353 gi_ptr->filename, GCOV_LOCKED
354 ? "" : " or concurrent update without locking support");
355 all.checksum = ~0u;
359 program.checksum = gcov_crc32;
361 /* Write out the data. */
362 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
363 gcov_write_unsigned (gi_ptr->stamp);
365 /* Write execution counts for each function. */
366 for (f_ix = gi_ptr->n_functions, fi_ptr = gi_ptr->functions; f_ix--;
367 fi_ptr = (const struct gcov_fn_info *)
368 ((const char *) fi_ptr + fi_stride))
370 /* Announce function. */
371 gcov_write_tag_length (GCOV_TAG_FUNCTION, GCOV_TAG_FUNCTION_LENGTH);
372 gcov_write_unsigned (fi_ptr->ident);
373 gcov_write_unsigned (fi_ptr->checksum);
375 for (c_ix = t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
376 if ((1 << t_ix) & gi_ptr->ctr_mask)
378 unsigned n_counts = fi_ptr->n_ctrs[c_ix];
379 gcov_type *c_ptr;
381 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
382 GCOV_TAG_COUNTER_LENGTH (n_counts));
383 c_ptr = values[c_ix];
384 while (n_counts--)
385 gcov_write_counter (*c_ptr++);
386 values[c_ix] = c_ptr;
387 c_ix++;
391 /* Object file summary. */
392 gcov_write_summary (GCOV_TAG_OBJECT_SUMMARY, &object);
394 /* Generate whole program statistics. */
395 gcov_seek (summary_pos);
396 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &program);
397 if ((error = gcov_close ()))
398 fprintf (stderr, error < 0 ?
399 "profiling:%s:Overflow writing\n" :
400 "profiling:%s:Error writing\n",
401 gi_ptr->filename);
405 /* Add a new object file onto the bb chain. Invoked automatically
406 when running an object file's global ctors. */
408 void
409 __gcov_init (struct gcov_info *info)
411 if (!info->version)
412 return;
413 if (gcov_version (info, info->version))
415 const char *ptr = info->filename;
416 gcov_unsigned_t crc32 = gcov_crc32;
420 unsigned ix;
421 gcov_unsigned_t value = *ptr << 24;
423 for (ix = 8; ix--; value <<= 1)
425 gcov_unsigned_t feedback;
427 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
428 crc32 <<= 1;
429 crc32 ^= feedback;
432 while (*ptr++);
434 gcov_crc32 = crc32;
436 if (!gcov_list)
437 atexit (gcov_exit);
439 info->next = gcov_list;
440 gcov_list = info;
442 info->version = 0;
445 /* Called before fork or exec - write out profile information gathered so
446 far and reset it to zero. This avoids duplication or loss of the
447 profile information gathered so far. */
449 void
450 __gcov_flush (void)
452 const struct gcov_info *gi_ptr;
454 gcov_exit ();
455 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
457 unsigned t_ix;
458 const struct gcov_ctr_info *ci_ptr;
460 for (t_ix = 0, ci_ptr = gi_ptr->counts; t_ix != GCOV_COUNTERS; t_ix++)
461 if ((1 << t_ix) & gi_ptr->ctr_mask)
463 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
464 ci_ptr++;
469 #endif /* L_gcov */
471 #ifdef L_gcov_merge_add
472 /* The profile merging function that just adds the counters. It is given
473 an array COUNTERS of N_COUNTERS old counters and it reads the same number
474 of counters from the gcov file. */
475 void
476 __gcov_merge_add (gcov_type *counters, unsigned n_counters)
478 for (; n_counters; counters++, n_counters--)
479 *counters += gcov_read_counter ();
481 #endif /* L_gcov_merge_add */
483 #ifdef L_gcov_merge_single
484 /* The profile merging function for choosing the most common value.
485 It is given an array COUNTERS of N_COUNTERS old counters and it
486 reads the same number of counters from the gcov file. The counters
487 are split into 3-tuples where the members of the tuple have
488 meanings:
490 -- the stored candidate on the most common value of the measured entity
491 -- counter
492 -- total number of evaluations of the value */
493 void
494 __gcov_merge_single (gcov_type *counters, unsigned n_counters)
496 unsigned i, n_measures;
497 gcov_type value, counter, all;
499 GCOV_CHECK (!(n_counters % 3));
500 n_measures = n_counters / 3;
501 for (i = 0; i < n_measures; i++, counters += 3)
503 value = gcov_read_counter ();
504 counter = gcov_read_counter ();
505 all = gcov_read_counter ();
507 if (counters[0] == value)
508 counters[1] += counter;
509 else if (counter > counters[1])
511 counters[0] = value;
512 counters[1] = counter - counters[1];
514 else
515 counters[1] -= counter;
516 counters[2] += all;
519 #endif /* L_gcov_merge_single */
521 #ifdef L_gcov_merge_delta
522 /* The profile merging function for choosing the most common
523 difference between two consecutive evaluations of the value. It is
524 given an array COUNTERS of N_COUNTERS old counters and it reads the
525 same number of counters from the gcov file. The counters are split
526 into 4-tuples where the members of the tuple have meanings:
528 -- the last value of the measured entity
529 -- the stored candidate on the most common difference
530 -- counter
531 -- total number of evaluations of the value */
532 void
533 __gcov_merge_delta (gcov_type *counters, unsigned n_counters)
535 unsigned i, n_measures;
536 gcov_type last, value, counter, all;
538 GCOV_CHECK (!(n_counters % 4));
539 n_measures = n_counters / 4;
540 for (i = 0; i < n_measures; i++, counters += 4)
542 last = gcov_read_counter ();
543 value = gcov_read_counter ();
544 counter = gcov_read_counter ();
545 all = gcov_read_counter ();
547 if (counters[1] == value)
548 counters[2] += counter;
549 else if (counter > counters[2])
551 counters[1] = value;
552 counters[2] = counter - counters[2];
554 else
555 counters[2] -= counter;
556 counters[3] += all;
559 #endif /* L_gcov_merge_delta */
561 #endif /* inhibit_libc */