OSDN Git Service

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