coverage.c revision 259405
150471Speter/* Read and write coverage files, and associated functionality.
223449Sjoerg   Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
323449Sjoerg   2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
423449Sjoerg   Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
523449Sjoerg   based on some ideas from Dain Samples of UC Berkeley.
623449Sjoerg   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  char *dup = NULL;
433  char *ptr;
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#define GLOBAL_PREFIX "_GLOBAL__"
440#define TRAILING_N "N_"
441#define ISCAPXDIGIT(a) (((a) >= '0' && (a) <= '9') || ((a) >= 'A' && (a) <= 'F'))
442  if ((ptr = strstr (string, GLOBAL_PREFIX)))
443    {
444      /* Skip _GLOBAL__. */
445      ptr += strlen (GLOBAL_PREFIX);
446
447      /* Skip optional N_ (in case __GLOBAL_N__). */
448      if (!strncmp (ptr, TRAILING_N, strlen (TRAILING_N)))
449          ptr += strlen (TRAILING_N);
450      /* At this point, ptr should point after "_GLOBAL__N_" or "_GLOBAL__". */
451
452      while ((ptr = strchr (ptr, '_')) != NULL)
453        {
454          int y;
455          /* For every "_" in the rest of the string,
456             try the follwing pattern matching */
457
458          /* Skip over '_'. */
459          ptr++;
460#define NDIGITS (8)
461          /* Try matching the pattern:
462             <8-digit hex>_<8-digit hex>
463             The second number is randomly generated
464             so we want to mask it out before computing the checksum. */
465          for (y = 0; *ptr != 0 && y < NDIGITS; y++, ptr++)
466              if (!ISCAPXDIGIT (*ptr))
467                  break;
468          if (y != NDIGITS || *ptr != '_')
469              continue;
470          /* Skip over '_' again. */
471          ptr++;
472          for (y = 0; *ptr != 0 && y < NDIGITS; y++, ptr++)
473              if (!ISCAPXDIGIT (*ptr))
474                  break;
475
476          if (y == NDIGITS)
477            {
478              /* We have a match.
479                 Duplicate the string and mask out
480                 the second 8-digit number. */
481              dup = xstrdup (string);
482              ptr = dup + (ptr - string);
483              for(y = -NDIGITS - 1 ; y < 0; y++)
484                {
485                  ptr[y] = '0';
486                }
487              ptr = dup;
488              break;
489            }
490        }
491        /* "ptr" should be NULL if we couldn't find the match
492           (strchr will return NULL if no match is found),
493           or it should point to dup which contains the string
494           with the random part masked. */
495    }
496
497  chksum = crc32_string (chksum, (ptr) ? ptr : string);
498
499  if (dup)
500      free (dup);
501
502  return chksum;
503}
504
505/* Compute checksum for the current function.  We generate a CRC32.  */
506
507static unsigned
508compute_checksum (void)
509{
510  expanded_location xloc
511    = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
512  unsigned chksum = xloc.line;
513
514  chksum = coverage_checksum_string (chksum, xloc.file);
515  chksum = coverage_checksum_string
516    (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
517
518  return chksum;
519}
520
521/* Begin output to the graph file for the current function.
522   Opens the output file, if not already done. Writes the
523   function header, if not already done. Returns nonzero if data
524   should be output.  */
525
526int
527coverage_begin_output (void)
528{
529  if (no_coverage)
530    return 0;
531
532  if (!bbg_function_announced)
533    {
534      expanded_location xloc
535	= expand_location (DECL_SOURCE_LOCATION (current_function_decl));
536      unsigned long offset;
537
538      if (!bbg_file_opened)
539	{
540	  if (!gcov_open (bbg_file_name, -1))
541	    error ("cannot open %s", bbg_file_name);
542	  else
543	    {
544	      gcov_write_unsigned (GCOV_NOTE_MAGIC);
545	      gcov_write_unsigned (GCOV_VERSION);
546	      gcov_write_unsigned (local_tick);
547	    }
548	  bbg_file_opened = 1;
549	}
550
551      /* Announce function */
552      offset = gcov_write_tag (GCOV_TAG_FUNCTION);
553      gcov_write_unsigned (current_function_funcdef_no + 1);
554      gcov_write_unsigned (compute_checksum ());
555      gcov_write_string (IDENTIFIER_POINTER
556			 (DECL_ASSEMBLER_NAME (current_function_decl)));
557      gcov_write_string (xloc.file);
558      gcov_write_unsigned (xloc.line);
559      gcov_write_length (offset);
560
561      bbg_function_announced = 1;
562    }
563  return !gcov_is_error ();
564}
565
566/* Finish coverage data for the current function. Verify no output
567   error has occurred.  Save function coverage counts.  */
568
569void
570coverage_end_function (void)
571{
572  unsigned i;
573
574  if (bbg_file_opened > 1 && gcov_is_error ())
575    {
576      warning (0, "error writing %qs", bbg_file_name);
577      bbg_file_opened = -1;
578    }
579
580  if (fn_ctr_mask)
581    {
582      struct function_list *item;
583
584      item = XNEW (struct function_list);
585
586      *functions_tail = item;
587      functions_tail = &item->next;
588
589      item->next = 0;
590      item->ident = current_function_funcdef_no + 1;
591      item->checksum = compute_checksum ();
592      for (i = 0; i != GCOV_COUNTERS; i++)
593	{
594	  item->n_ctrs[i] = fn_n_ctrs[i];
595	  prg_n_ctrs[i] += fn_n_ctrs[i];
596	  fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
597	}
598      prg_ctr_mask |= fn_ctr_mask;
599      fn_ctr_mask = 0;
600    }
601  bbg_function_announced = 0;
602}
603
604/* Creates the gcov_fn_info RECORD_TYPE.  */
605
606static tree
607build_fn_info_type (unsigned int counters)
608{
609  tree type = lang_hooks.types.make_type (RECORD_TYPE);
610  tree field, fields;
611  tree array_type;
612
613  /* ident */
614  fields = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
615
616  /* checksum */
617  field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
618  TREE_CHAIN (field) = fields;
619  fields = field;
620
621  array_type = build_int_cst (NULL_TREE, counters - 1);
622  array_type = build_index_type (array_type);
623  array_type = build_array_type (get_gcov_unsigned_t (), array_type);
624
625  /* counters */
626  field = build_decl (FIELD_DECL, NULL_TREE, array_type);
627  TREE_CHAIN (field) = fields;
628  fields = field;
629
630  finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
631
632  return type;
633}
634
635/* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
636   the function being processed and TYPE is the gcov_fn_info
637   RECORD_TYPE.  */
638
639static tree
640build_fn_info_value (const struct function_list *function, tree type)
641{
642  tree value = NULL_TREE;
643  tree fields = TYPE_FIELDS (type);
644  unsigned ix;
645  tree array_value = NULL_TREE;
646
647  /* ident */
648  value = tree_cons (fields, build_int_cstu (get_gcov_unsigned_t (),
649					     function->ident), value);
650  fields = TREE_CHAIN (fields);
651
652  /* checksum */
653  value = tree_cons (fields, build_int_cstu (get_gcov_unsigned_t (),
654					     function->checksum), value);
655  fields = TREE_CHAIN (fields);
656
657  /* counters */
658  for (ix = 0; ix != GCOV_COUNTERS; ix++)
659    if (prg_ctr_mask & (1 << ix))
660      {
661	tree counters = build_int_cstu (get_gcov_unsigned_t (),
662					function->n_ctrs[ix]);
663
664	array_value = tree_cons (NULL_TREE, counters, array_value);
665      }
666
667  /* FIXME: use build_constructor directly.  */
668  array_value = build_constructor_from_list (TREE_TYPE (fields),
669					     nreverse (array_value));
670  value = tree_cons (fields, array_value, value);
671
672  /* FIXME: use build_constructor directly.  */
673  value = build_constructor_from_list (type, nreverse (value));
674
675  return value;
676}
677
678/* Creates the gcov_ctr_info RECORD_TYPE.  */
679
680static tree
681build_ctr_info_type (void)
682{
683  tree type = lang_hooks.types.make_type (RECORD_TYPE);
684  tree field, fields = NULL_TREE;
685  tree gcov_ptr_type = build_pointer_type (get_gcov_type ());
686  tree gcov_merge_fn_type;
687
688  /* counters */
689  field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
690  TREE_CHAIN (field) = fields;
691  fields = field;
692
693  /* values */
694  field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
695  TREE_CHAIN (field) = fields;
696  fields = field;
697
698  /* merge */
699  gcov_merge_fn_type =
700    build_function_type_list (void_type_node,
701			      gcov_ptr_type, get_gcov_unsigned_t (),
702			      NULL_TREE);
703  field = build_decl (FIELD_DECL, NULL_TREE,
704		      build_pointer_type (gcov_merge_fn_type));
705  TREE_CHAIN (field) = fields;
706  fields = field;
707
708  finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
709
710  return type;
711}
712
713/* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
714   the counter being processed and TYPE is the gcov_ctr_info
715   RECORD_TYPE.  */
716
717static tree
718build_ctr_info_value (unsigned int counter, tree type)
719{
720  tree value = NULL_TREE;
721  tree fields = TYPE_FIELDS (type);
722  tree fn;
723
724  /* counters */
725  value = tree_cons (fields,
726		     build_int_cstu (get_gcov_unsigned_t (),
727				     prg_n_ctrs[counter]),
728		     value);
729  fields = TREE_CHAIN (fields);
730
731  if (prg_n_ctrs[counter])
732    {
733      tree array_type;
734
735      array_type = build_int_cstu (get_gcov_unsigned_t (),
736				   prg_n_ctrs[counter] - 1);
737      array_type = build_index_type (array_type);
738      array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
739				     array_type);
740
741      TREE_TYPE (tree_ctr_tables[counter]) = array_type;
742      DECL_SIZE (tree_ctr_tables[counter]) = TYPE_SIZE (array_type);
743      DECL_SIZE_UNIT (tree_ctr_tables[counter]) = TYPE_SIZE_UNIT (array_type);
744      assemble_variable (tree_ctr_tables[counter], 0, 0, 0);
745
746      value = tree_cons (fields,
747			 build1 (ADDR_EXPR, TREE_TYPE (fields),
748					    tree_ctr_tables[counter]),
749			 value);
750    }
751  else
752    value = tree_cons (fields, null_pointer_node, value);
753  fields = TREE_CHAIN (fields);
754
755  fn = build_decl (FUNCTION_DECL,
756		   get_identifier (ctr_merge_functions[counter]),
757		   TREE_TYPE (TREE_TYPE (fields)));
758  DECL_EXTERNAL (fn) = 1;
759  TREE_PUBLIC (fn) = 1;
760  DECL_ARTIFICIAL (fn) = 1;
761  TREE_NOTHROW (fn) = 1;
762  value = tree_cons (fields,
763		     build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
764		     value);
765
766  /* FIXME: use build_constructor directly.  */
767  value = build_constructor_from_list (type, nreverse (value));
768
769  return value;
770}
771
772/* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
773   CONSTRUCTOR.  */
774
775static tree
776build_gcov_info (void)
777{
778  unsigned n_ctr_types, ix;
779  tree type, const_type;
780  tree fn_info_type, fn_info_value = NULL_TREE;
781  tree fn_info_ptr_type;
782  tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
783  tree field, fields = NULL_TREE;
784  tree value = NULL_TREE;
785  tree filename_string;
786  char *filename;
787  int filename_len;
788  unsigned n_fns;
789  const struct function_list *fn;
790  tree string_type;
791
792  /* Count the number of active counters.  */
793  for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
794    if (prg_ctr_mask & (1 << ix))
795      n_ctr_types++;
796
797  type = lang_hooks.types.make_type (RECORD_TYPE);
798  const_type = build_qualified_type (type, TYPE_QUAL_CONST);
799
800  /* Version ident */
801  field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
802  TREE_CHAIN (field) = fields;
803  fields = field;
804  value = tree_cons (field, build_int_cstu (TREE_TYPE (field), GCOV_VERSION),
805		     value);
806
807  /* next -- NULL */
808  field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
809  TREE_CHAIN (field) = fields;
810  fields = field;
811  value = tree_cons (field, null_pointer_node, value);
812
813  /* stamp */
814  field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
815  TREE_CHAIN (field) = fields;
816  fields = field;
817  value = tree_cons (field, build_int_cstu (TREE_TYPE (field), local_tick),
818		     value);
819
820  /* Filename */
821  string_type = build_pointer_type (build_qualified_type (char_type_node,
822						    TYPE_QUAL_CONST));
823  field = build_decl (FIELD_DECL, NULL_TREE, string_type);
824  TREE_CHAIN (field) = fields;
825  fields = field;
826  filename = getpwd ();
827  filename = (filename && da_file_name[0] != '/'
828	      ? concat (filename, "/", da_file_name, NULL)
829	      : da_file_name);
830  filename_len = strlen (filename);
831  filename_string = build_string (filename_len + 1, filename);
832  if (filename != da_file_name)
833    free (filename);
834  TREE_TYPE (filename_string) = build_array_type
835    (char_type_node, build_index_type
836     (build_int_cst (NULL_TREE, filename_len)));
837  value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
838		     value);
839
840  /* Build the fn_info type and initializer.  */
841  fn_info_type = build_fn_info_type (n_ctr_types);
842  fn_info_ptr_type = build_pointer_type (build_qualified_type
843					 (fn_info_type, TYPE_QUAL_CONST));
844  for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
845    fn_info_value = tree_cons (NULL_TREE,
846			       build_fn_info_value (fn, fn_info_type),
847			       fn_info_value);
848  if (n_fns)
849    {
850      tree array_type;
851
852      array_type = build_index_type (build_int_cst (NULL_TREE, n_fns - 1));
853      array_type = build_array_type (fn_info_type, array_type);
854
855      /* FIXME: use build_constructor directly.  */
856      fn_info_value = build_constructor_from_list (array_type,
857						   nreverse (fn_info_value));
858      fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
859    }
860  else
861    fn_info_value = null_pointer_node;
862
863  /* number of functions */
864  field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
865  TREE_CHAIN (field) = fields;
866  fields = field;
867  value = tree_cons (field,
868		     build_int_cstu (get_gcov_unsigned_t (), n_fns),
869		     value);
870
871  /* fn_info table */
872  field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type);
873  TREE_CHAIN (field) = fields;
874  fields = field;
875  value = tree_cons (field, fn_info_value, value);
876
877  /* counter_mask */
878  field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
879  TREE_CHAIN (field) = fields;
880  fields = field;
881  value = tree_cons (field,
882		     build_int_cstu (get_gcov_unsigned_t (), prg_ctr_mask),
883		     value);
884
885  /* counters */
886  ctr_info_type = build_ctr_info_type ();
887  ctr_info_ary_type = build_index_type (build_int_cst (NULL_TREE,
888						       n_ctr_types));
889  ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
890  for (ix = 0; ix != GCOV_COUNTERS; ix++)
891    if (prg_ctr_mask & (1 << ix))
892      ctr_info_value = tree_cons (NULL_TREE,
893				  build_ctr_info_value (ix, ctr_info_type),
894				  ctr_info_value);
895  /* FIXME: use build_constructor directly.  */
896  ctr_info_value = build_constructor_from_list (ctr_info_ary_type,
897				                nreverse (ctr_info_value));
898
899  field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
900  TREE_CHAIN (field) = fields;
901  fields = field;
902  value = tree_cons (field, ctr_info_value, value);
903
904  finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
905
906  /* FIXME: use build_constructor directly.  */
907  value = build_constructor_from_list (type, nreverse (value));
908
909  return value;
910}
911
912/* Write out the structure which libgcov uses to locate all the
913   counters.  The structures used here must match those defined in
914   gcov-io.h.  Write out the constructor to call __gcov_init.  */
915
916static void
917create_coverage (void)
918{
919  tree gcov_info, gcov_init, body, t;
920  char name_buf[32];
921
922  no_coverage = 1; /* Disable any further coverage.  */
923
924  if (!prg_ctr_mask)
925    return;
926
927  t = build_gcov_info ();
928
929  gcov_info = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (t));
930  TREE_STATIC (gcov_info) = 1;
931  ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
932  DECL_NAME (gcov_info) = get_identifier (name_buf);
933  DECL_INITIAL (gcov_info) = t;
934
935  /* Build structure.  */
936  assemble_variable (gcov_info, 0, 0, 0);
937
938  /* Build a decl for __gcov_init.  */
939  t = build_pointer_type (TREE_TYPE (gcov_info));
940  t = build_function_type_list (void_type_node, t, NULL);
941  t = build_decl (FUNCTION_DECL, get_identifier ("__gcov_init"), t);
942  TREE_PUBLIC (t) = 1;
943  DECL_EXTERNAL (t) = 1;
944  gcov_init = t;
945
946  /* Generate a call to __gcov_init(&gcov_info).  */
947  body = NULL;
948  t = build_fold_addr_expr (gcov_info);
949  t = tree_cons (NULL, t, NULL);
950  t = build_function_call_expr (gcov_init, t);
951  append_to_statement_list (t, &body);
952
953  /* Generate a constructor to run it.  */
954  cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
955}
956
957/* Perform file-level initialization. Read in data file, generate name
958   of graph file.  */
959
960void
961coverage_init (const char *filename)
962{
963  int len = strlen (filename);
964
965  /* Name of da file.  */
966  da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX) + 1);
967  strcpy (da_file_name, filename);
968  strcat (da_file_name, GCOV_DATA_SUFFIX);
969
970  /* Name of bbg file.  */
971  bbg_file_name = XNEWVEC (char, len + strlen (GCOV_NOTE_SUFFIX) + 1);
972  strcpy (bbg_file_name, filename);
973  strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
974
975  read_counts_file ();
976}
977
978/* Performs file-level cleanup.  Close graph file, generate coverage
979   variables and constructor.  */
980
981void
982coverage_finish (void)
983{
984  create_coverage ();
985  if (bbg_file_opened)
986    {
987      int error = gcov_close ();
988
989      if (error)
990	unlink (bbg_file_name);
991      if (!local_tick)
992	/* Only remove the da file, if we cannot stamp it. If we can
993	   stamp it, libgcov will DTRT.  */
994	unlink (da_file_name);
995    }
996}
997
998#include "gt-coverage.h"
999