OSDN Git Service

* c-typeck.c (common_type): Correct comment.
[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 "target.h"
43 #include "coverage.h"
44 #include "libfuncs.h"
45 #include "langhooks.h"
46 #include "hashtab.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 t;
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   t = build (ARRAY_REF, GCOV_TYPE_NODE, tree_ctr_tables[counter],
439              build_int_2 (no, 0));
440   return t;
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   unsigned chksum = DECL_SOURCE_LINE (current_function_decl);
502
503   chksum = coverage_checksum_string (chksum,
504                                      DECL_SOURCE_FILE (current_function_decl));
505   chksum = coverage_checksum_string
506     (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
507
508   return chksum;
509 }
510 \f
511 /* Begin output to the graph file for the current function.
512    Opens the output file, if not already done. Writes the
513    function header, if not already done. Returns nonzero if data
514    should be output.  */
515
516 int
517 coverage_begin_output (void)
518 {
519   if (no_coverage)
520     return 0;
521
522   if (!bbg_function_announced)
523     {
524       const char *file = DECL_SOURCE_FILE (current_function_decl);
525       unsigned line = DECL_SOURCE_LINE (current_function_decl);
526       unsigned long offset;
527
528       if (!bbg_file_opened)
529         {
530           if (!gcov_open (bbg_file_name, -1))
531             error ("cannot open %s", bbg_file_name);
532           else
533             {
534               gcov_write_unsigned (GCOV_NOTE_MAGIC);
535               gcov_write_unsigned (GCOV_VERSION);
536               gcov_write_unsigned (local_tick);
537             }
538           bbg_file_opened = 1;
539         }
540
541       /* Announce function */
542       offset = gcov_write_tag (GCOV_TAG_FUNCTION);
543       gcov_write_unsigned (current_function_funcdef_no + 1);
544       gcov_write_unsigned (compute_checksum ());
545       gcov_write_string (IDENTIFIER_POINTER
546                          (DECL_ASSEMBLER_NAME (current_function_decl)));
547       gcov_write_string (file);
548       gcov_write_unsigned (line);
549       gcov_write_length (offset);
550
551       bbg_function_announced = 1;
552     }
553   return !gcov_is_error ();
554 }
555
556 /* Finish coverage data for the current function. Verify no output
557    error has occurred.  Save function coverage counts.  */
558
559 void
560 coverage_end_function (void)
561 {
562   unsigned i;
563
564   if (bbg_file_opened > 1 && gcov_is_error ())
565     {
566       warning ("error writing `%s'", bbg_file_name);
567       bbg_file_opened = -1;
568     }
569
570   if (fn_ctr_mask)
571     {
572       struct function_list *item;
573
574       item = xmalloc (sizeof (struct function_list));
575
576       *functions_tail = item;
577       functions_tail = &item->next;
578
579       item->next = 0;
580       item->ident = current_function_funcdef_no + 1;
581       item->checksum = compute_checksum ();
582       for (i = 0; i != GCOV_COUNTERS; i++)
583         {
584           item->n_ctrs[i] = fn_n_ctrs[i];
585           prg_n_ctrs[i] += fn_n_ctrs[i];
586           fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
587         }
588       prg_ctr_mask |= fn_ctr_mask;
589       fn_ctr_mask = 0;
590     }
591   bbg_function_announced = 0;
592 }
593
594 /* Creates the gcov_fn_info RECORD_TYPE.  */
595
596 static tree
597 build_fn_info_type (unsigned int counters)
598 {
599   tree type = lang_hooks.types.make_type (RECORD_TYPE);
600   tree field, fields;
601   tree array_type;
602
603   /* ident */
604   fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
605
606   /* checksum */
607   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
608   TREE_CHAIN (field) = fields;
609   fields = field;
610
611   array_type = build_index_type (build_int_2 (counters - 1, 0));
612   array_type = build_array_type (unsigned_type_node, array_type);
613
614   /* counters */
615   field = build_decl (FIELD_DECL, NULL_TREE, array_type);
616   TREE_CHAIN (field) = fields;
617   fields = field;
618
619   finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
620
621   return type;
622 }
623
624 /* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
625    the function being processed and TYPE is the gcov_fn_info
626    RECORD_TYPE.  */
627
628 static tree
629 build_fn_info_value (const struct function_list *function, tree type)
630 {
631   tree value = NULL_TREE;
632   tree fields = TYPE_FIELDS (type);
633   unsigned ix;
634   tree array_value = NULL_TREE;
635
636   /* ident */
637   value = tree_cons (fields,
638                      convert (unsigned_intSI_type_node,
639                               build_int_2 (function->ident, 0)),
640                      value);
641   fields = TREE_CHAIN (fields);
642
643   /* checksum */
644   value = tree_cons (fields,
645                      convert (unsigned_intSI_type_node,
646                               build_int_2 (function->checksum, 0)),
647                      value);
648   fields = TREE_CHAIN (fields);
649
650   /* counters */
651   for (ix = 0; ix != GCOV_COUNTERS; ix++)
652     if (prg_ctr_mask & (1 << ix))
653       {
654         tree counters = convert (unsigned_type_node,
655                                  build_int_2 (function->n_ctrs[ix], 0));
656
657         array_value = tree_cons (NULL_TREE, counters, array_value);
658       }
659
660   array_value = build_constructor (TREE_TYPE (fields), nreverse (array_value));
661   value = tree_cons (fields, array_value, value);
662
663   value = build_constructor (type, nreverse (value));
664
665   return value;
666 }
667
668 /* Creates the gcov_ctr_info RECORD_TYPE.  */
669
670 static tree
671 build_ctr_info_type (void)
672 {
673   tree type = lang_hooks.types.make_type (RECORD_TYPE);
674   tree field, fields = NULL_TREE;
675   tree gcov_ptr_type = build_pointer_type (GCOV_TYPE_NODE);
676   tree gcov_merge_fn_type;
677
678   /* counters */
679   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
680   TREE_CHAIN (field) = fields;
681   fields = field;
682
683   /* values */
684   field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
685   TREE_CHAIN (field) = fields;
686   fields = field;
687
688   /* merge */
689   gcov_merge_fn_type =
690     build_function_type_list (void_type_node,
691                               gcov_ptr_type, unsigned_type_node,
692                               NULL_TREE);
693   field = build_decl (FIELD_DECL, NULL_TREE,
694                       build_pointer_type (gcov_merge_fn_type));
695   TREE_CHAIN (field) = fields;
696   fields = field;
697
698   finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
699
700   return type;
701 }
702
703 /* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
704    the counter being processed and TYPE is the gcov_ctr_info
705    RECORD_TYPE.  */
706
707 static tree
708 build_ctr_info_value (unsigned int counter, tree type)
709 {
710   tree value = NULL_TREE;
711   tree fields = TYPE_FIELDS (type);
712   tree fn;
713
714   /* counters */
715   value = tree_cons (fields,
716                      convert (unsigned_intSI_type_node,
717                               build_int_2 (prg_n_ctrs[counter], 0)),
718                      value);
719   fields = TREE_CHAIN (fields);
720
721   if (prg_n_ctrs[counter])
722     {
723       tree array_type;
724
725       array_type = build_index_type (build_int_2 (prg_n_ctrs[counter] - 1, 0));
726       array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
727                                      array_type);
728
729       TREE_TYPE (tree_ctr_tables[counter]) = array_type;
730       DECL_SIZE (tree_ctr_tables[counter]) = TYPE_SIZE (array_type);
731       DECL_SIZE_UNIT (tree_ctr_tables[counter]) = TYPE_SIZE_UNIT (array_type);
732       assemble_variable (tree_ctr_tables[counter], 0, 0, 0);
733
734       value = tree_cons (fields,
735                          build1 (ADDR_EXPR, TREE_TYPE (fields), 
736                                             tree_ctr_tables[counter]),
737                          value);
738     }
739   else
740     value = tree_cons (fields, null_pointer_node, value);
741   fields = TREE_CHAIN (fields);
742
743   fn = build_decl (FUNCTION_DECL,
744                    get_identifier (ctr_merge_functions[counter]),
745                    TREE_TYPE (TREE_TYPE (fields)));
746   DECL_EXTERNAL (fn) = 1;
747   TREE_PUBLIC (fn) = 1;
748   DECL_ARTIFICIAL (fn) = 1;
749   TREE_NOTHROW (fn) = 1;
750   value = tree_cons (fields,
751                      build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
752                      value);
753
754   value = build_constructor (type, nreverse (value));
755
756   return value;
757 }
758
759 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
760    CONSTRUCTOR.  */
761
762 static tree
763 build_gcov_info (void)
764 {
765   unsigned n_ctr_types, ix;
766   tree type, const_type;
767   tree fn_info_type, fn_info_value = NULL_TREE;
768   tree fn_info_ptr_type;
769   tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
770   tree field, fields = NULL_TREE;
771   tree value = NULL_TREE;
772   tree filename_string;
773   char *filename;
774   int filename_len;
775   unsigned n_fns;
776   const struct function_list *fn;
777   tree string_type;
778
779   /* Count the number of active counters.  */
780   for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
781     if (prg_ctr_mask & (1 << ix))
782       n_ctr_types++;
783
784   type = lang_hooks.types.make_type (RECORD_TYPE);
785   const_type = build_qualified_type (type, TYPE_QUAL_CONST);
786
787   /* Version ident */
788   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
789   TREE_CHAIN (field) = fields;
790   fields = field;
791   value = tree_cons (field, convert (unsigned_intSI_type_node,
792                                      build_int_2 (GCOV_VERSION, 0)),
793                      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, convert (unsigned_intSI_type_node,
806                                      build_int_2 (local_tick, 0)),
807                      value);
808
809   /* Filename */
810   string_type = build_pointer_type (build_qualified_type (char_type_node,
811                                                     TYPE_QUAL_CONST));
812   field = build_decl (FIELD_DECL, NULL_TREE, string_type);
813   TREE_CHAIN (field) = fields;
814   fields = field;
815   filename = getpwd ();
816   filename = (filename && da_file_name[0] != '/'
817               ? concat (filename, "/", da_file_name, NULL)
818               : da_file_name);
819   filename_len = strlen (filename);
820   filename_string = build_string (filename_len + 1, filename);
821   if (filename != da_file_name)
822     free (filename);
823   TREE_TYPE (filename_string) =
824           build_array_type (char_type_node,
825                             build_index_type (build_int_2 (filename_len, 0)));
826   value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
827                      value);
828
829   /* Build the fn_info type and initializer.  */
830   fn_info_type = build_fn_info_type (n_ctr_types);
831   fn_info_ptr_type = build_pointer_type (build_qualified_type
832                                          (fn_info_type, TYPE_QUAL_CONST));
833   for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
834     fn_info_value = tree_cons (NULL_TREE,
835                                build_fn_info_value (fn, fn_info_type),
836                                fn_info_value);
837   if (n_fns)
838     {
839       tree array_type;
840
841       array_type = build_index_type (build_int_2 (n_fns - 1, 0));
842       array_type = build_array_type (fn_info_type, array_type);
843
844       fn_info_value = build_constructor (array_type, nreverse (fn_info_value));
845       fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
846     }
847   else
848     fn_info_value = null_pointer_node;
849
850   /* number of functions */
851   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
852   TREE_CHAIN (field) = fields;
853   fields = field;
854   value = tree_cons (field,
855                      convert (unsigned_type_node, build_int_2 (n_fns, 0)),
856                      value);
857
858   /* fn_info table */
859   field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type);
860   TREE_CHAIN (field) = fields;
861   fields = field;
862   value = tree_cons (field, fn_info_value, value);
863
864   /* counter_mask */
865   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
866   TREE_CHAIN (field) = fields;
867   fields = field;
868   value = tree_cons (field,
869                      convert (unsigned_type_node,
870                               build_int_2 (prg_ctr_mask, 0)),
871                      value);
872
873   /* counters */
874   ctr_info_type = build_ctr_info_type ();
875   ctr_info_ary_type = build_index_type (build_int_2 (n_ctr_types, 0));
876   ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
877   for (ix = 0; ix != GCOV_COUNTERS; ix++)
878     if (prg_ctr_mask & (1 << ix))
879       ctr_info_value = tree_cons (NULL_TREE,
880                                   build_ctr_info_value (ix, ctr_info_type),
881                                   ctr_info_value);
882   ctr_info_value = build_constructor (ctr_info_ary_type,
883                                       nreverse (ctr_info_value));
884
885   field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
886   TREE_CHAIN (field) = fields;
887   fields = field;
888   value = tree_cons (field, ctr_info_value, value);
889
890   finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
891
892   value = build_constructor (type, nreverse (value));
893
894   return value;
895 }
896
897 /* Write out the structure which libgcov uses to locate all the
898    counters.  The structures used here must match those defined in
899    gcov-io.h.  Write out the constructor to call __gcov_init.  */
900
901 static void
902 create_coverage (void)
903 {
904   tree gcov_info, gcov_info_value;
905   char name[20];
906   char *ctor_name;
907   tree ctor;
908   rtx gcov_info_address;
909
910   no_coverage = 1; /* Disable any further coverage.  */
911
912   if (!prg_ctr_mask)
913     return;
914
915   gcov_info_value = build_gcov_info ();
916
917   gcov_info = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (gcov_info_value));
918   DECL_INITIAL (gcov_info) = gcov_info_value;
919
920   TREE_STATIC (gcov_info) = 1;
921   ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 0);
922   DECL_NAME (gcov_info) = get_identifier (name);
923
924   /* Build structure.  */
925   assemble_variable (gcov_info, 0, 0, 0);
926
927   /* Build the constructor function to invoke __gcov_init.  */
928   ctor_name = concat (IDENTIFIER_POINTER (get_file_function_name ('I')),
929                       "_GCOV", NULL);
930   ctor = build_decl (FUNCTION_DECL, get_identifier (ctor_name),
931                      build_function_type (void_type_node, NULL_TREE));
932   free (ctor_name);
933   DECL_EXTERNAL (ctor) = 0;
934
935   /* It can be a static function as long as collect2 does not have
936      to scan the object file to find its ctor/dtor routine.  */
937   TREE_PUBLIC (ctor) = ! targetm.have_ctors_dtors;
938   TREE_USED (ctor) = 1;
939   DECL_RESULT (ctor) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
940   DECL_UNINLINABLE (ctor) = 1;
941
942   rest_of_decl_compilation (ctor, 0, 1, 0);
943   announce_function (ctor);
944   current_function_decl = ctor;
945   make_decl_rtl (ctor, NULL);
946   init_function_start (ctor);
947   expand_function_start (ctor, 0);
948   /* Actually generate the code to call __gcov_init.  */
949   gcov_info_address = force_reg (Pmode, XEXP (DECL_RTL (gcov_info), 0));
950   emit_library_call (gcov_init_libfunc, LCT_NORMAL, VOIDmode, 1,
951                      gcov_info_address, Pmode);
952
953   expand_function_end ();
954   /* Create a dummy BLOCK.  */
955   DECL_INITIAL (ctor) = make_node (BLOCK);
956   TREE_USED (DECL_INITIAL (ctor)) = 1;
957
958   rest_of_compilation (ctor);
959
960   if (! quiet_flag)
961     fflush (asm_out_file);
962   current_function_decl = NULL_TREE;
963
964   if (targetm.have_ctors_dtors)
965     targetm.asm_out.constructor (XEXP (DECL_RTL (ctor), 0),
966                                  DEFAULT_INIT_PRIORITY);
967 }
968 \f
969 /* Perform file-level initialization. Read in data file, generate name
970    of graph file.  */
971
972 void
973 coverage_init (const char *filename)
974 {
975   int len = strlen (filename);
976
977   /* Name of da file.  */
978   da_file_name = xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1);
979   strcpy (da_file_name, filename);
980   strcat (da_file_name, GCOV_DATA_SUFFIX);
981
982   /* Name of bbg file.  */
983   bbg_file_name = xmalloc (len + strlen (GCOV_NOTE_SUFFIX) + 1);
984   strcpy (bbg_file_name, filename);
985   strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
986
987   read_counts_file ();
988 }
989
990 /* Performs file-level cleanup.  Close graph file, generate coverage
991    variables and constructor.  */
992
993 void
994 coverage_finish (void)
995 {
996   create_coverage ();
997   if (bbg_file_opened)
998     {
999       int error = gcov_close ();
1000
1001       if (error)
1002         unlink (bbg_file_name);
1003       if (!local_tick)
1004         /* Only remove the da file, if we cannot stamp it. If we can
1005            stamp it, libgcov will DTRT.  */
1006         unlink (da_file_name);
1007     }
1008 }
1009
1010 #include "gt-coverage.h"