Merge branch 'master' of ssh://crater.dragonflybsd.org/repository/git/dragonfly
[dragonfly.git] / contrib / gcc-3.4 / gcc / coverage.c
blob85ba608380b73c147411b326a7b2083179d8f104
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 "target.h"
43 #include "coverage.h"
44 #include "libfuncs.h"
45 #include "langhooks.h"
46 #include "hashtab.h"
48 #include "gcov-io.c"
50 struct function_list
52 struct function_list *next; /* next function */
53 unsigned ident; /* function ident */
54 unsigned checksum; /* function checksum */
55 unsigned n_ctrs[GCOV_COUNTERS];/* number of counters. */
58 /* Counts information for a function. */
59 typedef struct counts_entry
61 /* We hash by */
62 unsigned ident;
63 unsigned ctr;
65 /* Store */
66 unsigned checksum;
67 gcov_type *counts;
68 struct gcov_ctr_summary summary;
70 /* Workspace */
71 struct counts_entry *chain;
73 } counts_entry_t;
75 static struct function_list *functions_head = 0;
76 static struct function_list **functions_tail = &functions_head;
77 static unsigned no_coverage = 0;
79 /* Cumulative counter information for whole program. */
80 static unsigned prg_ctr_mask; /* Mask of counter types generated. */
81 static unsigned prg_n_ctrs[GCOV_COUNTERS]; /* Total counters allocated. */
83 /* Counter information for current function. */
84 static unsigned fn_ctr_mask; /* Mask of counters used. */
85 static unsigned fn_n_ctrs[GCOV_COUNTERS]; /* Counters allocated. */
86 static unsigned fn_b_ctrs[GCOV_COUNTERS]; /* Allocation base. */
88 /* Name of the output file for coverage output file. */
89 static char *bbg_file_name;
90 static unsigned bbg_file_opened;
91 static int bbg_function_announced;
93 /* Name of the count data file. */
94 static char *da_file_name;
96 /* Hash table of count data. */
97 static htab_t counts_hash = NULL;
99 /* The names of the counter tables. */
100 static GTY(()) rtx ctr_labels[GCOV_COUNTERS];
102 /* The names of merge functions for counters. */
103 static const char *const ctr_merge_functions[GCOV_COUNTERS] = GCOV_MERGE_FUNCTIONS;
104 static const char *const ctr_names[GCOV_COUNTERS] = GCOV_COUNTER_NAMES;
106 /* Forward declarations. */
107 static hashval_t htab_counts_entry_hash (const void *);
108 static int htab_counts_entry_eq (const void *, const void *);
109 static void htab_counts_entry_del (void *);
110 static void read_counts_file (void);
111 static unsigned compute_checksum (void);
112 static unsigned coverage_checksum_string (unsigned, const char *);
113 static tree build_fn_info_type (unsigned);
114 static tree build_fn_info_value (const struct function_list *, tree);
115 static tree build_ctr_info_type (void);
116 static tree build_ctr_info_value (unsigned, tree);
117 static tree build_gcov_info (void);
118 static void create_coverage (void);
121 static hashval_t
122 htab_counts_entry_hash (const void *of)
124 const counts_entry_t *entry = of;
126 return entry->ident * GCOV_COUNTERS + entry->ctr;
129 static int
130 htab_counts_entry_eq (const void *of1, const void *of2)
132 const counts_entry_t *entry1 = of1;
133 const counts_entry_t *entry2 = of2;
135 return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
138 static void
139 htab_counts_entry_del (void *of)
141 counts_entry_t *entry = of;
143 free (entry->counts);
144 free (entry);
147 /* Read in the counts file, if available. */
149 static void
150 read_counts_file (void)
152 gcov_unsigned_t fn_ident = 0;
153 gcov_unsigned_t checksum = -1;
154 counts_entry_t *summaried = NULL;
155 unsigned seen_summary = 0;
156 gcov_unsigned_t tag;
157 int is_error = 0;
159 if (!gcov_open (da_file_name, 1))
160 return;
162 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
164 warning ("`%s' is not a gcov data file", da_file_name);
165 gcov_close ();
166 return;
168 else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
170 char v[4], e[4];
172 GCOV_UNSIGNED2STRING (v, tag);
173 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
175 warning ("`%s' is version `%.*s', expected version `%.*s'",
176 da_file_name, 4, v, 4, e);
177 gcov_close ();
178 return;
181 /* Read and discard the stamp. */
182 gcov_read_unsigned ();
184 counts_hash = htab_create (10,
185 htab_counts_entry_hash, htab_counts_entry_eq,
186 htab_counts_entry_del);
187 while ((tag = gcov_read_unsigned ()))
189 gcov_unsigned_t length;
190 gcov_position_t offset;
192 length = gcov_read_unsigned ();
193 offset = gcov_position ();
194 if (tag == GCOV_TAG_FUNCTION)
196 fn_ident = gcov_read_unsigned ();
197 checksum = gcov_read_unsigned ();
198 if (seen_summary)
200 /* We have already seen a summary, this means that this
201 new function begins a new set of program runs. We
202 must unlink the summaried chain. */
203 counts_entry_t *entry, *chain;
205 for (entry = summaried; entry; entry = chain)
207 chain = entry->chain;
208 entry->chain = NULL;
210 summaried = NULL;
211 seen_summary = 0;
214 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
216 counts_entry_t *entry;
217 struct gcov_summary summary;
219 gcov_read_summary (&summary);
220 seen_summary = 1;
221 for (entry = summaried; entry; entry = entry->chain)
223 struct gcov_ctr_summary *csum = &summary.ctrs[entry->ctr];
225 entry->summary.runs += csum->runs;
226 entry->summary.sum_all += csum->sum_all;
227 if (entry->summary.run_max < csum->run_max)
228 entry->summary.run_max = csum->run_max;
229 entry->summary.sum_max += csum->sum_max;
232 else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
234 counts_entry_t **slot, *entry, elt;
235 unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
236 unsigned ix;
238 elt.ident = fn_ident;
239 elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
241 slot = (counts_entry_t **) htab_find_slot
242 (counts_hash, &elt, INSERT);
243 entry = *slot;
244 if (!entry)
246 *slot = entry = xcalloc (1, sizeof (counts_entry_t));
247 entry->ident = elt.ident;
248 entry->ctr = elt.ctr;
249 entry->checksum = checksum;
250 entry->summary.num = n_counts;
251 entry->counts = xcalloc (n_counts, sizeof (gcov_type));
253 else if (entry->checksum != checksum)
255 error ("coverage mismatch for function %u while reading execution counters.",
256 fn_ident);
257 error ("checksum is %x instead of %x", entry->checksum, checksum);
258 htab_delete (counts_hash);
259 break;
261 else if (entry->summary.num != n_counts)
263 error ("coverage mismatch for function %u while reading execution counters.",
264 fn_ident);
265 error ("number of counters is %d instead of %d", entry->summary.num, n_counts);
266 htab_delete (counts_hash);
267 break;
269 else if (elt.ctr >= GCOV_COUNTERS_SUMMABLE)
271 error ("cannot merge separate %s counters for function %u",
272 ctr_names[elt.ctr], fn_ident);
273 goto skip_merge;
276 if (elt.ctr < GCOV_COUNTERS_SUMMABLE
277 /* This should always be true for a just allocated entry,
278 and always false for an existing one. Check this way, in
279 case the gcov file is corrupt. */
280 && (!entry->chain || summaried != entry))
282 entry->chain = summaried;
283 summaried = entry;
285 for (ix = 0; ix != n_counts; ix++)
286 entry->counts[ix] += gcov_read_counter ();
287 skip_merge:;
289 gcov_sync (offset, length);
290 if ((is_error = gcov_is_error ()))
291 break;
294 if (!gcov_is_eof ())
296 error (is_error < 0 ? "`%s' has overflowed" : "`%s' is corrupted",
297 da_file_name);
298 htab_delete (counts_hash);
301 gcov_close ();
304 /* Returns the counters for a particular tag. */
306 gcov_type *
307 get_coverage_counts (unsigned counter, unsigned expected,
308 const struct gcov_ctr_summary **summary)
310 counts_entry_t *entry, elt;
311 gcov_unsigned_t checksum = -1;
313 /* No hash table, no counts. */
314 if (!counts_hash)
316 static int warned = 0;
318 if (!warned++)
319 inform ("file %s not found, execution counts assumed to be zero",
320 da_file_name);
321 return NULL;
324 elt.ident = current_function_funcdef_no + 1;
325 elt.ctr = counter;
326 entry = htab_find (counts_hash, &elt);
327 if (!entry)
329 warning ("no coverage for function '%s' found.", IDENTIFIER_POINTER
330 (DECL_ASSEMBLER_NAME (current_function_decl)));
331 return 0;
334 checksum = compute_checksum ();
335 if (entry->checksum != checksum)
337 error ("coverage mismatch for function '%s' while reading counter '%s'.",
338 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
339 ctr_names[counter]);
340 error ("checksum is %x instead of %x", entry->checksum, checksum);
341 return 0;
343 else if (entry->summary.num != expected)
345 error ("coverage mismatch for function '%s' while reading counter '%s'.",
346 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
347 ctr_names[counter]);
348 error ("number of counters is %d instead of %d", entry->summary.num, expected);
349 return 0;
352 if (summary)
353 *summary = &entry->summary;
355 return entry->counts;
358 /* Allocate NUM counters of type COUNTER. Returns nonzero if the
359 allocation succeeded. */
362 coverage_counter_alloc (unsigned counter, unsigned num)
364 if (no_coverage)
365 return 0;
367 if (!num)
368 return 1;
370 if (!ctr_labels[counter])
372 /* Generate and save a copy of this so it can be shared. */
373 char buf[20];
375 ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
376 ctr_labels[counter] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
377 SYMBOL_REF_FLAGS (ctr_labels[counter]) = SYMBOL_FLAG_LOCAL;
379 fn_b_ctrs[counter] = fn_n_ctrs[counter];
380 fn_n_ctrs[counter] += num;
381 fn_ctr_mask |= 1 << counter;
382 return 1;
385 /* Generate a MEM rtl to access COUNTER NO. */
388 coverage_counter_ref (unsigned counter, unsigned no)
390 unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
391 enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
392 rtx ref;
394 if (no >= fn_n_ctrs[counter] - fn_b_ctrs[counter])
395 abort ();
396 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
397 ref = plus_constant (ctr_labels[counter], gcov_size / BITS_PER_UNIT * no);
398 ref = gen_rtx_MEM (mode, ref);
399 set_mem_alias_set (ref, new_alias_set ());
400 MEM_NOTRAP_P (ref) = 1;
402 return ref;
405 /* Generate a checksum for a string. CHKSUM is the current
406 checksum. */
408 static unsigned
409 coverage_checksum_string (unsigned chksum, const char *string)
411 int i;
412 char *dup = NULL;
414 /* Look for everything that looks if it were produced by
415 get_file_function_name_long and zero out the second part
416 that may result from flag_random_seed. This is not critical
417 as the checksums are used only for sanity checking. */
418 for (i = 0; string[i]; i++)
420 if (!strncmp (string + i, "_GLOBAL__", 9))
421 for (i = i + 9; string[i]; i++)
422 if (string[i]=='_')
424 int y;
425 unsigned seed;
427 for (y = 1; y < 9; y++)
428 if (!(string[i + y] >= '0' && string[i + y] <= '9')
429 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
430 break;
431 if (y != 9 || string[i + 9] != '_')
432 continue;
433 for (y = 10; y < 18; y++)
434 if (!(string[i + y] >= '0' && string[i + y] <= '9')
435 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
436 break;
437 if (y != 18)
438 continue;
439 if (!sscanf (string + i + 10, "%X", &seed))
440 abort ();
441 if (seed != crc32_string (0, flag_random_seed))
442 continue;
443 string = dup = xstrdup (string);
444 for (y = 10; y < 18; y++)
445 dup[i + y] = '0';
446 break;
448 break;
451 chksum = crc32_string (chksum, string);
452 if (dup)
453 free (dup);
455 return chksum;
458 /* Compute checksum for the current function. We generate a CRC32. */
460 static unsigned
461 compute_checksum (void)
463 unsigned chksum = DECL_SOURCE_LINE (current_function_decl);
465 chksum = coverage_checksum_string (chksum,
466 DECL_SOURCE_FILE (current_function_decl));
467 chksum = coverage_checksum_string
468 (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
470 return chksum;
473 /* Begin output to the graph file for the current function.
474 Opens the output file, if not already done. Writes the
475 function header, if not already done. Returns nonzero if data
476 should be output. */
479 coverage_begin_output (void)
481 if (no_coverage)
482 return 0;
484 if (!bbg_function_announced)
486 const char *file = DECL_SOURCE_FILE (current_function_decl);
487 unsigned line = DECL_SOURCE_LINE (current_function_decl);
488 unsigned long offset;
490 if (!bbg_file_opened)
492 if (!gcov_open (bbg_file_name, -1))
493 error ("cannot open %s", bbg_file_name);
494 else
496 gcov_write_unsigned (GCOV_NOTE_MAGIC);
497 gcov_write_unsigned (GCOV_VERSION);
498 gcov_write_unsigned (local_tick);
500 bbg_file_opened = 1;
503 /* Announce function */
504 offset = gcov_write_tag (GCOV_TAG_FUNCTION);
505 gcov_write_unsigned (current_function_funcdef_no + 1);
506 gcov_write_unsigned (compute_checksum ());
507 gcov_write_string (IDENTIFIER_POINTER
508 (DECL_ASSEMBLER_NAME (current_function_decl)));
509 gcov_write_string (file);
510 gcov_write_unsigned (line);
511 gcov_write_length (offset);
513 bbg_function_announced = 1;
515 return !gcov_is_error ();
518 /* Finish coverage data for the current function. Verify no output
519 error has occurred. Save function coverage counts. */
521 void
522 coverage_end_function (void)
524 unsigned i;
526 if (bbg_file_opened > 1 && gcov_is_error ())
528 warning ("error writing `%s'", bbg_file_name);
529 bbg_file_opened = -1;
532 if (fn_ctr_mask)
534 struct function_list *item;
536 item = xmalloc (sizeof (struct function_list));
538 *functions_tail = item;
539 functions_tail = &item->next;
541 item->next = 0;
542 item->ident = current_function_funcdef_no + 1;
543 item->checksum = compute_checksum ();
544 for (i = 0; i != GCOV_COUNTERS; i++)
546 item->n_ctrs[i] = fn_n_ctrs[i];
547 prg_n_ctrs[i] += fn_n_ctrs[i];
548 fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
550 prg_ctr_mask |= fn_ctr_mask;
551 fn_ctr_mask = 0;
553 bbg_function_announced = 0;
556 /* Creates the gcov_fn_info RECORD_TYPE. */
558 static tree
559 build_fn_info_type (unsigned int counters)
561 tree type = (*lang_hooks.types.make_type) (RECORD_TYPE);
562 tree field, fields;
563 tree array_type;
565 /* ident */
566 fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
568 /* checksum */
569 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
570 TREE_CHAIN (field) = fields;
571 fields = field;
573 array_type = build_index_type (build_int_2 (counters - 1, 0));
574 array_type = build_array_type (unsigned_type_node, array_type);
576 /* counters */
577 field = build_decl (FIELD_DECL, NULL_TREE, array_type);
578 TREE_CHAIN (field) = fields;
579 fields = field;
581 finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
583 return type;
586 /* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
587 the function being processed and TYPE is the gcov_fn_info
588 RECORD_TYPE. */
590 static tree
591 build_fn_info_value (const struct function_list *function, tree type)
593 tree value = NULL_TREE;
594 tree fields = TYPE_FIELDS (type);
595 unsigned ix;
596 tree array_value = NULL_TREE;
598 /* ident */
599 value = tree_cons (fields,
600 convert (unsigned_intSI_type_node,
601 build_int_2 (function->ident, 0)),
602 value);
603 fields = TREE_CHAIN (fields);
605 /* checksum */
606 value = tree_cons (fields,
607 convert (unsigned_intSI_type_node,
608 build_int_2 (function->checksum, 0)),
609 value);
610 fields = TREE_CHAIN (fields);
612 /* counters */
613 for (ix = 0; ix != GCOV_COUNTERS; ix++)
614 if (prg_ctr_mask & (1 << ix))
616 tree counters = convert (unsigned_type_node,
617 build_int_2 (function->n_ctrs[ix], 0));
619 array_value = tree_cons (NULL_TREE, counters, array_value);
622 array_value = build_constructor (TREE_TYPE (fields), nreverse (array_value));
623 value = tree_cons (fields, array_value, value);
625 value = build_constructor (type, nreverse (value));
627 return value;
630 /* Creates the gcov_ctr_info RECORD_TYPE. */
632 static tree
633 build_ctr_info_type (void)
635 tree type = (*lang_hooks.types.make_type) (RECORD_TYPE);
636 tree field, fields = NULL_TREE;
637 tree gcov_ptr_type = build_pointer_type (GCOV_TYPE_NODE);
638 tree gcov_merge_fn_type;
640 /* counters */
641 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
642 TREE_CHAIN (field) = fields;
643 fields = field;
645 /* values */
646 field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
647 TREE_CHAIN (field) = fields;
648 fields = field;
650 /* merge */
651 gcov_merge_fn_type =
652 build_function_type_list (void_type_node,
653 gcov_ptr_type, unsigned_type_node,
654 NULL_TREE);
655 field = build_decl (FIELD_DECL, NULL_TREE,
656 build_pointer_type (gcov_merge_fn_type));
657 TREE_CHAIN (field) = fields;
658 fields = field;
660 finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
662 return type;
665 /* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
666 the counter being processed and TYPE is the gcov_ctr_info
667 RECORD_TYPE. */
669 static tree
670 build_ctr_info_value (unsigned int counter, tree type)
672 tree value = NULL_TREE;
673 tree fields = TYPE_FIELDS (type);
674 tree fn;
676 /* counters */
677 value = tree_cons (fields,
678 convert (unsigned_intSI_type_node,
679 build_int_2 (prg_n_ctrs[counter], 0)),
680 value);
681 fields = TREE_CHAIN (fields);
683 if (prg_n_ctrs[counter])
685 tree array_type, array;
687 array_type = build_index_type (build_int_2 (prg_n_ctrs[counter] - 1, 0));
688 array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
689 array_type);
691 array = build_decl (VAR_DECL, NULL_TREE, array_type);
692 TREE_STATIC (array) = 1;
693 DECL_NAME (array) = get_identifier (XSTR (ctr_labels[counter], 0));
694 assemble_variable (array, 0, 0, 0);
696 value = tree_cons (fields,
697 build1 (ADDR_EXPR, TREE_TYPE (fields), array),
698 value);
700 else
701 value = tree_cons (fields, null_pointer_node, value);
702 fields = TREE_CHAIN (fields);
704 fn = build_decl (FUNCTION_DECL,
705 get_identifier (ctr_merge_functions[counter]),
706 TREE_TYPE (TREE_TYPE (fields)));
707 DECL_EXTERNAL (fn) = 1;
708 TREE_PUBLIC (fn) = 1;
709 DECL_ARTIFICIAL (fn) = 1;
710 TREE_NOTHROW (fn) = 1;
711 value = tree_cons (fields,
712 build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
713 value);
715 value = build_constructor (type, nreverse (value));
717 return value;
720 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
721 CONSTRUCTOR. */
723 static tree
724 build_gcov_info (void)
726 unsigned n_ctr_types, ix;
727 tree type, const_type;
728 tree fn_info_type, fn_info_value = NULL_TREE;
729 tree fn_info_ptr_type;
730 tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
731 tree field, fields = NULL_TREE;
732 tree value = NULL_TREE;
733 tree filename_string;
734 char *filename;
735 int filename_len;
736 unsigned n_fns;
737 const struct function_list *fn;
738 tree string_type;
740 /* Count the number of active counters. */
741 for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
742 if (prg_ctr_mask & (1 << ix))
743 n_ctr_types++;
745 type = (*lang_hooks.types.make_type) (RECORD_TYPE);
746 const_type = build_qualified_type (type, TYPE_QUAL_CONST);
748 /* Version ident */
749 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
750 TREE_CHAIN (field) = fields;
751 fields = field;
752 value = tree_cons (field, convert (unsigned_intSI_type_node,
753 build_int_2 (GCOV_VERSION, 0)),
754 value);
756 /* next -- NULL */
757 field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
758 TREE_CHAIN (field) = fields;
759 fields = field;
760 value = tree_cons (field, null_pointer_node, value);
762 /* stamp */
763 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
764 TREE_CHAIN (field) = fields;
765 fields = field;
766 value = tree_cons (field, convert (unsigned_intSI_type_node,
767 build_int_2 (local_tick, 0)),
768 value);
770 /* Filename */
771 string_type = build_pointer_type (build_qualified_type (char_type_node,
772 TYPE_QUAL_CONST));
773 field = build_decl (FIELD_DECL, NULL_TREE, string_type);
774 TREE_CHAIN (field) = fields;
775 fields = field;
776 filename = getpwd ();
777 filename = (filename && da_file_name[0] != '/'
778 ? concat (filename, "/", da_file_name, NULL)
779 : da_file_name);
780 filename_len = strlen (filename);
781 filename_string = build_string (filename_len + 1, filename);
782 if (filename != da_file_name)
783 free (filename);
784 TREE_TYPE (filename_string) =
785 build_array_type (char_type_node,
786 build_index_type (build_int_2 (filename_len, 0)));
787 value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
788 value);
790 /* Build the fn_info type and initializer. */
791 fn_info_type = build_fn_info_type (n_ctr_types);
792 fn_info_ptr_type = build_pointer_type (build_qualified_type
793 (fn_info_type, TYPE_QUAL_CONST));
794 for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
795 fn_info_value = tree_cons (NULL_TREE,
796 build_fn_info_value (fn, fn_info_type),
797 fn_info_value);
798 if (n_fns)
800 tree array_type;
802 array_type = build_index_type (build_int_2 (n_fns - 1, 0));
803 array_type = build_array_type (fn_info_type, array_type);
805 fn_info_value = build_constructor (array_type, nreverse (fn_info_value));
806 fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
808 else
809 fn_info_value = null_pointer_node;
811 /* number of functions */
812 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
813 TREE_CHAIN (field) = fields;
814 fields = field;
815 value = tree_cons (field,
816 convert (unsigned_type_node, build_int_2 (n_fns, 0)),
817 value);
819 /* fn_info table */
820 field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type);
821 TREE_CHAIN (field) = fields;
822 fields = field;
823 value = tree_cons (field, fn_info_value, value);
825 /* counter_mask */
826 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
827 TREE_CHAIN (field) = fields;
828 fields = field;
829 value = tree_cons (field,
830 convert (unsigned_type_node,
831 build_int_2 (prg_ctr_mask, 0)),
832 value);
834 /* counters */
835 ctr_info_type = build_ctr_info_type ();
836 ctr_info_ary_type = build_index_type (build_int_2 (n_ctr_types, 0));
837 ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
838 for (ix = 0; ix != GCOV_COUNTERS; ix++)
839 if (prg_ctr_mask & (1 << ix))
840 ctr_info_value = tree_cons (NULL_TREE,
841 build_ctr_info_value (ix, ctr_info_type),
842 ctr_info_value);
843 ctr_info_value = build_constructor (ctr_info_ary_type,
844 nreverse (ctr_info_value));
846 field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
847 TREE_CHAIN (field) = fields;
848 fields = field;
849 value = tree_cons (field, ctr_info_value, value);
851 finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
853 value = build_constructor (type, nreverse (value));
855 return value;
858 /* Write out the structure which libgcov uses to locate all the
859 counters. The structures used here must match those defined in
860 gcov-io.h. Write out the constructor to call __gcov_init. */
862 static void
863 create_coverage (void)
865 tree gcov_info, gcov_info_value;
866 char name[20];
867 char *ctor_name;
868 tree ctor;
869 rtx gcov_info_address;
871 no_coverage = 1; /* Disable any further coverage. */
873 if (!prg_ctr_mask)
874 return;
876 gcov_info_value = build_gcov_info ();
878 gcov_info = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (gcov_info_value));
879 DECL_INITIAL (gcov_info) = gcov_info_value;
881 TREE_STATIC (gcov_info) = 1;
882 ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 0);
883 DECL_NAME (gcov_info) = get_identifier (name);
885 /* Build structure. */
886 assemble_variable (gcov_info, 0, 0, 0);
888 /* Build the constructor function to invoke __gcov_init. */
889 ctor_name = concat (IDENTIFIER_POINTER (get_file_function_name ('I')),
890 "_GCOV", NULL);
891 ctor = build_decl (FUNCTION_DECL, get_identifier (ctor_name),
892 build_function_type (void_type_node, NULL_TREE));
893 free (ctor_name);
894 DECL_EXTERNAL (ctor) = 0;
896 /* It can be a static function as long as collect2 does not have
897 to scan the object file to find its ctor/dtor routine. */
898 TREE_PUBLIC (ctor) = ! targetm.have_ctors_dtors;
899 TREE_USED (ctor) = 1;
900 DECL_RESULT (ctor) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
901 DECL_UNINLINABLE (ctor) = 1;
903 ctor = (*lang_hooks.decls.pushdecl) (ctor);
904 rest_of_decl_compilation (ctor, 0, 1, 0);
905 announce_function (ctor);
906 current_function_decl = ctor;
907 make_decl_rtl (ctor, NULL);
908 init_function_start (ctor);
909 expand_function_start (ctor, 0);
910 /* Actually generate the code to call __gcov_init. */
911 gcov_info_address = force_reg (Pmode, XEXP (DECL_RTL (gcov_info), 0));
912 emit_library_call (gcov_init_libfunc, LCT_NORMAL, VOIDmode, 1,
913 gcov_info_address, Pmode);
915 expand_function_end ();
916 /* Create a dummy BLOCK. */
917 DECL_INITIAL (ctor) = make_node (BLOCK);
918 TREE_USED (DECL_INITIAL (ctor)) = 1;
920 rest_of_compilation (ctor);
922 if (! quiet_flag)
923 fflush (asm_out_file);
924 current_function_decl = NULL_TREE;
926 if (targetm.have_ctors_dtors)
927 (* targetm.asm_out.constructor) (XEXP (DECL_RTL (ctor), 0),
928 DEFAULT_INIT_PRIORITY);
931 /* Perform file-level initialization. Read in data file, generate name
932 of graph file. */
934 void
935 coverage_init (const char *filename)
937 int len = strlen (filename);
939 /* Name of da file. */
940 da_file_name = xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1);
941 strcpy (da_file_name, filename);
942 strcat (da_file_name, GCOV_DATA_SUFFIX);
944 /* Name of bbg file. */
945 bbg_file_name = xmalloc (len + strlen (GCOV_NOTE_SUFFIX) + 1);
946 strcpy (bbg_file_name, filename);
947 strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
949 read_counts_file ();
952 /* Performs file-level cleanup. Close graph file, generate coverage
953 variables and constructor. */
955 void
956 coverage_finish (void)
958 create_coverage ();
959 if (bbg_file_opened)
961 int error = gcov_close ();
963 if (error)
964 unlink (bbg_file_name);
965 if (!local_tick)
966 /* Only remove the da file, if we cannot stamp it. If we can
967 stamp it, libgcov will DTRT. */
968 unlink (da_file_name);
972 #include "gt-coverage.h"