OSDN Git Service

05e18149c511221ecd11f8aa3c1d634ac24e1bd4
[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  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 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 ("file %s not found, execution counts assumed to be zero",
320                 da_file_name);
321       return NULL;
322     }
323
324   elt.ident = current_function_funcdef_no + 1;
325   elt.ctr = counter;
326   entry = htab_find (counts_hash, &elt);
327   if (!entry)
328     {
329       warning ("no coverage for function '%s' found.", IDENTIFIER_POINTER
330                (DECL_ASSEMBLER_NAME (current_function_decl)));
331       return 0;
332     }
333
334   checksum = compute_checksum ();
335   if (entry->checksum != checksum)
336     {
337       error ("coverage mismatch for function '%s' while reading counter '%s'.",
338              IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
339              ctr_names[counter]);
340       error ("checksum is %x instead of %x", entry->checksum, checksum);
341       return 0;
342     }
343   else if (entry->summary.num != expected)
344     {
345       error ("coverage mismatch for function '%s' while reading counter '%s'.",
346              IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
347              ctr_names[counter]);
348       error ("number of counters is %d instead of %d", entry->summary.num, expected);
349       return 0;
350     }
351
352   if (summary)
353     *summary = &entry->summary;
354
355   return entry->counts;
356 }
357
358 /* Allocate NUM counters of type COUNTER. Returns nonzero if the
359    allocation succeeded.  */
360
361 int
362 coverage_counter_alloc (unsigned counter, unsigned num)
363 {
364   if (no_coverage)
365     return 0;
366
367   if (!num)
368     return 1;
369
370   if (!ctr_labels[counter])
371     {
372       /* Generate and save a copy of this so it can be shared.  */
373       char buf[20];
374
375       ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
376       ctr_labels[counter] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
377       SYMBOL_REF_FLAGS (ctr_labels[counter]) = SYMBOL_FLAG_LOCAL;
378     }
379   fn_b_ctrs[counter] = fn_n_ctrs[counter];
380   fn_n_ctrs[counter] += num;
381   fn_ctr_mask |= 1 << counter;
382   return 1;
383 }
384
385 /* Generate a MEM rtl to access COUNTER NO.  */
386
387 rtx
388 coverage_counter_ref (unsigned counter, unsigned no)
389 {
390   unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
391   enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
392   rtx ref;
393
394   if (no >= fn_n_ctrs[counter] - fn_b_ctrs[counter])
395     abort ();
396   no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
397   ref = plus_constant (ctr_labels[counter], gcov_size / BITS_PER_UNIT * no);
398   ref = gen_rtx_MEM (mode, ref);
399   set_mem_alias_set (ref, new_alias_set ());
400
401   return ref;
402 }
403 \f
404 /* Generate a checksum for a string.  CHKSUM is the current
405    checksum.  */
406
407 static unsigned
408 checksum_string (unsigned chksum, const char *string)
409 {
410   do
411     {
412       unsigned value = *string << 24;
413       unsigned ix;
414
415       for (ix = 8; ix--; value <<= 1)
416         {
417           unsigned feedback;
418
419           feedback = (value ^ chksum) & 0x80000000 ? 0x04c11db7 : 0;
420           chksum <<= 1;
421           chksum ^= feedback;
422         }
423     }
424   while (*string++);
425
426   return chksum;
427 }
428
429 /* Compute checksum for the current function.  We generate a CRC32.  */
430
431 static unsigned
432 compute_checksum (void)
433 {
434   unsigned chksum = DECL_SOURCE_LINE (current_function_decl);
435
436   chksum = checksum_string (chksum, DECL_SOURCE_FILE (current_function_decl));
437   chksum = checksum_string
438     (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
439
440   return chksum;
441 }
442 \f
443 /* Begin output to the graph file for the current function.
444    Opens the output file, if not already done. Writes the
445    function header, if not already done. Returns nonzero if data
446    should be output.  */
447
448 int
449 coverage_begin_output (void)
450 {
451   if (no_coverage)
452     return 0;
453
454   if (!bbg_function_announced)
455     {
456       const char *file = DECL_SOURCE_FILE (current_function_decl);
457       unsigned line = DECL_SOURCE_LINE (current_function_decl);
458       unsigned long offset;
459
460       if (!bbg_file_opened)
461         {
462           if (!gcov_open (bbg_file_name, -1))
463             error ("cannot open %s", bbg_file_name);
464           else
465             {
466               gcov_write_unsigned (GCOV_NOTE_MAGIC);
467               gcov_write_unsigned (GCOV_VERSION);
468               gcov_write_unsigned (local_tick);
469             }
470           bbg_file_opened = 1;
471         }
472
473       /* Announce function */
474       offset = gcov_write_tag (GCOV_TAG_FUNCTION);
475       gcov_write_unsigned (current_function_funcdef_no + 1);
476       gcov_write_unsigned (compute_checksum ());
477       gcov_write_string (IDENTIFIER_POINTER
478                          (DECL_ASSEMBLER_NAME (current_function_decl)));
479       gcov_write_string (file);
480       gcov_write_unsigned (line);
481       gcov_write_length (offset);
482
483       bbg_function_announced = 1;
484     }
485   return !gcov_is_error ();
486 }
487
488 /* Finish coverage data for the current function. Verify no output
489    error has occurred.  Save function coverage counts.  */
490
491 void
492 coverage_end_function (void)
493 {
494   unsigned i;
495
496   if (bbg_file_opened > 1 && gcov_is_error ())
497     {
498       warning ("error writing `%s'", bbg_file_name);
499       bbg_file_opened = -1;
500     }
501
502   if (fn_ctr_mask)
503     {
504       struct function_list *item;
505
506       item = xmalloc (sizeof (struct function_list));
507
508       *functions_tail = item;
509       functions_tail = &item->next;
510
511       item->next = 0;
512       item->ident = current_function_funcdef_no + 1;
513       item->checksum = compute_checksum ();
514       for (i = 0; i != GCOV_COUNTERS; i++)
515         {
516           item->n_ctrs[i] = fn_n_ctrs[i];
517           prg_n_ctrs[i] += fn_n_ctrs[i];
518           fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
519         }
520       prg_ctr_mask |= fn_ctr_mask;
521       fn_ctr_mask = 0;
522     }
523   bbg_function_announced = 0;
524 }
525
526 /* Creates the gcov_fn_info RECORD_TYPE.  */
527
528 static tree
529 build_fn_info_type (unsigned int counters)
530 {
531   tree type = (*lang_hooks.types.make_type) (RECORD_TYPE);
532   tree field, fields;
533   tree array_type;
534
535   /* ident */
536   fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
537
538   /* checksum */
539   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
540   TREE_CHAIN (field) = fields;
541   fields = field;
542
543   array_type = build_index_type (build_int_2 (counters - 1, 0));
544   array_type = build_array_type (unsigned_type_node, array_type);
545
546   /* counters */
547   field = build_decl (FIELD_DECL, NULL_TREE, array_type);
548   TREE_CHAIN (field) = fields;
549   fields = field;
550
551   finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
552
553   return type;
554 }
555
556 /* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
557    the function being processed and TYPE is the gcov_fn_info
558    RECORD_TYPE.  */
559
560 static tree
561 build_fn_info_value (const struct function_list *function, tree type)
562 {
563   tree value = NULL_TREE;
564   tree fields = TYPE_FIELDS (type);
565   unsigned ix;
566   tree array_value = NULL_TREE;
567
568   /* ident */
569   value = tree_cons (fields,
570                      convert (unsigned_intSI_type_node,
571                               build_int_2 (function->ident, 0)),
572                      value);
573   fields = TREE_CHAIN (fields);
574
575   /* checksum */
576   value = tree_cons (fields,
577                      convert (unsigned_intSI_type_node,
578                               build_int_2 (function->checksum, 0)),
579                      value);
580   fields = TREE_CHAIN (fields);
581
582   /* counters */
583   for (ix = 0; ix != GCOV_COUNTERS; ix++)
584     if (prg_ctr_mask & (1 << ix))
585       {
586         tree counters = convert (unsigned_type_node,
587                                  build_int_2 (function->n_ctrs[ix], 0));
588
589         array_value = tree_cons (NULL_TREE, counters, array_value);
590       }
591
592   array_value = build_constructor (TREE_TYPE (fields), nreverse (array_value));
593   value = tree_cons (fields, array_value, value);
594
595   value = build_constructor (type, nreverse (value));
596
597   return value;
598 }
599
600 /* Creates the gcov_ctr_info RECORD_TYPE.  */
601
602 static tree
603 build_ctr_info_type (void)
604 {
605   tree type = (*lang_hooks.types.make_type) (RECORD_TYPE);
606   tree field, fields = NULL_TREE;
607   tree gcov_ptr_type = build_pointer_type (GCOV_TYPE_NODE);
608   tree gcov_merge_fn_type;
609
610   /* counters */
611   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
612   TREE_CHAIN (field) = fields;
613   fields = field;
614
615   /* values */
616   field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
617   TREE_CHAIN (field) = fields;
618   fields = field;
619
620   /* merge */
621   gcov_merge_fn_type =
622     build_function_type_list (void_type_node,
623                               gcov_ptr_type, unsigned_type_node,
624                               NULL_TREE);
625   field = build_decl (FIELD_DECL, NULL_TREE,
626                       build_pointer_type (gcov_merge_fn_type));
627   TREE_CHAIN (field) = fields;
628   fields = field;
629
630   finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
631
632   return type;
633 }
634
635 /* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
636    the counter being processed and TYPE is the gcov_ctr_info
637    RECORD_TYPE.  */
638
639 static tree
640 build_ctr_info_value (unsigned int counter, tree type)
641 {
642   tree value = NULL_TREE;
643   tree fields = TYPE_FIELDS (type);
644   tree fn;
645
646   /* counters */
647   value = tree_cons (fields,
648                      convert (unsigned_intSI_type_node,
649                               build_int_2 (prg_n_ctrs[counter], 0)),
650                      value);
651   fields = TREE_CHAIN (fields);
652
653   if (prg_n_ctrs[counter])
654     {
655       tree array_type, array;
656
657       array_type = build_index_type (build_int_2 (prg_n_ctrs[counter] - 1, 0));
658       array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
659                                      array_type);
660
661       array = build_decl (VAR_DECL, NULL_TREE, array_type);
662       TREE_STATIC (array) = 1;
663       DECL_NAME (array) = get_identifier (XSTR (ctr_labels[counter], 0));
664       assemble_variable (array, 0, 0, 0);
665
666       value = tree_cons (fields,
667                          build1 (ADDR_EXPR, TREE_TYPE (fields), array),
668                          value);
669     }
670   else
671     value = tree_cons (fields, null_pointer_node, value);
672   fields = TREE_CHAIN (fields);
673
674   fn = build_decl (FUNCTION_DECL,
675                    get_identifier (ctr_merge_functions[counter]),
676                    TREE_TYPE (TREE_TYPE (fields)));
677   DECL_EXTERNAL (fn) = 1;
678   TREE_PUBLIC (fn) = 1;
679   DECL_ARTIFICIAL (fn) = 1;
680   TREE_NOTHROW (fn) = 1;
681   value = tree_cons (fields,
682                      build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
683                      value);
684
685   value = build_constructor (type, nreverse (value));
686
687   return value;
688 }
689
690 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
691    CONSTRUCTOR.  */
692
693 static tree
694 build_gcov_info (void)
695 {
696   unsigned n_ctr_types, ix;
697   tree type, const_type;
698   tree fn_info_type, fn_info_value = NULL_TREE;
699   tree fn_info_ptr_type;
700   tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
701   tree field, fields = NULL_TREE;
702   tree value = NULL_TREE;
703   tree filename_string;
704   char *filename;
705   int filename_len;
706   unsigned n_fns;
707   const struct function_list *fn;
708   tree string_type;
709
710   /* Count the number of active counters.  */
711   for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
712     if (prg_ctr_mask & (1 << ix))
713       n_ctr_types++;
714
715   type = (*lang_hooks.types.make_type) (RECORD_TYPE);
716   const_type = build_qualified_type (type, TYPE_QUAL_CONST);
717
718   /* Version ident */
719   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
720   TREE_CHAIN (field) = fields;
721   fields = field;
722   value = tree_cons (field, convert (unsigned_intSI_type_node,
723                                      build_int_2 (GCOV_VERSION, 0)),
724                      value);
725
726   /* next -- NULL */
727   field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
728   TREE_CHAIN (field) = fields;
729   fields = field;
730   value = tree_cons (field, null_pointer_node, value);
731
732   /* stamp */
733   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
734   TREE_CHAIN (field) = fields;
735   fields = field;
736   value = tree_cons (field, convert (unsigned_intSI_type_node,
737                                      build_int_2 (local_tick, 0)),
738                      value);
739
740   /* Filename */
741   string_type = build_pointer_type (build_qualified_type (char_type_node,
742                                                     TYPE_QUAL_CONST));
743   field = build_decl (FIELD_DECL, NULL_TREE, string_type);
744   TREE_CHAIN (field) = fields;
745   fields = field;
746   filename = getpwd ();
747   filename = (filename && da_file_name[0] != '/'
748               ? concat (filename, "/", da_file_name, NULL)
749               : da_file_name);
750   filename_len = strlen (filename);
751   filename_string = build_string (filename_len + 1, filename);
752   if (filename != da_file_name)
753     free (filename);
754   TREE_TYPE (filename_string) =
755           build_array_type (char_type_node,
756                             build_index_type (build_int_2 (filename_len, 0)));
757   value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
758                      value);
759
760   /* Build the fn_info type and initializer.  */
761   fn_info_type = build_fn_info_type (n_ctr_types);
762   fn_info_ptr_type = build_pointer_type (build_qualified_type
763                                          (fn_info_type, TYPE_QUAL_CONST));
764   for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
765     fn_info_value = tree_cons (NULL_TREE,
766                                build_fn_info_value (fn, fn_info_type),
767                                fn_info_value);
768   if (n_fns)
769     {
770       tree array_type;
771
772       array_type = build_index_type (build_int_2 (n_fns - 1, 0));
773       array_type = build_array_type (fn_info_type, array_type);
774
775       fn_info_value = build_constructor (array_type, nreverse (fn_info_value));
776       fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
777     }
778   else
779     fn_info_value = null_pointer_node;
780
781   /* number of functions */
782   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
783   TREE_CHAIN (field) = fields;
784   fields = field;
785   value = tree_cons (field,
786                      convert (unsigned_type_node, build_int_2 (n_fns, 0)),
787                      value);
788
789   /* fn_info table */
790   field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type);
791   TREE_CHAIN (field) = fields;
792   fields = field;
793   value = tree_cons (field, fn_info_value, value);
794
795   /* counter_mask */
796   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
797   TREE_CHAIN (field) = fields;
798   fields = field;
799   value = tree_cons (field,
800                      convert (unsigned_type_node,
801                               build_int_2 (prg_ctr_mask, 0)),
802                      value);
803
804   /* counters */
805   ctr_info_type = build_ctr_info_type ();
806   ctr_info_ary_type = build_index_type (build_int_2 (n_ctr_types, 0));
807   ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
808   for (ix = 0; ix != GCOV_COUNTERS; ix++)
809     if (prg_ctr_mask & (1 << ix))
810       ctr_info_value = tree_cons (NULL_TREE,
811                                   build_ctr_info_value (ix, ctr_info_type),
812                                   ctr_info_value);
813   ctr_info_value = build_constructor (ctr_info_ary_type,
814                                       nreverse (ctr_info_value));
815
816   field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
817   TREE_CHAIN (field) = fields;
818   fields = field;
819   value = tree_cons (field, ctr_info_value, value);
820
821   finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
822
823   value = build_constructor (type, nreverse (value));
824
825   return value;
826 }
827
828 /* Write out the structure which libgcov uses to locate all the
829    counters.  The structures used here must match those defined in
830    gcov-io.h.  Write out the constructor to call __gcov_init.  */
831
832 static void
833 create_coverage (void)
834 {
835   tree gcov_info, gcov_info_value;
836   char name[20];
837   char *ctor_name;
838   tree ctor;
839   rtx gcov_info_address;
840
841   no_coverage = 1; /* Disable any further coverage.  */
842
843   if (!prg_ctr_mask)
844     return;
845
846   gcov_info_value = build_gcov_info ();
847
848   gcov_info = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (gcov_info_value));
849   DECL_INITIAL (gcov_info) = gcov_info_value;
850
851   TREE_STATIC (gcov_info) = 1;
852   ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 0);
853   DECL_NAME (gcov_info) = get_identifier (name);
854
855   /* Build structure.  */
856   assemble_variable (gcov_info, 0, 0, 0);
857
858   /* Build the constructor function to invoke __gcov_init.  */
859   ctor_name = concat (IDENTIFIER_POINTER (get_file_function_name ('I')),
860                       "_GCOV", NULL);
861   ctor = build_decl (FUNCTION_DECL, get_identifier (ctor_name),
862                      build_function_type (void_type_node, NULL_TREE));
863   free (ctor_name);
864   DECL_EXTERNAL (ctor) = 0;
865
866   /* It can be a static function as long as collect2 does not have
867      to scan the object file to find its ctor/dtor routine.  */
868   TREE_PUBLIC (ctor) = ! targetm.have_ctors_dtors;
869   TREE_USED (ctor) = 1;
870   DECL_RESULT (ctor) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
871   DECL_UNINLINABLE (ctor) = 1;
872
873   ctor = (*lang_hooks.decls.pushdecl) (ctor);
874   rest_of_decl_compilation (ctor, 0, 1, 0);
875   announce_function (ctor);
876   current_function_decl = ctor;
877   make_decl_rtl (ctor, NULL);
878   init_function_start (ctor);
879   expand_function_start (ctor, 0);
880   /* Actually generate the code to call __gcov_init.  */
881   gcov_info_address = force_reg (Pmode, XEXP (DECL_RTL (gcov_info), 0));
882   emit_library_call (gcov_init_libfunc, LCT_NORMAL, VOIDmode, 1,
883                      gcov_info_address, Pmode);
884
885   expand_function_end ();
886   /* Create a dummy BLOCK.  */
887   DECL_INITIAL (ctor) = make_node (BLOCK);
888   TREE_USED (DECL_INITIAL (ctor)) = 1;
889
890   rest_of_compilation (ctor);
891
892   if (! quiet_flag)
893     fflush (asm_out_file);
894   current_function_decl = NULL_TREE;
895
896   if (targetm.have_ctors_dtors)
897     (* targetm.asm_out.constructor) (XEXP (DECL_RTL (ctor), 0),
898                                      DEFAULT_INIT_PRIORITY);
899 }
900 \f
901 /* Perform file-level initialization. Read in data file, generate name
902    of graph file.  */
903
904 void
905 coverage_init (const char *filename)
906 {
907   int len = strlen (filename);
908
909   /* Name of da file.  */
910   da_file_name = xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1);
911   strcpy (da_file_name, filename);
912   strcat (da_file_name, GCOV_DATA_SUFFIX);
913
914   /* Name of bbg file.  */
915   bbg_file_name = xmalloc (len + strlen (GCOV_NOTE_SUFFIX) + 1);
916   strcpy (bbg_file_name, filename);
917   strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
918
919   read_counts_file ();
920 }
921
922 /* Performs file-level cleanup.  Close graph file, generate coverage
923    variables and constructor.  */
924
925 void
926 coverage_finish (void)
927 {
928   create_coverage ();
929   if (bbg_file_opened)
930     {
931       int error = gcov_close ();
932
933       if (error)
934         unlink (bbg_file_name);
935       if (!local_tick)
936         /* Only remove the da file, if we cannot stamp it. If we can
937            stamp it, libgcov will DTRT.  */
938         unlink (da_file_name);
939     }
940 }
941
942 #include "gt-coverage.h"