OSDN Git Service

2004-07-04 Matthias Klose <doko@debian.org>
[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         break;
296     }
297
298   if (!gcov_is_eof ())
299     {
300       error (is_error < 0 ? "`%s' has overflowed" : "`%s' is corrupted",
301              da_file_name);
302       htab_delete (counts_hash);
303     }
304
305   gcov_close ();
306 }
307
308 /* Returns the counters for a particular tag.  */
309
310 gcov_type *
311 get_coverage_counts (unsigned counter, unsigned expected,
312                      const struct gcov_ctr_summary **summary)
313 {
314   counts_entry_t *entry, elt;
315   gcov_unsigned_t checksum = -1;
316
317   /* No hash table, no counts.  */
318   if (!counts_hash)
319     {
320       static int warned = 0;
321
322       if (!warned++)
323         inform ((flag_guess_branch_prob
324                  ? "file %s not found, execution counts estimated"
325                  : "file %s not found, execution counts assumed to be zero"),
326                 da_file_name);
327       return NULL;
328     }
329
330   elt.ident = current_function_funcdef_no + 1;
331   elt.ctr = counter;
332   entry = htab_find (counts_hash, &elt);
333   if (!entry)
334     {
335       warning ("no coverage for function '%s' found.", IDENTIFIER_POINTER
336                (DECL_ASSEMBLER_NAME (current_function_decl)));
337       return 0;
338     }
339
340   checksum = compute_checksum ();
341   if (entry->checksum != checksum)
342     {
343       error ("coverage mismatch for function '%s' while reading counter '%s'.",
344              IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
345              ctr_names[counter]);
346       error ("checksum is %x instead of %x", entry->checksum, checksum);
347       return 0;
348     }
349   else if (entry->summary.num != expected)
350     {
351       error ("coverage mismatch for function '%s' while reading counter '%s'.",
352              IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
353              ctr_names[counter]);
354       error ("number of counters is %d instead of %d", entry->summary.num, expected);
355       return 0;
356     }
357
358   if (summary)
359     *summary = &entry->summary;
360
361   return entry->counts;
362 }
363
364 /* Allocate NUM counters of type COUNTER. Returns nonzero if the
365    allocation succeeded.  */
366
367 int
368 coverage_counter_alloc (unsigned counter, unsigned num)
369 {
370   if (no_coverage)
371     return 0;
372
373   if (!num)
374     return 1;
375
376   if (!tree_ctr_tables[counter])
377     {
378       /* Generate and save a copy of this so it can be shared.  */
379       /* We don't know the size yet; make it big enough that nobody
380          will make any clever transformation on it.  */
381       char buf[20];
382       tree domain_tree
383         = build_index_type (build_int_2 (1000, 0)); /* replaced later */
384       tree gcov_type_array_type
385         = build_array_type (GCOV_TYPE_NODE, domain_tree);
386       tree_ctr_tables[counter]
387         = build_decl (VAR_DECL, NULL_TREE, gcov_type_array_type);
388       TREE_STATIC (tree_ctr_tables[counter]) = 1;
389       ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
390       DECL_NAME (tree_ctr_tables[counter]) = get_identifier (buf);
391       DECL_ALIGN (tree_ctr_tables[counter]) = TYPE_ALIGN (GCOV_TYPE_NODE);
392     }
393   fn_b_ctrs[counter] = fn_n_ctrs[counter];
394   fn_n_ctrs[counter] += num;
395   fn_ctr_mask |= 1 << counter;
396   return 1;
397 }
398
399 /* Generate a MEM rtl to access COUNTER NO.  */
400
401 rtx
402 rtl_coverage_counter_ref (unsigned counter, unsigned no)
403 {
404   unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
405   enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
406   rtx ref;
407
408   if (no >= fn_n_ctrs[counter] - fn_b_ctrs[counter])
409     abort ();
410   no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
411   if (!ctr_labels[counter])
412       {
413         ctr_labels[counter] = gen_rtx_SYMBOL_REF (Pmode,
414                                ggc_strdup (IDENTIFIER_POINTER (DECL_NAME
415                                (tree_ctr_tables[counter]))));
416         SYMBOL_REF_FLAGS (ctr_labels[counter]) = SYMBOL_FLAG_LOCAL;
417       }
418   ref = plus_constant (ctr_labels[counter], gcov_size / BITS_PER_UNIT * no);
419   ref = gen_rtx_MEM (mode, ref);
420   set_mem_alias_set (ref, new_alias_set ());
421   MEM_NOTRAP_P (ref) = 1;
422
423   return ref;
424 }
425
426 /* Generate a tree to access COUNTER NO.  */
427
428 tree
429 tree_coverage_counter_ref (unsigned counter, unsigned no)
430 {
431   tree domain_type = TYPE_DOMAIN (TREE_TYPE (tree_ctr_tables[counter]));
432
433   if (no >= fn_n_ctrs[counter] - fn_b_ctrs[counter])
434     abort ();
435   no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
436
437   /* "no" here is an array index, scaled to bytes later.  */
438   return build (ARRAY_REF, GCOV_TYPE_NODE, tree_ctr_tables[counter],
439                 fold_convert (domain_type, build_int_2 (no, 0)),
440                 TYPE_MIN_VALUE (domain_type),
441                 size_binop (EXACT_DIV_EXPR, TYPE_SIZE_UNIT (GCOV_TYPE_NODE),
442                             size_int (TYPE_ALIGN (GCOV_TYPE_NODE))));
443 }
444 \f
445 /* Generate a checksum for a string.  CHKSUM is the current
446    checksum.  */
447
448 static unsigned
449 coverage_checksum_string (unsigned chksum, const char *string)
450 {
451   int i;
452   char *dup = NULL;
453
454   /* Look for everything that looks if it were produced by
455      get_file_function_name_long and zero out the second part
456      that may result from flag_random_seed.  This is not critical
457      as the checksums are used only for sanity checking.  */
458   for (i = 0; string[i]; i++)
459     {
460       if (!strncmp (string + i, "_GLOBAL__", 9))
461         for (i = i + 9; string[i]; i++)
462           if (string[i]=='_')
463             {
464               int y;
465               unsigned seed;
466
467               for (y = 1; y < 9; y++)
468                 if (!(string[i + y] >= '0' && string[i + y] <= '9')
469                     && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
470                   break;
471               if (y != 9 || string[i + 9] != '_')
472                 continue;
473               for (y = 10; y < 18; y++)
474                 if (!(string[i + y] >= '0' && string[i + y] <= '9')
475                     && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
476                   break;
477               if (y != 18)
478                 continue;
479               if (!sscanf (string + i + 10, "%X", &seed))
480                 abort ();
481               if (seed != crc32_string (0, flag_random_seed))
482                 continue;
483               string = dup = xstrdup (string);
484               for (y = 10; y < 18; y++)
485                 dup[i + y] = '0';
486               break;
487             }
488       break;
489     }
490
491   chksum = crc32_string (chksum, string);
492   if (dup)
493     free (dup);
494
495   return chksum;
496 }
497
498 /* Compute checksum for the current function.  We generate a CRC32.  */
499
500 static unsigned
501 compute_checksum (void)
502 {
503   expanded_location xloc
504     = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
505   unsigned chksum = xloc.line;
506
507   chksum = coverage_checksum_string (chksum, xloc.file);
508   chksum = coverage_checksum_string
509     (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
510
511   return chksum;
512 }
513 \f
514 /* Begin output to the graph file for the current function.
515    Opens the output file, if not already done. Writes the
516    function header, if not already done. Returns nonzero if data
517    should be output.  */
518
519 int
520 coverage_begin_output (void)
521 {
522   if (no_coverage)
523     return 0;
524
525   if (!bbg_function_announced)
526     {
527       expanded_location xloc
528         = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
529       unsigned long offset;
530
531       if (!bbg_file_opened)
532         {
533           if (!gcov_open (bbg_file_name, -1))
534             error ("cannot open %s", bbg_file_name);
535           else
536             {
537               gcov_write_unsigned (GCOV_NOTE_MAGIC);
538               gcov_write_unsigned (GCOV_VERSION);
539               gcov_write_unsigned (local_tick);
540             }
541           bbg_file_opened = 1;
542         }
543
544       /* Announce function */
545       offset = gcov_write_tag (GCOV_TAG_FUNCTION);
546       gcov_write_unsigned (current_function_funcdef_no + 1);
547       gcov_write_unsigned (compute_checksum ());
548       gcov_write_string (IDENTIFIER_POINTER
549                          (DECL_ASSEMBLER_NAME (current_function_decl)));
550       gcov_write_string (xloc.file);
551       gcov_write_unsigned (xloc.line);
552       gcov_write_length (offset);
553
554       bbg_function_announced = 1;
555     }
556   return !gcov_is_error ();
557 }
558
559 /* Finish coverage data for the current function. Verify no output
560    error has occurred.  Save function coverage counts.  */
561
562 void
563 coverage_end_function (void)
564 {
565   unsigned i;
566
567   if (bbg_file_opened > 1 && gcov_is_error ())
568     {
569       warning ("error writing `%s'", bbg_file_name);
570       bbg_file_opened = -1;
571     }
572
573   if (fn_ctr_mask)
574     {
575       struct function_list *item;
576
577       item = xmalloc (sizeof (struct function_list));
578
579       *functions_tail = item;
580       functions_tail = &item->next;
581
582       item->next = 0;
583       item->ident = current_function_funcdef_no + 1;
584       item->checksum = compute_checksum ();
585       for (i = 0; i != GCOV_COUNTERS; i++)
586         {
587           item->n_ctrs[i] = fn_n_ctrs[i];
588           prg_n_ctrs[i] += fn_n_ctrs[i];
589           fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
590         }
591       prg_ctr_mask |= fn_ctr_mask;
592       fn_ctr_mask = 0;
593     }
594   bbg_function_announced = 0;
595 }
596
597 /* Creates the gcov_fn_info RECORD_TYPE.  */
598
599 static tree
600 build_fn_info_type (unsigned int counters)
601 {
602   tree type = lang_hooks.types.make_type (RECORD_TYPE);
603   tree field, fields;
604   tree array_type;
605
606   /* ident */
607   fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
608
609   /* checksum */
610   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
611   TREE_CHAIN (field) = fields;
612   fields = field;
613
614   array_type = build_index_type (build_int_2 (counters - 1, 0));
615   array_type = build_array_type (unsigned_type_node, array_type);
616
617   /* counters */
618   field = build_decl (FIELD_DECL, NULL_TREE, array_type);
619   TREE_CHAIN (field) = fields;
620   fields = field;
621
622   finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
623
624   return type;
625 }
626
627 /* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
628    the function being processed and TYPE is the gcov_fn_info
629    RECORD_TYPE.  */
630
631 static tree
632 build_fn_info_value (const struct function_list *function, tree type)
633 {
634   tree value = NULL_TREE;
635   tree fields = TYPE_FIELDS (type);
636   unsigned ix;
637   tree array_value = NULL_TREE;
638
639   /* ident */
640   value = tree_cons (fields,
641                      convert (unsigned_intSI_type_node,
642                               build_int_2 (function->ident, 0)),
643                      value);
644   fields = TREE_CHAIN (fields);
645
646   /* checksum */
647   value = tree_cons (fields,
648                      convert (unsigned_intSI_type_node,
649                               build_int_2 (function->checksum, 0)),
650                      value);
651   fields = TREE_CHAIN (fields);
652
653   /* counters */
654   for (ix = 0; ix != GCOV_COUNTERS; ix++)
655     if (prg_ctr_mask & (1 << ix))
656       {
657         tree counters = convert (unsigned_type_node,
658                                  build_int_2 (function->n_ctrs[ix], 0));
659
660         array_value = tree_cons (NULL_TREE, counters, array_value);
661       }
662
663   array_value = build_constructor (TREE_TYPE (fields), nreverse (array_value));
664   value = tree_cons (fields, array_value, value);
665
666   value = build_constructor (type, nreverse (value));
667
668   return value;
669 }
670
671 /* Creates the gcov_ctr_info RECORD_TYPE.  */
672
673 static tree
674 build_ctr_info_type (void)
675 {
676   tree type = lang_hooks.types.make_type (RECORD_TYPE);
677   tree field, fields = NULL_TREE;
678   tree gcov_ptr_type = build_pointer_type (GCOV_TYPE_NODE);
679   tree gcov_merge_fn_type;
680
681   /* counters */
682   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
683   TREE_CHAIN (field) = fields;
684   fields = field;
685
686   /* values */
687   field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
688   TREE_CHAIN (field) = fields;
689   fields = field;
690
691   /* merge */
692   gcov_merge_fn_type =
693     build_function_type_list (void_type_node,
694                               gcov_ptr_type, unsigned_type_node,
695                               NULL_TREE);
696   field = build_decl (FIELD_DECL, NULL_TREE,
697                       build_pointer_type (gcov_merge_fn_type));
698   TREE_CHAIN (field) = fields;
699   fields = field;
700
701   finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
702
703   return type;
704 }
705
706 /* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
707    the counter being processed and TYPE is the gcov_ctr_info
708    RECORD_TYPE.  */
709
710 static tree
711 build_ctr_info_value (unsigned int counter, tree type)
712 {
713   tree value = NULL_TREE;
714   tree fields = TYPE_FIELDS (type);
715   tree fn;
716
717   /* counters */
718   value = tree_cons (fields,
719                      convert (unsigned_intSI_type_node,
720                               build_int_2 (prg_n_ctrs[counter], 0)),
721                      value);
722   fields = TREE_CHAIN (fields);
723
724   if (prg_n_ctrs[counter])
725     {
726       tree array_type;
727
728       array_type = build_index_type (build_int_2 (prg_n_ctrs[counter] - 1, 0));
729       array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
730                                      array_type);
731
732       TREE_TYPE (tree_ctr_tables[counter]) = array_type;
733       DECL_SIZE (tree_ctr_tables[counter]) = TYPE_SIZE (array_type);
734       DECL_SIZE_UNIT (tree_ctr_tables[counter]) = TYPE_SIZE_UNIT (array_type);
735       assemble_variable (tree_ctr_tables[counter], 0, 0, 0);
736
737       value = tree_cons (fields,
738                          build1 (ADDR_EXPR, TREE_TYPE (fields), 
739                                             tree_ctr_tables[counter]),
740                          value);
741     }
742   else
743     value = tree_cons (fields, null_pointer_node, value);
744   fields = TREE_CHAIN (fields);
745
746   fn = build_decl (FUNCTION_DECL,
747                    get_identifier (ctr_merge_functions[counter]),
748                    TREE_TYPE (TREE_TYPE (fields)));
749   DECL_EXTERNAL (fn) = 1;
750   TREE_PUBLIC (fn) = 1;
751   DECL_ARTIFICIAL (fn) = 1;
752   TREE_NOTHROW (fn) = 1;
753   value = tree_cons (fields,
754                      build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
755                      value);
756
757   value = build_constructor (type, nreverse (value));
758
759   return value;
760 }
761
762 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
763    CONSTRUCTOR.  */
764
765 static tree
766 build_gcov_info (void)
767 {
768   unsigned n_ctr_types, ix;
769   tree type, const_type;
770   tree fn_info_type, fn_info_value = NULL_TREE;
771   tree fn_info_ptr_type;
772   tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
773   tree field, fields = NULL_TREE;
774   tree value = NULL_TREE;
775   tree filename_string;
776   char *filename;
777   int filename_len;
778   unsigned n_fns;
779   const struct function_list *fn;
780   tree string_type;
781
782   /* Count the number of active counters.  */
783   for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
784     if (prg_ctr_mask & (1 << ix))
785       n_ctr_types++;
786
787   type = lang_hooks.types.make_type (RECORD_TYPE);
788   const_type = build_qualified_type (type, TYPE_QUAL_CONST);
789
790   /* Version ident */
791   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
792   TREE_CHAIN (field) = fields;
793   fields = field;
794   value = tree_cons (field, convert (unsigned_intSI_type_node,
795                                      build_int_2 (GCOV_VERSION, 0)),
796                      value);
797
798   /* next -- NULL */
799   field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
800   TREE_CHAIN (field) = fields;
801   fields = field;
802   value = tree_cons (field, null_pointer_node, value);
803
804   /* stamp */
805   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
806   TREE_CHAIN (field) = fields;
807   fields = field;
808   value = tree_cons (field, convert (unsigned_intSI_type_node,
809                                      build_int_2 (local_tick, 0)),
810                      value);
811
812   /* Filename */
813   string_type = build_pointer_type (build_qualified_type (char_type_node,
814                                                     TYPE_QUAL_CONST));
815   field = build_decl (FIELD_DECL, NULL_TREE, string_type);
816   TREE_CHAIN (field) = fields;
817   fields = field;
818   filename = getpwd ();
819   filename = (filename && da_file_name[0] != '/'
820               ? concat (filename, "/", da_file_name, NULL)
821               : da_file_name);
822   filename_len = strlen (filename);
823   filename_string = build_string (filename_len + 1, filename);
824   if (filename != da_file_name)
825     free (filename);
826   TREE_TYPE (filename_string) =
827           build_array_type (char_type_node,
828                             build_index_type (build_int_2 (filename_len, 0)));
829   value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
830                      value);
831
832   /* Build the fn_info type and initializer.  */
833   fn_info_type = build_fn_info_type (n_ctr_types);
834   fn_info_ptr_type = build_pointer_type (build_qualified_type
835                                          (fn_info_type, TYPE_QUAL_CONST));
836   for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
837     fn_info_value = tree_cons (NULL_TREE,
838                                build_fn_info_value (fn, fn_info_type),
839                                fn_info_value);
840   if (n_fns)
841     {
842       tree array_type;
843
844       array_type = build_index_type (build_int_2 (n_fns - 1, 0));
845       array_type = build_array_type (fn_info_type, array_type);
846
847       fn_info_value = build_constructor (array_type, nreverse (fn_info_value));
848       fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
849     }
850   else
851     fn_info_value = null_pointer_node;
852
853   /* number of functions */
854   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
855   TREE_CHAIN (field) = fields;
856   fields = field;
857   value = tree_cons (field,
858                      convert (unsigned_type_node, build_int_2 (n_fns, 0)),
859                      value);
860
861   /* fn_info table */
862   field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type);
863   TREE_CHAIN (field) = fields;
864   fields = field;
865   value = tree_cons (field, fn_info_value, value);
866
867   /* counter_mask */
868   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
869   TREE_CHAIN (field) = fields;
870   fields = field;
871   value = tree_cons (field,
872                      convert (unsigned_type_node,
873                               build_int_2 (prg_ctr_mask, 0)),
874                      value);
875
876   /* counters */
877   ctr_info_type = build_ctr_info_type ();
878   ctr_info_ary_type = build_index_type (build_int_2 (n_ctr_types, 0));
879   ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
880   for (ix = 0; ix != GCOV_COUNTERS; ix++)
881     if (prg_ctr_mask & (1 << ix))
882       ctr_info_value = tree_cons (NULL_TREE,
883                                   build_ctr_info_value (ix, ctr_info_type),
884                                   ctr_info_value);
885   ctr_info_value = build_constructor (ctr_info_ary_type,
886                                       nreverse (ctr_info_value));
887
888   field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
889   TREE_CHAIN (field) = fields;
890   fields = field;
891   value = tree_cons (field, ctr_info_value, value);
892
893   finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
894
895   value = build_constructor (type, nreverse (value));
896
897   return value;
898 }
899
900 /* Write out the structure which libgcov uses to locate all the
901    counters.  The structures used here must match those defined in
902    gcov-io.h.  Write out the constructor to call __gcov_init.  */
903
904 static void
905 create_coverage (void)
906 {
907   tree gcov_info, gcov_init, body, t;
908   char name_buf[32];
909
910   no_coverage = 1; /* Disable any further coverage.  */
911
912   if (!prg_ctr_mask)
913     return;
914
915   t = build_gcov_info ();
916
917   gcov_info = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (t));
918   TREE_STATIC (gcov_info) = 1;
919   ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
920   DECL_NAME (gcov_info) = get_identifier (name_buf);
921   DECL_INITIAL (gcov_info) = t;
922
923   /* Build structure.  */
924   assemble_variable (gcov_info, 0, 0, 0);
925
926   /* Build a decl for __gcov_init.  */
927   t = build_pointer_type (TREE_TYPE (gcov_info));
928   t = build_function_type_list (void_type_node, t, NULL);
929   t = build_decl (FUNCTION_DECL, get_identifier ("__gcov_init"), t);
930   TREE_PUBLIC (t) = 1;
931   DECL_EXTERNAL (t) = 1;
932   gcov_init = t;
933
934   /* Generate a call to __gcov_init(&gcov_info).  */
935   body = NULL;
936   t = build_fold_addr_expr (gcov_info);
937   t = tree_cons (NULL, t, NULL);
938   t = build_function_call_expr (gcov_init, t);
939   append_to_statement_list (t, &body);
940
941   /* Generate a constructor to run it.  */
942   cgraph_build_static_cdtor ('I', body);
943 }
944 \f
945 /* Perform file-level initialization. Read in data file, generate name
946    of graph file.  */
947
948 void
949 coverage_init (const char *filename)
950 {
951   int len = strlen (filename);
952
953   /* Name of da file.  */
954   da_file_name = xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1);
955   strcpy (da_file_name, filename);
956   strcat (da_file_name, GCOV_DATA_SUFFIX);
957
958   /* Name of bbg file.  */
959   bbg_file_name = xmalloc (len + strlen (GCOV_NOTE_SUFFIX) + 1);
960   strcpy (bbg_file_name, filename);
961   strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
962
963   read_counts_file ();
964 }
965
966 /* Performs file-level cleanup.  Close graph file, generate coverage
967    variables and constructor.  */
968
969 void
970 coverage_finish (void)
971 {
972   create_coverage ();
973   if (bbg_file_opened)
974     {
975       int error = gcov_close ();
976
977       if (error)
978         unlink (bbg_file_name);
979       if (!local_tick)
980         /* Only remove the da file, if we cannot stamp it. If we can
981            stamp it, libgcov will DTRT.  */
982         unlink (da_file_name);
983     }
984 }
985
986 #include "gt-coverage.h"