gcc/
[official-gcc.git] / gcc / coverage.c
blob9b8a6900e6bb762f7acd6f23442fc34e0a623545
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, 2008, 2009, 2010
4 Free Software Foundation, Inc.
5 Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
6 based on some ideas from Dain Samples of UC Berkeley.
7 Further mangling by Bob Manson, Cygnus Support.
8 Further mangled by Nathan Sidwell, CodeSourcery
10 This file is part of GCC.
12 GCC is free software; you can redistribute it and/or modify it under
13 the terms of the GNU General Public License as published by the Free
14 Software Foundation; either version 3, or (at your option) any later
15 version.
17 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
18 WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 for more details.
22 You should have received a copy of the GNU General Public License
23 along with GCC; see the file COPYING3. If not see
24 <http://www.gnu.org/licenses/>. */
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 "basic-block.h"
41 #include "toplev.h"
42 #include "tm_p.h"
43 #include "ggc.h"
44 #include "coverage.h"
45 #include "langhooks.h"
46 #include "hashtab.h"
47 #include "tree-iterator.h"
48 #include "cgraph.h"
49 #include "tree-pass.h"
50 #include "diagnostic-core.h"
51 #include "intl.h"
53 #include "gcov-io.c"
55 struct function_list
57 struct function_list *next; /* next function */
58 unsigned ident; /* function ident */
59 unsigned checksum; /* function checksum */
60 unsigned n_ctrs[GCOV_COUNTERS];/* number of counters. */
63 /* Counts information for a function. */
64 typedef struct counts_entry
66 /* We hash by */
67 unsigned ident;
68 unsigned ctr;
70 /* Store */
71 unsigned checksum;
72 gcov_type *counts;
73 struct gcov_ctr_summary summary;
75 /* Workspace */
76 struct counts_entry *chain;
78 } counts_entry_t;
80 static struct function_list *functions_head = 0;
81 static struct function_list **functions_tail = &functions_head;
82 static unsigned no_coverage = 0;
84 /* Cumulative counter information for whole program. */
85 static unsigned prg_ctr_mask; /* Mask of counter types generated. */
86 static unsigned prg_n_ctrs[GCOV_COUNTERS]; /* Total counters allocated. */
88 /* Counter information for current function. */
89 static unsigned fn_ctr_mask; /* Mask of counters used. */
90 static unsigned fn_n_ctrs[GCOV_COUNTERS]; /* Counters allocated. */
91 static unsigned fn_b_ctrs[GCOV_COUNTERS]; /* Allocation base. */
93 /* Name of the output file for coverage output file. */
94 static char *bbg_file_name;
95 static unsigned bbg_file_opened;
96 static int bbg_function_announced;
98 /* Name of the count data file. */
99 static char *da_file_name;
101 /* Hash table of count data. */
102 static htab_t counts_hash = NULL;
104 /* Trees representing the counter table arrays. */
105 static GTY(()) tree tree_ctr_tables[GCOV_COUNTERS];
107 /* The names of the counter tables. Not used if we're
108 generating counters at tree level. */
109 static GTY(()) rtx ctr_labels[GCOV_COUNTERS];
111 /* The names of merge functions for counters. */
112 static const char *const ctr_merge_functions[GCOV_COUNTERS] = GCOV_MERGE_FUNCTIONS;
113 static const char *const ctr_names[GCOV_COUNTERS] = GCOV_COUNTER_NAMES;
115 /* Forward declarations. */
116 static hashval_t htab_counts_entry_hash (const void *);
117 static int htab_counts_entry_eq (const void *, const void *);
118 static void htab_counts_entry_del (void *);
119 static void read_counts_file (void);
120 static unsigned compute_checksum (void);
121 static unsigned coverage_checksum_string (unsigned, const char *);
122 static tree build_fn_info_type (unsigned);
123 static tree build_fn_info_value (const struct function_list *, tree);
124 static tree build_ctr_info_type (void);
125 static tree build_ctr_info_value (unsigned, tree);
126 static tree build_gcov_info (void);
127 static void create_coverage (void);
129 /* Return the type node for gcov_type. */
131 tree
132 get_gcov_type (void)
134 return lang_hooks.types.type_for_size (GCOV_TYPE_SIZE, false);
137 /* Return the type node for gcov_unsigned_t. */
139 static tree
140 get_gcov_unsigned_t (void)
142 return lang_hooks.types.type_for_size (32, true);
145 static hashval_t
146 htab_counts_entry_hash (const void *of)
148 const counts_entry_t *const entry = (const counts_entry_t *) of;
150 return entry->ident * GCOV_COUNTERS + entry->ctr;
153 static int
154 htab_counts_entry_eq (const void *of1, const void *of2)
156 const counts_entry_t *const entry1 = (const counts_entry_t *) of1;
157 const counts_entry_t *const entry2 = (const counts_entry_t *) of2;
159 return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
162 static void
163 htab_counts_entry_del (void *of)
165 counts_entry_t *const entry = (counts_entry_t *) of;
167 free (entry->counts);
168 free (entry);
171 /* Read in the counts file, if available. */
173 static void
174 read_counts_file (void)
176 gcov_unsigned_t fn_ident = 0;
177 gcov_unsigned_t checksum = -1;
178 counts_entry_t *summaried = NULL;
179 unsigned seen_summary = 0;
180 gcov_unsigned_t tag;
181 int is_error = 0;
183 if (!gcov_open (da_file_name, 1))
184 return;
186 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
188 warning (0, "%qs is not a gcov data file", da_file_name);
189 gcov_close ();
190 return;
192 else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
194 char v[4], e[4];
196 GCOV_UNSIGNED2STRING (v, tag);
197 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
199 warning (0, "%qs is version %q.*s, expected version %q.*s",
200 da_file_name, 4, v, 4, e);
201 gcov_close ();
202 return;
205 /* Read and discard the stamp. */
206 gcov_read_unsigned ();
208 counts_hash = htab_create (10,
209 htab_counts_entry_hash, htab_counts_entry_eq,
210 htab_counts_entry_del);
211 while ((tag = gcov_read_unsigned ()))
213 gcov_unsigned_t length;
214 gcov_position_t offset;
216 length = gcov_read_unsigned ();
217 offset = gcov_position ();
218 if (tag == GCOV_TAG_FUNCTION)
220 fn_ident = gcov_read_unsigned ();
221 checksum = gcov_read_unsigned ();
222 if (seen_summary)
224 /* We have already seen a summary, this means that this
225 new function begins a new set of program runs. We
226 must unlink the summaried chain. */
227 counts_entry_t *entry, *chain;
229 for (entry = summaried; entry; entry = chain)
231 chain = entry->chain;
232 entry->chain = NULL;
234 summaried = NULL;
235 seen_summary = 0;
238 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
240 counts_entry_t *entry;
241 struct gcov_summary summary;
243 gcov_read_summary (&summary);
244 seen_summary = 1;
245 for (entry = summaried; entry; entry = entry->chain)
247 struct gcov_ctr_summary *csum = &summary.ctrs[entry->ctr];
249 entry->summary.runs += csum->runs;
250 entry->summary.sum_all += csum->sum_all;
251 if (entry->summary.run_max < csum->run_max)
252 entry->summary.run_max = csum->run_max;
253 entry->summary.sum_max += csum->sum_max;
256 else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
258 counts_entry_t **slot, *entry, elt;
259 unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
260 unsigned ix;
262 elt.ident = fn_ident;
263 elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
265 slot = (counts_entry_t **) htab_find_slot
266 (counts_hash, &elt, INSERT);
267 entry = *slot;
268 if (!entry)
270 *slot = entry = XCNEW (counts_entry_t);
271 entry->ident = elt.ident;
272 entry->ctr = elt.ctr;
273 entry->checksum = checksum;
274 entry->summary.num = n_counts;
275 entry->counts = XCNEWVEC (gcov_type, n_counts);
277 else if (entry->checksum != checksum)
279 error ("coverage mismatch for function %u while reading execution counters",
280 fn_ident);
281 error ("checksum is %x instead of %x", entry->checksum, checksum);
282 htab_delete (counts_hash);
283 break;
285 else if (entry->summary.num != n_counts)
287 error ("coverage mismatch for function %u while reading execution counters",
288 fn_ident);
289 error ("number of counters is %d instead of %d", entry->summary.num, n_counts);
290 htab_delete (counts_hash);
291 break;
293 else if (elt.ctr >= GCOV_COUNTERS_SUMMABLE)
295 error ("cannot merge separate %s counters for function %u",
296 ctr_names[elt.ctr], fn_ident);
297 goto skip_merge;
300 if (elt.ctr < GCOV_COUNTERS_SUMMABLE
301 /* This should always be true for a just allocated entry,
302 and always false for an existing one. Check this way, in
303 case the gcov file is corrupt. */
304 && (!entry->chain || summaried != entry))
306 entry->chain = summaried;
307 summaried = entry;
309 for (ix = 0; ix != n_counts; ix++)
310 entry->counts[ix] += gcov_read_counter ();
311 skip_merge:;
313 gcov_sync (offset, length);
314 if ((is_error = gcov_is_error ()))
316 error (is_error < 0 ? "%qs has overflowed" : "%qs is corrupted",
317 da_file_name);
318 htab_delete (counts_hash);
319 break;
323 gcov_close ();
326 /* Returns the counters for a particular tag. */
328 gcov_type *
329 get_coverage_counts (unsigned counter, unsigned expected,
330 const struct gcov_ctr_summary **summary)
332 counts_entry_t *entry, elt;
333 gcov_unsigned_t checksum = -1;
335 /* No hash table, no counts. */
336 if (!counts_hash)
338 static int warned = 0;
340 if (!warned++)
341 inform (input_location, (flag_guess_branch_prob
342 ? "file %s not found, execution counts estimated"
343 : "file %s not found, execution counts assumed to be zero"),
344 da_file_name);
345 return NULL;
348 elt.ident = current_function_funcdef_no + 1;
349 elt.ctr = counter;
350 entry = (counts_entry_t *) htab_find (counts_hash, &elt);
351 if (!entry)
353 warning (0, "no coverage for function %qE found",
354 DECL_ASSEMBLER_NAME (current_function_decl));
355 return NULL;
358 checksum = compute_checksum ();
359 if (entry->checksum != checksum
360 || entry->summary.num != expected)
362 static int warned = 0;
363 bool warning_printed = false;
364 tree id = DECL_ASSEMBLER_NAME (current_function_decl);
366 warning_printed =
367 warning_at (input_location, OPT_Wcoverage_mismatch,
368 "coverage mismatch for function "
369 "%qE while reading counter %qs", id, ctr_names[counter]);
370 if (warning_printed)
372 if (entry->checksum != checksum)
373 inform (input_location, "checksum is %x instead of %x",
374 entry->checksum, checksum);
375 else
376 inform (input_location, "number of counters is %d instead of %d",
377 entry->summary.num, expected);
379 if (!seen_error ()
380 && !warned++)
382 inform (input_location, "coverage mismatch ignored");
383 inform (input_location, flag_guess_branch_prob
384 ? G_("execution counts estimated")
385 : G_("execution counts assumed to be zero"));
386 if (!flag_guess_branch_prob)
387 inform (input_location,
388 "this can result in poorly optimized code");
392 return NULL;
395 if (summary)
396 *summary = &entry->summary;
398 return entry->counts;
401 /* Allocate NUM counters of type COUNTER. Returns nonzero if the
402 allocation succeeded. */
405 coverage_counter_alloc (unsigned counter, unsigned num)
407 if (no_coverage)
408 return 0;
410 if (!num)
411 return 1;
413 if (!tree_ctr_tables[counter])
415 /* Generate and save a copy of this so it can be shared. Leave
416 the index type unspecified for now; it will be set after all
417 functions have been compiled. */
418 char buf[20];
419 tree gcov_type_node = get_gcov_type ();
420 tree gcov_type_array_type
421 = build_array_type (gcov_type_node, NULL_TREE);
422 tree_ctr_tables[counter]
423 = build_decl (BUILTINS_LOCATION,
424 VAR_DECL, NULL_TREE, gcov_type_array_type);
425 TREE_STATIC (tree_ctr_tables[counter]) = 1;
426 ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
427 DECL_NAME (tree_ctr_tables[counter]) = get_identifier (buf);
428 DECL_ALIGN (tree_ctr_tables[counter]) = TYPE_ALIGN (gcov_type_node);
430 if (dump_file)
431 fprintf (dump_file, "Using data file %s\n", da_file_name);
433 fn_b_ctrs[counter] = fn_n_ctrs[counter];
434 fn_n_ctrs[counter] += num;
435 fn_ctr_mask |= 1 << counter;
436 return 1;
439 /* Generate a tree to access COUNTER NO. */
441 tree
442 tree_coverage_counter_ref (unsigned counter, unsigned no)
444 tree gcov_type_node = get_gcov_type ();
446 gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
447 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
449 /* "no" here is an array index, scaled to bytes later. */
450 return build4 (ARRAY_REF, gcov_type_node, tree_ctr_tables[counter],
451 build_int_cst (NULL_TREE, no), NULL, NULL);
454 /* Generate a tree to access the address of COUNTER NO. */
456 tree
457 tree_coverage_counter_addr (unsigned counter, unsigned no)
459 tree gcov_type_node = get_gcov_type ();
461 gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
462 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
464 TREE_ADDRESSABLE (tree_ctr_tables[counter]) = 1;
466 /* "no" here is an array index, scaled to bytes later. */
467 return build_fold_addr_expr (build4 (ARRAY_REF, gcov_type_node,
468 tree_ctr_tables[counter],
469 build_int_cst (NULL_TREE, no),
470 NULL, NULL));
473 /* Generate a checksum for a string. CHKSUM is the current
474 checksum. */
476 static unsigned
477 coverage_checksum_string (unsigned chksum, const char *string)
479 int i;
480 char *dup = NULL;
482 /* Look for everything that looks if it were produced by
483 get_file_function_name and zero out the second part
484 that may result from flag_random_seed. This is not critical
485 as the checksums are used only for sanity checking. */
486 for (i = 0; string[i]; i++)
488 int offset = 0;
489 if (!strncmp (string + i, "_GLOBAL__N_", 11))
490 offset = 11;
491 if (!strncmp (string + i, "_GLOBAL__", 9))
492 offset = 9;
494 /* C++ namespaces do have scheme:
495 _GLOBAL__N_<filename>_<wrongmagicnumber>_<magicnumber>functionname
496 since filename might contain extra underscores there seems
497 to be no better chance then walk all possible offsets looking
498 for magicnumber. */
499 if (offset)
501 for (i = i + offset; string[i]; i++)
502 if (string[i]=='_')
504 int y;
506 for (y = 1; y < 9; y++)
507 if (!(string[i + y] >= '0' && string[i + y] <= '9')
508 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
509 break;
510 if (y != 9 || string[i + 9] != '_')
511 continue;
512 for (y = 10; y < 18; y++)
513 if (!(string[i + y] >= '0' && string[i + y] <= '9')
514 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
515 break;
516 if (y != 18)
517 continue;
518 if (!dup)
519 string = dup = xstrdup (string);
520 for (y = 10; y < 18; y++)
521 dup[i + y] = '0';
523 break;
527 chksum = crc32_string (chksum, string);
528 if (dup)
529 free (dup);
531 return chksum;
534 /* Compute checksum for the current function. We generate a CRC32. */
536 static unsigned
537 compute_checksum (void)
539 expanded_location xloc
540 = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
541 unsigned chksum = xloc.line;
543 chksum = coverage_checksum_string (chksum, xloc.file);
544 chksum = coverage_checksum_string
545 (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
547 return chksum;
550 /* Begin output to the graph file for the current function.
551 Opens the output file, if not already done. Writes the
552 function header, if not already done. Returns nonzero if data
553 should be output. */
556 coverage_begin_output (void)
558 /* We don't need to output .gcno file unless we're under -ftest-coverage
559 (e.g. -fprofile-arcs/generate/use don't need .gcno to work). */
560 if (no_coverage || !flag_test_coverage || flag_compare_debug)
561 return 0;
563 if (!bbg_function_announced)
565 expanded_location xloc
566 = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
567 unsigned long offset;
569 if (!bbg_file_opened)
571 if (!gcov_open (bbg_file_name, -1))
572 error ("cannot open %s", bbg_file_name);
573 else
575 gcov_write_unsigned (GCOV_NOTE_MAGIC);
576 gcov_write_unsigned (GCOV_VERSION);
577 gcov_write_unsigned (local_tick);
579 bbg_file_opened = 1;
582 /* Announce function */
583 offset = gcov_write_tag (GCOV_TAG_FUNCTION);
584 gcov_write_unsigned (current_function_funcdef_no + 1);
585 gcov_write_unsigned (compute_checksum ());
586 gcov_write_string (IDENTIFIER_POINTER
587 (DECL_ASSEMBLER_NAME (current_function_decl)));
588 gcov_write_string (xloc.file);
589 gcov_write_unsigned (xloc.line);
590 gcov_write_length (offset);
592 bbg_function_announced = 1;
594 return !gcov_is_error ();
597 /* Finish coverage data for the current function. Verify no output
598 error has occurred. Save function coverage counts. */
600 void
601 coverage_end_function (void)
603 unsigned i;
605 if (bbg_file_opened > 1 && gcov_is_error ())
607 warning (0, "error writing %qs", bbg_file_name);
608 bbg_file_opened = -1;
611 if (fn_ctr_mask)
613 struct function_list *item;
615 item = XNEW (struct function_list);
617 *functions_tail = item;
618 functions_tail = &item->next;
620 item->next = 0;
621 item->ident = current_function_funcdef_no + 1;
622 item->checksum = compute_checksum ();
623 for (i = 0; i != GCOV_COUNTERS; i++)
625 item->n_ctrs[i] = fn_n_ctrs[i];
626 prg_n_ctrs[i] += fn_n_ctrs[i];
627 fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
629 prg_ctr_mask |= fn_ctr_mask;
630 fn_ctr_mask = 0;
632 bbg_function_announced = 0;
635 /* Creates the gcov_fn_info RECORD_TYPE. */
637 static tree
638 build_fn_info_type (unsigned int counters)
640 tree type = lang_hooks.types.make_type (RECORD_TYPE);
641 tree field, fields;
642 tree array_type;
644 /* ident */
645 fields = build_decl (BUILTINS_LOCATION,
646 FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
648 /* checksum */
649 field = build_decl (BUILTINS_LOCATION,
650 FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
651 TREE_CHAIN (field) = fields;
652 fields = field;
654 array_type = build_int_cst (NULL_TREE, counters - 1);
655 array_type = build_index_type (array_type);
656 array_type = build_array_type (get_gcov_unsigned_t (), array_type);
658 /* counters */
659 field = build_decl (BUILTINS_LOCATION,
660 FIELD_DECL, NULL_TREE, array_type);
661 TREE_CHAIN (field) = fields;
662 fields = field;
664 finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
666 return type;
669 /* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
670 the function being processed and TYPE is the gcov_fn_info
671 RECORD_TYPE. */
673 static tree
674 build_fn_info_value (const struct function_list *function, tree type)
676 tree fields = TYPE_FIELDS (type);
677 unsigned ix;
678 VEC(constructor_elt,gc) *v1 = NULL;
679 VEC(constructor_elt,gc) *v2 = NULL;
681 /* ident */
682 CONSTRUCTOR_APPEND_ELT (v1, fields,
683 build_int_cstu (get_gcov_unsigned_t (),
684 function->ident));
685 fields = TREE_CHAIN (fields);
687 /* checksum */
688 CONSTRUCTOR_APPEND_ELT (v1, fields,
689 build_int_cstu (get_gcov_unsigned_t (),
690 function->checksum));
691 fields = TREE_CHAIN (fields);
693 /* counters */
694 for (ix = 0; ix != GCOV_COUNTERS; ix++)
695 if (prg_ctr_mask & (1 << ix))
696 CONSTRUCTOR_APPEND_ELT (v2, NULL,
697 build_int_cstu (get_gcov_unsigned_t (),
698 function->n_ctrs[ix]));
700 CONSTRUCTOR_APPEND_ELT (v1, fields,
701 build_constructor (TREE_TYPE (fields), v2));
703 return build_constructor (type, v1);
706 /* Creates the gcov_ctr_info RECORD_TYPE. */
708 static tree
709 build_ctr_info_type (void)
711 tree type = lang_hooks.types.make_type (RECORD_TYPE);
712 tree field, fields = NULL_TREE;
713 tree gcov_ptr_type = build_pointer_type (get_gcov_type ());
714 tree gcov_merge_fn_type;
716 /* counters */
717 field = build_decl (BUILTINS_LOCATION,
718 FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
719 TREE_CHAIN (field) = fields;
720 fields = field;
722 /* values */
723 field = build_decl (BUILTINS_LOCATION,
724 FIELD_DECL, NULL_TREE, gcov_ptr_type);
725 TREE_CHAIN (field) = fields;
726 fields = field;
728 /* merge */
729 gcov_merge_fn_type =
730 build_function_type_list (void_type_node,
731 gcov_ptr_type, get_gcov_unsigned_t (),
732 NULL_TREE);
733 field = build_decl (BUILTINS_LOCATION,
734 FIELD_DECL, NULL_TREE,
735 build_pointer_type (gcov_merge_fn_type));
736 TREE_CHAIN (field) = fields;
737 fields = field;
739 finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
741 return type;
744 /* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
745 the counter being processed and TYPE is the gcov_ctr_info
746 RECORD_TYPE. */
748 static tree
749 build_ctr_info_value (unsigned int counter, tree type)
751 tree fields = TYPE_FIELDS (type);
752 tree fn;
753 VEC(constructor_elt,gc) *v = NULL;
755 /* counters */
756 CONSTRUCTOR_APPEND_ELT (v, fields,
757 build_int_cstu (get_gcov_unsigned_t (),
758 prg_n_ctrs[counter]));
759 fields = TREE_CHAIN (fields);
761 if (prg_n_ctrs[counter])
763 tree array_type;
765 array_type = build_int_cstu (get_gcov_unsigned_t (),
766 prg_n_ctrs[counter] - 1);
767 array_type = build_index_type (array_type);
768 array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
769 array_type);
771 TREE_TYPE (tree_ctr_tables[counter]) = array_type;
772 DECL_SIZE (tree_ctr_tables[counter]) = TYPE_SIZE (array_type);
773 DECL_SIZE_UNIT (tree_ctr_tables[counter]) = TYPE_SIZE_UNIT (array_type);
774 varpool_finalize_decl (tree_ctr_tables[counter]);
776 CONSTRUCTOR_APPEND_ELT (v, fields,
777 build1 (ADDR_EXPR, TREE_TYPE (fields),
778 tree_ctr_tables[counter]));
780 else
781 CONSTRUCTOR_APPEND_ELT (v, fields, null_pointer_node);
782 fields = TREE_CHAIN (fields);
784 fn = build_decl (BUILTINS_LOCATION,
785 FUNCTION_DECL,
786 get_identifier (ctr_merge_functions[counter]),
787 TREE_TYPE (TREE_TYPE (fields)));
788 DECL_EXTERNAL (fn) = 1;
789 TREE_PUBLIC (fn) = 1;
790 DECL_ARTIFICIAL (fn) = 1;
791 TREE_NOTHROW (fn) = 1;
792 DECL_ASSEMBLER_NAME (fn); /* Initialize assembler name so we can stream out. */
793 CONSTRUCTOR_APPEND_ELT (v, fields, build1 (ADDR_EXPR, TREE_TYPE (fields), fn));
795 return build_constructor (type, v);
798 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
799 CONSTRUCTOR. */
801 static tree
802 build_gcov_info (void)
804 unsigned n_ctr_types, ix;
805 tree type, const_type;
806 tree fn_info_type, fn_info_value = NULL_TREE;
807 tree fn_info_ptr_type;
808 tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
809 tree field, fields = NULL_TREE;
810 tree filename_string;
811 int da_file_name_len;
812 unsigned n_fns;
813 const struct function_list *fn;
814 tree string_type;
815 VEC(constructor_elt,gc) *v1 = NULL;
816 VEC(constructor_elt,gc) *v2 = NULL;
818 /* Count the number of active counters. */
819 for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
820 if (prg_ctr_mask & (1 << ix))
821 n_ctr_types++;
823 type = lang_hooks.types.make_type (RECORD_TYPE);
824 const_type = build_qualified_type (type, TYPE_QUAL_CONST);
826 /* Version ident */
827 field = build_decl (BUILTINS_LOCATION,
828 FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
829 TREE_CHAIN (field) = fields;
830 fields = field;
831 CONSTRUCTOR_APPEND_ELT (v1, field,
832 build_int_cstu (TREE_TYPE (field), GCOV_VERSION));
834 /* next -- NULL */
835 field = build_decl (BUILTINS_LOCATION,
836 FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
837 TREE_CHAIN (field) = fields;
838 fields = field;
839 CONSTRUCTOR_APPEND_ELT (v1, field, null_pointer_node);
841 /* stamp */
842 field = build_decl (BUILTINS_LOCATION,
843 FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
844 TREE_CHAIN (field) = fields;
845 fields = field;
846 CONSTRUCTOR_APPEND_ELT (v1, field,
847 build_int_cstu (TREE_TYPE (field), local_tick));
849 /* Filename */
850 string_type = build_pointer_type (build_qualified_type (char_type_node,
851 TYPE_QUAL_CONST));
852 field = build_decl (BUILTINS_LOCATION,
853 FIELD_DECL, NULL_TREE, string_type);
854 TREE_CHAIN (field) = fields;
855 fields = field;
856 da_file_name_len = strlen (da_file_name);
857 filename_string = build_string (da_file_name_len + 1, da_file_name);
858 TREE_TYPE (filename_string) = build_array_type
859 (char_type_node, build_index_type
860 (build_int_cst (NULL_TREE, da_file_name_len)));
861 CONSTRUCTOR_APPEND_ELT (v1, field,
862 build1 (ADDR_EXPR, string_type, filename_string));
864 /* Build the fn_info type and initializer. */
865 fn_info_type = build_fn_info_type (n_ctr_types);
866 fn_info_ptr_type = build_pointer_type (build_qualified_type
867 (fn_info_type, TYPE_QUAL_CONST));
868 for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
869 CONSTRUCTOR_APPEND_ELT (v2, NULL_TREE,
870 build_fn_info_value (fn, fn_info_type));
872 if (n_fns)
874 tree array_type;
876 array_type = build_index_type (build_int_cst (NULL_TREE, n_fns - 1));
877 array_type = build_array_type (fn_info_type, array_type);
879 fn_info_value = build_constructor (array_type, v2);
880 fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
882 else
883 fn_info_value = null_pointer_node;
885 /* number of functions */
886 field = build_decl (BUILTINS_LOCATION,
887 FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
888 TREE_CHAIN (field) = fields;
889 fields = field;
890 CONSTRUCTOR_APPEND_ELT (v1, field,
891 build_int_cstu (get_gcov_unsigned_t (), n_fns));
893 /* fn_info table */
894 field = build_decl (BUILTINS_LOCATION,
895 FIELD_DECL, NULL_TREE, fn_info_ptr_type);
896 TREE_CHAIN (field) = fields;
897 fields = field;
898 CONSTRUCTOR_APPEND_ELT (v1, field, fn_info_value);
900 /* counter_mask */
901 field = build_decl (BUILTINS_LOCATION,
902 FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
903 TREE_CHAIN (field) = fields;
904 fields = field;
905 CONSTRUCTOR_APPEND_ELT (v1, field,
906 build_int_cstu (get_gcov_unsigned_t (),
907 prg_ctr_mask));
909 /* counters */
910 ctr_info_type = build_ctr_info_type ();
911 ctr_info_ary_type = build_index_type (build_int_cst (NULL_TREE,
912 n_ctr_types));
913 ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
914 v2 = NULL;
915 for (ix = 0; ix != GCOV_COUNTERS; ix++)
916 if (prg_ctr_mask & (1 << ix))
917 CONSTRUCTOR_APPEND_ELT (v2, NULL_TREE,
918 build_ctr_info_value (ix, ctr_info_type));
919 ctr_info_value = build_constructor (ctr_info_ary_type, v2);
921 field = build_decl (BUILTINS_LOCATION,
922 FIELD_DECL, NULL_TREE, ctr_info_ary_type);
923 TREE_CHAIN (field) = fields;
924 fields = field;
925 CONSTRUCTOR_APPEND_ELT (v1, field, ctr_info_value);
927 finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
929 return build_constructor (type, v1);
932 /* Write out the structure which libgcov uses to locate all the
933 counters. The structures used here must match those defined in
934 gcov-io.h. Write out the constructor to call __gcov_init. */
936 static void
937 create_coverage (void)
939 tree gcov_info, gcov_init, body, t;
940 char name_buf[32];
942 no_coverage = 1; /* Disable any further coverage. */
944 if (!prg_ctr_mask)
945 return;
947 t = build_gcov_info ();
949 gcov_info = build_decl (BUILTINS_LOCATION,
950 VAR_DECL, NULL_TREE, TREE_TYPE (t));
951 TREE_STATIC (gcov_info) = 1;
952 ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
953 DECL_NAME (gcov_info) = get_identifier (name_buf);
954 DECL_INITIAL (gcov_info) = t;
956 /* Build structure. */
957 varpool_finalize_decl (gcov_info);
959 /* Build a decl for __gcov_init. */
960 t = build_pointer_type (TREE_TYPE (gcov_info));
961 t = build_function_type_list (void_type_node, t, NULL);
962 t = build_decl (BUILTINS_LOCATION,
963 FUNCTION_DECL, get_identifier ("__gcov_init"), t);
964 TREE_PUBLIC (t) = 1;
965 DECL_EXTERNAL (t) = 1;
966 DECL_ASSEMBLER_NAME (t); /* Initialize assembler name so we can stream out. */
967 gcov_init = t;
969 /* Generate a call to __gcov_init(&gcov_info). */
970 body = NULL;
971 t = build_fold_addr_expr (gcov_info);
972 t = build_call_expr (gcov_init, 1, t);
973 append_to_statement_list (t, &body);
975 /* Generate a constructor to run it. */
976 cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
979 /* Perform file-level initialization. Read in data file, generate name
980 of graph file. */
982 void
983 coverage_init (const char *filename)
985 int len = strlen (filename);
986 /* + 1 for extra '/', in case prefix doesn't end with /. */
987 int prefix_len;
989 if (profile_data_prefix == 0 && filename[0] != '/')
990 profile_data_prefix = getpwd ();
992 prefix_len = (profile_data_prefix) ? strlen (profile_data_prefix) + 1 : 0;
994 /* Name of da file. */
995 da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX)
996 + prefix_len + 1);
998 if (profile_data_prefix)
1000 strcpy (da_file_name, profile_data_prefix);
1001 da_file_name[prefix_len - 1] = '/';
1002 da_file_name[prefix_len] = 0;
1004 else
1005 da_file_name[0] = 0;
1006 strcat (da_file_name, filename);
1007 strcat (da_file_name, GCOV_DATA_SUFFIX);
1009 /* Name of bbg file. */
1010 bbg_file_name = XNEWVEC (char, len + strlen (GCOV_NOTE_SUFFIX) + 1);
1011 strcpy (bbg_file_name, filename);
1012 strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
1014 if (flag_profile_use)
1015 read_counts_file ();
1018 /* Performs file-level cleanup. Close graph file, generate coverage
1019 variables and constructor. */
1021 void
1022 coverage_finish (void)
1024 create_coverage ();
1025 if (bbg_file_opened)
1027 int error = gcov_close ();
1029 if (error)
1030 unlink (bbg_file_name);
1031 if (!local_tick)
1032 /* Only remove the da file, if we cannot stamp it. If we can
1033 stamp it, libgcov will DTRT. */
1034 unlink (da_file_name);
1038 #include "gt-coverage.h"