OSDN Git Service

* config/h8300/h8300.md (pushqi1_h8300hs): Revert my patch
[pf3gnuchains/gcc-fork.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  Free Software Foundation, Inc.
5
6 This file is part of GCC.
7
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.
12
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.)
21
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.
26
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.  */
31
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.  */
35
36 #include "tconfig.h"
37 #include "tsystem.h"
38 #include "coretypes.h"
39 #include "tm.h"
40
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"
52
53 #if defined(inhibit_libc)
54 /* If libc and its header files are not available, provide dummy functions.  */
55
56 #ifdef L_gcov
57 void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {}
58 void __gcov_flush (void) {}
59 #endif
60
61 #ifdef L_gcov_merge_add
62 void __gcov_merge_add (gcov_type *counters  __attribute__ ((unused)),
63                        unsigned n_counters __attribute__ ((unused))) {}
64 #endif
65
66 #ifdef L_gcov_merge_single
67 void __gcov_merge_single (gcov_type *counters  __attribute__ ((unused)),
68                           unsigned n_counters __attribute__ ((unused))) {}
69 #endif
70
71 #ifdef L_gcov_merge_delta
72 void __gcov_merge_delta (gcov_type *counters  __attribute__ ((unused)),
73                          unsigned n_counters __attribute__ ((unused))) {}
74 #endif
75
76 #else
77
78 #include <string.h>
79 #if GCOV_LOCKED
80 #include <fcntl.h>
81 #include <errno.h>
82 #endif
83
84 #ifdef L_gcov
85 #include "gcov-io.c"
86
87 /* Chain of per-object gcov structures.  */
88 static struct gcov_info *gcov_list;
89
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;
93
94 static void
95 gcov_version_mismatch (struct gcov_info *ptr, gcov_unsigned_t version)
96 {
97   gcov_unsigned_t expected = GCOV_VERSION;
98   unsigned ix;
99   char e[4], v[4];
100
101   for (ix = 4; ix--; expected >>= 8, version >>= 8)
102     {
103       e[ix] = expected;
104       v[ix] = version;
105     }
106   
107   fprintf (stderr,
108            "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
109            ptr->filename, e, v);
110 }
111
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.  */
118
119 static void
120 gcov_exit (void)
121 {
122   struct gcov_info *gi_ptr;
123   struct gcov_summary this_program;
124   struct gcov_summary all;
125
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)
130     {
131       const struct gcov_ctr_info *ci_ptr;
132       struct gcov_ctr_summary *cs_ptr;
133       unsigned t_ix;
134       
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)
138           {
139             const gcov_type *c_ptr;
140             gcov_unsigned_t c_num;
141
142             cs_ptr->num += ci_ptr->num;
143             for (c_num = ci_ptr->num, c_ptr = ci_ptr->values; c_num--; c_ptr++)
144               {
145                 cs_ptr->sum_all += *c_ptr;
146                 if (cs_ptr->run_max < *c_ptr)
147                   cs_ptr->run_max = *c_ptr;
148               }
149             ci_ptr++;
150           }
151     }
152
153   /* Now merge each file.  */
154   for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
155     {
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       int merging;
167       gcov_unsigned_t tag, length;
168       gcov_position_t summary_pos = 0;
169
170       memset (&this_object, 0, sizeof (this_object));
171       memset (&object, 0, sizeof (object));
172       
173       /* Totals for this object file.  */
174       for (t_ix = c_ix = 0,
175              ci_ptr = gi_ptr->counts, cs_ptr = this_object.ctrs;
176            t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++, cs_ptr++)
177         if ((1 << t_ix) & gi_ptr->ctr_mask)
178           {
179             const gcov_type *c_ptr;
180             gcov_unsigned_t c_num;
181
182             cs_ptr->num += ci_ptr->num;
183             values[c_ix] = ci_ptr->values;
184             for (c_num = ci_ptr->num, c_ptr = ci_ptr->values; c_num--; c_ptr++)
185               {
186                 cs_ptr->sum_all += *c_ptr;
187                 if (cs_ptr->run_max < *c_ptr)
188                   cs_ptr->run_max = *c_ptr;
189               }
190             c_ix++;
191             ci_ptr++;
192           }
193
194       /* Calculate the function_info stride. This depends on the
195          number of counter types being measured.  */
196       fi_stride = sizeof (struct gcov_fn_info) + c_ix * sizeof (unsigned);
197       if (__alignof__ (struct gcov_fn_info) > sizeof (unsigned))
198         {
199           fi_stride += __alignof__ (struct gcov_fn_info) - 1;
200           fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1);
201         }
202       
203       /* Open for modification, if possible */
204       merging = gcov_open (gi_ptr->filename, 0);
205       if (!merging)
206         {
207           fprintf (stderr, "profiling:%s:Cannot open\n", gi_ptr->filename);
208           continue;
209         }
210       
211       if (merging > 0)
212         {
213           /* Merge data from file.  */
214           if (gcov_read_unsigned () != GCOV_DATA_MAGIC)
215             {
216               fprintf (stderr, "profiling:%s:Not a gcov data file\n",
217                        gi_ptr->filename);
218             read_fatal:;
219               gcov_close ();
220               continue;
221             }
222           length = gcov_read_unsigned ();
223           if (length != GCOV_VERSION)
224             {
225               gcov_version_mismatch (gi_ptr, length);
226               goto read_fatal;
227             }
228
229           length = gcov_read_unsigned ();
230           if (length != gi_ptr->stamp)
231             {
232               /* Read from a different compilation. Overwrite the
233                  file.  */
234               gcov_truncate ();
235               goto rewrite;
236             }
237           
238           /* Merge execution counts for each function.  */
239           for (f_ix = gi_ptr->n_functions, fi_ptr = gi_ptr->functions;
240                f_ix--;
241                fi_ptr = (const struct gcov_fn_info *)
242                  ((const char *) fi_ptr + fi_stride))
243             {
244               tag = gcov_read_unsigned ();
245               length = gcov_read_unsigned ();
246
247               /* Check function.  */
248               if (tag != GCOV_TAG_FUNCTION
249                   || length != GCOV_TAG_FUNCTION_LENGTH
250                   || gcov_read_unsigned () != fi_ptr->ident
251                   || gcov_read_unsigned () != fi_ptr->checksum)
252                 {
253                 read_mismatch:;
254                   fprintf (stderr, "profiling:%s:Merge mismatch for %s\n",
255                            gi_ptr->filename,
256                            f_ix + 1 ? "function" : "summaries");
257                   goto read_fatal;
258                 }
259
260               for (c_ix = t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
261                 if ((1 << t_ix) & gi_ptr->ctr_mask)
262                   {
263                     unsigned n_counts = fi_ptr->n_ctrs[c_ix];
264                     gcov_merge_fn merge = gi_ptr->counts[c_ix].merge;
265                     
266                     tag = gcov_read_unsigned ();
267                     length = gcov_read_unsigned ();
268                     if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
269                         || length != GCOV_TAG_COUNTER_LENGTH (n_counts))
270                       goto read_mismatch;
271                     (*merge) (values[c_ix], n_counts);
272                     values[c_ix] += n_counts;
273                     c_ix++;
274                 }
275               if ((error = gcov_is_error ()))
276                 goto read_error;
277             }
278
279           /* Check program & object summary */
280           while (1)
281             {
282               gcov_position_t base = gcov_position ();
283               int is_program;
284               
285               tag = gcov_read_unsigned ();
286               if (!tag)
287                 break;
288               length = gcov_read_unsigned ();
289               is_program = tag == GCOV_TAG_PROGRAM_SUMMARY;
290               if (length != GCOV_TAG_SUMMARY_LENGTH
291                   || (!is_program && tag != GCOV_TAG_OBJECT_SUMMARY))
292                 goto read_mismatch;
293               gcov_read_summary (is_program ? &program : &object);
294               if ((error = gcov_is_error ()))
295                 goto read_error;
296               if (is_program && program.checksum == gcov_crc32)
297                 {
298                   summary_pos = base;
299                   goto rewrite;
300                 }
301             }
302           if (!gcov_is_eof ())
303             {
304             read_error:;
305               fprintf (stderr, error < 0 ? "profiling:%s:Overflow merging\n"
306                        : "profiling:%s:Error merging\n", gi_ptr->filename);
307               goto read_fatal;
308             }
309         rewrite:;
310           gcov_rewrite ();
311         }
312       if (!summary_pos)
313         memset (&program, 0, sizeof (program));
314
315       /* Merge the summaries.  */
316       f_ix = ~0u;
317       for (t_ix = c_ix = 0,
318              cs_obj = object.ctrs, cs_tobj = this_object.ctrs,
319              cs_prg = program.ctrs, cs_tprg = this_program.ctrs,
320              cs_all = all.ctrs;
321            t_ix != GCOV_COUNTERS_SUMMABLE;
322            t_ix++, cs_obj++, cs_tobj++, cs_prg++, cs_tprg++, cs_all++)
323         {
324           if ((1 << t_ix) & gi_ptr->ctr_mask)
325             {
326               if (!cs_obj->runs++)
327                 cs_obj->num = cs_tobj->num;
328               else if (cs_obj->num != cs_tobj->num)
329                 goto read_mismatch;
330               cs_obj->sum_all += cs_tobj->sum_all;
331               if (cs_obj->run_max < cs_tobj->run_max)
332                 cs_obj->run_max = cs_tobj->run_max;
333               cs_obj->sum_max += cs_tobj->run_max;
334               
335               if (!cs_prg->runs++)
336                 cs_prg->num = cs_tprg->num;
337               else if (cs_prg->num != cs_tprg->num)
338                 goto read_mismatch;
339               cs_prg->sum_all += cs_tprg->sum_all;
340               if (cs_prg->run_max < cs_tprg->run_max)
341                 cs_prg->run_max = cs_tprg->run_max;
342               cs_prg->sum_max += cs_tprg->run_max;
343               
344               values[c_ix] = gi_ptr->counts[c_ix].values;
345               c_ix++;
346             }
347           else if (cs_obj->num || cs_prg->num)
348             goto read_mismatch;
349           
350           if (!cs_all->runs && cs_prg->runs)
351             memcpy (cs_all, cs_prg, sizeof (*cs_all));
352           else if (!all.checksum
353                    && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs)
354                    && memcmp (cs_all, cs_prg, sizeof (*cs_all)))
355             {
356               fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s",
357                        gi_ptr->filename, GCOV_LOCKED
358                        ? "" : " or concurrent update without locking support");
359               all.checksum = ~0u;
360             }
361         }
362       
363       program.checksum = gcov_crc32;
364       
365       /* Write out the data.  */
366       gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
367       gcov_write_unsigned (gi_ptr->stamp);
368       
369       /* Write execution counts for each function.  */
370       for (f_ix = gi_ptr->n_functions, fi_ptr = gi_ptr->functions; f_ix--;
371            fi_ptr = (const struct gcov_fn_info *)
372              ((const char *) fi_ptr + fi_stride))
373         {
374           /* Announce function.  */
375           gcov_write_tag_length (GCOV_TAG_FUNCTION, GCOV_TAG_FUNCTION_LENGTH);
376           gcov_write_unsigned (fi_ptr->ident);
377           gcov_write_unsigned (fi_ptr->checksum);
378
379           for (c_ix = t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
380             if ((1 << t_ix) & gi_ptr->ctr_mask)
381               {
382                 unsigned n_counts = fi_ptr->n_ctrs[c_ix];
383                 gcov_type *c_ptr;
384                     
385                 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
386                                        GCOV_TAG_COUNTER_LENGTH (n_counts));
387                 c_ptr = values[c_ix];
388                 while (n_counts--)
389                   gcov_write_counter (*c_ptr++);
390                 values[c_ix] = c_ptr;
391                 c_ix++;
392               }
393         }
394
395       /* Object file summary.  */
396       gcov_write_summary (GCOV_TAG_OBJECT_SUMMARY, &object);
397
398       /* Generate whole program statistics.  */
399       gcov_seek (summary_pos);
400       gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &program);
401       if ((error = gcov_close ()))
402           fprintf (stderr, error  < 0 ?
403                    "profiling:%s:Overflow writing\n" :
404                    "profiling:%s:Error writing\n",
405                    gi_ptr->filename);
406     }
407 }
408
409 /* Add a new object file onto the bb chain.  Invoked automatically
410    when running an object file's global ctors.  */
411
412 void
413 __gcov_init (struct gcov_info *info)
414 {
415   if (!info->version)
416     return;
417   if (info->version != GCOV_VERSION)
418     gcov_version_mismatch (info, info->version);
419   else
420     {
421       const char *ptr = info->filename;
422       gcov_unsigned_t crc32 = gcov_crc32;
423   
424       do
425         {
426           unsigned ix;
427           gcov_unsigned_t value = *ptr << 24;
428
429           for (ix = 8; ix--; value <<= 1)
430             {
431               gcov_unsigned_t feedback;
432
433               feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
434               crc32 <<= 1;
435               crc32 ^= feedback;
436             }
437         }
438       while (*ptr++);
439       
440       gcov_crc32 = crc32;
441       
442       if (!gcov_list)
443         atexit (gcov_exit);
444       
445       info->next = gcov_list;
446       gcov_list = info;
447     }
448   info->version = 0;
449 }
450
451 /* Called before fork or exec - write out profile information gathered so
452    far and reset it to zero.  This avoids duplication or loss of the
453    profile information gathered so far.  */
454
455 void
456 __gcov_flush (void)
457 {
458   const struct gcov_info *gi_ptr;
459
460   gcov_exit ();
461   for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
462     {
463       unsigned t_ix;
464       const struct gcov_ctr_info *ci_ptr;
465       
466       for (t_ix = 0, ci_ptr = gi_ptr->counts; t_ix != GCOV_COUNTERS; t_ix++)
467         if ((1 << t_ix) & gi_ptr->ctr_mask)
468           {
469             memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
470             ci_ptr++;
471           }
472     }
473 }
474
475 #endif /* L_gcov */
476
477 #ifdef L_gcov_merge_add
478 /* The profile merging function that just adds the counters.  It is given
479    an array COUNTERS of N_COUNTERS old counters and it reads the same number
480    of counters from the gcov file.  */
481 void
482 __gcov_merge_add (gcov_type *counters, unsigned n_counters)
483 {
484   for (; n_counters; counters++, n_counters--)
485     *counters += gcov_read_counter ();
486 }
487 #endif /* L_gcov_merge_add */
488
489 #ifdef L_gcov_merge_single
490 /* The profile merging function for choosing the most common value.  It is given
491    an array COUNTERS of N_COUNTERS old counters and it reads the same number
492    of counters from the gcov file.  The counters are split into 3-tuples
493    where the members of the tuple have meanings:
494    -- the stored candidate on the most common value of the measured entity
495    -- counter
496    -- total number of evaluations of the value  */
497 void
498 __gcov_merge_single (gcov_type *counters, unsigned n_counters)
499 {
500   unsigned i, n_measures;
501   gcov_type value, counter, all;
502
503   if (n_counters % 3)
504     abort ();
505
506   n_measures = n_counters / 3;
507   for (i = 0; i < n_measures; i++, counters += 3)
508     {
509       value = gcov_read_counter ();
510       counter = gcov_read_counter ();
511       all = gcov_read_counter ();
512
513       if (counters[0] == value)
514         counters[1] += counter;
515       else if (counter > counters[1])
516         {
517           counters[0] = value;
518           counters[1] = counter - counters[1];
519         }
520       else
521         counters[1] -= counter;
522       counters[2] += all;
523     }
524 }
525 #endif /* L_gcov_merge_single */
526
527 #ifdef L_gcov_merge_delta
528 /* The profile merging function for choosing the most common difference between
529    two consecutive evaluations of the value.  It is given an array COUNTERS of
530    N_COUNTERS old counters and it reads the same number of counters from the
531    gcov file.  The counters are split into 4-tuples where the members of the
532    tuple have meanings:
533    -- the last value of the measured entity
534    -- the stored candidate on the most common difference
535    -- counter
536    -- total number of evaluations of the value  */
537 void
538 __gcov_merge_delta (gcov_type *counters, unsigned n_counters)
539 {
540   unsigned i, n_measures;
541   gcov_type last, value, counter, all;
542
543   if (n_counters % 4)
544     abort ();
545
546   n_measures = n_counters / 4;
547   for (i = 0; i < n_measures; i++, counters += 4)
548     {
549       last = gcov_read_counter ();
550       value = gcov_read_counter ();
551       counter = gcov_read_counter ();
552       all = gcov_read_counter ();
553
554       if (counters[1] == value)
555         counters[2] += counter;
556       else if (counter > counters[2])
557         {
558           counters[1] = value;
559           counters[2] = counter - counters[2];
560         }
561       else
562         counters[2] -= counter;
563       counters[3] += all;
564     }
565 }
566 #endif /* L_gcov_merge_delta */
567
568 #endif /* inhibit_libc */