Commit 5366b186 by Nathan Sidwell Committed by Nathan Sidwell

libgcov.c (struct gcov_fn_buffer): New struct.

	libgcc/
	* libgcov.c (struct gcov_fn_buffer): New struct.
	(buffer_fn_data): New helper.
	(gcov_exit): Rework for new gcov data structures.

	gcc/
	* gcov.c (object_summary): Replace with ...
	(object_runs): ... this.
	(process_file): Remove functions with no data.
	(generate_results): Ignore files with no lines.
	(release_function): New helper, broken out of ...
	(release_structures): ... here.  Use it.
	(read_count_file): Adjust for new data file format.
	(output_lines): Use object_runs.
	* gcov-io.h (GCOV_TAG_OBJECT_SUMMARY): Obsolete.
	(struct gcov_ctr_info): Move definition.
	(struct gcov_fn_info): Add key field, use gcov_ctr_info for
	trailing array.
	(struct gcov_info): Add merge function array, remove mask and
	counts.  Trailing array is array of pointers to function info.
	* coverage.c (struct function_list): Replace counter numbers with
	counter arrays.  Add fndecl field.  GTYify.
	(counts_entry): Remove chain workspace.
	(functions_head): GTYify.
	(prg_n_ctrs): Remove.
	(fn_v_ctrs): New.
	(tree_ctr_tables): Remove.
	(read_counts_file): Cope with blank entries and expect program
	summaries before functions.  Don't warn on missing entries.
	(coverage_counter_alloc): Allocate individual function arrays.
	(tree_coverage_counter_ref, tree_coverage_counter_addr): Adjust
	for individual function arrays.
	(coverage_end_function): GTYify function list object. Finalize
	function's counter arrays.
	(build_var): New.  Create a counter-related variable with
	appropriate linkage.
	(build_fn_info_type): Adjust for new runtime structure.
	(build_fn_info_value): Rename to ...
	(build_fn_info): ... here.  Build new format data.
	(build_ctr_info_type, build_ctr_info_value): Remove.
	(build_info_type): New. Build new format data structure.
	(build_info): Adjust for new format data.
	(create_coverage): Likewise.
	* gcov-dump.c (tag_function): Recognize placeholders.

	gcc/testsuite/
	* gcc.dg/profile-dir-1.c: Adjust final scan.
	* gcc.dg/profile-dir-2.c: Adjust final scan.
	* gcc.dg/profile-dir-3.c: Adjust final scan.
	* gcc.misc-tests/gcov.exp: Adjust regexp.
	* gcc.misc-tests/gcov-12.c: New.
	* gcc.misc-tests/gcov-13.c: New.
	* gcc.misc-tests/gcovpart-13b.c: New.
	* gcc.misc-tests/gcov-14.c: New.

