]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Makefile.in (LIBGCOV): Add _gcov_merge_add.
authorZdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
Sun, 4 May 2003 15:20:26 +0000 (17:20 +0200)
committerZdenek Dvorak <rakdver@gcc.gnu.org>
Sun, 4 May 2003 15:20:26 +0000 (15:20 +0000)
* 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
gcc/Makefile.in
gcc/coverage.c
gcc/gcov-io.h
gcc/libgcov.c

index 98fcabc6a0ae0974f96ba792406fc8d0fd84d717..4830beadad96ee1e4ea298e66a21ebe8dea91366 100644 (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>
 
        * toplev.h (pedwarn_with_file_and_line): Don't declare.
index e99dbb9646d1b9ee760a34ece75a5a3895ec26fb..70df3eadfe67efa7cb263e20e8d8b5f8676ac237 100644 (file)
@@ -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 \
index 6d8ae9a55fba15dbe1462422931d014eb616df19..36400f32e9c39cd901b6908e636982428659c8ef 100644 (file)
@@ -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));
   
index df5fb976543372018f59b419bb48692095edbb42..19b43aba35faded76ad3ac0c48cb462fafc330c7 100644 (file)
@@ -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
index a40611494fcbd3806e851aad7d029b1d95dc7cd2..74e8fa123de24fb129df0e811b330a8633be7026 100644 (file)
@@ -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 */