OSDN Git Service

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