From-SVN: r181105
parent 74155a6f
2011-11-07 Nathan Sidwell <nathan@acm.org>
* gcov.c (object_summary): Replace with ...
(object_runs): ... this.
(process_file): Remove functions with no data.
(generate_results): Ignore files with no lines.
(release_function): New helper, broken out of ...
(release_structures): ... here. Use it.
(read_count_file): Adjust for new data file format.
(output_lines): Use object_runs.
* gcov-io.h (GCOV_TAG_OBJECT_SUMMARY): Obsolete.
(struct gcov_ctr_info): Move definition.
(struct gcov_fn_info): Add key field, use gcov_ctr_info for
trailing array.
(struct gcov_info): Add merge function array, remove mask and
counts. Trailing array is array of pointers to function info.
* coverage.c (struct function_list): Replace counter numbers with
counter arrays. Add fndecl field. GTYify.
(counts_entry): Remove chain workspace.
(functions_head): GTYify.
(prg_n_ctrs): Remove.
(fn_v_ctrs): New.
(tree_ctr_tables): Remove.
(read_counts_file): Cope with blank entries and expect program
summaries before functions. Don't warn on missing entries.
(coverage_counter_alloc): Allocate individual function arrays.
(tree_coverage_counter_ref, tree_coverage_counter_addr): Adjust
for individual function arrays.
(coverage_end_function): GTYify function list object. Finalize
function's counter arrays.
(build_var): New. Create a counter-related variable with
appropriate linkage.
(build_fn_info_type): Adjust for new runtime structure.
(build_fn_info_value): Rename to ...
(build_fn_info): ... here. Build new format data.
(build_ctr_info_type, build_ctr_info_value): Remove.
(build_info_type): New. Build new format data structure.
(build_info): Adjust for new format data.
(create_coverage): Likewise.
* gcov-dump.c (tag_function): Recognize placeholders.
2011-11-07 Georg-Johann Lay <avr@gjlay.de>
* config/avr/constraints.md (Cm2): New constraint for int -2.
......@@ -276,23 +276,28 @@ dump_file (const char *filename)
static void
tag_function (const char *filename ATTRIBUTE_UNUSED,
unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
unsigned tag ATTRIBUTE_UNUSED, unsigned length)
{
unsigned long pos = gcov_position ();
printf (" ident=%u", gcov_read_unsigned ());
printf (", lineno_checksum=0x%08x", gcov_read_unsigned ());
printf (", cfg_checksum_checksum=0x%08x", gcov_read_unsigned ());
if (gcov_position () - pos < length)
if (!length)
printf (" placeholder");
else
{
const char *name;
printf (" ident=%u", gcov_read_unsigned ());
printf (", lineno_checksum=0x%08x", gcov_read_unsigned ());
printf (", cfg_checksum_checksum=0x%08x", gcov_read_unsigned ());
name = gcov_read_string ();
printf (", `%s'", name ? name : "NULL");
name = gcov_read_string ();
printf (" %s", name ? name : "NULL");
printf (":%u", 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 ());
}
}
}
......
......@@ -130,26 +130,26 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
blocks they are for.
The data file contains the following records.
data: {unit function-data* summary:object summary:program*}*
data: {unit summary:object summary:program* function-data*}*
unit: header int32:checksum
function-data: announce_function arc_counts
function-data: announce_function present counts
announce_function: header int32:ident
int32:lineno_checksum int32:cfg_checksum
arc_counts: header int64:count*
summary: int32:checksum {count-summary}GCOV_COUNTERS
present: header int32:present
counts: header int64:count*
summary: int32:checksum {count-summary}GCOV_COUNTERS_SUMMABLE
count-summary: int32:num int32:runs int64:sum
int64:max int64:sum_max
The ANNOUNCE_FUNCTION record is the same as that in the note file,
but without the source location. The ARC_COUNTS gives the counter
values for those arcs that are instrumented. The SUMMARY records
give information about the whole object file and about the whole
but without the source location. The COUNTS gives the
counter values for instrumented features. The about the whole
program. The checksum is used for whole program summaries, and
disambiguates different programs which include the same
instrumented object file. There may be several program summaries,
each with a unique checksum. The object summary's checksum is zero.
Note that the data file might contain information from several runs
concatenated, or the data might be merged.
each with a unique checksum. The object summary's checksum is
zero. Note that the data file might contain information from
several runs concatenated, or the data might be merged.
This file is included by both the compiler, gcov tools and the
runtime support library libgcov. IN_LIBGCOV and IN_GCOV are used to
......@@ -307,7 +307,7 @@ typedef HOST_WIDEST_INT gcov_type;
#define GCOV_TAG_COUNTER_BASE ((gcov_unsigned_t)0x01a10000)
#define GCOV_TAG_COUNTER_LENGTH(NUM) ((NUM) * 2)
#define GCOV_TAG_COUNTER_NUM(LENGTH) ((LENGTH) / 2)
#define GCOV_TAG_OBJECT_SUMMARY ((gcov_unsigned_t)0xa1000000)
#define GCOV_TAG_OBJECT_SUMMARY ((gcov_unsigned_t)0xa1000000) /* Obsolete */
#define GCOV_TAG_PROGRAM_SUMMARY ((gcov_unsigned_t)0xa3000000)
#define GCOV_TAG_SUMMARY_LENGTH \
(1 + GCOV_COUNTERS_SUMMABLE * (2 + 3 * 2))
......@@ -343,7 +343,7 @@ typedef HOST_WIDEST_INT gcov_type;
/* A list of human readable names of the counters */
#define GCOV_COUNTER_NAMES {"arcs", "interval", "pow2", "single", \
"delta","indirect_call", "average", "ior"}
"delta", "indirect_call", "average", "ior"}
/* Names of merge functions for counters. */
#define GCOV_MERGE_FUNCTIONS {"__gcov_merge_add", \
......@@ -410,30 +410,31 @@ struct gcov_summary
by write_profile must match these. */
#if IN_LIBGCOV
/* Information about counters for a single function. */
struct gcov_ctr_info
{
gcov_unsigned_t num; /* number of counters. */
gcov_type *values; /* their values. */
};
/* Information about a single function. This uses the trailing array
idiom. The number of counters is determined from the counter_mask
in gcov_info. We hold an array of function info, so have to
explicitly calculate the correct array stride. */
idiom. The number of counters is determined from the merge pointer
array in gcov_info. The key is used to detect which of a set of
comdat functions was selected -- it points to the gcov_info object
of the object file containing the selected comdat function. */
struct gcov_fn_info
{
gcov_unsigned_t ident; /* unique ident of function */
const struct gcov_info *key; /* comdat key */
gcov_unsigned_t ident; /* unique ident of function */
gcov_unsigned_t lineno_checksum; /* function lineo_checksum */
gcov_unsigned_t cfg_checksum; /* function cfg checksum */
unsigned n_ctrs[0]; /* instrumented counters */
gcov_unsigned_t cfg_checksum; /* function cfg checksum */
struct gcov_ctr_info ctrs[0]; /* instrumented counters */
};
/* Type of function used to merge counters. */
typedef void (*gcov_merge_fn) (gcov_type *, gcov_unsigned_t);
/* Information about counters. */
struct gcov_ctr_info
{
gcov_unsigned_t 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. */
struct gcov_info
{
......@@ -443,14 +444,12 @@ struct gcov_info
gcov_unsigned_t stamp; /* uniquifying time stamp */
const char *filename; /* output file name */
gcov_merge_fn merge[GCOV_COUNTERS]; /* merge functions (null for
unused) */
unsigned n_functions; /* number of functions */
const struct gcov_fn_info *functions; /* table of functions */
unsigned ctr_mask; /* mask of counters instrumented. */
struct gcov_ctr_info counts[0]; /* count data. The number of bits
set in the ctr_mask field
determines how big this array
is. */
const struct gcov_fn_info *functions[0]; /* pointers to function
information */
};
/* Register a new object file module. */
......
......@@ -265,7 +265,7 @@ static unsigned source_index;
/* This holds data summary information. */
static struct gcov_summary object_summary;
static unsigned object_runs;
static unsigned program_count;
/* Modification time of graph file. */
......@@ -362,6 +362,7 @@ static int output_branch_count (FILE *, int, const arc_t *);
static void output_lines (FILE *, const source_t *);
static char *make_gcov_file_name (const char *, const char *);
static void release_structures (void);
static void release_function (function_t *);
extern int main (int, char **);
int
......@@ -537,7 +538,7 @@ static void
process_file (const char *file_name)
{
function_t *fn;
function_t *fn_p;
function_t **fn_p;
function_t *old_functions;
/* Save and clear the list of current functions. They will be appended
......@@ -558,11 +559,25 @@ process_file (const char *file_name)
if (read_count_file ())
return;
for (fn_p = NULL, fn = functions; fn; fn_p = fn, fn = fn->next)
solve_flow_graph (fn);
fn_p = &functions;
while ((fn = *fn_p) != NULL)
{
if (fn->counts)
{
solve_flow_graph (fn);
fn_p = &fn->next;
}
else
{
/* The function was not in the executable -- some other
instance must have been selected. */
function_t *next = fn->next;
release_function (fn);
*fn_p = next;
}
}
if (fn_p)
fn_p->next = old_functions;
*fn_p = old_functions;
}
static void
......@@ -591,7 +606,7 @@ generate_results (const char *file_name)
{
accumulate_line_counts (src);
function_summary (&src->coverage, "File");
if (flag_gcov_file)
if (flag_gcov_file && src->coverage.lines)
{
char *gcov_file_name = make_gcov_file_name (file_name, src->name);
FILE *gcov_file = fopen (gcov_file_name, "w");
......@@ -615,6 +630,28 @@ generate_results (const char *file_name)
}
}
/* Release a function structure */
static void
release_function (function_t *fn)
{
unsigned ix;
block_t *block;
for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
{
arc_t *arc, *arc_n;
for (arc = block->succ; arc; arc = arc_n)
{
arc_n = arc->succ_next;
free (arc);
}
}
free (fn->blocks);
free (fn->counts);
}
/* Release all memory used. */
static void
......@@ -633,22 +670,8 @@ release_structures (void)
while ((fn = functions))
{
unsigned ix;
block_t *block;
functions = fn->next;
for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
{
arc_t *arc, *arc_n;
for (arc = block->succ; arc; arc = arc_n)
{
arc_n = arc->succ_next;
free (arc);
}
}
free (fn->blocks);
free (fn->counts);
release_function (fn);
}
}
......@@ -1085,35 +1108,39 @@ read_count_file (void)
unsigned length = gcov_read_unsigned ();
unsigned long base = gcov_position ();
if (tag == GCOV_TAG_OBJECT_SUMMARY)
gcov_read_summary (&object_summary);
else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
program_count++;
else if (tag == GCOV_TAG_FUNCTION)
if (tag == GCOV_TAG_PROGRAM_SUMMARY)
{
{
unsigned ident = gcov_read_unsigned ();
struct function_info *fn_n = functions;
struct gcov_summary summary;
gcov_read_summary (&summary);
object_runs += summary.ctrs[GCOV_COUNTER_ARCS].runs;
program_count++;
}
else if (tag == GCOV_TAG_FUNCTION && !length)
; /* placeholder */
else if (tag == GCOV_TAG_FUNCTION && length == GCOV_TAG_FUNCTION_LENGTH)
{
unsigned ident;
struct function_info *fn_n;
/* Try to find the function in the list.
To speed up the search, first start from the last function
found. */
for (fn = fn ? fn->next : NULL; ; fn = fn->next)
{
if (fn)
;
else if ((fn = fn_n))
fn_n = NULL;
else
{
fnotice (stderr, "%s:unknown function '%u'\n",
da_file_name, ident);
break;
}
if (fn->ident == ident)
/* Try to find the function in the list. To speed up the
search, first start from the last function found. */
ident = gcov_read_unsigned ();
fn_n = functions;
for (fn = fn ? fn->next : NULL; ; fn = fn->next)
{
if (fn)
;
else if ((fn = fn_n))
fn_n = NULL;
else
{
fnotice (stderr, "%s:unknown function '%u'\n",
da_file_name, ident);
break;
}
}
}
if (fn->ident == ident)
break;
}
if (!fn)
;
......@@ -1908,8 +1935,7 @@ output_lines (FILE *gcov_file, const source_t *src)
fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0,
no_data_file ? "-" : da_file_name);
fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0,
object_summary.ctrs[GCOV_COUNTER_ARCS].runs);
fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0, object_runs);
}
fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
......
2011-11-07 Nathan Sidwell <nathan@acm.org>
* gcc.dg/profile-dir-1.c: Adjust final scan.
* gcc.dg/profile-dir-2.c: Adjust final scan.
* gcc.dg/profile-dir-3.c: Adjust final scan.
* gcc.misc-tests/gcov.exp: Adjust regexp.
* gcc.misc-tests/gcov-12.c: New.
* gcc.misc-tests/gcov-13.c: New.
* gcc.misc-tests/gcovpart-13b.c: New.
* gcc.misc-tests/gcov-14.c: New.
2011-11-07 Jason Merrill <jason@redhat.com>
PR c++/35688
......
/* { dg-do compile } */
/* { dg-options "-O -fprofile-generate=. -fdump-ipa-profile" } */
/* { dg-final { scan-ipa-dump " ./profile-dir-1.gcda" "profile" } } */
/* { dg-options "-O -fprofile-generate=. -fdump-ipa-cgraph" } */
/* { dg-final { scan-ipa-dump " ./profile-dir-1.gcda" "cgraph" } } */
int
main(void)
......@@ -8,4 +8,4 @@ main(void)
return 0;
}
/* { dg-final { cleanup-ipa-dump "profile" } } */
/* { dg-final { cleanup-ipa-dump "cgraph" } } */
/* { dg-do compile } */
/* { dg-options "-O -fprofile-generate -fdump-ipa-profile" } */
/* { dg-final { scan-ipa-dump "/profile-dir-2.gcda" "profile" } } */
/* { dg-options "-O -fprofile-generate -fdump-ipa-cgraph" } */
/* { dg-final { scan-ipa-dump "/profile-dir-2.gcda" "cgraph" } } */
int
main(void)
......@@ -8,4 +8,4 @@ main(void)
return 0;
}
/* { dg-final { cleanup-ipa-dump "profile" } } */
/* { dg-final { cleanup-ipa-dump "cgraph" } } */
/* { dg-do compile } */
/* { dg-options "-O -fprofile-generate -fprofile-dir=. -fdump-ipa-profile" } */
/* { dg-final { scan-ipa-dump " ./profile-dir-3.gcda" "profile" } } */
/* { dg-options "-O -fprofile-generate -fprofile-dir=. -fdump-ipa-cgraph" } */
/* { dg-final { scan-ipa-dump " ./profile-dir-3.gcda" "cgraph" } } */
int
main(void)
......@@ -8,4 +8,4 @@ main(void)
return 0;
}
/* { dg-final { cleanup-ipa-dump "profile" } } */
/* { dg-final { cleanup-ipa-dump "cgraph" } } */
/* Test gcov weak ellision. */
/* { dg-options "-fprofile-arcs -ftest-coverage" } */
/* { dg-require-weak "" } */
/* { dg-do run { target native } } */
int __attribute__ ((weak)) weak ()
{
return 0; /* count(1) */
}
int main ()
{
return weak (); /* count(1) */
}
/* { dg-final { run-gcov { -a gcov-12.c } } } */
/* Test gcov weak ellision. */
/* { dg-options "-fprofile-arcs -ftest-coverage" } */
/* { dg-require-weak "" } */
/* { dg-do run { target native } } */
/* { dg-additional-sources "gcovpart-13b.c" } */
int __attribute__ ((weak)) weak ()
{
return 1; /* count(-) */
}
int main ()
{
return weak (); /* count(1) */
}
/* { dg-final { run-gcov { -a gcov-13.c } } } */
/* Test gcov extern inline. */
/* { dg-options "-O2 -fprofile-arcs -ftest-coverage" } */
/* { dg-require-weak "" } */
/* { dg-do run { target native } } */
extern int __attribute__ ((weak)) Foo ();
extern __inline int Foo ()
{
return 0; /* count(-) */
}
int (* __attribute__ ((noinline)) Bar ()) ()
{
return Foo; /* count(1) */
}
int main ()
{
return Bar () != 0; /* count(1) */
}
/* { dg-final { run-gcov { -a gcov-14.c } } } */
......@@ -33,7 +33,7 @@ if { ![is_remote host] && [string match "*/*" [lindex $GCC_UNDER_TEST 0]] } {
dg-init
# Delete old .gcda files.
set files [glob -nocomplain gcov-*.gcda]
set files [glob -nocomplain gcov*.gcda]
if { $files != "" } {
eval "remote_file build delete $files"
}
......
int weak ()
{
return 0; /* count(1) */
}
2011-11-07 Nathan Sidwell <nathan@acm.org>
* libgcov.c (struct gcov_fn_buffer): New struct.
(buffer_fn_data): New helper.
(gcov_exit): Rework for new gcov data structures.
2011-11-07 Georg-Johann Lay <avr@gjlay.de>
PR target/49313
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment