OSDN Git Service

e04d22b7a88d98fb6d5431c2c553f9ec0d175030
[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       varpool_finalize_decl (tree_ctr_tables[counter]);
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   DECL_ASSEMBLER_NAME (fn);  /* Initialize assembler name so we can stream out. */
799   value = tree_cons (fields,
800                      build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
801                      value);
802
803   /* FIXME: use build_constructor directly.  */
804   value = build_constructor_from_list (type, nreverse (value));
805
806   return value;
807 }
808
809 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
810    CONSTRUCTOR.  */
811
812 static tree
813 build_gcov_info (void)
814 {
815   unsigned n_ctr_types, ix;
816   tree type, const_type;
817   tree fn_info_type, fn_info_value = NULL_TREE;
818   tree fn_info_ptr_type;
819   tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
820   tree field, fields = NULL_TREE;
821   tree value = NULL_TREE;
822   tree filename_string;
823   int da_file_name_len;
824   unsigned n_fns;
825   const struct function_list *fn;
826   tree string_type;
827
828   /* Count the number of active counters.  */
829   for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
830     if (prg_ctr_mask & (1 << ix))
831       n_ctr_types++;
832
833   type = lang_hooks.types.make_type (RECORD_TYPE);
834   const_type = build_qualified_type (type, TYPE_QUAL_CONST);
835
836   /* Version ident */
837   field = build_decl (BUILTINS_LOCATION,
838                       FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
839   TREE_CHAIN (field) = fields;
840   fields = field;
841   value = tree_cons (field, build_int_cstu (TREE_TYPE (field), GCOV_VERSION),
842                      value);
843
844   /* next -- NULL */
845   field = build_decl (BUILTINS_LOCATION,
846                       FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
847   TREE_CHAIN (field) = fields;
848   fields = field;
849   value = tree_cons (field, null_pointer_node, value);
850
851   /* stamp */
852   field = build_decl (BUILTINS_LOCATION,
853                       FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
854   TREE_CHAIN (field) = fields;
855   fields = field;
856   value = tree_cons (field, build_int_cstu (TREE_TYPE (field), local_tick),
857                      value);
858
859   /* Filename */
860   string_type = build_pointer_type (build_qualified_type (char_type_node,
861                                                     TYPE_QUAL_CONST));
862   field = build_decl (BUILTINS_LOCATION,
863                       FIELD_DECL, NULL_TREE, string_type);
864   TREE_CHAIN (field) = fields;
865   fields = field;
866   da_file_name_len = strlen (da_file_name);
867   filename_string = build_string (da_file_name_len + 1, da_file_name);
868   TREE_TYPE (filename_string) = build_array_type
869     (char_type_node, build_index_type
870      (build_int_cst (NULL_TREE, da_file_name_len)));
871   value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
872                      value);
873
874   /* Build the fn_info type and initializer.  */
875   fn_info_type = build_fn_info_type (n_ctr_types);
876   fn_info_ptr_type = build_pointer_type (build_qualified_type
877                                          (fn_info_type, TYPE_QUAL_CONST));
878   for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
879     fn_info_value = tree_cons (NULL_TREE,
880                                build_fn_info_value (fn, fn_info_type),
881                                fn_info_value);
882   if (n_fns)
883     {
884       tree array_type;
885
886       array_type = build_index_type (build_int_cst (NULL_TREE, n_fns - 1));
887       array_type = build_array_type (fn_info_type, array_type);
888
889       /* FIXME: use build_constructor directly.  */
890       fn_info_value = build_constructor_from_list (array_type,
891                                                    nreverse (fn_info_value));
892       fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
893     }
894   else
895     fn_info_value = null_pointer_node;
896
897   /* number of functions */
898   field = build_decl (BUILTINS_LOCATION,
899                       FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
900   TREE_CHAIN (field) = fields;
901   fields = field;
902   value = tree_cons (field,
903                      build_int_cstu (get_gcov_unsigned_t (), n_fns),
904                      value);
905
906   /* fn_info table */
907   field = build_decl (BUILTINS_LOCATION,
908                       FIELD_DECL, NULL_TREE, fn_info_ptr_type);
909   TREE_CHAIN (field) = fields;
910   fields = field;
911   value = tree_cons (field, fn_info_value, value);
912
913   /* counter_mask */
914   field = build_decl (BUILTINS_LOCATION,
915                       FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
916   TREE_CHAIN (field) = fields;
917   fields = field;
918   value = tree_cons (field,
919                      build_int_cstu (get_gcov_unsigned_t (), prg_ctr_mask),
920                      value);
921
922   /* counters */
923   ctr_info_type = build_ctr_info_type ();
924   ctr_info_ary_type = build_index_type (build_int_cst (NULL_TREE,
925                                                        n_ctr_types));
926   ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
927   for (ix = 0; ix != GCOV_COUNTERS; ix++)
928     if (prg_ctr_mask & (1 << ix))
929       ctr_info_value = tree_cons (NULL_TREE,
930                                   build_ctr_info_value (ix, ctr_info_type),
931                                   ctr_info_value);
932   /* FIXME: use build_constructor directly.  */
933   ctr_info_value = build_constructor_from_list (ctr_info_ary_type,
934                                                 nreverse (ctr_info_value));
935
936   field = build_decl (BUILTINS_LOCATION,
937                       FIELD_DECL, NULL_TREE, ctr_info_ary_type);
938   TREE_CHAIN (field) = fields;
939   fields = field;
940   value = tree_cons (field, ctr_info_value, value);
941
942   finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
943
944   /* FIXME: use build_constructor directly.  */
945   value = build_constructor_from_list (type, nreverse (value));
946
947   return value;
948 }
949
950 /* Write out the structure which libgcov uses to locate all the
951    counters.  The structures used here must match those defined in
952    gcov-io.h.  Write out the constructor to call __gcov_init.  */
953
954 static void
955 create_coverage (void)
956 {
957   tree gcov_info, gcov_init, body, t;
958   char name_buf[32];
959
960   no_coverage = 1; /* Disable any further coverage.  */
961
962   if (!prg_ctr_mask)
963     return;
964
965   t = build_gcov_info ();
966
967   gcov_info = build_decl (BUILTINS_LOCATION,
968                           VAR_DECL, NULL_TREE, TREE_TYPE (t));
969   TREE_STATIC (gcov_info) = 1;
970   ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
971   DECL_NAME (gcov_info) = get_identifier (name_buf);
972   DECL_INITIAL (gcov_info) = t;
973
974   /* Build structure.  */
975   varpool_finalize_decl (gcov_info);
976
977   /* Build a decl for __gcov_init.  */
978   t = build_pointer_type (TREE_TYPE (gcov_info));
979   t = build_function_type_list (void_type_node, t, NULL);
980   t = build_decl (BUILTINS_LOCATION,
981                   FUNCTION_DECL, get_identifier ("__gcov_init"), t);
982   TREE_PUBLIC (t) = 1;
983   DECL_EXTERNAL (t) = 1;
984   DECL_ASSEMBLER_NAME (t);  /* Initialize assembler name so we can stream out. */
985   gcov_init = t;
986
987   /* Generate a call to __gcov_init(&gcov_info).  */
988   body = NULL;
989   t = build_fold_addr_expr (gcov_info);
990   t = build_call_expr (gcov_init, 1, t);
991   append_to_statement_list (t, &body);
992
993   /* Generate a constructor to run it.  */
994   cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
995 }
996 \f
997 /* Perform file-level initialization. Read in data file, generate name
998    of graph file.  */
999
1000 void
1001 coverage_init (const char *filename)
1002 {
1003   int len = strlen (filename);
1004   /* + 1 for extra '/', in case prefix doesn't end with /.  */
1005   int prefix_len;
1006
1007   if (profile_data_prefix == 0 && filename[0] != '/')
1008     profile_data_prefix = getpwd ();
1009
1010   prefix_len = (profile_data_prefix) ? strlen (profile_data_prefix) + 1 : 0;
1011
1012   /* Name of da file.  */
1013   da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX)
1014                           + prefix_len + 1);
1015
1016   if (profile_data_prefix)
1017     {
1018       strcpy (da_file_name, profile_data_prefix);
1019       da_file_name[prefix_len - 1] = '/';
1020       da_file_name[prefix_len] = 0;
1021     }
1022   else
1023     da_file_name[0] = 0;
1024   strcat (da_file_name, filename);
1025   strcat (da_file_name, GCOV_DATA_SUFFIX);
1026
1027   /* Name of bbg file.  */
1028   bbg_file_name = XNEWVEC (char, len + strlen (GCOV_NOTE_SUFFIX) + 1);
1029   strcpy (bbg_file_name, filename);
1030   strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
1031
1032   if (flag_profile_use)
1033     read_counts_file ();
1034 }
1035
1036 /* Performs file-level cleanup.  Close graph file, generate coverage
1037    variables and constructor.  */
1038
1039 void
1040 coverage_finish (void)
1041 {
1042   create_coverage ();
1043   if (bbg_file_opened)
1044     {
1045       int error = gcov_close ();
1046
1047       if (error)
1048         unlink (bbg_file_name);
1049       if (!local_tick)
1050         /* Only remove the da file, if we cannot stamp it. If we can
1051            stamp it, libgcov will DTRT.  */
1052         unlink (da_file_name);
1053     }
1054 }
1055
1056 #include "gt-coverage.h"