OSDN Git Service

Sanitize the behavior of -Wcoverage-mismatch.
[pf3gnuchains/gcc-fork.git] / gcc / coverage.c
1 /* Read and write coverage files, and associated functionality.
2    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
3    2000, 2001, 2003, 2004, 2005, 2007, 2008 Free Software Foundation,
4    Inc.
5    Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
6    based on some ideas from Dain Samples of UC Berkeley.
7    Further mangling by Bob Manson, Cygnus Support.
8    Further mangled by Nathan Sidwell, CodeSourcery
9
10 This file is part of GCC.
11
12 GCC is free software; you can redistribute it and/or modify it under
13 the terms of the GNU General Public License as published by the Free
14 Software Foundation; either version 3, or (at your option) any later
15 version.
16
17 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
18 WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with GCC; see the file COPYING3.  If not see
24 <http://www.gnu.org/licenses/>.  */
25
26
27 #define GCOV_LINKAGE
28
29 #include "config.h"
30 #include "system.h"
31 #include "coretypes.h"
32 #include "tm.h"
33 #include "rtl.h"
34 #include "tree.h"
35 #include "flags.h"
36 #include "output.h"
37 #include "regs.h"
38 #include "expr.h"
39 #include "function.h"
40 #include "toplev.h"
41 #include "tm_p.h"
42 #include "ggc.h"
43 #include "coverage.h"
44 #include "langhooks.h"
45 #include "hashtab.h"
46 #include "tree-iterator.h"
47 #include "cgraph.h"
48 #include "tree-pass.h"
49 #include "diagnostic.h"
50 #include "intl.h"
51
52 #include "gcov-io.c"
53
54 struct function_list
55 {
56   struct function_list *next;    /* next function */
57   unsigned ident;                /* function ident */
58   unsigned checksum;             /* function checksum */
59   unsigned n_ctrs[GCOV_COUNTERS];/* number of counters.  */
60 };
61
62 /* Counts information for a function.  */
63 typedef struct counts_entry
64 {
65   /* We hash by  */
66   unsigned ident;
67   unsigned ctr;
68
69   /* Store  */
70   unsigned checksum;
71   gcov_type *counts;
72   struct gcov_ctr_summary summary;
73
74   /* Workspace */
75   struct counts_entry *chain;
76
77 } counts_entry_t;
78
79 static struct function_list *functions_head = 0;
80 static struct function_list **functions_tail = &functions_head;
81 static unsigned no_coverage = 0;
82
83 /* Cumulative counter information for whole program.  */
84 static unsigned prg_ctr_mask; /* Mask of counter types generated.  */
85 static unsigned prg_n_ctrs[GCOV_COUNTERS]; /* Total counters allocated.  */
86
87 /* Counter information for current function.  */
88 static unsigned fn_ctr_mask; /* Mask of counters used.  */
89 static unsigned fn_n_ctrs[GCOV_COUNTERS]; /* Counters allocated.  */
90 static unsigned fn_b_ctrs[GCOV_COUNTERS]; /* Allocation base.  */
91
92 /* Name of the output file for coverage output file.  */
93 static char *bbg_file_name;
94 static unsigned bbg_file_opened;
95 static int bbg_function_announced;
96
97 /* Name of the count data file.  */
98 static char *da_file_name;
99
100 /* Hash table of count data.  */
101 static htab_t counts_hash = NULL;
102
103 /* Trees representing the counter table arrays.  */
104 static GTY(()) tree tree_ctr_tables[GCOV_COUNTERS];
105
106 /* The names of the counter tables.  Not used if we're
107    generating counters at tree level.  */
108 static GTY(()) rtx ctr_labels[GCOV_COUNTERS];
109
110 /* The names of merge functions for counters.  */
111 static const char *const ctr_merge_functions[GCOV_COUNTERS] = GCOV_MERGE_FUNCTIONS;
112 static const char *const ctr_names[GCOV_COUNTERS] = GCOV_COUNTER_NAMES;
113
114 /* Forward declarations.  */
115 static hashval_t htab_counts_entry_hash (const void *);
116 static int htab_counts_entry_eq (const void *, const void *);
117 static void htab_counts_entry_del (void *);
118 static void read_counts_file (void);
119 static unsigned compute_checksum (void);
120 static unsigned coverage_checksum_string (unsigned, const char *);
121 static tree build_fn_info_type (unsigned);
122 static tree build_fn_info_value (const struct function_list *, tree);
123 static tree build_ctr_info_type (void);
124 static tree build_ctr_info_value (unsigned, tree);
125 static tree build_gcov_info (void);
126 static void create_coverage (void);
127 \f
128 /* Return the type node for gcov_type.  */
129
130 tree
131 get_gcov_type (void)
132 {
133   return lang_hooks.types.type_for_size (GCOV_TYPE_SIZE, false);
134 }
135
136 /* Return the type node for gcov_unsigned_t.  */
137
138 static tree
139 get_gcov_unsigned_t (void)
140 {
141   return lang_hooks.types.type_for_size (32, true);
142 }
143 \f
144 static hashval_t
145 htab_counts_entry_hash (const void *of)
146 {
147   const counts_entry_t *const entry = (const counts_entry_t *) of;
148
149   return entry->ident * GCOV_COUNTERS + entry->ctr;
150 }
151
152 static int
153 htab_counts_entry_eq (const void *of1, const void *of2)
154 {
155   const counts_entry_t *const entry1 = (const counts_entry_t *) of1;
156   const counts_entry_t *const entry2 = (const counts_entry_t *) of2;
157
158   return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
159 }
160
161 static void
162 htab_counts_entry_del (void *of)
163 {
164   counts_entry_t *const entry = (counts_entry_t *) of;
165
166   free (entry->counts);
167   free (entry);
168 }
169
170 /* Read in the counts file, if available.  */
171
172 static void
173 read_counts_file (void)
174 {
175   gcov_unsigned_t fn_ident = 0;
176   gcov_unsigned_t checksum = -1;
177   counts_entry_t *summaried = NULL;
178   unsigned seen_summary = 0;
179   gcov_unsigned_t tag;
180   int is_error = 0;
181
182   if (!gcov_open (da_file_name, 1))
183     return;
184
185   if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
186     {
187       warning (0, "%qs is not a gcov data file", da_file_name);
188       gcov_close ();
189       return;
190     }
191   else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
192     {
193       char v[4], e[4];
194
195       GCOV_UNSIGNED2STRING (v, tag);
196       GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
197
198       warning (0, "%qs is version %q.*s, expected version %q.*s",
199                da_file_name, 4, v, 4, e);
200       gcov_close ();
201       return;
202     }
203
204   /* Read and discard the stamp.  */
205   gcov_read_unsigned ();
206
207   counts_hash = htab_create (10,
208                              htab_counts_entry_hash, htab_counts_entry_eq,
209                              htab_counts_entry_del);
210   while ((tag = gcov_read_unsigned ()))
211     {
212       gcov_unsigned_t length;
213       gcov_position_t offset;
214
215       length = gcov_read_unsigned ();
216       offset = gcov_position ();
217       if (tag == GCOV_TAG_FUNCTION)
218         {
219           fn_ident = gcov_read_unsigned ();
220           checksum = gcov_read_unsigned ();
221           if (seen_summary)
222             {
223               /* We have already seen a summary, this means that this
224                  new function begins a new set of program runs. We
225                  must unlink the summaried chain.  */
226               counts_entry_t *entry, *chain;
227
228               for (entry = summaried; entry; entry = chain)
229                 {
230                   chain = entry->chain;
231                   entry->chain = NULL;
232                 }
233               summaried = NULL;
234               seen_summary = 0;
235             }
236         }
237       else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
238         {
239           counts_entry_t *entry;
240           struct gcov_summary summary;
241
242           gcov_read_summary (&summary);
243           seen_summary = 1;
244           for (entry = summaried; entry; entry = entry->chain)
245             {
246               struct gcov_ctr_summary *csum = &summary.ctrs[entry->ctr];
247
248               entry->summary.runs += csum->runs;
249               entry->summary.sum_all += csum->sum_all;
250               if (entry->summary.run_max < csum->run_max)
251                 entry->summary.run_max = csum->run_max;
252               entry->summary.sum_max += csum->sum_max;
253             }
254         }
255       else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
256         {
257           counts_entry_t **slot, *entry, elt;
258           unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
259           unsigned ix;
260
261           elt.ident = fn_ident;
262           elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
263
264           slot = (counts_entry_t **) htab_find_slot
265             (counts_hash, &elt, INSERT);
266           entry = *slot;
267           if (!entry)
268             {
269               *slot = entry = XCNEW (counts_entry_t);
270               entry->ident = elt.ident;
271               entry->ctr = elt.ctr;
272               entry->checksum = checksum;
273               entry->summary.num = n_counts;
274               entry->counts = XCNEWVEC (gcov_type, n_counts);
275             }
276           else if (entry->checksum != checksum)
277             {
278               error ("coverage mismatch for function %u while reading execution counters",
279                      fn_ident);
280               error ("checksum is %x instead of %x", entry->checksum, checksum);
281               htab_delete (counts_hash);
282               break;
283             }
284           else if (entry->summary.num != n_counts)
285             {
286               error ("coverage mismatch for function %u while reading execution counters",
287                      fn_ident);
288               error ("number of counters is %d instead of %d", entry->summary.num, n_counts);
289               htab_delete (counts_hash);
290               break;
291             }
292           else if (elt.ctr >= GCOV_COUNTERS_SUMMABLE)
293             {
294               error ("cannot merge separate %s counters for function %u",
295                      ctr_names[elt.ctr], fn_ident);
296               goto skip_merge;
297             }
298
299           if (elt.ctr < GCOV_COUNTERS_SUMMABLE
300               /* This should always be true for a just allocated entry,
301                  and always false for an existing one. Check this way, in
302                  case the gcov file is corrupt.  */
303               && (!entry->chain || summaried != entry))
304             {
305               entry->chain = summaried;
306               summaried = entry;
307             }
308           for (ix = 0; ix != n_counts; ix++)
309             entry->counts[ix] += gcov_read_counter ();
310         skip_merge:;
311         }
312       gcov_sync (offset, length);
313       if ((is_error = gcov_is_error ()))
314         {
315           error (is_error < 0 ? "%qs has overflowed" : "%qs is corrupted",
316                  da_file_name);
317           htab_delete (counts_hash);
318           break;
319         }
320     }
321
322   gcov_close ();
323 }
324
325 /* Returns the counters for a particular tag.  */
326
327 gcov_type *
328 get_coverage_counts (unsigned counter, unsigned expected,
329                      const struct gcov_ctr_summary **summary)
330 {
331   counts_entry_t *entry, elt;
332   gcov_unsigned_t checksum = -1;
333
334   /* No hash table, no counts.  */
335   if (!counts_hash)
336     {
337       static int warned = 0;
338
339       if (!warned++)
340         inform (input_location, (flag_guess_branch_prob
341                  ? "file %s not found, execution counts estimated"
342                  : "file %s not found, execution counts assumed to be zero"),
343                 da_file_name);
344       return NULL;
345     }
346
347   elt.ident = current_function_funcdef_no + 1;
348   elt.ctr = counter;
349   entry = (counts_entry_t *) htab_find (counts_hash, &elt);
350   if (!entry)
351     {
352       warning (0, "no coverage for function %qE found",
353                DECL_ASSEMBLER_NAME (current_function_decl));
354       return NULL;
355     }
356
357   checksum = compute_checksum ();
358   if (entry->checksum != checksum
359       || entry->summary.num != expected)
360     {
361       static int warned = 0;
362       bool warning_printed = false;
363       tree id = DECL_ASSEMBLER_NAME (current_function_decl);
364
365       warning_printed = 
366         warning_at (input_location, OPT_Wcoverage_mismatch, 
367                     "coverage mismatch for function "
368                     "%qE while reading counter %qs", id, ctr_names[counter]);
369       if (warning_printed)
370         {
371           if (entry->checksum != checksum)
372             inform (input_location, "checksum is %x instead of %x",
373                     entry->checksum, checksum);
374           else
375             inform (input_location, "number of counters is %d instead of %d",
376                     entry->summary.num, expected);
377           
378           if (!(errorcount || sorrycount)
379               && !warned++)
380             {
381               inform (input_location, "coverage mismatch ignored");
382               inform (input_location, flag_guess_branch_prob
383                       ? G_("execution counts estimated")
384                       : G_("execution counts assumed to be zero"));
385               if (!flag_guess_branch_prob)
386                 inform (input_location,
387                         "this can result in poorly optimized code");
388             }
389         }
390
391       return NULL;
392     }
393
394   if (summary)
395     *summary = &entry->summary;
396
397   return entry->counts;
398 }
399
400 /* Allocate NUM counters of type COUNTER. Returns nonzero if the
401    allocation succeeded.  */
402
403 int
404 coverage_counter_alloc (unsigned counter, unsigned num)
405 {
406   if (no_coverage)
407     return 0;
408
409   if (!num)
410     return 1;
411
412   if (!tree_ctr_tables[counter])
413     {
414       /* Generate and save a copy of this so it can be shared.  Leave
415          the index type unspecified for now; it will be set after all
416          functions have been compiled.  */
417       char buf[20];
418       tree gcov_type_node = get_gcov_type ();
419       tree gcov_type_array_type
420         = build_array_type (gcov_type_node, NULL_TREE);
421       tree_ctr_tables[counter]
422         = build_decl (BUILTINS_LOCATION,
423                       VAR_DECL, NULL_TREE, gcov_type_array_type);
424       TREE_STATIC (tree_ctr_tables[counter]) = 1;
425       ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
426       DECL_NAME (tree_ctr_tables[counter]) = get_identifier (buf);
427       DECL_ALIGN (tree_ctr_tables[counter]) = TYPE_ALIGN (gcov_type_node);
428
429       if (dump_file)
430         fprintf (dump_file, "Using data file %s\n", da_file_name);
431     }
432   fn_b_ctrs[counter] = fn_n_ctrs[counter];
433   fn_n_ctrs[counter] += num;
434   fn_ctr_mask |= 1 << counter;
435   return 1;
436 }
437
438 /* Generate a tree to access COUNTER NO.  */
439
440 tree
441 tree_coverage_counter_ref (unsigned counter, unsigned no)
442 {
443   tree gcov_type_node = get_gcov_type ();
444
445   gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
446   no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
447
448   /* "no" here is an array index, scaled to bytes later.  */
449   return build4 (ARRAY_REF, gcov_type_node, tree_ctr_tables[counter],
450                  build_int_cst (NULL_TREE, no), NULL, NULL);
451 }
452
453 /* Generate a tree to access the address of COUNTER NO.  */
454
455 tree
456 tree_coverage_counter_addr (unsigned counter, unsigned no)
457 {
458   tree gcov_type_node = get_gcov_type ();
459
460   gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
461   no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
462
463   TREE_ADDRESSABLE (tree_ctr_tables[counter]) = 1;
464
465   /* "no" here is an array index, scaled to bytes later.  */
466   return build_fold_addr_expr (build4 (ARRAY_REF, gcov_type_node,
467                                        tree_ctr_tables[counter],
468                                        build_int_cst (NULL_TREE, no),
469                                        NULL, NULL));
470 }
471 \f
472 /* Generate a checksum for a string.  CHKSUM is the current
473    checksum.  */
474
475 static unsigned
476 coverage_checksum_string (unsigned chksum, const char *string)
477 {
478   int i;
479   char *dup = NULL;
480
481   /* Look for everything that looks if it were produced by
482      get_file_function_name and zero out the second part
483      that may result from flag_random_seed.  This is not critical
484      as the checksums are used only for sanity checking.  */
485   for (i = 0; string[i]; i++)
486     {
487       int offset = 0;
488       if (!strncmp (string + i, "_GLOBAL__N_", 11))
489       offset = 11;
490       if (!strncmp (string + i, "_GLOBAL__", 9))
491       offset = 9;
492
493       /* C++ namespaces do have scheme:
494          _GLOBAL__N_<filename>_<wrongmagicnumber>_<magicnumber>functionname
495        since filename might contain extra underscores there seems
496        to be no better chance then walk all possible offsets looking
497        for magicnumber.  */
498       if (offset)
499         {
500           for (i = i + offset; string[i]; i++)
501             if (string[i]=='_')
502               {
503                 int y;
504
505                 for (y = 1; y < 9; y++)
506                   if (!(string[i + y] >= '0' && string[i + y] <= '9')
507                       && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
508                     break;
509                 if (y != 9 || string[i + 9] != '_')
510                   continue;
511                 for (y = 10; y < 18; y++)
512                   if (!(string[i + y] >= '0' && string[i + y] <= '9')
513                       && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
514                     break;
515                 if (y != 18)
516                   continue;
517                 if (!dup)
518                   string = dup = xstrdup (string);
519                 for (y = 10; y < 18; y++)
520                   dup[i + y] = '0';
521               }
522           break;
523         }
524     }
525
526   chksum = crc32_string (chksum, string);
527   if (dup)
528     free (dup);
529
530   return chksum;
531 }
532
533 /* Compute checksum for the current function.  We generate a CRC32.  */
534
535 static unsigned
536 compute_checksum (void)
537 {
538   expanded_location xloc
539     = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
540   unsigned chksum = xloc.line;
541
542   chksum = coverage_checksum_string (chksum, xloc.file);
543   chksum = coverage_checksum_string
544     (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
545
546   return chksum;
547 }
548 \f
549 /* Begin output to the graph file for the current function.
550    Opens the output file, if not already done. Writes the
551    function header, if not already done. Returns nonzero if data
552    should be output.  */
553
554 int
555 coverage_begin_output (void)
556 {
557   /* We don't need to output .gcno file unless we're under -ftest-coverage
558      (e.g. -fprofile-arcs/generate/use don't need .gcno to work). */
559   if (no_coverage || !flag_test_coverage || flag_compare_debug)
560     return 0;
561
562   if (!bbg_function_announced)
563     {
564       expanded_location xloc
565         = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
566       unsigned long offset;
567
568       if (!bbg_file_opened)
569         {
570           if (!gcov_open (bbg_file_name, -1))
571             error ("cannot open %s", bbg_file_name);
572           else
573             {
574               gcov_write_unsigned (GCOV_NOTE_MAGIC);
575               gcov_write_unsigned (GCOV_VERSION);
576               gcov_write_unsigned (local_tick);
577             }
578           bbg_file_opened = 1;
579         }
580
581       /* Announce function */
582       offset = gcov_write_tag (GCOV_TAG_FUNCTION);
583       gcov_write_unsigned (current_function_funcdef_no + 1);
584       gcov_write_unsigned (compute_checksum ());
585       gcov_write_string (IDENTIFIER_POINTER
586                          (DECL_ASSEMBLER_NAME (current_function_decl)));
587       gcov_write_string (xloc.file);
588       gcov_write_unsigned (xloc.line);
589       gcov_write_length (offset);
590
591       bbg_function_announced = 1;
592     }
593   return !gcov_is_error ();
594 }
595
596 /* Finish coverage data for the current function. Verify no output
597    error has occurred.  Save function coverage counts.  */
598
599 void
600 coverage_end_function (void)
601 {
602   unsigned i;
603
604   if (bbg_file_opened > 1 && gcov_is_error ())
605     {
606       warning (0, "error writing %qs", bbg_file_name);
607       bbg_file_opened = -1;
608     }
609
610   if (fn_ctr_mask)
611     {
612       struct function_list *item;
613
614       item = XNEW (struct function_list);
615
616       *functions_tail = item;
617       functions_tail = &item->next;
618
619       item->next = 0;
620       item->ident = current_function_funcdef_no + 1;
621       item->checksum = compute_checksum ();
622       for (i = 0; i != GCOV_COUNTERS; i++)
623         {
624           item->n_ctrs[i] = fn_n_ctrs[i];
625           prg_n_ctrs[i] += fn_n_ctrs[i];
626           fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
627         }
628       prg_ctr_mask |= fn_ctr_mask;
629       fn_ctr_mask = 0;
630     }
631   bbg_function_announced = 0;
632 }
633
634 /* Creates the gcov_fn_info RECORD_TYPE.  */
635
636 static tree
637 build_fn_info_type (unsigned int counters)
638 {
639   tree type = lang_hooks.types.make_type (RECORD_TYPE);
640   tree field, fields;
641   tree array_type;
642
643   /* ident */
644   fields = build_decl (BUILTINS_LOCATION,
645                        FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
646
647   /* checksum */
648   field = build_decl (BUILTINS_LOCATION,
649                       FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
650   TREE_CHAIN (field) = fields;
651   fields = field;
652
653   array_type = build_int_cst (NULL_TREE, counters - 1);
654   array_type = build_index_type (array_type);
655   array_type = build_array_type (get_gcov_unsigned_t (), array_type);
656
657   /* counters */
658   field = build_decl (BUILTINS_LOCATION,
659                       FIELD_DECL, NULL_TREE, array_type);
660   TREE_CHAIN (field) = fields;
661   fields = field;
662
663   finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
664
665   return type;
666 }
667
668 /* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
669    the function being processed and TYPE is the gcov_fn_info
670    RECORD_TYPE.  */
671
672 static tree
673 build_fn_info_value (const struct function_list *function, tree type)
674 {
675   tree value = NULL_TREE;
676   tree fields = TYPE_FIELDS (type);
677   unsigned ix;
678   tree array_value = NULL_TREE;
679
680   /* ident */
681   value = tree_cons (fields, build_int_cstu (get_gcov_unsigned_t (),
682                                              function->ident), value);
683   fields = TREE_CHAIN (fields);
684
685   /* checksum */
686   value = tree_cons (fields, build_int_cstu (get_gcov_unsigned_t (),
687                                              function->checksum), value);
688   fields = TREE_CHAIN (fields);
689
690   /* counters */
691   for (ix = 0; ix != GCOV_COUNTERS; ix++)
692     if (prg_ctr_mask & (1 << ix))
693       {
694         tree counters = build_int_cstu (get_gcov_unsigned_t (),
695                                         function->n_ctrs[ix]);
696
697         array_value = tree_cons (NULL_TREE, counters, array_value);
698       }
699
700   /* FIXME: use build_constructor directly.  */
701   array_value = build_constructor_from_list (TREE_TYPE (fields),
702                                              nreverse (array_value));
703   value = tree_cons (fields, array_value, value);
704
705   /* FIXME: use build_constructor directly.  */
706   value = build_constructor_from_list (type, nreverse (value));
707
708   return value;
709 }
710
711 /* Creates the gcov_ctr_info RECORD_TYPE.  */
712
713 static tree
714 build_ctr_info_type (void)
715 {
716   tree type = lang_hooks.types.make_type (RECORD_TYPE);
717   tree field, fields = NULL_TREE;
718   tree gcov_ptr_type = build_pointer_type (get_gcov_type ());
719   tree gcov_merge_fn_type;
720
721   /* counters */
722   field = build_decl (BUILTINS_LOCATION,
723                       FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
724   TREE_CHAIN (field) = fields;
725   fields = field;
726
727   /* values */
728   field = build_decl (BUILTINS_LOCATION,
729                       FIELD_DECL, NULL_TREE, gcov_ptr_type);
730   TREE_CHAIN (field) = fields;
731   fields = field;
732
733   /* merge */
734   gcov_merge_fn_type =
735     build_function_type_list (void_type_node,
736                               gcov_ptr_type, get_gcov_unsigned_t (),
737                               NULL_TREE);
738   field = build_decl (BUILTINS_LOCATION,
739                       FIELD_DECL, NULL_TREE,
740                       build_pointer_type (gcov_merge_fn_type));
741   TREE_CHAIN (field) = fields;
742   fields = field;
743
744   finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
745
746   return type;
747 }
748
749 /* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
750    the counter being processed and TYPE is the gcov_ctr_info
751    RECORD_TYPE.  */
752
753 static tree
754 build_ctr_info_value (unsigned int counter, tree type)
755 {
756   tree value = NULL_TREE;
757   tree fields = TYPE_FIELDS (type);
758   tree fn;
759
760   /* counters */
761   value = tree_cons (fields,
762                      build_int_cstu (get_gcov_unsigned_t (),
763                                      prg_n_ctrs[counter]),
764                      value);
765   fields = TREE_CHAIN (fields);
766
767   if (prg_n_ctrs[counter])
768     {
769       tree array_type;
770
771       array_type = build_int_cstu (get_gcov_unsigned_t (),
772                                    prg_n_ctrs[counter] - 1);
773       array_type = build_index_type (array_type);
774       array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
775                                      array_type);
776
777       TREE_TYPE (tree_ctr_tables[counter]) = array_type;
778       DECL_SIZE (tree_ctr_tables[counter]) = TYPE_SIZE (array_type);
779       DECL_SIZE_UNIT (tree_ctr_tables[counter]) = TYPE_SIZE_UNIT (array_type);
780       varpool_finalize_decl (tree_ctr_tables[counter]);
781
782       value = tree_cons (fields,
783                          build1 (ADDR_EXPR, TREE_TYPE (fields),
784                                             tree_ctr_tables[counter]),
785                          value);
786     }
787   else
788     value = tree_cons (fields, null_pointer_node, value);
789   fields = TREE_CHAIN (fields);
790
791   fn = build_decl (BUILTINS_LOCATION,
792                    FUNCTION_DECL,
793                    get_identifier (ctr_merge_functions[counter]),
794                    TREE_TYPE (TREE_TYPE (fields)));
795   DECL_EXTERNAL (fn) = 1;
796   TREE_PUBLIC (fn) = 1;
797   DECL_ARTIFICIAL (fn) = 1;
798   TREE_NOTHROW (fn) = 1;
799   DECL_ASSEMBLER_NAME (fn);  /* Initialize assembler name so we can stream out. */
800   value = tree_cons (fields,
801                      build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
802                      value);
803
804   /* FIXME: use build_constructor directly.  */
805   value = build_constructor_from_list (type, nreverse (value));
806
807   return value;
808 }
809
810 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
811    CONSTRUCTOR.  */
812
813 static tree
814 build_gcov_info (void)
815 {
816   unsigned n_ctr_types, ix;
817   tree type, const_type;
818   tree fn_info_type, fn_info_value = NULL_TREE;
819   tree fn_info_ptr_type;
820   tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
821   tree field, fields = NULL_TREE;
822   tree value = NULL_TREE;
823   tree filename_string;
824   int da_file_name_len;
825   unsigned n_fns;
826   const struct function_list *fn;
827   tree string_type;
828
829   /* Count the number of active counters.  */
830   for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
831     if (prg_ctr_mask & (1 << ix))
832       n_ctr_types++;
833
834   type = lang_hooks.types.make_type (RECORD_TYPE);
835   const_type = build_qualified_type (type, TYPE_QUAL_CONST);
836
837   /* Version ident */
838   field = build_decl (BUILTINS_LOCATION,
839                       FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
840   TREE_CHAIN (field) = fields;
841   fields = field;
842   value = tree_cons (field, build_int_cstu (TREE_TYPE (field), GCOV_VERSION),
843                      value);
844
845   /* next -- NULL */
846   field = build_decl (BUILTINS_LOCATION,
847                       FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
848   TREE_CHAIN (field) = fields;
849   fields = field;
850   value = tree_cons (field, null_pointer_node, value);
851
852   /* stamp */
853   field = build_decl (BUILTINS_LOCATION,
854                       FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
855   TREE_CHAIN (field) = fields;
856   fields = field;
857   value = tree_cons (field, build_int_cstu (TREE_TYPE (field), local_tick),
858                      value);
859
860   /* Filename */
861   string_type = build_pointer_type (build_qualified_type (char_type_node,
862                                                     TYPE_QUAL_CONST));
863   field = build_decl (BUILTINS_LOCATION,
864                       FIELD_DECL, NULL_TREE, string_type);
865   TREE_CHAIN (field) = fields;
866   fields = field;
867   da_file_name_len = strlen (da_file_name);
868   filename_string = build_string (da_file_name_len + 1, da_file_name);
869   TREE_TYPE (filename_string) = build_array_type
870     (char_type_node, build_index_type
871      (build_int_cst (NULL_TREE, da_file_name_len)));
872   value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
873                      value);
874
875   /* Build the fn_info type and initializer.  */
876   fn_info_type = build_fn_info_type (n_ctr_types);
877   fn_info_ptr_type = build_pointer_type (build_qualified_type
878                                          (fn_info_type, TYPE_QUAL_CONST));
879   for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
880     fn_info_value = tree_cons (NULL_TREE,
881                                build_fn_info_value (fn, fn_info_type),
882                                fn_info_value);
883   if (n_fns)
884     {
885       tree array_type;
886
887       array_type = build_index_type (build_int_cst (NULL_TREE, n_fns - 1));
888       array_type = build_array_type (fn_info_type, array_type);
889
890       /* FIXME: use build_constructor directly.  */
891       fn_info_value = build_constructor_from_list (array_type,
892                                                    nreverse (fn_info_value));
893       fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
894     }
895   else
896     fn_info_value = null_pointer_node;
897
898   /* number of functions */
899   field = build_decl (BUILTINS_LOCATION,
900                       FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
901   TREE_CHAIN (field) = fields;
902   fields = field;
903   value = tree_cons (field,
904                      build_int_cstu (get_gcov_unsigned_t (), n_fns),
905                      value);
906
907   /* fn_info table */
908   field = build_decl (BUILTINS_LOCATION,
909                       FIELD_DECL, NULL_TREE, fn_info_ptr_type);
910   TREE_CHAIN (field) = fields;
911   fields = field;
912   value = tree_cons (field, fn_info_value, value);
913
914   /* counter_mask */
915   field = build_decl (BUILTINS_LOCATION,
916                       FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
917   TREE_CHAIN (field) = fields;
918   fields = field;
919   value = tree_cons (field,
920                      build_int_cstu (get_gcov_unsigned_t (), prg_ctr_mask),
921                      value);
922
923   /* counters */
924   ctr_info_type = build_ctr_info_type ();
925   ctr_info_ary_type = build_index_type (build_int_cst (NULL_TREE,
926                                                        n_ctr_types));
927   ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
928   for (ix = 0; ix != GCOV_COUNTERS; ix++)
929     if (prg_ctr_mask & (1 << ix))
930       ctr_info_value = tree_cons (NULL_TREE,
931                                   build_ctr_info_value (ix, ctr_info_type),
932                                   ctr_info_value);
933   /* FIXME: use build_constructor directly.  */
934   ctr_info_value = build_constructor_from_list (ctr_info_ary_type,
935                                                 nreverse (ctr_info_value));
936
937   field = build_decl (BUILTINS_LOCATION,
938                       FIELD_DECL, NULL_TREE, ctr_info_ary_type);
939   TREE_CHAIN (field) = fields;
940   fields = field;
941   value = tree_cons (field, ctr_info_value, value);
942
943   finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
944
945   /* FIXME: use build_constructor directly.  */
946   value = build_constructor_from_list (type, nreverse (value));
947
948   return value;
949 }
950
951 /* Write out the structure which libgcov uses to locate all the
952    counters.  The structures used here must match those defined in
953    gcov-io.h.  Write out the constructor to call __gcov_init.  */
954
955 static void
956 create_coverage (void)
957 {
958   tree gcov_info, gcov_init, body, t;
959   char name_buf[32];
960
961   no_coverage = 1; /* Disable any further coverage.  */
962
963   if (!prg_ctr_mask)
964     return;
965
966   t = build_gcov_info ();
967
968   gcov_info = build_decl (BUILTINS_LOCATION,
969                           VAR_DECL, NULL_TREE, TREE_TYPE (t));
970   TREE_STATIC (gcov_info) = 1;
971   ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
972   DECL_NAME (gcov_info) = get_identifier (name_buf);
973   DECL_INITIAL (gcov_info) = t;
974
975   /* Build structure.  */
976   varpool_finalize_decl (gcov_info);
977
978   /* Build a decl for __gcov_init.  */
979   t = build_pointer_type (TREE_TYPE (gcov_info));
980   t = build_function_type_list (void_type_node, t, NULL);
981   t = build_decl (BUILTINS_LOCATION,
982                   FUNCTION_DECL, get_identifier ("__gcov_init"), t);
983   TREE_PUBLIC (t) = 1;
984   DECL_EXTERNAL (t) = 1;
985   DECL_ASSEMBLER_NAME (t);  /* Initialize assembler name so we can stream out. */
986   gcov_init = t;
987
988   /* Generate a call to __gcov_init(&gcov_info).  */
989   body = NULL;
990   t = build_fold_addr_expr (gcov_info);
991   t = build_call_expr (gcov_init, 1, t);
992   append_to_statement_list (t, &body);
993
994   /* Generate a constructor to run it.  */
995   cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
996 }
997 \f
998 /* Perform file-level initialization. Read in data file, generate name
999    of graph file.  */
1000
1001 void
1002 coverage_init (const char *filename)
1003 {
1004   int len = strlen (filename);
1005   /* + 1 for extra '/', in case prefix doesn't end with /.  */
1006   int prefix_len;
1007
1008   if (profile_data_prefix == 0 && filename[0] != '/')
1009     profile_data_prefix = getpwd ();
1010
1011   prefix_len = (profile_data_prefix) ? strlen (profile_data_prefix) + 1 : 0;
1012
1013   /* Name of da file.  */
1014   da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX)
1015                           + prefix_len + 1);
1016
1017   if (profile_data_prefix)
1018     {
1019       strcpy (da_file_name, profile_data_prefix);
1020       da_file_name[prefix_len - 1] = '/';
1021       da_file_name[prefix_len] = 0;
1022     }
1023   else
1024     da_file_name[0] = 0;
1025   strcat (da_file_name, filename);
1026   strcat (da_file_name, GCOV_DATA_SUFFIX);
1027
1028   /* Name of bbg file.  */
1029   bbg_file_name = XNEWVEC (char, len + strlen (GCOV_NOTE_SUFFIX) + 1);
1030   strcpy (bbg_file_name, filename);
1031   strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
1032
1033   if (flag_profile_use)
1034     read_counts_file ();
1035 }
1036
1037 /* Performs file-level cleanup.  Close graph file, generate coverage
1038    variables and constructor.  */
1039
1040 void
1041 coverage_finish (void)
1042 {
1043   create_coverage ();
1044   if (bbg_file_opened)
1045     {
1046       int error = gcov_close ();
1047
1048       if (error)
1049         unlink (bbg_file_name);
1050       if (!local_tick)
1051         /* Only remove the da file, if we cannot stamp it. If we can
1052            stamp it, libgcov will DTRT.  */
1053         unlink (da_file_name);
1054     }
1055 }
1056
1057 #include "gt-coverage.h"