OSDN Git Service

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