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