Daily bump.
[official-gcc.git] / gcc / coverage.c
blobcd1c13e2d5702a69d2564970c441ab5118950b1a
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, 2005, 2007 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 3, 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 COPYING3. If not see
23 <http://www.gnu.org/licenses/>. */
26 #define GCOV_LINKAGE
28 #include "config.h"
29 #include "system.h"
30 #include "coretypes.h"
31 #include "tm.h"
32 #include "rtl.h"
33 #include "tree.h"
34 #include "flags.h"
35 #include "output.h"
36 #include "regs.h"
37 #include "expr.h"
38 #include "function.h"
39 #include "toplev.h"
40 #include "ggc.h"
41 #include "coverage.h"
42 #include "langhooks.h"
43 #include "hashtab.h"
44 #include "tree-iterator.h"
45 #include "cgraph.h"
47 #include "gcov-io.c"
49 struct function_list
51 struct function_list *next; /* next function */
52 unsigned ident; /* function ident */
53 unsigned checksum; /* function checksum */
54 unsigned n_ctrs[GCOV_COUNTERS];/* number of counters. */
57 /* Counts information for a function. */
58 typedef struct counts_entry
60 /* We hash by */
61 unsigned ident;
62 unsigned ctr;
64 /* Store */
65 unsigned checksum;
66 gcov_type *counts;
67 struct gcov_ctr_summary summary;
69 /* Workspace */
70 struct counts_entry *chain;
72 } counts_entry_t;
74 static struct function_list *functions_head = 0;
75 static struct function_list **functions_tail = &functions_head;
76 static unsigned no_coverage = 0;
78 /* Cumulative counter information for whole program. */
79 static unsigned prg_ctr_mask; /* Mask of counter types generated. */
80 static unsigned prg_n_ctrs[GCOV_COUNTERS]; /* Total counters allocated. */
82 /* Counter information for current function. */
83 static unsigned fn_ctr_mask; /* Mask of counters used. */
84 static unsigned fn_n_ctrs[GCOV_COUNTERS]; /* Counters allocated. */
85 static unsigned fn_b_ctrs[GCOV_COUNTERS]; /* Allocation base. */
87 /* Name of the output file for coverage output file. */
88 static char *bbg_file_name;
89 static unsigned bbg_file_opened;
90 static int bbg_function_announced;
92 /* Name of the count data file. */
93 static char *da_file_name;
95 /* Hash table of count data. */
96 static htab_t counts_hash = NULL;
98 /* Trees representing the counter table arrays. */
99 static GTY(()) tree tree_ctr_tables[GCOV_COUNTERS];
101 /* The names of the counter tables. Not used if we're
102 generating counters at tree level. */
103 static GTY(()) rtx ctr_labels[GCOV_COUNTERS];
105 /* The names of merge functions for counters. */
106 static const char *const ctr_merge_functions[GCOV_COUNTERS] = GCOV_MERGE_FUNCTIONS;
107 static const char *const ctr_names[GCOV_COUNTERS] = GCOV_COUNTER_NAMES;
109 /* Forward declarations. */
110 static hashval_t htab_counts_entry_hash (const void *);
111 static int htab_counts_entry_eq (const void *, const void *);
112 static void htab_counts_entry_del (void *);
113 static void read_counts_file (void);
114 static unsigned compute_checksum (void);
115 static unsigned coverage_checksum_string (unsigned, const char *);
116 static tree build_fn_info_type (unsigned);
117 static tree build_fn_info_value (const struct function_list *, tree);
118 static tree build_ctr_info_type (void);
119 static tree build_ctr_info_value (unsigned, tree);
120 static tree build_gcov_info (void);
121 static void create_coverage (void);
123 /* Return the type node for gcov_type. */
125 tree
126 get_gcov_type (void)
128 return lang_hooks.types.type_for_size (GCOV_TYPE_SIZE, false);
131 /* Return the type node for gcov_unsigned_t. */
133 static tree
134 get_gcov_unsigned_t (void)
136 return lang_hooks.types.type_for_size (32, true);
139 static hashval_t
140 htab_counts_entry_hash (const void *of)
142 const counts_entry_t *entry = of;
144 return entry->ident * GCOV_COUNTERS + entry->ctr;
147 static int
148 htab_counts_entry_eq (const void *of1, const void *of2)
150 const counts_entry_t *entry1 = of1;
151 const counts_entry_t *entry2 = of2;
153 return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
156 static void
157 htab_counts_entry_del (void *of)
159 counts_entry_t *entry = of;
161 free (entry->counts);
162 free (entry);
165 /* Read in the counts file, if available. */
167 static void
168 read_counts_file (void)
170 gcov_unsigned_t fn_ident = 0;
171 gcov_unsigned_t checksum = -1;
172 counts_entry_t *summaried = NULL;
173 unsigned seen_summary = 0;
174 gcov_unsigned_t tag;
175 int is_error = 0;
177 if (!gcov_open (da_file_name, 1))
178 return;
180 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
182 warning (0, "%qs is not a gcov data file", da_file_name);
183 gcov_close ();
184 return;
186 else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
188 char v[4], e[4];
190 GCOV_UNSIGNED2STRING (v, tag);
191 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
193 warning (0, "%qs is version %q.*s, expected version %q.*s",
194 da_file_name, 4, v, 4, e);
195 gcov_close ();
196 return;
199 /* Read and discard the stamp. */
200 gcov_read_unsigned ();
202 counts_hash = htab_create (10,
203 htab_counts_entry_hash, htab_counts_entry_eq,
204 htab_counts_entry_del);
205 while ((tag = gcov_read_unsigned ()))
207 gcov_unsigned_t length;
208 gcov_position_t offset;
210 length = gcov_read_unsigned ();
211 offset = gcov_position ();
212 if (tag == GCOV_TAG_FUNCTION)
214 fn_ident = gcov_read_unsigned ();
215 checksum = gcov_read_unsigned ();
216 if (seen_summary)
218 /* We have already seen a summary, this means that this
219 new function begins a new set of program runs. We
220 must unlink the summaried chain. */
221 counts_entry_t *entry, *chain;
223 for (entry = summaried; entry; entry = chain)
225 chain = entry->chain;
226 entry->chain = NULL;
228 summaried = NULL;
229 seen_summary = 0;
232 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
234 counts_entry_t *entry;
235 struct gcov_summary summary;
237 gcov_read_summary (&summary);
238 seen_summary = 1;
239 for (entry = summaried; entry; entry = entry->chain)
241 struct gcov_ctr_summary *csum = &summary.ctrs[entry->ctr];
243 entry->summary.runs += csum->runs;
244 entry->summary.sum_all += csum->sum_all;
245 if (entry->summary.run_max < csum->run_max)
246 entry->summary.run_max = csum->run_max;
247 entry->summary.sum_max += csum->sum_max;
250 else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
252 counts_entry_t **slot, *entry, elt;
253 unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
254 unsigned ix;
256 elt.ident = fn_ident;
257 elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
259 slot = (counts_entry_t **) htab_find_slot
260 (counts_hash, &elt, INSERT);
261 entry = *slot;
262 if (!entry)
264 *slot = entry = XCNEW (counts_entry_t);
265 entry->ident = elt.ident;
266 entry->ctr = elt.ctr;
267 entry->checksum = checksum;
268 entry->summary.num = n_counts;
269 entry->counts = XCNEWVEC (gcov_type, n_counts);
271 else if (entry->checksum != checksum)
273 error ("coverage mismatch for function %u while reading execution counters",
274 fn_ident);
275 error ("checksum is %x instead of %x", entry->checksum, checksum);
276 htab_delete (counts_hash);
277 break;
279 else if (entry->summary.num != n_counts)
281 error ("coverage mismatch for function %u while reading execution counters",
282 fn_ident);
283 error ("number of counters is %d instead of %d", entry->summary.num, n_counts);
284 htab_delete (counts_hash);
285 break;
287 else if (elt.ctr >= GCOV_COUNTERS_SUMMABLE)
289 error ("cannot merge separate %s counters for function %u",
290 ctr_names[elt.ctr], fn_ident);
291 goto skip_merge;
294 if (elt.ctr < GCOV_COUNTERS_SUMMABLE
295 /* This should always be true for a just allocated entry,
296 and always false for an existing one. Check this way, in
297 case the gcov file is corrupt. */
298 && (!entry->chain || summaried != entry))
300 entry->chain = summaried;
301 summaried = entry;
303 for (ix = 0; ix != n_counts; ix++)
304 entry->counts[ix] += gcov_read_counter ();
305 skip_merge:;
307 gcov_sync (offset, length);
308 if ((is_error = gcov_is_error ()))
310 error (is_error < 0 ? "%qs has overflowed" : "%qs is corrupted",
311 da_file_name);
312 htab_delete (counts_hash);
313 break;
317 gcov_close ();
320 /* Returns the counters for a particular tag. */
322 gcov_type *
323 get_coverage_counts (unsigned counter, unsigned expected,
324 const struct gcov_ctr_summary **summary)
326 counts_entry_t *entry, elt;
327 gcov_unsigned_t checksum = -1;
329 /* No hash table, no counts. */
330 if (!counts_hash)
332 static int warned = 0;
334 if (!warned++)
335 inform ((flag_guess_branch_prob
336 ? "file %s not found, execution counts estimated"
337 : "file %s not found, execution counts assumed to be zero"),
338 da_file_name);
339 return NULL;
342 elt.ident = current_function_funcdef_no + 1;
343 elt.ctr = counter;
344 entry = htab_find (counts_hash, &elt);
345 if (!entry)
347 warning (0, "no coverage for function %qs found", IDENTIFIER_POINTER
348 (DECL_ASSEMBLER_NAME (current_function_decl)));
349 return NULL;
352 checksum = compute_checksum ();
353 if (entry->checksum != checksum
354 || entry->summary.num != expected)
356 static int warned = 0;
357 const char *id = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME
358 (current_function_decl));
360 if (warn_coverage_mismatch)
361 warning (OPT_Wcoverage_mismatch, "coverage mismatch for function "
362 "%qs while reading counter %qs", id, ctr_names[counter]);
363 else
364 error ("coverage mismatch for function %qs while reading counter %qs",
365 id, ctr_names[counter]);
367 if (!inhibit_warnings)
369 if (entry->checksum != checksum)
370 inform ("checksum is %x instead of %x", entry->checksum, checksum);
371 else
372 inform ("number of counters is %d instead of %d",
373 entry->summary.num, expected);
376 if (warn_coverage_mismatch
377 && !inhibit_warnings
378 && !warned++)
380 inform ("coverage mismatch ignored due to -Wcoverage-mismatch");
381 inform (flag_guess_branch_prob
382 ? "execution counts estimated"
383 : "execution counts assumed to be zero");
384 if (!flag_guess_branch_prob)
385 inform ("this can result in poorly optimized code");
388 return NULL;
391 if (summary)
392 *summary = &entry->summary;
394 return entry->counts;
397 /* Allocate NUM counters of type COUNTER. Returns nonzero if the
398 allocation succeeded. */
401 coverage_counter_alloc (unsigned counter, unsigned num)
403 if (no_coverage)
404 return 0;
406 if (!num)
407 return 1;
409 if (!tree_ctr_tables[counter])
411 /* Generate and save a copy of this so it can be shared. Leave
412 the index type unspecified for now; it will be set after all
413 functions have been compiled. */
414 char buf[20];
415 tree gcov_type_node = get_gcov_type ();
416 tree gcov_type_array_type
417 = build_array_type (gcov_type_node, NULL_TREE);
418 tree_ctr_tables[counter]
419 = build_decl (VAR_DECL, NULL_TREE, gcov_type_array_type);
420 TREE_STATIC (tree_ctr_tables[counter]) = 1;
421 ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
422 DECL_NAME (tree_ctr_tables[counter]) = get_identifier (buf);
423 DECL_ALIGN (tree_ctr_tables[counter]) = TYPE_ALIGN (gcov_type_node);
425 fn_b_ctrs[counter] = fn_n_ctrs[counter];
426 fn_n_ctrs[counter] += num;
427 fn_ctr_mask |= 1 << counter;
428 return 1;
431 /* Generate a tree to access COUNTER NO. */
433 tree
434 tree_coverage_counter_ref (unsigned counter, unsigned no)
436 tree gcov_type_node = get_gcov_type ();
438 gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
439 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
441 /* "no" here is an array index, scaled to bytes later. */
442 return build4 (ARRAY_REF, gcov_type_node, tree_ctr_tables[counter],
443 build_int_cst (NULL_TREE, no), NULL, NULL);
446 /* Generate a tree to access the address of COUNTER NO. */
448 tree
449 tree_coverage_counter_addr (unsigned counter, unsigned no)
451 tree gcov_type_node = get_gcov_type ();
453 gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
454 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
456 /* "no" here is an array index, scaled to bytes later. */
457 return build_fold_addr_expr (build4 (ARRAY_REF, gcov_type_node,
458 tree_ctr_tables[counter],
459 build_int_cst (NULL_TREE, no),
460 NULL, NULL));
463 /* Generate a checksum for a string. CHKSUM is the current
464 checksum. */
466 static unsigned
467 coverage_checksum_string (unsigned chksum, const char *string)
469 int i;
470 char *dup = NULL;
472 /* Look for everything that looks if it were produced by
473 get_file_function_name and zero out the second part
474 that may result from flag_random_seed. This is not critical
475 as the checksums are used only for sanity checking. */
476 for (i = 0; string[i]; i++)
478 int offset = 0;
479 if (!strncmp (string + i, "_GLOBAL__N_", 11))
480 offset = 11;
481 if (!strncmp (string + i, "_GLOBAL__", 9))
482 offset = 9;
484 /* C++ namespaces do have scheme:
485 _GLOBAL__N_<filename>_<wrongmagicnumber>_<magicnumber>functionname
486 since filename might contain extra underscores there seems
487 to be no better chance then walk all possible offsets looking
488 for magicnuber. */
489 if (offset)
491 for (i = i + offset; string[i]; i++)
492 if (string[i]=='_')
494 int y;
496 for (y = 1; y < 9; y++)
497 if (!(string[i + y] >= '0' && string[i + y] <= '9')
498 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
499 break;
500 if (y != 9 || string[i + 9] != '_')
501 continue;
502 for (y = 10; y < 18; y++)
503 if (!(string[i + y] >= '0' && string[i + y] <= '9')
504 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
505 break;
506 if (y != 18)
507 continue;
508 if (!dup)
509 string = dup = xstrdup (string);
510 for (y = 10; y < 18; y++)
511 dup[i + y] = '0';
513 break;
517 chksum = crc32_string (chksum, string);
518 if (dup)
519 free (dup);
521 return chksum;
524 /* Compute checksum for the current function. We generate a CRC32. */
526 static unsigned
527 compute_checksum (void)
529 expanded_location xloc
530 = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
531 unsigned chksum = xloc.line;
533 chksum = coverage_checksum_string (chksum, xloc.file);
534 chksum = coverage_checksum_string
535 (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
537 return chksum;
540 /* Begin output to the graph file for the current function.
541 Opens the output file, if not already done. Writes the
542 function header, if not already done. Returns nonzero if data
543 should be output. */
546 coverage_begin_output (void)
548 /* We don't need to output .gcno file unless we're under -ftest-coverage
549 (e.g. -fprofile-arcs/generate/use don't need .gcno to work). */
550 if (no_coverage || !flag_test_coverage)
551 return 0;
553 if (!bbg_function_announced)
555 expanded_location xloc
556 = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
557 unsigned long offset;
559 if (!bbg_file_opened)
561 if (!gcov_open (bbg_file_name, -1))
562 error ("cannot open %s", bbg_file_name);
563 else
565 gcov_write_unsigned (GCOV_NOTE_MAGIC);
566 gcov_write_unsigned (GCOV_VERSION);
567 gcov_write_unsigned (local_tick);
569 bbg_file_opened = 1;
572 /* Announce function */
573 offset = gcov_write_tag (GCOV_TAG_FUNCTION);
574 gcov_write_unsigned (current_function_funcdef_no + 1);
575 gcov_write_unsigned (compute_checksum ());
576 gcov_write_string (IDENTIFIER_POINTER
577 (DECL_ASSEMBLER_NAME (current_function_decl)));
578 gcov_write_string (xloc.file);
579 gcov_write_unsigned (xloc.line);
580 gcov_write_length (offset);
582 bbg_function_announced = 1;
584 return !gcov_is_error ();
587 /* Finish coverage data for the current function. Verify no output
588 error has occurred. Save function coverage counts. */
590 void
591 coverage_end_function (void)
593 unsigned i;
595 if (bbg_file_opened > 1 && gcov_is_error ())
597 warning (0, "error writing %qs", bbg_file_name);
598 bbg_file_opened = -1;
601 if (fn_ctr_mask)
603 struct function_list *item;
605 item = XNEW (struct function_list);
607 *functions_tail = item;
608 functions_tail = &item->next;
610 item->next = 0;
611 item->ident = current_function_funcdef_no + 1;
612 item->checksum = compute_checksum ();
613 for (i = 0; i != GCOV_COUNTERS; i++)
615 item->n_ctrs[i] = fn_n_ctrs[i];
616 prg_n_ctrs[i] += fn_n_ctrs[i];
617 fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
619 prg_ctr_mask |= fn_ctr_mask;
620 fn_ctr_mask = 0;
622 bbg_function_announced = 0;
625 /* Creates the gcov_fn_info RECORD_TYPE. */
627 static tree
628 build_fn_info_type (unsigned int counters)
630 tree type = lang_hooks.types.make_type (RECORD_TYPE);
631 tree field, fields;
632 tree array_type;
634 /* ident */
635 fields = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
637 /* checksum */
638 field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
639 TREE_CHAIN (field) = fields;
640 fields = field;
642 array_type = build_int_cst (NULL_TREE, counters - 1);
643 array_type = build_index_type (array_type);
644 array_type = build_array_type (get_gcov_unsigned_t (), array_type);
646 /* counters */
647 field = build_decl (FIELD_DECL, NULL_TREE, array_type);
648 TREE_CHAIN (field) = fields;
649 fields = field;
651 finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
653 return type;
656 /* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
657 the function being processed and TYPE is the gcov_fn_info
658 RECORD_TYPE. */
660 static tree
661 build_fn_info_value (const struct function_list *function, tree type)
663 tree value = NULL_TREE;
664 tree fields = TYPE_FIELDS (type);
665 unsigned ix;
666 tree array_value = NULL_TREE;
668 /* ident */
669 value = tree_cons (fields, build_int_cstu (get_gcov_unsigned_t (),
670 function->ident), value);
671 fields = TREE_CHAIN (fields);
673 /* checksum */
674 value = tree_cons (fields, build_int_cstu (get_gcov_unsigned_t (),
675 function->checksum), value);
676 fields = TREE_CHAIN (fields);
678 /* counters */
679 for (ix = 0; ix != GCOV_COUNTERS; ix++)
680 if (prg_ctr_mask & (1 << ix))
682 tree counters = build_int_cstu (get_gcov_unsigned_t (),
683 function->n_ctrs[ix]);
685 array_value = tree_cons (NULL_TREE, counters, array_value);
688 /* FIXME: use build_constructor directly. */
689 array_value = build_constructor_from_list (TREE_TYPE (fields),
690 nreverse (array_value));
691 value = tree_cons (fields, array_value, value);
693 /* FIXME: use build_constructor directly. */
694 value = build_constructor_from_list (type, nreverse (value));
696 return value;
699 /* Creates the gcov_ctr_info RECORD_TYPE. */
701 static tree
702 build_ctr_info_type (void)
704 tree type = lang_hooks.types.make_type (RECORD_TYPE);
705 tree field, fields = NULL_TREE;
706 tree gcov_ptr_type = build_pointer_type (get_gcov_type ());
707 tree gcov_merge_fn_type;
709 /* counters */
710 field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
711 TREE_CHAIN (field) = fields;
712 fields = field;
714 /* values */
715 field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
716 TREE_CHAIN (field) = fields;
717 fields = field;
719 /* merge */
720 gcov_merge_fn_type =
721 build_function_type_list (void_type_node,
722 gcov_ptr_type, get_gcov_unsigned_t (),
723 NULL_TREE);
724 field = build_decl (FIELD_DECL, NULL_TREE,
725 build_pointer_type (gcov_merge_fn_type));
726 TREE_CHAIN (field) = fields;
727 fields = field;
729 finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
731 return type;
734 /* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
735 the counter being processed and TYPE is the gcov_ctr_info
736 RECORD_TYPE. */
738 static tree
739 build_ctr_info_value (unsigned int counter, tree type)
741 tree value = NULL_TREE;
742 tree fields = TYPE_FIELDS (type);
743 tree fn;
745 /* counters */
746 value = tree_cons (fields,
747 build_int_cstu (get_gcov_unsigned_t (),
748 prg_n_ctrs[counter]),
749 value);
750 fields = TREE_CHAIN (fields);
752 if (prg_n_ctrs[counter])
754 tree array_type;
756 array_type = build_int_cstu (get_gcov_unsigned_t (),
757 prg_n_ctrs[counter] - 1);
758 array_type = build_index_type (array_type);
759 array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
760 array_type);
762 TREE_TYPE (tree_ctr_tables[counter]) = array_type;
763 DECL_SIZE (tree_ctr_tables[counter]) = TYPE_SIZE (array_type);
764 DECL_SIZE_UNIT (tree_ctr_tables[counter]) = TYPE_SIZE_UNIT (array_type);
765 assemble_variable (tree_ctr_tables[counter], 0, 0, 0);
767 value = tree_cons (fields,
768 build1 (ADDR_EXPR, TREE_TYPE (fields),
769 tree_ctr_tables[counter]),
770 value);
772 else
773 value = tree_cons (fields, null_pointer_node, value);
774 fields = TREE_CHAIN (fields);
776 fn = build_decl (FUNCTION_DECL,
777 get_identifier (ctr_merge_functions[counter]),
778 TREE_TYPE (TREE_TYPE (fields)));
779 DECL_EXTERNAL (fn) = 1;
780 TREE_PUBLIC (fn) = 1;
781 DECL_ARTIFICIAL (fn) = 1;
782 TREE_NOTHROW (fn) = 1;
783 value = tree_cons (fields,
784 build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
785 value);
787 /* FIXME: use build_constructor directly. */
788 value = build_constructor_from_list (type, nreverse (value));
790 return value;
793 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
794 CONSTRUCTOR. */
796 static tree
797 build_gcov_info (void)
799 unsigned n_ctr_types, ix;
800 tree type, const_type;
801 tree fn_info_type, fn_info_value = NULL_TREE;
802 tree fn_info_ptr_type;
803 tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
804 tree field, fields = NULL_TREE;
805 tree value = NULL_TREE;
806 tree filename_string;
807 int da_file_name_len;
808 unsigned n_fns;
809 const struct function_list *fn;
810 tree string_type;
812 /* Count the number of active counters. */
813 for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
814 if (prg_ctr_mask & (1 << ix))
815 n_ctr_types++;
817 type = lang_hooks.types.make_type (RECORD_TYPE);
818 const_type = build_qualified_type (type, TYPE_QUAL_CONST);
820 /* Version ident */
821 field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
822 TREE_CHAIN (field) = fields;
823 fields = field;
824 value = tree_cons (field, build_int_cstu (TREE_TYPE (field), GCOV_VERSION),
825 value);
827 /* next -- NULL */
828 field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
829 TREE_CHAIN (field) = fields;
830 fields = field;
831 value = tree_cons (field, null_pointer_node, value);
833 /* stamp */
834 field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
835 TREE_CHAIN (field) = fields;
836 fields = field;
837 value = tree_cons (field, build_int_cstu (TREE_TYPE (field), local_tick),
838 value);
840 /* Filename */
841 string_type = build_pointer_type (build_qualified_type (char_type_node,
842 TYPE_QUAL_CONST));
843 field = build_decl (FIELD_DECL, NULL_TREE, string_type);
844 TREE_CHAIN (field) = fields;
845 fields = field;
846 da_file_name_len = strlen (da_file_name);
847 filename_string = build_string (da_file_name_len + 1, da_file_name);
848 TREE_TYPE (filename_string) = build_array_type
849 (char_type_node, build_index_type
850 (build_int_cst (NULL_TREE, da_file_name_len)));
851 value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
852 value);
854 /* Build the fn_info type and initializer. */
855 fn_info_type = build_fn_info_type (n_ctr_types);
856 fn_info_ptr_type = build_pointer_type (build_qualified_type
857 (fn_info_type, TYPE_QUAL_CONST));
858 for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
859 fn_info_value = tree_cons (NULL_TREE,
860 build_fn_info_value (fn, fn_info_type),
861 fn_info_value);
862 if (n_fns)
864 tree array_type;
866 array_type = build_index_type (build_int_cst (NULL_TREE, n_fns - 1));
867 array_type = build_array_type (fn_info_type, array_type);
869 /* FIXME: use build_constructor directly. */
870 fn_info_value = build_constructor_from_list (array_type,
871 nreverse (fn_info_value));
872 fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
874 else
875 fn_info_value = null_pointer_node;
877 /* number of functions */
878 field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
879 TREE_CHAIN (field) = fields;
880 fields = field;
881 value = tree_cons (field,
882 build_int_cstu (get_gcov_unsigned_t (), n_fns),
883 value);
885 /* fn_info table */
886 field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type);
887 TREE_CHAIN (field) = fields;
888 fields = field;
889 value = tree_cons (field, fn_info_value, value);
891 /* counter_mask */
892 field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
893 TREE_CHAIN (field) = fields;
894 fields = field;
895 value = tree_cons (field,
896 build_int_cstu (get_gcov_unsigned_t (), prg_ctr_mask),
897 value);
899 /* counters */
900 ctr_info_type = build_ctr_info_type ();
901 ctr_info_ary_type = build_index_type (build_int_cst (NULL_TREE,
902 n_ctr_types));
903 ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
904 for (ix = 0; ix != GCOV_COUNTERS; ix++)
905 if (prg_ctr_mask & (1 << ix))
906 ctr_info_value = tree_cons (NULL_TREE,
907 build_ctr_info_value (ix, ctr_info_type),
908 ctr_info_value);
909 /* FIXME: use build_constructor directly. */
910 ctr_info_value = build_constructor_from_list (ctr_info_ary_type,
911 nreverse (ctr_info_value));
913 field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
914 TREE_CHAIN (field) = fields;
915 fields = field;
916 value = tree_cons (field, ctr_info_value, value);
918 finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
920 /* FIXME: use build_constructor directly. */
921 value = build_constructor_from_list (type, nreverse (value));
923 return value;
926 /* Write out the structure which libgcov uses to locate all the
927 counters. The structures used here must match those defined in
928 gcov-io.h. Write out the constructor to call __gcov_init. */
930 static void
931 create_coverage (void)
933 tree gcov_info, gcov_init, body, t;
934 char name_buf[32];
936 no_coverage = 1; /* Disable any further coverage. */
938 if (!prg_ctr_mask)
939 return;
941 t = build_gcov_info ();
943 gcov_info = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (t));
944 TREE_STATIC (gcov_info) = 1;
945 ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
946 DECL_NAME (gcov_info) = get_identifier (name_buf);
947 DECL_INITIAL (gcov_info) = t;
949 /* Build structure. */
950 assemble_variable (gcov_info, 0, 0, 0);
952 /* Build a decl for __gcov_init. */
953 t = build_pointer_type (TREE_TYPE (gcov_info));
954 t = build_function_type_list (void_type_node, t, NULL);
955 t = build_decl (FUNCTION_DECL, get_identifier ("__gcov_init"), t);
956 TREE_PUBLIC (t) = 1;
957 DECL_EXTERNAL (t) = 1;
958 gcov_init = t;
960 /* Generate a call to __gcov_init(&gcov_info). */
961 body = NULL;
962 t = build_fold_addr_expr (gcov_info);
963 t = build_call_expr (gcov_init, 1, t);
964 append_to_statement_list (t, &body);
966 /* Generate a constructor to run it. */
967 cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
970 /* Perform file-level initialization. Read in data file, generate name
971 of graph file. */
973 void
974 coverage_init (const char *filename)
976 int len = strlen (filename);
977 /* + 1 for extra '/', in case prefix doesn't end with /. */
978 int prefix_len;
980 if (profile_data_prefix == 0 && filename[0] != '/')
981 profile_data_prefix = getpwd ();
983 prefix_len = (profile_data_prefix) ? strlen (profile_data_prefix) + 1 : 0;
985 /* Name of da file. */
986 da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX)
987 + prefix_len + 1);
989 if (profile_data_prefix)
991 strcpy (da_file_name, profile_data_prefix);
992 da_file_name[prefix_len - 1] = '/';
993 da_file_name[prefix_len] = 0;
995 else
996 da_file_name[0] = 0;
997 strcat (da_file_name, filename);
998 strcat (da_file_name, GCOV_DATA_SUFFIX);
1000 /* Name of bbg file. */
1001 bbg_file_name = XNEWVEC (char, len + strlen (GCOV_NOTE_SUFFIX) + 1);
1002 strcpy (bbg_file_name, filename);
1003 strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
1005 if (flag_profile_use)
1006 read_counts_file ();
1009 /* Performs file-level cleanup. Close graph file, generate coverage
1010 variables and constructor. */
1012 void
1013 coverage_finish (void)
1015 create_coverage ();
1016 if (bbg_file_opened)
1018 int error = gcov_close ();
1020 if (error)
1021 unlink (bbg_file_name);
1022 if (!local_tick)
1023 /* Only remove the da file, if we cannot stamp it. If we can
1024 stamp it, libgcov will DTRT. */
1025 unlink (da_file_name);
1029 #include "gt-coverage.h"