From 09780dfb652960d422da1c5a9d81dc536cdf09f4 Mon Sep 17 00:00:00 2001 From: Zdenek Dvorak Date: Sun, 4 May 2003 17:20:26 +0200 Subject: [PATCH] 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 --- gcc/ChangeLog | 15 +++++++++++++++ gcc/Makefile.in | 2 +- gcc/coverage.c | 31 ++++++++++++++++++++++++++++++ gcc/gcov-io.h | 50 ++++++++++++++++++++++++++++++++++++++++++++----- gcc/libgcov.c | 37 ++++++++++++++++++++++++++++++------ 5 files changed, 123 insertions(+), 12 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 98fcabc6a0a..4830beadad9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2003-05-04 Zdenek Dvorak + + * 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 * toplev.h (pedwarn_with_file_and_line): Don't declare. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index e99dbb9646d..70df3eadfe6 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -854,7 +854,7 @@ STAGESTUFF = *$(objext) insn-flags.h insn-config.h insn-codes.h \ LIB2FUNCS_ST = _eprintf __gcc_bcmp # 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 \ _fpcmp_parts_sf _compare_sf _eq_sf _ne_sf _gt_sf _ge_sf \ diff --git a/gcc/coverage.c b/gcc/coverage.c index 6d8ae9a55fb..36400f32e9c 100644 --- a/gcc/coverage.c +++ b/gcc/coverage.c @@ -98,6 +98,9 @@ static htab_t counts_hash = NULL; /* The names of the counter tables. */ 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. */ static hashval_t htab_counts_entry_hash PARAMS ((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 field, fields = NULL_TREE; + tree gcov_merge_fn_type; /* counters */ field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node); @@ -571,6 +575,18 @@ build_ctr_info_type () TREE_CHAIN (field) = fields; 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); return type; @@ -587,6 +603,7 @@ build_ctr_info_value (counter, type) { tree value = NULL_TREE; tree fields = TYPE_FIELDS (type); + tree fn; /* counters */ value = tree_cons (fields, @@ -614,6 +631,20 @@ build_ctr_info_value (counter, type) } else 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)); diff --git a/gcc/gcov-io.h b/gcc/gcov-io.h index df5fb976543..19b43aba35f 100644 --- a/gcc/gcov-io.h +++ b/gcc/gcov-io.h @@ -176,15 +176,46 @@ typedef HOST_WIDEST_INT gcov_type; #endif #endif -/* In lib gcov we want function linkage to be static, so we do not - polute the global namespace. In the compiler we want it extern, so - that they can be accessed from elsewhere. */ -#if IN_LIBGCOV || IN_GCOV +/* In gcov we want function linkage to be static, so we do not + polute the global namespace. In libgcov we need these functions + to be extern, so prefix them with __gcov so that we do not conflict. + 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 -#else + +#else /* !IN_LIBGCOV && !IN_GCOV */ + #ifndef GCOV_LINKAGE #define GCOV_LINKAGE extern #endif + #endif /* File suffixes. */ @@ -220,6 +251,9 @@ typedef HOST_WIDEST_INT gcov_type; /* A list of human readable names of the counters */ #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. */ #define GCOV_TAG_FOR_COUNTER(COUNT) \ (GCOV_TAG_COUNTER_BASE + ((COUNT) << 17)) @@ -286,11 +320,15 @@ struct gcov_fn_info unsigned n_ctrs[0]; /* instrumented counters */ }; +/* Type of function used to merge counters. */ +typedef void (*gcov_merge_fn) (gcov_type *, unsigned); + /* Information about counters. */ struct gcov_ctr_info { unsigned num; /* number of counters. */ gcov_type *values; /* their values. */ + gcov_merge_fn merge; /* The function used to merge them. */ }; /* Information about a single object file. */ @@ -317,6 +355,8 @@ extern void __gcov_init (struct gcov_info *); /* Called before fork, to avoid double counting. */ extern void __gcov_flush (void); +/* The merge function that just sums the counters. */ +extern void __gcov_merge_add (gcov_type *, unsigned); #endif /* IN_LIBGCOV */ /* Because small reads and writes, interspersed with seeks cause lots diff --git a/gcc/libgcov.c b/gcc/libgcov.c index a40611494fc..74e8fa123de 100644 --- a/gcc/libgcov.c +++ b/gcc/libgcov.c @@ -32,11 +32,19 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #if defined(inhibit_libc) /* If libc and its header files are not available, provide dummy functions. */ +#ifdef L_gcov void __gcov_init (void *p); void __gcov_flush (void); void __gcov_init (void *p) { } 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 @@ -59,6 +67,8 @@ void __gcov_flush (void) { } #endif #define IN_LIBGCOV 1 #include "gcov-io.h" + +#ifdef L_gcov #include "gcov-io.c" /* Chain of per-object gcov structures. */ @@ -227,7 +237,7 @@ gcov_exit (void) if ((1 << t_ix) & gi_ptr->ctr_mask) { unsigned n_counts; - gcov_type *c_ptr; + gcov_merge_fn merge; tag = gcov_read_unsigned (); length = gcov_read_unsigned (); @@ -235,11 +245,10 @@ gcov_exit (void) if (tag != GCOV_TAG_FOR_COUNTER (t_ix) || fi_ptr->n_ctrs[c_ix] * 8 != length) goto read_mismatch; - c_ptr = values[c_ix]; - for (n_counts = fi_ptr->n_ctrs[c_ix]; - n_counts--; c_ptr++) - *c_ptr += gcov_read_counter (); - values[c_ix] = c_ptr; + n_counts = fi_ptr->n_ctrs[c_ix]; + merge = gi_ptr->counts[c_ix].merge; + (*merge) (values[c_ix], n_counts); + values[c_ix] += n_counts; c_ix++; } 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 */