OSDN Git Service

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