OSDN Git Service

gcc/
[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 \f
446 /* Generate a checksum for a string.  CHKSUM is the current
447    checksum.  */
448
449 static unsigned
450 coverage_checksum_string (unsigned chksum, const char *string)
451 {
452   int i;
453   char *dup = NULL;
454
455   /* Look for everything that looks if it were produced by
456      get_file_function_name and zero out the second part
457      that may result from flag_random_seed.  This is not critical
458      as the checksums are used only for sanity checking.  */
459   for (i = 0; string[i]; i++)
460     {
461       int offset = 0;
462       if (!strncmp (string + i, "_GLOBAL__N_", 11))
463       offset = 11;
464       if (!strncmp (string + i, "_GLOBAL__", 9))
465       offset = 9;
466
467       /* C++ namespaces do have scheme:
468          _GLOBAL__N_<filename>_<wrongmagicnumber>_<magicnumber>functionname
469        since filename might contain extra underscores there seems
470        to be no better chance then walk all possible offsets looking
471        for magicnuber.  */
472       if (offset)
473         {
474           for (i = i + offset; string[i]; i++)
475             if (string[i]=='_')
476               {
477                 int y;
478
479                 for (y = 1; y < 9; y++)
480                   if (!(string[i + y] >= '0' && string[i + y] <= '9')
481                       && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
482                     break;
483                 if (y != 9 || string[i + 9] != '_')
484                   continue;
485                 for (y = 10; y < 18; y++)
486                   if (!(string[i + y] >= '0' && string[i + y] <= '9')
487                       && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
488                     break;
489                 if (y != 18)
490                   continue;
491                 if (!dup)
492                   string = dup = xstrdup (string);
493                 for (y = 10; y < 18; y++)
494                   dup[i + y] = '0';
495               }
496           break;
497         }
498     }
499
500   chksum = crc32_string (chksum, string);
501   if (dup)
502     free (dup);
503
504   return chksum;
505 }
506
507 /* Compute checksum for the current function.  We generate a CRC32.  */
508
509 static unsigned
510 compute_checksum (void)
511 {
512   expanded_location xloc
513     = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
514   unsigned chksum = xloc.line;
515
516   chksum = coverage_checksum_string (chksum, xloc.file);
517   chksum = coverage_checksum_string
518     (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
519
520   return chksum;
521 }
522 \f
523 /* Begin output to the graph file for the current function.
524    Opens the output file, if not already done. Writes the
525    function header, if not already done. Returns nonzero if data
526    should be output.  */
527
528 int
529 coverage_begin_output (void)
530 {
531   if (no_coverage)
532     return 0;
533
534   if (!bbg_function_announced)
535     {
536       expanded_location xloc
537         = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
538       unsigned long offset;
539
540       if (!bbg_file_opened)
541         {
542           if (!gcov_open (bbg_file_name, -1))
543             error ("cannot open %s", bbg_file_name);
544           else
545             {
546               gcov_write_unsigned (GCOV_NOTE_MAGIC);
547               gcov_write_unsigned (GCOV_VERSION);
548               gcov_write_unsigned (local_tick);
549             }
550           bbg_file_opened = 1;
551         }
552
553       /* Announce function */
554       offset = gcov_write_tag (GCOV_TAG_FUNCTION);
555       gcov_write_unsigned (current_function_funcdef_no + 1);
556       gcov_write_unsigned (compute_checksum ());
557       gcov_write_string (IDENTIFIER_POINTER
558                          (DECL_ASSEMBLER_NAME (current_function_decl)));
559       gcov_write_string (xloc.file);
560       gcov_write_unsigned (xloc.line);
561       gcov_write_length (offset);
562
563       bbg_function_announced = 1;
564     }
565   return !gcov_is_error ();
566 }
567
568 /* Finish coverage data for the current function. Verify no output
569    error has occurred.  Save function coverage counts.  */
570
571 void
572 coverage_end_function (void)
573 {
574   unsigned i;
575
576   if (bbg_file_opened > 1 && gcov_is_error ())
577     {
578       warning (0, "error writing %qs", bbg_file_name);
579       bbg_file_opened = -1;
580     }
581
582   if (fn_ctr_mask)
583     {
584       struct function_list *item;
585
586       item = XNEW (struct function_list);
587
588       *functions_tail = item;
589       functions_tail = &item->next;
590
591       item->next = 0;
592       item->ident = current_function_funcdef_no + 1;
593       item->checksum = compute_checksum ();
594       for (i = 0; i != GCOV_COUNTERS; i++)
595         {
596           item->n_ctrs[i] = fn_n_ctrs[i];
597           prg_n_ctrs[i] += fn_n_ctrs[i];
598           fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
599         }
600       prg_ctr_mask |= fn_ctr_mask;
601       fn_ctr_mask = 0;
602     }
603   bbg_function_announced = 0;
604 }
605
606 /* Creates the gcov_fn_info RECORD_TYPE.  */
607
608 static tree
609 build_fn_info_type (unsigned int counters)
610 {
611   tree type = lang_hooks.types.make_type (RECORD_TYPE);
612   tree field, fields;
613   tree array_type;
614
615   /* ident */
616   fields = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
617
618   /* checksum */
619   field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
620   TREE_CHAIN (field) = fields;
621   fields = field;
622
623   array_type = build_int_cst (NULL_TREE, counters - 1);
624   array_type = build_index_type (array_type);
625   array_type = build_array_type (get_gcov_unsigned_t (), array_type);
626
627   /* counters */
628   field = build_decl (FIELD_DECL, NULL_TREE, array_type);
629   TREE_CHAIN (field) = fields;
630   fields = field;
631
632   finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
633
634   return type;
635 }
636
637 /* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
638    the function being processed and TYPE is the gcov_fn_info
639    RECORD_TYPE.  */
640
641 static tree
642 build_fn_info_value (const struct function_list *function, tree type)
643 {
644   tree value = NULL_TREE;
645   tree fields = TYPE_FIELDS (type);
646   unsigned ix;
647   tree array_value = NULL_TREE;
648
649   /* ident */
650   value = tree_cons (fields, build_int_cstu (get_gcov_unsigned_t (),
651                                              function->ident), value);
652   fields = TREE_CHAIN (fields);
653
654   /* checksum */
655   value = tree_cons (fields, build_int_cstu (get_gcov_unsigned_t (),
656                                              function->checksum), value);
657   fields = TREE_CHAIN (fields);
658
659   /* counters */
660   for (ix = 0; ix != GCOV_COUNTERS; ix++)
661     if (prg_ctr_mask & (1 << ix))
662       {
663         tree counters = build_int_cstu (get_gcov_unsigned_t (),
664                                         function->n_ctrs[ix]);
665
666         array_value = tree_cons (NULL_TREE, counters, array_value);
667       }
668
669   /* FIXME: use build_constructor directly.  */
670   array_value = build_constructor_from_list (TREE_TYPE (fields),
671                                              nreverse (array_value));
672   value = tree_cons (fields, array_value, value);
673
674   /* FIXME: use build_constructor directly.  */
675   value = build_constructor_from_list (type, nreverse (value));
676
677   return value;
678 }
679
680 /* Creates the gcov_ctr_info RECORD_TYPE.  */
681
682 static tree
683 build_ctr_info_type (void)
684 {
685   tree type = lang_hooks.types.make_type (RECORD_TYPE);
686   tree field, fields = NULL_TREE;
687   tree gcov_ptr_type = build_pointer_type (get_gcov_type ());
688   tree gcov_merge_fn_type;
689
690   /* counters */
691   field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
692   TREE_CHAIN (field) = fields;
693   fields = field;
694
695   /* values */
696   field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
697   TREE_CHAIN (field) = fields;
698   fields = field;
699
700   /* merge */
701   gcov_merge_fn_type =
702     build_function_type_list (void_type_node,
703                               gcov_ptr_type, get_gcov_unsigned_t (),
704                               NULL_TREE);
705   field = build_decl (FIELD_DECL, NULL_TREE,
706                       build_pointer_type (gcov_merge_fn_type));
707   TREE_CHAIN (field) = fields;
708   fields = field;
709
710   finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
711
712   return type;
713 }
714
715 /* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
716    the counter being processed and TYPE is the gcov_ctr_info
717    RECORD_TYPE.  */
718
719 static tree
720 build_ctr_info_value (unsigned int counter, tree type)
721 {
722   tree value = NULL_TREE;
723   tree fields = TYPE_FIELDS (type);
724   tree fn;
725
726   /* counters */
727   value = tree_cons (fields,
728                      build_int_cstu (get_gcov_unsigned_t (),
729                                      prg_n_ctrs[counter]),
730                      value);
731   fields = TREE_CHAIN (fields);
732
733   if (prg_n_ctrs[counter])
734     {
735       tree array_type;
736
737       array_type = build_int_cstu (get_gcov_unsigned_t (),
738                                    prg_n_ctrs[counter] - 1);
739       array_type = build_index_type (array_type);
740       array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
741                                      array_type);
742
743       TREE_TYPE (tree_ctr_tables[counter]) = array_type;
744       DECL_SIZE (tree_ctr_tables[counter]) = TYPE_SIZE (array_type);
745       DECL_SIZE_UNIT (tree_ctr_tables[counter]) = TYPE_SIZE_UNIT (array_type);
746       assemble_variable (tree_ctr_tables[counter], 0, 0, 0);
747
748       value = tree_cons (fields,
749                          build1 (ADDR_EXPR, TREE_TYPE (fields), 
750                                             tree_ctr_tables[counter]),
751                          value);
752     }
753   else
754     value = tree_cons (fields, null_pointer_node, value);
755   fields = TREE_CHAIN (fields);
756
757   fn = build_decl (FUNCTION_DECL,
758                    get_identifier (ctr_merge_functions[counter]),
759                    TREE_TYPE (TREE_TYPE (fields)));
760   DECL_EXTERNAL (fn) = 1;
761   TREE_PUBLIC (fn) = 1;
762   DECL_ARTIFICIAL (fn) = 1;
763   TREE_NOTHROW (fn) = 1;
764   value = tree_cons (fields,
765                      build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
766                      value);
767
768   /* FIXME: use build_constructor directly.  */
769   value = build_constructor_from_list (type, nreverse (value));
770
771   return value;
772 }
773
774 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
775    CONSTRUCTOR.  */
776
777 static tree
778 build_gcov_info (void)
779 {
780   unsigned n_ctr_types, ix;
781   tree type, const_type;
782   tree fn_info_type, fn_info_value = NULL_TREE;
783   tree fn_info_ptr_type;
784   tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
785   tree field, fields = NULL_TREE;
786   tree value = NULL_TREE;
787   tree filename_string;
788   char *filename;
789   int filename_len;
790   unsigned n_fns;
791   const struct function_list *fn;
792   tree string_type;
793
794   /* Count the number of active counters.  */
795   for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
796     if (prg_ctr_mask & (1 << ix))
797       n_ctr_types++;
798
799   type = lang_hooks.types.make_type (RECORD_TYPE);
800   const_type = build_qualified_type (type, TYPE_QUAL_CONST);
801
802   /* Version ident */
803   field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
804   TREE_CHAIN (field) = fields;
805   fields = field;
806   value = tree_cons (field, build_int_cstu (TREE_TYPE (field), GCOV_VERSION),
807                      value);
808
809   /* next -- NULL */
810   field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
811   TREE_CHAIN (field) = fields;
812   fields = field;
813   value = tree_cons (field, null_pointer_node, value);
814
815   /* stamp */
816   field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
817   TREE_CHAIN (field) = fields;
818   fields = field;
819   value = tree_cons (field, build_int_cstu (TREE_TYPE (field), local_tick),
820                      value);
821
822   /* Filename */
823   string_type = build_pointer_type (build_qualified_type (char_type_node,
824                                                     TYPE_QUAL_CONST));
825   field = build_decl (FIELD_DECL, NULL_TREE, string_type);
826   TREE_CHAIN (field) = fields;
827   fields = field;
828   filename = getpwd ();
829   filename = (filename && da_file_name[0] != '/'
830               ? concat (filename, "/", da_file_name, NULL)
831               : da_file_name);
832   filename_len = strlen (filename);
833   filename_string = build_string (filename_len + 1, filename);
834   if (filename != da_file_name)
835     free (filename);
836   TREE_TYPE (filename_string) = build_array_type
837     (char_type_node, build_index_type
838      (build_int_cst (NULL_TREE, filename_len)));
839   value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
840                      value);
841
842   /* Build the fn_info type and initializer.  */
843   fn_info_type = build_fn_info_type (n_ctr_types);
844   fn_info_ptr_type = build_pointer_type (build_qualified_type
845                                          (fn_info_type, TYPE_QUAL_CONST));
846   for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
847     fn_info_value = tree_cons (NULL_TREE,
848                                build_fn_info_value (fn, fn_info_type),
849                                fn_info_value);
850   if (n_fns)
851     {
852       tree array_type;
853
854       array_type = build_index_type (build_int_cst (NULL_TREE, n_fns - 1));
855       array_type = build_array_type (fn_info_type, array_type);
856
857       /* FIXME: use build_constructor directly.  */
858       fn_info_value = build_constructor_from_list (array_type,
859                                                    nreverse (fn_info_value));
860       fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
861     }
862   else
863     fn_info_value = null_pointer_node;
864
865   /* number of functions */
866   field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
867   TREE_CHAIN (field) = fields;
868   fields = field;
869   value = tree_cons (field,
870                      build_int_cstu (get_gcov_unsigned_t (), n_fns),
871                      value);
872
873   /* fn_info table */
874   field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type);
875   TREE_CHAIN (field) = fields;
876   fields = field;
877   value = tree_cons (field, fn_info_value, value);
878
879   /* counter_mask */
880   field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
881   TREE_CHAIN (field) = fields;
882   fields = field;
883   value = tree_cons (field,
884                      build_int_cstu (get_gcov_unsigned_t (), prg_ctr_mask),
885                      value);
886
887   /* counters */
888   ctr_info_type = build_ctr_info_type ();
889   ctr_info_ary_type = build_index_type (build_int_cst (NULL_TREE,
890                                                        n_ctr_types));
891   ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
892   for (ix = 0; ix != GCOV_COUNTERS; ix++)
893     if (prg_ctr_mask & (1 << ix))
894       ctr_info_value = tree_cons (NULL_TREE,
895                                   build_ctr_info_value (ix, ctr_info_type),
896                                   ctr_info_value);
897   /* FIXME: use build_constructor directly.  */
898   ctr_info_value = build_constructor_from_list (ctr_info_ary_type,
899                                                 nreverse (ctr_info_value));
900
901   field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
902   TREE_CHAIN (field) = fields;
903   fields = field;
904   value = tree_cons (field, ctr_info_value, value);
905
906   finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
907
908   /* FIXME: use build_constructor directly.  */
909   value = build_constructor_from_list (type, nreverse (value));
910
911   return value;
912 }
913
914 /* Write out the structure which libgcov uses to locate all the
915    counters.  The structures used here must match those defined in
916    gcov-io.h.  Write out the constructor to call __gcov_init.  */
917
918 static void
919 create_coverage (void)
920 {
921   tree gcov_info, gcov_init, body, t;
922   char name_buf[32];
923
924   no_coverage = 1; /* Disable any further coverage.  */
925
926   if (!prg_ctr_mask)
927     return;
928
929   t = build_gcov_info ();
930
931   gcov_info = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (t));
932   TREE_STATIC (gcov_info) = 1;
933   ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
934   DECL_NAME (gcov_info) = get_identifier (name_buf);
935   DECL_INITIAL (gcov_info) = t;
936
937   /* Build structure.  */
938   assemble_variable (gcov_info, 0, 0, 0);
939
940   /* Build a decl for __gcov_init.  */
941   t = build_pointer_type (TREE_TYPE (gcov_info));
942   t = build_function_type_list (void_type_node, t, NULL);
943   t = build_decl (FUNCTION_DECL, get_identifier ("__gcov_init"), t);
944   TREE_PUBLIC (t) = 1;
945   DECL_EXTERNAL (t) = 1;
946   gcov_init = t;
947
948   /* Generate a call to __gcov_init(&gcov_info).  */
949   body = NULL;
950   t = build_fold_addr_expr (gcov_info);
951   t = build_call_expr (gcov_init, 1, t);
952   append_to_statement_list (t, &body);
953
954   /* Generate a constructor to run it.  */
955   cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
956 }
957 \f
958 /* Perform file-level initialization. Read in data file, generate name
959    of graph file.  */
960
961 void
962 coverage_init (const char *filename)
963 {
964   int len = strlen (filename);
965
966   /* Name of da file.  */
967   da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX) + 1);
968   strcpy (da_file_name, filename);
969   strcat (da_file_name, GCOV_DATA_SUFFIX);
970
971   /* Name of bbg file.  */
972   bbg_file_name = XNEWVEC (char, len + strlen (GCOV_NOTE_SUFFIX) + 1);
973   strcpy (bbg_file_name, filename);
974   strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
975
976   read_counts_file ();
977 }
978
979 /* Performs file-level cleanup.  Close graph file, generate coverage
980    variables and constructor.  */
981
982 void
983 coverage_finish (void)
984 {
985   create_coverage ();
986   if (bbg_file_opened)
987     {
988       int error = gcov_close ();
989
990       if (error)
991         unlink (bbg_file_name);
992       if (!local_tick)
993         /* Only remove the da file, if we cannot stamp it. If we can
994            stamp it, libgcov will DTRT.  */
995         unlink (da_file_name);
996     }
997 }
998
999 #include "gt-coverage.h"