include/ChangeLog:
[official-gcc.git] / gcc / coverage.c
blob7f0aa8da0128115cecbb3873598283e251bd2cd1
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 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 "target.h"
43 #include "coverage.h"
44 #include "libfuncs.h"
45 #include "langhooks.h"
46 #include "hashtab.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 /* 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 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);
121 static hashval_t
122 htab_counts_entry_hash (const void *of)
124 const counts_entry_t *entry = of;
126 return entry->ident * GCOV_COUNTERS + entry->ctr;
129 static int
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;
138 static void
139 htab_counts_entry_del (void *of)
141 counts_entry_t *entry = of;
143 free (entry->counts);
144 free (entry);
147 /* Read in the counts file, if available. */
149 static void
150 read_counts_file (void)
152 gcov_unsigned_t fn_ident = 0;
153 gcov_unsigned_t version, checksum = -1;
154 unsigned ix;
155 counts_entry_t *summaried = NULL;
156 unsigned seen_summary = 0;
157 gcov_unsigned_t tag;
158 int error = 0;
160 if (!gcov_open (da_file_name, 1))
161 return;
163 if (gcov_read_unsigned () != GCOV_DATA_MAGIC)
165 warning ("`%s' is not a gcov data file", da_file_name);
166 gcov_close ();
167 return;
169 else if ((version = gcov_read_unsigned ()) != GCOV_VERSION)
171 char v[4], e[4];
172 gcov_unsigned_t required = GCOV_VERSION;
174 for (ix = 4; ix--; required >>= 8, version >>= 8)
176 v[ix] = version;
177 e[ix] = required;
179 warning ("`%s' is version `%.4s', expected version `%.4s'",
180 da_file_name, v, e);
181 gcov_close ();
182 return;
185 counts_hash = htab_create (10,
186 htab_counts_entry_hash, htab_counts_entry_eq,
187 htab_counts_entry_del);
188 while ((tag = gcov_read_unsigned ()))
190 gcov_unsigned_t length;
191 gcov_position_t offset;
193 length = gcov_read_unsigned ();
194 offset = gcov_position ();
195 if (tag == GCOV_TAG_FUNCTION)
197 fn_ident = gcov_read_unsigned ();
198 checksum = gcov_read_unsigned ();
199 if (seen_summary)
201 /* We have already seen a summary, this means that this
202 new function begins a new set of program runs. We
203 must unlink the summaried chain. */
204 counts_entry_t *entry, *chain;
206 for (entry = summaried; entry; entry = chain)
208 chain = entry->chain;
209 entry->chain = NULL;
211 summaried = NULL;
212 seen_summary = 0;
215 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
217 counts_entry_t *entry;
218 struct gcov_summary summary;
220 gcov_read_summary (&summary);
221 seen_summary = 1;
222 for (entry = summaried; entry; entry = entry->chain)
224 struct gcov_ctr_summary *csum = &summary.ctrs[entry->ctr];
226 entry->summary.runs += csum->runs;
227 entry->summary.sum_all += csum->sum_all;
228 if (entry->summary.run_max < csum->run_max)
229 entry->summary.run_max = csum->run_max;
230 entry->summary.sum_max += csum->sum_max;
233 else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
235 counts_entry_t **slot, *entry, elt;
236 unsigned n_counts = length / 8;
237 unsigned ix;
239 elt.ident = fn_ident;
240 elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
242 slot = (counts_entry_t **) htab_find_slot
243 (counts_hash, &elt, INSERT);
244 entry = *slot;
245 if (!entry)
247 *slot = entry = xcalloc (1, sizeof (counts_entry_t));
248 entry->ident = elt.ident;
249 entry->ctr = elt.ctr;
250 entry->checksum = checksum;
251 entry->summary.num = n_counts;
252 entry->counts = xcalloc (n_counts, sizeof (gcov_type));
254 else if (entry->checksum != checksum
255 || entry->summary.num != n_counts)
257 warning ("coverage mismatch for function %u", fn_ident);
258 htab_delete (counts_hash);
259 break;
261 else if (elt.ctr >= GCOV_COUNTERS_SUMMABLE)
263 warning ("cannot merge separate %s counters for function %u",
264 ctr_names[elt.ctr], fn_ident);
265 goto skip_merge;
268 if (elt.ctr < GCOV_COUNTERS_SUMMABLE
269 /* This should always be true for a just allocated entry,
270 and always false for an existing one. Check this way, in
271 case the gcov file is corrupt. */
272 && (!entry->chain || summaried != entry))
274 entry->chain = summaried;
275 summaried = entry;
277 for (ix = 0; ix != n_counts; ix++)
278 entry->counts[ix] += gcov_read_counter ();
279 skip_merge:;
281 gcov_sync (offset, length);
282 if ((error = gcov_is_error ()))
283 break;
286 if (!gcov_is_eof ())
288 warning (error < 0 ? "`%s' has overflowed" : "`%s' is corrupted",
289 da_file_name);
290 htab_delete (counts_hash);
293 gcov_close ();
296 /* Returns the counters for a particular tag. */
298 gcov_type *
299 get_coverage_counts (unsigned counter, unsigned expected,
300 const struct gcov_ctr_summary **summary)
302 counts_entry_t *entry, elt;
304 /* No hash table, no counts. */
305 if (!counts_hash)
307 static int warned = 0;
309 if (!warned++)
310 warning ("file %s not found, execution counts assumed to be zero",
311 da_file_name);
312 return NULL;
315 elt.ident = current_function_funcdef_no + 1;
316 elt.ctr = counter;
317 entry = htab_find (counts_hash, &elt);
318 if (!entry)
320 warning ("no coverage for function '%s' found.", IDENTIFIER_POINTER
321 (DECL_ASSEMBLER_NAME (current_function_decl)));
322 return 0;
325 if (expected != entry->summary.num
326 || compute_checksum () != entry->checksum)
328 warning ("coverage mismatch for `%s'", IDENTIFIER_POINTER
329 (DECL_ASSEMBLER_NAME (current_function_decl)));
330 return NULL;
333 if (summary)
334 *summary = &entry->summary;
336 return entry->counts;
339 /* Allocate NUM counters of type COUNTER. Returns nonzero if the
340 allocation succeeded. */
343 coverage_counter_alloc (unsigned counter, unsigned num)
345 if (no_coverage)
346 return 0;
348 if (!num)
349 return 1;
351 if (!ctr_labels[counter])
353 /* Generate and save a copy of this so it can be shared. */
354 char buf[20];
356 ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
357 ctr_labels[counter] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
359 fn_b_ctrs[counter] = fn_n_ctrs[counter];
360 fn_n_ctrs[counter] += num;
361 fn_ctr_mask |= 1 << counter;
362 return 1;
365 /* Generate a MEM rtl to access COUNTER NO. */
368 coverage_counter_ref (unsigned counter, unsigned no)
370 unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
371 enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
372 rtx ref;
374 if (no >= fn_n_ctrs[counter] - fn_b_ctrs[counter])
375 abort ();
376 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
377 ref = plus_constant (ctr_labels[counter], gcov_size / BITS_PER_UNIT * no);
378 ref = gen_rtx_MEM (mode, ref);
379 set_mem_alias_set (ref, new_alias_set ());
381 return ref;
384 /* Generate a checksum for a string. CHKSUM is the current
385 checksum. */
387 static unsigned
388 checksum_string (unsigned chksum, const char *string)
392 unsigned value = *string << 24;
393 unsigned ix;
395 for (ix = 8; ix--; value <<= 1)
397 unsigned feedback;
399 feedback = (value ^ chksum) & 0x80000000 ? 0x04c11db7 : 0;
400 chksum <<= 1;
401 chksum ^= feedback;
404 while (*string++);
406 return chksum;
409 /* Compute checksum for the current function. We generate a CRC32. */
411 static unsigned
412 compute_checksum (void)
414 unsigned chksum = DECL_SOURCE_LINE (current_function_decl);
416 chksum = checksum_string (chksum, DECL_SOURCE_FILE (current_function_decl));
417 chksum = checksum_string
418 (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
420 return chksum;
423 /* Begin output to the graph file for the current function.
424 Opens the output file, if not already done. Writes the
425 function header, if not already done. Returns nonzero if data
426 should be output. */
429 coverage_begin_output (void)
431 if (no_coverage)
432 return 0;
434 if (!bbg_function_announced)
436 const char *file = DECL_SOURCE_FILE (current_function_decl);
437 unsigned line = DECL_SOURCE_LINE (current_function_decl);
438 unsigned long offset;
440 if (!bbg_file_opened)
442 if (!gcov_open (bbg_file_name, -1))
443 error ("cannot open %s", bbg_file_name);
444 else
446 gcov_write_unsigned (GCOV_GRAPH_MAGIC);
447 gcov_write_unsigned (GCOV_VERSION);
449 bbg_file_opened = 1;
452 /* Announce function */
453 offset = gcov_write_tag (GCOV_TAG_FUNCTION);
454 gcov_write_unsigned (current_function_funcdef_no + 1);
455 gcov_write_unsigned (compute_checksum ());
456 gcov_write_string (IDENTIFIER_POINTER
457 (DECL_ASSEMBLER_NAME (current_function_decl)));
458 gcov_write_string (file);
459 gcov_write_unsigned (line);
460 gcov_write_length (offset);
462 bbg_function_announced = 1;
464 return !gcov_is_error ();
467 /* Finish coverage data for the current function. Verify no output
468 error has occurred. Save function coverage counts. */
470 void
471 coverage_end_function (void)
473 unsigned i;
475 if (bbg_file_opened > 1 && gcov_is_error ())
477 warning ("error writing `%s'", bbg_file_name);
478 bbg_file_opened = -1;
481 if (fn_ctr_mask)
483 struct function_list *item;
485 item = xmalloc (sizeof (struct function_list));
487 *functions_tail = item;
488 functions_tail = &item->next;
490 item->next = 0;
491 item->ident = current_function_funcdef_no + 1;
492 item->checksum = compute_checksum ();
493 for (i = 0; i != GCOV_COUNTERS; i++)
495 item->n_ctrs[i] = fn_n_ctrs[i];
496 prg_n_ctrs[i] += fn_n_ctrs[i];
497 fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
499 prg_ctr_mask |= fn_ctr_mask;
500 fn_ctr_mask = 0;
502 bbg_function_announced = 0;
505 /* Creates the gcov_fn_info RECORD_TYPE. */
507 static tree
508 build_fn_info_type (unsigned int counters)
510 tree type = (*lang_hooks.types.make_type) (RECORD_TYPE);
511 tree field, fields;
512 tree array_type;
514 /* ident */
515 fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
517 /* checksum */
518 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
519 TREE_CHAIN (field) = fields;
520 fields = field;
522 array_type = build_index_type (build_int_2 (counters - 1, 0));
523 array_type = build_array_type (unsigned_type_node, array_type);
525 /* counters */
526 field = build_decl (FIELD_DECL, NULL_TREE, array_type);
527 TREE_CHAIN (field) = fields;
528 fields = field;
530 finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
532 return type;
535 /* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
536 the function being processed and TYPE is the gcov_fn_info
537 RECORD_TYPE. */
539 static tree
540 build_fn_info_value (const struct function_list *function, tree type)
542 tree value = NULL_TREE;
543 tree fields = TYPE_FIELDS (type);
544 unsigned ix;
545 tree array_value = NULL_TREE;
547 /* ident */
548 value = tree_cons (fields,
549 convert (unsigned_intSI_type_node,
550 build_int_2 (function->ident, 0)),
551 value);
552 fields = TREE_CHAIN (fields);
554 /* checksum */
555 value = tree_cons (fields,
556 convert (unsigned_intSI_type_node,
557 build_int_2 (function->checksum, 0)),
558 value);
559 fields = TREE_CHAIN (fields);
561 /* counters */
562 for (ix = 0; ix != GCOV_COUNTERS; ix++)
563 if (prg_ctr_mask & (1 << ix))
565 tree counters = convert (unsigned_type_node,
566 build_int_2 (function->n_ctrs[ix], 0));
568 array_value = tree_cons (NULL_TREE, counters, array_value);
571 array_value = build_constructor (TREE_TYPE (fields), nreverse (array_value));
572 value = tree_cons (fields, array_value, value);
574 value = build_constructor (type, nreverse (value));
576 return value;
579 /* Creates the gcov_ctr_info RECORD_TYPE. */
581 static tree
582 build_ctr_info_type (void)
584 tree type = (*lang_hooks.types.make_type) (RECORD_TYPE);
585 tree field, fields = NULL_TREE;
586 tree gcov_ptr_type = build_pointer_type (GCOV_TYPE_NODE);
587 tree gcov_merge_fn_type;
589 /* counters */
590 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
591 TREE_CHAIN (field) = fields;
592 fields = field;
594 /* values */
595 field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
596 TREE_CHAIN (field) = fields;
597 fields = field;
599 /* merge */
600 gcov_merge_fn_type =
601 build_function_type_list (void_type_node,
602 gcov_ptr_type, unsigned_type_node,
603 NULL_TREE);
604 field = build_decl (FIELD_DECL, NULL_TREE,
605 build_pointer_type (gcov_merge_fn_type));
606 TREE_CHAIN (field) = fields;
607 fields = field;
609 finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
611 return type;
614 /* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
615 the counter being processed and TYPE is the gcov_ctr_info
616 RECORD_TYPE. */
618 static tree
619 build_ctr_info_value (unsigned int counter, tree type)
621 tree value = NULL_TREE;
622 tree fields = TYPE_FIELDS (type);
623 tree fn;
625 /* counters */
626 value = tree_cons (fields,
627 convert (unsigned_intSI_type_node,
628 build_int_2 (prg_n_ctrs[counter], 0)),
629 value);
630 fields = TREE_CHAIN (fields);
632 if (prg_n_ctrs[counter])
634 tree array_type, array;
636 array_type = build_index_type (build_int_2 (prg_n_ctrs[counter] - 1, 0));
637 array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
638 array_type);
640 array = build (VAR_DECL, array_type, NULL_TREE, NULL_TREE);
641 TREE_STATIC (array) = 1;
642 DECL_NAME (array) = get_identifier (XSTR (ctr_labels[counter], 0));
643 assemble_variable (array, 0, 0, 0);
645 value = tree_cons (fields,
646 build1 (ADDR_EXPR, TREE_TYPE (fields), array),
647 value);
649 else
650 value = tree_cons (fields, null_pointer_node, value);
651 fields = TREE_CHAIN (fields);
653 fn = build_decl (FUNCTION_DECL,
654 get_identifier (ctr_merge_functions[counter]),
655 TREE_TYPE (TREE_TYPE (fields)));
656 DECL_EXTERNAL (fn) = 1;
657 TREE_PUBLIC (fn) = 1;
658 DECL_ARTIFICIAL (fn) = 1;
659 TREE_NOTHROW (fn) = 1;
660 value = tree_cons (fields,
661 build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
662 value);
664 value = build_constructor (type, nreverse (value));
666 return value;
669 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
670 CONSTRUCTOR. */
672 static tree
673 build_gcov_info (void)
675 unsigned n_ctr_types, ix;
676 tree type, const_type;
677 tree fn_info_type, fn_info_value = NULL_TREE;
678 tree fn_info_ptr_type;
679 tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
680 tree field, fields = NULL_TREE;
681 tree value = NULL_TREE;
682 tree filename_string;
683 char *filename;
684 int filename_len;
685 unsigned n_fns;
686 const struct function_list *fn;
687 tree string_type;
689 /* Count the number of active counters. */
690 for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
691 if (prg_ctr_mask & (1 << ix))
692 n_ctr_types++;
694 type = (*lang_hooks.types.make_type) (RECORD_TYPE);
695 const_type = build_qualified_type (type, TYPE_QUAL_CONST);
697 /* Version ident */
698 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
699 TREE_CHAIN (field) = fields;
700 fields = field;
701 value = tree_cons (field, convert (unsigned_intSI_type_node,
702 build_int_2 (GCOV_VERSION, 0)),
703 value);
705 /* next -- NULL */
706 field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
707 TREE_CHAIN (field) = fields;
708 fields = field;
709 value = tree_cons (field, null_pointer_node, value);
711 /* Filename */
712 string_type = build_pointer_type (build_qualified_type (char_type_node,
713 TYPE_QUAL_CONST));
714 field = build_decl (FIELD_DECL, NULL_TREE, string_type);
715 TREE_CHAIN (field) = fields;
716 fields = field;
717 filename = getpwd ();
718 filename = (filename && da_file_name[0] != '/'
719 ? concat (filename, "/", da_file_name, NULL)
720 : da_file_name);
721 filename_len = strlen (filename);
722 filename_string = build_string (filename_len + 1, filename);
723 if (filename != da_file_name)
724 free (filename);
725 TREE_TYPE (filename_string) =
726 build_array_type (char_type_node,
727 build_index_type (build_int_2 (filename_len, 0)));
728 value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
729 value);
731 /* Build the fn_info type and initializer. */
732 fn_info_type = build_fn_info_type (n_ctr_types);
733 fn_info_ptr_type = build_pointer_type (build_qualified_type
734 (fn_info_type, TYPE_QUAL_CONST));
735 for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
736 fn_info_value = tree_cons (NULL_TREE,
737 build_fn_info_value (fn, fn_info_type),
738 fn_info_value);
739 if (n_fns)
741 tree array_type;
743 array_type = build_index_type (build_int_2 (n_fns - 1, 0));
744 array_type = build_array_type (fn_info_type, array_type);
746 fn_info_value = build_constructor (array_type, nreverse (fn_info_value));
747 fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
749 else
750 fn_info_value = null_pointer_node;
752 /* number of functions */
753 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
754 TREE_CHAIN (field) = fields;
755 fields = field;
756 value = tree_cons (field,
757 convert (unsigned_type_node, build_int_2 (n_fns, 0)),
758 value);
760 /* fn_info table */
761 field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type);
762 TREE_CHAIN (field) = fields;
763 fields = field;
764 value = tree_cons (field, fn_info_value, value);
766 /* counter_mask */
767 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
768 TREE_CHAIN (field) = fields;
769 fields = field;
770 value = tree_cons (field,
771 convert (unsigned_type_node,
772 build_int_2 (prg_ctr_mask, 0)),
773 value);
775 /* counters */
776 ctr_info_type = build_ctr_info_type ();
777 ctr_info_ary_type = build_index_type (build_int_2 (n_ctr_types, 0));
778 ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
779 for (ix = 0; ix != GCOV_COUNTERS; ix++)
780 if (prg_ctr_mask & (1 << ix))
781 ctr_info_value = tree_cons (NULL_TREE,
782 build_ctr_info_value (ix, ctr_info_type),
783 ctr_info_value);
784 ctr_info_value = build_constructor (ctr_info_ary_type,
785 nreverse (ctr_info_value));
787 field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
788 TREE_CHAIN (field) = fields;
789 fields = field;
790 value = tree_cons (field, ctr_info_value, value);
792 finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
794 value = build_constructor (type, nreverse (value));
796 return value;
799 /* Write out the structure which libgcov uses to locate all the
800 counters. The structures used here must match those defined in
801 gcov-io.h. Write out the constructor to call __gcov_init. */
803 static void
804 create_coverage (void)
806 tree gcov_info, gcov_info_value;
807 char name[20];
808 char *ctor_name;
809 tree ctor;
810 rtx gcov_info_address;
812 no_coverage = 1; /* Disable any further coverage. */
814 if (!prg_ctr_mask)
815 return;
817 gcov_info_value = build_gcov_info ();
819 gcov_info = build (VAR_DECL, TREE_TYPE (gcov_info_value),
820 NULL_TREE, NULL_TREE);
821 DECL_INITIAL (gcov_info) = gcov_info_value;
823 TREE_STATIC (gcov_info) = 1;
824 ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 0);
825 DECL_NAME (gcov_info) = get_identifier (name);
827 /* Build structure. */
828 assemble_variable (gcov_info, 0, 0, 0);
830 /* Build the constructor function to invoke __gcov_init. */
831 ctor_name = concat (IDENTIFIER_POINTER (get_file_function_name ('I')),
832 "_GCOV", NULL);
833 ctor = build_decl (FUNCTION_DECL, get_identifier (ctor_name),
834 build_function_type (void_type_node, NULL_TREE));
835 free (ctor_name);
836 DECL_EXTERNAL (ctor) = 0;
838 /* It can be a static function as long as collect2 does not have
839 to scan the object file to find its ctor/dtor routine. */
840 TREE_PUBLIC (ctor) = ! targetm.have_ctors_dtors;
841 TREE_USED (ctor) = 1;
842 DECL_RESULT (ctor) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
843 DECL_UNINLINABLE (ctor) = 1;
845 ctor = (*lang_hooks.decls.pushdecl) (ctor);
846 rest_of_decl_compilation (ctor, 0, 1, 0);
847 announce_function (ctor);
848 current_function_decl = ctor;
849 DECL_INITIAL (ctor) = error_mark_node;
850 make_decl_rtl (ctor, NULL);
851 init_function_start (ctor);
852 (*lang_hooks.decls.pushlevel) (0);
853 expand_function_start (ctor, 0);
855 /* Actually generate the code to call __gcov_init. */
856 gcov_info_address = force_reg (Pmode, XEXP (DECL_RTL (gcov_info), 0));
857 emit_library_call (gcov_init_libfunc, LCT_NORMAL, VOIDmode, 1,
858 gcov_info_address, Pmode);
860 expand_function_end ();
861 (*lang_hooks.decls.poplevel) (1, 0, 1);
863 rest_of_compilation (ctor);
865 if (! quiet_flag)
866 fflush (asm_out_file);
867 current_function_decl = NULL_TREE;
869 if (targetm.have_ctors_dtors)
870 (* targetm.asm_out.constructor) (XEXP (DECL_RTL (ctor), 0),
871 DEFAULT_INIT_PRIORITY);
874 /* Perform file-level initialization. Read in data file, generate name
875 of graph file. */
877 void
878 coverage_init (const char *filename)
880 int len = strlen (filename);
882 /* Name of da file. */
883 da_file_name = (char *) xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1);
884 strcpy (da_file_name, filename);
885 strcat (da_file_name, GCOV_DATA_SUFFIX);
887 /* Name of bbg file. */
888 bbg_file_name = (char *) xmalloc (len + strlen (GCOV_GRAPH_SUFFIX) + 1);
889 strcpy (bbg_file_name, filename);
890 strcat (bbg_file_name, GCOV_GRAPH_SUFFIX);
892 read_counts_file ();
895 /* Performs file-level cleanup. Close graph file, generate coverage
896 variables and constructor. */
898 void
899 coverage_finish (void)
901 create_coverage ();
902 if (bbg_file_opened)
904 int error = gcov_close ();
906 if (error)
907 unlink (bbg_file_name);
908 #if SELF_COVERAGE
909 /* If the compiler is instrumented, we should not
910 unconditionally remove the counts file, because we might be
911 recompiling ourselves. The .da files are all removed during
912 copying the stage1 files. */
913 if (error)
914 #endif
915 unlink (da_file_name);
919 #include "gt-coverage.h"