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