Commit 1ce1b792 by Nathan Sidwell

gcov.c (struct function_info): Make src an index, not a pointer.

	* gcov.c (struct function_info): Make src an index, not a pointer.
	(struct source_info): Remove index and next source fields.
	(fn_end): New static var.
	(sources_index): Remove.
	(sources): Now a pointer to an array, not a list.
	(n_sources, a_sources): New.
	(process_file): Adjust for changes to read_graph_file. Insert
	functions into source lists and check line numbers here.
	(generate_results): Only allocate lines for sources with
	contents.  Adjust for source array.
	(release_structures): Likewise.
	(find_source): Return source index, adjust for source array.
	(read_graph_file): Return function list.  Don't insert into source
	lists here.
	(read_count_file): Take list of functions.
	(solve_flow_graph): Reverse the arc lists here.
	(add_line_counts): Adjust for source array.

From-SVN: r181265
parent ea17de23
2011-11-10 Nathan Sidwell <nathan@acm.org>
* gcov.c (struct function_info): Make src an index, not a pointer.
(struct source_info): Remove index and next source fields.
(fn_end): New static var.
(sources_index): Remove.
(sources): Now a pointer to an array, not a list.
(n_sources, a_sources): New.
(process_file): Adjust for changes to read_graph_file. Insert
functions into source lists and check line numbers here.
(generate_results): Only allocate lines for sources with
contents. Adjust for source array.
(release_structures): Likewise.
(find_source): Return source index, adjust for source array.
(read_graph_file): Return function list. Don't insert into source
lists here.
(read_count_file): Take list of functions.
(solve_flow_graph): Reverse the arc lists here.
(add_line_counts): Adjust for source array.
2011-11-10 Jakub Jelinek <jakub@redhat.com> 2011-11-10 Jakub Jelinek <jakub@redhat.com>
PR middle-end/51077 PR middle-end/51077
...@@ -7,8 +27,8 @@ ...@@ -7,8 +27,8 @@
2011-11-10 Andrew MacLeod <amacleod@redhat.com> 2011-11-10 Andrew MacLeod <amacleod@redhat.com>
PR rtl-optimization/51040 PR rtl-optimization/51040
* optabs.c (expand_atomic_fetch_op): Patchup code for NAND should be AND * optabs.c (expand_atomic_fetch_op): Patchup code for NAND should
followed by NOT. be AND followed by NOT.
* builtins.c (expand_builtin_atomic_fetch_op): Patchup code for NAND * builtins.c (expand_builtin_atomic_fetch_op): Patchup code for NAND
should be AND followed by NOT. should be AND followed by NOT.
* testsuite/gcc.dg/atomic-noinline[-aux].c: Test no-inline NAND and * testsuite/gcc.dg/atomic-noinline[-aux].c: Test no-inline NAND and
...@@ -181,9 +181,9 @@ typedef struct function_info ...@@ -181,9 +181,9 @@ typedef struct function_info
gcov_type *counts; gcov_type *counts;
unsigned num_counts; unsigned num_counts;
/* First line number. */ /* First line number & file. */
unsigned line; unsigned line;
struct source_info *src; unsigned src;
/* Next function in same source file. */ /* Next function in same source file. */
struct function_info *line_next; struct function_info *line_next;
...@@ -233,7 +233,6 @@ typedef struct source_info ...@@ -233,7 +233,6 @@ typedef struct source_info
{ {
/* Name of source file. */ /* Name of source file. */
char *name; char *name;
unsigned index;
time_t file_time; time_t file_time;
/* Array of line information. */ /* Array of line information. */
...@@ -245,23 +244,16 @@ typedef struct source_info ...@@ -245,23 +244,16 @@ typedef struct source_info
/* Functions in this source file. These are in ascending line /* Functions in this source file. These are in ascending line
number order. */ number order. */
function_t *functions; function_t *functions;
/* Next source file. */
struct source_info *next;
} source_t; } source_t;
/* Holds a list of function basic block graphs. */ /* Holds a list of function basic block graphs. */
static function_t *functions; static function_t *functions;
static function_t **fn_end = &functions;
/* This points to the head of the sourcefile structure list. New elements static source_t *sources; /* Array of source files */
are always prepended. */ static unsigned n_sources; /* Number of sources */
static unsigned a_sources; /* Allocated sources */
static source_t *sources;
/* Next index for a source file. */
static unsigned source_index;
/* This holds data summary information. */ /* This holds data summary information. */
...@@ -349,9 +341,9 @@ static void print_version (void) ATTRIBUTE_NORETURN; ...@@ -349,9 +341,9 @@ static void print_version (void) ATTRIBUTE_NORETURN;
static void process_file (const char *); static void process_file (const char *);
static void generate_results (const char *); static void generate_results (const char *);
static void create_file_names (const char *); static void create_file_names (const char *);
static source_t *find_source (const char *); static unsigned find_source (const char *);
static int read_graph_file (void); static function_t *read_graph_file (void);
static int read_count_file (void); static int read_count_file (function_t *);
static void solve_flow_graph (function_t *); static void solve_flow_graph (function_t *);
static void add_branch_counts (coverage_t *, const arc_t *); static void add_branch_counts (coverage_t *, const arc_t *);
static void add_line_counts (coverage_t *, function_t *); static void add_line_counts (coverage_t *, function_t *);
...@@ -537,57 +529,85 @@ process_args (int argc, char **argv) ...@@ -537,57 +529,85 @@ process_args (int argc, char **argv)
static void static void
process_file (const char *file_name) process_file (const char *file_name)
{ {
function_t *fn; function_t *fns;
function_t **fn_p;
function_t *old_functions;
/* Save and clear the list of current functions. They will be appended
later. */
old_functions = functions;
functions = NULL;
create_file_names (file_name); create_file_names (file_name);
if (read_graph_file ()) fns = read_graph_file ();
if (!fns)
return; return;
if (!functions) read_count_file (fns);
while (fns)
{ {
fnotice (stderr, "%s:no functions found\n", bbg_file_name); function_t *fn = fns;
return;
}
if (read_count_file ())
return;
fn_p = &functions; fns = fn->next;
while ((fn = *fn_p) != NULL) fn->next = NULL;
{
if (fn->counts) if (fn->counts)
{ {
unsigned src = fn->src;
unsigned line = fn->line;
unsigned block_no;
function_t *probe, **prev;
/* Now insert it into the source file's list of
functions. Normally functions will be encountered in
ascending order, so a simple scan is quick. Note we're
building this list in reverse order. */
for (prev = &sources[src].functions;
(probe = *prev); prev = &probe->line_next)
if (probe->line <= line)
break;
fn->line_next = probe;
*prev = fn;
/* Mark last line in files touched by function. */
for (block_no = 0; block_no != fn->num_blocks; block_no++)
{
unsigned *enc = fn->blocks[block_no].u.line.encoding;
unsigned num = fn->blocks[block_no].u.line.num;
for (; num--; enc++)
if (!*enc)
{
if (enc[1] != src)
{
if (line >= sources[src].num_lines)
sources[src].num_lines = line + 1;
line = 0;
src = enc[1];
}
enc++;
num--;
}
else if (*enc > line)
line = *enc;
}
if (line >= sources[src].num_lines)
sources[src].num_lines = line + 1;
solve_flow_graph (fn); solve_flow_graph (fn);
fn_p = &fn->next; *fn_end = fn;
fn_end = &fn->next;
} }
else else
{ /* The function was not in the executable -- some other
/* The function was not in the executable -- some other instance must have been selected. */
instance must have been selected. */ release_function (fn);
function_t *next = fn->next;
release_function (fn);
*fn_p = next;
}
} }
*fn_p = old_functions;
} }
static void static void
generate_results (const char *file_name) generate_results (const char *file_name)
{ {
unsigned ix;
source_t *src; source_t *src;
function_t *fn; function_t *fn;
for (src = sources; src; src = src->next) for (ix = n_sources, src = sources; ix--; src++)
src->lines = XCNEWVEC (line_t, src->num_lines); if (src->num_lines)
src->lines = XCNEWVEC (line_t, src->num_lines);
for (fn = functions; fn; fn = fn->next) for (fn = functions; fn; fn = fn->next)
{ {
coverage_t coverage; coverage_t coverage;
...@@ -602,7 +622,7 @@ generate_results (const char *file_name) ...@@ -602,7 +622,7 @@ generate_results (const char *file_name)
} }
} }
for (src = sources; src; src = src->next) for (ix = n_sources, src = sources; ix--; src++)
{ {
accumulate_line_counts (src); accumulate_line_counts (src);
function_summary (&src->coverage, "File"); function_summary (&src->coverage, "File");
...@@ -657,15 +677,13 @@ release_function (function_t *fn) ...@@ -657,15 +677,13 @@ release_function (function_t *fn)
static void static void
release_structures (void) release_structures (void)
{ {
unsigned ix;
function_t *fn; function_t *fn;
source_t *src;
while ((src = sources)) for (ix = n_sources; ix--;)
{ {
sources = src->next; free (sources[ix].name);
free (sources[ix].lines);
free (src->name);
free (src->lines);
} }
while ((fn = functions)) while ((fn = functions))
...@@ -746,28 +764,40 @@ create_file_names (const char *file_name) ...@@ -746,28 +764,40 @@ create_file_names (const char *file_name)
/* Find or create a source file structure for FILE_NAME. Copies /* Find or create a source file structure for FILE_NAME. Copies
FILE_NAME on creation */ FILE_NAME on creation */
static source_t * static unsigned
find_source (const char *file_name) find_source (const char *file_name)
{ {
source_t *src; unsigned ix;
source_t *src = 0;
struct stat status; struct stat status;
if (!file_name) if (!file_name)
file_name = "<unknown>"; file_name = "<unknown>";
for (src = sources; src; src = src->next) for (ix = n_sources; ix--;)
if (!filename_cmp (file_name, src->name)) if (!filename_cmp (file_name, sources[ix].name))
break; {
src = &sources[ix];
break;
}
if (!src) if (!src)
{ {
src = XCNEW (source_t); if (n_sources == a_sources)
{
if (!a_sources)
a_sources = 10;
a_sources *= 2;
src = XNEWVEC (source_t, a_sources);
memcpy (src, sources, n_sources * sizeof (*sources));
free (sources);
sources = src;
}
ix = n_sources;
src = &sources[ix];
src->name = xstrdup (file_name); src->name = xstrdup (file_name);
src->coverage.name = src->name; src->coverage.name = src->name;
src->index = source_index++; n_sources++;
src->next = sources;
sources = src;
if (!stat (file_name, &status)) if (!stat (file_name, &status))
src->file_time = status.st_mtime; src->file_time = status.st_mtime;
} }
...@@ -787,33 +817,34 @@ find_source (const char *file_name) ...@@ -787,33 +817,34 @@ find_source (const char *file_name)
src->file_time = 0; src->file_time = 0;
} }
return src; return ix;
} }
/* Read the graph file. Return nonzero on fatal error. */ /* Read the graph file. Return list of functions read -- in reverse order. */
static int static function_t *
read_graph_file (void) read_graph_file (void)
{ {
unsigned version; unsigned version;
unsigned current_tag = 0; unsigned current_tag = 0;
struct function_info *fn = NULL; function_t *fn = NULL;
function_t *old_functions_head = functions; function_t *fns = NULL;
source_t *src = NULL; function_t **fns_end = &fns;
unsigned src_idx = 0;
unsigned ix; unsigned ix;
unsigned tag; unsigned tag;
if (!gcov_open (bbg_file_name, 1)) if (!gcov_open (bbg_file_name, 1))
{ {
fnotice (stderr, "%s:cannot open graph file\n", bbg_file_name); fnotice (stderr, "%s:cannot open graph file\n", bbg_file_name);
return 1; return fns;
} }
bbg_file_time = gcov_time (); bbg_file_time = gcov_time ();
if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC)) if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
{ {
fnotice (stderr, "%s:not a gcov graph file\n", bbg_file_name); fnotice (stderr, "%s:not a gcov graph file\n", bbg_file_name);
gcov_close (); gcov_close ();
return 1; return fns;
} }
version = gcov_read_unsigned (); version = gcov_read_unsigned ();
...@@ -839,14 +870,12 @@ read_graph_file (void) ...@@ -839,14 +870,12 @@ read_graph_file (void)
char *function_name; char *function_name;
unsigned ident, lineno; unsigned ident, lineno;
unsigned lineno_checksum, cfg_checksum; unsigned lineno_checksum, cfg_checksum;
source_t *src;
function_t *probe, *prev;
ident = gcov_read_unsigned (); ident = gcov_read_unsigned ();
lineno_checksum = gcov_read_unsigned (); lineno_checksum = gcov_read_unsigned ();
cfg_checksum = gcov_read_unsigned (); cfg_checksum = gcov_read_unsigned ();
function_name = xstrdup (gcov_read_string ()); function_name = xstrdup (gcov_read_string ());
src = find_source (gcov_read_string ()); src_idx = find_source (gcov_read_string ());
lineno = gcov_read_unsigned (); lineno = gcov_read_unsigned ();
fn = XCNEW (function_t); fn = XCNEW (function_t);
...@@ -854,27 +883,14 @@ read_graph_file (void) ...@@ -854,27 +883,14 @@ read_graph_file (void)
fn->ident = ident; fn->ident = ident;
fn->lineno_checksum = lineno_checksum; fn->lineno_checksum = lineno_checksum;
fn->cfg_checksum = cfg_checksum; fn->cfg_checksum = cfg_checksum;
fn->src = src; fn->src = src_idx;
fn->line = lineno; fn->line = lineno;
fn->next = functions; fn->line_next = NULL;
functions = fn; fn->next = NULL;
*fns_end = fn;
fns_end = &fn->next;
current_tag = tag; current_tag = tag;
if (lineno >= src->num_lines)
src->num_lines = lineno + 1;
/* Now insert it into the source file's list of
functions. Normally functions will be encountered in
ascending order, so a simple scan is quick. */
for (probe = src->functions, prev = NULL;
probe && probe->line > lineno;
prev = probe, probe = probe->line_next)
continue;
fn->line_next = probe;
if (prev)
prev->line_next = fn;
else
src->functions = fn;
} }
else if (fn && tag == GCOV_TAG_BLOCKS) else if (fn && tag == GCOV_TAG_BLOCKS)
{ {
...@@ -966,11 +982,9 @@ read_graph_file (void) ...@@ -966,11 +982,9 @@ read_graph_file (void)
if (!ix) if (!ix)
{ {
line_nos[ix++] = 0; line_nos[ix++] = 0;
line_nos[ix++] = src->index; line_nos[ix++] = src_idx;
} }
line_nos[ix++] = lineno; line_nos[ix++] = lineno;
if (lineno >= src->num_lines)
src->num_lines = lineno + 1;
} }
else else
{ {
...@@ -978,10 +992,9 @@ read_graph_file (void) ...@@ -978,10 +992,9 @@ read_graph_file (void)
if (!file_name) if (!file_name)
break; break;
src = find_source (file_name); src_idx = find_source (file_name);
line_nos[ix++] = 0; line_nos[ix++] = 0;
line_nos[ix++] = src->index; line_nos[ix++] = src_idx;
} }
} }
...@@ -998,72 +1011,22 @@ read_graph_file (void) ...@@ -998,72 +1011,22 @@ read_graph_file (void)
{ {
corrupt:; corrupt:;
fnotice (stderr, "%s:corrupted\n", bbg_file_name); fnotice (stderr, "%s:corrupted\n", bbg_file_name);
gcov_close (); break;
return 1;
} }
} }
gcov_close (); gcov_close ();
/* We built everything backwards, so nreverse them all. */ if (!fns)
fnotice (stderr, "%s:no functions found\n", bbg_file_name);
/* Reverse sources. Not strictly necessary, but we'll then process
them in the 'expected' order. */
{
source_t *src, *src_p, *src_n;
for (src_p = NULL, src = sources; src; src_p = src, src = src_n)
{
src_n = src->next;
src->next = src_p;
}
sources = src_p;
}
/* Reverse functions. */
{
function_t *fn, *fn_p, *fn_n;
for (fn_p = old_functions_head, fn = functions;
fn != old_functions_head;
fn_p = fn, fn = fn_n)
{
unsigned ix;
fn_n = fn->next;
fn->next = fn_p;
/* Reverse the arcs. */ return fns;
for (ix = fn->num_blocks; ix--;)
{
arc_t *arc, *arc_p, *arc_n;
for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
arc_p = arc, arc = arc_n)
{
arc_n = arc->succ_next;
arc->succ_next = arc_p;
}
fn->blocks[ix].succ = arc_p;
for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
arc_p = arc, arc = arc_n)
{
arc_n = arc->pred_next;
arc->pred_next = arc_p;
}
fn->blocks[ix].pred = arc_p;
}
}
functions = fn_p;
}
return 0;
} }
/* Reads profiles from the count file and attach to each /* Reads profiles from the count file and attach to each
function. Return nonzero if fatal error. */ function. Return nonzero if fatal error. */
static int static int
read_count_file (void) read_count_file (function_t *fns)
{ {
unsigned ix; unsigned ix;
unsigned version; unsigned version;
...@@ -1125,7 +1088,7 @@ read_count_file (void) ...@@ -1125,7 +1088,7 @@ read_count_file (void)
/* Try to find the function in the list. To speed up the /* Try to find the function in the list. To speed up the
search, first start from the last function found. */ search, first start from the last function found. */
ident = gcov_read_unsigned (); ident = gcov_read_unsigned ();
fn_n = functions; fn_n = fns;
for (fn = fn ? fn->next : NULL; ; fn = fn->next) for (fn = fn ? fn->next : NULL; ; fn = fn->next)
{ {
if (fn) if (fn)
...@@ -1190,6 +1153,28 @@ solve_flow_graph (function_t *fn) ...@@ -1190,6 +1153,28 @@ solve_flow_graph (function_t *fn)
block_t *valid_blocks = NULL; /* valid, but unpropagated blocks. */ block_t *valid_blocks = NULL; /* valid, but unpropagated blocks. */
block_t *invalid_blocks = NULL; /* invalid, but inferable blocks. */ block_t *invalid_blocks = NULL; /* invalid, but inferable blocks. */
/* The arcs were built in reverse order. Fix that now. */
for (ix = fn->num_blocks; ix--;)
{
arc_t *arc_p, *arc_n;
for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
arc_p = arc, arc = arc_n)
{
arc_n = arc->succ_next;
arc->succ_next = arc_p;
}
fn->blocks[ix].succ = arc_p;
for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
arc_p = arc, arc = arc_n)
{
arc_n = arc->pred_next;
arc->pred_next = arc_p;
}
fn->blocks[ix].pred = arc_p;
}
if (fn->num_blocks < 2) if (fn->num_blocks < 2)
fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n", fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n",
bbg_file_name, fn->name); bbg_file_name, fn->name);
...@@ -1643,10 +1628,7 @@ add_line_counts (coverage_t *coverage, function_t *fn) ...@@ -1643,10 +1628,7 @@ add_line_counts (coverage_t *coverage, function_t *fn)
jx != block->u.line.num; jx++, encoding++) jx != block->u.line.num; jx++, encoding++)
if (!*encoding) if (!*encoding)
{ {
unsigned src_n = *++encoding; src = &sources[*++encoding];
for (src = sources; src->index != src_n; src = src->next)
continue;
jx++; jx++;
} }
else else
...@@ -1671,7 +1653,10 @@ add_line_counts (coverage_t *coverage, function_t *fn) ...@@ -1671,7 +1653,10 @@ add_line_counts (coverage_t *coverage, function_t *fn)
/* Entry or exit block */; /* Entry or exit block */;
else if (flag_all_blocks) else if (flag_all_blocks)
{ {
line_t *block_line = line ? line : &fn->src->lines[fn->line]; line_t *block_line = line;
if (!block_line)
block_line = &sources[fn->src].lines[fn->line];
block->chain = block_line->u.blocks; block->chain = block_line->u.blocks;
block_line->u.blocks = block; block_line->u.blocks = block;
......
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