* target.h (struct gcc_target): Add new field to struct cxx: import_export_class.
[official-gcc.git] / gcc / coverage.c
blob15a6a41873e9204afb4fd6c89b9743ac1b94762f
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 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 "coverage.h"
43 #include "langhooks.h"
44 #include "hashtab.h"
45 #include "tree-iterator.h"
46 #include "cgraph.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 /* Trees representing the counter table arrays. */
100 static GTY(()) tree tree_ctr_tables[GCOV_COUNTERS];
102 /* The names of the counter tables. Not used if we're
103 generating counters at tree level. */
104 static GTY(()) rtx ctr_labels[GCOV_COUNTERS];
106 /* The names of merge functions for counters. */
107 static const char *const ctr_merge_functions[GCOV_COUNTERS] = GCOV_MERGE_FUNCTIONS;
108 static const char *const ctr_names[GCOV_COUNTERS] = GCOV_COUNTER_NAMES;
110 /* Forward declarations. */
111 static hashval_t htab_counts_entry_hash (const void *);
112 static int htab_counts_entry_eq (const void *, const void *);
113 static void htab_counts_entry_del (void *);
114 static void read_counts_file (void);
115 static unsigned compute_checksum (void);
116 static unsigned coverage_checksum_string (unsigned, const char *);
117 static tree build_fn_info_type (unsigned);
118 static tree build_fn_info_value (const struct function_list *, tree);
119 static tree build_ctr_info_type (void);
120 static tree build_ctr_info_value (unsigned, tree);
121 static tree build_gcov_info (void);
122 static void create_coverage (void);
125 static hashval_t
126 htab_counts_entry_hash (const void *of)
128 const counts_entry_t *entry = of;
130 return entry->ident * GCOV_COUNTERS + entry->ctr;
133 static int
134 htab_counts_entry_eq (const void *of1, const void *of2)
136 const counts_entry_t *entry1 = of1;
137 const counts_entry_t *entry2 = of2;
139 return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
142 static void
143 htab_counts_entry_del (void *of)
145 counts_entry_t *entry = of;
147 free (entry->counts);
148 free (entry);
151 /* Read in the counts file, if available. */
153 static void
154 read_counts_file (void)
156 gcov_unsigned_t fn_ident = 0;
157 gcov_unsigned_t checksum = -1;
158 counts_entry_t *summaried = NULL;
159 unsigned seen_summary = 0;
160 gcov_unsigned_t tag;
161 int is_error = 0;
163 if (!gcov_open (da_file_name, 1))
164 return;
166 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
168 warning ("`%s' is not a gcov data file", da_file_name);
169 gcov_close ();
170 return;
172 else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
174 char v[4], e[4];
176 GCOV_UNSIGNED2STRING (v, tag);
177 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
179 warning ("`%s' is version `%.*s', expected version `%.*s'",
180 da_file_name, 4, v, 4, e);
181 gcov_close ();
182 return;
185 /* Read and discard the stamp. */
186 gcov_read_unsigned ();
188 counts_hash = htab_create (10,
189 htab_counts_entry_hash, htab_counts_entry_eq,
190 htab_counts_entry_del);
191 while ((tag = gcov_read_unsigned ()))
193 gcov_unsigned_t length;
194 gcov_position_t offset;
196 length = gcov_read_unsigned ();
197 offset = gcov_position ();
198 if (tag == GCOV_TAG_FUNCTION)
200 fn_ident = gcov_read_unsigned ();
201 checksum = gcov_read_unsigned ();
202 if (seen_summary)
204 /* We have already seen a summary, this means that this
205 new function begins a new set of program runs. We
206 must unlink the summaried chain. */
207 counts_entry_t *entry, *chain;
209 for (entry = summaried; entry; entry = chain)
211 chain = entry->chain;
212 entry->chain = NULL;
214 summaried = NULL;
215 seen_summary = 0;
218 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
220 counts_entry_t *entry;
221 struct gcov_summary summary;
223 gcov_read_summary (&summary);
224 seen_summary = 1;
225 for (entry = summaried; entry; entry = entry->chain)
227 struct gcov_ctr_summary *csum = &summary.ctrs[entry->ctr];
229 entry->summary.runs += csum->runs;
230 entry->summary.sum_all += csum->sum_all;
231 if (entry->summary.run_max < csum->run_max)
232 entry->summary.run_max = csum->run_max;
233 entry->summary.sum_max += csum->sum_max;
236 else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
238 counts_entry_t **slot, *entry, elt;
239 unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
240 unsigned ix;
242 elt.ident = fn_ident;
243 elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
245 slot = (counts_entry_t **) htab_find_slot
246 (counts_hash, &elt, INSERT);
247 entry = *slot;
248 if (!entry)
250 *slot = entry = xcalloc (1, sizeof (counts_entry_t));
251 entry->ident = elt.ident;
252 entry->ctr = elt.ctr;
253 entry->checksum = checksum;
254 entry->summary.num = n_counts;
255 entry->counts = xcalloc (n_counts, sizeof (gcov_type));
257 else if (entry->checksum != checksum)
259 error ("coverage mismatch for function %u while reading execution counters.",
260 fn_ident);
261 error ("checksum is %x instead of %x", entry->checksum, checksum);
262 htab_delete (counts_hash);
263 break;
265 else if (entry->summary.num != n_counts)
267 error ("coverage mismatch for function %u while reading execution counters.",
268 fn_ident);
269 error ("number of counters is %d instead of %d", entry->summary.num, n_counts);
270 htab_delete (counts_hash);
271 break;
273 else if (elt.ctr >= GCOV_COUNTERS_SUMMABLE)
275 error ("cannot merge separate %s counters for function %u",
276 ctr_names[elt.ctr], fn_ident);
277 goto skip_merge;
280 if (elt.ctr < GCOV_COUNTERS_SUMMABLE
281 /* This should always be true for a just allocated entry,
282 and always false for an existing one. Check this way, in
283 case the gcov file is corrupt. */
284 && (!entry->chain || summaried != entry))
286 entry->chain = summaried;
287 summaried = entry;
289 for (ix = 0; ix != n_counts; ix++)
290 entry->counts[ix] += gcov_read_counter ();
291 skip_merge:;
293 gcov_sync (offset, length);
294 if ((is_error = gcov_is_error ()))
295 break;
298 if (!gcov_is_eof ())
300 error (is_error < 0 ? "`%s' has overflowed" : "`%s' is corrupted",
301 da_file_name);
302 htab_delete (counts_hash);
305 gcov_close ();
308 /* Returns the counters for a particular tag. */
310 gcov_type *
311 get_coverage_counts (unsigned counter, unsigned expected,
312 const struct gcov_ctr_summary **summary)
314 counts_entry_t *entry, elt;
315 gcov_unsigned_t checksum = -1;
317 /* No hash table, no counts. */
318 if (!counts_hash)
320 static int warned = 0;
322 if (!warned++)
323 inform ((flag_guess_branch_prob
324 ? "file %s not found, execution counts estimated"
325 : "file %s not found, execution counts assumed to be zero"),
326 da_file_name);
327 return NULL;
330 elt.ident = current_function_funcdef_no + 1;
331 elt.ctr = counter;
332 entry = htab_find (counts_hash, &elt);
333 if (!entry)
335 warning ("no coverage for function '%s' found.", IDENTIFIER_POINTER
336 (DECL_ASSEMBLER_NAME (current_function_decl)));
337 return 0;
340 checksum = compute_checksum ();
341 if (entry->checksum != checksum)
343 error ("coverage mismatch for function '%s' while reading counter '%s'.",
344 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
345 ctr_names[counter]);
346 error ("checksum is %x instead of %x", entry->checksum, checksum);
347 return 0;
349 else if (entry->summary.num != expected)
351 error ("coverage mismatch for function '%s' while reading counter '%s'.",
352 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
353 ctr_names[counter]);
354 error ("number of counters is %d instead of %d", entry->summary.num, expected);
355 return 0;
358 if (summary)
359 *summary = &entry->summary;
361 return entry->counts;
364 /* Allocate NUM counters of type COUNTER. Returns nonzero if the
365 allocation succeeded. */
368 coverage_counter_alloc (unsigned counter, unsigned num)
370 if (no_coverage)
371 return 0;
373 if (!num)
374 return 1;
376 if (!tree_ctr_tables[counter])
378 /* Generate and save a copy of this so it can be shared. */
379 /* We don't know the size yet; make it big enough that nobody
380 will make any clever transformation on it. */
381 char buf[20];
382 tree domain_tree
383 = build_index_type (build_int_2 (1000, 0)); /* replaced later */
384 tree gcov_type_array_type
385 = build_array_type (GCOV_TYPE_NODE, domain_tree);
386 tree_ctr_tables[counter]
387 = build_decl (VAR_DECL, NULL_TREE, gcov_type_array_type);
388 TREE_STATIC (tree_ctr_tables[counter]) = 1;
389 ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
390 DECL_NAME (tree_ctr_tables[counter]) = get_identifier (buf);
391 DECL_ALIGN (tree_ctr_tables[counter]) = TYPE_ALIGN (GCOV_TYPE_NODE);
393 fn_b_ctrs[counter] = fn_n_ctrs[counter];
394 fn_n_ctrs[counter] += num;
395 fn_ctr_mask |= 1 << counter;
396 return 1;
399 /* Generate a MEM rtl to access COUNTER NO. */
402 rtl_coverage_counter_ref (unsigned counter, unsigned no)
404 unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
405 enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
406 rtx ref;
408 if (no >= fn_n_ctrs[counter] - fn_b_ctrs[counter])
409 abort ();
410 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
411 if (!ctr_labels[counter])
413 ctr_labels[counter] = gen_rtx_SYMBOL_REF (Pmode,
414 ggc_strdup (IDENTIFIER_POINTER (DECL_NAME
415 (tree_ctr_tables[counter]))));
416 SYMBOL_REF_FLAGS (ctr_labels[counter]) = SYMBOL_FLAG_LOCAL;
418 ref = plus_constant (ctr_labels[counter], gcov_size / BITS_PER_UNIT * no);
419 ref = gen_rtx_MEM (mode, ref);
420 set_mem_alias_set (ref, new_alias_set ());
421 MEM_NOTRAP_P (ref) = 1;
423 return ref;
426 /* Generate a tree to access COUNTER NO. */
428 tree
429 tree_coverage_counter_ref (unsigned counter, unsigned no)
431 tree domain_type = TYPE_DOMAIN (TREE_TYPE (tree_ctr_tables[counter]));
433 if (no >= fn_n_ctrs[counter] - fn_b_ctrs[counter])
434 abort ();
435 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
437 /* "no" here is an array index, scaled to bytes later. */
438 return build (ARRAY_REF, GCOV_TYPE_NODE, tree_ctr_tables[counter],
439 fold_convert (domain_type, build_int_2 (no, 0)),
440 TYPE_MIN_VALUE (domain_type),
441 size_binop (EXACT_DIV_EXPR, TYPE_SIZE_UNIT (GCOV_TYPE_NODE),
442 size_int (TYPE_ALIGN (GCOV_TYPE_NODE))));
445 /* Generate a checksum for a string. CHKSUM is the current
446 checksum. */
448 static unsigned
449 coverage_checksum_string (unsigned chksum, const char *string)
451 int i;
452 char *dup = NULL;
454 /* Look for everything that looks if it were produced by
455 get_file_function_name_long and zero out the second part
456 that may result from flag_random_seed. This is not critical
457 as the checksums are used only for sanity checking. */
458 for (i = 0; string[i]; i++)
460 if (!strncmp (string + i, "_GLOBAL__", 9))
461 for (i = i + 9; string[i]; i++)
462 if (string[i]=='_')
464 int y;
465 unsigned seed;
467 for (y = 1; y < 9; y++)
468 if (!(string[i + y] >= '0' && string[i + y] <= '9')
469 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
470 break;
471 if (y != 9 || string[i + 9] != '_')
472 continue;
473 for (y = 10; y < 18; y++)
474 if (!(string[i + y] >= '0' && string[i + y] <= '9')
475 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
476 break;
477 if (y != 18)
478 continue;
479 if (!sscanf (string + i + 10, "%X", &seed))
480 abort ();
481 if (seed != crc32_string (0, flag_random_seed))
482 continue;
483 string = dup = xstrdup (string);
484 for (y = 10; y < 18; y++)
485 dup[i + y] = '0';
486 break;
488 break;
491 chksum = crc32_string (chksum, string);
492 if (dup)
493 free (dup);
495 return chksum;
498 /* Compute checksum for the current function. We generate a CRC32. */
500 static unsigned
501 compute_checksum (void)
503 expanded_location xloc
504 = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
505 unsigned chksum = xloc.line;
507 chksum = coverage_checksum_string (chksum, xloc.file);
508 chksum = coverage_checksum_string
509 (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
511 return chksum;
514 /* Begin output to the graph file for the current function.
515 Opens the output file, if not already done. Writes the
516 function header, if not already done. Returns nonzero if data
517 should be output. */
520 coverage_begin_output (void)
522 if (no_coverage)
523 return 0;
525 if (!bbg_function_announced)
527 expanded_location xloc
528 = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
529 unsigned long offset;
531 if (!bbg_file_opened)
533 if (!gcov_open (bbg_file_name, -1))
534 error ("cannot open %s", bbg_file_name);
535 else
537 gcov_write_unsigned (GCOV_NOTE_MAGIC);
538 gcov_write_unsigned (GCOV_VERSION);
539 gcov_write_unsigned (local_tick);
541 bbg_file_opened = 1;
544 /* Announce function */
545 offset = gcov_write_tag (GCOV_TAG_FUNCTION);
546 gcov_write_unsigned (current_function_funcdef_no + 1);
547 gcov_write_unsigned (compute_checksum ());
548 gcov_write_string (IDENTIFIER_POINTER
549 (DECL_ASSEMBLER_NAME (current_function_decl)));
550 gcov_write_string (xloc.file);
551 gcov_write_unsigned (xloc.line);
552 gcov_write_length (offset);
554 bbg_function_announced = 1;
556 return !gcov_is_error ();
559 /* Finish coverage data for the current function. Verify no output
560 error has occurred. Save function coverage counts. */
562 void
563 coverage_end_function (void)
565 unsigned i;
567 if (bbg_file_opened > 1 && gcov_is_error ())
569 warning ("error writing `%s'", bbg_file_name);
570 bbg_file_opened = -1;
573 if (fn_ctr_mask)
575 struct function_list *item;
577 item = xmalloc (sizeof (struct function_list));
579 *functions_tail = item;
580 functions_tail = &item->next;
582 item->next = 0;
583 item->ident = current_function_funcdef_no + 1;
584 item->checksum = compute_checksum ();
585 for (i = 0; i != GCOV_COUNTERS; i++)
587 item->n_ctrs[i] = fn_n_ctrs[i];
588 prg_n_ctrs[i] += fn_n_ctrs[i];
589 fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
591 prg_ctr_mask |= fn_ctr_mask;
592 fn_ctr_mask = 0;
594 bbg_function_announced = 0;
597 /* Creates the gcov_fn_info RECORD_TYPE. */
599 static tree
600 build_fn_info_type (unsigned int counters)
602 tree type = lang_hooks.types.make_type (RECORD_TYPE);
603 tree field, fields;
604 tree array_type;
606 /* ident */
607 fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
609 /* checksum */
610 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
611 TREE_CHAIN (field) = fields;
612 fields = field;
614 array_type = build_index_type (build_int_2 (counters - 1, 0));
615 array_type = build_array_type (unsigned_type_node, array_type);
617 /* counters */
618 field = build_decl (FIELD_DECL, NULL_TREE, array_type);
619 TREE_CHAIN (field) = fields;
620 fields = field;
622 finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
624 return type;
627 /* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
628 the function being processed and TYPE is the gcov_fn_info
629 RECORD_TYPE. */
631 static tree
632 build_fn_info_value (const struct function_list *function, tree type)
634 tree value = NULL_TREE;
635 tree fields = TYPE_FIELDS (type);
636 unsigned ix;
637 tree array_value = NULL_TREE;
639 /* ident */
640 value = tree_cons (fields,
641 convert (unsigned_intSI_type_node,
642 build_int_2 (function->ident, 0)),
643 value);
644 fields = TREE_CHAIN (fields);
646 /* checksum */
647 value = tree_cons (fields,
648 convert (unsigned_intSI_type_node,
649 build_int_2 (function->checksum, 0)),
650 value);
651 fields = TREE_CHAIN (fields);
653 /* counters */
654 for (ix = 0; ix != GCOV_COUNTERS; ix++)
655 if (prg_ctr_mask & (1 << ix))
657 tree counters = convert (unsigned_type_node,
658 build_int_2 (function->n_ctrs[ix], 0));
660 array_value = tree_cons (NULL_TREE, counters, array_value);
663 array_value = build_constructor (TREE_TYPE (fields), nreverse (array_value));
664 value = tree_cons (fields, array_value, value);
666 value = build_constructor (type, nreverse (value));
668 return value;
671 /* Creates the gcov_ctr_info RECORD_TYPE. */
673 static tree
674 build_ctr_info_type (void)
676 tree type = lang_hooks.types.make_type (RECORD_TYPE);
677 tree field, fields = NULL_TREE;
678 tree gcov_ptr_type = build_pointer_type (GCOV_TYPE_NODE);
679 tree gcov_merge_fn_type;
681 /* counters */
682 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
683 TREE_CHAIN (field) = fields;
684 fields = field;
686 /* values */
687 field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
688 TREE_CHAIN (field) = fields;
689 fields = field;
691 /* merge */
692 gcov_merge_fn_type =
693 build_function_type_list (void_type_node,
694 gcov_ptr_type, unsigned_type_node,
695 NULL_TREE);
696 field = build_decl (FIELD_DECL, NULL_TREE,
697 build_pointer_type (gcov_merge_fn_type));
698 TREE_CHAIN (field) = fields;
699 fields = field;
701 finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
703 return type;
706 /* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
707 the counter being processed and TYPE is the gcov_ctr_info
708 RECORD_TYPE. */
710 static tree
711 build_ctr_info_value (unsigned int counter, tree type)
713 tree value = NULL_TREE;
714 tree fields = TYPE_FIELDS (type);
715 tree fn;
717 /* counters */
718 value = tree_cons (fields,
719 convert (unsigned_intSI_type_node,
720 build_int_2 (prg_n_ctrs[counter], 0)),
721 value);
722 fields = TREE_CHAIN (fields);
724 if (prg_n_ctrs[counter])
726 tree array_type;
728 array_type = build_index_type (build_int_2 (prg_n_ctrs[counter] - 1, 0));
729 array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
730 array_type);
732 TREE_TYPE (tree_ctr_tables[counter]) = array_type;
733 DECL_SIZE (tree_ctr_tables[counter]) = TYPE_SIZE (array_type);
734 DECL_SIZE_UNIT (tree_ctr_tables[counter]) = TYPE_SIZE_UNIT (array_type);
735 assemble_variable (tree_ctr_tables[counter], 0, 0, 0);
737 value = tree_cons (fields,
738 build1 (ADDR_EXPR, TREE_TYPE (fields),
739 tree_ctr_tables[counter]),
740 value);
742 else
743 value = tree_cons (fields, null_pointer_node, value);
744 fields = TREE_CHAIN (fields);
746 fn = build_decl (FUNCTION_DECL,
747 get_identifier (ctr_merge_functions[counter]),
748 TREE_TYPE (TREE_TYPE (fields)));
749 DECL_EXTERNAL (fn) = 1;
750 TREE_PUBLIC (fn) = 1;
751 DECL_ARTIFICIAL (fn) = 1;
752 TREE_NOTHROW (fn) = 1;
753 value = tree_cons (fields,
754 build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
755 value);
757 value = build_constructor (type, nreverse (value));
759 return value;
762 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
763 CONSTRUCTOR. */
765 static tree
766 build_gcov_info (void)
768 unsigned n_ctr_types, ix;
769 tree type, const_type;
770 tree fn_info_type, fn_info_value = NULL_TREE;
771 tree fn_info_ptr_type;
772 tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
773 tree field, fields = NULL_TREE;
774 tree value = NULL_TREE;
775 tree filename_string;
776 char *filename;
777 int filename_len;
778 unsigned n_fns;
779 const struct function_list *fn;
780 tree string_type;
782 /* Count the number of active counters. */
783 for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
784 if (prg_ctr_mask & (1 << ix))
785 n_ctr_types++;
787 type = lang_hooks.types.make_type (RECORD_TYPE);
788 const_type = build_qualified_type (type, TYPE_QUAL_CONST);
790 /* Version ident */
791 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
792 TREE_CHAIN (field) = fields;
793 fields = field;
794 value = tree_cons (field, convert (unsigned_intSI_type_node,
795 build_int_2 (GCOV_VERSION, 0)),
796 value);
798 /* next -- NULL */
799 field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
800 TREE_CHAIN (field) = fields;
801 fields = field;
802 value = tree_cons (field, null_pointer_node, value);
804 /* stamp */
805 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
806 TREE_CHAIN (field) = fields;
807 fields = field;
808 value = tree_cons (field, convert (unsigned_intSI_type_node,
809 build_int_2 (local_tick, 0)),
810 value);
812 /* Filename */
813 string_type = build_pointer_type (build_qualified_type (char_type_node,
814 TYPE_QUAL_CONST));
815 field = build_decl (FIELD_DECL, NULL_TREE, string_type);
816 TREE_CHAIN (field) = fields;
817 fields = field;
818 filename = getpwd ();
819 filename = (filename && da_file_name[0] != '/'
820 ? concat (filename, "/", da_file_name, NULL)
821 : da_file_name);
822 filename_len = strlen (filename);
823 filename_string = build_string (filename_len + 1, filename);
824 if (filename != da_file_name)
825 free (filename);
826 TREE_TYPE (filename_string) =
827 build_array_type (char_type_node,
828 build_index_type (build_int_2 (filename_len, 0)));
829 value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
830 value);
832 /* Build the fn_info type and initializer. */
833 fn_info_type = build_fn_info_type (n_ctr_types);
834 fn_info_ptr_type = build_pointer_type (build_qualified_type
835 (fn_info_type, TYPE_QUAL_CONST));
836 for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
837 fn_info_value = tree_cons (NULL_TREE,
838 build_fn_info_value (fn, fn_info_type),
839 fn_info_value);
840 if (n_fns)
842 tree array_type;
844 array_type = build_index_type (build_int_2 (n_fns - 1, 0));
845 array_type = build_array_type (fn_info_type, array_type);
847 fn_info_value = build_constructor (array_type, nreverse (fn_info_value));
848 fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
850 else
851 fn_info_value = null_pointer_node;
853 /* number of functions */
854 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
855 TREE_CHAIN (field) = fields;
856 fields = field;
857 value = tree_cons (field,
858 convert (unsigned_type_node, build_int_2 (n_fns, 0)),
859 value);
861 /* fn_info table */
862 field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type);
863 TREE_CHAIN (field) = fields;
864 fields = field;
865 value = tree_cons (field, fn_info_value, value);
867 /* counter_mask */
868 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
869 TREE_CHAIN (field) = fields;
870 fields = field;
871 value = tree_cons (field,
872 convert (unsigned_type_node,
873 build_int_2 (prg_ctr_mask, 0)),
874 value);
876 /* counters */
877 ctr_info_type = build_ctr_info_type ();
878 ctr_info_ary_type = build_index_type (build_int_2 (n_ctr_types, 0));
879 ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
880 for (ix = 0; ix != GCOV_COUNTERS; ix++)
881 if (prg_ctr_mask & (1 << ix))
882 ctr_info_value = tree_cons (NULL_TREE,
883 build_ctr_info_value (ix, ctr_info_type),
884 ctr_info_value);
885 ctr_info_value = build_constructor (ctr_info_ary_type,
886 nreverse (ctr_info_value));
888 field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
889 TREE_CHAIN (field) = fields;
890 fields = field;
891 value = tree_cons (field, ctr_info_value, value);
893 finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
895 value = build_constructor (type, nreverse (value));
897 return value;
900 /* Write out the structure which libgcov uses to locate all the
901 counters. The structures used here must match those defined in
902 gcov-io.h. Write out the constructor to call __gcov_init. */
904 static void
905 create_coverage (void)
907 tree gcov_info, gcov_init, body, t;
908 char name_buf[32];
910 no_coverage = 1; /* Disable any further coverage. */
912 if (!prg_ctr_mask)
913 return;
915 t = build_gcov_info ();
917 gcov_info = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (t));
918 TREE_STATIC (gcov_info) = 1;
919 ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
920 DECL_NAME (gcov_info) = get_identifier (name_buf);
921 DECL_INITIAL (gcov_info) = t;
923 /* Build structure. */
924 assemble_variable (gcov_info, 0, 0, 0);
926 /* Build a decl for __gcov_init. */
927 t = build_pointer_type (TREE_TYPE (gcov_info));
928 t = build_function_type_list (void_type_node, t, NULL);
929 t = build_decl (FUNCTION_DECL, get_identifier ("__gcov_init"), t);
930 TREE_PUBLIC (t) = 1;
931 DECL_EXTERNAL (t) = 1;
932 gcov_init = t;
934 /* Generate a call to __gcov_init(&gcov_info). */
935 body = NULL;
936 t = build_fold_addr_expr (gcov_info);
937 t = tree_cons (NULL, t, NULL);
938 t = build_function_call_expr (gcov_init, t);
939 append_to_statement_list (t, &body);
941 /* Generate a constructor to run it. */
942 cgraph_build_static_cdtor ('I', body);
945 /* Perform file-level initialization. Read in data file, generate name
946 of graph file. */
948 void
949 coverage_init (const char *filename)
951 int len = strlen (filename);
953 /* Name of da file. */
954 da_file_name = xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1);
955 strcpy (da_file_name, filename);
956 strcat (da_file_name, GCOV_DATA_SUFFIX);
958 /* Name of bbg file. */
959 bbg_file_name = xmalloc (len + strlen (GCOV_NOTE_SUFFIX) + 1);
960 strcpy (bbg_file_name, filename);
961 strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
963 read_counts_file ();
966 /* Performs file-level cleanup. Close graph file, generate coverage
967 variables and constructor. */
969 void
970 coverage_finish (void)
972 create_coverage ();
973 if (bbg_file_opened)
975 int error = gcov_close ();
977 if (error)
978 unlink (bbg_file_name);
979 if (!local_tick)
980 /* Only remove the da file, if we cannot stamp it. If we can
981 stamp it, libgcov will DTRT. */
982 unlink (da_file_name);
986 #include "gt-coverage.h"