OSDN Git Service

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