OSDN Git Service

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