OSDN Git Service

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