* dbxout.c (current_file): Also wrap inside DBX_DEBUGGING_INFO ||
[official-gcc.git] / gcc / coverage.c
blobb02c97c15d652a1702b331a934b3eefd19d74f50
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 checksum = -1;
154 counts_entry_t *summaried = NULL;
155 unsigned seen_summary = 0;
156 gcov_unsigned_t tag;
157 int error = 0;
159 if (!gcov_open (da_file_name, 1))
160 return;
162 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
164 warning ("`%s' is not a gcov data file", da_file_name);
165 gcov_close ();
166 return;
168 else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
170 char v[4], e[4];
172 GCOV_UNSIGNED2STRING (v, tag);
173 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
175 warning ("`%s' is version `%.4s', expected version `%.4s'",
176 da_file_name, v, e);
177 gcov_close ();
178 return;
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 ();
198 if (seen_summary)
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;
208 entry->chain = NULL;
210 summaried = NULL;
211 seen_summary = 0;
214 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
216 counts_entry_t *entry;
217 struct gcov_summary summary;
219 gcov_read_summary (&summary);
220 seen_summary = 1;
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);
236 unsigned ix;
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);
243 entry = *slot;
244 if (!entry)
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
254 || entry->summary.num != n_counts)
256 warning ("coverage mismatch for function %u", fn_ident);
257 htab_delete (counts_hash);
258 break;
260 else if (elt.ctr >= GCOV_COUNTERS_SUMMABLE)
262 warning ("cannot merge separate %s counters for function %u",
263 ctr_names[elt.ctr], fn_ident);
264 goto skip_merge;
267 if (elt.ctr < GCOV_COUNTERS_SUMMABLE
268 /* This should always be true for a just allocated entry,
269 and always false for an existing one. Check this way, in
270 case the gcov file is corrupt. */
271 && (!entry->chain || summaried != entry))
273 entry->chain = summaried;
274 summaried = entry;
276 for (ix = 0; ix != n_counts; ix++)
277 entry->counts[ix] += gcov_read_counter ();
278 skip_merge:;
280 gcov_sync (offset, length);
281 if ((error = gcov_is_error ()))
282 break;
285 if (!gcov_is_eof ())
287 warning (error < 0 ? "`%s' has overflowed" : "`%s' is corrupted",
288 da_file_name);
289 htab_delete (counts_hash);
292 gcov_close ();
295 /* Returns the counters for a particular tag. */
297 gcov_type *
298 get_coverage_counts (unsigned counter, unsigned expected,
299 const struct gcov_ctr_summary **summary)
301 counts_entry_t *entry, elt;
303 /* No hash table, no counts. */
304 if (!counts_hash)
306 static int warned = 0;
308 if (!warned++)
309 warning ("file %s not found, execution counts assumed to be zero",
310 da_file_name);
311 return NULL;
314 elt.ident = current_function_funcdef_no + 1;
315 elt.ctr = counter;
316 entry = htab_find (counts_hash, &elt);
317 if (!entry)
319 warning ("no coverage for function '%s' found.", IDENTIFIER_POINTER
320 (DECL_ASSEMBLER_NAME (current_function_decl)));
321 return 0;
324 if (expected != entry->summary.num
325 || compute_checksum () != entry->checksum)
327 warning ("coverage mismatch for `%s'", IDENTIFIER_POINTER
328 (DECL_ASSEMBLER_NAME (current_function_decl)));
329 return NULL;
332 if (summary)
333 *summary = &entry->summary;
335 return entry->counts;
338 /* Allocate NUM counters of type COUNTER. Returns nonzero if the
339 allocation succeeded. */
342 coverage_counter_alloc (unsigned counter, unsigned num)
344 if (no_coverage)
345 return 0;
347 if (!num)
348 return 1;
350 if (!ctr_labels[counter])
352 /* Generate and save a copy of this so it can be shared. */
353 char buf[20];
355 ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
356 ctr_labels[counter] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
358 fn_b_ctrs[counter] = fn_n_ctrs[counter];
359 fn_n_ctrs[counter] += num;
360 fn_ctr_mask |= 1 << counter;
361 return 1;
364 /* Generate a MEM rtl to access COUNTER NO. */
367 coverage_counter_ref (unsigned counter, unsigned no)
369 unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
370 enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
371 rtx ref;
373 if (no >= fn_n_ctrs[counter] - fn_b_ctrs[counter])
374 abort ();
375 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
376 ref = plus_constant (ctr_labels[counter], gcov_size / BITS_PER_UNIT * no);
377 ref = gen_rtx_MEM (mode, ref);
378 set_mem_alias_set (ref, new_alias_set ());
380 return ref;
383 /* Generate a checksum for a string. CHKSUM is the current
384 checksum. */
386 static unsigned
387 checksum_string (unsigned chksum, const char *string)
391 unsigned value = *string << 24;
392 unsigned ix;
394 for (ix = 8; ix--; value <<= 1)
396 unsigned feedback;
398 feedback = (value ^ chksum) & 0x80000000 ? 0x04c11db7 : 0;
399 chksum <<= 1;
400 chksum ^= feedback;
403 while (*string++);
405 return chksum;
408 /* Compute checksum for the current function. We generate a CRC32. */
410 static unsigned
411 compute_checksum (void)
413 unsigned chksum = DECL_SOURCE_LINE (current_function_decl);
415 chksum = checksum_string (chksum, DECL_SOURCE_FILE (current_function_decl));
416 chksum = checksum_string
417 (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
419 return chksum;
422 /* Begin output to the graph file for the current function.
423 Opens the output file, if not already done. Writes the
424 function header, if not already done. Returns nonzero if data
425 should be output. */
428 coverage_begin_output (void)
430 if (no_coverage)
431 return 0;
433 if (!bbg_function_announced)
435 const char *file = DECL_SOURCE_FILE (current_function_decl);
436 unsigned line = DECL_SOURCE_LINE (current_function_decl);
437 unsigned long offset;
439 if (!bbg_file_opened)
441 if (!gcov_open (bbg_file_name, -1))
442 error ("cannot open %s", bbg_file_name);
443 else
445 gcov_write_unsigned (GCOV_NOTE_MAGIC);
446 gcov_write_unsigned (GCOV_VERSION);
447 gcov_write_unsigned (local_tick);
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_decl (VAR_DECL, NULL_TREE, array_type);
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 /* stamp */
712 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
713 TREE_CHAIN (field) = fields;
714 fields = field;
715 value = tree_cons (field, convert (unsigned_intSI_type_node,
716 build_int_2 (local_tick, 0)),
717 value);
719 /* Filename */
720 string_type = build_pointer_type (build_qualified_type (char_type_node,
721 TYPE_QUAL_CONST));
722 field = build_decl (FIELD_DECL, NULL_TREE, string_type);
723 TREE_CHAIN (field) = fields;
724 fields = field;
725 filename = getpwd ();
726 filename = (filename && da_file_name[0] != '/'
727 ? concat (filename, "/", da_file_name, NULL)
728 : da_file_name);
729 filename_len = strlen (filename);
730 filename_string = build_string (filename_len + 1, filename);
731 if (filename != da_file_name)
732 free (filename);
733 TREE_TYPE (filename_string) =
734 build_array_type (char_type_node,
735 build_index_type (build_int_2 (filename_len, 0)));
736 value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
737 value);
739 /* Build the fn_info type and initializer. */
740 fn_info_type = build_fn_info_type (n_ctr_types);
741 fn_info_ptr_type = build_pointer_type (build_qualified_type
742 (fn_info_type, TYPE_QUAL_CONST));
743 for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
744 fn_info_value = tree_cons (NULL_TREE,
745 build_fn_info_value (fn, fn_info_type),
746 fn_info_value);
747 if (n_fns)
749 tree array_type;
751 array_type = build_index_type (build_int_2 (n_fns - 1, 0));
752 array_type = build_array_type (fn_info_type, array_type);
754 fn_info_value = build_constructor (array_type, nreverse (fn_info_value));
755 fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
757 else
758 fn_info_value = null_pointer_node;
760 /* number of functions */
761 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
762 TREE_CHAIN (field) = fields;
763 fields = field;
764 value = tree_cons (field,
765 convert (unsigned_type_node, build_int_2 (n_fns, 0)),
766 value);
768 /* fn_info table */
769 field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type);
770 TREE_CHAIN (field) = fields;
771 fields = field;
772 value = tree_cons (field, fn_info_value, value);
774 /* counter_mask */
775 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
776 TREE_CHAIN (field) = fields;
777 fields = field;
778 value = tree_cons (field,
779 convert (unsigned_type_node,
780 build_int_2 (prg_ctr_mask, 0)),
781 value);
783 /* counters */
784 ctr_info_type = build_ctr_info_type ();
785 ctr_info_ary_type = build_index_type (build_int_2 (n_ctr_types, 0));
786 ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
787 for (ix = 0; ix != GCOV_COUNTERS; ix++)
788 if (prg_ctr_mask & (1 << ix))
789 ctr_info_value = tree_cons (NULL_TREE,
790 build_ctr_info_value (ix, ctr_info_type),
791 ctr_info_value);
792 ctr_info_value = build_constructor (ctr_info_ary_type,
793 nreverse (ctr_info_value));
795 field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
796 TREE_CHAIN (field) = fields;
797 fields = field;
798 value = tree_cons (field, ctr_info_value, value);
800 finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
802 value = build_constructor (type, nreverse (value));
804 return value;
807 /* Write out the structure which libgcov uses to locate all the
808 counters. The structures used here must match those defined in
809 gcov-io.h. Write out the constructor to call __gcov_init. */
811 static void
812 create_coverage (void)
814 tree gcov_info, gcov_info_value;
815 char name[20];
816 char *ctor_name;
817 tree ctor;
818 rtx gcov_info_address;
820 no_coverage = 1; /* Disable any further coverage. */
822 if (!prg_ctr_mask)
823 return;
825 gcov_info_value = build_gcov_info ();
827 gcov_info = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (gcov_info_value));
828 DECL_INITIAL (gcov_info) = gcov_info_value;
830 TREE_STATIC (gcov_info) = 1;
831 ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 0);
832 DECL_NAME (gcov_info) = get_identifier (name);
834 /* Build structure. */
835 assemble_variable (gcov_info, 0, 0, 0);
837 /* Build the constructor function to invoke __gcov_init. */
838 ctor_name = concat (IDENTIFIER_POINTER (get_file_function_name ('I')),
839 "_GCOV", NULL);
840 ctor = build_decl (FUNCTION_DECL, get_identifier (ctor_name),
841 build_function_type (void_type_node, NULL_TREE));
842 free (ctor_name);
843 DECL_EXTERNAL (ctor) = 0;
845 /* It can be a static function as long as collect2 does not have
846 to scan the object file to find its ctor/dtor routine. */
847 TREE_PUBLIC (ctor) = ! targetm.have_ctors_dtors;
848 TREE_USED (ctor) = 1;
849 DECL_RESULT (ctor) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
850 DECL_UNINLINABLE (ctor) = 1;
852 ctor = (*lang_hooks.decls.pushdecl) (ctor);
853 rest_of_decl_compilation (ctor, 0, 1, 0);
854 announce_function (ctor);
855 current_function_decl = ctor;
856 make_decl_rtl (ctor, NULL);
857 init_function_start (ctor);
858 expand_function_start (ctor, 0);
859 /* Actually generate the code to call __gcov_init. */
860 gcov_info_address = force_reg (Pmode, XEXP (DECL_RTL (gcov_info), 0));
861 emit_library_call (gcov_init_libfunc, LCT_NORMAL, VOIDmode, 1,
862 gcov_info_address, Pmode);
864 expand_function_end ();
865 /* Create a dummy BLOCK. */
866 DECL_INITIAL (ctor) = make_node (BLOCK);
867 TREE_USED (DECL_INITIAL (ctor)) = 1;
869 rest_of_compilation (ctor);
871 if (! quiet_flag)
872 fflush (asm_out_file);
873 current_function_decl = NULL_TREE;
875 if (targetm.have_ctors_dtors)
876 (* targetm.asm_out.constructor) (XEXP (DECL_RTL (ctor), 0),
877 DEFAULT_INIT_PRIORITY);
880 /* Perform file-level initialization. Read in data file, generate name
881 of graph file. */
883 void
884 coverage_init (const char *filename)
886 int len = strlen (filename);
888 /* Name of da file. */
889 da_file_name = xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1);
890 strcpy (da_file_name, filename);
891 strcat (da_file_name, GCOV_DATA_SUFFIX);
893 /* Name of bbg file. */
894 bbg_file_name = xmalloc (len + strlen (GCOV_NOTE_SUFFIX) + 1);
895 strcpy (bbg_file_name, filename);
896 strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
898 read_counts_file ();
901 /* Performs file-level cleanup. Close graph file, generate coverage
902 variables and constructor. */
904 void
905 coverage_finish (void)
907 create_coverage ();
908 if (bbg_file_opened)
910 int error = gcov_close ();
912 if (error)
913 unlink (bbg_file_name);
914 if (!local_tick)
915 /* Only remove the da file, if we cannot stamp it. If we can
916 stamp it, libgcov will DTRT. */
917 unlink (da_file_name);
921 #include "gt-coverage.h"