New GCOV_TAG_FUNCTION layout
New GCOV_TAG_FUNCTION layout * coverage.c (struct function_list): Replace name with ident. (struct counts_entry): Likewise. (fn_ident): New. (htab_counts_entry_hash, htab_counts_entry_eq, htab_counts_entry_del): Adjust. (reads_count_file, get_coverage_counts, coverage_begin_output, coverage_end_function): Adjust. (build_fn_info_type, build_fn_info_value): Likewise. * gcov-dump.c (tag_function): Adjust. * gcov-io.c (gcov_write_string, gcov_read_string): Not in LIBGCOV. * gcov-io.h (gcov_write_string, gcov_read_string): Not in LIBGCOV. * gcov.c (struct function_info): Add ident. (read_graph_file, read_count_file): Adjust. * libgcov.c (gcov_exit): Adjust. From-SVN: r66035
This commit is contained in:
parent
374ca7f74e
commit
796621e8c2
@ -1,3 +1,21 @@
|
||||
2003-04-24 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
New GCOV_TAG_FUNCTION layout
|
||||
* coverage.c (struct function_list): Replace name with ident.
|
||||
(struct counts_entry): Likewise.
|
||||
(fn_ident): New.
|
||||
(htab_counts_entry_hash, htab_counts_entry_eq,
|
||||
htab_counts_entry_del): Adjust.
|
||||
(reads_count_file, get_coverage_counts,
|
||||
coverage_begin_output, coverage_end_function): Adjust.
|
||||
(build_fn_info_type, build_fn_info_value): Likewise.
|
||||
* gcov-dump.c (tag_function): Adjust.
|
||||
* gcov-io.c (gcov_write_string, gcov_read_string): Not in LIBGCOV.
|
||||
* gcov-io.h (gcov_write_string, gcov_read_string): Not in LIBGCOV.
|
||||
* gcov.c (struct function_info): Add ident.
|
||||
(read_graph_file, read_count_file): Adjust.
|
||||
* libgcov.c (gcov_exit): Adjust.
|
||||
|
||||
2003-04-23 Richard Henderson <rth@redhat.com>
|
||||
|
||||
PR opt/8300
|
||||
|
@ -50,7 +50,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
struct function_list
|
||||
{
|
||||
struct function_list *next; /* next function */
|
||||
const char *name; /* function name */
|
||||
unsigned ident; /* function ident */
|
||||
unsigned checksum; /* function checksum */
|
||||
unsigned n_ctrs[GCOV_COUNTERS];/* number of counters. */
|
||||
};
|
||||
@ -59,7 +59,7 @@ struct function_list
|
||||
typedef struct counts_entry
|
||||
{
|
||||
/* We hash by */
|
||||
char *function_name;
|
||||
unsigned ident;
|
||||
unsigned ctr;
|
||||
|
||||
/* Store */
|
||||
@ -72,6 +72,7 @@ typedef struct counts_entry
|
||||
|
||||
} counts_entry_t;
|
||||
|
||||
static unsigned fn_ident = 1;
|
||||
static struct function_list *functions_head = 0;
|
||||
static struct function_list **functions_tail = &functions_head;
|
||||
|
||||
@ -118,7 +119,7 @@ htab_counts_entry_hash (of)
|
||||
{
|
||||
const counts_entry_t *entry = of;
|
||||
|
||||
return htab_hash_string (entry->function_name) ^ entry->ctr;
|
||||
return entry->ident * GCOV_COUNTERS + entry->ctr;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -129,8 +130,7 @@ htab_counts_entry_eq (of1, of2)
|
||||
const counts_entry_t *entry1 = of1;
|
||||
const counts_entry_t *entry2 = of2;
|
||||
|
||||
return !strcmp (entry1->function_name, entry2->function_name)
|
||||
&& entry1->ctr == entry2->ctr;
|
||||
return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -139,7 +139,6 @@ htab_counts_entry_del (of)
|
||||
{
|
||||
counts_entry_t *entry = of;
|
||||
|
||||
free (entry->function_name);
|
||||
free (entry->counts);
|
||||
free (entry);
|
||||
}
|
||||
@ -149,7 +148,7 @@ htab_counts_entry_del (of)
|
||||
static void
|
||||
read_counts_file ()
|
||||
{
|
||||
char *function_name_buffer = NULL;
|
||||
unsigned fn_ident = 0;
|
||||
unsigned version, ix, checksum = -1;
|
||||
counts_entry_t *summaried = NULL;
|
||||
unsigned seen_summary = 0;
|
||||
@ -193,9 +192,7 @@ read_counts_file ()
|
||||
offset = gcov_position ();
|
||||
if (tag == GCOV_TAG_FUNCTION)
|
||||
{
|
||||
const char *string = gcov_read_string ();
|
||||
free (function_name_buffer);
|
||||
function_name_buffer = string ? xstrdup (string) : NULL;
|
||||
fn_ident = gcov_read_unsigned ();
|
||||
checksum = gcov_read_unsigned ();
|
||||
if (seen_summary)
|
||||
{
|
||||
@ -231,13 +228,13 @@ read_counts_file ()
|
||||
entry->summary.sum_max += csum->sum_max;
|
||||
}
|
||||
}
|
||||
else if (GCOV_TAG_IS_COUNTER (tag) && function_name_buffer)
|
||||
else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
|
||||
{
|
||||
counts_entry_t **slot, *entry, elt;
|
||||
unsigned n_counts = length / 8;
|
||||
unsigned ix;
|
||||
|
||||
elt.function_name = function_name_buffer;
|
||||
elt.ident = fn_ident;
|
||||
elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
|
||||
|
||||
slot = (counts_entry_t **) htab_find_slot
|
||||
@ -246,7 +243,7 @@ read_counts_file ()
|
||||
if (!entry)
|
||||
{
|
||||
*slot = entry = xcalloc (1, sizeof (counts_entry_t));
|
||||
entry->function_name = xstrdup (elt.function_name);
|
||||
entry->ident = elt.ident;
|
||||
entry->ctr = elt.ctr;
|
||||
entry->checksum = checksum;
|
||||
entry->summary.num = n_counts;
|
||||
@ -255,7 +252,7 @@ read_counts_file ()
|
||||
else if (entry->checksum != checksum
|
||||
|| entry->summary.num != n_counts)
|
||||
{
|
||||
warning ("profile mismatch for `%s'", function_name_buffer);
|
||||
warning ("coverage mismatch for function %u", fn_ident);
|
||||
htab_delete (counts_hash);
|
||||
break;
|
||||
}
|
||||
@ -281,7 +278,6 @@ read_counts_file ()
|
||||
}
|
||||
}
|
||||
|
||||
free (function_name_buffer);
|
||||
gcov_close ();
|
||||
}
|
||||
|
||||
@ -304,24 +300,24 @@ get_coverage_counts (unsigned counter, unsigned expected,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
elt.function_name
|
||||
= (char *) IDENTIFIER_POINTER
|
||||
(DECL_ASSEMBLER_NAME (current_function_decl));
|
||||
elt.ident = fn_ident;
|
||||
elt.ctr = counter;
|
||||
entry = htab_find (counts_hash, &elt);
|
||||
if (!entry)
|
||||
{
|
||||
warning ("No profile for function '%s' found.", elt.function_name);
|
||||
warning ("no coverage for function '%s' found.", IDENTIFIER_POINTER
|
||||
(DECL_ASSEMBLER_NAME (current_function_decl)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (expected != entry->summary.num
|
||||
|| compute_checksum () != entry->checksum)
|
||||
{
|
||||
warning ("profile mismatch for `%s'", elt.function_name);
|
||||
warning ("coverage mismatch for `%s'", IDENTIFIER_POINTER
|
||||
(DECL_ASSEMBLER_NAME (current_function_decl)));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if (summary)
|
||||
*summary = &entry->summary;
|
||||
|
||||
@ -426,9 +422,10 @@ coverage_begin_output ()
|
||||
|
||||
/* Announce function */
|
||||
offset = gcov_write_tag (GCOV_TAG_FUNCTION);
|
||||
gcov_write_unsigned (fn_ident);
|
||||
gcov_write_unsigned (compute_checksum ());
|
||||
gcov_write_string (IDENTIFIER_POINTER
|
||||
(DECL_ASSEMBLER_NAME (current_function_decl)));
|
||||
gcov_write_unsigned (compute_checksum ());
|
||||
gcov_write_string (file);
|
||||
gcov_write_unsigned (line);
|
||||
gcov_write_length (offset);
|
||||
@ -456,15 +453,14 @@ coverage_end_function ()
|
||||
{
|
||||
struct function_list *item;
|
||||
|
||||
/* ??? Probably should re-use the existing struct function. */
|
||||
item = xmalloc (sizeof (struct function_list));
|
||||
|
||||
*functions_tail = item;
|
||||
functions_tail = &item->next;
|
||||
|
||||
item->next = 0;
|
||||
item->name = xstrdup (IDENTIFIER_POINTER
|
||||
(DECL_ASSEMBLER_NAME (current_function_decl)));
|
||||
/* It would be nice to use the unique source location. */
|
||||
item->ident = fn_ident;
|
||||
item->checksum = compute_checksum ();
|
||||
for (i = 0; i != GCOV_COUNTERS; i++)
|
||||
{
|
||||
@ -476,6 +472,7 @@ coverage_end_function ()
|
||||
fn_ctr_mask = 0;
|
||||
}
|
||||
bbg_function_announced = 0;
|
||||
fn_ident++;
|
||||
}
|
||||
|
||||
/* Creates the gcov_fn_info RECORD_TYPE. */
|
||||
@ -486,13 +483,10 @@ build_fn_info_type (counters)
|
||||
{
|
||||
tree type = (*lang_hooks.types.make_type) (RECORD_TYPE);
|
||||
tree field, fields;
|
||||
tree string_type =
|
||||
build_pointer_type (build_qualified_type (char_type_node,
|
||||
TYPE_QUAL_CONST));
|
||||
tree array_type;
|
||||
|
||||
/* name */
|
||||
fields = build_decl (FIELD_DECL, NULL_TREE, string_type);
|
||||
/* ident */
|
||||
fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
|
||||
|
||||
/* checksum */
|
||||
field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
|
||||
@ -523,20 +517,13 @@ build_fn_info_value (function, type)
|
||||
{
|
||||
tree value = NULL_TREE;
|
||||
tree fields = TYPE_FIELDS (type);
|
||||
size_t name_len = strlen (function->name);
|
||||
tree fname = build_string (name_len + 1, function->name);
|
||||
tree string_type =
|
||||
build_pointer_type (build_qualified_type (char_type_node,
|
||||
TYPE_QUAL_CONST));
|
||||
unsigned ix;
|
||||
tree array_value = NULL_TREE;
|
||||
|
||||
/* name */
|
||||
TREE_TYPE (fname) =
|
||||
build_array_type (char_type_node,
|
||||
build_index_type (build_int_2 (name_len, 0)));
|
||||
/* ident */
|
||||
value = tree_cons (fields,
|
||||
build1 (ADDR_EXPR, string_type, fname),
|
||||
convert (unsigned_type_node,
|
||||
build_int_2 (function->ident, 0)),
|
||||
value);
|
||||
fields = TREE_CHAIN (fields);
|
||||
|
||||
@ -854,16 +841,17 @@ coverage_init (filename)
|
||||
{
|
||||
int len = strlen (filename);
|
||||
|
||||
/* Name of da file. */
|
||||
da_file_name = (char *) xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1);
|
||||
strcpy (da_file_name, filename);
|
||||
strcat (da_file_name, GCOV_DATA_SUFFIX);
|
||||
|
||||
read_counts_file ();
|
||||
|
||||
/* Open the bbg output file. */
|
||||
/* Name of bbg file. */
|
||||
bbg_file_name = (char *) xmalloc (len + strlen (GCOV_GRAPH_SUFFIX) + 1);
|
||||
strcpy (bbg_file_name, filename);
|
||||
strcat (bbg_file_name, GCOV_GRAPH_SUFFIX);
|
||||
|
||||
read_counts_file ();
|
||||
}
|
||||
|
||||
/* Performs file-level cleanup. Close graph file, generate coverage
|
||||
|
@ -254,15 +254,17 @@ tag_function (filename, tag, length)
|
||||
unsigned tag ATTRIBUTE_UNUSED;
|
||||
unsigned length ATTRIBUTE_UNUSED;
|
||||
{
|
||||
const char *name;
|
||||
unsigned long pos = gcov_position ();
|
||||
|
||||
name = gcov_read_string ();
|
||||
printf (" `%s'", name ? name : "NULL");
|
||||
printf (" checksum=0x%08x", gcov_read_unsigned ());
|
||||
printf (" ident=%u", gcov_read_unsigned ());
|
||||
printf (", checksum=0x%08x", gcov_read_unsigned ());
|
||||
|
||||
if (gcov_position () - pos < length)
|
||||
{
|
||||
const char *name;
|
||||
|
||||
name = gcov_read_string ();
|
||||
printf (", `%s'", name ? name : "NULL");
|
||||
name = gcov_read_string ();
|
||||
printf (" %s", name ? name : "NULL");
|
||||
printf (":%u", gcov_read_unsigned ());
|
||||
|
@ -222,6 +222,7 @@ gcov_write_counter (gcov_type value)
|
||||
}
|
||||
#endif /* IN_LIBGCOV */
|
||||
|
||||
#if !IN_LIBGCOV
|
||||
/* Write STRING to coverage file. Sets error flag on file
|
||||
error, overflow flag on overflow */
|
||||
|
||||
@ -254,6 +255,7 @@ gcov_write_string (const char *string)
|
||||
memcpy (buffer + 4 + length, &pad, rem);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Write a tag TAG and reserve space for the record length. Return a
|
||||
value to be used for gcov_write_length. */
|
||||
@ -396,6 +398,7 @@ gcov_read_counter ()
|
||||
buffer, or NULL on empty string. You must copy the string before
|
||||
calling another gcov function. */
|
||||
|
||||
#if !IN_LIBGCOV
|
||||
GCOV_LINKAGE const char *
|
||||
gcov_read_string ()
|
||||
{
|
||||
@ -407,6 +410,7 @@ gcov_read_string ()
|
||||
length += 4 - (length & 3);
|
||||
return (const char *) gcov_read_bytes (length);
|
||||
}
|
||||
#endif
|
||||
|
||||
GCOV_LINKAGE void
|
||||
gcov_read_summary (struct gcov_summary *summary)
|
||||
|
@ -95,10 +95,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
file and [a1..ff] for the counter file.
|
||||
|
||||
The basic block graph file contains the following records
|
||||
bbg: function-graph*
|
||||
bbg: unit function-graph*
|
||||
unit: header int32:checksum string:source
|
||||
function-graph: announce_function basic_blocks {arcs | lines}*
|
||||
announce_function: header string:name int32:checksum
|
||||
string:source int32:lineno
|
||||
announce_function: header int32:ident int32:checksum
|
||||
string:name string:source int32:lineno
|
||||
basic_block: header int32:flags*
|
||||
arcs: header int32:block_no arc*
|
||||
arc: int32:dest_block int32:flags
|
||||
@ -123,9 +124,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
blocks they are for.
|
||||
|
||||
The data file contains the following records.
|
||||
da: {function-data* summary:object summary:program*}*
|
||||
da: {unit function-data* summary:object summary:program*}*
|
||||
unit: header int32:checksum
|
||||
function-data: announce_function arc_counts
|
||||
announce_function: header string:name int32:checksum
|
||||
announce_function: header int32:ident int32:checksum
|
||||
arc_counts: header int64:count*
|
||||
summary: int32:checksum {count-summary}GCOV_COUNTERS
|
||||
count-summary: int32:num int32:runs int64:sum
|
||||
@ -279,7 +281,7 @@ struct gcov_summary
|
||||
explicitly calculate the correct array stride. */
|
||||
struct gcov_fn_info
|
||||
{
|
||||
const char *name; /* (mangled) name of function */
|
||||
unsigned ident; /* unique ident of function */
|
||||
unsigned checksum; /* function checksum */
|
||||
unsigned n_ctrs[0]; /* instrumented counters */
|
||||
};
|
||||
@ -339,8 +341,9 @@ GCOV_LINKAGE unsigned char *gcov_write_bytes (unsigned);
|
||||
GCOV_LINKAGE void gcov_write_unsigned (unsigned);
|
||||
#if IN_LIBGCOV
|
||||
GCOV_LINKAGE void gcov_write_counter (gcov_type);
|
||||
#endif
|
||||
#else
|
||||
GCOV_LINKAGE void gcov_write_string (const char *);
|
||||
#endif
|
||||
GCOV_LINKAGE unsigned long gcov_write_tag (unsigned);
|
||||
GCOV_LINKAGE void gcov_write_length (unsigned long /*position*/);
|
||||
#if IN_LIBGCOV
|
||||
@ -350,9 +353,10 @@ GCOV_LINKAGE void gcov_write_summary (unsigned, const struct gcov_summary *);
|
||||
GCOV_LINKAGE const unsigned char *gcov_read_bytes (unsigned);
|
||||
GCOV_LINKAGE unsigned gcov_read_unsigned (void);
|
||||
GCOV_LINKAGE gcov_type gcov_read_counter (void);
|
||||
#if !IN_LIBGCOV
|
||||
GCOV_LINKAGE const char *gcov_read_string (void);
|
||||
#endif
|
||||
GCOV_LINKAGE void gcov_read_summary (struct gcov_summary *);
|
||||
|
||||
static unsigned long gcov_position (void);
|
||||
static void gcov_seek (unsigned long /*base*/, unsigned /*length */);
|
||||
static unsigned long gcov_seek_end (void);
|
||||
|
17
gcc/gcov.c
17
gcc/gcov.c
@ -168,6 +168,7 @@ typedef struct function_info
|
||||
{
|
||||
/* Name of function. */
|
||||
char *name;
|
||||
unsigned ident;
|
||||
unsigned checksum;
|
||||
|
||||
/* Array of basic blocks. */
|
||||
@ -744,21 +745,23 @@ read_graph_file ()
|
||||
unsigned tag = gcov_read_unsigned ();
|
||||
unsigned length = gcov_read_unsigned ();
|
||||
unsigned long base = gcov_position ();
|
||||
|
||||
|
||||
if (tag == GCOV_TAG_FUNCTION)
|
||||
{
|
||||
char *function_name;
|
||||
unsigned checksum, lineno;
|
||||
unsigned ident, checksum, lineno;
|
||||
source_t *src;
|
||||
function_t *probe, *prev;
|
||||
|
||||
function_name = xstrdup (gcov_read_string ());
|
||||
ident = gcov_read_unsigned ();
|
||||
checksum = gcov_read_unsigned ();
|
||||
function_name = xstrdup (gcov_read_string ());
|
||||
src = find_source (gcov_read_string ());
|
||||
lineno = gcov_read_unsigned ();
|
||||
|
||||
fn = (function_t *)xcalloc (1, sizeof (function_t));
|
||||
fn->name = function_name;
|
||||
fn->ident = ident;
|
||||
fn->checksum = checksum;
|
||||
fn->src = src;
|
||||
fn->line = lineno;
|
||||
@ -1015,7 +1018,7 @@ read_count_file ()
|
||||
program_count++;
|
||||
else if (tag == GCOV_TAG_FUNCTION)
|
||||
{
|
||||
const char *function_name = gcov_read_string ();
|
||||
unsigned ident = gcov_read_unsigned ();
|
||||
struct function_info *fn_n = functions;
|
||||
|
||||
for (fn = fn ? fn->next : NULL; ; fn = fn->next)
|
||||
@ -1026,11 +1029,11 @@ read_count_file ()
|
||||
fn_n = NULL;
|
||||
else
|
||||
{
|
||||
fnotice (stderr, "%s:unknown function `%s'\n",
|
||||
da_file_name, function_name);
|
||||
fnotice (stderr, "%s:unknown function `%u'\n",
|
||||
da_file_name, ident);
|
||||
break;
|
||||
}
|
||||
if (!strcmp (fn->name, function_name))
|
||||
if (fn->ident == ident)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -203,7 +203,8 @@ gcov_exit (void)
|
||||
}
|
||||
|
||||
/* Merge execution counts for each function. */
|
||||
for (f_ix = gi_ptr->n_functions, fi_ptr = gi_ptr->functions; f_ix--;
|
||||
for (f_ix = gi_ptr->n_functions, fi_ptr = gi_ptr->functions;
|
||||
f_ix--;
|
||||
fi_ptr = (const struct gcov_fn_info *)
|
||||
((const char *) fi_ptr + fi_stride))
|
||||
{
|
||||
@ -211,19 +212,17 @@ gcov_exit (void)
|
||||
length = gcov_read_unsigned ();
|
||||
|
||||
/* Check function */
|
||||
if (tag != GCOV_TAG_FUNCTION)
|
||||
if (tag != GCOV_TAG_FUNCTION
|
||||
|| gcov_read_unsigned () != fi_ptr->ident
|
||||
|| gcov_read_unsigned () != fi_ptr->checksum)
|
||||
{
|
||||
read_mismatch:;
|
||||
fprintf (stderr, "profiling:%s:Merge mismatch for %s\n",
|
||||
gi_ptr->filename,
|
||||
fi_ptr ? fi_ptr->name : "summaries");
|
||||
f_ix + 1 ? "function" : "summaries");
|
||||
goto read_fatal;
|
||||
}
|
||||
|
||||
if (strcmp (gcov_read_string (), fi_ptr->name)
|
||||
|| gcov_read_unsigned () != fi_ptr->checksum)
|
||||
goto read_mismatch;
|
||||
|
||||
for (c_ix = t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
|
||||
if ((1 << t_ix) & gi_ptr->ctr_mask)
|
||||
{
|
||||
@ -284,9 +283,8 @@ gcov_exit (void)
|
||||
if (!summary_pos)
|
||||
memset (&program, 0, sizeof (program));
|
||||
|
||||
fi_ptr = 0;
|
||||
|
||||
/* Merge the summaries. */
|
||||
f_ix = ~0u;
|
||||
for (t_ix = c_ix = 0,
|
||||
cs_obj = object.ctrs, cs_tobj = this_object.ctrs,
|
||||
cs_prg = program.ctrs, cs_tprg = this_program.ctrs,
|
||||
@ -346,7 +344,7 @@ gcov_exit (void)
|
||||
{
|
||||
/* Announce function. */
|
||||
base = gcov_write_tag (GCOV_TAG_FUNCTION);
|
||||
gcov_write_string (fi_ptr->name);
|
||||
gcov_write_unsigned (fi_ptr->ident);
|
||||
gcov_write_unsigned (fi_ptr->checksum);
|
||||
gcov_write_length (base);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user