Mark as release
[official-gcc.git] / gcc / coverage.c
blobd0c4cefb67f177ab378f32c8ea65f7f9445d9a87
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 0;
352 checksum = compute_checksum ();
353 if (entry->checksum != checksum)
355 error ("coverage mismatch for function %qs while reading counter %qs",
356 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
357 ctr_names[counter]);
358 error ("checksum is %x instead of %x", entry->checksum, checksum);
359 return 0;
361 else if (entry->summary.num != expected)
363 error ("coverage mismatch for function %qs while reading counter %qs",
364 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
365 ctr_names[counter]);
366 error ("number of counters is %d instead of %d", entry->summary.num, expected);
367 return 0;
370 if (summary)
371 *summary = &entry->summary;
373 return entry->counts;
376 /* Allocate NUM counters of type COUNTER. Returns nonzero if the
377 allocation succeeded. */
380 coverage_counter_alloc (unsigned counter, unsigned num)
382 if (no_coverage)
383 return 0;
385 if (!num)
386 return 1;
388 if (!tree_ctr_tables[counter])
390 /* Generate and save a copy of this so it can be shared. Leave
391 the index type unspecified for now; it will be set after all
392 functions have been compiled. */
393 char buf[20];
394 tree gcov_type_node = get_gcov_type ();
395 tree gcov_type_array_type
396 = build_array_type (gcov_type_node, NULL_TREE);
397 tree_ctr_tables[counter]
398 = build_decl (VAR_DECL, NULL_TREE, gcov_type_array_type);
399 TREE_STATIC (tree_ctr_tables[counter]) = 1;
400 ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
401 DECL_NAME (tree_ctr_tables[counter]) = get_identifier (buf);
402 DECL_ALIGN (tree_ctr_tables[counter]) = TYPE_ALIGN (gcov_type_node);
404 fn_b_ctrs[counter] = fn_n_ctrs[counter];
405 fn_n_ctrs[counter] += num;
406 fn_ctr_mask |= 1 << counter;
407 return 1;
410 /* Generate a tree to access COUNTER NO. */
412 tree
413 tree_coverage_counter_ref (unsigned counter, unsigned no)
415 tree gcov_type_node = get_gcov_type ();
417 gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
418 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
420 /* "no" here is an array index, scaled to bytes later. */
421 return build4 (ARRAY_REF, gcov_type_node, tree_ctr_tables[counter],
422 build_int_cst (NULL_TREE, no), NULL, NULL);
425 /* Generate a checksum for a string. CHKSUM is the current
426 checksum. */
428 static unsigned
429 coverage_checksum_string (unsigned chksum, const char *string)
431 int i;
432 char *dup = NULL;
434 /* Look for everything that looks if it were produced by
435 get_file_function_name_long and zero out the second part
436 that may result from flag_random_seed. This is not critical
437 as the checksums are used only for sanity checking. */
438 for (i = 0; string[i]; i++)
440 int offset = 0;
441 if (!strncmp (string + i, "_GLOBAL__N_", 11))
442 offset = 11;
443 if (!strncmp (string + i, "_GLOBAL__", 9))
444 offset = 9;
446 /* C++ namespaces do have scheme:
447 _GLOBAL__N_<filename>_<wrongmagicnumber>_<magicnumber>functionname
448 since filename might contain extra underscores there seems
449 to be no better chance then walk all possible offsets looking
450 for magicnuber. */
451 if (offset)
453 for (i = i + offset; string[i]; i++)
454 if (string[i]=='_')
456 int y;
458 for (y = 1; y < 9; y++)
459 if (!(string[i + y] >= '0' && string[i + y] <= '9')
460 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
461 break;
462 if (y != 9 || string[i + 9] != '_')
463 continue;
464 for (y = 10; y < 18; y++)
465 if (!(string[i + y] >= '0' && string[i + y] <= '9')
466 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
467 break;
468 if (y != 18)
469 continue;
470 if (!dup)
471 string = dup = xstrdup (string);
472 for (y = 10; y < 18; y++)
473 dup[i + y] = '0';
475 break;
479 chksum = crc32_string (chksum, string);
480 if (dup)
481 free (dup);
483 return chksum;
486 /* Compute checksum for the current function. We generate a CRC32. */
488 static unsigned
489 compute_checksum (void)
491 expanded_location xloc
492 = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
493 unsigned chksum = xloc.line;
495 chksum = coverage_checksum_string (chksum, xloc.file);
496 chksum = coverage_checksum_string
497 (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
499 return chksum;
502 /* Begin output to the graph file for the current function.
503 Opens the output file, if not already done. Writes the
504 function header, if not already done. Returns nonzero if data
505 should be output. */
508 coverage_begin_output (void)
510 if (no_coverage)
511 return 0;
513 if (!bbg_function_announced)
515 expanded_location xloc
516 = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
517 unsigned long offset;
519 if (!bbg_file_opened)
521 if (!gcov_open (bbg_file_name, -1))
522 error ("cannot open %s", bbg_file_name);
523 else
525 gcov_write_unsigned (GCOV_NOTE_MAGIC);
526 gcov_write_unsigned (GCOV_VERSION);
527 gcov_write_unsigned (local_tick);
529 bbg_file_opened = 1;
532 /* Announce function */
533 offset = gcov_write_tag (GCOV_TAG_FUNCTION);
534 gcov_write_unsigned (current_function_funcdef_no + 1);
535 gcov_write_unsigned (compute_checksum ());
536 gcov_write_string (IDENTIFIER_POINTER
537 (DECL_ASSEMBLER_NAME (current_function_decl)));
538 gcov_write_string (xloc.file);
539 gcov_write_unsigned (xloc.line);
540 gcov_write_length (offset);
542 bbg_function_announced = 1;
544 return !gcov_is_error ();
547 /* Finish coverage data for the current function. Verify no output
548 error has occurred. Save function coverage counts. */
550 void
551 coverage_end_function (void)
553 unsigned i;
555 if (bbg_file_opened > 1 && gcov_is_error ())
557 warning (0, "error writing %qs", bbg_file_name);
558 bbg_file_opened = -1;
561 if (fn_ctr_mask)
563 struct function_list *item;
565 item = XNEW (struct function_list);
567 *functions_tail = item;
568 functions_tail = &item->next;
570 item->next = 0;
571 item->ident = current_function_funcdef_no + 1;
572 item->checksum = compute_checksum ();
573 for (i = 0; i != GCOV_COUNTERS; i++)
575 item->n_ctrs[i] = fn_n_ctrs[i];
576 prg_n_ctrs[i] += fn_n_ctrs[i];
577 fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
579 prg_ctr_mask |= fn_ctr_mask;
580 fn_ctr_mask = 0;
582 bbg_function_announced = 0;
585 /* Creates the gcov_fn_info RECORD_TYPE. */
587 static tree
588 build_fn_info_type (unsigned int counters)
590 tree type = lang_hooks.types.make_type (RECORD_TYPE);
591 tree field, fields;
592 tree array_type;
594 /* ident */
595 fields = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
597 /* checksum */
598 field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
599 TREE_CHAIN (field) = fields;
600 fields = field;
602 array_type = build_int_cst (NULL_TREE, counters - 1);
603 array_type = build_index_type (array_type);
604 array_type = build_array_type (get_gcov_unsigned_t (), array_type);
606 /* counters */
607 field = build_decl (FIELD_DECL, NULL_TREE, array_type);
608 TREE_CHAIN (field) = fields;
609 fields = field;
611 finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
613 return type;
616 /* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
617 the function being processed and TYPE is the gcov_fn_info
618 RECORD_TYPE. */
620 static tree
621 build_fn_info_value (const struct function_list *function, tree type)
623 tree value = NULL_TREE;
624 tree fields = TYPE_FIELDS (type);
625 unsigned ix;
626 tree array_value = NULL_TREE;
628 /* ident */
629 value = tree_cons (fields, build_int_cstu (get_gcov_unsigned_t (),
630 function->ident), value);
631 fields = TREE_CHAIN (fields);
633 /* checksum */
634 value = tree_cons (fields, build_int_cstu (get_gcov_unsigned_t (),
635 function->checksum), value);
636 fields = TREE_CHAIN (fields);
638 /* counters */
639 for (ix = 0; ix != GCOV_COUNTERS; ix++)
640 if (prg_ctr_mask & (1 << ix))
642 tree counters = build_int_cstu (get_gcov_unsigned_t (),
643 function->n_ctrs[ix]);
645 array_value = tree_cons (NULL_TREE, counters, array_value);
648 /* FIXME: use build_constructor directly. */
649 array_value = build_constructor_from_list (TREE_TYPE (fields),
650 nreverse (array_value));
651 value = tree_cons (fields, array_value, value);
653 /* FIXME: use build_constructor directly. */
654 value = build_constructor_from_list (type, nreverse (value));
656 return value;
659 /* Creates the gcov_ctr_info RECORD_TYPE. */
661 static tree
662 build_ctr_info_type (void)
664 tree type = lang_hooks.types.make_type (RECORD_TYPE);
665 tree field, fields = NULL_TREE;
666 tree gcov_ptr_type = build_pointer_type (get_gcov_type ());
667 tree gcov_merge_fn_type;
669 /* counters */
670 field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
671 TREE_CHAIN (field) = fields;
672 fields = field;
674 /* values */
675 field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
676 TREE_CHAIN (field) = fields;
677 fields = field;
679 /* merge */
680 gcov_merge_fn_type =
681 build_function_type_list (void_type_node,
682 gcov_ptr_type, get_gcov_unsigned_t (),
683 NULL_TREE);
684 field = build_decl (FIELD_DECL, NULL_TREE,
685 build_pointer_type (gcov_merge_fn_type));
686 TREE_CHAIN (field) = fields;
687 fields = field;
689 finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
691 return type;
694 /* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
695 the counter being processed and TYPE is the gcov_ctr_info
696 RECORD_TYPE. */
698 static tree
699 build_ctr_info_value (unsigned int counter, tree type)
701 tree value = NULL_TREE;
702 tree fields = TYPE_FIELDS (type);
703 tree fn;
705 /* counters */
706 value = tree_cons (fields,
707 build_int_cstu (get_gcov_unsigned_t (),
708 prg_n_ctrs[counter]),
709 value);
710 fields = TREE_CHAIN (fields);
712 if (prg_n_ctrs[counter])
714 tree array_type;
716 array_type = build_int_cstu (get_gcov_unsigned_t (),
717 prg_n_ctrs[counter] - 1);
718 array_type = build_index_type (array_type);
719 array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
720 array_type);
722 TREE_TYPE (tree_ctr_tables[counter]) = array_type;
723 DECL_SIZE (tree_ctr_tables[counter]) = TYPE_SIZE (array_type);
724 DECL_SIZE_UNIT (tree_ctr_tables[counter]) = TYPE_SIZE_UNIT (array_type);
725 assemble_variable (tree_ctr_tables[counter], 0, 0, 0);
727 value = tree_cons (fields,
728 build1 (ADDR_EXPR, TREE_TYPE (fields),
729 tree_ctr_tables[counter]),
730 value);
732 else
733 value = tree_cons (fields, null_pointer_node, value);
734 fields = TREE_CHAIN (fields);
736 fn = build_decl (FUNCTION_DECL,
737 get_identifier (ctr_merge_functions[counter]),
738 TREE_TYPE (TREE_TYPE (fields)));
739 DECL_EXTERNAL (fn) = 1;
740 TREE_PUBLIC (fn) = 1;
741 DECL_ARTIFICIAL (fn) = 1;
742 TREE_NOTHROW (fn) = 1;
743 value = tree_cons (fields,
744 build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
745 value);
747 /* FIXME: use build_constructor directly. */
748 value = build_constructor_from_list (type, nreverse (value));
750 return value;
753 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
754 CONSTRUCTOR. */
756 static tree
757 build_gcov_info (void)
759 unsigned n_ctr_types, ix;
760 tree type, const_type;
761 tree fn_info_type, fn_info_value = NULL_TREE;
762 tree fn_info_ptr_type;
763 tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
764 tree field, fields = NULL_TREE;
765 tree value = NULL_TREE;
766 tree filename_string;
767 char *filename;
768 int filename_len;
769 unsigned n_fns;
770 const struct function_list *fn;
771 tree string_type;
773 /* Count the number of active counters. */
774 for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
775 if (prg_ctr_mask & (1 << ix))
776 n_ctr_types++;
778 type = lang_hooks.types.make_type (RECORD_TYPE);
779 const_type = build_qualified_type (type, TYPE_QUAL_CONST);
781 /* Version ident */
782 field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
783 TREE_CHAIN (field) = fields;
784 fields = field;
785 value = tree_cons (field, build_int_cstu (TREE_TYPE (field), GCOV_VERSION),
786 value);
788 /* next -- NULL */
789 field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
790 TREE_CHAIN (field) = fields;
791 fields = field;
792 value = tree_cons (field, null_pointer_node, value);
794 /* stamp */
795 field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
796 TREE_CHAIN (field) = fields;
797 fields = field;
798 value = tree_cons (field, build_int_cstu (TREE_TYPE (field), local_tick),
799 value);
801 /* Filename */
802 string_type = build_pointer_type (build_qualified_type (char_type_node,
803 TYPE_QUAL_CONST));
804 field = build_decl (FIELD_DECL, NULL_TREE, string_type);
805 TREE_CHAIN (field) = fields;
806 fields = field;
807 filename = getpwd ();
808 filename = (filename && da_file_name[0] != '/'
809 ? concat (filename, "/", da_file_name, NULL)
810 : da_file_name);
811 filename_len = strlen (filename);
812 filename_string = build_string (filename_len + 1, filename);
813 if (filename != da_file_name)
814 free (filename);
815 TREE_TYPE (filename_string) = build_array_type
816 (char_type_node, build_index_type
817 (build_int_cst (NULL_TREE, filename_len)));
818 value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
819 value);
821 /* Build the fn_info type and initializer. */
822 fn_info_type = build_fn_info_type (n_ctr_types);
823 fn_info_ptr_type = build_pointer_type (build_qualified_type
824 (fn_info_type, TYPE_QUAL_CONST));
825 for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
826 fn_info_value = tree_cons (NULL_TREE,
827 build_fn_info_value (fn, fn_info_type),
828 fn_info_value);
829 if (n_fns)
831 tree array_type;
833 array_type = build_index_type (build_int_cst (NULL_TREE, n_fns - 1));
834 array_type = build_array_type (fn_info_type, array_type);
836 /* FIXME: use build_constructor directly. */
837 fn_info_value = build_constructor_from_list (array_type,
838 nreverse (fn_info_value));
839 fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
841 else
842 fn_info_value = null_pointer_node;
844 /* number of functions */
845 field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
846 TREE_CHAIN (field) = fields;
847 fields = field;
848 value = tree_cons (field,
849 build_int_cstu (get_gcov_unsigned_t (), n_fns),
850 value);
852 /* fn_info table */
853 field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type);
854 TREE_CHAIN (field) = fields;
855 fields = field;
856 value = tree_cons (field, fn_info_value, value);
858 /* counter_mask */
859 field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
860 TREE_CHAIN (field) = fields;
861 fields = field;
862 value = tree_cons (field,
863 build_int_cstu (get_gcov_unsigned_t (), prg_ctr_mask),
864 value);
866 /* counters */
867 ctr_info_type = build_ctr_info_type ();
868 ctr_info_ary_type = build_index_type (build_int_cst (NULL_TREE,
869 n_ctr_types));
870 ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
871 for (ix = 0; ix != GCOV_COUNTERS; ix++)
872 if (prg_ctr_mask & (1 << ix))
873 ctr_info_value = tree_cons (NULL_TREE,
874 build_ctr_info_value (ix, ctr_info_type),
875 ctr_info_value);
876 /* FIXME: use build_constructor directly. */
877 ctr_info_value = build_constructor_from_list (ctr_info_ary_type,
878 nreverse (ctr_info_value));
880 field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
881 TREE_CHAIN (field) = fields;
882 fields = field;
883 value = tree_cons (field, ctr_info_value, value);
885 finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
887 /* FIXME: use build_constructor directly. */
888 value = build_constructor_from_list (type, nreverse (value));
890 return value;
893 /* Write out the structure which libgcov uses to locate all the
894 counters. The structures used here must match those defined in
895 gcov-io.h. Write out the constructor to call __gcov_init. */
897 static void
898 create_coverage (void)
900 tree gcov_info, gcov_init, body, t;
901 char name_buf[32];
903 no_coverage = 1; /* Disable any further coverage. */
905 if (!prg_ctr_mask)
906 return;
908 t = build_gcov_info ();
910 gcov_info = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (t));
911 TREE_STATIC (gcov_info) = 1;
912 ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
913 DECL_NAME (gcov_info) = get_identifier (name_buf);
914 DECL_INITIAL (gcov_info) = t;
916 /* Build structure. */
917 assemble_variable (gcov_info, 0, 0, 0);
919 /* Build a decl for __gcov_init. */
920 t = build_pointer_type (TREE_TYPE (gcov_info));
921 t = build_function_type_list (void_type_node, t, NULL);
922 t = build_decl (FUNCTION_DECL, get_identifier ("__gcov_init"), t);
923 TREE_PUBLIC (t) = 1;
924 DECL_EXTERNAL (t) = 1;
925 gcov_init = t;
927 /* Generate a call to __gcov_init(&gcov_info). */
928 body = NULL;
929 t = build_fold_addr_expr (gcov_info);
930 t = tree_cons (NULL, t, NULL);
931 t = build_function_call_expr (gcov_init, t);
932 append_to_statement_list (t, &body);
934 /* Generate a constructor to run it. */
935 cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
938 /* Perform file-level initialization. Read in data file, generate name
939 of graph file. */
941 void
942 coverage_init (const char *filename)
944 int len = strlen (filename);
946 /* Name of da file. */
947 da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX) + 1);
948 strcpy (da_file_name, filename);
949 strcat (da_file_name, GCOV_DATA_SUFFIX);
951 /* Name of bbg file. */
952 bbg_file_name = XNEWVEC (char, len + strlen (GCOV_NOTE_SUFFIX) + 1);
953 strcpy (bbg_file_name, filename);
954 strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
956 read_counts_file ();
959 /* Performs file-level cleanup. Close graph file, generate coverage
960 variables and constructor. */
962 void
963 coverage_finish (void)
965 create_coverage ();
966 if (bbg_file_opened)
968 int error = gcov_close ();
970 if (error)
971 unlink (bbg_file_name);
972 if (!local_tick)
973 /* Only remove the da file, if we cannot stamp it. If we can
974 stamp it, libgcov will DTRT. */
975 unlink (da_file_name);
979 #include "gt-coverage.h"