OSDN Git Service

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