OSDN Git Service

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