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