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 /* The names of the counter tables. */
100 static GTY(()) rtx ctr_labels[GCOV_COUNTERS];
102 /* The names of merge functions for counters. */
103 static const char *const ctr_merge_functions[GCOV_COUNTERS] = GCOV_MERGE_FUNCTIONS;
104 static const char *const ctr_names[GCOV_COUNTERS] = GCOV_COUNTER_NAMES;
106 /* Forward declarations. */
107 static hashval_t htab_counts_entry_hash (const void *);
108 static int htab_counts_entry_eq (const void *, const void *);
109 static void htab_counts_entry_del (void *);
110 static void read_counts_file (void);
111 static unsigned compute_checksum (void);
112 static unsigned coverage_checksum_string (unsigned, const char *);
113 static tree build_fn_info_type (unsigned);
114 static tree build_fn_info_value (const struct function_list *, tree);
115 static tree build_ctr_info_type (void);
116 static tree build_ctr_info_value (unsigned, tree);
117 static tree build_gcov_info (void);
118 static void create_coverage (void);
122 htab_counts_entry_hash (const void *of)
124 const counts_entry_t *entry = of;
126 return entry->ident * GCOV_COUNTERS + entry->ctr;
130 htab_counts_entry_eq (const void *of1, const void *of2)
132 const counts_entry_t *entry1 = of1;
133 const counts_entry_t *entry2 = of2;
135 return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
139 htab_counts_entry_del (void *of)
141 counts_entry_t *entry = of;
143 free (entry->counts);
147 /* Read in the counts file, if available. */
150 read_counts_file (void)
152 gcov_unsigned_t fn_ident = 0;
153 gcov_unsigned_t checksum = -1;
154 counts_entry_t *summaried = NULL;
155 unsigned seen_summary = 0;
159 if (!gcov_open (da_file_name, 1))
162 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
164 warning ("`%s' is not a gcov data file", da_file_name);
168 else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
172 GCOV_UNSIGNED2STRING (v, tag);
173 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
175 warning ("`%s' is version `%.4s', expected version `%.4s'",
181 /* Read and discard the stamp. */
182 gcov_read_unsigned ();
184 counts_hash = htab_create (10,
185 htab_counts_entry_hash, htab_counts_entry_eq,
186 htab_counts_entry_del);
187 while ((tag = gcov_read_unsigned ()))
189 gcov_unsigned_t length;
190 gcov_position_t offset;
192 length = gcov_read_unsigned ();
193 offset = gcov_position ();
194 if (tag == GCOV_TAG_FUNCTION)
196 fn_ident = gcov_read_unsigned ();
197 checksum = gcov_read_unsigned ();
200 /* We have already seen a summary, this means that this
201 new function begins a new set of program runs. We
202 must unlink the summaried chain. */
203 counts_entry_t *entry, *chain;
205 for (entry = summaried; entry; entry = chain)
207 chain = entry->chain;
214 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
216 counts_entry_t *entry;
217 struct gcov_summary summary;
219 gcov_read_summary (&summary);
221 for (entry = summaried; entry; entry = entry->chain)
223 struct gcov_ctr_summary *csum = &summary.ctrs[entry->ctr];
225 entry->summary.runs += csum->runs;
226 entry->summary.sum_all += csum->sum_all;
227 if (entry->summary.run_max < csum->run_max)
228 entry->summary.run_max = csum->run_max;
229 entry->summary.sum_max += csum->sum_max;
232 else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
234 counts_entry_t **slot, *entry, elt;
235 unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
238 elt.ident = fn_ident;
239 elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
241 slot = (counts_entry_t **) htab_find_slot
242 (counts_hash, &elt, INSERT);
246 *slot = entry = xcalloc (1, sizeof (counts_entry_t));
247 entry->ident = elt.ident;
248 entry->ctr = elt.ctr;
249 entry->checksum = checksum;
250 entry->summary.num = n_counts;
251 entry->counts = xcalloc (n_counts, sizeof (gcov_type));
253 else if (entry->checksum != checksum)
255 error ("coverage mismatch for function %u while reading execution counters.",
257 error ("checksum is %x instead of %x", entry->checksum, checksum);
258 htab_delete (counts_hash);
261 else if (entry->summary.num != n_counts)
263 error ("coverage mismatch for function %u while reading execution counters.",
265 error ("number of counters is %d instead of %d", entry->summary.num, n_counts);
266 htab_delete (counts_hash);
269 else if (elt.ctr >= GCOV_COUNTERS_SUMMABLE)
271 error ("cannot merge separate %s counters for function %u",
272 ctr_names[elt.ctr], fn_ident);
276 if (elt.ctr < GCOV_COUNTERS_SUMMABLE
277 /* This should always be true for a just allocated entry,
278 and always false for an existing one. Check this way, in
279 case the gcov file is corrupt. */
280 && (!entry->chain || summaried != entry))
282 entry->chain = summaried;
285 for (ix = 0; ix != n_counts; ix++)
286 entry->counts[ix] += gcov_read_counter ();
289 gcov_sync (offset, length);
290 if ((is_error = gcov_is_error ()))
296 error (is_error < 0 ? "`%s' has overflowed" : "`%s' is corrupted",
298 htab_delete (counts_hash);
304 /* Returns the counters for a particular tag. */
307 get_coverage_counts (unsigned counter, unsigned expected,
308 const struct gcov_ctr_summary **summary)
310 counts_entry_t *entry, elt;
311 gcov_unsigned_t checksum = -1;
313 /* No hash table, no counts. */
316 static int warned = 0;
319 inform ("file %s not found, execution counts assumed to be zero",
324 elt.ident = current_function_funcdef_no + 1;
326 entry = htab_find (counts_hash, &elt);
329 warning ("no coverage for function '%s' found.", IDENTIFIER_POINTER
330 (DECL_ASSEMBLER_NAME (current_function_decl)));
334 checksum = compute_checksum ();
335 if (entry->checksum != checksum)
337 error ("coverage mismatch for function '%s' while reading counter '%s'.",
338 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
340 error ("checksum is %x instead of %x", entry->checksum, checksum);
343 else if (entry->summary.num != expected)
345 error ("coverage mismatch for function '%s' while reading counter '%s'.",
346 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
348 error ("number of counters is %d instead of %d", entry->summary.num, expected);
353 *summary = &entry->summary;
355 return entry->counts;
358 /* Allocate NUM counters of type COUNTER. Returns nonzero if the
359 allocation succeeded. */
362 coverage_counter_alloc (unsigned counter, unsigned num)
370 if (!ctr_labels[counter])
372 /* Generate and save a copy of this so it can be shared. */
375 ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
376 ctr_labels[counter] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
377 SYMBOL_REF_FLAGS (ctr_labels[counter]) = SYMBOL_FLAG_LOCAL;
379 fn_b_ctrs[counter] = fn_n_ctrs[counter];
380 fn_n_ctrs[counter] += num;
381 fn_ctr_mask |= 1 << counter;
385 /* Generate a MEM rtl to access COUNTER NO. */
388 coverage_counter_ref (unsigned counter, unsigned no)
390 unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
391 enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
394 if (no >= fn_n_ctrs[counter] - fn_b_ctrs[counter])
396 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
397 ref = plus_constant (ctr_labels[counter], gcov_size / BITS_PER_UNIT * no);
398 ref = gen_rtx_MEM (mode, ref);
399 set_mem_alias_set (ref, new_alias_set ());
404 /* Generate a checksum for a string. CHKSUM is the current
408 coverage_checksum_string (unsigned chksum, const char *string)
413 /* Look for everything that looks if it were produced by
414 get_file_function_name_long and zero out the second part
415 that may result from flag_random_seed. This is not critical
416 as the checksums are used only for sanity checking. */
417 for (i = 0; string[i]; i++)
419 if (!strncmp (string + i, "_GLOBAL__", 9))
420 for (i = i + 9; string[i]; i++)
426 for (y = 1; y < 9; y++)
427 if (!(string[i + y] >= '0' && string[i + y] <= '9')
428 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
430 if (y != 9 || string[i + 9] != '_')
432 for (y = 10; y < 18; y++)
433 if (!(string[i + y] >= '0' && string[i + y] <= '9')
434 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
438 if (!sscanf (string + i + 10, "%X", &seed))
440 if (seed != crc32_string (0, flag_random_seed))
442 string = dup = xstrdup (string);
443 for (y = 10; y < 18; y++)
450 chksum = crc32_string (chksum, string);
457 /* Compute checksum for the current function. We generate a CRC32. */
460 compute_checksum (void)
462 unsigned chksum = DECL_SOURCE_LINE (current_function_decl);
464 chksum = coverage_checksum_string (chksum,
465 DECL_SOURCE_FILE (current_function_decl));
466 chksum = coverage_checksum_string
467 (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
472 /* Begin output to the graph file for the current function.
473 Opens the output file, if not already done. Writes the
474 function header, if not already done. Returns nonzero if data
478 coverage_begin_output (void)
483 if (!bbg_function_announced)
485 const char *file = DECL_SOURCE_FILE (current_function_decl);
486 unsigned line = DECL_SOURCE_LINE (current_function_decl);
487 unsigned long offset;
489 if (!bbg_file_opened)
491 if (!gcov_open (bbg_file_name, -1))
492 error ("cannot open %s", bbg_file_name);
495 gcov_write_unsigned (GCOV_NOTE_MAGIC);
496 gcov_write_unsigned (GCOV_VERSION);
497 gcov_write_unsigned (local_tick);
502 /* Announce function */
503 offset = gcov_write_tag (GCOV_TAG_FUNCTION);
504 gcov_write_unsigned (current_function_funcdef_no + 1);
505 gcov_write_unsigned (compute_checksum ());
506 gcov_write_string (IDENTIFIER_POINTER
507 (DECL_ASSEMBLER_NAME (current_function_decl)));
508 gcov_write_string (file);
509 gcov_write_unsigned (line);
510 gcov_write_length (offset);
512 bbg_function_announced = 1;
514 return !gcov_is_error ();
517 /* Finish coverage data for the current function. Verify no output
518 error has occurred. Save function coverage counts. */
521 coverage_end_function (void)
525 if (bbg_file_opened > 1 && gcov_is_error ())
527 warning ("error writing `%s'", bbg_file_name);
528 bbg_file_opened = -1;
533 struct function_list *item;
535 item = xmalloc (sizeof (struct function_list));
537 *functions_tail = item;
538 functions_tail = &item->next;
541 item->ident = current_function_funcdef_no + 1;
542 item->checksum = compute_checksum ();
543 for (i = 0; i != GCOV_COUNTERS; i++)
545 item->n_ctrs[i] = fn_n_ctrs[i];
546 prg_n_ctrs[i] += fn_n_ctrs[i];
547 fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
549 prg_ctr_mask |= fn_ctr_mask;
552 bbg_function_announced = 0;
555 /* Creates the gcov_fn_info RECORD_TYPE. */
558 build_fn_info_type (unsigned int counters)
560 tree type = (*lang_hooks.types.make_type) (RECORD_TYPE);
565 fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
568 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
569 TREE_CHAIN (field) = fields;
572 array_type = build_index_type (build_int_2 (counters - 1, 0));
573 array_type = build_array_type (unsigned_type_node, array_type);
576 field = build_decl (FIELD_DECL, NULL_TREE, array_type);
577 TREE_CHAIN (field) = fields;
580 finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
585 /* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
586 the function being processed and TYPE is the gcov_fn_info
590 build_fn_info_value (const struct function_list *function, tree type)
592 tree value = NULL_TREE;
593 tree fields = TYPE_FIELDS (type);
595 tree array_value = NULL_TREE;
598 value = tree_cons (fields,
599 convert (unsigned_intSI_type_node,
600 build_int_2 (function->ident, 0)),
602 fields = TREE_CHAIN (fields);
605 value = tree_cons (fields,
606 convert (unsigned_intSI_type_node,
607 build_int_2 (function->checksum, 0)),
609 fields = TREE_CHAIN (fields);
612 for (ix = 0; ix != GCOV_COUNTERS; ix++)
613 if (prg_ctr_mask & (1 << ix))
615 tree counters = convert (unsigned_type_node,
616 build_int_2 (function->n_ctrs[ix], 0));
618 array_value = tree_cons (NULL_TREE, counters, array_value);
621 array_value = build_constructor (TREE_TYPE (fields), nreverse (array_value));
622 value = tree_cons (fields, array_value, value);
624 value = build_constructor (type, nreverse (value));
629 /* Creates the gcov_ctr_info RECORD_TYPE. */
632 build_ctr_info_type (void)
634 tree type = (*lang_hooks.types.make_type) (RECORD_TYPE);
635 tree field, fields = NULL_TREE;
636 tree gcov_ptr_type = build_pointer_type (GCOV_TYPE_NODE);
637 tree gcov_merge_fn_type;
640 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
641 TREE_CHAIN (field) = fields;
645 field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
646 TREE_CHAIN (field) = fields;
651 build_function_type_list (void_type_node,
652 gcov_ptr_type, unsigned_type_node,
654 field = build_decl (FIELD_DECL, NULL_TREE,
655 build_pointer_type (gcov_merge_fn_type));
656 TREE_CHAIN (field) = fields;
659 finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
664 /* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
665 the counter being processed and TYPE is the gcov_ctr_info
669 build_ctr_info_value (unsigned int counter, tree type)
671 tree value = NULL_TREE;
672 tree fields = TYPE_FIELDS (type);
676 value = tree_cons (fields,
677 convert (unsigned_intSI_type_node,
678 build_int_2 (prg_n_ctrs[counter], 0)),
680 fields = TREE_CHAIN (fields);
682 if (prg_n_ctrs[counter])
684 tree array_type, array;
686 array_type = build_index_type (build_int_2 (prg_n_ctrs[counter] - 1, 0));
687 array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
690 array = build_decl (VAR_DECL, NULL_TREE, array_type);
691 TREE_STATIC (array) = 1;
692 DECL_NAME (array) = get_identifier (XSTR (ctr_labels[counter], 0));
693 assemble_variable (array, 0, 0, 0);
695 value = tree_cons (fields,
696 build1 (ADDR_EXPR, TREE_TYPE (fields), array),
700 value = tree_cons (fields, null_pointer_node, value);
701 fields = TREE_CHAIN (fields);
703 fn = build_decl (FUNCTION_DECL,
704 get_identifier (ctr_merge_functions[counter]),
705 TREE_TYPE (TREE_TYPE (fields)));
706 DECL_EXTERNAL (fn) = 1;
707 TREE_PUBLIC (fn) = 1;
708 DECL_ARTIFICIAL (fn) = 1;
709 TREE_NOTHROW (fn) = 1;
710 value = tree_cons (fields,
711 build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
714 value = build_constructor (type, nreverse (value));
719 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
723 build_gcov_info (void)
725 unsigned n_ctr_types, ix;
726 tree type, const_type;
727 tree fn_info_type, fn_info_value = NULL_TREE;
728 tree fn_info_ptr_type;
729 tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
730 tree field, fields = NULL_TREE;
731 tree value = NULL_TREE;
732 tree filename_string;
736 const struct function_list *fn;
739 /* Count the number of active counters. */
740 for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
741 if (prg_ctr_mask & (1 << ix))
744 type = (*lang_hooks.types.make_type) (RECORD_TYPE);
745 const_type = build_qualified_type (type, TYPE_QUAL_CONST);
748 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
749 TREE_CHAIN (field) = fields;
751 value = tree_cons (field, convert (unsigned_intSI_type_node,
752 build_int_2 (GCOV_VERSION, 0)),
756 field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
757 TREE_CHAIN (field) = fields;
759 value = tree_cons (field, null_pointer_node, value);
762 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
763 TREE_CHAIN (field) = fields;
765 value = tree_cons (field, convert (unsigned_intSI_type_node,
766 build_int_2 (local_tick, 0)),
770 string_type = build_pointer_type (build_qualified_type (char_type_node,
772 field = build_decl (FIELD_DECL, NULL_TREE, string_type);
773 TREE_CHAIN (field) = fields;
775 filename = getpwd ();
776 filename = (filename && da_file_name[0] != '/'
777 ? concat (filename, "/", da_file_name, NULL)
779 filename_len = strlen (filename);
780 filename_string = build_string (filename_len + 1, filename);
781 if (filename != da_file_name)
783 TREE_TYPE (filename_string) =
784 build_array_type (char_type_node,
785 build_index_type (build_int_2 (filename_len, 0)));
786 value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
789 /* Build the fn_info type and initializer. */
790 fn_info_type = build_fn_info_type (n_ctr_types);
791 fn_info_ptr_type = build_pointer_type (build_qualified_type
792 (fn_info_type, TYPE_QUAL_CONST));
793 for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
794 fn_info_value = tree_cons (NULL_TREE,
795 build_fn_info_value (fn, fn_info_type),
801 array_type = build_index_type (build_int_2 (n_fns - 1, 0));
802 array_type = build_array_type (fn_info_type, array_type);
804 fn_info_value = build_constructor (array_type, nreverse (fn_info_value));
805 fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
808 fn_info_value = null_pointer_node;
810 /* number of functions */
811 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
812 TREE_CHAIN (field) = fields;
814 value = tree_cons (field,
815 convert (unsigned_type_node, build_int_2 (n_fns, 0)),
819 field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type);
820 TREE_CHAIN (field) = fields;
822 value = tree_cons (field, fn_info_value, value);
825 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
826 TREE_CHAIN (field) = fields;
828 value = tree_cons (field,
829 convert (unsigned_type_node,
830 build_int_2 (prg_ctr_mask, 0)),
834 ctr_info_type = build_ctr_info_type ();
835 ctr_info_ary_type = build_index_type (build_int_2 (n_ctr_types, 0));
836 ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
837 for (ix = 0; ix != GCOV_COUNTERS; ix++)
838 if (prg_ctr_mask & (1 << ix))
839 ctr_info_value = tree_cons (NULL_TREE,
840 build_ctr_info_value (ix, ctr_info_type),
842 ctr_info_value = build_constructor (ctr_info_ary_type,
843 nreverse (ctr_info_value));
845 field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
846 TREE_CHAIN (field) = fields;
848 value = tree_cons (field, ctr_info_value, value);
850 finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
852 value = build_constructor (type, nreverse (value));
857 /* Write out the structure which libgcov uses to locate all the
858 counters. The structures used here must match those defined in
859 gcov-io.h. Write out the constructor to call __gcov_init. */
862 create_coverage (void)
864 tree gcov_info, gcov_info_value;
868 rtx gcov_info_address;
870 no_coverage = 1; /* Disable any further coverage. */
875 gcov_info_value = build_gcov_info ();
877 gcov_info = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (gcov_info_value));
878 DECL_INITIAL (gcov_info) = gcov_info_value;
880 TREE_STATIC (gcov_info) = 1;
881 ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 0);
882 DECL_NAME (gcov_info) = get_identifier (name);
884 /* Build structure. */
885 assemble_variable (gcov_info, 0, 0, 0);
887 /* Build the constructor function to invoke __gcov_init. */
888 ctor_name = concat (IDENTIFIER_POINTER (get_file_function_name ('I')),
890 ctor = build_decl (FUNCTION_DECL, get_identifier (ctor_name),
891 build_function_type (void_type_node, NULL_TREE));
893 DECL_EXTERNAL (ctor) = 0;
895 /* It can be a static function as long as collect2 does not have
896 to scan the object file to find its ctor/dtor routine. */
897 TREE_PUBLIC (ctor) = ! targetm.have_ctors_dtors;
898 TREE_USED (ctor) = 1;
899 DECL_RESULT (ctor) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
900 DECL_UNINLINABLE (ctor) = 1;
902 ctor = (*lang_hooks.decls.pushdecl) (ctor);
903 rest_of_decl_compilation (ctor, 0, 1, 0);
904 announce_function (ctor);
905 current_function_decl = ctor;
906 make_decl_rtl (ctor, NULL);
907 init_function_start (ctor);
908 expand_function_start (ctor, 0);
909 /* Actually generate the code to call __gcov_init. */
910 gcov_info_address = force_reg (Pmode, XEXP (DECL_RTL (gcov_info), 0));
911 emit_library_call (gcov_init_libfunc, LCT_NORMAL, VOIDmode, 1,
912 gcov_info_address, Pmode);
914 expand_function_end ();
915 /* Create a dummy BLOCK. */
916 DECL_INITIAL (ctor) = make_node (BLOCK);
917 TREE_USED (DECL_INITIAL (ctor)) = 1;
919 rest_of_compilation (ctor);
922 fflush (asm_out_file);
923 current_function_decl = NULL_TREE;
925 if (targetm.have_ctors_dtors)
926 (* targetm.asm_out.constructor) (XEXP (DECL_RTL (ctor), 0),
927 DEFAULT_INIT_PRIORITY);
930 /* Perform file-level initialization. Read in data file, generate name
934 coverage_init (const char *filename)
936 int len = strlen (filename);
938 /* Name of da file. */
939 da_file_name = xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1);
940 strcpy (da_file_name, filename);
941 strcat (da_file_name, GCOV_DATA_SUFFIX);
943 /* Name of bbg file. */
944 bbg_file_name = xmalloc (len + strlen (GCOV_NOTE_SUFFIX) + 1);
945 strcpy (bbg_file_name, filename);
946 strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
951 /* Performs file-level cleanup. Close graph file, generate coverage
952 variables and constructor. */
955 coverage_finish (void)
960 int error = gcov_close ();
963 unlink (bbg_file_name);
965 /* Only remove the da file, if we cannot stamp it. If we can
966 stamp it, libgcov will DTRT. */
967 unlink (da_file_name);
971 #include "gt-coverage.h"