OSDN Git Service

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