2003-04-21 Aldy Hernandez <aldyh@redhat.com>
[official-gcc.git] / gcc / coverage.c
blob07c56a3ffc706518f4ea45b55625e46dab975f2e
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 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 const char *name; /* function name */
54 unsigned cfg_checksum; /* function checksum */
55 unsigned n_counter_sections; /* number of counter sections */
56 struct gcov_counter_section counter_sections[MAX_COUNTER_SECTIONS];
57 /* the sections */
60 /* Counts information for a function. */
61 typedef struct counts_entry
63 /* We hash by */
64 char *function_name;
65 unsigned section;
67 /* Store */
68 unsigned checksum;
69 unsigned n_counts;
70 gcov_type *counts;
71 unsigned merged;
72 gcov_type max_counter;
73 gcov_type max_counter_sum;
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;
83 /* Instantiate the profile info structure. */
85 struct profile_info profile_info;
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 /* The name of the count table. Used by the edge profiling code. */
99 static GTY(()) rtx profiler_label;
101 /* Forward declarations. */
102 static hashval_t htab_counts_entry_hash PARAMS ((const void *));
103 static int htab_counts_entry_eq PARAMS ((const void *, const void *));
104 static void htab_counts_entry_del PARAMS ((void *));
105 static void read_counts_file PARAMS ((void));
106 static unsigned compute_checksum PARAMS ((void));
107 static unsigned checksum_string PARAMS ((unsigned, const char *));
108 static void set_purpose PARAMS ((tree, tree));
109 static rtx label_for_tag PARAMS ((unsigned));
110 static tree build_counter_section_fields PARAMS ((void));
111 static tree build_counter_section_value PARAMS ((unsigned, unsigned));
112 static tree build_counter_section_data_fields PARAMS ((void));
113 static tree build_counter_section_data_value PARAMS ((unsigned, unsigned));
114 static tree build_function_info_fields PARAMS ((void));
115 static tree build_function_info_value PARAMS ((struct function_list *));
116 static tree build_gcov_info_fields PARAMS ((tree));
117 static tree build_gcov_info_value PARAMS ((void));
118 static void create_coverage PARAMS ((void));
121 static hashval_t
122 htab_counts_entry_hash (of)
123 const void *of;
125 const counts_entry_t *entry = of;
127 return htab_hash_string (entry->function_name) ^ entry->section;
130 static int
131 htab_counts_entry_eq (of1, of2)
132 const void *of1;
133 const void *of2;
135 const counts_entry_t *entry1 = of1;
136 const counts_entry_t *entry2 = of2;
138 return !strcmp (entry1->function_name, entry2->function_name)
139 && entry1->section == entry2->section;
142 static void
143 htab_counts_entry_del (of)
144 void *of;
146 counts_entry_t *entry = of;
148 free (entry->function_name);
149 free (entry->counts);
150 free (entry);
153 /* Read in the counts file, if available. */
155 static void
156 read_counts_file ()
158 char *function_name_buffer = NULL;
159 unsigned version, ix, checksum = -1;
160 counts_entry_t *summaried = NULL;
161 unsigned seen_summary = 0;
163 if (!gcov_open (da_file_name, 1))
164 return;
166 if (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 ((version = gcov_read_unsigned ()) != GCOV_VERSION)
174 char v[4], e[4];
175 unsigned required = GCOV_VERSION;
177 for (ix = 4; ix--; required >>= 8, version >>= 8)
179 v[ix] = version;
180 e[ix] = required;
182 warning ("`%s' is version `%.4s', expected version `%.4s'",
183 da_file_name, v, e);
184 gcov_close ();
185 return;
188 counts_hash = htab_create (10,
189 htab_counts_entry_hash, htab_counts_entry_eq,
190 htab_counts_entry_del);
191 while (!gcov_is_eof ())
193 unsigned tag, length;
194 unsigned long offset;
195 int error;
197 tag = gcov_read_unsigned ();
198 length = gcov_read_unsigned ();
199 offset = gcov_position ();
200 if (tag == GCOV_TAG_FUNCTION)
202 const char *string = gcov_read_string ();
203 free (function_name_buffer);
204 function_name_buffer = string ? xstrdup (string) : NULL;
205 checksum = gcov_read_unsigned ();
206 if (seen_summary)
208 /* We have already seen a summary, this means that this
209 new function begins a new set of program runs. We
210 must unlink the summaried chain. */
211 counts_entry_t *entry, *chain;
213 for (entry = summaried; entry; entry = chain)
215 chain = entry->chain;
217 entry->max_counter_sum += entry->max_counter;
218 entry->chain = NULL;
220 summaried = NULL;
221 seen_summary = 0;
224 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
226 counts_entry_t *entry;
227 struct gcov_summary summary;
229 gcov_read_summary (&summary);
230 seen_summary = 1;
231 for (entry = summaried; entry; entry = entry->chain)
233 entry->merged += summary.runs;
234 if (entry->max_counter < summary.arc_sum_max)
235 entry->max_counter = summary.arc_sum_max;
238 else if (GCOV_TAG_IS_SUBTAG (GCOV_TAG_FUNCTION, tag)
239 && function_name_buffer)
241 counts_entry_t **slot, *entry, elt;
242 unsigned n_counts = length / 8;
243 unsigned ix;
245 elt.function_name = function_name_buffer;
246 elt.section = tag;
248 slot = (counts_entry_t **) htab_find_slot
249 (counts_hash, &elt, INSERT);
250 entry = *slot;
251 if (!entry)
253 *slot = entry = xmalloc (sizeof (counts_entry_t));
254 entry->function_name = xstrdup (function_name_buffer);
255 entry->section = tag;
256 entry->checksum = checksum;
257 entry->n_counts = n_counts;
258 entry->counts = xcalloc (n_counts, sizeof (gcov_type));
260 else if (entry->checksum != checksum || entry->n_counts != n_counts)
262 warning ("profile mismatch for `%s'", function_name_buffer);
263 htab_delete (counts_hash);
264 break;
267 /* This should always be true for a just allocated entry,
268 and always false for an existing one. Check this way, in
269 case the gcov file is corrupt. */
270 if (!entry->chain || summaried != entry)
272 entry->chain = summaried;
273 summaried = entry;
275 for (ix = 0; ix != n_counts; ix++)
276 entry->counts[ix] += gcov_read_counter ();
278 gcov_seek (offset, length);
279 if ((error = gcov_is_error ()))
281 warning (error < 0 ? "`%s' has overflowed" : "`%s' is corrupted",
282 da_file_name);
283 htab_delete (counts_hash);
284 break;
288 free (function_name_buffer);
289 gcov_close ();
292 /* Returns the counters for a particular tag. */
294 gcov_type *
295 get_coverage_counts (unsigned tag, unsigned expected)
297 counts_entry_t *entry, elt;
299 profile_info.max_counter_in_program = 0;
300 profile_info.count_profiles_merged = 0;
302 /* No hash table, no counts. */
303 if (!counts_hash)
305 static int warned = 0;
307 if (!warned++)
308 warning ("file %s not found, execution counts assumed to be zero",
309 da_file_name);
310 return NULL;
313 elt.function_name
314 = (char *) IDENTIFIER_POINTER
315 (DECL_ASSEMBLER_NAME (current_function_decl));
316 elt.section = tag;
317 entry = htab_find (counts_hash, &elt);
318 if (!entry)
320 warning ("No profile for function '%s' found.", elt.function_name);
321 return 0;
324 if (expected != entry->n_counts
325 || compute_checksum () != entry->checksum)
327 warning ("profile mismatch for `%s'", elt.function_name);
328 return NULL;
331 profile_info.count_profiles_merged = entry->merged;
332 profile_info.max_counter_in_program = entry->max_counter_sum;
334 return entry->counts;
337 /* Generate a checksum for a string. CHKSUM is the current
338 checksum. */
340 static unsigned
341 checksum_string (unsigned chksum, const char *string)
345 unsigned value = *string << 24;
346 unsigned ix;
348 for (ix = 8; ix--; value <<= 1)
350 unsigned feedback;
352 feedback = (value ^ chksum) & 0x80000000 ? 0x04c11db7 : 0;
353 chksum <<= 1;
354 chksum ^= feedback;
357 while (*string++);
359 return chksum;
362 /* Compute checksum for the current function. We generate a CRC32. */
364 static unsigned
365 compute_checksum ()
367 unsigned chksum = DECL_SOURCE_LINE (current_function_decl);
369 chksum = checksum_string (chksum, DECL_SOURCE_FILE (current_function_decl));
370 chksum = checksum_string
371 (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
373 return chksum;
376 /* Begin output to the graph file for the current function.
377 Opens the output file, if not already done. Writes the
378 function header, if not already done. Returns non-zero if data
379 should be output. */
382 coverage_begin_output ()
384 if (!bbg_function_announced)
386 const char *file = DECL_SOURCE_FILE (current_function_decl);
387 unsigned line = DECL_SOURCE_LINE (current_function_decl);
388 unsigned long offset;
390 if (!bbg_file_opened)
392 if (!gcov_open (bbg_file_name, -1))
393 error ("cannot open %s", bbg_file_name);
394 else
396 gcov_write_unsigned (GCOV_GRAPH_MAGIC);
397 gcov_write_unsigned (GCOV_VERSION);
399 bbg_file_opened = 1;
402 /* Announce function */
403 offset = gcov_write_tag (GCOV_TAG_FUNCTION);
404 gcov_write_string (IDENTIFIER_POINTER
405 (DECL_ASSEMBLER_NAME (current_function_decl)));
406 gcov_write_unsigned (compute_checksum ());
407 gcov_write_string (file);
408 gcov_write_unsigned (line);
409 gcov_write_length (offset);
411 bbg_function_announced = 1;
413 return !gcov_is_error ();
416 /* Finish coverage data for the current function. Verify no output
417 error has occurred. Save function coverage counts. */
419 void
420 coverage_end_function ()
422 unsigned i;
424 if (bbg_file_opened > 1 && gcov_is_error ())
426 warning ("error writing `%s'", bbg_file_name);
427 bbg_file_opened = -1;
430 for (i = 0; i != profile_info.n_sections; i++)
431 if (profile_info.section_info[i].n_counters_now)
433 struct function_list *item;
435 /* ??? Probably should re-use the existing struct function. */
436 item = xmalloc (sizeof (struct function_list));
438 *functions_tail = item;
439 functions_tail = &item->next;
441 item->next = 0;
442 item->name = xstrdup (IDENTIFIER_POINTER
443 (DECL_ASSEMBLER_NAME (current_function_decl)));
444 item->cfg_checksum = compute_checksum ();
445 item->n_counter_sections = 0;
446 for (i = 0; i < profile_info.n_sections; i++)
447 if (profile_info.section_info[i].n_counters_now)
449 item->counter_sections[item->n_counter_sections].tag =
450 profile_info.section_info[i].tag;
451 item->counter_sections[item->n_counter_sections].n_counters =
452 profile_info.section_info[i].n_counters_now;
453 item->n_counter_sections++;
454 profile_info.section_info[i].n_counters
455 += profile_info.section_info[i].n_counters_now;
456 profile_info.section_info[i].n_counters_now = 0;
458 break;
460 bbg_function_announced = 0;
463 /* Set FIELDS as purpose to VALUE. */
464 static void
465 set_purpose (value, fields)
466 tree value;
467 tree fields;
469 tree act_field, act_value;
471 for (act_field = fields, act_value = value;
472 act_field;
473 act_field = TREE_CHAIN (act_field), act_value = TREE_CHAIN (act_value))
474 TREE_PURPOSE (act_value) = act_field;
477 /* Returns label for base of counters inside TAG section. */
478 static rtx
479 label_for_tag (tag)
480 unsigned tag;
482 switch (tag)
484 case GCOV_TAG_ARC_COUNTS:
485 return profiler_label;
486 default:
487 abort ();
491 /* Creates fields of struct counter_section (in gcov-io.h). */
492 static tree
493 build_counter_section_fields ()
495 tree field, fields;
497 /* tag */
498 fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
500 /* n_counters */
501 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
502 TREE_CHAIN (field) = fields;
503 fields = field;
505 return fields;
508 /* Creates value of struct counter_section (in gcov-io.h). */
509 static tree
510 build_counter_section_value (tag, n_counters)
511 unsigned tag;
512 unsigned n_counters;
514 tree value = NULL_TREE;
516 /* tag */
517 value = tree_cons (NULL_TREE,
518 convert (unsigned_type_node,
519 build_int_2 (tag, 0)),
520 value);
522 /* n_counters */
523 value = tree_cons (NULL_TREE,
524 convert (unsigned_type_node,
525 build_int_2 (n_counters, 0)),
526 value);
528 return value;
531 /* Creates fields of struct counter_section_data (in gcov-io.h). */
532 static tree
533 build_counter_section_data_fields ()
535 tree field, fields, gcov_type, gcov_ptr_type;
537 gcov_type = make_signed_type (GCOV_TYPE_SIZE);
538 gcov_ptr_type =
539 build_pointer_type (build_qualified_type (gcov_type,
540 TYPE_QUAL_CONST));
542 /* tag */
543 fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
545 /* n_counters */
546 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
547 TREE_CHAIN (field) = fields;
548 fields = field;
550 /* counters */
551 field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
552 TREE_CHAIN (field) = fields;
553 fields = field;
555 return fields;
558 /* Creates value of struct counter_section_data (in gcov-io.h). */
559 static tree
560 build_counter_section_data_value (tag, n_counters)
561 unsigned tag;
562 unsigned n_counters;
564 tree value = NULL_TREE, counts_table, gcov_type, gcov_ptr_type;
566 gcov_type = make_signed_type (GCOV_TYPE_SIZE);
567 gcov_ptr_type
568 = build_pointer_type (build_qualified_type
569 (gcov_type, TYPE_QUAL_CONST));
571 /* tag */
572 value = tree_cons (NULL_TREE,
573 convert (unsigned_type_node,
574 build_int_2 (tag, 0)),
575 value);
577 /* n_counters */
578 value = tree_cons (NULL_TREE,
579 convert (unsigned_type_node,
580 build_int_2 (n_counters, 0)),
581 value);
583 /* counters */
584 if (n_counters)
586 tree gcov_type_array_type =
587 build_array_type (gcov_type,
588 build_index_type (build_int_2 (n_counters - 1,
589 0)));
590 counts_table =
591 build (VAR_DECL, gcov_type_array_type, NULL_TREE, NULL_TREE);
592 TREE_STATIC (counts_table) = 1;
593 DECL_NAME (counts_table) = get_identifier (XSTR (label_for_tag (tag), 0));
594 assemble_variable (counts_table, 0, 0, 0);
595 counts_table = build1 (ADDR_EXPR, gcov_ptr_type, counts_table);
597 else
598 counts_table = null_pointer_node;
600 value = tree_cons (NULL_TREE, counts_table, value);
602 return value;
605 /* Creates fields for struct function_info type (in gcov-io.h). */
606 static tree
607 build_function_info_fields ()
609 tree field, fields, counter_section_fields, counter_section_type;
610 tree counter_sections_ptr_type;
611 tree string_type =
612 build_pointer_type (build_qualified_type (char_type_node,
613 TYPE_QUAL_CONST));
614 /* name */
615 fields = build_decl (FIELD_DECL, NULL_TREE, string_type);
617 /* checksum */
618 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
619 TREE_CHAIN (field) = fields;
620 fields = field;
622 /* n_counter_sections */
623 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
624 TREE_CHAIN (field) = fields;
625 fields = field;
627 /* counter_sections */
628 counter_section_fields = build_counter_section_fields ();
629 counter_section_type = (*lang_hooks.types.make_type) (RECORD_TYPE);
630 finish_builtin_struct (counter_section_type, "__counter_section",
631 counter_section_fields, NULL_TREE);
632 counter_sections_ptr_type =
633 build_pointer_type
634 (build_qualified_type (counter_section_type,
635 TYPE_QUAL_CONST));
636 field = build_decl (FIELD_DECL, NULL_TREE, counter_sections_ptr_type);
637 TREE_CHAIN (field) = fields;
638 fields = field;
640 return fields;
643 /* Creates value for struct function_info (in gcov-io.h). */
644 static tree
645 build_function_info_value (function)
646 struct function_list *function;
648 tree value = NULL_TREE;
649 size_t name_len = strlen (function->name);
650 tree fname = build_string (name_len + 1, function->name);
651 tree string_type =
652 build_pointer_type (build_qualified_type (char_type_node,
653 TYPE_QUAL_CONST));
654 tree counter_section_fields, counter_section_type, counter_sections_value;
655 tree counter_sections_ptr_type, counter_sections_array_type;
656 unsigned i;
658 /* name */
659 TREE_TYPE (fname) =
660 build_array_type (char_type_node,
661 build_index_type (build_int_2 (name_len, 0)));
662 value = tree_cons (NULL_TREE,
663 build1 (ADDR_EXPR,
664 string_type,
665 fname),
666 value);
668 /* checksum */
669 value = tree_cons (NULL_TREE,
670 convert (unsigned_type_node,
671 build_int_2 (function->cfg_checksum, 0)),
672 value);
674 /* n_counter_sections */
676 value = tree_cons (NULL_TREE,
677 convert (unsigned_type_node,
678 build_int_2 (function->n_counter_sections, 0)),
679 value);
681 /* counter_sections */
682 counter_section_fields = build_counter_section_fields ();
683 counter_section_type = (*lang_hooks.types.make_type) (RECORD_TYPE);
684 counter_sections_ptr_type =
685 build_pointer_type
686 (build_qualified_type (counter_section_type,
687 TYPE_QUAL_CONST));
688 counter_sections_array_type =
689 build_array_type (counter_section_type,
690 build_index_type (
691 build_int_2 (function->n_counter_sections - 1,
692 0)));
694 counter_sections_value = NULL_TREE;
695 for (i = 0; i < function->n_counter_sections; i++)
697 tree counter_section_value
698 = build_counter_section_value (function->counter_sections[i].tag,
699 function->counter_sections[i].n_counters);
700 set_purpose (counter_section_value, counter_section_fields);
701 counter_sections_value =
702 tree_cons (NULL_TREE,
703 build_constructor (counter_section_type,
704 nreverse (counter_section_value)),
705 counter_sections_value);
707 finish_builtin_struct (counter_section_type, "__counter_section",
708 counter_section_fields, NULL_TREE);
710 if (function->n_counter_sections)
712 counter_sections_value =
713 build_constructor (counter_sections_array_type,
714 nreverse (counter_sections_value)),
715 counter_sections_value = build1 (ADDR_EXPR,
716 counter_sections_ptr_type,
717 counter_sections_value);
719 else
720 counter_sections_value = null_pointer_node;
722 value = tree_cons (NULL_TREE, counter_sections_value, value);
724 return value;
727 /* Creates fields of struct gcov_info type (in gcov-io.h). */
728 static tree
729 build_gcov_info_fields (gcov_info_type)
730 tree gcov_info_type;
732 tree field, fields;
733 char *filename;
734 int filename_len;
735 tree string_type =
736 build_pointer_type (build_qualified_type (char_type_node,
737 TYPE_QUAL_CONST));
738 tree function_info_fields, function_info_type, function_info_ptr_type;
739 tree counter_section_data_fields, counter_section_data_type;
740 tree counter_section_data_ptr_type;
742 /* Version ident */
743 fields = build_decl (FIELD_DECL, NULL_TREE, long_unsigned_type_node);
745 /* next -- NULL */
746 field = build_decl (FIELD_DECL, NULL_TREE,
747 build_pointer_type
748 (build_qualified_type
749 (gcov_info_type, TYPE_QUAL_CONST)));
750 TREE_CHAIN (field) = fields;
751 fields = field;
753 /* Filename */
754 filename = getpwd ();
755 filename = (filename && da_file_name[0] != '/'
756 ? concat (filename, "/", da_file_name, NULL)
757 : da_file_name);
758 filename_len = strlen (filename);
759 if (filename != da_file_name)
760 free (filename);
762 field = build_decl (FIELD_DECL, NULL_TREE, string_type);
763 TREE_CHAIN (field) = fields;
764 fields = field;
766 /* Workspace */
767 field = build_decl (FIELD_DECL, NULL_TREE, long_integer_type_node);
768 TREE_CHAIN (field) = fields;
769 fields = field;
771 /* number of functions */
772 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
773 TREE_CHAIN (field) = fields;
774 fields = field;
776 /* function_info table */
777 function_info_fields = build_function_info_fields ();
778 function_info_type = (*lang_hooks.types.make_type) (RECORD_TYPE);
779 finish_builtin_struct (function_info_type, "__function_info",
780 function_info_fields, NULL_TREE);
781 function_info_ptr_type =
782 build_pointer_type
783 (build_qualified_type (function_info_type,
784 TYPE_QUAL_CONST));
785 field = build_decl (FIELD_DECL, NULL_TREE, function_info_ptr_type);
786 TREE_CHAIN (field) = fields;
787 fields = field;
789 /* n_counter_sections */
790 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
791 TREE_CHAIN (field) = fields;
792 fields = field;
794 /* counter sections */
795 counter_section_data_fields = build_counter_section_data_fields ();
796 counter_section_data_type = (*lang_hooks.types.make_type) (RECORD_TYPE);
797 finish_builtin_struct (counter_section_data_type, "__counter_section_data",
798 counter_section_data_fields, NULL_TREE);
799 counter_section_data_ptr_type =
800 build_pointer_type
801 (build_qualified_type (counter_section_data_type,
802 TYPE_QUAL_CONST));
803 field = build_decl (FIELD_DECL, NULL_TREE, counter_section_data_ptr_type);
804 TREE_CHAIN (field) = fields;
805 fields = field;
807 return fields;
810 /* Creates struct gcov_info value (in gcov-io.h). */
811 static tree
812 build_gcov_info_value ()
814 tree value = NULL_TREE;
815 tree filename_string;
816 char *filename;
817 int filename_len;
818 unsigned n_functions, i;
819 struct function_list *item;
820 tree string_type =
821 build_pointer_type (build_qualified_type (char_type_node,
822 TYPE_QUAL_CONST));
823 tree function_info_fields, function_info_type, function_info_ptr_type;
824 tree functions;
825 tree counter_section_data_fields, counter_section_data_type;
826 tree counter_section_data_ptr_type, counter_sections;
828 /* Version ident */
829 value = tree_cons (NULL_TREE,
830 convert (long_unsigned_type_node,
831 build_int_2 (GCOV_VERSION, 0)),
832 value);
834 /* next -- NULL */
835 value = tree_cons (NULL_TREE, null_pointer_node, value);
837 /* Filename */
838 filename = getpwd ();
839 filename = (filename && da_file_name[0] != '/'
840 ? concat (filename, "/", da_file_name, NULL)
841 : da_file_name);
842 filename_len = strlen (filename);
843 filename_string = build_string (filename_len + 1, filename);
844 if (filename != da_file_name)
845 free (filename);
846 TREE_TYPE (filename_string) =
847 build_array_type (char_type_node,
848 build_index_type (build_int_2 (filename_len, 0)));
849 value = tree_cons (NULL_TREE,
850 build1 (ADDR_EXPR,
851 string_type,
852 filename_string),
853 value);
855 /* Workspace */
856 value = tree_cons (NULL_TREE,
857 convert (long_integer_type_node, integer_zero_node),
858 value);
860 /* number of functions */
861 n_functions = 0;
862 for (item = functions_head; item != 0; item = item->next, n_functions++)
863 continue;
864 value = tree_cons (NULL_TREE,
865 convert (unsigned_type_node,
866 build_int_2 (n_functions, 0)),
867 value);
869 /* function_info table */
870 function_info_fields = build_function_info_fields ();
871 function_info_type = (*lang_hooks.types.make_type) (RECORD_TYPE);
872 function_info_ptr_type =
873 build_pointer_type (
874 build_qualified_type (function_info_type,
875 TYPE_QUAL_CONST));
876 functions = NULL_TREE;
877 for (item = functions_head; item != 0; item = item->next)
879 tree function_info_value = build_function_info_value (item);
880 set_purpose (function_info_value, function_info_fields);
881 functions
882 = tree_cons (NULL_TREE,
883 build_constructor (function_info_type,
884 nreverse (function_info_value)),
885 functions);
887 finish_builtin_struct (function_info_type, "__function_info",
888 function_info_fields, NULL_TREE);
890 /* Create constructor for array. */
891 if (n_functions)
893 tree array_type;
895 array_type = build_array_type (
896 function_info_type,
897 build_index_type (build_int_2 (n_functions - 1, 0)));
898 functions = build_constructor (array_type, nreverse (functions));
899 functions = build1 (ADDR_EXPR,
900 function_info_ptr_type,
901 functions);
903 else
904 functions = null_pointer_node;
906 value = tree_cons (NULL_TREE, functions, value);
908 /* n_counter_sections */
909 value = tree_cons (NULL_TREE,
910 convert (unsigned_type_node,
911 build_int_2 (profile_info.n_sections, 0)),
912 value);
914 /* counter sections */
915 counter_section_data_fields = build_counter_section_data_fields ();
916 counter_section_data_type = (*lang_hooks.types.make_type) (RECORD_TYPE);
917 counter_sections = NULL_TREE;
918 for (i = 0; i < profile_info.n_sections; i++)
920 tree counter_sections_value =
921 build_counter_section_data_value (
922 profile_info.section_info[i].tag,
923 profile_info.section_info[i].n_counters);
924 set_purpose (counter_sections_value, counter_section_data_fields);
925 counter_sections =
926 tree_cons (NULL_TREE,
927 build_constructor (counter_section_data_type,
928 nreverse (counter_sections_value)),
929 counter_sections);
931 finish_builtin_struct (counter_section_data_type, "__counter_section_data",
932 counter_section_data_fields, NULL_TREE);
933 counter_section_data_ptr_type =
934 build_pointer_type
935 (build_qualified_type (counter_section_data_type,
936 TYPE_QUAL_CONST));
938 if (profile_info.n_sections)
940 tree cst_type = build_index_type (build_int_2 (profile_info.n_sections-1,
941 0));
942 cst_type = build_array_type (counter_section_data_type, cst_type);
943 counter_sections = build_constructor (cst_type,
944 nreverse (counter_sections));
945 counter_sections = build1 (ADDR_EXPR,
946 counter_section_data_ptr_type,
947 counter_sections);
949 else
950 counter_sections = null_pointer_node;
951 value = tree_cons (NULL_TREE, counter_sections, value);
953 return value;
956 /* Write out the structure which libgcc uses to locate all the arc
957 counters. The structures used here must match those defined in
958 gcov-io.h. Write out the constructor to call __gcov_init. */
960 static void
961 create_coverage ()
963 tree gcov_info_fields, gcov_info_type, gcov_info_value, gcov_info;
964 char name[20];
965 char *ctor_name;
966 tree ctor;
967 rtx gcov_info_address;
968 int save_flag_inline_functions = flag_inline_functions;
969 unsigned i;
971 for (i = 0; i < profile_info.n_sections; i++)
972 if (profile_info.section_info[i].n_counters)
973 break;
974 if (i == profile_info.n_sections)
975 return;
977 gcov_info_type = (*lang_hooks.types.make_type) (RECORD_TYPE);
978 gcov_info_fields = build_gcov_info_fields (gcov_info_type);
979 gcov_info_value = build_gcov_info_value ();
980 set_purpose (gcov_info_value, gcov_info_fields);
981 finish_builtin_struct (gcov_info_type, "__gcov_info",
982 gcov_info_fields, NULL_TREE);
984 gcov_info = build (VAR_DECL, gcov_info_type, NULL_TREE, NULL_TREE);
985 DECL_INITIAL (gcov_info) =
986 build_constructor (gcov_info_type, nreverse (gcov_info_value));
988 TREE_STATIC (gcov_info) = 1;
989 ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 0);
990 DECL_NAME (gcov_info) = get_identifier (name);
992 /* Build structure. */
993 assemble_variable (gcov_info, 0, 0, 0);
995 /* Build the constructor function to invoke __gcov_init. */
996 ctor_name = concat (IDENTIFIER_POINTER (get_file_function_name ('I')),
997 "_GCOV", NULL);
998 ctor = build_decl (FUNCTION_DECL, get_identifier (ctor_name),
999 build_function_type (void_type_node, NULL_TREE));
1000 free (ctor_name);
1001 DECL_EXTERNAL (ctor) = 0;
1003 /* It can be a static function as long as collect2 does not have
1004 to scan the object file to find its ctor/dtor routine. */
1005 TREE_PUBLIC (ctor) = ! targetm.have_ctors_dtors;
1006 TREE_USED (ctor) = 1;
1007 DECL_RESULT (ctor) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
1009 ctor = (*lang_hooks.decls.pushdecl) (ctor);
1010 rest_of_decl_compilation (ctor, 0, 1, 0);
1011 announce_function (ctor);
1012 current_function_decl = ctor;
1013 DECL_INITIAL (ctor) = error_mark_node;
1014 make_decl_rtl (ctor, NULL);
1015 init_function_start (ctor, input_filename, lineno);
1016 (*lang_hooks.decls.pushlevel) (0);
1017 expand_function_start (ctor, 0);
1018 cfun->arc_profile = 0;
1020 /* Actually generate the code to call __gcov_init. */
1021 gcov_info_address = force_reg (Pmode, XEXP (DECL_RTL (gcov_info), 0));
1022 emit_library_call (gcov_init_libfunc, LCT_NORMAL, VOIDmode, 1,
1023 gcov_info_address, Pmode);
1025 expand_function_end (input_filename, lineno, 0);
1026 (*lang_hooks.decls.poplevel) (1, 0, 1);
1028 /* Since ctor isn't in the list of globals, it would never be emitted
1029 when it's considered to be 'safe' for inlining, so turn off
1030 flag_inline_functions. */
1031 flag_inline_functions = 0;
1033 rest_of_compilation (ctor);
1035 /* Reset flag_inline_functions to its original value. */
1036 flag_inline_functions = save_flag_inline_functions;
1038 if (! quiet_flag)
1039 fflush (asm_out_file);
1040 current_function_decl = NULL_TREE;
1042 if (targetm.have_ctors_dtors)
1043 (* targetm.asm_out.constructor) (XEXP (DECL_RTL (ctor), 0),
1044 DEFAULT_INIT_PRIORITY);
1047 /* Find (and create if not present) a section with TAG for the current
1048 function. */
1049 struct section_info *
1050 find_counters_section (tag)
1051 unsigned tag;
1053 unsigned i;
1055 for (i = 0; i < profile_info.n_sections; i++)
1056 if (profile_info.section_info[i].tag == tag)
1057 return profile_info.section_info + i;
1059 if (i == MAX_COUNTER_SECTIONS)
1060 abort ();
1062 profile_info.section_info[i].tag = tag;
1063 profile_info.section_info[i].present = 0;
1064 profile_info.section_info[i].n_counters = 0;
1065 profile_info.section_info[i].n_counters_now = 0;
1066 profile_info.n_sections++;
1068 return profile_info.section_info + i;
1071 /* Generate a MEM rtl to access counter NO in counter section TAG. */
1074 coverage_counter_ref (unsigned tag, unsigned no)
1076 enum machine_mode mode = mode_for_size (GCOV_TYPE_SIZE, MODE_INT, 0);
1077 struct section_info *sect = find_counters_section (tag);
1078 rtx ref;
1080 if (!profiler_label)
1082 /* Generate and save a copy of this so it can be shared. */
1083 char buf[20];
1085 ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", 2);
1086 profiler_label = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
1088 if (no + 1 > (unsigned) sect->n_counters_now)
1089 sect->n_counters_now = no + 1;
1091 no += sect->n_counters;
1092 ref = plus_constant (profiler_label, GCOV_TYPE_SIZE / BITS_PER_UNIT * no);
1093 ref = gen_rtx_MEM (mode, ref);
1094 set_mem_alias_set (ref, new_alias_set ());
1096 return ref;
1100 /* Perform file-level initialization. Read in data file, generate name
1101 of graph file. */
1103 void
1104 coverage_init (filename)
1105 const char *filename;
1107 int len = strlen (filename);
1109 da_file_name = (char *) xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1);
1110 strcpy (da_file_name, filename);
1111 strcat (da_file_name, GCOV_DATA_SUFFIX);
1113 read_counts_file ();
1115 /* Open the bbg output file. */
1116 bbg_file_name = (char *) xmalloc (len + strlen (GCOV_GRAPH_SUFFIX) + 1);
1117 strcpy (bbg_file_name, filename);
1118 strcat (bbg_file_name, GCOV_GRAPH_SUFFIX);
1121 /* Performs file-level cleanup. Close graph file, generate coverage
1122 variables and constructor. */
1124 void
1125 coverage_finish ()
1127 create_coverage ();
1128 if (bbg_file_opened)
1130 int error = gcov_close ();
1132 if (error)
1133 unlink (bbg_file_name);
1134 #if SELF_COVERAGE
1135 /* If the compiler is instrumented, we should not
1136 unconditionally remove the counts file, because we might be
1137 recompiling ourselves. The .da files are all removed during
1138 copying the stage1 files. */
1139 if (error)
1140 #endif
1141 unlink (da_file_name);
1146 #include "gt-coverage.h"