OSDN Git Service

gcc:
[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, 2009, 2010
4    Free Software Foundation, 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 "basic-block.h"
41 #include "toplev.h"
42 #include "tm_p.h"
43 #include "ggc.h"
44 #include "coverage.h"
45 #include "langhooks.h"
46 #include "hashtab.h"
47 #include "tree-iterator.h"
48 #include "cgraph.h"
49 #include "tree-pass.h"
50 #include "diagnostic-core.h"
51 #include "intl.h"
52 #include "filenames.h"
53
54 #include "gcov-io.c"
55
56 struct function_list
57 {
58   struct function_list *next;    /* next function */
59   unsigned ident;                /* function ident */
60   unsigned checksum;             /* function checksum */
61   unsigned n_ctrs[GCOV_COUNTERS];/* number of counters.  */
62 };
63
64 /* Counts information for a function.  */
65 typedef struct counts_entry
66 {
67   /* We hash by  */
68   unsigned ident;
69   unsigned ctr;
70
71   /* Store  */
72   unsigned checksum;
73   gcov_type *counts;
74   struct gcov_ctr_summary summary;
75
76   /* Workspace */
77   struct counts_entry *chain;
78
79 } counts_entry_t;
80
81 static struct function_list *functions_head = 0;
82 static struct function_list **functions_tail = &functions_head;
83 static unsigned no_coverage = 0;
84
85 /* Cumulative counter information for whole program.  */
86 static unsigned prg_ctr_mask; /* Mask of counter types generated.  */
87 static unsigned prg_n_ctrs[GCOV_COUNTERS]; /* Total counters allocated.  */
88
89 /* Counter information for current function.  */
90 static unsigned fn_ctr_mask; /* Mask of counters used.  */
91 static unsigned fn_n_ctrs[GCOV_COUNTERS]; /* Counters allocated.  */
92 static unsigned fn_b_ctrs[GCOV_COUNTERS]; /* Allocation base.  */
93
94 /* Name of the output file for coverage output file.  */
95 static char *bbg_file_name;
96 static unsigned bbg_file_opened;
97 static int bbg_function_announced;
98
99 /* Name of the count data file.  */
100 static char *da_file_name;
101
102 /* Hash table of count data.  */
103 static htab_t counts_hash = NULL;
104
105 /* Trees representing the counter table arrays.  */
106 static GTY(()) tree tree_ctr_tables[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       bool warning_printed = false;
361       tree id = DECL_ASSEMBLER_NAME (current_function_decl);
362
363       warning_printed = 
364         warning_at (input_location, OPT_Wcoverage_mismatch, 
365                     "coverage mismatch for function "
366                     "%qE while reading counter %qs", id, ctr_names[counter]);
367       if (warning_printed)
368         {
369           if (entry->checksum != checksum)
370             inform (input_location, "checksum is %x instead of %x",
371                     entry->checksum, checksum);
372           else
373             inform (input_location, "number of counters is %d instead of %d",
374                     entry->summary.num, expected);
375           
376           if (!seen_error ()
377               && !warned++)
378             {
379               inform (input_location, "coverage mismatch ignored");
380               inform (input_location, flag_guess_branch_prob
381                       ? G_("execution counts estimated")
382                       : G_("execution counts assumed to be zero"));
383               if (!flag_guess_branch_prob)
384                 inform (input_location,
385                         "this can result in poorly optimized code");
386             }
387         }
388
389       return NULL;
390     }
391
392   if (summary)
393     *summary = &entry->summary;
394
395   return entry->counts;
396 }
397
398 /* Allocate NUM counters of type COUNTER. Returns nonzero if the
399    allocation succeeded.  */
400
401 int
402 coverage_counter_alloc (unsigned counter, unsigned num)
403 {
404   if (no_coverage)
405     return 0;
406
407   if (!num)
408     return 1;
409
410   if (!tree_ctr_tables[counter])
411     {
412       /* Generate and save a copy of this so it can be shared.  Leave
413          the index type unspecified for now; it will be set after all
414          functions have been compiled.  */
415       char buf[20];
416       tree gcov_type_node = get_gcov_type ();
417       tree gcov_type_array_type
418         = build_array_type (gcov_type_node, NULL_TREE);
419       tree_ctr_tables[counter]
420         = build_decl (BUILTINS_LOCATION,
421                       VAR_DECL, NULL_TREE, gcov_type_array_type);
422       TREE_STATIC (tree_ctr_tables[counter]) = 1;
423       ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
424       DECL_NAME (tree_ctr_tables[counter]) = get_identifier (buf);
425       DECL_ALIGN (tree_ctr_tables[counter]) = TYPE_ALIGN (gcov_type_node);
426
427       if (dump_file)
428         fprintf (dump_file, "Using data file %s\n", da_file_name);
429     }
430   fn_b_ctrs[counter] = fn_n_ctrs[counter];
431   fn_n_ctrs[counter] += num;
432   fn_ctr_mask |= 1 << counter;
433   return 1;
434 }
435
436 /* Generate a tree to access COUNTER NO.  */
437
438 tree
439 tree_coverage_counter_ref (unsigned counter, unsigned no)
440 {
441   tree gcov_type_node = get_gcov_type ();
442
443   gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
444   no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
445
446   /* "no" here is an array index, scaled to bytes later.  */
447   return build4 (ARRAY_REF, gcov_type_node, tree_ctr_tables[counter],
448                  build_int_cst (NULL_TREE, no), NULL, NULL);
449 }
450
451 /* Generate a tree to access the address of COUNTER NO.  */
452
453 tree
454 tree_coverage_counter_addr (unsigned counter, unsigned no)
455 {
456   tree gcov_type_node = get_gcov_type ();
457
458   gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
459   no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
460
461   TREE_ADDRESSABLE (tree_ctr_tables[counter]) = 1;
462
463   /* "no" here is an array index, scaled to bytes later.  */
464   return build_fold_addr_expr (build4 (ARRAY_REF, gcov_type_node,
465                                        tree_ctr_tables[counter],
466                                        build_int_cst (NULL_TREE, no),
467                                        NULL, NULL));
468 }
469 \f
470 /* Generate a checksum for a string.  CHKSUM is the current
471    checksum.  */
472
473 static unsigned
474 coverage_checksum_string (unsigned chksum, const char *string)
475 {
476   int i;
477   char *dup = NULL;
478
479   /* Look for everything that looks if it were produced by
480      get_file_function_name and zero out the second part
481      that may result from flag_random_seed.  This is not critical
482      as the checksums are used only for sanity checking.  */
483   for (i = 0; string[i]; i++)
484     {
485       int offset = 0;
486       if (!strncmp (string + i, "_GLOBAL__N_", 11))
487       offset = 11;
488       if (!strncmp (string + i, "_GLOBAL__", 9))
489       offset = 9;
490
491       /* C++ namespaces do have scheme:
492          _GLOBAL__N_<filename>_<wrongmagicnumber>_<magicnumber>functionname
493        since filename might contain extra underscores there seems
494        to be no better chance then walk all possible offsets looking
495        for magicnumber.  */
496       if (offset)
497         {
498           for (i = i + offset; string[i]; i++)
499             if (string[i]=='_')
500               {
501                 int y;
502
503                 for (y = 1; y < 9; y++)
504                   if (!(string[i + y] >= '0' && string[i + y] <= '9')
505                       && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
506                     break;
507                 if (y != 9 || string[i + 9] != '_')
508                   continue;
509                 for (y = 10; y < 18; y++)
510                   if (!(string[i + y] >= '0' && string[i + y] <= '9')
511                       && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
512                     break;
513                 if (y != 18)
514                   continue;
515                 if (!dup)
516                   string = dup = xstrdup (string);
517                 for (y = 10; y < 18; y++)
518                   dup[i + y] = '0';
519               }
520           break;
521         }
522     }
523
524   chksum = crc32_string (chksum, string);
525   if (dup)
526     free (dup);
527
528   return chksum;
529 }
530
531 /* Compute checksum for the current function.  We generate a CRC32.  */
532
533 static unsigned
534 compute_checksum (void)
535 {
536   expanded_location xloc
537     = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
538   unsigned chksum = xloc.line;
539
540   chksum = coverage_checksum_string (chksum, xloc.file);
541   chksum = coverage_checksum_string
542     (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
543
544   return chksum;
545 }
546 \f
547 /* Begin output to the graph file for the current function.
548    Opens the output file, if not already done. Writes the
549    function header, if not already done. Returns nonzero if data
550    should be output.  */
551
552 int
553 coverage_begin_output (void)
554 {
555   /* We don't need to output .gcno file unless we're under -ftest-coverage
556      (e.g. -fprofile-arcs/generate/use don't need .gcno to work). */
557   if (no_coverage || !flag_test_coverage || flag_compare_debug)
558     return 0;
559
560   if (!bbg_function_announced)
561     {
562       expanded_location xloc
563         = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
564       unsigned long offset;
565
566       if (!bbg_file_opened)
567         {
568           if (!gcov_open (bbg_file_name, -1))
569             error ("cannot open %s", bbg_file_name);
570           else
571             {
572               gcov_write_unsigned (GCOV_NOTE_MAGIC);
573               gcov_write_unsigned (GCOV_VERSION);
574               gcov_write_unsigned (local_tick);
575             }
576           bbg_file_opened = 1;
577         }
578
579       /* Announce function */
580       offset = gcov_write_tag (GCOV_TAG_FUNCTION);
581       gcov_write_unsigned (current_function_funcdef_no + 1);
582       gcov_write_unsigned (compute_checksum ());
583       gcov_write_string (IDENTIFIER_POINTER
584                          (DECL_ASSEMBLER_NAME (current_function_decl)));
585       gcov_write_string (xloc.file);
586       gcov_write_unsigned (xloc.line);
587       gcov_write_length (offset);
588
589       bbg_function_announced = 1;
590     }
591   return !gcov_is_error ();
592 }
593
594 /* Finish coverage data for the current function. Verify no output
595    error has occurred.  Save function coverage counts.  */
596
597 void
598 coverage_end_function (void)
599 {
600   unsigned i;
601
602   if (bbg_file_opened > 1 && gcov_is_error ())
603     {
604       warning (0, "error writing %qs", bbg_file_name);
605       bbg_file_opened = -1;
606     }
607
608   if (fn_ctr_mask)
609     {
610       struct function_list *item;
611
612       item = XNEW (struct function_list);
613
614       *functions_tail = item;
615       functions_tail = &item->next;
616
617       item->next = 0;
618       item->ident = current_function_funcdef_no + 1;
619       item->checksum = compute_checksum ();
620       for (i = 0; i != GCOV_COUNTERS; i++)
621         {
622           item->n_ctrs[i] = fn_n_ctrs[i];
623           prg_n_ctrs[i] += fn_n_ctrs[i];
624           fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
625         }
626       prg_ctr_mask |= fn_ctr_mask;
627       fn_ctr_mask = 0;
628     }
629   bbg_function_announced = 0;
630 }
631
632 /* Creates the gcov_fn_info RECORD_TYPE.  */
633
634 static tree
635 build_fn_info_type (unsigned int counters)
636 {
637   tree type = lang_hooks.types.make_type (RECORD_TYPE);
638   tree field, fields;
639   tree array_type;
640
641   /* ident */
642   fields = build_decl (BUILTINS_LOCATION,
643                        FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
644
645   /* checksum */
646   field = build_decl (BUILTINS_LOCATION,
647                       FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
648   DECL_CHAIN (field) = fields;
649   fields = field;
650
651   array_type = build_int_cst (NULL_TREE, counters - 1);
652   array_type = build_index_type (array_type);
653   array_type = build_array_type (get_gcov_unsigned_t (), array_type);
654
655   /* counters */
656   field = build_decl (BUILTINS_LOCATION,
657                       FIELD_DECL, NULL_TREE, array_type);
658   DECL_CHAIN (field) = fields;
659   fields = field;
660
661   finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
662
663   return type;
664 }
665
666 /* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
667    the function being processed and TYPE is the gcov_fn_info
668    RECORD_TYPE.  */
669
670 static tree
671 build_fn_info_value (const struct function_list *function, tree type)
672 {
673   tree fields = TYPE_FIELDS (type);
674   unsigned ix;
675   VEC(constructor_elt,gc) *v1 = NULL;
676   VEC(constructor_elt,gc) *v2 = NULL;
677
678   /* ident */
679   CONSTRUCTOR_APPEND_ELT (v1, fields,
680                           build_int_cstu (get_gcov_unsigned_t (),
681                                           function->ident));
682   fields = DECL_CHAIN (fields);
683
684   /* checksum */
685   CONSTRUCTOR_APPEND_ELT (v1, fields,
686                           build_int_cstu (get_gcov_unsigned_t (),
687                                           function->checksum));
688   fields = DECL_CHAIN (fields);
689
690   /* counters */
691   for (ix = 0; ix != GCOV_COUNTERS; ix++)
692     if (prg_ctr_mask & (1 << ix))
693       CONSTRUCTOR_APPEND_ELT (v2, NULL,
694                               build_int_cstu (get_gcov_unsigned_t (),
695                                               function->n_ctrs[ix]));
696
697   CONSTRUCTOR_APPEND_ELT (v1, fields,
698                           build_constructor (TREE_TYPE (fields), v2));
699
700   return build_constructor (type, v1);
701 }
702
703 /* Creates the gcov_ctr_info RECORD_TYPE.  */
704
705 static tree
706 build_ctr_info_type (void)
707 {
708   tree type = lang_hooks.types.make_type (RECORD_TYPE);
709   tree field, fields = NULL_TREE;
710   tree gcov_ptr_type = build_pointer_type (get_gcov_type ());
711   tree gcov_merge_fn_type;
712
713   /* counters */
714   field = build_decl (BUILTINS_LOCATION,
715                       FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
716   DECL_CHAIN (field) = fields;
717   fields = field;
718
719   /* values */
720   field = build_decl (BUILTINS_LOCATION,
721                       FIELD_DECL, NULL_TREE, gcov_ptr_type);
722   DECL_CHAIN (field) = fields;
723   fields = field;
724
725   /* merge */
726   gcov_merge_fn_type =
727     build_function_type_list (void_type_node,
728                               gcov_ptr_type, get_gcov_unsigned_t (),
729                               NULL_TREE);
730   field = build_decl (BUILTINS_LOCATION,
731                       FIELD_DECL, NULL_TREE,
732                       build_pointer_type (gcov_merge_fn_type));
733   DECL_CHAIN (field) = fields;
734   fields = field;
735
736   finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
737
738   return type;
739 }
740
741 /* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
742    the counter being processed and TYPE is the gcov_ctr_info
743    RECORD_TYPE.  */
744
745 static tree
746 build_ctr_info_value (unsigned int counter, tree type)
747 {
748   tree fields = TYPE_FIELDS (type);
749   tree fn;
750   VEC(constructor_elt,gc) *v = NULL;
751
752   /* counters */
753   CONSTRUCTOR_APPEND_ELT (v, fields,
754                           build_int_cstu (get_gcov_unsigned_t (),
755                                           prg_n_ctrs[counter]));
756   fields = DECL_CHAIN (fields);
757
758   if (prg_n_ctrs[counter])
759     {
760       tree array_type;
761
762       array_type = build_int_cstu (get_gcov_unsigned_t (),
763                                    prg_n_ctrs[counter] - 1);
764       array_type = build_index_type (array_type);
765       array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
766                                      array_type);
767
768       TREE_TYPE (tree_ctr_tables[counter]) = array_type;
769       DECL_SIZE (tree_ctr_tables[counter]) = TYPE_SIZE (array_type);
770       DECL_SIZE_UNIT (tree_ctr_tables[counter]) = TYPE_SIZE_UNIT (array_type);
771       varpool_finalize_decl (tree_ctr_tables[counter]);
772
773       CONSTRUCTOR_APPEND_ELT (v, fields,
774                               build1 (ADDR_EXPR, TREE_TYPE (fields),
775                                       tree_ctr_tables[counter]));
776     }
777   else
778     CONSTRUCTOR_APPEND_ELT (v, fields, null_pointer_node);
779   fields = DECL_CHAIN (fields);
780
781   fn = build_decl (BUILTINS_LOCATION,
782                    FUNCTION_DECL,
783                    get_identifier (ctr_merge_functions[counter]),
784                    TREE_TYPE (TREE_TYPE (fields)));
785   DECL_EXTERNAL (fn) = 1;
786   TREE_PUBLIC (fn) = 1;
787   DECL_ARTIFICIAL (fn) = 1;
788   TREE_NOTHROW (fn) = 1;
789   DECL_ASSEMBLER_NAME (fn);  /* Initialize assembler name so we can stream out. */
790   CONSTRUCTOR_APPEND_ELT (v, fields, build1 (ADDR_EXPR, TREE_TYPE (fields), fn));
791
792   return build_constructor (type, v);
793 }
794
795 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
796    CONSTRUCTOR.  */
797
798 static tree
799 build_gcov_info (void)
800 {
801   unsigned n_ctr_types, ix;
802   tree type, const_type;
803   tree fn_info_type, fn_info_value = NULL_TREE;
804   tree fn_info_ptr_type;
805   tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
806   tree field, fields = NULL_TREE;
807   tree filename_string;
808   int da_file_name_len;
809   unsigned n_fns;
810   const struct function_list *fn;
811   tree string_type;
812   VEC(constructor_elt,gc) *v1 = NULL;
813   VEC(constructor_elt,gc) *v2 = NULL;
814
815   /* Count the number of active counters.  */
816   for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
817     if (prg_ctr_mask & (1 << ix))
818       n_ctr_types++;
819
820   type = lang_hooks.types.make_type (RECORD_TYPE);
821   const_type = build_qualified_type (type, TYPE_QUAL_CONST);
822
823   /* Version ident */
824   field = build_decl (BUILTINS_LOCATION,
825                       FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
826   DECL_CHAIN (field) = fields;
827   fields = field;
828   CONSTRUCTOR_APPEND_ELT (v1, field,
829                           build_int_cstu (TREE_TYPE (field), GCOV_VERSION));
830
831   /* next -- NULL */
832   field = build_decl (BUILTINS_LOCATION,
833                       FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
834   DECL_CHAIN (field) = fields;
835   fields = field;
836   CONSTRUCTOR_APPEND_ELT (v1, field, null_pointer_node);
837
838   /* stamp */
839   field = build_decl (BUILTINS_LOCATION,
840                       FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
841   DECL_CHAIN (field) = fields;
842   fields = field;
843   CONSTRUCTOR_APPEND_ELT (v1, field,
844                           build_int_cstu (TREE_TYPE (field), local_tick));
845
846   /* Filename */
847   string_type = build_pointer_type (build_qualified_type (char_type_node,
848                                                     TYPE_QUAL_CONST));
849   field = build_decl (BUILTINS_LOCATION,
850                       FIELD_DECL, NULL_TREE, string_type);
851   DECL_CHAIN (field) = fields;
852   fields = field;
853   da_file_name_len = strlen (da_file_name);
854   filename_string = build_string (da_file_name_len + 1, da_file_name);
855   TREE_TYPE (filename_string) = build_array_type
856     (char_type_node, build_index_type
857      (build_int_cst (NULL_TREE, da_file_name_len)));
858   CONSTRUCTOR_APPEND_ELT (v1, field,
859                           build1 (ADDR_EXPR, string_type, filename_string));
860
861   /* Build the fn_info type and initializer.  */
862   fn_info_type = build_fn_info_type (n_ctr_types);
863   fn_info_ptr_type = build_pointer_type (build_qualified_type
864                                          (fn_info_type, TYPE_QUAL_CONST));
865   for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
866     CONSTRUCTOR_APPEND_ELT (v2, NULL_TREE,
867                             build_fn_info_value (fn, fn_info_type));
868
869   if (n_fns)
870     {
871       tree array_type;
872
873       array_type = build_index_type (build_int_cst (NULL_TREE, n_fns - 1));
874       array_type = build_array_type (fn_info_type, array_type);
875
876       fn_info_value = build_constructor (array_type, v2);
877       fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
878     }
879   else
880     fn_info_value = null_pointer_node;
881
882   /* number of functions */
883   field = build_decl (BUILTINS_LOCATION,
884                       FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
885   DECL_CHAIN (field) = fields;
886   fields = field;
887   CONSTRUCTOR_APPEND_ELT (v1, field,
888                           build_int_cstu (get_gcov_unsigned_t (), n_fns));
889
890   /* fn_info table */
891   field = build_decl (BUILTINS_LOCATION,
892                       FIELD_DECL, NULL_TREE, fn_info_ptr_type);
893   DECL_CHAIN (field) = fields;
894   fields = field;
895   CONSTRUCTOR_APPEND_ELT (v1, field, fn_info_value);
896
897   /* counter_mask */
898   field = build_decl (BUILTINS_LOCATION,
899                       FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
900   DECL_CHAIN (field) = fields;
901   fields = field;
902   CONSTRUCTOR_APPEND_ELT (v1, field, 
903                           build_int_cstu (get_gcov_unsigned_t (),
904                                           prg_ctr_mask));
905
906   /* counters */
907   ctr_info_type = build_ctr_info_type ();
908   ctr_info_ary_type = build_index_type (build_int_cst (NULL_TREE,
909                                                        n_ctr_types));
910   ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
911   v2 = NULL;
912   for (ix = 0; ix != GCOV_COUNTERS; ix++)
913     if (prg_ctr_mask & (1 << ix))
914       CONSTRUCTOR_APPEND_ELT (v2, NULL_TREE,
915                               build_ctr_info_value (ix, ctr_info_type));
916   ctr_info_value = build_constructor (ctr_info_ary_type, v2);
917
918   field = build_decl (BUILTINS_LOCATION,
919                       FIELD_DECL, NULL_TREE, ctr_info_ary_type);
920   DECL_CHAIN (field) = fields;
921   fields = field;
922   CONSTRUCTOR_APPEND_ELT (v1, field, ctr_info_value);
923
924   finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
925
926   return build_constructor (type, v1);
927 }
928
929 /* Write out the structure which libgcov uses to locate all the
930    counters.  The structures used here must match those defined in
931    gcov-io.h.  Write out the constructor to call __gcov_init.  */
932
933 static void
934 create_coverage (void)
935 {
936   tree gcov_info, gcov_init, body, t;
937   char name_buf[32];
938
939   no_coverage = 1; /* Disable any further coverage.  */
940
941   if (!prg_ctr_mask)
942     return;
943
944   t = build_gcov_info ();
945
946   gcov_info = build_decl (BUILTINS_LOCATION,
947                           VAR_DECL, NULL_TREE, TREE_TYPE (t));
948   TREE_STATIC (gcov_info) = 1;
949   ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
950   DECL_NAME (gcov_info) = get_identifier (name_buf);
951   DECL_INITIAL (gcov_info) = t;
952
953   /* Build structure.  */
954   varpool_finalize_decl (gcov_info);
955
956   /* Build a decl for __gcov_init.  */
957   t = build_pointer_type (TREE_TYPE (gcov_info));
958   t = build_function_type_list (void_type_node, t, NULL);
959   t = build_decl (BUILTINS_LOCATION,
960                   FUNCTION_DECL, get_identifier ("__gcov_init"), t);
961   TREE_PUBLIC (t) = 1;
962   DECL_EXTERNAL (t) = 1;
963   DECL_ASSEMBLER_NAME (t);  /* Initialize assembler name so we can stream out. */
964   gcov_init = t;
965
966   /* Generate a call to __gcov_init(&gcov_info).  */
967   body = NULL;
968   t = build_fold_addr_expr (gcov_info);
969   t = build_call_expr (gcov_init, 1, t);
970   append_to_statement_list (t, &body);
971
972   /* Generate a constructor to run it.  */
973   cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
974 }
975 \f
976 /* Perform file-level initialization. Read in data file, generate name
977    of graph file.  */
978
979 void
980 coverage_init (const char *filename)
981 {
982   int len = strlen (filename);
983   /* + 1 for extra '/', in case prefix doesn't end with /.  */
984   int prefix_len;
985
986   if (profile_data_prefix == 0 && !IS_ABSOLUTE_PATH(&filename[0]))
987     profile_data_prefix = getpwd ();
988
989   prefix_len = (profile_data_prefix) ? strlen (profile_data_prefix) + 1 : 0;
990
991   /* Name of da file.  */
992   da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX)
993                           + prefix_len + 1);
994
995   if (profile_data_prefix)
996     {
997       strcpy (da_file_name, profile_data_prefix);
998       da_file_name[prefix_len - 1] = '/';
999       da_file_name[prefix_len] = 0;
1000     }
1001   else
1002     da_file_name[0] = 0;
1003   strcat (da_file_name, filename);
1004   strcat (da_file_name, GCOV_DATA_SUFFIX);
1005
1006   /* Name of bbg file.  */
1007   bbg_file_name = XNEWVEC (char, len + strlen (GCOV_NOTE_SUFFIX) + 1);
1008   strcpy (bbg_file_name, filename);
1009   strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
1010
1011   if (flag_profile_use)
1012     read_counts_file ();
1013 }
1014
1015 /* Performs file-level cleanup.  Close graph file, generate coverage
1016    variables and constructor.  */
1017
1018 void
1019 coverage_finish (void)
1020 {
1021   create_coverage ();
1022   if (bbg_file_opened)
1023     {
1024       int error = gcov_close ();
1025
1026       if (error)
1027         unlink (bbg_file_name);
1028       if (!local_tick)
1029         /* Only remove the da file, if we cannot stamp it. If we can
1030            stamp it, libgcov will DTRT.  */
1031         unlink (da_file_name);
1032     }
1033 }
1034
1035 #include "gt-coverage.h"