OSDN Git Service

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