Makefile.in (LIBGCOV): Add _gcov_merge_add.

* Makefile.in (LIBGCOV): Add _gcov_merge_add.
	* gcov-io.h: Make GCOV_LINKAGE extern in libgcov and prevent resulting
	namespace clash.
	(GCOV_MERGE_FUNCTIONS): New.
	(gcov_merge_fn): Declare.
	(struct gcov_ctr_info): New field "merge".
	(__gcov_merge_add): Declare.
	* coverage.c (ctr_merge_functions): New.
	(build_ctr_info_type, build_ctr_info_value): Initialize merge field
	of gcov_ctr_info type.
	* libgcov.c (__gcov_merge_add): New.
	(gcov_exit): Call a hook to merge values of counters.

From-SVN: r66457
This commit is contained in:
Zdenek Dvorak 2003-05-04 17:20:26 +02:00 committed by Zdenek Dvorak
parent c71f2ffd78
commit 09780dfb65
5 changed files with 123 additions and 12 deletions

View File

@ -1,3 +1,18 @@
2003-05-04 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
* Makefile.in (LIBGCOV): Add _gcov_merge_add.
* gcov-io.h: Make GCOV_LINKAGE extern in libgcov and prevent resulting
namespace clash.
(GCOV_MERGE_FUNCTIONS): New.
(gcov_merge_fn): Declare.
(struct gcov_ctr_info): New field "merge".
(__gcov_merge_add): Declare.
* coverage.c (ctr_merge_functions): New.
(build_ctr_info_type, build_ctr_info_value): Initialize merge field
of gcov_ctr_info type.
* libgcov.c (__gcov_merge_add): New.
(gcov_exit): Call a hook to merge values of counters.
2003-05-04 Gabriel Dos Reis <gdr@integrable-solutions.net> 2003-05-04 Gabriel Dos Reis <gdr@integrable-solutions.net>
* toplev.h (pedwarn_with_file_and_line): Don't declare. * toplev.h (pedwarn_with_file_and_line): Don't declare.

View File

@ -854,7 +854,7 @@ STAGESTUFF = *$(objext) insn-flags.h insn-config.h insn-codes.h \
LIB2FUNCS_ST = _eprintf __gcc_bcmp LIB2FUNCS_ST = _eprintf __gcc_bcmp
# Defined in libgcov.c, included only in gcov library # Defined in libgcov.c, included only in gcov library
LIBGCOV = _gcov LIBGCOV = _gcov _gcov_merge_add
FPBIT_FUNCS = _pack_sf _unpack_sf _addsub_sf _mul_sf _div_sf \ FPBIT_FUNCS = _pack_sf _unpack_sf _addsub_sf _mul_sf _div_sf \
_fpcmp_parts_sf _compare_sf _eq_sf _ne_sf _gt_sf _ge_sf \ _fpcmp_parts_sf _compare_sf _eq_sf _ne_sf _gt_sf _ge_sf \

View File

