OSDN Git Service

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