coverage.c revision 132718
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
9This file is part of GCC.
10
11GCC is free software; you can redistribute it and/or modify it under
12the terms of the GNU General Public License as published by the Free
13Software Foundation; either version 2, or (at your option) any later
14version.
15
16GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17WARRANTY; without even the implied warranty of MERCHANTABILITY or
18FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19for more details.
20
21You should have received a copy of the GNU General Public License
22along with GCC; see the file COPYING.  If not, write to the Free
23Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2402111-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
50struct 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.  */
59typedef 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
75static struct function_list *functions_head = 0;
76static struct function_list **functions_tail = &functions_head;
77static unsigned no_coverage = 0;
78
79/* Cumulative counter information for whole program.  */
80static unsigned prg_ctr_mask; /* Mask of counter types generated.  */
81static unsigned prg_n_ctrs[GCOV_COUNTERS]; /* Total counters allocated.  */
82
83/* Counter information for current function.  */
84static unsigned fn_ctr_mask; /* Mask of counters used.  */
85static unsigned fn_n_ctrs[GCOV_COUNTERS]; /* Counters allocated.  */
86static unsigned fn_b_ctrs[GCOV_COUNTERS]; /* Allocation base.  */
87
88/* Name of the output file for coverage output file.  */
89static char *bbg_file_name;
90static unsigned bbg_file_opened;
91static int bbg_function_announced;
92
93/* Name of the count data file.  */
94static char *da_file_name;
95
96/* Hash table of count data.  */
97static htab_t counts_hash = NULL;
98
99/* The names of the counter tables.  */
100static GTY(()) rtx ctr_labels[GCOV_COUNTERS];
101
102/* The names of merge functions for counters.  */
103static const char *const ctr_merge_functions[GCOV_COUNTERS] = GCOV_MERGE_FUNCTIONS;
104static const char *const ctr_names[GCOV_COUNTERS] = GCOV_COUNTER_NAMES;
105
106/* Forward declarations.  */
107static hashval_t htab_counts_entry_hash (const void *);
108static int htab_counts_entry_eq (const void *, const void *);
109static void htab_counts_entry_del (void *);
110static void read_counts_file (void);
111static unsigned compute_checksum (void);
112static unsigned coverage_checksum_string (unsigned, const char *);
113static tree build_fn_info_type (unsigned);
114static tree build_fn_info_value (const struct function_list *, tree);
115static tree build_ctr_info_type (void);
116static tree build_ctr_info_value (unsigned, tree);
117static tree build_gcov_info (void);
118static void create_coverage (void);
119
120
121static hashval_t
122htab_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
129static int
130htab_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
138static void
139htab_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
149static void
150read_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
306gcov_type *
307get_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 ("file %s not found, execution counts assumed to be zero",
320		da_file_name);
321      return NULL;
322    }
323
324  elt.ident = current_function_funcdef_no + 1;
325  elt.ctr = counter;
326  entry = htab_find (counts_hash, &elt);
327  if (!entry)
328    {
329      warning ("no coverage for function '%s' found.", IDENTIFIER_POINTER
330	       (DECL_ASSEMBLER_NAME (current_function_decl)));
331      return 0;
332    }
333
334  checksum = compute_checksum ();
335  if (entry->checksum != checksum)
336    {
337      error ("coverage mismatch for function '%s' while reading counter '%s'.",
338	     IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
339	     ctr_names[counter]);
340      error ("checksum is %x instead of %x", entry->checksum, checksum);
341      return 0;
342    }
343  else if (entry->summary.num != expected)
344    {
345      error ("coverage mismatch for function '%s' while reading counter '%s'.",
346	     IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
347	     ctr_names[counter]);
348      error ("number of counters is %d instead of %d", entry->summary.num, expected);
349      return 0;
350    }
351
352  if (summary)
353    *summary = &entry->summary;
354
355  return entry->counts;
356}
357
358/* Allocate NUM counters of type COUNTER. Returns nonzero if the
359   allocation succeeded.  */
360
361int
362coverage_counter_alloc (unsigned counter, unsigned num)
363{
364  if (no_coverage)
365    return 0;
366
367  if (!num)
368    return 1;
369
370  if (!ctr_labels[counter])
371    {
372      /* Generate and save a copy of this so it can be shared.  */
373      char buf[20];
374
375      ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
376      ctr_labels[counter] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
377      SYMBOL_REF_FLAGS (ctr_labels[counter]) = SYMBOL_FLAG_LOCAL;
378    }
379  fn_b_ctrs[counter] = fn_n_ctrs[counter];
380  fn_n_ctrs[counter] += num;
381  fn_ctr_mask |= 1 << counter;
382  return 1;
383}
384
385/* Generate a MEM rtl to access COUNTER NO.  */
386
387rtx
388coverage_counter_ref (unsigned counter, unsigned no)
389{
390  unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
391  enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
392  rtx ref;
393
394  if (no >= fn_n_ctrs[counter] - fn_b_ctrs[counter])
395    abort ();
396  no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
397  ref = plus_constant (ctr_labels[counter], gcov_size / BITS_PER_UNIT * no);
398  ref = gen_rtx_MEM (mode, ref);
399  set_mem_alias_set (ref, new_alias_set ());
400  MEM_NOTRAP_P (ref) = 1;
401
402  return ref;
403}
404
405/* Generate a checksum for a string.  CHKSUM is the current
406   checksum.  */
407
408static unsigned
409coverage_checksum_string (unsigned chksum, const char *string)
410{
411  int i;
412  char *dup = NULL;
413
414  /* Look for everything that looks if it were produced by
415     get_file_function_name_long and zero out the second part
416     that may result from flag_random_seed.  This is not critical
417     as the checksums are used only for sanity checking.  */
418  for (i = 0; string[i]; i++)
419    {
420      if (!strncmp (string + i, "_GLOBAL__", 9))
421	for (i = i + 9; string[i]; i++)
422	  if (string[i]=='_')
423	    {
424	      int y;
425	      unsigned seed;
426
427	      for (y = 1; y < 9; y++)
428		if (!(string[i + y] >= '0' && string[i + y] <= '9')
429		    && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
430		  break;
431	      if (y != 9 || string[i + 9] != '_')
432		continue;
433	      for (y = 10; y < 18; y++)
434		if (!(string[i + y] >= '0' && string[i + y] <= '9')
435		    && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
436		  break;
437	      if (y != 18)
438		continue;
439	      if (!sscanf (string + i + 10, "%X", &seed))
440		abort ();
441	      if (seed != crc32_string (0, flag_random_seed))
442		continue;
443	      string = dup = xstrdup (string);
444	      for (y = 10; y < 18; y++)
445		dup[i + y] = '0';
446	      break;
447	    }
448      break;
449    }
450
451  chksum = crc32_string (chksum, string);
452  if (dup)
453    free (dup);
454
455  return chksum;
456}
457
458/* Compute checksum for the current function.  We generate a CRC32.  */
459
460static unsigned
461compute_checksum (void)
462{
463  unsigned chksum = DECL_SOURCE_LINE (current_function_decl);
464
465  chksum = coverage_checksum_string (chksum,
466      				     DECL_SOURCE_FILE (current_function_decl));
467  chksum = coverage_checksum_string
468    (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
469
470  return chksum;
471}
472
473/* Begin output to the graph file for the current function.
474   Opens the output file, if not already done. Writes the
475   function header, if not already done. Returns nonzero if data
476   should be output.  */
477
478int
479coverage_begin_output (void)
480{
481  if (no_coverage)
482    return 0;
483
484  if (!bbg_function_announced)
485    {
486      const char *file = DECL_SOURCE_FILE (current_function_decl);
487      unsigned line = DECL_SOURCE_LINE (current_function_decl);
488      unsigned long offset;
489
490      if (!bbg_file_opened)
491	{
492	  if (!gcov_open (bbg_file_name, -1))
493	    error ("cannot open %s", bbg_file_name);
494	  else
495	    {
496	      gcov_write_unsigned (GCOV_NOTE_MAGIC);
497	      gcov_write_unsigned (GCOV_VERSION);
498	      gcov_write_unsigned (local_tick);
499	    }
500	  bbg_file_opened = 1;
501	}
502
503      /* Announce function */
504      offset = gcov_write_tag (GCOV_TAG_FUNCTION);
505      gcov_write_unsigned (current_function_funcdef_no + 1);
506      gcov_write_unsigned (compute_checksum ());
507      gcov_write_string (IDENTIFIER_POINTER
508			 (DECL_ASSEMBLER_NAME (current_function_decl)));
509      gcov_write_string (file);
510      gcov_write_unsigned (line);
511      gcov_write_length (offset);
512
513      bbg_function_announced = 1;
514    }
515  return !gcov_is_error ();
516}
517
518/* Finish coverage data for the current function. Verify no output
519   error has occurred.  Save function coverage counts.  */
520
521void
522coverage_end_function (void)
523{
524  unsigned i;
525
526  if (bbg_file_opened > 1 && gcov_is_error ())
527    {
528      warning ("error writing `%s'", bbg_file_name);
529      bbg_file_opened = -1;
530    }
531
532  if (fn_ctr_mask)
533    {
534      struct function_list *item;
535
536      item = xmalloc (sizeof (struct function_list));
537
538      *functions_tail = item;
539      functions_tail = &item->next;
540
541      item->next = 0;
542      item->ident = current_function_funcdef_no + 1;
543      item->checksum = compute_checksum ();
544      for (i = 0; i != GCOV_COUNTERS; i++)
545	{
546	  item->n_ctrs[i] = fn_n_ctrs[i];
547	  prg_n_ctrs[i] += fn_n_ctrs[i];
548	  fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
549	}
550      prg_ctr_mask |= fn_ctr_mask;
551      fn_ctr_mask = 0;
552    }
553  bbg_function_announced = 0;
554}
555
556/* Creates the gcov_fn_info RECORD_TYPE.  */
557
558static tree
559build_fn_info_type (unsigned int counters)
560{
561  tree type = (*lang_hooks.types.make_type) (RECORD_TYPE);
562  tree field, fields;
563  tree array_type;
564
565  /* ident */
566  fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
567
568  /* checksum */
569  field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
570  TREE_CHAIN (field) = fields;
571  fields = field;
572
573  array_type = build_index_type (build_int_2 (counters - 1, 0));
574  array_type = build_array_type (unsigned_type_node, array_type);
575
576  /* counters */
577  field = build_decl (FIELD_DECL, NULL_TREE, array_type);
578  TREE_CHAIN (field) = fields;
579  fields = field;
580
581  finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
582
583  return type;
584}
585
586/* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
587   the function being processed and TYPE is the gcov_fn_info
588   RECORD_TYPE.  */
589
590static tree
591build_fn_info_value (const struct function_list *function, tree type)
592{
593  tree value = NULL_TREE;
594  tree fields = TYPE_FIELDS (type);
595  unsigned ix;
596  tree array_value = NULL_TREE;
597
598  /* ident */
599  value = tree_cons (fields,
600		     convert (unsigned_intSI_type_node,
601			      build_int_2 (function->ident, 0)),
602		     value);
603  fields = TREE_CHAIN (fields);
604
605  /* checksum */
606  value = tree_cons (fields,
607		     convert (unsigned_intSI_type_node,
608			      build_int_2 (function->checksum, 0)),
609		     value);
610  fields = TREE_CHAIN (fields);
611
612  /* counters */
613  for (ix = 0; ix != GCOV_COUNTERS; ix++)
614    if (prg_ctr_mask & (1 << ix))
615      {
616	tree counters = convert (unsigned_type_node,
617				 build_int_2 (function->n_ctrs[ix], 0));
618
619	array_value = tree_cons (NULL_TREE, counters, array_value);
620      }
621
622  array_value = build_constructor (TREE_TYPE (fields), nreverse (array_value));
623  value = tree_cons (fields, array_value, value);
624
625  value = build_constructor (type, nreverse (value));
626
627  return value;
628}
629
630/* Creates the gcov_ctr_info RECORD_TYPE.  */
631
632static tree
633build_ctr_info_type (void)
634{
635  tree type = (*lang_hooks.types.make_type) (RECORD_TYPE);
636  tree field, fields = NULL_TREE;
637  tree gcov_ptr_type = build_pointer_type (GCOV_TYPE_NODE);
638  tree gcov_merge_fn_type;
639
640  /* counters */
641  field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
642  TREE_CHAIN (field) = fields;
643  fields = field;
644
645  /* values */
646  field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
647  TREE_CHAIN (field) = fields;
648  fields = field;
649
650  /* merge */
651  gcov_merge_fn_type =
652    build_function_type_list (void_type_node,
653			      gcov_ptr_type, unsigned_type_node,
654			      NULL_TREE);
655  field = build_decl (FIELD_DECL, NULL_TREE,
656		      build_pointer_type (gcov_merge_fn_type));
657  TREE_CHAIN (field) = fields;
658  fields = field;
659
660  finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
661
662  return type;
663}
664
665/* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
666   the counter being processed and TYPE is the gcov_ctr_info
667   RECORD_TYPE.  */
668
669static tree
670build_ctr_info_value (unsigned int counter, tree type)
671{
672  tree value = NULL_TREE;
673  tree fields = TYPE_FIELDS (type);
674  tree fn;
675
676  /* counters */
677  value = tree_cons (fields,
678		     convert (unsigned_intSI_type_node,
679			      build_int_2 (prg_n_ctrs[counter], 0)),
680		     value);
681  fields = TREE_CHAIN (fields);
682
683  if (prg_n_ctrs[counter])
684    {
685      tree array_type, array;
686
687      array_type = build_index_type (build_int_2 (prg_n_ctrs[counter] - 1, 0));
688      array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
689				     array_type);
690
691      array = build_decl (VAR_DECL, NULL_TREE, array_type);
692      TREE_STATIC (array) = 1;
693      DECL_NAME (array) = get_identifier (XSTR (ctr_labels[counter], 0));
694      assemble_variable (array, 0, 0, 0);
695
696      value = tree_cons (fields,
697			 build1 (ADDR_EXPR, TREE_TYPE (fields), array),
698			 value);
699    }
700  else
701    value = tree_cons (fields, null_pointer_node, value);
702  fields = TREE_CHAIN (fields);
703
704  fn = build_decl (FUNCTION_DECL,
705		   get_identifier (ctr_merge_functions[counter]),
706		   TREE_TYPE (TREE_TYPE (fields)));
707  DECL_EXTERNAL (fn) = 1;
708  TREE_PUBLIC (fn) = 1;
709  DECL_ARTIFICIAL (fn) = 1;
710  TREE_NOTHROW (fn) = 1;
711  value = tree_cons (fields,
712		     build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
713		     value);
714
715  value = build_constructor (type, nreverse (value));
716
717  return value;
718}
719
720/* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
721   CONSTRUCTOR.  */
722
723static tree
724build_gcov_info (void)
725{
726  unsigned n_ctr_types, ix;
727  tree type, const_type;
728  tree fn_info_type, fn_info_value = NULL_TREE;
729  tree fn_info_ptr_type;
730  tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
731  tree field, fields = NULL_TREE;
732  tree value = NULL_TREE;
733  tree filename_string;
734  char *filename;
735  int filename_len;
736  unsigned n_fns;
737  const struct function_list *fn;
738  tree string_type;
739
740  /* Count the number of active counters.  */
741  for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
742    if (prg_ctr_mask & (1 << ix))
743      n_ctr_types++;
744
745  type = (*lang_hooks.types.make_type) (RECORD_TYPE);
746  const_type = build_qualified_type (type, TYPE_QUAL_CONST);
747
748  /* Version ident */
749  field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
750  TREE_CHAIN (field) = fields;
751  fields = field;
752  value = tree_cons (field, convert (unsigned_intSI_type_node,
753				     build_int_2 (GCOV_VERSION, 0)),
754		     value);
755
756  /* next -- NULL */
757  field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
758  TREE_CHAIN (field) = fields;
759  fields = field;
760  value = tree_cons (field, null_pointer_node, value);
761
762  /* stamp */
763  field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
764  TREE_CHAIN (field) = fields;
765  fields = field;
766  value = tree_cons (field, convert (unsigned_intSI_type_node,
767				     build_int_2 (local_tick, 0)),
768		     value);
769
770  /* Filename */
771  string_type = build_pointer_type (build_qualified_type (char_type_node,
772						    TYPE_QUAL_CONST));
773  field = build_decl (FIELD_DECL, NULL_TREE, string_type);
774  TREE_CHAIN (field) = fields;
775  fields = field;
776  filename = getpwd ();
777  filename = (filename && da_file_name[0] != '/'
778	      ? concat (filename, "/", da_file_name, NULL)
779	      : da_file_name);
780  filename_len = strlen (filename);
781  filename_string = build_string (filename_len + 1, filename);
782  if (filename != da_file_name)
783    free (filename);
784  TREE_TYPE (filename_string) =
785	  build_array_type (char_type_node,
786			    build_index_type (build_int_2 (filename_len, 0)));
787  value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
788		     value);
789
790  /* Build the fn_info type and initializer.  */
791  fn_info_type = build_fn_info_type (n_ctr_types);
792  fn_info_ptr_type = build_pointer_type (build_qualified_type
793					 (fn_info_type, TYPE_QUAL_CONST));
794  for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
795    fn_info_value = tree_cons (NULL_TREE,
796			       build_fn_info_value (fn, fn_info_type),
797			       fn_info_value);
798  if (n_fns)
799    {
800      tree array_type;
801
802      array_type = build_index_type (build_int_2 (n_fns - 1, 0));
803      array_type = build_array_type (fn_info_type, array_type);
804
805      fn_info_value = build_constructor (array_type, nreverse (fn_info_value));
806      fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
807    }
808  else
809    fn_info_value = null_pointer_node;
810
811  /* number of functions */
812  field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
813  TREE_CHAIN (field) = fields;
814  fields = field;
815  value = tree_cons (field,
816		     convert (unsigned_type_node, build_int_2 (n_fns, 0)),
817		     value);
818
819  /* fn_info table */
820  field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type);
821  TREE_CHAIN (field) = fields;
822  fields = field;
823  value = tree_cons (field, fn_info_value, value);
824
825  /* counter_mask */
826  field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
827  TREE_CHAIN (field) = fields;
828  fields = field;
829  value = tree_cons (field,
830		     convert (unsigned_type_node,
831			      build_int_2 (prg_ctr_mask, 0)),
832		     value);
833
834  /* counters */
835  ctr_info_type = build_ctr_info_type ();
836  ctr_info_ary_type = build_index_type (build_int_2 (n_ctr_types, 0));
837  ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
838  for (ix = 0; ix != GCOV_COUNTERS; ix++)
839    if (prg_ctr_mask & (1 << ix))
840      ctr_info_value = tree_cons (NULL_TREE,
841				  build_ctr_info_value (ix, ctr_info_type),
842				  ctr_info_value);
843  ctr_info_value = build_constructor (ctr_info_ary_type,
844				      nreverse (ctr_info_value));
845
846  field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
847  TREE_CHAIN (field) = fields;
848  fields = field;
849  value = tree_cons (field, ctr_info_value, value);
850
851  finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
852
853  value = build_constructor (type, nreverse (value));
854
855  return value;
856}
857
858/* Write out the structure which libgcov uses to locate all the
859   counters.  The structures used here must match those defined in
860   gcov-io.h.  Write out the constructor to call __gcov_init.  */
861
862static void
863create_coverage (void)
864{
865  tree gcov_info, gcov_info_value;
866  char name[20];
867  char *ctor_name;
868  tree ctor;
869  rtx gcov_info_address;
870
871  no_coverage = 1; /* Disable any further coverage.  */
872
873  if (!prg_ctr_mask)
874    return;
875
876  gcov_info_value = build_gcov_info ();
877
878  gcov_info = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (gcov_info_value));
879  DECL_INITIAL (gcov_info) = gcov_info_value;
880
881  TREE_STATIC (gcov_info) = 1;
882  ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 0);
883  DECL_NAME (gcov_info) = get_identifier (name);
884
885  /* Build structure.  */
886  assemble_variable (gcov_info, 0, 0, 0);
887
888  /* Build the constructor function to invoke __gcov_init.  */
889  ctor_name = concat (IDENTIFIER_POINTER (get_file_function_name ('I')),
890		      "_GCOV", NULL);
891  ctor = build_decl (FUNCTION_DECL, get_identifier (ctor_name),
892		     build_function_type (void_type_node, NULL_TREE));
893  free (ctor_name);
894  DECL_EXTERNAL (ctor) = 0;
895
896  /* It can be a static function as long as collect2 does not have
897     to scan the object file to find its ctor/dtor routine.  */
898  TREE_PUBLIC (ctor) = ! targetm.have_ctors_dtors;
899  TREE_USED (ctor) = 1;
900  DECL_RESULT (ctor) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
901  DECL_UNINLINABLE (ctor) = 1;
902
903  ctor = (*lang_hooks.decls.pushdecl) (ctor);
904  rest_of_decl_compilation (ctor, 0, 1, 0);
905  announce_function (ctor);
906  current_function_decl = ctor;
907  make_decl_rtl (ctor, NULL);
908  init_function_start (ctor);
909  expand_function_start (ctor, 0);
910  /* Actually generate the code to call __gcov_init.  */
911  gcov_info_address = force_reg (Pmode, XEXP (DECL_RTL (gcov_info), 0));
912  emit_library_call (gcov_init_libfunc, LCT_NORMAL, VOIDmode, 1,
913		     gcov_info_address, Pmode);
914
915  expand_function_end ();
916  /* Create a dummy BLOCK.  */
917  DECL_INITIAL (ctor) = make_node (BLOCK);
918  TREE_USED (DECL_INITIAL (ctor)) = 1;
919
920  rest_of_compilation (ctor);
921
922  if (! quiet_flag)
923    fflush (asm_out_file);
924  current_function_decl = NULL_TREE;
925
926  if (targetm.have_ctors_dtors)
927    (* targetm.asm_out.constructor) (XEXP (DECL_RTL (ctor), 0),
928				     DEFAULT_INIT_PRIORITY);
929}
930
931/* Perform file-level initialization. Read in data file, generate name
932   of graph file.  */
933
934void
935coverage_init (const char *filename)
936{
937  int len = strlen (filename);
938
939  /* Name of da file.  */
940  da_file_name = xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1);
941  strcpy (da_file_name, filename);
942  strcat (da_file_name, GCOV_DATA_SUFFIX);
943
944  /* Name of bbg file.  */
945  bbg_file_name = xmalloc (len + strlen (GCOV_NOTE_SUFFIX) + 1);
946  strcpy (bbg_file_name, filename);
947  strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
948
949  read_counts_file ();
950}
951
952/* Performs file-level cleanup.  Close graph file, generate coverage
953   variables and constructor.  */
954
955void
956coverage_finish (void)
957{
958  create_coverage ();
959  if (bbg_file_opened)
960    {
961      int error = gcov_close ();
962
963      if (error)
964	unlink (bbg_file_name);
965      if (!local_tick)
966	/* Only remove the da file, if we cannot stamp it. If we can
967	   stamp it, libgcov will DTRT.  */
968	unlink (da_file_name);
969    }
970}
971
972#include "gt-coverage.h"
973