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, 2005, 2007 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 3, 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 COPYING3. If not see
23 <http://www.gnu.org/licenses/>. */
30 #include "coretypes.h"
42 #include "langhooks.h"
44 #include "tree-iterator.h"
51 struct function_list
*next
; /* next function */
52 unsigned ident
; /* function ident */
53 unsigned checksum
; /* function checksum */
54 unsigned n_ctrs
[GCOV_COUNTERS
];/* number of counters. */
57 /* Counts information for a function. */
58 typedef struct counts_entry
67 struct gcov_ctr_summary summary
;
70 struct counts_entry
*chain
;
74 static struct function_list
*functions_head
= 0;
75 static struct function_list
**functions_tail
= &functions_head
;
76 static unsigned no_coverage
= 0;
78 /* Cumulative counter information for whole program. */
79 static unsigned prg_ctr_mask
; /* Mask of counter types generated. */
80 static unsigned prg_n_ctrs
[GCOV_COUNTERS
]; /* Total counters allocated. */
82 /* Counter information for current function. */
83 static unsigned fn_ctr_mask
; /* Mask of counters used. */
84 static unsigned fn_n_ctrs
[GCOV_COUNTERS
]; /* Counters allocated. */
85 static unsigned fn_b_ctrs
[GCOV_COUNTERS
]; /* Allocation base. */
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 /* Trees representing the counter table arrays. */
99 static GTY(()) tree tree_ctr_tables
[GCOV_COUNTERS
];
101 /* The names of the counter tables. Not used if we're
102 generating counters at tree level. */
103 static GTY(()) rtx ctr_labels
[GCOV_COUNTERS
];
105 /* The names of merge functions for counters. */
106 static const char *const ctr_merge_functions
[GCOV_COUNTERS
] = GCOV_MERGE_FUNCTIONS
;
107 static const char *const ctr_names
[GCOV_COUNTERS
] = GCOV_COUNTER_NAMES
;
109 /* Forward declarations. */
110 static hashval_t
htab_counts_entry_hash (const void *);
111 static int htab_counts_entry_eq (const void *, const void *);
112 static void htab_counts_entry_del (void *);
113 static void read_counts_file (void);
114 static unsigned compute_checksum (void);
115 static unsigned coverage_checksum_string (unsigned, const char *);
116 static tree
build_fn_info_type (unsigned);
117 static tree
build_fn_info_value (const struct function_list
*, tree
);
118 static tree
build_ctr_info_type (void);
119 static tree
build_ctr_info_value (unsigned, tree
);
120 static tree
build_gcov_info (void);
121 static void create_coverage (void);
123 /* Return the type node for gcov_type. */
128 return lang_hooks
.types
.type_for_size (GCOV_TYPE_SIZE
, false);
131 /* Return the type node for gcov_unsigned_t. */
134 get_gcov_unsigned_t (void)
136 return lang_hooks
.types
.type_for_size (32, true);
140 htab_counts_entry_hash (const void *of
)
142 const counts_entry_t
*entry
= of
;
144 return entry
->ident
* GCOV_COUNTERS
+ entry
->ctr
;
148 htab_counts_entry_eq (const void *of1
, const void *of2
)
150 const counts_entry_t
*entry1
= of1
;
151 const counts_entry_t
*entry2
= of2
;
153 return entry1
->ident
== entry2
->ident
&& entry1
->ctr
== entry2
->ctr
;
157 htab_counts_entry_del (void *of
)
159 counts_entry_t
*entry
= of
;
161 free (entry
->counts
);
165 /* Read in the counts file, if available. */
168 read_counts_file (void)
170 gcov_unsigned_t fn_ident
= 0;
171 gcov_unsigned_t checksum
= -1;
172 counts_entry_t
*summaried
= NULL
;
173 unsigned seen_summary
= 0;
177 if (!gcov_open (da_file_name
, 1))
180 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC
))
182 warning (0, "%qs is not a gcov data file", da_file_name
);
186 else if ((tag
= gcov_read_unsigned ()) != GCOV_VERSION
)
190 GCOV_UNSIGNED2STRING (v
, tag
);
191 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
193 warning (0, "%qs is version %q.*s, expected version %q.*s",
194 da_file_name
, 4, v
, 4, e
);
199 /* Read and discard the stamp. */
200 gcov_read_unsigned ();
202 counts_hash
= htab_create (10,
203 htab_counts_entry_hash
, htab_counts_entry_eq
,
204 htab_counts_entry_del
);
205 while ((tag
= gcov_read_unsigned ()))
207 gcov_unsigned_t length
;
208 gcov_position_t offset
;
210 length
= gcov_read_unsigned ();
211 offset
= gcov_position ();
212 if (tag
== GCOV_TAG_FUNCTION
)
214 fn_ident
= gcov_read_unsigned ();
215 checksum
= gcov_read_unsigned ();
218 /* We have already seen a summary, this means that this
219 new function begins a new set of program runs. We
220 must unlink the summaried chain. */
221 counts_entry_t
*entry
, *chain
;
223 for (entry
= summaried
; entry
; entry
= chain
)
225 chain
= entry
->chain
;
232 else if (tag
== GCOV_TAG_PROGRAM_SUMMARY
)
234 counts_entry_t
*entry
;
235 struct gcov_summary summary
;
237 gcov_read_summary (&summary
);
239 for (entry
= summaried
; entry
; entry
= entry
->chain
)
241 struct gcov_ctr_summary
*csum
= &summary
.ctrs
[entry
->ctr
];
243 entry
->summary
.runs
+= csum
->runs
;
244 entry
->summary
.sum_all
+= csum
->sum_all
;
245 if (entry
->summary
.run_max
< csum
->run_max
)
246 entry
->summary
.run_max
= csum
->run_max
;
247 entry
->summary
.sum_max
+= csum
->sum_max
;
250 else if (GCOV_TAG_IS_COUNTER (tag
) && fn_ident
)
252 counts_entry_t
**slot
, *entry
, elt
;
253 unsigned n_counts
= GCOV_TAG_COUNTER_NUM (length
);
256 elt
.ident
= fn_ident
;
257 elt
.ctr
= GCOV_COUNTER_FOR_TAG (tag
);
259 slot
= (counts_entry_t
**) htab_find_slot
260 (counts_hash
, &elt
, INSERT
);
264 *slot
= entry
= XCNEW (counts_entry_t
);
265 entry
->ident
= elt
.ident
;
266 entry
->ctr
= elt
.ctr
;
267 entry
->checksum
= checksum
;
268 entry
->summary
.num
= n_counts
;
269 entry
->counts
= XCNEWVEC (gcov_type
, n_counts
);
271 else if (entry
->checksum
!= checksum
)
273 error ("coverage mismatch for function %u while reading execution counters",
275 error ("checksum is %x instead of %x", entry
->checksum
, checksum
);
276 htab_delete (counts_hash
);
279 else if (entry
->summary
.num
!= n_counts
)
281 error ("coverage mismatch for function %u while reading execution counters",
283 error ("number of counters is %d instead of %d", entry
->summary
.num
, n_counts
);
284 htab_delete (counts_hash
);
287 else if (elt
.ctr
>= GCOV_COUNTERS_SUMMABLE
)
289 error ("cannot merge separate %s counters for function %u",
290 ctr_names
[elt
.ctr
], fn_ident
);
294 if (elt
.ctr
< GCOV_COUNTERS_SUMMABLE
295 /* This should always be true for a just allocated entry,
296 and always false for an existing one. Check this way, in
297 case the gcov file is corrupt. */
298 && (!entry
->chain
|| summaried
!= entry
))
300 entry
->chain
= summaried
;
303 for (ix
= 0; ix
!= n_counts
; ix
++)
304 entry
->counts
[ix
] += gcov_read_counter ();
307 gcov_sync (offset
, length
);
308 if ((is_error
= gcov_is_error ()))
310 error (is_error
< 0 ? "%qs has overflowed" : "%qs is corrupted",
312 htab_delete (counts_hash
);
320 /* Returns the counters for a particular tag. */
323 get_coverage_counts (unsigned counter
, unsigned expected
,
324 const struct gcov_ctr_summary
**summary
)
326 counts_entry_t
*entry
, elt
;
327 gcov_unsigned_t checksum
= -1;
329 /* No hash table, no counts. */
332 static int warned
= 0;
335 inform ((flag_guess_branch_prob
336 ? "file %s not found, execution counts estimated"
337 : "file %s not found, execution counts assumed to be zero"),
342 elt
.ident
= current_function_funcdef_no
+ 1;
344 entry
= htab_find (counts_hash
, &elt
);
347 warning (0, "no coverage for function %qs found", IDENTIFIER_POINTER
348 (DECL_ASSEMBLER_NAME (current_function_decl
)));
352 checksum
= compute_checksum ();
353 if (entry
->checksum
!= checksum
354 || entry
->summary
.num
!= expected
)
356 static int warned
= 0;
357 const char *id
= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME
358 (current_function_decl
));
360 if (warn_coverage_mismatch
)
361 warning (OPT_Wcoverage_mismatch
, "coverage mismatch for function "
362 "%qs while reading counter %qs", id
, ctr_names
[counter
]);
364 error ("coverage mismatch for function %qs while reading counter %qs",
365 id
, ctr_names
[counter
]);
367 if (!inhibit_warnings
)
369 if (entry
->checksum
!= checksum
)
370 inform ("checksum is %x instead of %x", entry
->checksum
, checksum
);
372 inform ("number of counters is %d instead of %d",
373 entry
->summary
.num
, expected
);
376 if (warn_coverage_mismatch
380 inform ("coverage mismatch ignored due to -Wcoverage-mismatch");
381 inform (flag_guess_branch_prob
382 ? "execution counts estimated"
383 : "execution counts assumed to be zero");
384 if (!flag_guess_branch_prob
)
385 inform ("this can result in poorly optimized code");
392 *summary
= &entry
->summary
;
394 return entry
->counts
;
397 /* Allocate NUM counters of type COUNTER. Returns nonzero if the
398 allocation succeeded. */
401 coverage_counter_alloc (unsigned counter
, unsigned num
)
409 if (!tree_ctr_tables
[counter
])
411 /* Generate and save a copy of this so it can be shared. Leave
412 the index type unspecified for now; it will be set after all
413 functions have been compiled. */
415 tree gcov_type_node
= get_gcov_type ();
416 tree gcov_type_array_type
417 = build_array_type (gcov_type_node
, NULL_TREE
);
418 tree_ctr_tables
[counter
]
419 = build_decl (VAR_DECL
, NULL_TREE
, gcov_type_array_type
);
420 TREE_STATIC (tree_ctr_tables
[counter
]) = 1;
421 ASM_GENERATE_INTERNAL_LABEL (buf
, "LPBX", counter
+ 1);
422 DECL_NAME (tree_ctr_tables
[counter
]) = get_identifier (buf
);
423 DECL_ALIGN (tree_ctr_tables
[counter
]) = TYPE_ALIGN (gcov_type_node
);
425 fn_b_ctrs
[counter
] = fn_n_ctrs
[counter
];
426 fn_n_ctrs
[counter
] += num
;
427 fn_ctr_mask
|= 1 << counter
;
431 /* Generate a tree to access COUNTER NO. */
434 tree_coverage_counter_ref (unsigned counter
, unsigned no
)
436 tree gcov_type_node
= get_gcov_type ();
438 gcc_assert (no
< fn_n_ctrs
[counter
] - fn_b_ctrs
[counter
]);
439 no
+= prg_n_ctrs
[counter
] + fn_b_ctrs
[counter
];
441 /* "no" here is an array index, scaled to bytes later. */
442 return build4 (ARRAY_REF
, gcov_type_node
, tree_ctr_tables
[counter
],
443 build_int_cst (NULL_TREE
, no
), NULL
, NULL
);
446 /* Generate a tree to access the address of COUNTER NO. */
449 tree_coverage_counter_addr (unsigned counter
, unsigned no
)
451 tree gcov_type_node
= get_gcov_type ();
453 gcc_assert (no
< fn_n_ctrs
[counter
] - fn_b_ctrs
[counter
]);
454 no
+= prg_n_ctrs
[counter
] + fn_b_ctrs
[counter
];
456 /* "no" here is an array index, scaled to bytes later. */
457 return build_fold_addr_expr (build4 (ARRAY_REF
, gcov_type_node
,
458 tree_ctr_tables
[counter
],
459 build_int_cst (NULL_TREE
, no
),
463 /* Generate a checksum for a string. CHKSUM is the current
467 coverage_checksum_string (unsigned chksum
, const char *string
)
472 /* Look for everything that looks if it were produced by
473 get_file_function_name and zero out the second part
474 that may result from flag_random_seed. This is not critical
475 as the checksums are used only for sanity checking. */
476 for (i
= 0; string
[i
]; i
++)
479 if (!strncmp (string
+ i
, "_GLOBAL__N_", 11))
481 if (!strncmp (string
+ i
, "_GLOBAL__", 9))
484 /* C++ namespaces do have scheme:
485 _GLOBAL__N_<filename>_<wrongmagicnumber>_<magicnumber>functionname
486 since filename might contain extra underscores there seems
487 to be no better chance then walk all possible offsets looking
491 for (i
= i
+ offset
; string
[i
]; i
++)
496 for (y
= 1; y
< 9; y
++)
497 if (!(string
[i
+ y
] >= '0' && string
[i
+ y
] <= '9')
498 && !(string
[i
+ y
] >= 'A' && string
[i
+ y
] <= 'F'))
500 if (y
!= 9 || string
[i
+ 9] != '_')
502 for (y
= 10; y
< 18; y
++)
503 if (!(string
[i
+ y
] >= '0' && string
[i
+ y
] <= '9')
504 && !(string
[i
+ y
] >= 'A' && string
[i
+ y
] <= 'F'))
509 string
= dup
= xstrdup (string
);
510 for (y
= 10; y
< 18; y
++)
517 chksum
= crc32_string (chksum
, string
);
524 /* Compute checksum for the current function. We generate a CRC32. */
527 compute_checksum (void)
529 expanded_location xloc
530 = expand_location (DECL_SOURCE_LOCATION (current_function_decl
));
531 unsigned chksum
= xloc
.line
;
533 chksum
= coverage_checksum_string (chksum
, xloc
.file
);
534 chksum
= coverage_checksum_string
535 (chksum
, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl
)));
540 /* Begin output to the graph file for the current function.
541 Opens the output file, if not already done. Writes the
542 function header, if not already done. Returns nonzero if data
546 coverage_begin_output (void)
551 if (!bbg_function_announced
)
553 expanded_location xloc
554 = expand_location (DECL_SOURCE_LOCATION (current_function_decl
));
555 unsigned long offset
;
557 if (!bbg_file_opened
)
559 if (!gcov_open (bbg_file_name
, -1))
560 error ("cannot open %s", bbg_file_name
);
563 gcov_write_unsigned (GCOV_NOTE_MAGIC
);
564 gcov_write_unsigned (GCOV_VERSION
);
565 gcov_write_unsigned (local_tick
);
570 /* Announce function */
571 offset
= gcov_write_tag (GCOV_TAG_FUNCTION
);
572 gcov_write_unsigned (current_function_funcdef_no
+ 1);
573 gcov_write_unsigned (compute_checksum ());
574 gcov_write_string (IDENTIFIER_POINTER
575 (DECL_ASSEMBLER_NAME (current_function_decl
)));
576 gcov_write_string (xloc
.file
);
577 gcov_write_unsigned (xloc
.line
);
578 gcov_write_length (offset
);
580 bbg_function_announced
= 1;
582 return !gcov_is_error ();
585 /* Finish coverage data for the current function. Verify no output
586 error has occurred. Save function coverage counts. */
589 coverage_end_function (void)
593 if (bbg_file_opened
> 1 && gcov_is_error ())
595 warning (0, "error writing %qs", bbg_file_name
);
596 bbg_file_opened
= -1;
601 struct function_list
*item
;
603 item
= XNEW (struct function_list
);
605 *functions_tail
= item
;
606 functions_tail
= &item
->next
;
609 item
->ident
= current_function_funcdef_no
+ 1;
610 item
->checksum
= compute_checksum ();
611 for (i
= 0; i
!= GCOV_COUNTERS
; i
++)
613 item
->n_ctrs
[i
] = fn_n_ctrs
[i
];
614 prg_n_ctrs
[i
] += fn_n_ctrs
[i
];
615 fn_n_ctrs
[i
] = fn_b_ctrs
[i
] = 0;
617 prg_ctr_mask
|= fn_ctr_mask
;
620 bbg_function_announced
= 0;
623 /* Creates the gcov_fn_info RECORD_TYPE. */
626 build_fn_info_type (unsigned int counters
)
628 tree type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
633 fields
= build_decl (FIELD_DECL
, NULL_TREE
, get_gcov_unsigned_t ());
636 field
= build_decl (FIELD_DECL
, NULL_TREE
, get_gcov_unsigned_t ());
637 TREE_CHAIN (field
) = fields
;
640 array_type
= build_int_cst (NULL_TREE
, counters
- 1);
641 array_type
= build_index_type (array_type
);
642 array_type
= build_array_type (get_gcov_unsigned_t (), array_type
);
645 field
= build_decl (FIELD_DECL
, NULL_TREE
, array_type
);
646 TREE_CHAIN (field
) = fields
;
649 finish_builtin_struct (type
, "__gcov_fn_info", fields
, NULL_TREE
);
654 /* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
655 the function being processed and TYPE is the gcov_fn_info
659 build_fn_info_value (const struct function_list
*function
, tree type
)
661 tree value
= NULL_TREE
;
662 tree fields
= TYPE_FIELDS (type
);
664 tree array_value
= NULL_TREE
;
667 value
= tree_cons (fields
, build_int_cstu (get_gcov_unsigned_t (),
668 function
->ident
), value
);
669 fields
= TREE_CHAIN (fields
);
672 value
= tree_cons (fields
, build_int_cstu (get_gcov_unsigned_t (),
673 function
->checksum
), value
);
674 fields
= TREE_CHAIN (fields
);
677 for (ix
= 0; ix
!= GCOV_COUNTERS
; ix
++)
678 if (prg_ctr_mask
& (1 << ix
))
680 tree counters
= build_int_cstu (get_gcov_unsigned_t (),
681 function
->n_ctrs
[ix
]);
683 array_value
= tree_cons (NULL_TREE
, counters
, array_value
);
686 /* FIXME: use build_constructor directly. */
687 array_value
= build_constructor_from_list (TREE_TYPE (fields
),
688 nreverse (array_value
));
689 value
= tree_cons (fields
, array_value
, value
);
691 /* FIXME: use build_constructor directly. */
692 value
= build_constructor_from_list (type
, nreverse (value
));
697 /* Creates the gcov_ctr_info RECORD_TYPE. */
700 build_ctr_info_type (void)
702 tree type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
703 tree field
, fields
= NULL_TREE
;
704 tree gcov_ptr_type
= build_pointer_type (get_gcov_type ());
705 tree gcov_merge_fn_type
;
708 field
= build_decl (FIELD_DECL
, NULL_TREE
, get_gcov_unsigned_t ());
709 TREE_CHAIN (field
) = fields
;
713 field
= build_decl (FIELD_DECL
, NULL_TREE
, gcov_ptr_type
);
714 TREE_CHAIN (field
) = fields
;
719 build_function_type_list (void_type_node
,
720 gcov_ptr_type
, get_gcov_unsigned_t (),
722 field
= build_decl (FIELD_DECL
, NULL_TREE
,
723 build_pointer_type (gcov_merge_fn_type
));
724 TREE_CHAIN (field
) = fields
;
727 finish_builtin_struct (type
, "__gcov_ctr_info", fields
, NULL_TREE
);
732 /* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
733 the counter being processed and TYPE is the gcov_ctr_info
737 build_ctr_info_value (unsigned int counter
, tree type
)
739 tree value
= NULL_TREE
;
740 tree fields
= TYPE_FIELDS (type
);
744 value
= tree_cons (fields
,
745 build_int_cstu (get_gcov_unsigned_t (),
746 prg_n_ctrs
[counter
]),
748 fields
= TREE_CHAIN (fields
);
750 if (prg_n_ctrs
[counter
])
754 array_type
= build_int_cstu (get_gcov_unsigned_t (),
755 prg_n_ctrs
[counter
] - 1);
756 array_type
= build_index_type (array_type
);
757 array_type
= build_array_type (TREE_TYPE (TREE_TYPE (fields
)),
760 TREE_TYPE (tree_ctr_tables
[counter
]) = array_type
;
761 DECL_SIZE (tree_ctr_tables
[counter
]) = TYPE_SIZE (array_type
);
762 DECL_SIZE_UNIT (tree_ctr_tables
[counter
]) = TYPE_SIZE_UNIT (array_type
);
763 assemble_variable (tree_ctr_tables
[counter
], 0, 0, 0);
765 value
= tree_cons (fields
,
766 build1 (ADDR_EXPR
, TREE_TYPE (fields
),
767 tree_ctr_tables
[counter
]),
771 value
= tree_cons (fields
, null_pointer_node
, value
);
772 fields
= TREE_CHAIN (fields
);
774 fn
= build_decl (FUNCTION_DECL
,
775 get_identifier (ctr_merge_functions
[counter
]),
776 TREE_TYPE (TREE_TYPE (fields
)));
777 DECL_EXTERNAL (fn
) = 1;
778 TREE_PUBLIC (fn
) = 1;
779 DECL_ARTIFICIAL (fn
) = 1;
780 TREE_NOTHROW (fn
) = 1;
781 value
= tree_cons (fields
,
782 build1 (ADDR_EXPR
, TREE_TYPE (fields
), fn
),
785 /* FIXME: use build_constructor directly. */
786 value
= build_constructor_from_list (type
, nreverse (value
));
791 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
795 build_gcov_info (void)
797 unsigned n_ctr_types
, ix
;
798 tree type
, const_type
;
799 tree fn_info_type
, fn_info_value
= NULL_TREE
;
800 tree fn_info_ptr_type
;
801 tree ctr_info_type
, ctr_info_ary_type
, ctr_info_value
= NULL_TREE
;
802 tree field
, fields
= NULL_TREE
;
803 tree value
= NULL_TREE
;
804 tree filename_string
;
808 const struct function_list
*fn
;
811 /* Count the number of active counters. */
812 for (n_ctr_types
= 0, ix
= 0; ix
!= GCOV_COUNTERS
; ix
++)
813 if (prg_ctr_mask
& (1 << ix
))
816 type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
817 const_type
= build_qualified_type (type
, TYPE_QUAL_CONST
);
820 field
= build_decl (FIELD_DECL
, NULL_TREE
, get_gcov_unsigned_t ());
821 TREE_CHAIN (field
) = fields
;
823 value
= tree_cons (field
, build_int_cstu (TREE_TYPE (field
), GCOV_VERSION
),
827 field
= build_decl (FIELD_DECL
, NULL_TREE
, build_pointer_type (const_type
));
828 TREE_CHAIN (field
) = fields
;
830 value
= tree_cons (field
, null_pointer_node
, value
);
833 field
= build_decl (FIELD_DECL
, NULL_TREE
, get_gcov_unsigned_t ());
834 TREE_CHAIN (field
) = fields
;
836 value
= tree_cons (field
, build_int_cstu (TREE_TYPE (field
), local_tick
),
840 string_type
= build_pointer_type (build_qualified_type (char_type_node
,
842 field
= build_decl (FIELD_DECL
, NULL_TREE
, string_type
);
843 TREE_CHAIN (field
) = fields
;
845 filename
= getpwd ();
846 filename
= (filename
&& da_file_name
[0] != '/'
847 ? concat (filename
, "/", da_file_name
, NULL
)
849 filename_len
= strlen (filename
);
850 filename_string
= build_string (filename_len
+ 1, filename
);
851 if (filename
!= da_file_name
)
853 TREE_TYPE (filename_string
) = build_array_type
854 (char_type_node
, build_index_type
855 (build_int_cst (NULL_TREE
, filename_len
)));
856 value
= tree_cons (field
, build1 (ADDR_EXPR
, string_type
, filename_string
),
859 /* Build the fn_info type and initializer. */
860 fn_info_type
= build_fn_info_type (n_ctr_types
);
861 fn_info_ptr_type
= build_pointer_type (build_qualified_type
862 (fn_info_type
, TYPE_QUAL_CONST
));
863 for (fn
= functions_head
, n_fns
= 0; fn
; fn
= fn
->next
, n_fns
++)
864 fn_info_value
= tree_cons (NULL_TREE
,
865 build_fn_info_value (fn
, fn_info_type
),
871 array_type
= build_index_type (build_int_cst (NULL_TREE
, n_fns
- 1));
872 array_type
= build_array_type (fn_info_type
, array_type
);
874 /* FIXME: use build_constructor directly. */
875 fn_info_value
= build_constructor_from_list (array_type
,
876 nreverse (fn_info_value
));
877 fn_info_value
= build1 (ADDR_EXPR
, fn_info_ptr_type
, fn_info_value
);
880 fn_info_value
= null_pointer_node
;
882 /* number of functions */
883 field
= build_decl (FIELD_DECL
, NULL_TREE
, get_gcov_unsigned_t ());
884 TREE_CHAIN (field
) = fields
;
886 value
= tree_cons (field
,
887 build_int_cstu (get_gcov_unsigned_t (), n_fns
),
891 field
= build_decl (FIELD_DECL
, NULL_TREE
, fn_info_ptr_type
);
892 TREE_CHAIN (field
) = fields
;
894 value
= tree_cons (field
, fn_info_value
, value
);
897 field
= build_decl (FIELD_DECL
, NULL_TREE
, get_gcov_unsigned_t ());
898 TREE_CHAIN (field
) = fields
;
900 value
= tree_cons (field
,
901 build_int_cstu (get_gcov_unsigned_t (), prg_ctr_mask
),
905 ctr_info_type
= build_ctr_info_type ();
906 ctr_info_ary_type
= build_index_type (build_int_cst (NULL_TREE
,
908 ctr_info_ary_type
= build_array_type (ctr_info_type
, ctr_info_ary_type
);
909 for (ix
= 0; ix
!= GCOV_COUNTERS
; ix
++)
910 if (prg_ctr_mask
& (1 << ix
))
911 ctr_info_value
= tree_cons (NULL_TREE
,
912 build_ctr_info_value (ix
, ctr_info_type
),
914 /* FIXME: use build_constructor directly. */
915 ctr_info_value
= build_constructor_from_list (ctr_info_ary_type
,
916 nreverse (ctr_info_value
));
918 field
= build_decl (FIELD_DECL
, NULL_TREE
, ctr_info_ary_type
);
919 TREE_CHAIN (field
) = fields
;
921 value
= tree_cons (field
, ctr_info_value
, value
);
923 finish_builtin_struct (type
, "__gcov_info", fields
, NULL_TREE
);
925 /* FIXME: use build_constructor directly. */
926 value
= build_constructor_from_list (type
, nreverse (value
));
931 /* Write out the structure which libgcov uses to locate all the
932 counters. The structures used here must match those defined in
933 gcov-io.h. Write out the constructor to call __gcov_init. */
936 create_coverage (void)
938 tree gcov_info
, gcov_init
, body
, t
;
941 no_coverage
= 1; /* Disable any further coverage. */
946 t
= build_gcov_info ();
948 gcov_info
= build_decl (VAR_DECL
, NULL_TREE
, TREE_TYPE (t
));
949 TREE_STATIC (gcov_info
) = 1;
950 ASM_GENERATE_INTERNAL_LABEL (name_buf
, "LPBX", 0);
951 DECL_NAME (gcov_info
) = get_identifier (name_buf
);
952 DECL_INITIAL (gcov_info
) = t
;
954 /* Build structure. */
955 assemble_variable (gcov_info
, 0, 0, 0);
957 /* Build a decl for __gcov_init. */
958 t
= build_pointer_type (TREE_TYPE (gcov_info
));
959 t
= build_function_type_list (void_type_node
, t
, NULL
);
960 t
= build_decl (FUNCTION_DECL
, get_identifier ("__gcov_init"), t
);
962 DECL_EXTERNAL (t
) = 1;
965 /* Generate a call to __gcov_init(&gcov_info). */
967 t
= build_fold_addr_expr (gcov_info
);
968 t
= build_call_expr (gcov_init
, 1, t
);
969 append_to_statement_list (t
, &body
);
971 /* Generate a constructor to run it. */
972 cgraph_build_static_cdtor ('I', body
, DEFAULT_INIT_PRIORITY
);
975 /* Perform file-level initialization. Read in data file, generate name
979 coverage_init (const char *filename
)
981 int len
= strlen (filename
);
983 /* Name of da file. */
984 da_file_name
= XNEWVEC (char, len
+ strlen (GCOV_DATA_SUFFIX
) + 1);
985 strcpy (da_file_name
, filename
);
986 strcat (da_file_name
, GCOV_DATA_SUFFIX
);
988 /* Name of bbg file. */
989 bbg_file_name
= XNEWVEC (char, len
+ strlen (GCOV_NOTE_SUFFIX
) + 1);
990 strcpy (bbg_file_name
, filename
);
991 strcat (bbg_file_name
, GCOV_NOTE_SUFFIX
);
996 /* Performs file-level cleanup. Close graph file, generate coverage
997 variables and constructor. */
1000 coverage_finish (void)
1003 if (bbg_file_opened
)
1005 int error
= gcov_close ();
1008 unlink (bbg_file_name
);
1010 /* Only remove the da file, if we cannot stamp it. If we can
1011 stamp it, libgcov will DTRT. */
1012 unlink (da_file_name
);
1016 #include "gt-coverage.h"