@ -98,6 +98,9 @@ static htab_t counts_hash = NULL;
/* The names of the counter tables. */ /* The names of the counter tables. */
static GTY(()) rtx ctr_labels[GCOV_COUNTERS]; static GTY(()) rtx ctr_labels[GCOV_COUNTERS];
/* The names of merge functions for counters. */
static const char *ctr_merge_functions[GCOV_COUNTERS] = GCOV_MERGE_FUNCTIONS;
/* Forward declarations. */ /* Forward declarations. */
static hashval_t htab_counts_entry_hash PARAMS ((const void *)); static hashval_t htab_counts_entry_hash PARAMS ((const void *));
static int htab_counts_entry_eq PARAMS ((const void *, const void *)); static int htab_counts_entry_eq PARAMS ((const void *, const void *));
@ -559,6 +562,7 @@ build_ctr_info_type ()
{ {
tree type = (*lang_hooks.types.make_type) (RECORD_TYPE); tree type = (*lang_hooks.types.make_type) (RECORD_TYPE);
tree field, fields = NULL_TREE; tree field, fields = NULL_TREE;
tree gcov_merge_fn_type;
/* counters */ /* counters */
field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node); field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
@ -571,6 +575,18 @@ build_ctr_info_type ()
TREE_CHAIN (field) = fields; TREE_CHAIN (field) = fields;
fields = field; fields = field;
/* merge */
gcov_merge_fn_type =
build_function_type_list (
void_type_node,
build_pointer_type (make_signed_type (GCOV_TYPE_SIZE)),
unsigned_type_node,
NULL_TREE);
field = build_decl (FIELD_DECL, NULL_TREE,
build_pointer_type (gcov_merge_fn_type));
TREE_CHAIN (field) = fields;
fields = field;
finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE); finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
return type; return type;
@ -587,6 +603,7 @@ build_ctr_info_value (counter, type)
{ {
tree value = NULL_TREE; tree value = NULL_TREE;
tree fields = TYPE_FIELDS (type); tree fields = TYPE_FIELDS (type);
tree fn;
/* counters */ /* counters */
value = tree_cons (fields, value = tree_cons (fields,
@ -614,6 +631,20 @@ build_ctr_info_value (counter, type)
} }
else else
value = tree_cons (fields, null_pointer_node, value); value = tree_cons (fields, null_pointer_node, value);
fields = TREE_CHAIN (fields);
fn = build_decl (FUNCTION_DECL,
get_identifier (ctr_merge_functions[counter]),
TREE_TYPE (TREE_TYPE (fields)));
DECL_EXTERNAL (fn) = 1;
TREE_PUBLIC (fn) = 1;
DECL_ARTIFICIAL (fn) = 1;
TREE_NOTHROW (fn) = 1;
value = tree_cons (fields,
build1 (ADDR_EXPR,
TREE_TYPE (fields),
fn),
value);
value = build_constructor (type, nreverse (value)); value = build_constructor (type, nreverse (value));

View File

@ -176,15 +176,46 @@ typedef HOST_WIDEST_INT gcov_type;
#endif #endif
#endif #endif
/* In lib gcov we want function linkage to be static, so we do not /* In gcov we want function linkage to be static, so we do not
polute the global namespace. In the compiler we want it extern, so polute the global namespace. In libgcov we need these functions
that they can be accessed from elsewhere. */ to be extern, so prefix them with __gcov so that we do not conflict.
#if IN_LIBGCOV || IN_GCOV In the compiler we want it extern, so that they can be accessed from
elsewhere. */
#if IN_LIBGCOV
#define GCOV_LINKAGE /* nothing */
#define gcov_var __gcov_var
#define gcov_open __gcov_open
#define gcov_close __gcov_close
#define gcov_write_bytes __gcov_write_bytes
#define gcov_write_unsigned __gcov_write_unsigned
#define gcov_write_counter __gcov_write_counter
#define gcov_write_string __gcov_write_string
#define gcov_write_tag __gcov_write_tag
#define gcov_write_length __gcov_write_length
#define gcov_write_summary __gcov_write_summary
#define gcov_read_bytes __gcov_read_bytes
#define gcov_read_unsigned __gcov_read_unsigned
#define gcov_read_counter __gcov_read_counter
#define gcov_read_string __gcov_read_string
#define gcov_read_summary __gcov_read_summary
#define gcov_position __gcov_position
#define gcov_seek __gcov_seek
#define gcov_seek_end __gcov_seek_end
#define gcov_is_eof __gcov_is_eof
#define gcov_is_error __gcov_is_error
#define gcov_time __gcov_time
#elif IN_GCOV
#define GCOV_LINKAGE static #define GCOV_LINKAGE static
#else
#else /* !IN_LIBGCOV && !IN_GCOV */
#ifndef GCOV_LINKAGE #ifndef GCOV_LINKAGE
#define GCOV_LINKAGE extern #define GCOV_LINKAGE extern
#endif #endif
#endif #endif
/* File suffixes. */ /* File suffixes. */
@ -220,6 +251,9 @@ typedef HOST_WIDEST_INT gcov_type;
/* A list of human readable names of the counters */ /* A list of human readable names of the counters */
#define GCOV_COUNTER_NAMES {"arcs"} #define GCOV_COUNTER_NAMES {"arcs"}
/* Names of merge functions for counters. */
#define GCOV_MERGE_FUNCTIONS {"__gcov_merge_add"}
/* Convert a counter index to a tag. */ /* Convert a counter index to a tag. */
#define GCOV_TAG_FOR_COUNTER(COUNT) \ #define GCOV_TAG_FOR_COUNTER(COUNT) \
(GCOV_TAG_COUNTER_BASE + ((COUNT) << 17)) (GCOV_TAG_COUNTER_BASE + ((COUNT) << 17))
@ -286,11 +320,15 @@ struct gcov_fn_info
unsigned n_ctrs[0]; /* instrumented counters */ unsigned n_ctrs[0]; /* instrumented counters */
}; };
/* Type of function used to merge counters. */
typedef void (*gcov_merge_fn) (gcov_type *, unsigned);
/* Information about counters. */ /* Information about counters. */
struct gcov_ctr_info struct gcov_ctr_info
{ {
unsigned num; /* number of counters. */ unsigned num; /* number of counters. */
gcov_type *values; /* their values. */ gcov_type *values; /* their values. */
gcov_merge_fn merge; /* The function used to merge them. */
}; };
/* Information about a single object file. */ /* Information about a single object file. */
@ -317,6 +355,8 @@ extern void __gcov_init (struct gcov_info *);
/* Called before fork, to avoid double counting. */ /* Called before fork, to avoid double counting. */
extern void __gcov_flush (void); extern void __gcov_flush (void);
/* The merge function that just sums the counters. */
extern void __gcov_merge_add (gcov_type *, unsigned);
#endif /* IN_LIBGCOV */ #endif /* IN_LIBGCOV */
/* Because small reads and writes, interspersed with seeks cause lots /* Because small reads and writes, interspersed with seeks cause lots

View File

@ -32,11 +32,19 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#if defined(inhibit_libc) #if defined(inhibit_libc)
/* If libc and its header files are not available, provide dummy functions. */ /* If libc and its header files are not available, provide dummy functions. */
#ifdef L_gcov
void __gcov_init (void *p); void __gcov_init (void *p);
void __gcov_flush (void); void __gcov_flush (void);
void __gcov_init (void *p) { } void __gcov_init (void *p) { }
void __gcov_flush (void) { } void __gcov_flush (void) { }
#endif
#ifdef L_gcov_merge_add
void __gcov_merge_add (gcov_type *, unsigned);
void __gcov_merge_add (gcov_type *counters, unsigned n_counters) { }
#endif
#else #else
@ -59,6 +67,8 @@ void __gcov_flush (void) { }
#endif #endif
#define IN_LIBGCOV 1 #define IN_LIBGCOV 1
#include "gcov-io.h" #include "gcov-io.h"
#ifdef L_gcov
#include "gcov-io.c" #include "gcov-io.c"
/* Chain of per-object gcov structures. */ /* Chain of per-object gcov structures. */
@ -227,7 +237,7 @@ gcov_exit (void)
if ((1 << t_ix) & gi_ptr->ctr_mask) if ((1 << t_ix) & gi_ptr->ctr_mask)
{ {
unsigned n_counts; unsigned n_counts;
gcov_type *c_ptr; gcov_merge_fn merge;
tag = gcov_read_unsigned (); tag = gcov_read_unsigned ();
length = gcov_read_unsigned (); length = gcov_read_unsigned ();
@ -235,11 +245,10 @@ gcov_exit (void)
if (tag != GCOV_TAG_FOR_COUNTER (t_ix) if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
|| fi_ptr->n_ctrs[c_ix] * 8 != length) || fi_ptr->n_ctrs[c_ix] * 8 != length)
goto read_mismatch; goto read_mismatch;
c_ptr = values[c_ix]; n_counts = fi_ptr->n_ctrs[c_ix];
for (n_counts = fi_ptr->n_ctrs[c_ix]; merge = gi_ptr->counts[c_ix].merge;
n_counts--; c_ptr++) (*merge) (values[c_ix], n_counts);
*c_ptr += gcov_read_counter (); values[c_ix] += n_counts;
values[c_ix] = c_ptr;
c_ix++; c_ix++;
} }
if ((error = gcov_is_error ())) if ((error = gcov_is_error ()))
@ -450,4 +459,20 @@ __gcov_flush (void)
} }
} }
#endif /* L_gcov */
#ifdef L_gcov_merge_add
/* The profile merging function that just adds the counters. It is given
an array COUNTERS of N_COUNTERS old counters and it reads the same number
of counters from the gcov file. */
void
__gcov_merge_add (counters, n_counters)
gcov_type *counters;
unsigned n_counters;
{
for (; n_counters; counters++, n_counters--)
*counters += gcov_read_counter ();
}
#endif /* L_gcov_merge_add */
#endif /* inhibit_libc */ #endif /* inhibit_libc */