* call.c (z_candidate::template_decl): Rename from template.
[official-gcc.git] / gcc / coverage.c
blobabaad02d11d8e20c464bf0de1d89094fd6543c29
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 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
9 This file is part of GCC.
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.
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.
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, 59 Temple Place - Suite 330, Boston, MA
24 02111-1307, USA. */
27 #define GCOV_LINKAGE
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"
48 #include "gcov-io.c"
50 struct function_list
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. */
58 /* Counts information for a function. */
59 typedef struct counts_entry
61 /* We hash by */
62 unsigned ident;
63 unsigned ctr;
65 /* Store */
66 unsigned checksum;
67 gcov_type *counts;
68 struct gcov_ctr_summary summary;
70 /* Workspace */
71 struct counts_entry *chain;
73 } counts_entry_t;
75 static struct function_list *functions_head = 0;
76 static struct function_list **functions_tail = &functions_head;
77 static unsigned no_coverage = 0;
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. */
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. */
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;
93 /* Name of the count data file. */
94 static char *da_file_name;
96 /* Hash table of count data. */
97 static htab_t counts_hash = NULL;
99 /* Trees representing the counter table arrays. */
100 static GTY(()) tree tree_ctr_tables[GCOV_COUNTERS];
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];
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;
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);
125 static hashval_t
126 htab_counts_entry_hash (const void *of)
128 const counts_entry_t *entry = of;
130 return entry->ident * GCOV_COUNTERS + entry->ctr;
133 static int
134 htab_counts_entry_eq (const void *of1, const void *of2)
136 const counts_entry_t *entry1 = of1;
137 const counts_entry_t *entry2 = of2;
139 return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
142 static void
143 htab_counts_entry_del (void *of)
145 counts_entry_t *entry = of;
147 free (entry->counts);
148 free (entry);
151 /* Read in the counts file, if available. */
153 static void
154 read_counts_file (void)
156 gcov_unsigned_t fn_ident = 0;
157 gcov_unsigned_t checksum = -1;
158 counts_entry_t *summaried = NULL;
159 unsigned seen_summary = 0;
160 gcov_unsigned_t tag;
161 int is_error = 0;
163 if (!gcov_open (da_file_name, 1))
164 return;
166 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
168 warning ("`%s' is not a gcov data file", da_file_name);
169 gcov_close ();
170 return;
172 else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
174 char v[4], e[4];
176 GCOV_UNSIGNED2STRING (v, tag);
177 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
179 warning ("`%s' is version `%.*s', expected version `%.*s'",
180 da_file_name, 4, v, 4, e);
181 gcov_close ();
182 return;
185 /* Read and discard the stamp. */
186 gcov_read_unsigned ();
188 counts_hash = htab_create (10,
189 htab_counts_entry_hash, htab_counts_entry_eq,
190 htab_counts_entry_del);
191 while ((tag = gcov_read_unsigned ()))
193 gcov_unsigned_t length;
194 gcov_position_t offset;
196 length = gcov_read_unsigned ();
197 offset = gcov_position ();
198 if (tag == GCOV_TAG_FUNCTION)
200 fn_ident = gcov_read_unsigned ();
201 checksum = gcov_read_unsigned ();
202 if (seen_summary)
204 /* We have already seen a summary, this means that this
205 new function begins a new set of program runs. We
206 must unlink the summaried chain. */
207 counts_entry_t *entry, *chain;
209 for (entry = summaried; entry; entry = chain)
211 chain = entry->chain;
212 entry->chain = NULL;
214 summaried = NULL;
215 seen_summary = 0;
218 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
220 counts_entry_t *entry;
221 struct gcov_summary summary;
223 gcov_read_summary (&summary);
224 seen_summary = 1;
225 for (entry = summaried; entry; entry = entry->chain)
227 struct gcov_ctr_summary *csum = &summary.ctrs[entry->ctr];
229 entry->summary.runs += csum->runs;
230 entry->summary.sum_all += csum->sum_all;
231 if (entry->summary.run_max < csum->run_max)
232 entry->summary.run_max = csum->run_max;
233 entry->summary.sum_max += csum->sum_max;
236 else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
238 counts_entry_t **slot, *entry, elt;
239 unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
240 unsigned ix;
242 elt.ident = fn_ident;
243 elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
245 slot = (counts_entry_t **) htab_find_slot
246 (counts_hash, &elt, INSERT);
247 entry = *slot;
248 if (!entry)
250 *slot = entry = xcalloc (1, sizeof (counts_entry_t));
251 entry->ident = elt.ident;
252 entry->ctr = elt.ctr;
253 entry->checksum = checksum;
254 entry->summary.num = n_counts;
255 entry->counts = xcalloc (n_counts, sizeof (gcov_type));
257 else if (entry->checksum != checksum)
259 error ("coverage mismatch for function %u while reading execution counters.",
260 fn_ident);
261 error ("checksum is %x instead of %x", entry->checksum, checksum);
262 htab_delete (counts_hash);
263 break;
265 else if (entry->summary.num != n_counts)
267 error ("coverage mismatch for function %u while reading execution counters.",
268 fn_ident);
269 error ("number of counters is %d instead of %d", entry->summary.num, n_counts);
270 htab_delete (counts_hash);
271 break;
273 else if (elt.ctr >= GCOV_COUNTERS_SUMMABLE)
275 error ("cannot merge separate %s counters for function %u",
276 ctr_names[elt.ctr], fn_ident);
277 goto skip_merge;
280 if (elt.ctr < GCOV_COUNTERS_SUMMABLE
281 /* This should always be true for a just allocated entry,
282 and always false for an existing one. Check this way, in
283 case the gcov file is corrupt. */
284 && (!entry->chain || summaried != entry))
286 entry->chain = summaried;
287 summaried = entry;
289 for (ix = 0; ix != n_counts; ix++)
290 entry->counts[ix] += gcov_read_counter ();
291 skip_merge:;
293 gcov_sync (offset, length);
294 if ((is_error = gcov_is_error ()))
296 error (is_error < 0 ? "`%s' has overflowed" : "`%s' is corrupted",
297 da_file_name);
298 htab_delete (counts_hash);
299 break;
303 gcov_close ();
306 /* Returns the counters for a particular tag. */
308 gcov_type *
309 get_coverage_counts (unsigned counter, unsigned expected,
310 const struct gcov_ctr_summary **summary)
312 counts_entry_t *entry, elt;
313 gcov_unsigned_t checksum = -1;
315 /* No hash table, no counts. */
316 if (!counts_hash)
318 static int warned = 0;
320 if (!warned++)
321 inform ((flag_guess_branch_prob
322 ? "file %s not found, execution counts estimated"
323 : "file %s not found, execution counts assumed to be zero"),
324 da_file_name);
325 return NULL;
328 elt.ident = current_function_funcdef_no + 1;
329 elt.ctr = counter;
330 entry = htab_find (counts_hash, &elt);
331 if (!entry)
333 warning ("no coverage for function '%s' found.", IDENTIFIER_POINTER
334 (DECL_ASSEMBLER_NAME (current_function_decl)));
335 return 0;
338 checksum = compute_checksum ();
339 if (entry->checksum != checksum)
341 error ("coverage mismatch for function '%s' while reading counter '%s'.",
342 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
343 ctr_names[counter]);
344 error ("checksum is %x instead of %x", entry->checksum, checksum);
345 return 0;
347 else if (entry->summary.num != expected)
349 error ("coverage mismatch for function '%s' while reading counter '%s'.",
350 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
351 ctr_names[counter]);
352 error ("number of counters is %d instead of %d", entry->summary.num, expected);
353 return 0;
356 if (summary)
357 *summary = &entry->summary;
359 return entry->counts;
362 /* Allocate NUM counters of type COUNTER. Returns nonzero if the
363 allocation succeeded. */
366 coverage_counter_alloc (unsigned counter, unsigned num)
368 if (no_coverage)
369 return 0;
371 if (!num)
372 return 1;
374 if (!tree_ctr_tables[counter])
376 /* Generate and save a copy of this so it can be shared. */
377 /* We don't know the size yet; make it big enough that nobody
378 will make any clever transformation on it. */
379 char buf[20];
380 tree domain_tree
381 = build_index_type (build_int_2 (1000, 0)); /* replaced later */
382 tree gcov_type_array_type
383 = build_array_type (GCOV_TYPE_NODE, domain_tree);
384 tree_ctr_tables[counter]
385 = build_decl (VAR_DECL, NULL_TREE, gcov_type_array_type);
386 TREE_STATIC (tree_ctr_tables[counter]) = 1;
387 ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
388 DECL_NAME (tree_ctr_tables[counter]) = get_identifier (buf);
389 DECL_ALIGN (tree_ctr_tables[counter]) = TYPE_ALIGN (GCOV_TYPE_NODE);
391 fn_b_ctrs[counter] = fn_n_ctrs[counter];
392 fn_n_ctrs[counter] += num;
393 fn_ctr_mask |= 1 << counter;
394 return 1;
397 /* Generate a MEM rtl to access COUNTER NO. */
400 rtl_coverage_counter_ref (unsigned counter, unsigned no)
402 unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
403 enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
404 rtx ref;
406 if (no >= fn_n_ctrs[counter] - fn_b_ctrs[counter])
407 abort ();
408 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
409 if (!ctr_labels[counter])
411 ctr_labels[counter] = gen_rtx_SYMBOL_REF (Pmode,
412 ggc_strdup (IDENTIFIER_POINTER (DECL_NAME
413 (tree_ctr_tables[counter]))));
414 SYMBOL_REF_FLAGS (ctr_labels[counter]) = SYMBOL_FLAG_LOCAL;
416 ref = plus_constant (ctr_labels[counter], gcov_size / BITS_PER_UNIT * no);
417 ref = gen_rtx_MEM (mode, ref);
418 set_mem_alias_set (ref, new_alias_set ());
419 MEM_NOTRAP_P (ref) = 1;
421 return ref;
424 /* Generate a tree to access COUNTER NO. */
426 tree
427 tree_coverage_counter_ref (unsigned counter, unsigned no)
429 tree domain_type = TYPE_DOMAIN (TREE_TYPE (tree_ctr_tables[counter]));
431 if (no >= fn_n_ctrs[counter] - fn_b_ctrs[counter])
432 abort ();
433 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
435 /* "no" here is an array index, scaled to bytes later. */
436 return build4 (ARRAY_REF, GCOV_TYPE_NODE, tree_ctr_tables[counter],
437 fold_convert (domain_type, build_int_2 (no, 0)),
438 TYPE_MIN_VALUE (domain_type),
439 size_binop (EXACT_DIV_EXPR, TYPE_SIZE_UNIT (GCOV_TYPE_NODE),
440 size_int (TYPE_ALIGN (GCOV_TYPE_NODE))));
443 /* Generate a checksum for a string. CHKSUM is the current
444 checksum. */
446 static unsigned
447 coverage_checksum_string (unsigned chksum, const char *string)
449 int i;
450 char *dup = NULL;
452 /* Look for everything that looks if it were produced by
453 get_file_function_name_long and zero out the second part
454 that may result from flag_random_seed. This is not critical
455 as the checksums are used only for sanity checking. */
456 for (i = 0; string[i]; i++)
458 if (!strncmp (string + i, "_GLOBAL__", 9))
459 for (i = i + 9; string[i]; i++)
460 if (string[i]=='_')
462 int y;
463 unsigned seed;
465 for (y = 1; y < 9; y++)
466 if (!(string[i + y] >= '0' && string[i + y] <= '9')
467 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
468 break;
469 if (y != 9 || string[i + 9] != '_')
470 continue;
471 for (y = 10; y < 18; y++)
472 if (!(string[i + y] >= '0' && string[i + y] <= '9')
473 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
474 break;
475 if (y != 18)
476 continue;
477 if (!sscanf (string + i + 10, "%X", &seed))
478 abort ();
479 if (seed != crc32_string (0, flag_random_seed))
480 continue;
481 string = dup = xstrdup (string);
482 for (y = 10; y < 18; y++)
483 dup[i + y] = '0';
484 break;
486 break;
489 chksum = crc32_string (chksum, string);
490 if (dup)
491 free (dup);
493 return chksum;
496 /* Compute checksum for the current function. We generate a CRC32. */
498 static unsigned
499 compute_checksum (void)
501 expanded_location xloc
502 = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
503 unsigned chksum = xloc.line;
505 chksum = coverage_checksum_string (chksum, xloc.file);
506 chksum = coverage_checksum_string
507 (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
509 return chksum;
512 /* Begin output to the graph file for the current function.
513 Opens the output file, if not already done. Writes the
514 function header, if not already done. Returns nonzero if data
515 should be output. */
518 coverage_begin_output (void)
520 if (no_coverage)
521 return 0;
523 if (!bbg_function_announced)
525 expanded_location xloc
526 = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
527 unsigned long offset;
529 if (!bbg_file_opened)
531 if (!gcov_open (bbg_file_name, -1))
532 error ("cannot open %s", bbg_file_name);
533 else
535 gcov_write_unsigned (GCOV_NOTE_MAGIC);
536 gcov_write_unsigned (GCOV_VERSION);
537 gcov_write_unsigned (local_tick);
539 bbg_file_opened = 1;
542 /* Announce function */
543 offset = gcov_write_tag (GCOV_TAG_FUNCTION);
544 gcov_write_unsigned (current_function_funcdef_no + 1);
545 gcov_write_unsigned (compute_checksum ());
546 gcov_write_string (IDENTIFIER_POINTER
547 (DECL_ASSEMBLER_NAME (current_function_decl)));
548 gcov_write_string (xloc.file);
549 gcov_write_unsigned (xloc.line);
550 gcov_write_length (offset);
552 bbg_function_announced = 1;
554 return !gcov_is_error ();
557 /* Finish coverage data for the current function. Verify no output
558 error has occurred. Save function coverage counts. */
560 void
561 coverage_end_function (void)
563 unsigned i;
565 if (bbg_file_opened > 1 && gcov_is_error ())
567 warning ("error writing `%s'", bbg_file_name);
568 bbg_file_opened = -1;
571 if (fn_ctr_mask)
573 struct function_list *item;
575 item = xmalloc (sizeof (struct function_list));
577 *functions_tail = item;
578 functions_tail = &item->next;
580 item->next = 0;
581 item->ident = current_function_funcdef_no + 1;
582 item->checksum = compute_checksum ();
583 for (i = 0; i != GCOV_COUNTERS; i++)
585 item->n_ctrs[i] = fn_n_ctrs[i];
586 prg_n_ctrs[i] += fn_n_ctrs[i];
587 fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
589 prg_ctr_mask |= fn_ctr_mask;
590 fn_ctr_mask = 0;
592 bbg_function_announced = 0;
595 /* Creates the gcov_fn_info RECORD_TYPE. */
597 static tree
598 build_fn_info_type (unsigned int counters)
600 tree type = lang_hooks.types.make_type (RECORD_TYPE);
601 tree field, fields;
602 tree array_type;
604 /* ident */
605 fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
607 /* checksum */
608 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
609 TREE_CHAIN (field) = fields;
610 fields = field;
612 array_type = build_index_type (build_int_2 (counters - 1, 0));
613 array_type = build_array_type (unsigned_type_node, array_type);
615 /* counters */
616 field = build_decl (FIELD_DECL, NULL_TREE, array_type);
617 TREE_CHAIN (field) = fields;
618 fields = field;
620 finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
622 return type;
625 /* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
626 the function being processed and TYPE is the gcov_fn_info
627 RECORD_TYPE. */
629 static tree
630 build_fn_info_value (const struct function_list *function, tree type)
632 tree value = NULL_TREE;
633 tree fields = TYPE_FIELDS (type);
634 unsigned ix;
635 tree array_value = NULL_TREE;
637 /* ident */
638 value = tree_cons (fields,
639 convert (unsigned_intSI_type_node,
640 build_int_2 (function->ident, 0)),
641 value);
642 fields = TREE_CHAIN (fields);
644 /* checksum */
645 value = tree_cons (fields,
646 convert (unsigned_intSI_type_node,
647 build_int_2 (function->checksum, 0)),
648 value);
649 fields = TREE_CHAIN (fields);
651 /* counters */
652 for (ix = 0; ix != GCOV_COUNTERS; ix++)
653 if (prg_ctr_mask & (1 << ix))
655 tree counters = convert (unsigned_type_node,
656 build_int_2 (function->n_ctrs[ix], 0));
658 array_value = tree_cons (NULL_TREE, counters, array_value);
661 array_value = build_constructor (TREE_TYPE (fields), nreverse (array_value));
662 value = tree_cons (fields, array_value, value);
664 value = build_constructor (type, nreverse (value));
666 return value;
669 /* Creates the gcov_ctr_info RECORD_TYPE. */
671 static tree
672 build_ctr_info_type (void)
674 tree type = lang_hooks.types.make_type (RECORD_TYPE);
675 tree field, fields = NULL_TREE;
676 tree gcov_ptr_type = build_pointer_type (GCOV_TYPE_NODE);
677 tree gcov_merge_fn_type;
679 /* counters */
680 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
681 TREE_CHAIN (field) = fields;
682 fields = field;
684 /* values */
685 field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
686 TREE_CHAIN (field) = fields;
687 fields = field;
689 /* merge */
690 gcov_merge_fn_type =
691 build_function_type_list (void_type_node,
692 gcov_ptr_type, unsigned_type_node,
693 NULL_TREE);
694 field = build_decl (FIELD_DECL, NULL_TREE,
695 build_pointer_type (gcov_merge_fn_type));
696 TREE_CHAIN (field) = fields;
697 fields = field;
699 finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
701 return type;
704 /* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
705 the counter being processed and TYPE is the gcov_ctr_info
706 RECORD_TYPE. */
708 static tree
709 build_ctr_info_value (unsigned int counter, tree type)
711 tree value = NULL_TREE;
712 tree fields = TYPE_FIELDS (type);
713 tree fn;
715 /* counters */
716 value = tree_cons (fields,
717 convert (unsigned_intSI_type_node,
718 build_int_2 (prg_n_ctrs[counter], 0)),
719 value);
720 fields = TREE_CHAIN (fields);
722 if (prg_n_ctrs[counter])
724 tree array_type;
726 array_type = build_index_type (build_int_2 (prg_n_ctrs[counter] - 1, 0));
727 array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
728 array_type);
730 TREE_TYPE (tree_ctr_tables[counter]) = array_type;
731 DECL_SIZE (tree_ctr_tables[counter]) = TYPE_SIZE (array_type);
732 DECL_SIZE_UNIT (tree_ctr_tables[counter]) = TYPE_SIZE_UNIT (array_type);
733 assemble_variable (tree_ctr_tables[counter], 0, 0, 0);
735 value = tree_cons (fields,
736 build1 (ADDR_EXPR, TREE_TYPE (fields),
737 tree_ctr_tables[counter]),
738 value);
740 else
741 value = tree_cons (fields, null_pointer_node, value);
742 fields = TREE_CHAIN (fields);
744 fn = build_decl (FUNCTION_DECL,
745 get_identifier (ctr_merge_functions[counter]),
746 TREE_TYPE (TREE_TYPE (fields)));
747 DECL_EXTERNAL (fn) = 1;
748 TREE_PUBLIC (fn) = 1;
749 DECL_ARTIFICIAL (fn) = 1;
750 TREE_NOTHROW (fn) = 1;
751 value = tree_cons (fields,
752 build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
753 value);
755 value = build_constructor (type, nreverse (value));
757 return value;
760 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
761 CONSTRUCTOR. */
763 static tree
764 build_gcov_info (void)
766 unsigned n_ctr_types, ix;
767 tree type, const_type;
768 tree fn_info_type, fn_info_value = NULL_TREE;
769 tree fn_info_ptr_type;
770 tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
771 tree field, fields = NULL_TREE;
772 tree value = NULL_TREE;
773 tree filename_string;
774 char *filename;
775 int filename_len;
776 unsigned n_fns;
777 const struct function_list *fn;
778 tree string_type;
780 /* Count the number of active counters. */
781 for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
782 if (prg_ctr_mask & (1 << ix))
783 n_ctr_types++;
785 type = lang_hooks.types.make_type (RECORD_TYPE);
786 const_type = build_qualified_type (type, TYPE_QUAL_CONST);
788 /* Version ident */
789 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
790 TREE_CHAIN (field) = fields;
791 fields = field;
792 value = tree_cons (field, convert (unsigned_intSI_type_node,
793 build_int_2 (GCOV_VERSION, 0)),
794 value);
796 /* next -- NULL */
797 field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
798 TREE_CHAIN (field) = fields;
799 fields = field;
800 value = tree_cons (field, null_pointer_node, value);
802 /* stamp */
803 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
804 TREE_CHAIN (field) = fields;
805 fields = field;
806 value = tree_cons (field, convert (unsigned_intSI_type_node,
807 build_int_2 (local_tick, 0)),
808 value);
810 /* Filename */
811 string_type = build_pointer_type (build_qualified_type (char_type_node,
812 TYPE_QUAL_CONST));
813 field = build_decl (FIELD_DECL, NULL_TREE, string_type);
814 TREE_CHAIN (field) = fields;
815 fields = field;
816 filename = getpwd ();
817 filename = (filename && da_file_name[0] != '/'
818 ? concat (filename, "/", da_file_name, NULL)
819 : da_file_name);
820 filename_len = strlen (filename);
821 filename_string = build_string (filename_len + 1, filename);
822 if (filename != da_file_name)
823 free (filename);
824 TREE_TYPE (filename_string) =
825 build_array_type (char_type_node,
826 build_index_type (build_int_2 (filename_len, 0)));
827 value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
828 value);
830 /* Build the fn_info type and initializer. */
831 fn_info_type = build_fn_info_type (n_ctr_types);
832 fn_info_ptr_type = build_pointer_type (build_qualified_type
833 (fn_info_type, TYPE_QUAL_CONST));
834 for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
835 fn_info_value = tree_cons (NULL_TREE,
836 build_fn_info_value (fn, fn_info_type),
837 fn_info_value);
838 if (n_fns)
840 tree array_type;
842 array_type = build_index_type (build_int_2 (n_fns - 1, 0));
843 array_type = build_array_type (fn_info_type, array_type);
845 fn_info_value = build_constructor (array_type, nreverse (fn_info_value));
846 fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
848 else
849 fn_info_value = null_pointer_node;
851 /* number of functions */
852 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
853 TREE_CHAIN (field) = fields;
854 fields = field;
855 value = tree_cons (field,
856 convert (unsigned_type_node, build_int_2 (n_fns, 0)),
857 value);
859 /* fn_info table */
860 field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type);
861 TREE_CHAIN (field) = fields;
862 fields = field;
863 value = tree_cons (field, fn_info_value, value);
865 /* counter_mask */
866 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
867 TREE_CHAIN (field) = fields;
868 fields = field;
869 value = tree_cons (field,
870 convert (unsigned_type_node,
871 build_int_2 (prg_ctr_mask, 0)),
872 value);
874 /* counters */
875 ctr_info_type = build_ctr_info_type ();
876 ctr_info_ary_type = build_index_type (build_int_2 (n_ctr_types, 0));
877 ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
878 for (ix = 0; ix != GCOV_COUNTERS; ix++)
879 if (prg_ctr_mask & (1 << ix))
880 ctr_info_value = tree_cons (NULL_TREE,
881 build_ctr_info_value (ix, ctr_info_type),
882 ctr_info_value);
883 ctr_info_value = build_constructor (ctr_info_ary_type,
884 nreverse (ctr_info_value));
886 field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
887 TREE_CHAIN (field) = fields;
888 fields = field;
889 value = tree_cons (field, ctr_info_value, value);
891 finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
893 value = build_constructor (type, nreverse (value));
895 return value;
898 /* Write out the structure which libgcov uses to locate all the
899 counters. The structures used here must match those defined in
900 gcov-io.h. Write out the constructor to call __gcov_init. */
902 static void
903 create_coverage (void)
905 tree gcov_info, gcov_init, body, t;
906 char name_buf[32];
908 no_coverage = 1; /* Disable any further coverage. */
910 if (!prg_ctr_mask)
911 return;
913 t = build_gcov_info ();
915 gcov_info = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (t));
916 TREE_STATIC (gcov_info) = 1;
917 ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
918 DECL_NAME (gcov_info) = get_identifier (name_buf);
919 DECL_INITIAL (gcov_info) = t;
921 /* Build structure. */
922 assemble_variable (gcov_info, 0, 0, 0);
924 /* Build a decl for __gcov_init. */
925 t = build_pointer_type (TREE_TYPE (gcov_info));
926 t = build_function_type_list (void_type_node, t, NULL);
927 t = build_decl (FUNCTION_DECL, get_identifier ("__gcov_init"), t);
928 TREE_PUBLIC (t) = 1;
929 DECL_EXTERNAL (t) = 1;
930 gcov_init = t;
932 /* Generate a call to __gcov_init(&gcov_info). */
933 body = NULL;
934 t = build_fold_addr_expr (gcov_info);
935 t = tree_cons (NULL, t, NULL);
936 t = build_function_call_expr (gcov_init, t);
937 append_to_statement_list (t, &body);
939 /* Generate a constructor to run it. */
940 cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
943 /* Perform file-level initialization. Read in data file, generate name
944 of graph file. */
946 void
947 coverage_init (const char *filename)
949 int len = strlen (filename);
951 /* Name of da file. */
952 da_file_name = xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1);
953 strcpy (da_file_name, filename);
954 strcat (da_file_name, GCOV_DATA_SUFFIX);
956 /* Name of bbg file. */
957 bbg_file_name = xmalloc (len + strlen (GCOV_NOTE_SUFFIX) + 1);
958 strcpy (bbg_file_name, filename);
959 strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
961 read_counts_file ();
964 /* Performs file-level cleanup. Close graph file, generate coverage
965 variables and constructor. */
967 void
968 coverage_finish (void)
970 create_coverage ();
971 if (bbg_file_opened)
973 int error = gcov_close ();
975 if (error)
976 unlink (bbg_file_name);
977 if (!local_tick)
978 /* Only remove the da file, if we cannot stamp it. If we can
979 stamp it, libgcov will DTRT. */
980 unlink (da_file_name);
984 #include "gt-coverage.h"