The basic format of the files is
- file : int32:magic int32:version record*
+ file : int32:magic int32:version int32:stamp record*
The magic ident is different for the bbg and the counter files.
The version is the same for both files and is derived from gcc's
- version number. Although the ident and version are formally 32 bit
+ version number. The stamp value is used to synchronize bbg and
+ counter files and to synchronize merging within a counter file. It
+ need not be an absolute time stamp, merely a ticker that increments
+ fast enough and cycles slow enough to distinguish different
+ compile/run/compile cycles.
+
+ Although the ident and version are formally 32 bit
numbers, they are derived from 4 character ASCII strings. The
version number consists of the single character major version
number, a two character minor version number (leading zero for
most significant is allocated first. Unused levels are zero.
Active levels are odd-valued, so that the LSB of the level is one.
A sub-level incorporates the values of its superlevels. This
- formatting allows you to determine the tag heirarchy, without
+ formatting allows you to determine the tag hierarchy, without
understanding the tags themselves, and is similar to the standard
section numbering used in technical documents. Level values
[1..3f] are used for common tags, values [41..9f] for the graph
#define gcov_read_counter __gcov_read_counter
#define gcov_read_summary __gcov_read_summary
-/* Poison these, so they don't accidentally slip in. */
+/* Poison these, so they don't accidentally slip in. */
#pragma GCC poison gcov_write_string gcov_write_tag gcov_write_length
#pragma GCC poison gcov_read_string gcov_sync gcov_time
/* Counters that are collected. */
#define GCOV_COUNTER_ARCS 0 /* Arc transitions. */
#define GCOV_COUNTERS_SUMMABLE 1 /* Counters which can be
- summaried. */
-#define GCOV_COUNTERS 1
-
-/* 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. */
+ summaried. */
+#define GCOV_COUNTER_V_INTERVAL 1 /* Histogram of value inside an interval. */
+#define GCOV_COUNTER_V_POW2 2 /* Histogram of exact power2 logarithm
+ of a value. */
+#define GCOV_COUNTER_V_SINGLE 3 /* The most common value of expression. */
+#define GCOV_COUNTER_V_DELTA 4 /* The most common difference between
+ consecutive values of expression. */
+#define GCOV_COUNTERS 5
+
+ /* A list of human readable names of the counters */
+#define GCOV_COUNTER_NAMES {"arcs", "interval", "pow2", "single", "delta"}
+
+ /* Names of merge functions for counters. */
+#define GCOV_MERGE_FUNCTIONS {"__gcov_merge_add", \
+ "__gcov_merge_add", \
+ "__gcov_merge_add", \
+ "__gcov_merge_single", \
+ "__gcov_merge_delta"}
+
+/* Convert a counter index to a tag. */
#define GCOV_TAG_FOR_COUNTER(COUNT) \
(GCOV_TAG_COUNTER_BASE + ((gcov_unsigned_t)(COUNT) << 17))
/* Convert a tag to a counter. */
/* Structured records. */
-/* Cumulative counter data. */
+/* Cumulative counter data. */
struct gcov_ctr_summary
{
gcov_unsigned_t num; /* number of counters. */
gcov_unsigned_t runs; /* number of program runs */
- gcov_type sum_all; /* sum of all counters accumulated. */
+ gcov_type sum_all; /* sum of all counters accumulated. */
gcov_type run_max; /* maximum value on a single run. */
- gcov_type sum_max; /* sum of individual run max values. */
+ gcov_type sum_max; /* sum of individual run max values. */
};
/* Object & program summary record. */
gcov_unsigned_t version; /* expected version number */
struct gcov_info *next; /* link to next, used by libgcc */
+ gcov_unsigned_t stamp; /* uniquifying time stamp */
const char *filename; /* output file name */
-
+
unsigned n_functions; /* number of functions */
const struct gcov_fn_info *functions; /* table of functions */
/* The merge function that just sums the counters. */
extern void __gcov_merge_add (gcov_type *, unsigned);
+
+/* The merge function to choose the most often value. */
+extern void __gcov_merge_single (gcov_type *, unsigned);
+
+/* The merge function to choose the most often difference between consecutive
+ values. */
+extern void __gcov_merge_delta (gcov_type *, unsigned);
#endif /* IN_LIBGCOV */
#if IN_LIBGCOV >= 0
{
FILE *file;
gcov_position_t start; /* Position of first byte of block */
- unsigned offset; /* Read/write position within the block. */
- unsigned length; /* Read limit in the block. */
+ unsigned offset; /* Read/write position within the block. */
+ unsigned length; /* Read limit in the block. */
unsigned overread; /* Number of bytes overread. */
int error; /* < 0 overflow, > 0 disk error. */
int mode; /* < 0 writing, > 0 reading */
may use the gcov_write functions, gcov_seek & gcov_error. When a
file is to be rewritten you use the functions for reading, then
gcov_rewrite then the functions for writing. Your file may become
- corrupted if you break these invariants. */
+ corrupted if you break these invariants. */
GCOV_LINKAGE int gcov_open (const char */*name*/, int /*truncate*/);
GCOV_LINKAGE int gcov_close (void);
GCOV_LINKAGE void gcov_write_tag_length (gcov_unsigned_t, gcov_unsigned_t);
GCOV_LINKAGE void gcov_write_summary (gcov_unsigned_t /*tag*/,
const struct gcov_summary *);
+static void gcov_truncate (void);
static void gcov_rewrite (void);
GCOV_LINKAGE void gcov_seek (gcov_position_t /*position*/);
#else
/* Return nonzero if we read to end of file. */
static inline int
-gcov_is_eof ()
+gcov_is_eof (void)
{
return !gcov_var.overread;
}
/* Return nonzero if the error flag is set. */
static inline int
-gcov_is_error ()
+gcov_is_error (void)
{
return gcov_var.file ? gcov_var.error : 1;
}
#if IN_LIBGCOV
-/* Move to beginning of file and intialize for writing. */
+/* Move to beginning of file and initialize for writing. */
static inline void
gcov_rewrite (void)
gcov_var.offset = 0;
fseek (gcov_var.file, 0L, SEEK_SET);
}
+
+static inline void
+gcov_truncate (void)
+{
+ ftruncate (fileno (gcov_var.file), 0L);
+}
#endif
#endif /* IN_LIBGCOV >= 0 */