OSDN Git Service

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