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
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
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
31 #include "coretypes.h"
45 #include "langhooks.h"
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
68 struct gcov_ctr_summary summary;
71 struct counts_entry *chain;
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);
126 htab_counts_entry_hash (const void *of)
128 const counts_entry_t *entry = of;
130 return entry->ident * GCOV_COUNTERS + entry->ctr;
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;
143 htab_counts_entry_del (void *of)
145 counts_entry_t *entry = of;
147 free (entry->counts);
151 /* Read in the counts file, if available. */
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;
163 if (!gcov_open (da_file_name, 1))
166 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
168 warning ("`%s' is not a gcov data file", da_file_name);
172 else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
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);
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 ();
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;
218 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
220 counts_entry_t *entry;
221 struct gcov_summary summary;
223 gcov_read_summary (&summary);
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);
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);
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.",
261 error ("checksum is %x instead of %x", entry->checksum, checksum);
262 htab_delete (counts_hash);
265 else if (entry->summary.num != n_counts)
267 error ("coverage mismatch for function %u while reading execution counters.",
269 error ("number of counters is %d instead of %d", entry->summary.num, n_counts);
270 htab_delete (counts_hash);
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);
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;
289 for (ix = 0; ix != n_counts; ix++)
290 entry->counts[ix] += gcov_read_counter ();
293 gcov_sync (offset, length);
294 if ((is_error = gcov_is_error ()))
300 error (is_error < 0 ? "`%s' has overflowed" : "`%s' is corrupted",
302 htab_delete (counts_hash);
308 /* Returns the counters for a particular tag. */
311 get_coverage_counts (unsigned counter, unsigned expected,
312 const struct gcov_ctr_summary **summary)
314 counts_entry_t *entry, elt;
315 gcov_unsigned_t checksum = -1;
317 /* No hash table, no counts. */
320 static int warned = 0;
323 inform ((flag_guess_branch_prob
324 ? "file %s not found, execution counts estimated"
325 : "file %s not found, execution counts assumed to be zero"),
330 elt.ident = current_function_funcdef_no + 1;
332 entry = htab_find (counts_hash, &elt);
335 warning ("no coverage for function '%s' found.", IDENTIFIER_POINTER
336 (DECL_ASSEMBLER_NAME (current_function_decl)));
340 checksum = compute_checksum ();
341 if (entry->checksum != checksum)
343 error ("coverage mismatch for function '%s' while reading counter '%s'.",
344 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
346 error ("checksum is %x instead of %x", entry->checksum, checksum);
349 else if (entry->summary.num != expected)
351 error ("coverage mismatch for function '%s' while reading counter '%s'.",
352 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
354 error ("number of counters is %d instead of %d", entry->summary.num, expected);
359 *summary = &entry->summary;
361 return entry->counts;
364 /* Allocate NUM counters of type COUNTER. Returns nonzero if the
365 allocation succeeded. */
368 coverage_counter_alloc (unsigned counter, unsigned num)
376 if (!tree_ctr_tables[counter])
378 /* Generate and save a copy of this so it can be shared. */
379 /* We don't know the size yet; make it big enough that nobody
380 will make any clever transformation on it. */
383 = build_index_type (build_int_2 (1000, 0)); /* replaced later */
384 tree gcov_type_array_type
385 = build_array_type (GCOV_TYPE_NODE, domain_tree);
386 tree_ctr_tables[counter]
387 = build_decl (VAR_DECL, NULL_TREE, gcov_type_array_type);
388 TREE_STATIC (tree_ctr_tables[counter]) = 1;
389 ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
390 DECL_NAME (tree_ctr_tables[counter]) = get_identifier (buf);
391 DECL_ALIGN (tree_ctr_tables[counter]) = TYPE_ALIGN (GCOV_TYPE_NODE);
393 fn_b_ctrs[counter] = fn_n_ctrs[counter];
394 fn_n_ctrs[counter] += num;
395 fn_ctr_mask |= 1 << counter;
399 /* Generate a MEM rtl to access COUNTER NO. */
402 rtl_coverage_counter_ref (unsigned counter, unsigned no)
404 unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
405 enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
408 if (no >= fn_n_ctrs[counter] - fn_b_ctrs[counter])
410 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
411 if (!ctr_labels[counter])
413 ctr_labels[counter] = gen_rtx_SYMBOL_REF (Pmode,
414 ggc_strdup (IDENTIFIER_POINTER (DECL_NAME
415 (tree_ctr_tables[counter]))));
416 SYMBOL_REF_FLAGS (ctr_labels[counter]) = SYMBOL_FLAG_LOCAL;
418 ref = plus_constant (ctr_labels[counter], gcov_size / BITS_PER_UNIT * no);
419 ref = gen_rtx_MEM (mode, ref);
420 set_mem_alias_set (ref, new_alias_set ());
421 MEM_NOTRAP_P (ref) = 1;
426 /* Generate a tree to access COUNTER NO. */
429 tree_coverage_counter_ref (unsigned counter, unsigned no)
431 tree domain_type = TYPE_DOMAIN (TREE_TYPE (tree_ctr_tables[counter]));
433 if (no >= fn_n_ctrs[counter] - fn_b_ctrs[counter])
435 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
437 /* "no" here is an array index, scaled to bytes later. */
438 return build (ARRAY_REF, GCOV_TYPE_NODE, tree_ctr_tables[counter],
439 fold_convert (domain_type, build_int_2 (no, 0)),
440 TYPE_MIN_VALUE (domain_type),
441 size_binop (EXACT_DIV_EXPR, TYPE_SIZE_UNIT (GCOV_TYPE_NODE),
442 size_int (TYPE_ALIGN (GCOV_TYPE_NODE))));
445 /* Generate a checksum for a string. CHKSUM is the current
449 coverage_checksum_string (unsigned chksum, const char *string)
454 /* Look for everything that looks if it were produced by
455 get_file_function_name_long and zero out the second part
456 that may result from flag_random_seed. This is not critical
457 as the checksums are used only for sanity checking. */
458 for (i = 0; string[i]; i++)
460 if (!strncmp (string + i, "_GLOBAL__", 9))
461 for (i = i + 9; string[i]; i++)
467 for (y = 1; y < 9; y++)
468 if (!(string[i + y] >= '0' && string[i + y] <= '9')
469 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
471 if (y != 9 || string[i + 9] != '_')
473 for (y = 10; y < 18; y++)
474 if (!(string[i + y] >= '0' && string[i + y] <= '9')
475 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
479 if (!sscanf (string + i + 10, "%X", &seed))
481 if (seed != crc32_string (0, flag_random_seed))
483 string = dup = xstrdup (string);
484 for (y = 10; y < 18; y++)
491 chksum = crc32_string (chksum, string);
498 /* Compute checksum for the current function. We generate a CRC32. */
501 compute_checksum (void)
503 unsigned chksum = DECL_SOURCE_LINE (current_function_decl);
505 chksum = coverage_checksum_string (chksum,
506 DECL_SOURCE_FILE (current_function_decl));
507 chksum = coverage_checksum_string
508 (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
513 /* Begin output to the graph file for the current function.
514 Opens the output file, if not already done. Writes the
515 function header, if not already done. Returns nonzero if data
519 coverage_begin_output (void)
524 if (!bbg_function_announced)
526 const char *file = DECL_SOURCE_FILE (current_function_decl);
527 unsigned line = DECL_SOURCE_LINE (current_function_decl);
528 unsigned long offset;
530 if (!bbg_file_opened)
532 if (!gcov_open (bbg_file_name, -1))
533 error ("cannot open %s", bbg_file_name);
536 gcov_write_unsigned (GCOV_NOTE_MAGIC);
537 gcov_write_unsigned (GCOV_VERSION);
538 gcov_write_unsigned (local_tick);
543 /* Announce function */
544 offset = gcov_write_tag (GCOV_TAG_FUNCTION);
545 gcov_write_unsigned (current_function_funcdef_no + 1);
546 gcov_write_unsigned (compute_checksum ());
547 gcov_write_string (IDENTIFIER_POINTER
548 (DECL_ASSEMBLER_NAME (current_function_decl)));
549 gcov_write_string (file);
550 gcov_write_unsigned (line);
551 gcov_write_length (offset);
553 bbg_function_announced = 1;
555 return !gcov_is_error ();
558 /* Finish coverage data for the current function. Verify no output
559 error has occurred. Save function coverage counts. */
562 coverage_end_function (void)
566 if (bbg_file_opened > 1 && gcov_is_error ())
568 warning ("error writing `%s'", bbg_file_name);
569 bbg_file_opened = -1;
574 struct function_list *item;
576 item = xmalloc (sizeof (struct function_list));
578 *functions_tail = item;
579 functions_tail = &item->next;
582 item->ident = current_function_funcdef_no + 1;
583 item->checksum = compute_checksum ();
584 for (i = 0; i != GCOV_COUNTERS; i++)
586 item->n_ctrs[i] = fn_n_ctrs[i];
587 prg_n_ctrs[i] += fn_n_ctrs[i];
588 fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
590 prg_ctr_mask |= fn_ctr_mask;
593 bbg_function_announced = 0;
596 /* Creates the gcov_fn_info RECORD_TYPE. */
599 build_fn_info_type (unsigned int counters)
601 tree type = lang_hooks.types.make_type (RECORD_TYPE);
606 fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
609 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
610 TREE_CHAIN (field) = fields;
613 array_type = build_index_type (build_int_2 (counters - 1, 0));
614 array_type = build_array_type (unsigned_type_node, array_type);
617 field = build_decl (FIELD_DECL, NULL_TREE, array_type);
618 TREE_CHAIN (field) = fields;
621 finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
626 /* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
627 the function being processed and TYPE is the gcov_fn_info
631 build_fn_info_value (const struct function_list *function, tree type)
633 tree value = NULL_TREE;
634 tree fields = TYPE_FIELDS (type);
636 tree array_value = NULL_TREE;
639 value = tree_cons (fields,
640 convert (unsigned_intSI_type_node,
641 build_int_2 (function->ident, 0)),
643 fields = TREE_CHAIN (fields);
646 value = tree_cons (fields,
647 convert (unsigned_intSI_type_node,
648 build_int_2 (function->checksum, 0)),
650 fields = TREE_CHAIN (fields);
653 for (ix = 0; ix != GCOV_COUNTERS; ix++)
654 if (prg_ctr_mask & (1 << ix))
656 tree counters = convert (unsigned_type_node,
657 build_int_2 (function->n_ctrs[ix], 0));
659 array_value = tree_cons (NULL_TREE, counters, array_value);
662 array_value = build_constructor (TREE_TYPE (fields), nreverse (array_value));
663 value = tree_cons (fields, array_value, value);
665 value = build_constructor (type, nreverse (value));
670 /* Creates the gcov_ctr_info RECORD_TYPE. */
673 build_ctr_info_type (void)
675 tree type = lang_hooks.types.make_type (RECORD_TYPE);
676 tree field, fields = NULL_TREE;
677 tree gcov_ptr_type = build_pointer_type (GCOV_TYPE_NODE);
678 tree gcov_merge_fn_type;
681 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
682 TREE_CHAIN (field) = fields;
686 field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
687 TREE_CHAIN (field) = fields;
692 build_function_type_list (void_type_node,
693 gcov_ptr_type, unsigned_type_node,
695 field = build_decl (FIELD_DECL, NULL_TREE,
696 build_pointer_type (gcov_merge_fn_type));
697 TREE_CHAIN (field) = fields;
700 finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
705 /* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
706 the counter being processed and TYPE is the gcov_ctr_info
710 build_ctr_info_value (unsigned int counter, tree type)
712 tree value = NULL_TREE;
713 tree fields = TYPE_FIELDS (type);
717 value = tree_cons (fields,
718 convert (unsigned_intSI_type_node,
719 build_int_2 (prg_n_ctrs[counter], 0)),
721 fields = TREE_CHAIN (fields);
723 if (prg_n_ctrs[counter])
727 array_type = build_index_type (build_int_2 (prg_n_ctrs[counter] - 1, 0));
728 array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
731 TREE_TYPE (tree_ctr_tables[counter]) = array_type;
732 DECL_SIZE (tree_ctr_tables[counter]) = TYPE_SIZE (array_type);
733 DECL_SIZE_UNIT (tree_ctr_tables[counter]) = TYPE_SIZE_UNIT (array_type);
734 assemble_variable (tree_ctr_tables[counter], 0, 0, 0);
736 value = tree_cons (fields,
737 build1 (ADDR_EXPR, TREE_TYPE (fields),
738 tree_ctr_tables[counter]),
742 value = tree_cons (fields, null_pointer_node, value);
743 fields = TREE_CHAIN (fields);
745 fn = build_decl (FUNCTION_DECL,
746 get_identifier (ctr_merge_functions[counter]),
747 TREE_TYPE (TREE_TYPE (fields)));
748 DECL_EXTERNAL (fn) = 1;
749 TREE_PUBLIC (fn) = 1;
750 DECL_ARTIFICIAL (fn) = 1;
751 TREE_NOTHROW (fn) = 1;
752 value = tree_cons (fields,
753 build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
756 value = build_constructor (type, nreverse (value));
761 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
765 build_gcov_info (void)
767 unsigned n_ctr_types, ix;
768 tree type, const_type;
769 tree fn_info_type, fn_info_value = NULL_TREE;
770 tree fn_info_ptr_type;
771 tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
772 tree field, fields = NULL_TREE;
773 tree value = NULL_TREE;
774 tree filename_string;
778 const struct function_list *fn;
781 /* Count the number of active counters. */
782 for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
783 if (prg_ctr_mask & (1 << ix))
786 type = lang_hooks.types.make_type (RECORD_TYPE);
787 const_type = build_qualified_type (type, TYPE_QUAL_CONST);
790 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
791 TREE_CHAIN (field) = fields;
793 value = tree_cons (field, convert (unsigned_intSI_type_node,
794 build_int_2 (GCOV_VERSION, 0)),
798 field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
799 TREE_CHAIN (field) = fields;
801 value = tree_cons (field, null_pointer_node, value);
804 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
805 TREE_CHAIN (field) = fields;
807 value = tree_cons (field, convert (unsigned_intSI_type_node,
808 build_int_2 (local_tick, 0)),
812 string_type = build_pointer_type (build_qualified_type (char_type_node,
814 field = build_decl (FIELD_DECL, NULL_TREE, string_type);
815 TREE_CHAIN (field) = fields;
817 filename = getpwd ();
818 filename = (filename && da_file_name[0] != '/'
819 ? concat (filename, "/", da_file_name, NULL)
821 filename_len = strlen (filename);
822 filename_string = build_string (filename_len + 1, filename);
823 if (filename != da_file_name)
825 TREE_TYPE (filename_string) =
826 build_array_type (char_type_node,
827 build_index_type (build_int_2 (filename_len, 0)));
828 value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
831 /* Build the fn_info type and initializer. */
832 fn_info_type = build_fn_info_type (n_ctr_types);
833 fn_info_ptr_type = build_pointer_type (build_qualified_type
834 (fn_info_type, TYPE_QUAL_CONST));
835 for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
836 fn_info_value = tree_cons (NULL_TREE,
837 build_fn_info_value (fn, fn_info_type),
843 array_type = build_index_type (build_int_2 (n_fns - 1, 0));
844 array_type = build_array_type (fn_info_type, array_type);
846 fn_info_value = build_constructor (array_type, nreverse (fn_info_value));
847 fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
850 fn_info_value = null_pointer_node;
852 /* number of functions */
853 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
854 TREE_CHAIN (field) = fields;
856 value = tree_cons (field,
857 convert (unsigned_type_node, build_int_2 (n_fns, 0)),
861 field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type);
862 TREE_CHAIN (field) = fields;
864 value = tree_cons (field, fn_info_value, value);
867 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
868 TREE_CHAIN (field) = fields;
870 value = tree_cons (field,
871 convert (unsigned_type_node,
872 build_int_2 (prg_ctr_mask, 0)),
876 ctr_info_type = build_ctr_info_type ();
877 ctr_info_ary_type = build_index_type (build_int_2 (n_ctr_types, 0));
878 ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
879 for (ix = 0; ix != GCOV_COUNTERS; ix++)
880 if (prg_ctr_mask & (1 << ix))
881 ctr_info_value = tree_cons (NULL_TREE,
882 build_ctr_info_value (ix, ctr_info_type),
884 ctr_info_value = build_constructor (ctr_info_ary_type,
885 nreverse (ctr_info_value));
887 field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
888 TREE_CHAIN (field) = fields;
890 value = tree_cons (field, ctr_info_value, value);
892 finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
894 value = build_constructor (type, nreverse (value));
899 /* Write out the structure which libgcov uses to locate all the
900 counters. The structures used here must match those defined in
901 gcov-io.h. Write out the constructor to call __gcov_init. */
904 create_coverage (void)
906 tree gcov_info, gcov_info_value;
910 rtx gcov_info_address;
912 no_coverage = 1; /* Disable any further coverage. */
917 gcov_info_value = build_gcov_info ();
919 gcov_info = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (gcov_info_value));
920 DECL_INITIAL (gcov_info) = gcov_info_value;
922 TREE_STATIC (gcov_info) = 1;
923 ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 0);
924 DECL_NAME (gcov_info) = get_identifier (name);
926 /* Build structure. */
927 assemble_variable (gcov_info, 0, 0, 0);
929 /* Build the constructor function to invoke __gcov_init. */
930 ctor_name = concat (IDENTIFIER_POINTER (get_file_function_name ('I')),
932 ctor = build_decl (FUNCTION_DECL, get_identifier (ctor_name),
933 build_function_type (void_type_node, NULL_TREE));
935 DECL_EXTERNAL (ctor) = 0;
937 /* It can be a static function as long as collect2 does not have
938 to scan the object file to find its ctor/dtor routine. */
939 TREE_PUBLIC (ctor) = ! targetm.have_ctors_dtors;
940 TREE_USED (ctor) = 1;
941 DECL_RESULT (ctor) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
942 DECL_UNINLINABLE (ctor) = 1;
944 rest_of_decl_compilation (ctor, 0, 1, 0);
945 announce_function (ctor);
946 current_function_decl = ctor;
947 make_decl_rtl (ctor, NULL);
948 init_function_start (ctor);
949 expand_function_start (ctor, 0);
950 /* Actually generate the code to call __gcov_init. */
951 gcov_info_address = force_reg (Pmode, XEXP (DECL_RTL (gcov_info), 0));
952 emit_library_call (gcov_init_libfunc, LCT_NORMAL, VOIDmode, 1,
953 gcov_info_address, Pmode);
955 expand_function_end ();
956 /* Create a dummy BLOCK. */
957 DECL_INITIAL (ctor) = make_node (BLOCK);
958 TREE_USED (DECL_INITIAL (ctor)) = 1;
960 rest_of_compilation ();
963 fflush (asm_out_file);
964 current_function_decl = NULL_TREE;
966 if (targetm.have_ctors_dtors)
967 targetm.asm_out.constructor (XEXP (DECL_RTL (ctor), 0),
968 DEFAULT_INIT_PRIORITY);
971 /* Perform file-level initialization. Read in data file, generate name
975 coverage_init (const char *filename)
977 int len = strlen (filename);
979 /* Name of da file. */
980 da_file_name = xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1);
981 strcpy (da_file_name, filename);
982 strcat (da_file_name, GCOV_DATA_SUFFIX);
984 /* Name of bbg file. */
985 bbg_file_name = xmalloc (len + strlen (GCOV_NOTE_SUFFIX) + 1);
986 strcpy (bbg_file_name, filename);
987 strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
992 /* Performs file-level cleanup. Close graph file, generate coverage
993 variables and constructor. */
996 coverage_finish (void)
1001 int error = gcov_close ();
1004 unlink (bbg_file_name);
1006 /* Only remove the da file, if we cannot stamp it. If we can
1007 stamp it, libgcov will DTRT. */
1008 unlink (da_file_name);
1012 #include "gt-coverage.h"