OSDN Git Service

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