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 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
68 struct gcov_ctr_summary summary
;
71 struct counts_entry
*chain
;
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 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);
122 htab_counts_entry_hash (const void *of
)
124 const counts_entry_t
*entry
= of
;
126 return entry
->ident
* GCOV_COUNTERS
+ entry
->ctr
;
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
;
139 htab_counts_entry_del (void *of
)
141 counts_entry_t
*entry
= of
;
143 free (entry
->counts
);
147 /* Read in the counts file, if available. */
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;
159 if (!gcov_open (da_file_name
, 1))
162 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC
))
164 warning ("`%s' is not a gcov data file", da_file_name
);
168 else if ((tag
= gcov_read_unsigned ()) != GCOV_VERSION
)
172 GCOV_UNSIGNED2STRING (v
, tag
);
173 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
175 warning ("`%s' is version `%.4s', expected version `%.4s'",
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 ();
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
;
214 else if (tag
== GCOV_TAG_PROGRAM_SUMMARY
)
216 counts_entry_t
*entry
;
217 struct gcov_summary summary
;
219 gcov_read_summary (&summary
);
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
);
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
);
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
254 || entry
->summary
.num
!= n_counts
)
256 warning ("coverage mismatch for function %u", fn_ident
);
257 htab_delete (counts_hash
);
260 else if (elt
.ctr
>= GCOV_COUNTERS_SUMMABLE
)
262 warning ("cannot merge separate %s counters for function %u",
263 ctr_names
[elt
.ctr
], fn_ident
);
267 if (elt
.ctr
< GCOV_COUNTERS_SUMMABLE
268 /* This should always be true for a just allocated entry,
269 and always false for an existing one. Check this way, in
270 case the gcov file is corrupt. */
271 && (!entry
->chain
|| summaried
!= entry
))
273 entry
->chain
= summaried
;
276 for (ix
= 0; ix
!= n_counts
; ix
++)
277 entry
->counts
[ix
] += gcov_read_counter ();
280 gcov_sync (offset
, length
);
281 if ((error
= gcov_is_error ()))
287 warning (error
< 0 ? "`%s' has overflowed" : "`%s' is corrupted",
289 htab_delete (counts_hash
);
295 /* Returns the counters for a particular tag. */
298 get_coverage_counts (unsigned counter
, unsigned expected
,
299 const struct gcov_ctr_summary
**summary
)
301 counts_entry_t
*entry
, elt
;
303 /* No hash table, no counts. */
306 static int warned
= 0;
309 warning ("file %s not found, execution counts assumed to be zero",
314 elt
.ident
= current_function_funcdef_no
+ 1;
316 entry
= htab_find (counts_hash
, &elt
);
319 warning ("no coverage for function '%s' found.", IDENTIFIER_POINTER
320 (DECL_ASSEMBLER_NAME (current_function_decl
)));
324 if (expected
!= entry
->summary
.num
325 || compute_checksum () != entry
->checksum
)
327 warning ("coverage mismatch for `%s'", IDENTIFIER_POINTER
328 (DECL_ASSEMBLER_NAME (current_function_decl
)));
333 *summary
= &entry
->summary
;
335 return entry
->counts
;
338 /* Allocate NUM counters of type COUNTER. Returns nonzero if the
339 allocation succeeded. */
342 coverage_counter_alloc (unsigned counter
, unsigned num
)
350 if (!ctr_labels
[counter
])
352 /* Generate and save a copy of this so it can be shared. */
355 ASM_GENERATE_INTERNAL_LABEL (buf
, "LPBX", counter
+ 1);
356 ctr_labels
[counter
] = gen_rtx_SYMBOL_REF (Pmode
, ggc_strdup (buf
));
358 fn_b_ctrs
[counter
] = fn_n_ctrs
[counter
];
359 fn_n_ctrs
[counter
] += num
;
360 fn_ctr_mask
|= 1 << counter
;
364 /* Generate a MEM rtl to access COUNTER NO. */
367 coverage_counter_ref (unsigned counter
, unsigned no
)
369 unsigned gcov_size
= tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE
), 1);
370 enum machine_mode mode
= mode_for_size (gcov_size
, MODE_INT
, 0);
373 if (no
>= fn_n_ctrs
[counter
] - fn_b_ctrs
[counter
])
375 no
+= prg_n_ctrs
[counter
] + fn_b_ctrs
[counter
];
376 ref
= plus_constant (ctr_labels
[counter
], gcov_size
/ BITS_PER_UNIT
* no
);
377 ref
= gen_rtx_MEM (mode
, ref
);
378 set_mem_alias_set (ref
, new_alias_set ());
383 /* Generate a checksum for a string. CHKSUM is the current
387 checksum_string (unsigned chksum
, const char *string
)
391 unsigned value
= *string
<< 24;
394 for (ix
= 8; ix
--; value
<<= 1)
398 feedback
= (value
^ chksum
) & 0x80000000 ? 0x04c11db7 : 0;
408 /* Compute checksum for the current function. We generate a CRC32. */
411 compute_checksum (void)
413 unsigned chksum
= DECL_SOURCE_LINE (current_function_decl
);
415 chksum
= checksum_string (chksum
, DECL_SOURCE_FILE (current_function_decl
));
416 chksum
= checksum_string
417 (chksum
, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl
)));
422 /* Begin output to the graph file for the current function.
423 Opens the output file, if not already done. Writes the
424 function header, if not already done. Returns nonzero if data
428 coverage_begin_output (void)
433 if (!bbg_function_announced
)
435 const char *file
= DECL_SOURCE_FILE (current_function_decl
);
436 unsigned line
= DECL_SOURCE_LINE (current_function_decl
);
437 unsigned long offset
;
439 if (!bbg_file_opened
)
441 if (!gcov_open (bbg_file_name
, -1))
442 error ("cannot open %s", bbg_file_name
);
445 gcov_write_unsigned (GCOV_NOTE_MAGIC
);
446 gcov_write_unsigned (GCOV_VERSION
);
447 gcov_write_unsigned (local_tick
);
452 /* Announce function */
453 offset
= gcov_write_tag (GCOV_TAG_FUNCTION
);
454 gcov_write_unsigned (current_function_funcdef_no
+ 1);
455 gcov_write_unsigned (compute_checksum ());
456 gcov_write_string (IDENTIFIER_POINTER
457 (DECL_ASSEMBLER_NAME (current_function_decl
)));
458 gcov_write_string (file
);
459 gcov_write_unsigned (line
);
460 gcov_write_length (offset
);
462 bbg_function_announced
= 1;
464 return !gcov_is_error ();
467 /* Finish coverage data for the current function. Verify no output
468 error has occurred. Save function coverage counts. */
471 coverage_end_function (void)
475 if (bbg_file_opened
> 1 && gcov_is_error ())
477 warning ("error writing `%s'", bbg_file_name
);
478 bbg_file_opened
= -1;
483 struct function_list
*item
;
485 item
= xmalloc (sizeof (struct function_list
));
487 *functions_tail
= item
;
488 functions_tail
= &item
->next
;
491 item
->ident
= current_function_funcdef_no
+ 1;
492 item
->checksum
= compute_checksum ();
493 for (i
= 0; i
!= GCOV_COUNTERS
; i
++)
495 item
->n_ctrs
[i
] = fn_n_ctrs
[i
];
496 prg_n_ctrs
[i
] += fn_n_ctrs
[i
];
497 fn_n_ctrs
[i
] = fn_b_ctrs
[i
] = 0;
499 prg_ctr_mask
|= fn_ctr_mask
;
502 bbg_function_announced
= 0;
505 /* Creates the gcov_fn_info RECORD_TYPE. */
508 build_fn_info_type (unsigned int counters
)
510 tree type
= (*lang_hooks
.types
.make_type
) (RECORD_TYPE
);
515 fields
= build_decl (FIELD_DECL
, NULL_TREE
, unsigned_intSI_type_node
);
518 field
= build_decl (FIELD_DECL
, NULL_TREE
, unsigned_intSI_type_node
);
519 TREE_CHAIN (field
) = fields
;
522 array_type
= build_index_type (build_int_2 (counters
- 1, 0));
523 array_type
= build_array_type (unsigned_type_node
, array_type
);
526 field
= build_decl (FIELD_DECL
, NULL_TREE
, array_type
);
527 TREE_CHAIN (field
) = fields
;
530 finish_builtin_struct (type
, "__gcov_fn_info", fields
, NULL_TREE
);
535 /* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
536 the function being processed and TYPE is the gcov_fn_info
540 build_fn_info_value (const struct function_list
*function
, tree type
)
542 tree value
= NULL_TREE
;
543 tree fields
= TYPE_FIELDS (type
);
545 tree array_value
= NULL_TREE
;
548 value
= tree_cons (fields
,
549 convert (unsigned_intSI_type_node
,
550 build_int_2 (function
->ident
, 0)),
552 fields
= TREE_CHAIN (fields
);
555 value
= tree_cons (fields
,
556 convert (unsigned_intSI_type_node
,
557 build_int_2 (function
->checksum
, 0)),
559 fields
= TREE_CHAIN (fields
);
562 for (ix
= 0; ix
!= GCOV_COUNTERS
; ix
++)
563 if (prg_ctr_mask
& (1 << ix
))
565 tree counters
= convert (unsigned_type_node
,
566 build_int_2 (function
->n_ctrs
[ix
], 0));
568 array_value
= tree_cons (NULL_TREE
, counters
, array_value
);
571 array_value
= build_constructor (TREE_TYPE (fields
), nreverse (array_value
));
572 value
= tree_cons (fields
, array_value
, value
);
574 value
= build_constructor (type
, nreverse (value
));
579 /* Creates the gcov_ctr_info RECORD_TYPE. */
582 build_ctr_info_type (void)
584 tree type
= (*lang_hooks
.types
.make_type
) (RECORD_TYPE
);
585 tree field
, fields
= NULL_TREE
;
586 tree gcov_ptr_type
= build_pointer_type (GCOV_TYPE_NODE
);
587 tree gcov_merge_fn_type
;
590 field
= build_decl (FIELD_DECL
, NULL_TREE
, unsigned_intSI_type_node
);
591 TREE_CHAIN (field
) = fields
;
595 field
= build_decl (FIELD_DECL
, NULL_TREE
, gcov_ptr_type
);
596 TREE_CHAIN (field
) = fields
;
601 build_function_type_list (void_type_node
,
602 gcov_ptr_type
, unsigned_type_node
,
604 field
= build_decl (FIELD_DECL
, NULL_TREE
,
605 build_pointer_type (gcov_merge_fn_type
));
606 TREE_CHAIN (field
) = fields
;
609 finish_builtin_struct (type
, "__gcov_ctr_info", fields
, NULL_TREE
);
614 /* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
615 the counter being processed and TYPE is the gcov_ctr_info
619 build_ctr_info_value (unsigned int counter
, tree type
)
621 tree value
= NULL_TREE
;
622 tree fields
= TYPE_FIELDS (type
);
626 value
= tree_cons (fields
,
627 convert (unsigned_intSI_type_node
,
628 build_int_2 (prg_n_ctrs
[counter
], 0)),
630 fields
= TREE_CHAIN (fields
);
632 if (prg_n_ctrs
[counter
])
634 tree array_type
, array
;
636 array_type
= build_index_type (build_int_2 (prg_n_ctrs
[counter
] - 1, 0));
637 array_type
= build_array_type (TREE_TYPE (TREE_TYPE (fields
)),
640 array
= build (VAR_DECL
, array_type
, NULL_TREE
, NULL_TREE
);
641 TREE_STATIC (array
) = 1;
642 DECL_NAME (array
) = get_identifier (XSTR (ctr_labels
[counter
], 0));
643 assemble_variable (array
, 0, 0, 0);
645 value
= tree_cons (fields
,
646 build1 (ADDR_EXPR
, TREE_TYPE (fields
), array
),
650 value
= tree_cons (fields
, null_pointer_node
, value
);
651 fields
= TREE_CHAIN (fields
);
653 fn
= build_decl (FUNCTION_DECL
,
654 get_identifier (ctr_merge_functions
[counter
]),
655 TREE_TYPE (TREE_TYPE (fields
)));
656 DECL_EXTERNAL (fn
) = 1;
657 TREE_PUBLIC (fn
) = 1;
658 DECL_ARTIFICIAL (fn
) = 1;
659 TREE_NOTHROW (fn
) = 1;
660 value
= tree_cons (fields
,
661 build1 (ADDR_EXPR
, TREE_TYPE (fields
), fn
),
664 value
= build_constructor (type
, nreverse (value
));
669 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
673 build_gcov_info (void)
675 unsigned n_ctr_types
, ix
;
676 tree type
, const_type
;
677 tree fn_info_type
, fn_info_value
= NULL_TREE
;
678 tree fn_info_ptr_type
;
679 tree ctr_info_type
, ctr_info_ary_type
, ctr_info_value
= NULL_TREE
;
680 tree field
, fields
= NULL_TREE
;
681 tree value
= NULL_TREE
;
682 tree filename_string
;
686 const struct function_list
*fn
;
689 /* Count the number of active counters. */
690 for (n_ctr_types
= 0, ix
= 0; ix
!= GCOV_COUNTERS
; ix
++)
691 if (prg_ctr_mask
& (1 << ix
))
694 type
= (*lang_hooks
.types
.make_type
) (RECORD_TYPE
);
695 const_type
= build_qualified_type (type
, TYPE_QUAL_CONST
);
698 field
= build_decl (FIELD_DECL
, NULL_TREE
, unsigned_intSI_type_node
);
699 TREE_CHAIN (field
) = fields
;
701 value
= tree_cons (field
, convert (unsigned_intSI_type_node
,
702 build_int_2 (GCOV_VERSION
, 0)),
706 field
= build_decl (FIELD_DECL
, NULL_TREE
, build_pointer_type (const_type
));
707 TREE_CHAIN (field
) = fields
;
709 value
= tree_cons (field
, null_pointer_node
, value
);
712 field
= build_decl (FIELD_DECL
, NULL_TREE
, unsigned_intSI_type_node
);
713 TREE_CHAIN (field
) = fields
;
715 value
= tree_cons (field
, convert (unsigned_intSI_type_node
,
716 build_int_2 (local_tick
, 0)),
720 string_type
= build_pointer_type (build_qualified_type (char_type_node
,
722 field
= build_decl (FIELD_DECL
, NULL_TREE
, string_type
);
723 TREE_CHAIN (field
) = fields
;
725 filename
= getpwd ();
726 filename
= (filename
&& da_file_name
[0] != '/'
727 ? concat (filename
, "/", da_file_name
, NULL
)
729 filename_len
= strlen (filename
);
730 filename_string
= build_string (filename_len
+ 1, filename
);
731 if (filename
!= da_file_name
)
733 TREE_TYPE (filename_string
) =
734 build_array_type (char_type_node
,
735 build_index_type (build_int_2 (filename_len
, 0)));
736 value
= tree_cons (field
, build1 (ADDR_EXPR
, string_type
, filename_string
),
739 /* Build the fn_info type and initializer. */
740 fn_info_type
= build_fn_info_type (n_ctr_types
);
741 fn_info_ptr_type
= build_pointer_type (build_qualified_type
742 (fn_info_type
, TYPE_QUAL_CONST
));
743 for (fn
= functions_head
, n_fns
= 0; fn
; fn
= fn
->next
, n_fns
++)
744 fn_info_value
= tree_cons (NULL_TREE
,
745 build_fn_info_value (fn
, fn_info_type
),
751 array_type
= build_index_type (build_int_2 (n_fns
- 1, 0));
752 array_type
= build_array_type (fn_info_type
, array_type
);
754 fn_info_value
= build_constructor (array_type
, nreverse (fn_info_value
));
755 fn_info_value
= build1 (ADDR_EXPR
, fn_info_ptr_type
, fn_info_value
);
758 fn_info_value
= null_pointer_node
;
760 /* number of functions */
761 field
= build_decl (FIELD_DECL
, NULL_TREE
, unsigned_type_node
);
762 TREE_CHAIN (field
) = fields
;
764 value
= tree_cons (field
,
765 convert (unsigned_type_node
, build_int_2 (n_fns
, 0)),
769 field
= build_decl (FIELD_DECL
, NULL_TREE
, fn_info_ptr_type
);
770 TREE_CHAIN (field
) = fields
;
772 value
= tree_cons (field
, fn_info_value
, value
);
775 field
= build_decl (FIELD_DECL
, NULL_TREE
, unsigned_type_node
);
776 TREE_CHAIN (field
) = fields
;
778 value
= tree_cons (field
,
779 convert (unsigned_type_node
,
780 build_int_2 (prg_ctr_mask
, 0)),
784 ctr_info_type
= build_ctr_info_type ();
785 ctr_info_ary_type
= build_index_type (build_int_2 (n_ctr_types
, 0));
786 ctr_info_ary_type
= build_array_type (ctr_info_type
, ctr_info_ary_type
);
787 for (ix
= 0; ix
!= GCOV_COUNTERS
; ix
++)
788 if (prg_ctr_mask
& (1 << ix
))
789 ctr_info_value
= tree_cons (NULL_TREE
,
790 build_ctr_info_value (ix
, ctr_info_type
),
792 ctr_info_value
= build_constructor (ctr_info_ary_type
,
793 nreverse (ctr_info_value
));
795 field
= build_decl (FIELD_DECL
, NULL_TREE
, ctr_info_ary_type
);
796 TREE_CHAIN (field
) = fields
;
798 value
= tree_cons (field
, ctr_info_value
, value
);
800 finish_builtin_struct (type
, "__gcov_info", fields
, NULL_TREE
);
802 value
= build_constructor (type
, nreverse (value
));
807 /* Write out the structure which libgcov uses to locate all the
808 counters. The structures used here must match those defined in
809 gcov-io.h. Write out the constructor to call __gcov_init. */
812 create_coverage (void)
814 tree gcov_info
, gcov_info_value
;
818 rtx gcov_info_address
;
820 no_coverage
= 1; /* Disable any further coverage. */
825 gcov_info_value
= build_gcov_info ();
827 gcov_info
= build (VAR_DECL
, TREE_TYPE (gcov_info_value
),
828 NULL_TREE
, NULL_TREE
);
829 DECL_INITIAL (gcov_info
) = gcov_info_value
;
831 TREE_STATIC (gcov_info
) = 1;
832 ASM_GENERATE_INTERNAL_LABEL (name
, "LPBX", 0);
833 DECL_NAME (gcov_info
) = get_identifier (name
);
835 /* Build structure. */
836 assemble_variable (gcov_info
, 0, 0, 0);
838 /* Build the constructor function to invoke __gcov_init. */
839 ctor_name
= concat (IDENTIFIER_POINTER (get_file_function_name ('I')),
841 ctor
= build_decl (FUNCTION_DECL
, get_identifier (ctor_name
),
842 build_function_type (void_type_node
, NULL_TREE
));
844 DECL_EXTERNAL (ctor
) = 0;
846 /* It can be a static function as long as collect2 does not have
847 to scan the object file to find its ctor/dtor routine. */
848 TREE_PUBLIC (ctor
) = ! targetm
.have_ctors_dtors
;
849 TREE_USED (ctor
) = 1;
850 DECL_RESULT (ctor
) = build_decl (RESULT_DECL
, NULL_TREE
, void_type_node
);
851 DECL_UNINLINABLE (ctor
) = 1;
853 ctor
= (*lang_hooks
.decls
.pushdecl
) (ctor
);
854 rest_of_decl_compilation (ctor
, 0, 1, 0);
855 announce_function (ctor
);
856 current_function_decl
= ctor
;
857 make_decl_rtl (ctor
, NULL
);
858 init_function_start (ctor
);
859 expand_function_start (ctor
, 0);
860 /* Actually generate the code to call __gcov_init. */
861 gcov_info_address
= force_reg (Pmode
, XEXP (DECL_RTL (gcov_info
), 0));
862 emit_library_call (gcov_init_libfunc
, LCT_NORMAL
, VOIDmode
, 1,
863 gcov_info_address
, Pmode
);
865 expand_function_end ();
866 /* Create a dummy BLOCK. */
867 DECL_INITIAL (ctor
) = make_node (BLOCK
);
868 TREE_USED (DECL_INITIAL (ctor
)) = 1;
870 rest_of_compilation (ctor
);
873 fflush (asm_out_file
);
874 current_function_decl
= NULL_TREE
;
876 if (targetm
.have_ctors_dtors
)
877 (* targetm
.asm_out
.constructor
) (XEXP (DECL_RTL (ctor
), 0),
878 DEFAULT_INIT_PRIORITY
);
881 /* Perform file-level initialization. Read in data file, generate name
885 coverage_init (const char *filename
)
887 int len
= strlen (filename
);
889 /* Name of da file. */
890 da_file_name
= xmalloc (len
+ strlen (GCOV_DATA_SUFFIX
) + 1);
891 strcpy (da_file_name
, filename
);
892 strcat (da_file_name
, GCOV_DATA_SUFFIX
);
894 /* Name of bbg file. */
895 bbg_file_name
= xmalloc (len
+ strlen (GCOV_NOTE_SUFFIX
) + 1);
896 strcpy (bbg_file_name
, filename
);
897 strcat (bbg_file_name
, GCOV_NOTE_SUFFIX
);
902 /* Performs file-level cleanup. Close graph file, generate coverage
903 variables and constructor. */
906 coverage_finish (void)
911 int error
= gcov_close ();
914 unlink (bbg_file_name
);
916 /* Only remove the da file, if we cannot stamp it. If we can
917 stamp it, libgcov will DTRT. */
918 unlink (da_file_name
);
922 #include "gt-coverage.h"