xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/coverage.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
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 
10 This file is part of GCC.
11 
12 GCC is free software; you can redistribute it and/or modify it under
13 the terms of the GNU General Public License as published by the Free
14 Software Foundation; either version 3, or (at your option) any later
15 version.
16 
17 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
18 WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 for more details.
21 
22 You should have received a copy of the GNU General Public License
23 along 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 
52 struct 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.  */
61 typedef 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 
77 static struct function_list *functions_head = 0;
78 static struct function_list **functions_tail = &functions_head;
79 static unsigned no_coverage = 0;
80 
81 /* Cumulative counter information for whole program.  */
82 static unsigned prg_ctr_mask; /* Mask of counter types generated.  */
83 static unsigned prg_n_ctrs[GCOV_COUNTERS]; /* Total counters allocated.  */
84 
85 /* Counter information for current function.  */
86 static unsigned fn_ctr_mask; /* Mask of counters used.  */
87 static unsigned fn_n_ctrs[GCOV_COUNTERS]; /* Counters allocated.  */
88 static unsigned fn_b_ctrs[GCOV_COUNTERS]; /* Allocation base.  */
89 
90 /* Name of the output file for coverage output file.  */
91 static char *bbg_file_name;
92 static unsigned bbg_file_opened;
93 static int bbg_function_announced;
94 
95 /* Name of the count data file.  */
96 static char *da_file_name;
97 
98 /* Hash table of count data.  */
99 static htab_t counts_hash = NULL;
100 
101 /* Trees representing the counter table arrays.  */
102 static 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.  */
106 static GTY(()) rtx ctr_labels[GCOV_COUNTERS];
107 
108 /* The names of merge functions for counters.  */
109 static const char *const ctr_merge_functions[GCOV_COUNTERS] = GCOV_MERGE_FUNCTIONS;
110 static const char *const ctr_names[GCOV_COUNTERS] = GCOV_COUNTER_NAMES;
111 
112 /* Forward declarations.  */
113 static hashval_t htab_counts_entry_hash (const void *);
114 static int htab_counts_entry_eq (const void *, const void *);
115 static void htab_counts_entry_del (void *);
116 static void read_counts_file (void);
117 static unsigned compute_checksum (void);
118 static unsigned coverage_checksum_string (unsigned, const char *);
119 static tree build_fn_info_type (unsigned);
120 static tree build_fn_info_value (const struct function_list *, tree);
121 static tree build_ctr_info_type (void);
122 static tree build_ctr_info_value (unsigned, tree);
123 static tree build_gcov_info (void);
124 static void create_coverage (void);
125 
126 /* Return the type node for gcov_type.  */
127 
128 tree
129 get_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 
136 static tree
137 get_gcov_unsigned_t (void)
138 {
139   return lang_hooks.types.type_for_size (32, true);
140 }
141 
142 static hashval_t
143 htab_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 
150 static int
151 htab_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 
159 static void
160 htab_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 
170 static void
171 read_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 
325 gcov_type *
326 get_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 
402 int
403 coverage_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 
439 tree
440 tree_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 
454 tree
455 tree_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 
474 static unsigned
475 coverage_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 
534 static unsigned
535 compute_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 
553 int
554 coverage_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 
598 void
599 coverage_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 
635 static tree
636 build_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 
671 static tree
672 build_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 
712 static tree
713 build_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 
752 static tree
753 build_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 
812 static tree
813 build_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 
954 static void
955 create_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 
1000 void
1001 coverage_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 
1039 void
1040 coverage_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