2002-06-06 James Clark <jjc@jclark.com>
[official-gcc.git] / gcc / coverage.c
blob1b537c621ebabe72f02721350aacaaf0deb6f3e5
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 PARAMS ((const void *));
108 static int htab_counts_entry_eq PARAMS ((const void *, const void *));
109 static void htab_counts_entry_del PARAMS ((void *));
110 static void read_counts_file PARAMS ((void));
111 static unsigned compute_checksum PARAMS ((void));
112 static unsigned checksum_string PARAMS ((unsigned, const char *));
113 static tree build_fn_info_type PARAMS ((unsigned));
114 static tree build_fn_info_value PARAMS ((const struct function_list *, tree));
115 static tree build_ctr_info_type PARAMS ((void));
116 static tree build_ctr_info_value PARAMS ((unsigned, tree));
117 static tree build_gcov_info PARAMS ((void));
118 static void create_coverage PARAMS ((void));
121 static hashval_t
122 htab_counts_entry_hash (of)
123 const void *of;
125 const counts_entry_t *entry = of;
127 return entry->ident * GCOV_COUNTERS + entry->ctr;
130 static int
131 htab_counts_entry_eq (of1, of2)
132 const void *of1;
133 const void *of2;
135 const counts_entry_t *entry1 = of1;
136 const counts_entry_t *entry2 = of2;
138 return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
141 static void
142 htab_counts_entry_del (of)
143 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 ()
156 gcov_unsigned_t fn_ident = 0;
157 gcov_unsigned_t version, checksum = -1;
158 unsigned ix;
159 counts_entry_t *summaried = NULL;
160 unsigned seen_summary = 0;
161 gcov_unsigned_t tag;
162 int error = 0;
164 if (!gcov_open (da_file_name, 1))
165 return;
167 if (gcov_read_unsigned () != GCOV_DATA_MAGIC)
169 warning ("`%s' is not a gcov data file", da_file_name);
170 gcov_close ();
171 return;
173 else if ((version = gcov_read_unsigned ()) != GCOV_VERSION)
175 char v[4], e[4];
176 gcov_unsigned_t required = GCOV_VERSION;
178 for (ix = 4; ix--; required >>= 8, version >>= 8)
180 v[ix] = version;
181 e[ix] = required;
183 warning ("`%s' is version `%.4s', expected version `%.4s'",
184 da_file_name, v, e);
185 gcov_close ();
186 return;
189 counts_hash = htab_create (10,
190 htab_counts_entry_hash, htab_counts_entry_eq,
191 htab_counts_entry_del);
192 while ((tag = gcov_read_unsigned ()))
194 gcov_unsigned_t length;
195 gcov_position_t offset;
197 length = gcov_read_unsigned ();
198 offset = gcov_position ();
199 if (tag == GCOV_TAG_FUNCTION)
201 fn_ident = gcov_read_unsigned ();
202 checksum = gcov_read_unsigned ();
203 if (seen_summary)
205 /* We have already seen a summary, this means that this
206 new function begins a new set of program runs. We
207 must unlink the summaried chain. */
208 counts_entry_t *entry, *chain;
210 for (entry = summaried; entry; entry = chain)
212 chain = entry->chain;
213 entry->chain = NULL;
215 summaried = NULL;
216 seen_summary = 0;
219 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
221 counts_entry_t *entry;
222 struct gcov_summary summary;
224 gcov_read_summary (&summary);
225 seen_summary = 1;
226 for (entry = summaried; entry; entry = entry->chain)
228 struct gcov_ctr_summary *csum = &summary.ctrs[entry->ctr];
230 entry->summary.runs += csum->runs;
231 entry->summary.sum_all += csum->sum_all;
232 if (entry->summary.run_max < csum->run_max)
233 entry->summary.run_max = csum->run_max;
234 entry->summary.sum_max += csum->sum_max;
237 else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
239 counts_entry_t **slot, *entry, elt;
240 unsigned n_counts = length / 8;
241 unsigned ix;
243 elt.ident = fn_ident;
244 elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
246 slot = (counts_entry_t **) htab_find_slot
247 (counts_hash, &elt, INSERT);
248 entry = *slot;
249 if (!entry)
251 *slot = entry = xcalloc (1, sizeof (counts_entry_t));
252 entry->ident = elt.ident;
253 entry->ctr = elt.ctr;
254 entry->checksum = checksum;
255 entry->summary.num = n_counts;
256 entry->counts = xcalloc (n_counts, sizeof (gcov_type));
258 else if (entry->checksum != checksum
259 || entry->summary.num != n_counts)
261 warning ("coverage mismatch for function %u", fn_ident);
262 htab_delete (counts_hash);
263 break;
265 else if (elt.ctr >= GCOV_COUNTERS_SUMMABLE)
267 warning ("cannot merge separate %s counters for function %u",
268 ctr_names[elt.ctr], fn_ident);
269 goto skip_merge;
272 if (elt.ctr < GCOV_COUNTERS_SUMMABLE
273 /* This should always be true for a just allocated entry,
274 and always false for an existing one. Check this way, in
275 case the gcov file is corrupt. */
276 && (!entry->chain || summaried != entry))
278 entry->chain = summaried;
279 summaried = entry;
281 for (ix = 0; ix != n_counts; ix++)
282 entry->counts[ix] += gcov_read_counter ();
283 skip_merge:;
285 gcov_sync (offset, length);
286 if ((error = gcov_is_error ()))
287 break;
290 if (!gcov_is_eof ())
292 warning (error < 0 ? "`%s' has overflowed" : "`%s' is corrupted",
293 da_file_name);
294 htab_delete (counts_hash);
297 gcov_close ();
300 /* Returns the counters for a particular tag. */
302 gcov_type *
303 get_coverage_counts (unsigned counter, unsigned expected,
304 const struct gcov_ctr_summary **summary)
306 counts_entry_t *entry, elt;
308 /* No hash table, no counts. */
309 if (!counts_hash)
311 static int warned = 0;
313 if (!warned++)
314 warning ("file %s not found, execution counts assumed to be zero",
315 da_file_name);
316 return NULL;
319 elt.ident = current_function_funcdef_no + 1;
320 elt.ctr = counter;
321 entry = htab_find (counts_hash, &elt);
322 if (!entry)
324 warning ("no coverage for function '%s' found.", IDENTIFIER_POINTER
325 (DECL_ASSEMBLER_NAME (current_function_decl)));
326 return 0;
329 if (expected != entry->summary.num
330 || compute_checksum () != entry->checksum)
332 warning ("coverage mismatch for `%s'", IDENTIFIER_POINTER
333 (DECL_ASSEMBLER_NAME (current_function_decl)));
334 return NULL;
337 if (summary)
338 *summary = &entry->summary;
340 return entry->counts;
343 /* Allocate NUM counters of type COUNTER. Returns non-zero if the
344 allocation succeeded. */
347 coverage_counter_alloc (unsigned counter, unsigned num)
349 if (no_coverage)
350 return 0;
352 if (!num)
353 return 1;
355 if (!ctr_labels[counter])
357 /* Generate and save a copy of this so it can be shared. */
358 char buf[20];
360 ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
361 ctr_labels[counter] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
363 fn_b_ctrs[counter] = fn_n_ctrs[counter];
364 fn_n_ctrs[counter] += num;
365 fn_ctr_mask |= 1 << counter;
366 return 1;
369 /* Generate a MEM rtl to access COUNTER NO. */
372 coverage_counter_ref (unsigned counter, unsigned no)
374 unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
375 enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
376 rtx ref;
378 if (no >= fn_n_ctrs[counter] - fn_b_ctrs[counter])
379 abort ();
380 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
381 ref = plus_constant (ctr_labels[counter], gcov_size / BITS_PER_UNIT * no);
382 ref = gen_rtx_MEM (mode, ref);
383 set_mem_alias_set (ref, new_alias_set ());
385 return ref;
388 /* Generate a checksum for a string. CHKSUM is the current
389 checksum. */
391 static unsigned
392 checksum_string (unsigned chksum, const char *string)
396 unsigned value = *string << 24;
397 unsigned ix;
399 for (ix = 8; ix--; value <<= 1)
401 unsigned feedback;
403 feedback = (value ^ chksum) & 0x80000000 ? 0x04c11db7 : 0;
404 chksum <<= 1;
405 chksum ^= feedback;
408 while (*string++);
410 return chksum;
413 /* Compute checksum for the current function. We generate a CRC32. */
415 static unsigned
416 compute_checksum ()
418 unsigned chksum = DECL_SOURCE_LINE (current_function_decl);
420 chksum = checksum_string (chksum, DECL_SOURCE_FILE (current_function_decl));
421 chksum = checksum_string
422 (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
424 return chksum;
427 /* Begin output to the graph file for the current function.
428 Opens the output file, if not already done. Writes the
429 function header, if not already done. Returns non-zero if data
430 should be output. */
433 coverage_begin_output ()
435 if (no_coverage)
436 return 0;
438 if (!bbg_function_announced)
440 const char *file = DECL_SOURCE_FILE (current_function_decl);
441 unsigned line = DECL_SOURCE_LINE (current_function_decl);
442 unsigned long offset;
444 if (!bbg_file_opened)
446 if (!gcov_open (bbg_file_name, -1))
447 error ("cannot open %s", bbg_file_name);
448 else
450 gcov_write_unsigned (GCOV_GRAPH_MAGIC);
451 gcov_write_unsigned (GCOV_VERSION);
453 bbg_file_opened = 1;
456 /* Announce function */
457 offset = gcov_write_tag (GCOV_TAG_FUNCTION);
458 gcov_write_unsigned (current_function_funcdef_no + 1);
459 gcov_write_unsigned (compute_checksum ());
460 gcov_write_string (IDENTIFIER_POINTER
461 (DECL_ASSEMBLER_NAME (current_function_decl)));
462 gcov_write_string (file);
463 gcov_write_unsigned (line);
464 gcov_write_length (offset);
466 bbg_function_announced = 1;
468 return !gcov_is_error ();
471 /* Finish coverage data for the current function. Verify no output
472 error has occurred. Save function coverage counts. */
474 void
475 coverage_end_function ()
477 unsigned i;
479 if (bbg_file_opened > 1 && gcov_is_error ())
481 warning ("error writing `%s'", bbg_file_name);
482 bbg_file_opened = -1;
485 if (fn_ctr_mask)
487 struct function_list *item;
489 item = xmalloc (sizeof (struct function_list));
491 *functions_tail = item;
492 functions_tail = &item->next;
494 item->next = 0;
495 item->ident = current_function_funcdef_no + 1;
496 item->checksum = compute_checksum ();
497 for (i = 0; i != GCOV_COUNTERS; i++)
499 item->n_ctrs[i] = fn_n_ctrs[i];
500 prg_n_ctrs[i] += fn_n_ctrs[i];
501 fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
503 prg_ctr_mask |= fn_ctr_mask;
504 fn_ctr_mask = 0;
506 bbg_function_announced = 0;
509 /* Creates the gcov_fn_info RECORD_TYPE. */
511 static tree
512 build_fn_info_type (counters)
513 unsigned counters;
515 tree type = (*lang_hooks.types.make_type) (RECORD_TYPE);
516 tree field, fields;
517 tree array_type;
519 /* ident */
520 fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
522 /* checksum */
523 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
524 TREE_CHAIN (field) = fields;
525 fields = field;
527 array_type = build_index_type (build_int_2 (counters - 1, 0));
528 array_type = build_array_type (unsigned_type_node, array_type);
530 /* counters */
531 field = build_decl (FIELD_DECL, NULL_TREE, array_type);
532 TREE_CHAIN (field) = fields;
533 fields = field;
535 finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
537 return type;
540 /* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
541 the function being processed and TYPE is the gcov_fn_info
542 RECORD_TYPE. */
544 static tree
545 build_fn_info_value (function, type)
546 const struct function_list *function;
547 tree type;
549 tree value = NULL_TREE;
550 tree fields = TYPE_FIELDS (type);
551 unsigned ix;
552 tree array_value = NULL_TREE;
554 /* ident */
555 value = tree_cons (fields,
556 convert (unsigned_intSI_type_node,
557 build_int_2 (function->ident, 0)),
558 value);
559 fields = TREE_CHAIN (fields);
561 /* checksum */
562 value = tree_cons (fields,
563 convert (unsigned_intSI_type_node,
564 build_int_2 (function->checksum, 0)),
565 value);
566 fields = TREE_CHAIN (fields);
568 /* counters */
569 for (ix = 0; ix != GCOV_COUNTERS; ix++)
570 if (prg_ctr_mask & (1 << ix))
572 tree counters = convert (unsigned_type_node,
573 build_int_2 (function->n_ctrs[ix], 0));
575 array_value = tree_cons (NULL_TREE, counters, array_value);
578 array_value = build_constructor (TREE_TYPE (fields), nreverse (array_value));
579 value = tree_cons (fields, array_value, value);
581 value = build_constructor (type, nreverse (value));
583 return value;
586 /* Creates the gcov_ctr_info RECORD_TYPE. */
588 static tree
589 build_ctr_info_type ()
591 tree type = (*lang_hooks.types.make_type) (RECORD_TYPE);
592 tree field, fields = NULL_TREE;
593 tree gcov_ptr_type = build_pointer_type (GCOV_TYPE_NODE);
594 tree gcov_merge_fn_type;
596 /* counters */
597 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
598 TREE_CHAIN (field) = fields;
599 fields = field;
601 /* values */
602 field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
603 TREE_CHAIN (field) = fields;
604 fields = field;
606 /* merge */
607 gcov_merge_fn_type =
608 build_function_type_list (void_type_node,
609 gcov_ptr_type, unsigned_type_node,
610 NULL_TREE);
611 field = build_decl (FIELD_DECL, NULL_TREE,
612 build_pointer_type (gcov_merge_fn_type));
613 TREE_CHAIN (field) = fields;
614 fields = field;
616 finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
618 return type;
621 /* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
622 the counter being processed and TYPE is the gcov_ctr_info
623 RECORD_TYPE. */
625 static tree
626 build_ctr_info_value (counter, type)
627 unsigned counter;
628 tree type;
630 tree value = NULL_TREE;
631 tree fields = TYPE_FIELDS (type);
632 tree fn;
634 /* counters */
635 value = tree_cons (fields,
636 convert (unsigned_intSI_type_node,
637 build_int_2 (prg_n_ctrs[counter], 0)),
638 value);
639 fields = TREE_CHAIN (fields);
641 if (prg_n_ctrs[counter])
643 tree array_type, array;
645 array_type = build_index_type (build_int_2 (prg_n_ctrs[counter] - 1, 0));
646 array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
647 array_type);
649 array = build (VAR_DECL, array_type, NULL_TREE, NULL_TREE);
650 TREE_STATIC (array) = 1;
651 DECL_NAME (array) = get_identifier (XSTR (ctr_labels[counter], 0));
652 assemble_variable (array, 0, 0, 0);
654 value = tree_cons (fields,
655 build1 (ADDR_EXPR, TREE_TYPE (fields), array),
656 value);
658 else
659 value = tree_cons (fields, null_pointer_node, value);
660 fields = TREE_CHAIN (fields);
662 fn = build_decl (FUNCTION_DECL,
663 get_identifier (ctr_merge_functions[counter]),
664 TREE_TYPE (TREE_TYPE (fields)));
665 DECL_EXTERNAL (fn) = 1;
666 TREE_PUBLIC (fn) = 1;
667 DECL_ARTIFICIAL (fn) = 1;
668 TREE_NOTHROW (fn) = 1;
669 value = tree_cons (fields,
670 build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
671 value);
673 value = build_constructor (type, nreverse (value));
675 return value;
678 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
679 CONSTRUCTOR. */
681 static tree
682 build_gcov_info ()
684 unsigned n_ctr_types, ix;
685 tree type, const_type;
686 tree fn_info_type, fn_info_value = NULL_TREE;
687 tree fn_info_ptr_type;
688 tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
689 tree field, fields = NULL_TREE;
690 tree value = NULL_TREE;
691 tree filename_string;
692 char *filename;
693 int filename_len;
694 unsigned n_fns;
695 const struct function_list *fn;
696 tree string_type;
698 /* Count the number of active counters. */
699 for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
700 if (prg_ctr_mask & (1 << ix))
701 n_ctr_types++;
703 type = (*lang_hooks.types.make_type) (RECORD_TYPE);
704 const_type = build_qualified_type (type, TYPE_QUAL_CONST);
706 /* Version ident */
707 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
708 TREE_CHAIN (field) = fields;
709 fields = field;
710 value = tree_cons (field, convert (unsigned_intSI_type_node,
711 build_int_2 (GCOV_VERSION, 0)),
712 value);
714 /* next -- NULL */
715 field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
716 TREE_CHAIN (field) = fields;
717 fields = field;
718 value = tree_cons (field, null_pointer_node, value);
720 /* Filename */
721 string_type = build_pointer_type (build_qualified_type (char_type_node,
722 TYPE_QUAL_CONST));
723 field = build_decl (FIELD_DECL, NULL_TREE, string_type);
724 TREE_CHAIN (field) = fields;
725 fields = field;
726 filename = getpwd ();
727 filename = (filename && da_file_name[0] != '/'
728 ? concat (filename, "/", da_file_name, NULL)
729 : da_file_name);
730 filename_len = strlen (filename);
731 filename_string = build_string (filename_len + 1, filename);
732 if (filename != da_file_name)
733 free (filename);
734 TREE_TYPE (filename_string) =
735 build_array_type (char_type_node,
736 build_index_type (build_int_2 (filename_len, 0)));
737 value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
738 value);
740 /* Build the fn_info type and initializer. */
741 fn_info_type = build_fn_info_type (n_ctr_types);
742 fn_info_ptr_type = build_pointer_type (build_qualified_type
743 (fn_info_type, TYPE_QUAL_CONST));
744 for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
745 fn_info_value = tree_cons (NULL_TREE,
746 build_fn_info_value (fn, fn_info_type),
747 fn_info_value);
748 if (n_fns)
750 tree array_type;
752 array_type = build_index_type (build_int_2 (n_fns - 1, 0));
753 array_type = build_array_type (fn_info_type, array_type);
755 fn_info_value = build_constructor (array_type, nreverse (fn_info_value));
756 fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
758 else
759 fn_info_value = null_pointer_node;
761 /* number of functions */
762 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
763 TREE_CHAIN (field) = fields;
764 fields = field;
765 value = tree_cons (field,
766 convert (unsigned_type_node, build_int_2 (n_fns, 0)),
767 value);
769 /* fn_info table */
770 field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type);
771 TREE_CHAIN (field) = fields;
772 fields = field;
773 value = tree_cons (field, fn_info_value, value);
775 /* counter_mask */
776 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
777 TREE_CHAIN (field) = fields;
778 fields = field;
779 value = tree_cons (field,
780 convert (unsigned_type_node,
781 build_int_2 (prg_ctr_mask, 0)),
782 value);
784 /* counters */
785 ctr_info_type = build_ctr_info_type ();
786 ctr_info_ary_type = build_index_type (build_int_2 (n_ctr_types, 0));
787 ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
788 for (ix = 0; ix != GCOV_COUNTERS; ix++)
789 if (prg_ctr_mask & (1 << ix))
790 ctr_info_value = tree_cons (NULL_TREE,
791 build_ctr_info_value (ix, ctr_info_type),
792 ctr_info_value);
793 ctr_info_value = build_constructor (ctr_info_ary_type,
794 nreverse (ctr_info_value));
796 field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
797 TREE_CHAIN (field) = fields;
798 fields = field;
799 value = tree_cons (field, ctr_info_value, value);
801 finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
803 value = build_constructor (type, nreverse (value));
805 return value;
808 /* Write out the structure which libgcov uses to locate all the
809 counters. The structures used here must match those defined in
810 gcov-io.h. Write out the constructor to call __gcov_init. */
812 static void
813 create_coverage ()
815 tree gcov_info, gcov_info_value;
816 char name[20];
817 char *ctor_name;
818 tree ctor;
819 rtx gcov_info_address;
821 no_coverage = 1; /* Disable any further coverage. */
823 if (!prg_ctr_mask)
824 return;
826 gcov_info_value = build_gcov_info ();
828 gcov_info = build (VAR_DECL, TREE_TYPE (gcov_info_value),
829 NULL_TREE, NULL_TREE);
830 DECL_INITIAL (gcov_info) = gcov_info_value;
832 TREE_STATIC (gcov_info) = 1;
833 ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 0);
834 DECL_NAME (gcov_info) = get_identifier (name);
836 /* Build structure. */
837 assemble_variable (gcov_info, 0, 0, 0);
839 /* Build the constructor function to invoke __gcov_init. */
840 ctor_name = concat (IDENTIFIER_POINTER (get_file_function_name ('I')),
841 "_GCOV", NULL);
842 ctor = build_decl (FUNCTION_DECL, get_identifier (ctor_name),
843 build_function_type (void_type_node, NULL_TREE));
844 free (ctor_name);
845 DECL_EXTERNAL (ctor) = 0;
847 /* It can be a static function as long as collect2 does not have
848 to scan the object file to find its ctor/dtor routine. */
849 TREE_PUBLIC (ctor) = ! targetm.have_ctors_dtors;
850 TREE_USED (ctor) = 1;
851 DECL_RESULT (ctor) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
852 DECL_UNINLINABLE (ctor) = 1;
854 ctor = (*lang_hooks.decls.pushdecl) (ctor);
855 rest_of_decl_compilation (ctor, 0, 1, 0);
856 announce_function (ctor);
857 current_function_decl = ctor;
858 DECL_INITIAL (ctor) = error_mark_node;
859 make_decl_rtl (ctor, NULL);
860 init_function_start (ctor, input_filename, input_line);
861 (*lang_hooks.decls.pushlevel) (0);
862 expand_function_start (ctor, 0);
864 /* Actually generate the code to call __gcov_init. */
865 gcov_info_address = force_reg (Pmode, XEXP (DECL_RTL (gcov_info), 0));
866 emit_library_call (gcov_init_libfunc, LCT_NORMAL, VOIDmode, 1,
867 gcov_info_address, Pmode);
869 expand_function_end (input_filename, input_line, 0);
870 (*lang_hooks.decls.poplevel) (1, 0, 1);
872 rest_of_compilation (ctor);
874 if (! quiet_flag)
875 fflush (asm_out_file);
876 current_function_decl = NULL_TREE;
878 if (targetm.have_ctors_dtors)
879 (* targetm.asm_out.constructor) (XEXP (DECL_RTL (ctor), 0),
880 DEFAULT_INIT_PRIORITY);
883 /* Perform file-level initialization. Read in data file, generate name
884 of graph file. */
886 void
887 coverage_init (filename)
888 const char *filename;
890 int len = strlen (filename);
892 /* Name of da file. */
893 da_file_name = (char *) xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1);
894 strcpy (da_file_name, filename);
895 strcat (da_file_name, GCOV_DATA_SUFFIX);
897 /* Name of bbg file. */
898 bbg_file_name = (char *) xmalloc (len + strlen (GCOV_GRAPH_SUFFIX) + 1);
899 strcpy (bbg_file_name, filename);
900 strcat (bbg_file_name, GCOV_GRAPH_SUFFIX);
902 read_counts_file ();
905 /* Performs file-level cleanup. Close graph file, generate coverage
906 variables and constructor. */
908 void
909 coverage_finish ()
911 create_coverage ();
912 if (bbg_file_opened)
914 int error = gcov_close ();
916 if (error)
917 unlink (bbg_file_name);
918 #if SELF_COVERAGE
919 /* If the compiler is instrumented, we should not
920 unconditionally remove the counts file, because we might be
921 recompiling ourselves. The .da files are all removed during
922 copying the stage1 files. */
923 if (error)
924 #endif
925 unlink (da_file_name);
929 #include "gt-coverage.h"