OSDN Git Service

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