OSDN Git Service

* gcc.dg/tree-ssa/fre-vce-1.c: Cleanup "fre" tree dump.
[pf3gnuchains/gcc-fork.git] / gcc / coverage.c
1 /* Read and write coverage files, and associated functionality.
2    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
3    2000, 2001, 2003, 2004, 2005, 2007, 2008 Free Software Foundation,
4    Inc.
5    Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
6    based on some ideas from Dain Samples of UC Berkeley.
7    Further mangling by Bob Manson, Cygnus Support.
8    Further mangled by Nathan Sidwell, CodeSourcery
9
10 This file is part of GCC.
11
12 GCC is free software; you can redistribute it and/or modify it under
13 the terms of the GNU General Public License as published by the Free
14 Software Foundation; either version 3, or (at your option) any later
15 version.
16
17 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
18 WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with GCC; see the file COPYING3.  If not see
24 <http://www.gnu.org/licenses/>.  */
25
26
27 #define GCOV_LINKAGE
28
29 #include "config.h"
30 #include "system.h"
31 #include "coretypes.h"
32 #include "tm.h"
33 #include "rtl.h"
34 #include "tree.h"
35 #include "flags.h"
36 #include "output.h"
37 #include "regs.h"
38 #include "expr.h"
39 #include "function.h"
40 #include "toplev.h"
41 #include "tm_p.h"
42 #include "ggc.h"
43 #include "coverage.h"
44 #include "langhooks.h"
45 #include "hashtab.h"
46 #include "tree-iterator.h"
47 #include "cgraph.h"
48 #include "tree-pass.h"
49
50 #include "gcov-io.c"
51
52 struct function_list
53 {
54   struct function_list *next;    /* next function */
55   unsigned ident;                /* function ident */
56   unsigned checksum;             /* function checksum */
57   unsigned n_ctrs[GCOV_COUNTERS];/* number of counters.  */
58 };
59
60 /* Counts information for a function.  */
61 typedef struct counts_entry
62 {
63   /* We hash by  */
64   unsigned ident;
65   unsigned ctr;
66
67   /* Store  */
68   unsigned checksum;
69   gcov_type *counts;
70   struct gcov_ctr_summary summary;
71
72   /* Workspace */
73   struct counts_entry *chain;
74
75 } counts_entry_t;
76
77 static struct function_list *functions_head = 0;
78 static struct function_list **functions_tail = &functions_head;
79 static unsigned no_coverage = 0;
80
81 /* Cumulative counter information for whole program.  */
82 static unsigned prg_ctr_mask; /* Mask of counter types generated.  */
83 static unsigned prg_n_ctrs[GCOV_COUNTERS]; /* Total counters allocated.  */
84
85 /* Counter information for current function.  */
86 static unsigned fn_ctr_mask; /* Mask of counters used.  */
87 static unsigned fn_n_ctrs[GCOV_COUNTERS]; /* Counters allocated.  */
88 static unsigned fn_b_ctrs[GCOV_COUNTERS]; /* Allocation base.  */
89
90 /* Name of the output file for coverage output file.  */
91 static char *bbg_file_name;
92 static unsigned bbg_file_opened;
93 static int bbg_function_announced;
94
95 /* Name of the count data file.  */
96 static char *da_file_name;
97
98 /* Hash table of count data.  */
99 static htab_t counts_hash = NULL;
100
101 /* Trees representing the counter table arrays.  */
102 static GTY(()) tree tree_ctr_tables[GCOV_COUNTERS];
103
104 /* The names of the counter tables.  Not used if we're
105    generating counters at tree level.  */
106 static GTY(()) rtx ctr_labels[GCOV_COUNTERS];
107
108 /* The names of merge functions for counters.  */
109 static const char *const ctr_merge_functions[GCOV_COUNTERS] = GCOV_MERGE_FUNCTIONS;
110 static const char *const ctr_names[GCOV_COUNTERS] = GCOV_COUNTER_NAMES;
111
112 /* Forward declarations.  */
113 static hashval_t htab_counts_entry_hash (const void *);
114 static int htab_counts_entry_eq (const void *, const void *);
115 static void htab_counts_entry_del (void *);
116 static void read_counts_file (void);
117 static unsigned compute_checksum (void);
118 static unsigned coverage_checksum_string (unsigned, const char *);
119 static tree build_fn_info_type (unsigned);
120 static tree build_fn_info_value (const struct function_list *, tree);
121 static tree build_ctr_info_type (void);
122 static tree build_ctr_info_value (unsigned, tree);
123 static tree build_gcov_info (void);
124 static void create_coverage (void);
125 \f
126 /* Return the type node for gcov_type.  */
127
128 tree
129 get_gcov_type (void)
130 {
131   return lang_hooks.types.type_for_size (GCOV_TYPE_SIZE, false);
132 }
133
134 /* Return the type node for gcov_unsigned_t.  */
135
136 static tree
137 get_gcov_unsigned_t (void)
138 {
139   return lang_hooks.types.type_for_size (32, true);
140 }
141 \f
142 static hashval_t
143 htab_counts_entry_hash (const void *of)
144 {
145   const counts_entry_t *const entry = (const counts_entry_t *) of;
146
147   return entry->ident * GCOV_COUNTERS + entry->ctr;
148 }
149
150 static int
151 htab_counts_entry_eq (const void *of1, const void *of2)
152 {
153   const counts_entry_t *const entry1 = (const counts_entry_t *) of1;
154   const counts_entry_t *const entry2 = (const counts_entry_t *) of2;
155
156   return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
157 }
158
159 static void
160 htab_counts_entry_del (void *of)
161 {
162   counts_entry_t *const entry = (counts_entry_t *) of;
163
164   free (entry->counts);
165   free (entry);
166 }
167
168 /* Read in the counts file, if available.  */
169
170 static void
171 read_counts_file (void)
172 {
173   gcov_unsigned_t fn_ident = 0;
174   gcov_unsigned_t checksum = -1;
175   counts_entry_t *summaried = NULL;
176   unsigned seen_summary = 0;
177   gcov_unsigned_t tag;
178   int is_error = 0;
179
180   if (!gcov_open (da_file_name, 1))
181     return;
182
183   if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
184     {
185       warning (0, "%qs is not a gcov data file", da_file_name);
186       gcov_close ();
187       return;
188     }
189   else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
190     {
191       char v[4], e[4];
192
193       GCOV_UNSIGNED2STRING (v, tag);
194       GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
195
196       warning (0, "%qs is version %q.*s, expected version %q.*s",
197                da_file_name, 4, v, 4, e);
198       gcov_close ();
199       return;
200     }
201
202   /* Read and discard the stamp.  */
203   gcov_read_unsigned ();
204   
205   counts_hash = htab_create (10,
206                              htab_counts_entry_hash, htab_counts_entry_eq,
207                              htab_counts_entry_del);
208   while ((tag = gcov_read_unsigned ()))
209     {
210       gcov_unsigned_t length;
211       gcov_position_t offset;
212
213       length = gcov_read_unsigned ();
214       offset = gcov_position ();
215       if (tag == GCOV_TAG_FUNCTION)
216         {
217           fn_ident = gcov_read_unsigned ();
218           checksum = gcov_read_unsigned ();
219           if (seen_summary)
220             {
221               /* We have already seen a summary, this means that this
222                  new function begins a new set of program runs. We
223                  must unlink the summaried chain.  */
224               counts_entry_t *entry, *chain;
225
226               for (entry = summaried; entry; entry = chain)
227                 {
228                   chain = entry->chain;
229                   entry->chain = NULL;
230                 }
231               summaried = NULL;
232               seen_summary = 0;
233             }
234         }
235       else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
236         {
237           counts_entry_t *entry;
238           struct gcov_summary summary;
239
240           gcov_read_summary (&summary);
241           seen_summary = 1;
242           for (entry = summaried; entry; entry = entry->chain)
243             {
244               struct gcov_ctr_summary *csum = &summary.ctrs[entry->ctr];
245
246               entry->summary.runs += csum->runs;
247               entry->summary.sum_all += csum->sum_all;
248               if (entry->summary.run_max < csum->run_max)
249                 entry->summary.run_max = csum->run_max;
250               entry->summary.sum_max += csum->sum_max;
251             }
252         }
253       else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
254         {
255           counts_entry_t **slot, *entry, elt;
256           unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
257           unsigned ix;
258
259           elt.ident = fn_ident;
260           elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
261
262           slot = (counts_entry_t **) htab_find_slot
263             (counts_hash, &elt, INSERT);
264           entry = *slot;
265           if (!entry)
266             {
267               *slot = entry = XCNEW (counts_entry_t);
268               entry->ident = elt.ident;
269               entry->ctr = elt.ctr;
270               entry->checksum = checksum;
271               entry->summary.num = n_counts;
272               entry->counts = XCNEWVEC (gcov_type, n_counts);
273             }
274           else if (entry->checksum != checksum)
275             {
276               error ("coverage mismatch for function %u while reading execution counters",
277                      fn_ident);
278               error ("checksum is %x instead of %x", entry->checksum, checksum);
279               htab_delete (counts_hash);
280               break;
281             }
282           else if (entry->summary.num != n_counts)
283             {
284               error ("coverage mismatch for function %u while reading execution counters",
285                      fn_ident);
286               error ("number of counters is %d instead of %d", entry->summary.num, n_counts);
287               htab_delete (counts_hash);
288               break;
289             }
290           else if (elt.ctr >= GCOV_COUNTERS_SUMMABLE)
291             {
292               error ("cannot merge separate %s counters for function %u",
293                      ctr_names[elt.ctr], fn_ident);
294               goto skip_merge;
295             }
296
297           if (elt.ctr < GCOV_COUNTERS_SUMMABLE
298               /* This should always be true for a just allocated entry,
299                  and always false for an existing one. Check this way, in
300                  case the gcov file is corrupt.  */
301               && (!entry->chain || summaried != entry))
302             {
303               entry->chain = summaried;
304               summaried = entry;
305             }
306           for (ix = 0; ix != n_counts; ix++)
307             entry->counts[ix] += gcov_read_counter ();
308         skip_merge:;
309         }
310       gcov_sync (offset, length);
311       if ((is_error = gcov_is_error ()))
312         {
313           error (is_error < 0 ? "%qs has overflowed" : "%qs is corrupted",
314                  da_file_name);
315           htab_delete (counts_hash);
316           break;
317         }
318     }
319
320   gcov_close ();
321 }
322
323 /* Returns the counters for a particular tag.  */
324
325 gcov_type *
326 get_coverage_counts (unsigned counter, unsigned expected,
327                      const struct gcov_ctr_summary **summary)
328 {
329   counts_entry_t *entry, elt;
330   gcov_unsigned_t checksum = -1;
331
332   /* No hash table, no counts.  */
333   if (!counts_hash)
334     {
335       static int warned = 0;
336
337       if (!warned++)
338         inform (input_location, (flag_guess_branch_prob
339                  ? "file %s not found, execution counts estimated"
340                  : "file %s not found, execution counts assumed to be zero"),
341                 da_file_name);
342       return NULL;
343     }
344
345   elt.ident = current_function_funcdef_no + 1;
346   elt.ctr = counter;
347   entry = (counts_entry_t *) htab_find (counts_hash, &elt);
348   if (!entry)
349     {
350       warning (0, "no coverage for function %qE found",
351                DECL_ASSEMBLER_NAME (current_function_decl));
352       return NULL;
353     }
354
355   checksum = compute_checksum ();
356   if (entry->checksum != checksum
357       || entry->summary.num != expected)
358     {
359       static int warned = 0;
360       tree id = DECL_ASSEMBLER_NAME (current_function_decl);
361
362       if (warn_coverage_mismatch)
363         warning (OPT_Wcoverage_mismatch, "coverage mismatch for function "
364                  "%qE while reading counter %qs", id, ctr_names[counter]);
365       else
366         error ("coverage mismatch for function %qE while reading counter %qs",
367                id, ctr_names[counter]);
368
369       if (!inhibit_warnings)
370         {
371           if (entry->checksum != checksum)
372             inform (input_location, "checksum is %x instead of %x", entry->checksum, checksum);
373           else
374             inform (input_location, "number of counters is %d instead of %d",
375                     entry->summary.num, expected);
376         }
377
378       if (warn_coverage_mismatch
379           && !inhibit_warnings
380           && !warned++)
381         {
382           inform (input_location, "coverage mismatch ignored due to -Wcoverage-mismatch");
383           inform (input_location, flag_guess_branch_prob
384                   ? "execution counts estimated"
385                   : "execution counts assumed to be zero");
386           if (!flag_guess_branch_prob)
387             inform (input_location, "this can result in poorly optimized code");
388         }
389
390       return NULL;
391     }
392
393   if (summary)
394     *summary = &entry->summary;
395
396   return entry->counts;
397 }
398
399 /* Allocate NUM counters of type COUNTER. Returns nonzero if the
400    allocation succeeded.  */
401
402 int
403 coverage_counter_alloc (unsigned counter, unsigned num)
404 {
405   if (no_coverage)
406     return 0;
407
408   if (!num)
409     return 1;
410
411   if (!tree_ctr_tables[counter])
412     {
413       /* Generate and save a copy of this so it can be shared.  Leave
414          the index type unspecified for now; it will be set after all
415          functions have been compiled.  */
416       char buf[20];
417       tree gcov_type_node = get_gcov_type ();
418       tree gcov_type_array_type
419         = build_array_type (gcov_type_node, NULL_TREE);
420       tree_ctr_tables[counter]
421         = build_decl (BUILTINS_LOCATION,
422                       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 || flag_compare_debug)
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 (BUILTINS_LOCATION,
644                        FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
645
646   /* checksum */
647   field = build_decl (BUILTINS_LOCATION,
648                       FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
649   TREE_CHAIN (field) = fields;
650   fields = field;
651
652   array_type = build_int_cst (NULL_TREE, counters - 1);
653   array_type = build_index_type (array_type);
654   array_type = build_array_type (get_gcov_unsigned_t (), array_type);
655
656   /* counters */
657   field = build_decl (BUILTINS_LOCATION,
658                       FIELD_DECL, NULL_TREE, array_type);
659   TREE_CHAIN (field) = fields;
660   fields = field;
661
662   finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
663
664   return type;
665 }
666
667 /* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
668    the function being processed and TYPE is the gcov_fn_info
669    RECORD_TYPE.  */
670
671 static tree
672 build_fn_info_value (const struct function_list *function, tree type)
673 {
674   tree value = NULL_TREE;
675   tree fields = TYPE_FIELDS (type);
676   unsigned ix;
677   tree array_value = NULL_TREE;
678
679   /* ident */
680   value = tree_cons (fields, build_int_cstu (get_gcov_unsigned_t (),
681                                              function->ident), value);
682   fields = TREE_CHAIN (fields);
683
684   /* checksum */
685   value = tree_cons (fields, build_int_cstu (get_gcov_unsigned_t (),
686                                              function->checksum), value);
687   fields = TREE_CHAIN (fields);
688
689   /* counters */
690   for (ix = 0; ix != GCOV_COUNTERS; ix++)
691     if (prg_ctr_mask & (1 << ix))
692       {
693         tree counters = build_int_cstu (get_gcov_unsigned_t (),
694                                         function->n_ctrs[ix]);
695
696         array_value = tree_cons (NULL_TREE, counters, array_value);
697       }
698
699   /* FIXME: use build_constructor directly.  */
700   array_value = build_constructor_from_list (TREE_TYPE (fields),
701                                              nreverse (array_value));
702   value = tree_cons (fields, array_value, value);
703
704   /* FIXME: use build_constructor directly.  */
705   value = build_constructor_from_list (type, nreverse (value));
706
707   return value;
708 }
709
710 /* Creates the gcov_ctr_info RECORD_TYPE.  */
711
712 static tree
713 build_ctr_info_type (void)
714 {
715   tree type = lang_hooks.types.make_type (RECORD_TYPE);
716   tree field, fields = NULL_TREE;
717   tree gcov_ptr_type = build_pointer_type (get_gcov_type ());
718   tree gcov_merge_fn_type;
719
720   /* counters */
721   field = build_decl (BUILTINS_LOCATION,
722                       FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
723   TREE_CHAIN (field) = fields;
724   fields = field;
725
726   /* values */
727   field = build_decl (BUILTINS_LOCATION,
728                       FIELD_DECL, NULL_TREE, gcov_ptr_type);
729   TREE_CHAIN (field) = fields;
730   fields = field;
731
732   /* merge */
733   gcov_merge_fn_type =
734     build_function_type_list (void_type_node,
735                               gcov_ptr_type, get_gcov_unsigned_t (),
736                               NULL_TREE);
737   field = build_decl (BUILTINS_LOCATION,
738                       FIELD_DECL, NULL_TREE,
739                       build_pointer_type (gcov_merge_fn_type));
740   TREE_CHAIN (field) = fields;
741   fields = field;
742
743   finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
744
745   return type;
746 }
747
748 /* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
749    the counter being processed and TYPE is the gcov_ctr_info
750    RECORD_TYPE.  */
751
752 static tree
753 build_ctr_info_value (unsigned int counter, tree type)
754 {
755   tree value = NULL_TREE;
756   tree fields = TYPE_FIELDS (type);
757   tree fn;
758
759   /* counters */
760   value = tree_cons (fields,
761                      build_int_cstu (get_gcov_unsigned_t (),
762                                      prg_n_ctrs[counter]),
763                      value);
764   fields = TREE_CHAIN (fields);
765
766   if (prg_n_ctrs[counter])
767     {
768       tree array_type;
769
770       array_type = build_int_cstu (get_gcov_unsigned_t (),
771                                    prg_n_ctrs[counter] - 1);
772       array_type = build_index_type (array_type);
773       array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
774                                      array_type);
775
776       TREE_TYPE (tree_ctr_tables[counter]) = array_type;
777       DECL_SIZE (tree_ctr_tables[counter]) = TYPE_SIZE (array_type);
778       DECL_SIZE_UNIT (tree_ctr_tables[counter]) = TYPE_SIZE_UNIT (array_type);
779       assemble_variable (tree_ctr_tables[counter], 0, 0, 0);
780
781       value = tree_cons (fields,
782                          build1 (ADDR_EXPR, TREE_TYPE (fields), 
783                                             tree_ctr_tables[counter]),
784                          value);
785     }
786   else
787     value = tree_cons (fields, null_pointer_node, value);
788   fields = TREE_CHAIN (fields);
789
790   fn = build_decl (BUILTINS_LOCATION,
791                    FUNCTION_DECL,
792                    get_identifier (ctr_merge_functions[counter]),
793                    TREE_TYPE (TREE_TYPE (fields)));
794   DECL_EXTERNAL (fn) = 1;
795   TREE_PUBLIC (fn) = 1;
796   DECL_ARTIFICIAL (fn) = 1;
797   TREE_NOTHROW (fn) = 1;
798   value = tree_cons (fields,
799                      build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
800                      value);
801
802   /* FIXME: use build_constructor directly.  */
803   value = build_constructor_from_list (type, nreverse (value));
804
805   return value;
806 }
807
808 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
809    CONSTRUCTOR.  */
810
811 static tree
812 build_gcov_info (void)
813 {
814   unsigned n_ctr_types, ix;
815   tree type, const_type;
816   tree fn_info_type, fn_info_value = NULL_TREE;
817   tree fn_info_ptr_type;
818   tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
819   tree field, fields = NULL_TREE;
820   tree value = NULL_TREE;
821   tree filename_string;
822   int da_file_name_len;
823   unsigned n_fns;
824   const struct function_list *fn;
825   tree string_type;
826
827   /* Count the number of active counters.  */
828   for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
829     if (prg_ctr_mask & (1 << ix))
830       n_ctr_types++;
831
832   type = lang_hooks.types.make_type (RECORD_TYPE);
833   const_type = build_qualified_type (type, TYPE_QUAL_CONST);
834
835   /* Version ident */
836   field = build_decl (BUILTINS_LOCATION,
837                       FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
838   TREE_CHAIN (field) = fields;
839   fields = field;
840   value = tree_cons (field, build_int_cstu (TREE_TYPE (field), GCOV_VERSION),
841                      value);
842
843   /* next -- NULL */
844   field = build_decl (BUILTINS_LOCATION,
845                       FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
846   TREE_CHAIN (field) = fields;
847   fields = field;
848   value = tree_cons (field, null_pointer_node, value);
849
850   /* stamp */
851   field = build_decl (BUILTINS_LOCATION,
852                       FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
853   TREE_CHAIN (field) = fields;
854   fields = field;
855   value = tree_cons (field, build_int_cstu (TREE_TYPE (field), local_tick),
856                      value);
857
858   /* Filename */
859   string_type = build_pointer_type (build_qualified_type (char_type_node,
860                                                     TYPE_QUAL_CONST));
861   field = build_decl (BUILTINS_LOCATION,
862                       FIELD_DECL, NULL_TREE, string_type);
863   TREE_CHAIN (field) = fields;
864   fields = field;
865   da_file_name_len = strlen (da_file_name);
866   filename_string = build_string (da_file_name_len + 1, da_file_name);
867   TREE_TYPE (filename_string) = build_array_type
868     (char_type_node, build_index_type
869      (build_int_cst (NULL_TREE, da_file_name_len)));
870   value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
871                      value);
872
873   /* Build the fn_info type and initializer.  */
874   fn_info_type = build_fn_info_type (n_ctr_types);
875   fn_info_ptr_type = build_pointer_type (build_qualified_type
876                                          (fn_info_type, TYPE_QUAL_CONST));
877   for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
878     fn_info_value = tree_cons (NULL_TREE,
879                                build_fn_info_value (fn, fn_info_type),
880                                fn_info_value);
881   if (n_fns)
882     {
883       tree array_type;
884
885       array_type = build_index_type (build_int_cst (NULL_TREE, n_fns - 1));
886       array_type = build_array_type (fn_info_type, array_type);
887
888       /* FIXME: use build_constructor directly.  */
889       fn_info_value = build_constructor_from_list (array_type,
890                                                    nreverse (fn_info_value));
891       fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
892     }
893   else
894     fn_info_value = null_pointer_node;
895
896   /* number of functions */
897   field = build_decl (BUILTINS_LOCATION,
898                       FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
899   TREE_CHAIN (field) = fields;
900   fields = field;
901   value = tree_cons (field,
902                      build_int_cstu (get_gcov_unsigned_t (), n_fns),
903                      value);
904
905   /* fn_info table */
906   field = build_decl (BUILTINS_LOCATION,
907                       FIELD_DECL, NULL_TREE, fn_info_ptr_type);
908   TREE_CHAIN (field) = fields;
909   fields = field;
910   value = tree_cons (field, fn_info_value, value);
911
912   /* counter_mask */
913   field = build_decl (BUILTINS_LOCATION,
914                       FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
915   TREE_CHAIN (field) = fields;
916   fields = field;
917   value = tree_cons (field,
918                      build_int_cstu (get_gcov_unsigned_t (), prg_ctr_mask),
919                      value);
920
921   /* counters */
922   ctr_info_type = build_ctr_info_type ();
923   ctr_info_ary_type = build_index_type (build_int_cst (NULL_TREE,
924                                                        n_ctr_types));
925   ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
926   for (ix = 0; ix != GCOV_COUNTERS; ix++)
927     if (prg_ctr_mask & (1 << ix))
928       ctr_info_value = tree_cons (NULL_TREE,
929                                   build_ctr_info_value (ix, ctr_info_type),
930                                   ctr_info_value);
931   /* FIXME: use build_constructor directly.  */
932   ctr_info_value = build_constructor_from_list (ctr_info_ary_type,
933                                                 nreverse (ctr_info_value));
934
935   field = build_decl (BUILTINS_LOCATION,
936                       FIELD_DECL, NULL_TREE, ctr_info_ary_type);
937   TREE_CHAIN (field) = fields;
938   fields = field;
939   value = tree_cons (field, ctr_info_value, value);
940
941   finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
942
943   /* FIXME: use build_constructor directly.  */
944   value = build_constructor_from_list (type, nreverse (value));
945
946   return value;
947 }
948
949 /* Write out the structure which libgcov uses to locate all the
950    counters.  The structures used here must match those defined in
951    gcov-io.h.  Write out the constructor to call __gcov_init.  */
952
953 static void
954 create_coverage (void)
955 {
956   tree gcov_info, gcov_init, body, t;
957   char name_buf[32];
958
959   no_coverage = 1; /* Disable any further coverage.  */
960
961   if (!prg_ctr_mask)
962     return;
963
964   t = build_gcov_info ();
965
966   gcov_info = build_decl (BUILTINS_LOCATION,
967                           VAR_DECL, NULL_TREE, TREE_TYPE (t));
968   TREE_STATIC (gcov_info) = 1;
969   ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
970   DECL_NAME (gcov_info) = get_identifier (name_buf);
971   DECL_INITIAL (gcov_info) = t;
972
973   /* Build structure.  */
974   assemble_variable (gcov_info, 0, 0, 0);
975
976   /* Build a decl for __gcov_init.  */
977   t = build_pointer_type (TREE_TYPE (gcov_info));
978   t = build_function_type_list (void_type_node, t, NULL);
979   t = build_decl (BUILTINS_LOCATION,
980                   FUNCTION_DECL, get_identifier ("__gcov_init"), t);
981   TREE_PUBLIC (t) = 1;
982   DECL_EXTERNAL (t) = 1;
983   gcov_init = t;
984
985   /* Generate a call to __gcov_init(&gcov_info).  */
986   body = NULL;
987   t = build_fold_addr_expr (gcov_info);
988   t = build_call_expr (gcov_init, 1, t);
989   append_to_statement_list (t, &body);
990
991   /* Generate a constructor to run it.  */
992   cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
993 }
994 \f
995 /* Perform file-level initialization. Read in data file, generate name
996    of graph file.  */
997
998 void
999 coverage_init (const char *filename)
1000 {
1001   int len = strlen (filename);
1002   /* + 1 for extra '/', in case prefix doesn't end with /.  */
1003   int prefix_len;
1004  
1005   if (profile_data_prefix == 0 && filename[0] != '/')
1006     profile_data_prefix = getpwd ();
1007
1008   prefix_len = (profile_data_prefix) ? strlen (profile_data_prefix) + 1 : 0;
1009
1010   /* Name of da file.  */
1011   da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX) 
1012                           + prefix_len + 1);
1013
1014   if (profile_data_prefix)
1015     {
1016       strcpy (da_file_name, profile_data_prefix);
1017       da_file_name[prefix_len - 1] = '/';
1018       da_file_name[prefix_len] = 0;
1019     }
1020   else
1021     da_file_name[0] = 0;
1022   strcat (da_file_name, filename);
1023   strcat (da_file_name, GCOV_DATA_SUFFIX);
1024
1025   /* Name of bbg file.  */
1026   bbg_file_name = XNEWVEC (char, len + strlen (GCOV_NOTE_SUFFIX) + 1);
1027   strcpy (bbg_file_name, filename);
1028   strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
1029
1030   if (flag_profile_use)
1031     read_counts_file ();
1032 }
1033
1034 /* Performs file-level cleanup.  Close graph file, generate coverage
1035    variables and constructor.  */
1036
1037 void
1038 coverage_finish (void)
1039 {
1040   create_coverage ();
1041   if (bbg_file_opened)
1042     {
1043       int error = gcov_close ();
1044
1045       if (error)
1046         unlink (bbg_file_name);
1047       if (!local_tick)
1048         /* Only remove the da file, if we cannot stamp it. If we can
1049            stamp it, libgcov will DTRT.  */
1050         unlink (da_file_name);
1051     }
1052 }
1053
1054 #include "gt-coverage.h"