xref: /dragonfly/contrib/gcc-4.7/gcc/coverage.c (revision 95d28233)
1e4b17023SJohn Marino /* Read and write coverage files, and associated functionality.
2e4b17023SJohn Marino    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
3e4b17023SJohn Marino    2000, 2001, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011, 2012
4e4b17023SJohn Marino    Free Software Foundation, Inc.
5e4b17023SJohn Marino    Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
6e4b17023SJohn Marino    based on some ideas from Dain Samples of UC Berkeley.
7e4b17023SJohn Marino    Further mangling by Bob Manson, Cygnus Support.
8e4b17023SJohn Marino    Further mangled by Nathan Sidwell, CodeSourcery
9e4b17023SJohn Marino 
10e4b17023SJohn Marino This file is part of GCC.
11e4b17023SJohn Marino 
12e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
13e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
14e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
15e4b17023SJohn Marino version.
16e4b17023SJohn Marino 
17e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
18e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
19e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20e4b17023SJohn Marino for more details.
21e4b17023SJohn Marino 
22e4b17023SJohn Marino You should have received a copy of the GNU General Public License
23e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
24e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
25e4b17023SJohn Marino 
26e4b17023SJohn Marino 
27e4b17023SJohn Marino #define GCOV_LINKAGE
28e4b17023SJohn Marino 
29e4b17023SJohn Marino #include "config.h"
30e4b17023SJohn Marino #include "system.h"
31e4b17023SJohn Marino #include "coretypes.h"
32e4b17023SJohn Marino #include "tm.h"
33e4b17023SJohn Marino #include "rtl.h"
34e4b17023SJohn Marino #include "tree.h"
35e4b17023SJohn Marino #include "flags.h"
36e4b17023SJohn Marino #include "output.h"
37e4b17023SJohn Marino #include "regs.h"
38e4b17023SJohn Marino #include "expr.h"
39e4b17023SJohn Marino #include "function.h"
40e4b17023SJohn Marino #include "basic-block.h"
41e4b17023SJohn Marino #include "toplev.h"
42e4b17023SJohn Marino #include "tm_p.h"
43e4b17023SJohn Marino #include "ggc.h"
44e4b17023SJohn Marino #include "coverage.h"
45e4b17023SJohn Marino #include "langhooks.h"
46e4b17023SJohn Marino #include "hashtab.h"
47e4b17023SJohn Marino #include "tree-iterator.h"
48e4b17023SJohn Marino #include "cgraph.h"
49e4b17023SJohn Marino #include "tree-pass.h"
50e4b17023SJohn Marino #include "diagnostic-core.h"
51e4b17023SJohn Marino #include "intl.h"
52e4b17023SJohn Marino #include "filenames.h"
53e4b17023SJohn Marino #include "target.h"
54e4b17023SJohn Marino 
55e4b17023SJohn Marino #include "gcov-io.h"
56e4b17023SJohn Marino #include "gcov-io.c"
57e4b17023SJohn Marino 
58e4b17023SJohn Marino struct GTY((chain_next ("%h.next"))) coverage_data
59e4b17023SJohn Marino {
60e4b17023SJohn Marino   struct coverage_data *next;	 /* next function */
61e4b17023SJohn Marino   unsigned ident;		 /* function ident */
62e4b17023SJohn Marino   unsigned lineno_checksum;	 /* function lineno checksum */
63e4b17023SJohn Marino   unsigned cfg_checksum;	 /* function cfg checksum */
64e4b17023SJohn Marino   tree fn_decl;			 /* the function decl */
65e4b17023SJohn Marino   tree ctr_vars[GCOV_COUNTERS];	 /* counter variables.  */
66e4b17023SJohn Marino };
67e4b17023SJohn Marino 
68e4b17023SJohn Marino /* Counts information for a function.  */
69e4b17023SJohn Marino typedef struct counts_entry
70e4b17023SJohn Marino {
71e4b17023SJohn Marino   /* We hash by  */
72e4b17023SJohn Marino   unsigned ident;
73e4b17023SJohn Marino   unsigned ctr;
74e4b17023SJohn Marino 
75e4b17023SJohn Marino   /* Store  */
76e4b17023SJohn Marino   unsigned lineno_checksum;
77e4b17023SJohn Marino   unsigned cfg_checksum;
78e4b17023SJohn Marino   gcov_type *counts;
79e4b17023SJohn Marino   struct gcov_ctr_summary summary;
80e4b17023SJohn Marino } counts_entry_t;
81e4b17023SJohn Marino 
82e4b17023SJohn Marino static GTY(()) struct coverage_data *functions_head = 0;
83e4b17023SJohn Marino static struct coverage_data **functions_tail = &functions_head;
84e4b17023SJohn Marino static unsigned no_coverage = 0;
85e4b17023SJohn Marino 
86e4b17023SJohn Marino /* Cumulative counter information for whole program.  */
87e4b17023SJohn Marino static unsigned prg_ctr_mask; /* Mask of counter types generated.  */
88e4b17023SJohn Marino 
89e4b17023SJohn Marino /* Counter information for current function.  */
90e4b17023SJohn Marino static unsigned fn_ctr_mask; /* Mask of counters used.  */
91e4b17023SJohn Marino static GTY(()) tree fn_v_ctrs[GCOV_COUNTERS];   /* counter variables.  */
92e4b17023SJohn Marino static unsigned fn_n_ctrs[GCOV_COUNTERS]; /* Counters allocated.  */
93e4b17023SJohn Marino static unsigned fn_b_ctrs[GCOV_COUNTERS]; /* Allocation base.  */
94e4b17023SJohn Marino 
95e4b17023SJohn Marino /* Coverage info VAR_DECL and function info type nodes.  */
96e4b17023SJohn Marino static GTY(()) tree gcov_info_var;
97e4b17023SJohn Marino static GTY(()) tree gcov_fn_info_type;
98e4b17023SJohn Marino static GTY(()) tree gcov_fn_info_ptr_type;
99e4b17023SJohn Marino 
100e4b17023SJohn Marino /* Name of the output file for coverage output file.  If this is NULL
101e4b17023SJohn Marino    we're not writing to the notes file.  */
102e4b17023SJohn Marino static char *bbg_file_name;
103e4b17023SJohn Marino 
104e4b17023SJohn Marino /* Name of the count data file.  */
105e4b17023SJohn Marino static char *da_file_name;
106e4b17023SJohn Marino 
107e4b17023SJohn Marino /* Hash table of count data.  */
108e4b17023SJohn Marino static htab_t counts_hash = NULL;
109e4b17023SJohn Marino 
110e4b17023SJohn Marino /* The names of merge functions for counters.  */
111e4b17023SJohn Marino static const char *const ctr_merge_functions[GCOV_COUNTERS] = GCOV_MERGE_FUNCTIONS;
112e4b17023SJohn Marino static const char *const ctr_names[GCOV_COUNTERS] = GCOV_COUNTER_NAMES;
113e4b17023SJohn Marino 
114e4b17023SJohn Marino /* Forward declarations.  */
115e4b17023SJohn Marino static hashval_t htab_counts_entry_hash (const void *);
116e4b17023SJohn Marino static int htab_counts_entry_eq (const void *, const void *);
117e4b17023SJohn Marino static void htab_counts_entry_del (void *);
118e4b17023SJohn Marino static void read_counts_file (void);
119e4b17023SJohn Marino static tree build_var (tree, tree, int);
120e4b17023SJohn Marino static void build_fn_info_type (tree, unsigned, tree);
121e4b17023SJohn Marino static void build_info_type (tree, tree);
122e4b17023SJohn Marino static tree build_fn_info (const struct coverage_data *, tree, tree);
123e4b17023SJohn Marino static tree build_info (tree, tree);
124e4b17023SJohn Marino static bool coverage_obj_init (void);
125e4b17023SJohn Marino static VEC(constructor_elt,gc) *coverage_obj_fn
126e4b17023SJohn Marino (VEC(constructor_elt,gc) *, tree, struct coverage_data const *);
127e4b17023SJohn Marino static void coverage_obj_finish (VEC(constructor_elt,gc) *);
128e4b17023SJohn Marino 
129e4b17023SJohn Marino /* Return the type node for gcov_type.  */
130e4b17023SJohn Marino 
131e4b17023SJohn Marino tree
get_gcov_type(void)132e4b17023SJohn Marino get_gcov_type (void)
133e4b17023SJohn Marino {
134e4b17023SJohn Marino   return lang_hooks.types.type_for_size (GCOV_TYPE_SIZE, false);
135e4b17023SJohn Marino }
136e4b17023SJohn Marino 
137e4b17023SJohn Marino /* Return the type node for gcov_unsigned_t.  */
138e4b17023SJohn Marino 
139e4b17023SJohn Marino static tree
get_gcov_unsigned_t(void)140e4b17023SJohn Marino get_gcov_unsigned_t (void)
141e4b17023SJohn Marino {
142e4b17023SJohn Marino   return lang_hooks.types.type_for_size (32, true);
143e4b17023SJohn Marino }
144e4b17023SJohn Marino 
145e4b17023SJohn Marino static hashval_t
htab_counts_entry_hash(const void * of)146e4b17023SJohn Marino htab_counts_entry_hash (const void *of)
147e4b17023SJohn Marino {
148e4b17023SJohn Marino   const counts_entry_t *const entry = (const counts_entry_t *) of;
149e4b17023SJohn Marino 
150e4b17023SJohn Marino   return entry->ident * GCOV_COUNTERS + entry->ctr;
151e4b17023SJohn Marino }
152e4b17023SJohn Marino 
153e4b17023SJohn Marino static int
htab_counts_entry_eq(const void * of1,const void * of2)154e4b17023SJohn Marino htab_counts_entry_eq (const void *of1, const void *of2)
155e4b17023SJohn Marino {
156e4b17023SJohn Marino   const counts_entry_t *const entry1 = (const counts_entry_t *) of1;
157e4b17023SJohn Marino   const counts_entry_t *const entry2 = (const counts_entry_t *) of2;
158e4b17023SJohn Marino 
159e4b17023SJohn Marino   return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
160e4b17023SJohn Marino }
161e4b17023SJohn Marino 
162e4b17023SJohn Marino static void
htab_counts_entry_del(void * of)163e4b17023SJohn Marino htab_counts_entry_del (void *of)
164e4b17023SJohn Marino {
165e4b17023SJohn Marino   counts_entry_t *const entry = (counts_entry_t *) of;
166e4b17023SJohn Marino 
167e4b17023SJohn Marino   free (entry->counts);
168e4b17023SJohn Marino   free (entry);
169e4b17023SJohn Marino }
170e4b17023SJohn Marino 
171e4b17023SJohn Marino /* Read in the counts file, if available.  */
172e4b17023SJohn Marino 
173e4b17023SJohn Marino static void
read_counts_file(void)174e4b17023SJohn Marino read_counts_file (void)
175e4b17023SJohn Marino {
176e4b17023SJohn Marino   gcov_unsigned_t fn_ident = 0;
177e4b17023SJohn Marino   struct gcov_summary summary;
178e4b17023SJohn Marino   unsigned new_summary = 1;
179e4b17023SJohn Marino   gcov_unsigned_t tag;
180e4b17023SJohn Marino   int is_error = 0;
181e4b17023SJohn Marino   unsigned lineno_checksum = 0;
182e4b17023SJohn Marino   unsigned cfg_checksum = 0;
183e4b17023SJohn Marino 
184e4b17023SJohn Marino   if (!gcov_open (da_file_name, 1))
185e4b17023SJohn Marino     return;
186e4b17023SJohn Marino 
187e4b17023SJohn Marino   if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
188e4b17023SJohn Marino     {
189e4b17023SJohn Marino       warning (0, "%qs is not a gcov data file", da_file_name);
190e4b17023SJohn Marino       gcov_close ();
191e4b17023SJohn Marino       return;
192e4b17023SJohn Marino     }
193e4b17023SJohn Marino   else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
194e4b17023SJohn Marino     {
195e4b17023SJohn Marino       char v[4], e[4];
196e4b17023SJohn Marino 
197e4b17023SJohn Marino       GCOV_UNSIGNED2STRING (v, tag);
198e4b17023SJohn Marino       GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
199e4b17023SJohn Marino 
200e4b17023SJohn Marino       warning (0, "%qs is version %q.*s, expected version %q.*s",
201e4b17023SJohn Marino  	       da_file_name, 4, v, 4, e);
202e4b17023SJohn Marino       gcov_close ();
203e4b17023SJohn Marino       return;
204e4b17023SJohn Marino     }
205e4b17023SJohn Marino 
206e4b17023SJohn Marino   /* Read and discard the stamp.  */
207e4b17023SJohn Marino   gcov_read_unsigned ();
208e4b17023SJohn Marino 
209e4b17023SJohn Marino   counts_hash = htab_create (10,
210e4b17023SJohn Marino 			     htab_counts_entry_hash, htab_counts_entry_eq,
211e4b17023SJohn Marino 			     htab_counts_entry_del);
212e4b17023SJohn Marino   while ((tag = gcov_read_unsigned ()))
213e4b17023SJohn Marino     {
214e4b17023SJohn Marino       gcov_unsigned_t length;
215e4b17023SJohn Marino       gcov_position_t offset;
216e4b17023SJohn Marino 
217e4b17023SJohn Marino       length = gcov_read_unsigned ();
218e4b17023SJohn Marino       offset = gcov_position ();
219e4b17023SJohn Marino       if (tag == GCOV_TAG_FUNCTION)
220e4b17023SJohn Marino 	{
221e4b17023SJohn Marino 	  if (length)
222e4b17023SJohn Marino 	    {
223e4b17023SJohn Marino 	      fn_ident = gcov_read_unsigned ();
224e4b17023SJohn Marino 	      lineno_checksum = gcov_read_unsigned ();
225e4b17023SJohn Marino 	      cfg_checksum = gcov_read_unsigned ();
226e4b17023SJohn Marino 	    }
227e4b17023SJohn Marino 	  else
228e4b17023SJohn Marino 	    fn_ident = lineno_checksum = cfg_checksum = 0;
229e4b17023SJohn Marino 	  new_summary = 1;
230e4b17023SJohn Marino 	}
231e4b17023SJohn Marino       else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
232e4b17023SJohn Marino 	{
233e4b17023SJohn Marino 	  struct gcov_summary sum;
234e4b17023SJohn Marino 	  unsigned ix;
235e4b17023SJohn Marino 
236e4b17023SJohn Marino 	  if (new_summary)
237e4b17023SJohn Marino 	    memset (&summary, 0, sizeof (summary));
238e4b17023SJohn Marino 
239e4b17023SJohn Marino 	  gcov_read_summary (&sum);
240e4b17023SJohn Marino 	  for (ix = 0; ix != GCOV_COUNTERS_SUMMABLE; ix++)
241e4b17023SJohn Marino 	    {
242e4b17023SJohn Marino 	      summary.ctrs[ix].runs += sum.ctrs[ix].runs;
243e4b17023SJohn Marino 	      summary.ctrs[ix].sum_all += sum.ctrs[ix].sum_all;
244e4b17023SJohn Marino 	      if (summary.ctrs[ix].run_max < sum.ctrs[ix].run_max)
245e4b17023SJohn Marino 		summary.ctrs[ix].run_max = sum.ctrs[ix].run_max;
246e4b17023SJohn Marino 	      summary.ctrs[ix].sum_max += sum.ctrs[ix].sum_max;
247e4b17023SJohn Marino 	    }
248e4b17023SJohn Marino 	  new_summary = 0;
249e4b17023SJohn Marino 	}
250e4b17023SJohn Marino       else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
251e4b17023SJohn Marino 	{
252e4b17023SJohn Marino 	  counts_entry_t **slot, *entry, elt;
253e4b17023SJohn Marino 	  unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
254e4b17023SJohn Marino 	  unsigned ix;
255e4b17023SJohn Marino 
256e4b17023SJohn Marino 	  elt.ident = fn_ident;
257e4b17023SJohn Marino 	  elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
258e4b17023SJohn Marino 
259e4b17023SJohn Marino 	  slot = (counts_entry_t **) htab_find_slot
260e4b17023SJohn Marino 	    (counts_hash, &elt, INSERT);
261e4b17023SJohn Marino 	  entry = *slot;
262e4b17023SJohn Marino 	  if (!entry)
263e4b17023SJohn Marino 	    {
264e4b17023SJohn Marino 	      *slot = entry = XCNEW (counts_entry_t);
265e4b17023SJohn Marino 	      entry->ident = fn_ident;
266e4b17023SJohn Marino 	      entry->ctr = elt.ctr;
267e4b17023SJohn Marino 	      entry->lineno_checksum = lineno_checksum;
268e4b17023SJohn Marino 	      entry->cfg_checksum = cfg_checksum;
269e4b17023SJohn Marino 	      entry->summary = summary.ctrs[elt.ctr];
270e4b17023SJohn Marino 	      entry->summary.num = n_counts;
271e4b17023SJohn Marino 	      entry->counts = XCNEWVEC (gcov_type, n_counts);
272e4b17023SJohn Marino 	    }
273e4b17023SJohn Marino 	  else if (entry->lineno_checksum != lineno_checksum
274e4b17023SJohn Marino 		   || entry->cfg_checksum != cfg_checksum)
275e4b17023SJohn Marino 	    {
276e4b17023SJohn Marino 	      error ("Profile data for function %u is corrupted", fn_ident);
277e4b17023SJohn Marino 	      error ("checksum is (%x,%x) instead of (%x,%x)",
278e4b17023SJohn Marino 		     entry->lineno_checksum, entry->cfg_checksum,
279e4b17023SJohn Marino 		     lineno_checksum, cfg_checksum);
280e4b17023SJohn Marino 	      htab_delete (counts_hash);
281e4b17023SJohn Marino 	      break;
282e4b17023SJohn Marino 	    }
283e4b17023SJohn Marino 	  else if (entry->summary.num != n_counts)
284e4b17023SJohn Marino 	    {
285e4b17023SJohn Marino 	      error ("Profile data for function %u is corrupted", fn_ident);
286e4b17023SJohn Marino 	      error ("number of counters is %d instead of %d", entry->summary.num, n_counts);
287e4b17023SJohn Marino 	      htab_delete (counts_hash);
288e4b17023SJohn Marino 	      break;
289e4b17023SJohn Marino 	    }
290e4b17023SJohn Marino 	  else if (elt.ctr >= GCOV_COUNTERS_SUMMABLE)
291e4b17023SJohn Marino 	    {
292e4b17023SJohn Marino 	      error ("cannot merge separate %s counters for function %u",
293e4b17023SJohn Marino 		     ctr_names[elt.ctr], fn_ident);
294e4b17023SJohn Marino 	      goto skip_merge;
295e4b17023SJohn Marino 	    }
296e4b17023SJohn Marino 	  else
297e4b17023SJohn Marino 	    {
298e4b17023SJohn Marino 	      entry->summary.runs += summary.ctrs[elt.ctr].runs;
299e4b17023SJohn Marino 	      entry->summary.sum_all += summary.ctrs[elt.ctr].sum_all;
300e4b17023SJohn Marino 	      if (entry->summary.run_max < summary.ctrs[elt.ctr].run_max)
301e4b17023SJohn Marino 		entry->summary.run_max = summary.ctrs[elt.ctr].run_max;
302e4b17023SJohn Marino 	      entry->summary.sum_max += summary.ctrs[elt.ctr].sum_max;
303e4b17023SJohn Marino 	    }
304e4b17023SJohn Marino 	  for (ix = 0; ix != n_counts; ix++)
305e4b17023SJohn Marino 	    entry->counts[ix] += gcov_read_counter ();
306e4b17023SJohn Marino 	skip_merge:;
307e4b17023SJohn Marino 	}
308e4b17023SJohn Marino       gcov_sync (offset, length);
309e4b17023SJohn Marino       if ((is_error = gcov_is_error ()))
310e4b17023SJohn Marino 	{
311e4b17023SJohn Marino 	  error (is_error < 0 ? "%qs has overflowed" : "%qs is corrupted",
312e4b17023SJohn Marino 		 da_file_name);
313e4b17023SJohn Marino 	  htab_delete (counts_hash);
314e4b17023SJohn Marino 	  break;
315e4b17023SJohn Marino 	}
316e4b17023SJohn Marino     }
317e4b17023SJohn Marino 
318e4b17023SJohn Marino   gcov_close ();
319e4b17023SJohn Marino }
320e4b17023SJohn Marino 
321e4b17023SJohn Marino /* Returns the counters for a particular tag.  */
322e4b17023SJohn Marino 
323e4b17023SJohn Marino gcov_type *
get_coverage_counts(unsigned counter,unsigned expected,unsigned cfg_checksum,unsigned lineno_checksum,const struct gcov_ctr_summary ** summary)324e4b17023SJohn Marino get_coverage_counts (unsigned counter, unsigned expected,
325e4b17023SJohn Marino                      unsigned cfg_checksum, unsigned lineno_checksum,
326e4b17023SJohn Marino 		     const struct gcov_ctr_summary **summary)
327e4b17023SJohn Marino {
328e4b17023SJohn Marino   counts_entry_t *entry, elt;
329e4b17023SJohn Marino 
330e4b17023SJohn Marino   /* No hash table, no counts.  */
331e4b17023SJohn Marino   if (!counts_hash)
332e4b17023SJohn Marino     {
333e4b17023SJohn Marino       static int warned = 0;
334e4b17023SJohn Marino 
335e4b17023SJohn Marino       if (!warned++)
336e4b17023SJohn Marino 	inform (input_location, (flag_guess_branch_prob
337e4b17023SJohn Marino 		 ? "file %s not found, execution counts estimated"
338e4b17023SJohn Marino 		 : "file %s not found, execution counts assumed to be zero"),
339e4b17023SJohn Marino 		da_file_name);
340e4b17023SJohn Marino       return NULL;
341e4b17023SJohn Marino     }
342e4b17023SJohn Marino 
343e4b17023SJohn Marino   elt.ident = current_function_funcdef_no + 1;
344e4b17023SJohn Marino   elt.ctr = counter;
345e4b17023SJohn Marino   entry = (counts_entry_t *) htab_find (counts_hash, &elt);
346e4b17023SJohn Marino   if (!entry || !entry->summary.num)
347e4b17023SJohn Marino     /* The function was not emitted, or is weak and not chosen in the
348e4b17023SJohn Marino        final executable.  Silently fail, because there's nothing we
349e4b17023SJohn Marino        can do about it.  */
350e4b17023SJohn Marino     return NULL;
351e4b17023SJohn Marino 
352e4b17023SJohn Marino   if (entry->cfg_checksum != cfg_checksum
353e4b17023SJohn Marino       || entry->summary.num != expected)
354e4b17023SJohn Marino     {
355e4b17023SJohn Marino       static int warned = 0;
356e4b17023SJohn Marino       bool warning_printed = false;
357e4b17023SJohn Marino       tree id = DECL_ASSEMBLER_NAME (current_function_decl);
358e4b17023SJohn Marino 
359e4b17023SJohn Marino       warning_printed =
360e4b17023SJohn Marino 	warning_at (input_location, OPT_Wcoverage_mismatch,
361e4b17023SJohn Marino 		    "the control flow of function %qE does not match "
362e4b17023SJohn Marino 		    "its profile data (counter %qs)", id, ctr_names[counter]);
363e4b17023SJohn Marino       if (warning_printed)
364e4b17023SJohn Marino 	{
365e4b17023SJohn Marino 	 inform (input_location, "use -Wno-error=coverage-mismatch to tolerate "
366e4b17023SJohn Marino 	 	 "the mismatch but performance may drop if the function is hot");
367e4b17023SJohn Marino 
368e4b17023SJohn Marino 	  if (!seen_error ()
369e4b17023SJohn Marino 	      && !warned++)
370e4b17023SJohn Marino 	    {
371e4b17023SJohn Marino 	      inform (input_location, "coverage mismatch ignored");
372e4b17023SJohn Marino 	      inform (input_location, flag_guess_branch_prob
373e4b17023SJohn Marino 		      ? G_("execution counts estimated")
374e4b17023SJohn Marino 		      : G_("execution counts assumed to be zero"));
375e4b17023SJohn Marino 	      if (!flag_guess_branch_prob)
376e4b17023SJohn Marino 		inform (input_location,
377e4b17023SJohn Marino 			"this can result in poorly optimized code");
378e4b17023SJohn Marino 	    }
379e4b17023SJohn Marino 	}
380e4b17023SJohn Marino 
381e4b17023SJohn Marino       return NULL;
382e4b17023SJohn Marino     }
383e4b17023SJohn Marino   else if (entry->lineno_checksum != lineno_checksum)
384e4b17023SJohn Marino     {
385e4b17023SJohn Marino       warning (0, "source locations for function %qE have changed,"
386e4b17023SJohn Marino 	       " the profile data may be out of date",
387e4b17023SJohn Marino 	       DECL_ASSEMBLER_NAME (current_function_decl));
388e4b17023SJohn Marino     }
389e4b17023SJohn Marino 
390e4b17023SJohn Marino   if (summary)
391e4b17023SJohn Marino     *summary = &entry->summary;
392e4b17023SJohn Marino 
393e4b17023SJohn Marino   return entry->counts;
394e4b17023SJohn Marino }
395e4b17023SJohn Marino 
396e4b17023SJohn Marino /* Allocate NUM counters of type COUNTER. Returns nonzero if the
397e4b17023SJohn Marino    allocation succeeded.  */
398e4b17023SJohn Marino 
399e4b17023SJohn Marino int
coverage_counter_alloc(unsigned counter,unsigned num)400e4b17023SJohn Marino coverage_counter_alloc (unsigned counter, unsigned num)
401e4b17023SJohn Marino {
402e4b17023SJohn Marino   if (no_coverage)
403e4b17023SJohn Marino     return 0;
404e4b17023SJohn Marino 
405e4b17023SJohn Marino   if (!num)
406e4b17023SJohn Marino     return 1;
407e4b17023SJohn Marino 
408e4b17023SJohn Marino   if (!fn_v_ctrs[counter])
409e4b17023SJohn Marino     {
410e4b17023SJohn Marino       tree array_type = build_array_type (get_gcov_type (), NULL_TREE);
411e4b17023SJohn Marino 
412e4b17023SJohn Marino       fn_v_ctrs[counter]
413e4b17023SJohn Marino 	= build_var (current_function_decl, array_type, counter);
414e4b17023SJohn Marino     }
415e4b17023SJohn Marino 
416e4b17023SJohn Marino   fn_b_ctrs[counter] = fn_n_ctrs[counter];
417e4b17023SJohn Marino   fn_n_ctrs[counter] += num;
418e4b17023SJohn Marino 
419e4b17023SJohn Marino   fn_ctr_mask |= 1 << counter;
420e4b17023SJohn Marino   return 1;
421e4b17023SJohn Marino }
422e4b17023SJohn Marino 
423e4b17023SJohn Marino /* Generate a tree to access COUNTER NO.  */
424e4b17023SJohn Marino 
425e4b17023SJohn Marino tree
tree_coverage_counter_ref(unsigned counter,unsigned no)426e4b17023SJohn Marino tree_coverage_counter_ref (unsigned counter, unsigned no)
427e4b17023SJohn Marino {
428e4b17023SJohn Marino   tree gcov_type_node = get_gcov_type ();
429e4b17023SJohn Marino 
430e4b17023SJohn Marino   gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
431e4b17023SJohn Marino 
432e4b17023SJohn Marino   no += fn_b_ctrs[counter];
433e4b17023SJohn Marino 
434e4b17023SJohn Marino   /* "no" here is an array index, scaled to bytes later.  */
435e4b17023SJohn Marino   return build4 (ARRAY_REF, gcov_type_node, fn_v_ctrs[counter],
436e4b17023SJohn Marino 		 build_int_cst (integer_type_node, no), NULL, NULL);
437e4b17023SJohn Marino }
438e4b17023SJohn Marino 
439e4b17023SJohn Marino /* Generate a tree to access the address of COUNTER NO.  */
440e4b17023SJohn Marino 
441e4b17023SJohn Marino tree
tree_coverage_counter_addr(unsigned counter,unsigned no)442e4b17023SJohn Marino tree_coverage_counter_addr (unsigned counter, unsigned no)
443e4b17023SJohn Marino {
444e4b17023SJohn Marino   tree gcov_type_node = get_gcov_type ();
445e4b17023SJohn Marino 
446e4b17023SJohn Marino   gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
447e4b17023SJohn Marino   no += fn_b_ctrs[counter];
448e4b17023SJohn Marino 
449e4b17023SJohn Marino   /* "no" here is an array index, scaled to bytes later.  */
450e4b17023SJohn Marino   return build_fold_addr_expr (build4 (ARRAY_REF, gcov_type_node,
451e4b17023SJohn Marino 				       fn_v_ctrs[counter],
452e4b17023SJohn Marino 				       build_int_cst (integer_type_node, no),
453e4b17023SJohn Marino 				       NULL, NULL));
454e4b17023SJohn Marino }
455e4b17023SJohn Marino 
456e4b17023SJohn Marino 
457e4b17023SJohn Marino /* Generate a checksum for a string.  CHKSUM is the current
458e4b17023SJohn Marino    checksum.  */
459e4b17023SJohn Marino 
460e4b17023SJohn Marino static unsigned
coverage_checksum_string(unsigned chksum,const char * string)461e4b17023SJohn Marino coverage_checksum_string (unsigned chksum, const char *string)
462e4b17023SJohn Marino {
463e4b17023SJohn Marino   int i;
464e4b17023SJohn Marino   char *dup = NULL;
465e4b17023SJohn Marino 
466e4b17023SJohn Marino   /* Look for everything that looks if it were produced by
467e4b17023SJohn Marino      get_file_function_name and zero out the second part
468e4b17023SJohn Marino      that may result from flag_random_seed.  This is not critical
469e4b17023SJohn Marino      as the checksums are used only for sanity checking.  */
470e4b17023SJohn Marino   for (i = 0; string[i]; i++)
471e4b17023SJohn Marino     {
472e4b17023SJohn Marino       int offset = 0;
473e4b17023SJohn Marino       if (!strncmp (string + i, "_GLOBAL__N_", 11))
474e4b17023SJohn Marino       offset = 11;
475e4b17023SJohn Marino       if (!strncmp (string + i, "_GLOBAL__", 9))
476e4b17023SJohn Marino       offset = 9;
477e4b17023SJohn Marino 
478e4b17023SJohn Marino       /* C++ namespaces do have scheme:
479e4b17023SJohn Marino          _GLOBAL__N_<filename>_<wrongmagicnumber>_<magicnumber>functionname
480e4b17023SJohn Marino        since filename might contain extra underscores there seems
481e4b17023SJohn Marino        to be no better chance then walk all possible offsets looking
482e4b17023SJohn Marino        for magicnumber.  */
483e4b17023SJohn Marino       if (offset)
484e4b17023SJohn Marino 	{
485e4b17023SJohn Marino 	  for (i = i + offset; string[i]; i++)
486e4b17023SJohn Marino 	    if (string[i]=='_')
487e4b17023SJohn Marino 	      {
488e4b17023SJohn Marino 		int y;
489e4b17023SJohn Marino 
490e4b17023SJohn Marino 		for (y = 1; y < 9; y++)
491e4b17023SJohn Marino 		  if (!(string[i + y] >= '0' && string[i + y] <= '9')
492e4b17023SJohn Marino 		      && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
493e4b17023SJohn Marino 		    break;
494e4b17023SJohn Marino 		if (y != 9 || string[i + 9] != '_')
495e4b17023SJohn Marino 		  continue;
496e4b17023SJohn Marino 		for (y = 10; y < 18; y++)
497e4b17023SJohn Marino 		  if (!(string[i + y] >= '0' && string[i + y] <= '9')
498e4b17023SJohn Marino 		      && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
499e4b17023SJohn Marino 		    break;
500e4b17023SJohn Marino 		if (y != 18)
501e4b17023SJohn Marino 		  continue;
502e4b17023SJohn Marino 		if (!dup)
503e4b17023SJohn Marino 		  string = dup = xstrdup (string);
504e4b17023SJohn Marino 		for (y = 10; y < 18; y++)
505e4b17023SJohn Marino 		  dup[i + y] = '0';
506e4b17023SJohn Marino 	      }
507e4b17023SJohn Marino 	  break;
508e4b17023SJohn Marino 	}
509e4b17023SJohn Marino     }
510e4b17023SJohn Marino 
511e4b17023SJohn Marino   chksum = crc32_string (chksum, string);
512e4b17023SJohn Marino   free (dup);
513e4b17023SJohn Marino 
514e4b17023SJohn Marino   return chksum;
515e4b17023SJohn Marino }
516e4b17023SJohn Marino 
517e4b17023SJohn Marino /* Compute checksum for the current function.  We generate a CRC32.  */
518e4b17023SJohn Marino 
519e4b17023SJohn Marino unsigned
coverage_compute_lineno_checksum(void)520e4b17023SJohn Marino coverage_compute_lineno_checksum (void)
521e4b17023SJohn Marino {
522e4b17023SJohn Marino   expanded_location xloc
523e4b17023SJohn Marino     = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
524e4b17023SJohn Marino   unsigned chksum = xloc.line;
525e4b17023SJohn Marino 
526e4b17023SJohn Marino   chksum = coverage_checksum_string (chksum, xloc.file);
527e4b17023SJohn Marino   chksum = coverage_checksum_string
528e4b17023SJohn Marino     (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
529e4b17023SJohn Marino 
530e4b17023SJohn Marino   return chksum;
531e4b17023SJohn Marino }
532e4b17023SJohn Marino 
533e4b17023SJohn Marino /* Compute cfg checksum for the current function.
534e4b17023SJohn Marino    The checksum is calculated carefully so that
535e4b17023SJohn Marino    source code changes that doesn't affect the control flow graph
536e4b17023SJohn Marino    won't change the checksum.
537e4b17023SJohn Marino    This is to make the profile data useable across source code change.
538e4b17023SJohn Marino    The downside of this is that the compiler may use potentially
539e4b17023SJohn Marino    wrong profile data - that the source code change has non-trivial impact
540e4b17023SJohn Marino    on the validity of profile data (e.g. the reversed condition)
541e4b17023SJohn Marino    but the compiler won't detect the change and use the wrong profile data.  */
542e4b17023SJohn Marino 
543e4b17023SJohn Marino unsigned
coverage_compute_cfg_checksum(void)544e4b17023SJohn Marino coverage_compute_cfg_checksum (void)
545e4b17023SJohn Marino {
546e4b17023SJohn Marino   basic_block bb;
547e4b17023SJohn Marino   unsigned chksum = n_basic_blocks;
548e4b17023SJohn Marino 
549e4b17023SJohn Marino   FOR_EACH_BB (bb)
550e4b17023SJohn Marino     {
551e4b17023SJohn Marino       edge e;
552e4b17023SJohn Marino       edge_iterator ei;
553e4b17023SJohn Marino       chksum = crc32_byte (chksum, bb->index);
554e4b17023SJohn Marino       FOR_EACH_EDGE (e, ei, bb->succs)
555e4b17023SJohn Marino         {
556e4b17023SJohn Marino           chksum = crc32_byte (chksum, e->dest->index);
557e4b17023SJohn Marino         }
558e4b17023SJohn Marino     }
559e4b17023SJohn Marino 
560e4b17023SJohn Marino   return chksum;
561e4b17023SJohn Marino }
562e4b17023SJohn Marino 
563e4b17023SJohn Marino /* Begin output to the graph file for the current function.
564e4b17023SJohn Marino    Writes the function header. Returns nonzero if data should be output.  */
565e4b17023SJohn Marino 
566e4b17023SJohn Marino int
coverage_begin_function(unsigned lineno_checksum,unsigned cfg_checksum)567e4b17023SJohn Marino coverage_begin_function (unsigned lineno_checksum, unsigned cfg_checksum)
568e4b17023SJohn Marino {
569e4b17023SJohn Marino   expanded_location xloc;
570e4b17023SJohn Marino   unsigned long offset;
571e4b17023SJohn Marino 
572e4b17023SJohn Marino   /* We don't need to output .gcno file unless we're under -ftest-coverage
573e4b17023SJohn Marino      (e.g. -fprofile-arcs/generate/use don't need .gcno to work). */
574e4b17023SJohn Marino   if (no_coverage || !bbg_file_name)
575e4b17023SJohn Marino     return 0;
576e4b17023SJohn Marino 
577e4b17023SJohn Marino   xloc = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
578e4b17023SJohn Marino 
579e4b17023SJohn Marino   /* Announce function */
580e4b17023SJohn Marino   offset = gcov_write_tag (GCOV_TAG_FUNCTION);
581e4b17023SJohn Marino   gcov_write_unsigned (current_function_funcdef_no + 1);
582e4b17023SJohn Marino   gcov_write_unsigned (lineno_checksum);
583e4b17023SJohn Marino   gcov_write_unsigned (cfg_checksum);
584e4b17023SJohn Marino   gcov_write_string (IDENTIFIER_POINTER
585e4b17023SJohn Marino 		     (DECL_ASSEMBLER_NAME (current_function_decl)));
586e4b17023SJohn Marino   gcov_write_string (xloc.file);
587e4b17023SJohn Marino   gcov_write_unsigned (xloc.line);
588e4b17023SJohn Marino   gcov_write_length (offset);
589e4b17023SJohn Marino 
590e4b17023SJohn Marino   return !gcov_is_error ();
591e4b17023SJohn Marino }
592e4b17023SJohn Marino 
593e4b17023SJohn Marino /* Finish coverage data for the current function. Verify no output
594e4b17023SJohn Marino    error has occurred.  Save function coverage counts.  */
595e4b17023SJohn Marino 
596e4b17023SJohn Marino void
coverage_end_function(unsigned lineno_checksum,unsigned cfg_checksum)597e4b17023SJohn Marino coverage_end_function (unsigned lineno_checksum, unsigned cfg_checksum)
598e4b17023SJohn Marino {
599e4b17023SJohn Marino   unsigned i;
600e4b17023SJohn Marino 
601e4b17023SJohn Marino   if (bbg_file_name && gcov_is_error ())
602e4b17023SJohn Marino     {
603e4b17023SJohn Marino       warning (0, "error writing %qs", bbg_file_name);
604e4b17023SJohn Marino       unlink (bbg_file_name);
605e4b17023SJohn Marino       bbg_file_name = NULL;
606e4b17023SJohn Marino     }
607e4b17023SJohn Marino 
608e4b17023SJohn Marino   if (fn_ctr_mask)
609e4b17023SJohn Marino     {
610e4b17023SJohn Marino       struct coverage_data *item = 0;
611e4b17023SJohn Marino 
612e4b17023SJohn Marino       /* If the function is extern (i.e. extern inline), then we won't
613e4b17023SJohn Marino 	 be outputting it, so don't chain it onto the function
614e4b17023SJohn Marino 	 list.  */
615e4b17023SJohn Marino       if (!DECL_EXTERNAL (current_function_decl))
616e4b17023SJohn Marino 	{
617e4b17023SJohn Marino 	  item = ggc_alloc_coverage_data ();
618e4b17023SJohn Marino 
619e4b17023SJohn Marino 	  item->ident = current_function_funcdef_no + 1;
620e4b17023SJohn Marino 	  item->lineno_checksum = lineno_checksum;
621e4b17023SJohn Marino 	  item->cfg_checksum = cfg_checksum;
622e4b17023SJohn Marino 
623e4b17023SJohn Marino 	  item->fn_decl = current_function_decl;
624e4b17023SJohn Marino 	  item->next = 0;
625e4b17023SJohn Marino 	  *functions_tail = item;
626e4b17023SJohn Marino 	  functions_tail = &item->next;
627e4b17023SJohn Marino 	}
628e4b17023SJohn Marino 
629e4b17023SJohn Marino       for (i = 0; i != GCOV_COUNTERS; i++)
630e4b17023SJohn Marino 	{
631e4b17023SJohn Marino 	  tree var = fn_v_ctrs[i];
632e4b17023SJohn Marino 
633e4b17023SJohn Marino 	  if (item)
634e4b17023SJohn Marino 	    item->ctr_vars[i] = var;
635e4b17023SJohn Marino 	  if (var)
636e4b17023SJohn Marino 	    {
637e4b17023SJohn Marino 	      tree array_type = build_index_type (size_int (fn_n_ctrs[i] - 1));
638e4b17023SJohn Marino 	      array_type = build_array_type (get_gcov_type (), array_type);
639e4b17023SJohn Marino 	      TREE_TYPE (var) = array_type;
640e4b17023SJohn Marino 	      DECL_SIZE (var) = TYPE_SIZE (array_type);
641e4b17023SJohn Marino 	      DECL_SIZE_UNIT (var) = TYPE_SIZE_UNIT (array_type);
642e4b17023SJohn Marino 	      varpool_finalize_decl (var);
643e4b17023SJohn Marino 	    }
644e4b17023SJohn Marino 
645e4b17023SJohn Marino 	  fn_b_ctrs[i] = fn_n_ctrs[i] = 0;
646e4b17023SJohn Marino 	  fn_v_ctrs[i] = NULL_TREE;
647e4b17023SJohn Marino 	}
648e4b17023SJohn Marino       prg_ctr_mask |= fn_ctr_mask;
649e4b17023SJohn Marino       fn_ctr_mask = 0;
650e4b17023SJohn Marino     }
651e4b17023SJohn Marino }
652e4b17023SJohn Marino 
653e4b17023SJohn Marino /* Build a coverage variable of TYPE for function FN_DECL.  If COUNTER
654e4b17023SJohn Marino    >= 0 it is a counter array, otherwise it is the function structure.  */
655e4b17023SJohn Marino 
656e4b17023SJohn Marino static tree
build_var(tree fn_decl,tree type,int counter)657e4b17023SJohn Marino build_var (tree fn_decl, tree type, int counter)
658e4b17023SJohn Marino {
659e4b17023SJohn Marino   tree var = build_decl (BUILTINS_LOCATION, VAR_DECL, NULL_TREE, type);
660e4b17023SJohn Marino   const char *fn_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fn_decl));
661e4b17023SJohn Marino   char *buf;
662e4b17023SJohn Marino   size_t fn_name_len, len;
663e4b17023SJohn Marino 
664e4b17023SJohn Marino   fn_name = targetm.strip_name_encoding (fn_name);
665e4b17023SJohn Marino   fn_name_len = strlen (fn_name);
666e4b17023SJohn Marino   buf = XALLOCAVEC (char, fn_name_len + 8 + sizeof (int) * 3);
667e4b17023SJohn Marino 
668e4b17023SJohn Marino   if (counter < 0)
669e4b17023SJohn Marino     strcpy (buf, "__gcov__");
670e4b17023SJohn Marino   else
671e4b17023SJohn Marino     sprintf (buf, "__gcov%u_", counter);
672e4b17023SJohn Marino   len = strlen (buf);
673e4b17023SJohn Marino #ifndef NO_DOT_IN_LABEL
674e4b17023SJohn Marino   buf[len - 1] = '.';
675e4b17023SJohn Marino #elif !defined NO_DOLLAR_IN_LABEL
676e4b17023SJohn Marino   buf[len - 1] = '$';
677e4b17023SJohn Marino #endif
678e4b17023SJohn Marino   memcpy (buf + len, fn_name, fn_name_len + 1);
679e4b17023SJohn Marino   DECL_NAME (var) = get_identifier (buf);
680e4b17023SJohn Marino   TREE_STATIC (var) = 1;
681e4b17023SJohn Marino   TREE_ADDRESSABLE (var) = 1;
682e4b17023SJohn Marino   DECL_ALIGN (var) = TYPE_ALIGN (type);
683e4b17023SJohn Marino 
684e4b17023SJohn Marino   return var;
685e4b17023SJohn Marino }
686e4b17023SJohn Marino 
687e4b17023SJohn Marino /* Creates the gcov_fn_info RECORD_TYPE.  */
688e4b17023SJohn Marino 
689e4b17023SJohn Marino static void
build_fn_info_type(tree type,unsigned counters,tree gcov_info_type)690e4b17023SJohn Marino build_fn_info_type (tree type, unsigned counters, tree gcov_info_type)
691e4b17023SJohn Marino {
692e4b17023SJohn Marino   tree ctr_info = lang_hooks.types.make_type (RECORD_TYPE);
693e4b17023SJohn Marino   tree field, fields;
694e4b17023SJohn Marino   tree array_type;
695e4b17023SJohn Marino 
696e4b17023SJohn Marino   gcc_assert (counters);
697e4b17023SJohn Marino 
698e4b17023SJohn Marino   /* ctr_info::num */
699e4b17023SJohn Marino   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
700e4b17023SJohn Marino 		      get_gcov_unsigned_t ());
701e4b17023SJohn Marino   fields = field;
702e4b17023SJohn Marino 
703e4b17023SJohn Marino   /* ctr_info::values */
704e4b17023SJohn Marino   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
705e4b17023SJohn Marino 		      build_pointer_type (get_gcov_type ()));
706e4b17023SJohn Marino   DECL_CHAIN (field) = fields;
707e4b17023SJohn Marino   fields = field;
708e4b17023SJohn Marino 
709e4b17023SJohn Marino   finish_builtin_struct (ctr_info, "__gcov_ctr_info", fields, NULL_TREE);
710e4b17023SJohn Marino 
711e4b17023SJohn Marino   /* key */
712e4b17023SJohn Marino   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
713e4b17023SJohn Marino 		      build_pointer_type (build_qualified_type
714e4b17023SJohn Marino 					  (gcov_info_type, TYPE_QUAL_CONST)));
715e4b17023SJohn Marino   fields = field;
716e4b17023SJohn Marino 
717e4b17023SJohn Marino   /* ident */
718e4b17023SJohn Marino   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
719e4b17023SJohn Marino 		      get_gcov_unsigned_t ());
720e4b17023SJohn Marino   DECL_CHAIN (field) = fields;
721e4b17023SJohn Marino   fields = field;
722e4b17023SJohn Marino 
723e4b17023SJohn Marino   /* lineno_checksum */
724e4b17023SJohn Marino   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
725e4b17023SJohn Marino 		      get_gcov_unsigned_t ());
726e4b17023SJohn Marino   DECL_CHAIN (field) = fields;
727e4b17023SJohn Marino   fields = field;
728e4b17023SJohn Marino 
729e4b17023SJohn Marino   /* cfg checksum */
730e4b17023SJohn Marino   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
731e4b17023SJohn Marino 		      get_gcov_unsigned_t ());
732e4b17023SJohn Marino   DECL_CHAIN (field) = fields;
733e4b17023SJohn Marino   fields = field;
734e4b17023SJohn Marino 
735e4b17023SJohn Marino   array_type = build_index_type (size_int (counters - 1));
736e4b17023SJohn Marino   array_type = build_array_type (ctr_info, array_type);
737e4b17023SJohn Marino 
738e4b17023SJohn Marino   /* counters */
739e4b17023SJohn Marino   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, array_type);
740e4b17023SJohn Marino   DECL_CHAIN (field) = fields;
741e4b17023SJohn Marino   fields = field;
742e4b17023SJohn Marino 
743e4b17023SJohn Marino   finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
744e4b17023SJohn Marino }
745e4b17023SJohn Marino 
746e4b17023SJohn Marino /* Returns a CONSTRUCTOR for a gcov_fn_info.  DATA is
747e4b17023SJohn Marino    the coverage data for the function and TYPE is the gcov_fn_info
748e4b17023SJohn Marino    RECORD_TYPE.  KEY is the object file key.  */
749e4b17023SJohn Marino 
750e4b17023SJohn Marino static tree
build_fn_info(const struct coverage_data * data,tree type,tree key)751e4b17023SJohn Marino build_fn_info (const struct coverage_data *data, tree type, tree key)
752e4b17023SJohn Marino {
753e4b17023SJohn Marino   tree fields = TYPE_FIELDS (type);
754e4b17023SJohn Marino   tree ctr_type;
755e4b17023SJohn Marino   unsigned ix;
756e4b17023SJohn Marino   VEC(constructor_elt,gc) *v1 = NULL;
757e4b17023SJohn Marino   VEC(constructor_elt,gc) *v2 = NULL;
758e4b17023SJohn Marino 
759e4b17023SJohn Marino   /* key */
760e4b17023SJohn Marino   CONSTRUCTOR_APPEND_ELT (v1, fields,
761e4b17023SJohn Marino 			  build1 (ADDR_EXPR, TREE_TYPE (fields), key));
762e4b17023SJohn Marino   fields = DECL_CHAIN (fields);
763e4b17023SJohn Marino 
764e4b17023SJohn Marino   /* ident */
765e4b17023SJohn Marino   CONSTRUCTOR_APPEND_ELT (v1, fields,
766e4b17023SJohn Marino 			  build_int_cstu (get_gcov_unsigned_t (),
767e4b17023SJohn Marino 					  data->ident));
768e4b17023SJohn Marino   fields = DECL_CHAIN (fields);
769e4b17023SJohn Marino 
770e4b17023SJohn Marino   /* lineno_checksum */
771e4b17023SJohn Marino   CONSTRUCTOR_APPEND_ELT (v1, fields,
772e4b17023SJohn Marino 			  build_int_cstu (get_gcov_unsigned_t (),
773e4b17023SJohn Marino 					  data->lineno_checksum));
774e4b17023SJohn Marino   fields = DECL_CHAIN (fields);
775e4b17023SJohn Marino 
776e4b17023SJohn Marino   /* cfg_checksum */
777e4b17023SJohn Marino   CONSTRUCTOR_APPEND_ELT (v1, fields,
778e4b17023SJohn Marino 			  build_int_cstu (get_gcov_unsigned_t (),
779e4b17023SJohn Marino 					  data->cfg_checksum));
780e4b17023SJohn Marino   fields = DECL_CHAIN (fields);
781e4b17023SJohn Marino 
782e4b17023SJohn Marino   /* counters */
783e4b17023SJohn Marino   ctr_type = TREE_TYPE (TREE_TYPE (fields));
784e4b17023SJohn Marino   for (ix = 0; ix != GCOV_COUNTERS; ix++)
785e4b17023SJohn Marino     if (prg_ctr_mask & (1 << ix))
786e4b17023SJohn Marino       {
787e4b17023SJohn Marino 	VEC(constructor_elt,gc) *ctr = NULL;
788e4b17023SJohn Marino 	tree var = data->ctr_vars[ix];
789e4b17023SJohn Marino 	unsigned count = 0;
790e4b17023SJohn Marino 
791e4b17023SJohn Marino 	if (var)
792e4b17023SJohn Marino 	  count
793e4b17023SJohn Marino 	    = tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (var))), 0)
794e4b17023SJohn Marino 	    + 1;
795e4b17023SJohn Marino 
796e4b17023SJohn Marino 	CONSTRUCTOR_APPEND_ELT (ctr, TYPE_FIELDS (ctr_type),
797e4b17023SJohn Marino 				build_int_cstu (get_gcov_unsigned_t (),
798e4b17023SJohn Marino 						count));
799e4b17023SJohn Marino 
800e4b17023SJohn Marino 	if (var)
801e4b17023SJohn Marino 	  CONSTRUCTOR_APPEND_ELT (ctr, DECL_CHAIN (TYPE_FIELDS (ctr_type)),
802e4b17023SJohn Marino 				  build_fold_addr_expr (var));
803e4b17023SJohn Marino 
804e4b17023SJohn Marino 	CONSTRUCTOR_APPEND_ELT (v2, NULL, build_constructor (ctr_type, ctr));
805e4b17023SJohn Marino       }
806e4b17023SJohn Marino 
807e4b17023SJohn Marino   CONSTRUCTOR_APPEND_ELT (v1, fields,
808e4b17023SJohn Marino 			  build_constructor (TREE_TYPE (fields), v2));
809e4b17023SJohn Marino 
810e4b17023SJohn Marino   return build_constructor (type, v1);
811e4b17023SJohn Marino }
812e4b17023SJohn Marino 
813e4b17023SJohn Marino /* Create gcov_info struct.  TYPE is the incomplete RECORD_TYPE to be
814e4b17023SJohn Marino    completed, and FN_INFO_PTR_TYPE is a pointer to the function info type.  */
815e4b17023SJohn Marino 
816e4b17023SJohn Marino static void
build_info_type(tree type,tree fn_info_ptr_type)817e4b17023SJohn Marino build_info_type (tree type, tree fn_info_ptr_type)
818e4b17023SJohn Marino {
819e4b17023SJohn Marino   tree field, fields = NULL_TREE;
820e4b17023SJohn Marino   tree merge_fn_type;
821e4b17023SJohn Marino 
822e4b17023SJohn Marino   /* Version ident */
823e4b17023SJohn Marino   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
824e4b17023SJohn Marino 		      get_gcov_unsigned_t ());
825e4b17023SJohn Marino   DECL_CHAIN (field) = fields;
826e4b17023SJohn Marino   fields = field;
827e4b17023SJohn Marino 
828e4b17023SJohn Marino   /* next pointer */
829e4b17023SJohn Marino   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
830e4b17023SJohn Marino 		      build_pointer_type (build_qualified_type
831e4b17023SJohn Marino 					  (type, TYPE_QUAL_CONST)));
832e4b17023SJohn Marino   DECL_CHAIN (field) = fields;
833e4b17023SJohn Marino   fields = field;
834e4b17023SJohn Marino 
835e4b17023SJohn Marino   /* stamp */
836e4b17023SJohn Marino   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
837e4b17023SJohn Marino 		      get_gcov_unsigned_t ());
838e4b17023SJohn Marino   DECL_CHAIN (field) = fields;
839e4b17023SJohn Marino   fields = field;
840e4b17023SJohn Marino 
841e4b17023SJohn Marino   /* Filename */
842e4b17023SJohn Marino   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
843e4b17023SJohn Marino 		      build_pointer_type (build_qualified_type
844e4b17023SJohn Marino 					  (char_type_node, TYPE_QUAL_CONST)));
845e4b17023SJohn Marino   DECL_CHAIN (field) = fields;
846e4b17023SJohn Marino   fields = field;
847e4b17023SJohn Marino 
848e4b17023SJohn Marino   /* merge fn array */
849e4b17023SJohn Marino   merge_fn_type
850e4b17023SJohn Marino     = build_function_type_list (void_type_node,
851e4b17023SJohn Marino 				build_pointer_type (get_gcov_type ()),
852e4b17023SJohn Marino 				get_gcov_unsigned_t (), NULL_TREE);
853e4b17023SJohn Marino   merge_fn_type
854e4b17023SJohn Marino     = build_array_type (build_pointer_type (merge_fn_type),
855e4b17023SJohn Marino 			build_index_type (size_int (GCOV_COUNTERS - 1)));
856e4b17023SJohn Marino   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
857e4b17023SJohn Marino 		      merge_fn_type);
858e4b17023SJohn Marino   DECL_CHAIN (field) = fields;
859e4b17023SJohn Marino   fields = field;
860e4b17023SJohn Marino 
861e4b17023SJohn Marino   /* n_functions */
862e4b17023SJohn Marino   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
863e4b17023SJohn Marino 		      get_gcov_unsigned_t ());
864e4b17023SJohn Marino   DECL_CHAIN (field) = fields;
865e4b17023SJohn Marino   fields = field;
866e4b17023SJohn Marino 
867e4b17023SJohn Marino   /* function_info pointer pointer */
868e4b17023SJohn Marino   fn_info_ptr_type = build_pointer_type
869e4b17023SJohn Marino     (build_qualified_type (fn_info_ptr_type, TYPE_QUAL_CONST));
870e4b17023SJohn Marino   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
871e4b17023SJohn Marino 		      fn_info_ptr_type);
872e4b17023SJohn Marino   DECL_CHAIN (field) = fields;
873e4b17023SJohn Marino   fields = field;
874e4b17023SJohn Marino 
875e4b17023SJohn Marino   finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
876e4b17023SJohn Marino }
877e4b17023SJohn Marino 
878e4b17023SJohn Marino /* Returns a CONSTRUCTOR for the gcov_info object.  INFO_TYPE is the
879e4b17023SJohn Marino    gcov_info structure type, FN_ARY is the array of pointers to
880e4b17023SJohn Marino    function info objects.  */
881e4b17023SJohn Marino 
882e4b17023SJohn Marino static tree
build_info(tree info_type,tree fn_ary)883e4b17023SJohn Marino build_info (tree info_type, tree fn_ary)
884e4b17023SJohn Marino {
885e4b17023SJohn Marino   tree info_fields = TYPE_FIELDS (info_type);
886e4b17023SJohn Marino   tree merge_fn_type, n_funcs;
887e4b17023SJohn Marino   unsigned ix;
888e4b17023SJohn Marino   tree filename_string;
889e4b17023SJohn Marino   int da_file_name_len;
890e4b17023SJohn Marino   VEC(constructor_elt,gc) *v1 = NULL;
891e4b17023SJohn Marino   VEC(constructor_elt,gc) *v2 = NULL;
892e4b17023SJohn Marino 
893e4b17023SJohn Marino   /* Version ident */
894e4b17023SJohn Marino   CONSTRUCTOR_APPEND_ELT (v1, info_fields,
895e4b17023SJohn Marino 			  build_int_cstu (TREE_TYPE (info_fields),
896e4b17023SJohn Marino 					  GCOV_VERSION));
897e4b17023SJohn Marino   info_fields = DECL_CHAIN (info_fields);
898e4b17023SJohn Marino 
899e4b17023SJohn Marino   /* next -- NULL */
900e4b17023SJohn Marino   CONSTRUCTOR_APPEND_ELT (v1, info_fields, null_pointer_node);
901e4b17023SJohn Marino   info_fields = DECL_CHAIN (info_fields);
902e4b17023SJohn Marino 
903e4b17023SJohn Marino   /* stamp */
904e4b17023SJohn Marino   CONSTRUCTOR_APPEND_ELT (v1, info_fields,
905e4b17023SJohn Marino 			  build_int_cstu (TREE_TYPE (info_fields),
906e4b17023SJohn Marino 					  local_tick));
907e4b17023SJohn Marino   info_fields = DECL_CHAIN (info_fields);
908e4b17023SJohn Marino 
909e4b17023SJohn Marino   /* Filename */
910e4b17023SJohn Marino   da_file_name_len = strlen (da_file_name);
911e4b17023SJohn Marino   filename_string = build_string (da_file_name_len + 1, da_file_name);
912e4b17023SJohn Marino   TREE_TYPE (filename_string) = build_array_type
913e4b17023SJohn Marino     (char_type_node, build_index_type (size_int (da_file_name_len)));
914e4b17023SJohn Marino   CONSTRUCTOR_APPEND_ELT (v1, info_fields,
915e4b17023SJohn Marino 			  build1 (ADDR_EXPR, TREE_TYPE (info_fields),
916e4b17023SJohn Marino 				  filename_string));
917e4b17023SJohn Marino   info_fields = DECL_CHAIN (info_fields);
918e4b17023SJohn Marino 
919e4b17023SJohn Marino   /* merge fn array -- NULL slots indicate unmeasured counters */
920e4b17023SJohn Marino   merge_fn_type = TREE_TYPE (TREE_TYPE (info_fields));
921e4b17023SJohn Marino   for (ix = 0; ix != GCOV_COUNTERS; ix++)
922e4b17023SJohn Marino     {
923e4b17023SJohn Marino       tree ptr = null_pointer_node;
924e4b17023SJohn Marino 
925e4b17023SJohn Marino       if ((1u << ix) & prg_ctr_mask)
926e4b17023SJohn Marino 	{
927e4b17023SJohn Marino 	  tree merge_fn = build_decl (BUILTINS_LOCATION,
928e4b17023SJohn Marino 				      FUNCTION_DECL,
929e4b17023SJohn Marino 				      get_identifier (ctr_merge_functions[ix]),
930e4b17023SJohn Marino 				      TREE_TYPE (merge_fn_type));
931e4b17023SJohn Marino 	  DECL_EXTERNAL (merge_fn) = 1;
932e4b17023SJohn Marino 	  TREE_PUBLIC (merge_fn) = 1;
933e4b17023SJohn Marino 	  DECL_ARTIFICIAL (merge_fn) = 1;
934e4b17023SJohn Marino 	  TREE_NOTHROW (merge_fn) = 1;
935e4b17023SJohn Marino 	  /* Initialize assembler name so we can stream out. */
936e4b17023SJohn Marino 	  DECL_ASSEMBLER_NAME (merge_fn);
937e4b17023SJohn Marino 	  ptr = build1 (ADDR_EXPR, merge_fn_type, merge_fn);
938e4b17023SJohn Marino 	}
939e4b17023SJohn Marino       CONSTRUCTOR_APPEND_ELT (v2, NULL, ptr);
940e4b17023SJohn Marino     }
941e4b17023SJohn Marino   CONSTRUCTOR_APPEND_ELT (v1, info_fields,
942e4b17023SJohn Marino 			  build_constructor (TREE_TYPE (info_fields), v2));
943e4b17023SJohn Marino   info_fields = DECL_CHAIN (info_fields);
944e4b17023SJohn Marino 
945e4b17023SJohn Marino   /* n_functions */
946e4b17023SJohn Marino   n_funcs = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (fn_ary)));
947e4b17023SJohn Marino   n_funcs = fold_build2 (PLUS_EXPR, TREE_TYPE (info_fields),
948e4b17023SJohn Marino 			 n_funcs, size_one_node);
949e4b17023SJohn Marino   CONSTRUCTOR_APPEND_ELT (v1, info_fields, n_funcs);
950e4b17023SJohn Marino   info_fields = DECL_CHAIN (info_fields);
951e4b17023SJohn Marino 
952e4b17023SJohn Marino   /* functions */
953e4b17023SJohn Marino   CONSTRUCTOR_APPEND_ELT (v1, info_fields,
954e4b17023SJohn Marino 			  build1 (ADDR_EXPR, TREE_TYPE (info_fields), fn_ary));
955e4b17023SJohn Marino   info_fields = DECL_CHAIN (info_fields);
956e4b17023SJohn Marino 
957e4b17023SJohn Marino   gcc_assert (!info_fields);
958e4b17023SJohn Marino   return build_constructor (info_type, v1);
959e4b17023SJohn Marino }
960e4b17023SJohn Marino 
961e4b17023SJohn Marino /* Create the gcov_info types and object.  Generate the constructor
962e4b17023SJohn Marino    function to call __gcov_init.  Does not generate the initializer
963e4b17023SJohn Marino    for the object.  Returns TRUE if coverage data is being emitted.  */
964e4b17023SJohn Marino 
965e4b17023SJohn Marino static bool
coverage_obj_init(void)966e4b17023SJohn Marino coverage_obj_init (void)
967e4b17023SJohn Marino {
968e4b17023SJohn Marino   tree gcov_info_type, ctor, stmt, init_fn;
969e4b17023SJohn Marino   unsigned n_counters = 0;
970e4b17023SJohn Marino   unsigned ix;
971e4b17023SJohn Marino   struct coverage_data *fn;
972e4b17023SJohn Marino   struct coverage_data **fn_prev;
973e4b17023SJohn Marino   char name_buf[32];
974e4b17023SJohn Marino 
975e4b17023SJohn Marino   no_coverage = 1; /* Disable any further coverage.  */
976e4b17023SJohn Marino 
977e4b17023SJohn Marino   if (!prg_ctr_mask)
978e4b17023SJohn Marino     return false;
979e4b17023SJohn Marino 
980e4b17023SJohn Marino   if (cgraph_dump_file)
981e4b17023SJohn Marino     fprintf (cgraph_dump_file, "Using data file %s\n", da_file_name);
982e4b17023SJohn Marino 
983e4b17023SJohn Marino   /* Prune functions.  */
984e4b17023SJohn Marino   for (fn_prev = &functions_head; (fn = *fn_prev);)
985e4b17023SJohn Marino     if (DECL_STRUCT_FUNCTION (fn->fn_decl))
986e4b17023SJohn Marino       fn_prev = &fn->next;
987e4b17023SJohn Marino     else
988e4b17023SJohn Marino       /* The function is not being emitted, remove from list.  */
989e4b17023SJohn Marino       *fn_prev = fn->next;
990e4b17023SJohn Marino 
991*95d28233SJohn Marino   if (functions_head == NULL)
992*95d28233SJohn Marino     return false;
993*95d28233SJohn Marino 
994e4b17023SJohn Marino   for (ix = 0; ix != GCOV_COUNTERS; ix++)
995e4b17023SJohn Marino     if ((1u << ix) & prg_ctr_mask)
996e4b17023SJohn Marino       n_counters++;
997e4b17023SJohn Marino 
998e4b17023SJohn Marino   /* Build the info and fn_info types.  These are mutually recursive.  */
999e4b17023SJohn Marino   gcov_info_type = lang_hooks.types.make_type (RECORD_TYPE);
1000e4b17023SJohn Marino   gcov_fn_info_type = lang_hooks.types.make_type (RECORD_TYPE);
1001e4b17023SJohn Marino   gcov_fn_info_ptr_type = build_pointer_type
1002e4b17023SJohn Marino     (build_qualified_type (gcov_fn_info_type, TYPE_QUAL_CONST));
1003e4b17023SJohn Marino   build_fn_info_type (gcov_fn_info_type, n_counters, gcov_info_type);
1004e4b17023SJohn Marino   build_info_type (gcov_info_type, gcov_fn_info_ptr_type);
1005e4b17023SJohn Marino 
1006e4b17023SJohn Marino   /* Build the gcov info var, this is referred to in its own
1007e4b17023SJohn Marino      initializer.  */
1008e4b17023SJohn Marino   gcov_info_var = build_decl (BUILTINS_LOCATION,
1009e4b17023SJohn Marino 			      VAR_DECL, NULL_TREE, gcov_info_type);
1010e4b17023SJohn Marino   TREE_STATIC (gcov_info_var) = 1;
1011e4b17023SJohn Marino   ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
1012e4b17023SJohn Marino   DECL_NAME (gcov_info_var) = get_identifier (name_buf);
1013e4b17023SJohn Marino 
1014e4b17023SJohn Marino   /* Build a decl for __gcov_init.  */
1015e4b17023SJohn Marino   init_fn = build_pointer_type (gcov_info_type);
1016e4b17023SJohn Marino   init_fn = build_function_type_list (void_type_node, init_fn, NULL);
1017e4b17023SJohn Marino   init_fn = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
1018e4b17023SJohn Marino 			get_identifier ("__gcov_init"), init_fn);
1019e4b17023SJohn Marino   TREE_PUBLIC (init_fn) = 1;
1020e4b17023SJohn Marino   DECL_EXTERNAL (init_fn) = 1;
1021e4b17023SJohn Marino   DECL_ASSEMBLER_NAME (init_fn);
1022e4b17023SJohn Marino 
1023e4b17023SJohn Marino   /* Generate a call to __gcov_init(&gcov_info).  */
1024e4b17023SJohn Marino   ctor = NULL;
1025e4b17023SJohn Marino   stmt = build_fold_addr_expr (gcov_info_var);
1026e4b17023SJohn Marino   stmt = build_call_expr (init_fn, 1, stmt);
1027e4b17023SJohn Marino   append_to_statement_list (stmt, &ctor);
1028e4b17023SJohn Marino 
1029e4b17023SJohn Marino   /* Generate a constructor to run it.  */
1030e4b17023SJohn Marino   cgraph_build_static_cdtor ('I', ctor, DEFAULT_INIT_PRIORITY);
1031e4b17023SJohn Marino 
1032e4b17023SJohn Marino   return true;
1033e4b17023SJohn Marino }
1034e4b17023SJohn Marino 
1035e4b17023SJohn Marino /* Generate the coverage function info for FN and DATA.  Append a
1036e4b17023SJohn Marino    pointer to that object to CTOR and return the appended CTOR.  */
1037e4b17023SJohn Marino 
VEC(constructor_elt,gc)1038e4b17023SJohn Marino static VEC(constructor_elt,gc) *
1039e4b17023SJohn Marino coverage_obj_fn (VEC(constructor_elt,gc) *ctor, tree fn,
1040e4b17023SJohn Marino 		 struct coverage_data const *data)
1041e4b17023SJohn Marino {
1042e4b17023SJohn Marino   tree init = build_fn_info (data, gcov_fn_info_type, gcov_info_var);
1043e4b17023SJohn Marino   tree var = build_var (fn, gcov_fn_info_type, -1);
1044e4b17023SJohn Marino 
1045e4b17023SJohn Marino   DECL_INITIAL (var) = init;
1046e4b17023SJohn Marino   varpool_finalize_decl (var);
1047e4b17023SJohn Marino 
1048e4b17023SJohn Marino   CONSTRUCTOR_APPEND_ELT (ctor, NULL,
1049e4b17023SJohn Marino 			  build1 (ADDR_EXPR, gcov_fn_info_ptr_type, var));
1050e4b17023SJohn Marino   return ctor;
1051e4b17023SJohn Marino }
1052e4b17023SJohn Marino 
1053e4b17023SJohn Marino /* Finalize the coverage data.  Generates the array of pointers to
1054e4b17023SJohn Marino    function objects from CTOR.  Generate the gcov_info initializer.  */
1055e4b17023SJohn Marino 
1056e4b17023SJohn Marino static void
coverage_obj_finish(VEC (constructor_elt,gc)* ctor)1057e4b17023SJohn Marino coverage_obj_finish (VEC(constructor_elt,gc) *ctor)
1058e4b17023SJohn Marino {
1059e4b17023SJohn Marino   unsigned n_functions = VEC_length(constructor_elt, ctor);
1060e4b17023SJohn Marino   tree fn_info_ary_type = build_array_type
1061e4b17023SJohn Marino     (build_qualified_type (gcov_fn_info_ptr_type, TYPE_QUAL_CONST),
1062e4b17023SJohn Marino      build_index_type (size_int (n_functions - 1)));
1063e4b17023SJohn Marino   tree fn_info_ary = build_decl (BUILTINS_LOCATION, VAR_DECL, NULL_TREE,
1064e4b17023SJohn Marino 				 fn_info_ary_type);
1065e4b17023SJohn Marino   char name_buf[32];
1066e4b17023SJohn Marino 
1067e4b17023SJohn Marino   TREE_STATIC (fn_info_ary) = 1;
1068e4b17023SJohn Marino   ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 1);
1069e4b17023SJohn Marino   DECL_NAME (fn_info_ary) = get_identifier (name_buf);
1070e4b17023SJohn Marino   DECL_INITIAL (fn_info_ary) = build_constructor (fn_info_ary_type, ctor);
1071e4b17023SJohn Marino   varpool_finalize_decl (fn_info_ary);
1072e4b17023SJohn Marino 
1073e4b17023SJohn Marino   DECL_INITIAL (gcov_info_var)
1074e4b17023SJohn Marino     = build_info (TREE_TYPE (gcov_info_var), fn_info_ary);
1075e4b17023SJohn Marino   varpool_finalize_decl (gcov_info_var);
1076e4b17023SJohn Marino }
1077e4b17023SJohn Marino 
1078e4b17023SJohn Marino /* Perform file-level initialization. Read in data file, generate name
1079e4b17023SJohn Marino    of graph file.  */
1080e4b17023SJohn Marino 
1081e4b17023SJohn Marino void
coverage_init(const char * filename)1082e4b17023SJohn Marino coverage_init (const char *filename)
1083e4b17023SJohn Marino {
1084e4b17023SJohn Marino   int len = strlen (filename);
1085e4b17023SJohn Marino   int prefix_len = 0;
1086e4b17023SJohn Marino 
1087e4b17023SJohn Marino   if (!profile_data_prefix && !IS_ABSOLUTE_PATH (filename))
1088e4b17023SJohn Marino     profile_data_prefix = getpwd ();
1089e4b17023SJohn Marino 
1090e4b17023SJohn Marino   if (profile_data_prefix)
1091e4b17023SJohn Marino     prefix_len = strlen (profile_data_prefix);
1092e4b17023SJohn Marino 
1093e4b17023SJohn Marino   /* Name of da file.  */
1094e4b17023SJohn Marino   da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX)
1095e4b17023SJohn Marino 			  + prefix_len + 2);
1096e4b17023SJohn Marino 
1097e4b17023SJohn Marino   if (profile_data_prefix)
1098e4b17023SJohn Marino     {
1099e4b17023SJohn Marino       memcpy (da_file_name, profile_data_prefix, prefix_len);
1100e4b17023SJohn Marino       da_file_name[prefix_len++] = '/';
1101e4b17023SJohn Marino     }
1102e4b17023SJohn Marino   memcpy (da_file_name + prefix_len, filename, len);
1103e4b17023SJohn Marino   strcpy (da_file_name + prefix_len + len, GCOV_DATA_SUFFIX);
1104e4b17023SJohn Marino 
1105*95d28233SJohn Marino   if (flag_branch_probabilities)
1106*95d28233SJohn Marino     read_counts_file ();
1107*95d28233SJohn Marino 
1108e4b17023SJohn Marino   /* Name of bbg file.  */
1109e4b17023SJohn Marino   if (flag_test_coverage && !flag_compare_debug)
1110e4b17023SJohn Marino     {
1111e4b17023SJohn Marino       bbg_file_name = XNEWVEC (char, len + strlen (GCOV_NOTE_SUFFIX) + 1);
1112e4b17023SJohn Marino       memcpy (bbg_file_name, filename, len);
1113e4b17023SJohn Marino       strcpy (bbg_file_name + len, GCOV_NOTE_SUFFIX);
1114e4b17023SJohn Marino 
1115e4b17023SJohn Marino       if (!gcov_open (bbg_file_name, -1))
1116e4b17023SJohn Marino 	{
1117e4b17023SJohn Marino 	  error ("cannot open %s", bbg_file_name);
1118e4b17023SJohn Marino 	  bbg_file_name = NULL;
1119e4b17023SJohn Marino 	}
1120e4b17023SJohn Marino       else
1121e4b17023SJohn Marino 	{
1122e4b17023SJohn Marino 	  gcov_write_unsigned (GCOV_NOTE_MAGIC);
1123e4b17023SJohn Marino 	  gcov_write_unsigned (GCOV_VERSION);
1124e4b17023SJohn Marino 	  gcov_write_unsigned (local_tick);
1125e4b17023SJohn Marino 	}
1126e4b17023SJohn Marino     }
1127e4b17023SJohn Marino }
1128e4b17023SJohn Marino 
1129e4b17023SJohn Marino /* Performs file-level cleanup.  Close graph file, generate coverage
1130e4b17023SJohn Marino    variables and constructor.  */
1131e4b17023SJohn Marino 
1132e4b17023SJohn Marino void
coverage_finish(void)1133e4b17023SJohn Marino coverage_finish (void)
1134e4b17023SJohn Marino {
1135e4b17023SJohn Marino   if (bbg_file_name && gcov_close ())
1136e4b17023SJohn Marino     unlink (bbg_file_name);
1137e4b17023SJohn Marino 
1138e4b17023SJohn Marino   if (!local_tick || local_tick == (unsigned)-1)
1139e4b17023SJohn Marino     /* Only remove the da file, if we cannot stamp it.  If we can
1140e4b17023SJohn Marino        stamp it, libgcov will DTRT.  */
1141e4b17023SJohn Marino     unlink (da_file_name);
1142e4b17023SJohn Marino 
1143e4b17023SJohn Marino   if (coverage_obj_init ())
1144e4b17023SJohn Marino     {
1145e4b17023SJohn Marino       VEC(constructor_elt,gc) *fn_ctor = NULL;
1146e4b17023SJohn Marino       struct coverage_data *fn;
1147e4b17023SJohn Marino 
1148e4b17023SJohn Marino       for (fn = functions_head; fn; fn = fn->next)
1149e4b17023SJohn Marino 	fn_ctor = coverage_obj_fn (fn_ctor, fn->fn_decl, fn);
1150e4b17023SJohn Marino       coverage_obj_finish (fn_ctor);
1151e4b17023SJohn Marino     }
1152e4b17023SJohn Marino }
1153e4b17023SJohn Marino 
1154e4b17023SJohn Marino #include "gt-coverage.h"
1155