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
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
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
31 #include "coretypes.h"
45 #include "langhooks.h"
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
];
60 /* Counts information for a function. */
61 typedef struct counts_entry
72 gcov_type max_counter
;
73 gcov_type max_counter_sum
;
76 struct counts_entry
*chain
;
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));
122 htab_counts_entry_hash (of
)
125 const counts_entry_t
*entry
= of
;
127 return htab_hash_string (entry
->function_name
) ^ entry
->section
;
131 htab_counts_entry_eq (of1
, 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
;
143 htab_counts_entry_del (of
)
146 counts_entry_t
*entry
= of
;
148 free (entry
->function_name
);
149 free (entry
->counts
);
153 /* Read in the counts file, if available. */
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))
166 if (gcov_read_unsigned () != GCOV_DATA_MAGIC
)
168 warning ("`%s' is not a gcov data file", da_file_name
);
172 else if ((version
= gcov_read_unsigned ()) != GCOV_VERSION
)
175 unsigned required
= GCOV_VERSION
;
177 for (ix
= 4; ix
--; required
>>= 8, version
>>= 8)
182 warning ("`%s' is version `%.4s', expected version `%.4s'",
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
;
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 ();
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
;
224 else if (tag
== GCOV_TAG_PROGRAM_SUMMARY
)
226 counts_entry_t
*entry
;
227 struct gcov_summary summary
;
229 gcov_read_summary (&summary
);
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;
245 elt
.function_name
= function_name_buffer
;
248 slot
= (counts_entry_t
**) htab_find_slot
249 (counts_hash
, &elt
, INSERT
);
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
);
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
;
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",
283 htab_delete (counts_hash
);
288 free (function_name_buffer
);
292 /* Returns the counters for a particular tag. */
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. */
305 static int warned
= 0;
308 warning ("file %s not found, execution counts assumed to be zero",
314 = (char *) IDENTIFIER_POINTER
315 (DECL_ASSEMBLER_NAME (current_function_decl
));
317 entry
= htab_find (counts_hash
, &elt
);
320 warning ("No profile for function '%s' found.", elt
.function_name
);
324 if (expected
!= entry
->n_counts
325 || compute_checksum () != entry
->checksum
)
327 warning ("profile mismatch for `%s'", elt
.function_name
);
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
341 checksum_string (unsigned chksum
, const char *string
)
345 unsigned value
= *string
<< 24;
348 for (ix
= 8; ix
--; value
<<= 1)
352 feedback
= (value
^ chksum
) & 0x80000000 ? 0x04c11db7 : 0;
362 /* Compute checksum for the current function. We generate a CRC32. */
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
)));
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
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
);
396 gcov_write_unsigned (GCOV_GRAPH_MAGIC
);
397 gcov_write_unsigned (GCOV_VERSION
);
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. */
420 coverage_end_function ()
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
;
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;
460 bbg_function_announced
= 0;
463 /* Set FIELDS as purpose to VALUE. */
465 set_purpose (value
, fields
)
469 tree act_field
, act_value
;
471 for (act_field
= fields
, act_value
= value
;
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. */
484 case GCOV_TAG_ARC_COUNTS
:
485 return profiler_label
;
491 /* Creates fields of struct counter_section (in gcov-io.h). */
493 build_counter_section_fields ()
498 fields
= build_decl (FIELD_DECL
, NULL_TREE
, unsigned_type_node
);
501 field
= build_decl (FIELD_DECL
, NULL_TREE
, unsigned_type_node
);
502 TREE_CHAIN (field
) = fields
;
508 /* Creates value of struct counter_section (in gcov-io.h). */
510 build_counter_section_value (tag
, n_counters
)
514 tree value
= NULL_TREE
;
517 value
= tree_cons (NULL_TREE
,
518 convert (unsigned_type_node
,
519 build_int_2 (tag
, 0)),
523 value
= tree_cons (NULL_TREE
,
524 convert (unsigned_type_node
,
525 build_int_2 (n_counters
, 0)),
531 /* Creates fields of struct counter_section_data (in gcov-io.h). */
533 build_counter_section_data_fields ()
535 tree field
, fields
, gcov_type
, gcov_ptr_type
;
537 gcov_type
= make_signed_type (GCOV_TYPE_SIZE
);
539 build_pointer_type (build_qualified_type (gcov_type
,
543 fields
= build_decl (FIELD_DECL
, NULL_TREE
, unsigned_type_node
);
546 field
= build_decl (FIELD_DECL
, NULL_TREE
, unsigned_type_node
);
547 TREE_CHAIN (field
) = fields
;
551 field
= build_decl (FIELD_DECL
, NULL_TREE
, gcov_ptr_type
);
552 TREE_CHAIN (field
) = fields
;
558 /* Creates value of struct counter_section_data (in gcov-io.h). */
560 build_counter_section_data_value (tag
, n_counters
)
564 tree value
= NULL_TREE
, counts_table
, gcov_type
, gcov_ptr_type
;
566 gcov_type
= make_signed_type (GCOV_TYPE_SIZE
);
568 = build_pointer_type (build_qualified_type
569 (gcov_type
, TYPE_QUAL_CONST
));
572 value
= tree_cons (NULL_TREE
,
573 convert (unsigned_type_node
,
574 build_int_2 (tag
, 0)),
578 value
= tree_cons (NULL_TREE
,
579 convert (unsigned_type_node
,
580 build_int_2 (n_counters
, 0)),
586 tree gcov_type_array_type
=
587 build_array_type (gcov_type
,
588 build_index_type (build_int_2 (n_counters
- 1,
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
);
598 counts_table
= null_pointer_node
;
600 value
= tree_cons (NULL_TREE
, counts_table
, value
);
605 /* Creates fields for struct function_info type (in gcov-io.h). */
607 build_function_info_fields ()
609 tree field
, fields
, counter_section_fields
, counter_section_type
;
610 tree counter_sections_ptr_type
;
612 build_pointer_type (build_qualified_type (char_type_node
,
615 fields
= build_decl (FIELD_DECL
, NULL_TREE
, string_type
);
618 field
= build_decl (FIELD_DECL
, NULL_TREE
, unsigned_type_node
);
619 TREE_CHAIN (field
) = fields
;
622 /* n_counter_sections */
623 field
= build_decl (FIELD_DECL
, NULL_TREE
, unsigned_type_node
);
624 TREE_CHAIN (field
) = fields
;
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
=
634 (build_qualified_type (counter_section_type
,
636 field
= build_decl (FIELD_DECL
, NULL_TREE
, counter_sections_ptr_type
);
637 TREE_CHAIN (field
) = fields
;
643 /* Creates value for struct function_info (in gcov-io.h). */
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
);
652 build_pointer_type (build_qualified_type (char_type_node
,
654 tree counter_section_fields
, counter_section_type
, counter_sections_value
;
655 tree counter_sections_ptr_type
, counter_sections_array_type
;
660 build_array_type (char_type_node
,
661 build_index_type (build_int_2 (name_len
, 0)));
662 value
= tree_cons (NULL_TREE
,
669 value
= tree_cons (NULL_TREE
,
670 convert (unsigned_type_node
,
671 build_int_2 (function
->cfg_checksum
, 0)),
674 /* n_counter_sections */
676 value
= tree_cons (NULL_TREE
,
677 convert (unsigned_type_node
,
678 build_int_2 (function
->n_counter_sections
, 0)),
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
=
686 (build_qualified_type (counter_section_type
,
688 counter_sections_array_type
=
689 build_array_type (counter_section_type
,
691 build_int_2 (function
->n_counter_sections
- 1,
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
);
720 counter_sections_value
= null_pointer_node
;
722 value
= tree_cons (NULL_TREE
, counter_sections_value
, value
);
727 /* Creates fields of struct gcov_info type (in gcov-io.h). */
729 build_gcov_info_fields (gcov_info_type
)
736 build_pointer_type (build_qualified_type (char_type_node
,
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
;
743 fields
= build_decl (FIELD_DECL
, NULL_TREE
, long_unsigned_type_node
);
746 field
= build_decl (FIELD_DECL
, NULL_TREE
,
748 (build_qualified_type
749 (gcov_info_type
, TYPE_QUAL_CONST
)));
750 TREE_CHAIN (field
) = fields
;
754 filename
= getpwd ();
755 filename
= (filename
&& da_file_name
[0] != '/'
756 ? concat (filename
, "/", da_file_name
, NULL
)
758 filename_len
= strlen (filename
);
759 if (filename
!= da_file_name
)
762 field
= build_decl (FIELD_DECL
, NULL_TREE
, string_type
);
763 TREE_CHAIN (field
) = fields
;
767 field
= build_decl (FIELD_DECL
, NULL_TREE
, long_integer_type_node
);
768 TREE_CHAIN (field
) = fields
;
771 /* number of functions */
772 field
= build_decl (FIELD_DECL
, NULL_TREE
, unsigned_type_node
);
773 TREE_CHAIN (field
) = fields
;
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
=
783 (build_qualified_type (function_info_type
,
785 field
= build_decl (FIELD_DECL
, NULL_TREE
, function_info_ptr_type
);
786 TREE_CHAIN (field
) = fields
;
789 /* n_counter_sections */
790 field
= build_decl (FIELD_DECL
, NULL_TREE
, unsigned_type_node
);
791 TREE_CHAIN (field
) = fields
;
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
=
801 (build_qualified_type (counter_section_data_type
,
803 field
= build_decl (FIELD_DECL
, NULL_TREE
, counter_section_data_ptr_type
);
804 TREE_CHAIN (field
) = fields
;
810 /* Creates struct gcov_info value (in gcov-io.h). */
812 build_gcov_info_value ()
814 tree value
= NULL_TREE
;
815 tree filename_string
;
818 unsigned n_functions
, i
;
819 struct function_list
*item
;
821 build_pointer_type (build_qualified_type (char_type_node
,
823 tree function_info_fields
, function_info_type
, function_info_ptr_type
;
825 tree counter_section_data_fields
, counter_section_data_type
;
826 tree counter_section_data_ptr_type
, counter_sections
;
829 value
= tree_cons (NULL_TREE
,
830 convert (long_unsigned_type_node
,
831 build_int_2 (GCOV_VERSION
, 0)),
835 value
= tree_cons (NULL_TREE
, null_pointer_node
, value
);
838 filename
= getpwd ();
839 filename
= (filename
&& da_file_name
[0] != '/'
840 ? concat (filename
, "/", da_file_name
, NULL
)
842 filename_len
= strlen (filename
);
843 filename_string
= build_string (filename_len
+ 1, filename
);
844 if (filename
!= da_file_name
)
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
,
856 value
= tree_cons (NULL_TREE
,
857 convert (long_integer_type_node
, integer_zero_node
),
860 /* number of functions */
862 for (item
= functions_head
; item
!= 0; item
= item
->next
, n_functions
++)
864 value
= tree_cons (NULL_TREE
,
865 convert (unsigned_type_node
,
866 build_int_2 (n_functions
, 0)),
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
=
874 build_qualified_type (function_info_type
,
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
);
882 = tree_cons (NULL_TREE
,
883 build_constructor (function_info_type
,
884 nreverse (function_info_value
)),
887 finish_builtin_struct (function_info_type
, "__function_info",
888 function_info_fields
, NULL_TREE
);
890 /* Create constructor for array. */
895 array_type
= build_array_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
,
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)),
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
);
926 tree_cons (NULL_TREE
,
927 build_constructor (counter_section_data_type
,
928 nreverse (counter_sections_value
)),
931 finish_builtin_struct (counter_section_data_type
, "__counter_section_data",
932 counter_section_data_fields
, NULL_TREE
);
933 counter_section_data_ptr_type
=
935 (build_qualified_type (counter_section_data_type
,
938 if (profile_info
.n_sections
)
940 tree cst_type
= build_index_type (build_int_2 (profile_info
.n_sections
-1,
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
,
950 counter_sections
= null_pointer_node
;
951 value
= tree_cons (NULL_TREE
, counter_sections
, 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. */
963 tree gcov_info_fields
, gcov_info_type
, gcov_info_value
, gcov_info
;
967 rtx gcov_info_address
;
968 int save_flag_inline_functions
= flag_inline_functions
;
971 for (i
= 0; i
< profile_info
.n_sections
; i
++)
972 if (profile_info
.section_info
[i
].n_counters
)
974 if (i
== profile_info
.n_sections
)
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')),
998 ctor
= build_decl (FUNCTION_DECL
, get_identifier (ctor_name
),
999 build_function_type (void_type_node
, NULL_TREE
));
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
;
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
1049 struct section_info
*
1050 find_counters_section (tag
)
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
)
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
);
1080 if (!profiler_label
)
1082 /* Generate and save a copy of this so it can be shared. */
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 ());
1100 /* Perform file-level initialization. Read in data file, generate name
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. */
1128 if (bbg_file_opened
)
1130 int error
= gcov_close ();
1133 unlink (bbg_file_name
);
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. */
1141 unlink (da_file_name
);
1146 #include "gt-coverage.h"