Commit 0790260e by Martin Liska Committed by Martin Liska

Simplify representation of locations of a block.

2017-04-28  Martin Liska  <mliska@suse.cz>

	* gcov.c (struct block_location_info): New struct.
	(process_file): Fill up the new structure.
	(read_graph_file): Replace usage of encoding by the newly added
	struct.
	(add_line_counts): Likewise.
	(accumulate_line_counts): Remove usage of the union.
	(function_info::function_info): New function.
	(function_info::~function_info): Likewise.
	(process_file): Call delete instead of release_function.
	(release_function): Release the function.
	(release_structures): Call delete instead of release_function.
	(solve_flow_graph): Replace usage of num_blocks.
	(find_exception_blocks): Likewise.
	(output_lines): Fix GNU coding style.

From-SVN: r247372
parent 4ebcdc23
2017-04-28 Martin Liska <mliska@suse.cz> 2017-04-28 Martin Liska <mliska@suse.cz>
* gcov.c (struct block_location_info): New struct.
(process_file): Fill up the new structure.
(read_graph_file): Replace usage of encoding by the newly added
struct.
(add_line_counts): Likewise.
(accumulate_line_counts): Remove usage of the union.
(function_info::function_info): New function.
(function_info::~function_info): Likewise.
(process_file): Call delete instead of release_function.
(release_function): Release the function.
(release_structures): Call delete instead of release_function.
(solve_flow_graph): Replace usage of num_blocks.
(find_exception_blocks): Likewise.
(output_lines): Fix GNU coding style.
2017-04-28 Martin Liska <mliska@suse.cz>
PR driver/56469 PR driver/56469
* coverage.c (coverage_remove_note_file): New function. * coverage.c (coverage_remove_note_file): New function.
* coverage.h: Declare the function. * coverage.h: Declare the function.
......
...@@ -114,6 +114,19 @@ typedef struct arc_info ...@@ -114,6 +114,19 @@ typedef struct arc_info
struct arc_info *pred_next; struct arc_info *pred_next;
} arc_t; } arc_t;
/* Describes which locations (lines and files) are associated with
a basic block. */
struct block_location_info
{
block_location_info (unsigned _source_file_idx):
source_file_idx (_source_file_idx)
{}
unsigned source_file_idx;
vector<unsigned> lines;
};
/* Describes a basic block. Contains lists of arcs to successor and /* Describes a basic block. Contains lists of arcs to successor and
predecessor blocks. */ predecessor blocks. */
...@@ -141,17 +154,8 @@ typedef struct block_info ...@@ -141,17 +154,8 @@ typedef struct block_info
/* Block is a landing pad for longjmp or throw. */ /* Block is a landing pad for longjmp or throw. */
unsigned is_nonlocal_return : 1; unsigned is_nonlocal_return : 1;
union vector<block_location_info> locations;
{
struct
{
/* Array of line numbers and source files. source files are
introduced by a linenumber of zero, the next 'line number' is
the number of the source file. Always starts with a source
file. */
unsigned *encoding;
unsigned num;
} line; /* Valid until blocks are linked onto lines */
struct struct
{ {
/* Single line graph cycle workspace. Used for all-blocks /* Single line graph cycle workspace. Used for all-blocks
...@@ -160,7 +164,6 @@ typedef struct block_info ...@@ -160,7 +164,6 @@ typedef struct block_info
unsigned ident; unsigned ident;
} cycle; /* Used in all-blocks mode, after blocks are linked onto } cycle; /* Used in all-blocks mode, after blocks are linked onto
lines. */ lines. */
} u;
/* Temporary chain for solving graph, and for chaining blocks on one /* Temporary chain for solving graph, and for chaining blocks on one
line. */ line. */
...@@ -172,6 +175,9 @@ typedef struct block_info ...@@ -172,6 +175,9 @@ typedef struct block_info
typedef struct function_info typedef struct function_info
{ {
function_info ();
~function_info ();
/* Name of function. */ /* Name of function. */
char *name; char *name;
char *demangled_name; char *demangled_name;
...@@ -186,8 +192,7 @@ typedef struct function_info ...@@ -186,8 +192,7 @@ typedef struct function_info
at blocks[0] and the exit block is at blocks[1]. */ at blocks[0] and the exit block is at blocks[1]. */
#define ENTRY_BLOCK (0) #define ENTRY_BLOCK (0)
#define EXIT_BLOCK (1) #define EXIT_BLOCK (1)
block_t *blocks; vector<block_t> blocks;
unsigned num_blocks;
unsigned blocks_executed; unsigned blocks_executed;
/* Raw arc coverage counts. */ /* Raw arc coverage counts. */
...@@ -427,9 +432,32 @@ static void output_lines (FILE *, const source_t *); ...@@ -427,9 +432,32 @@ static void output_lines (FILE *, const source_t *);
static char *make_gcov_file_name (const char *, const char *); static char *make_gcov_file_name (const char *, const char *);
static char *mangle_name (const char *, char *); static char *mangle_name (const char *, char *);
static void release_structures (void); static void release_structures (void);
static void release_function (function_t *);
extern int main (int, char **); extern int main (int, char **);
function_info::function_info ()
{
/* The type is POD, so that we can use memset. */
memset (this, 0, sizeof (*this));
}
function_info::~function_info ()
{
for (int i = blocks.size () - 1; i >= 0; i--)
{
arc_t *arc, *arc_n;
for (arc = blocks[i].succ; arc; arc = arc_n)
{
arc_n = arc->succ_next;
free (arc);
}
}
free (counts);
if (flag_demangled_names && demangled_name != name)
free (demangled_name);
free (name);
}
/* Cycle detection! /* Cycle detection!
There are a bajillion algorithms that do this. Boost's function is named There are a bajillion algorithms that do this. Boost's function is named
hawick_cycles, so I used the algorithm by K. A. Hawick and H. A. James in hawick_cycles, so I used the algorithm by K. A. Hawick and H. A. James in
...@@ -906,29 +934,26 @@ process_file (const char *file_name) ...@@ -906,29 +934,26 @@ process_file (const char *file_name)
*prev = fn; *prev = fn;
/* Mark last line in files touched by function. */ /* Mark last line in files touched by function. */
for (block_no = 0; block_no != fn->num_blocks; block_no++) for (block_no = 0; block_no != fn->blocks.size (); block_no++)
{ {
unsigned *enc = fn->blocks[block_no].u.line.encoding; block_t *block = &fn->blocks[block_no];
unsigned num = fn->blocks[block_no].u.line.num; for (unsigned i = 0; i < block->locations.size (); i++)
for (; num--; enc++)
if (!*enc)
{ {
if (enc[1] != src) unsigned s = block->locations[i].source_file_idx;
/* Sort lines of locations. */
sort (block->locations[i].lines.begin (),
block->locations[i].lines.end ());
if (!block->locations[i].lines.empty ())
{ {
if (line >= sources[src].num_lines) unsigned last_line
sources[src].num_lines = line + 1; = block->locations[i].lines.back () + 1;
line = 0; if (last_line > sources[s].num_lines)
src = enc[1]; sources[s].num_lines = last_line;
} }
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);
if (fn->has_catch) if (fn->has_catch)
...@@ -939,7 +964,7 @@ process_file (const char *file_name) ...@@ -939,7 +964,7 @@ process_file (const char *file_name)
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); delete fn;
} }
} }
...@@ -1040,31 +1065,6 @@ generate_results (const char *file_name) ...@@ -1040,31 +1065,6 @@ generate_results (const char *file_name)
executed_summary (total_lines, total_executed); executed_summary (total_lines, total_executed);
} }
/* 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);
if (flag_demangled_names && fn->demangled_name != fn->name)
free (fn->demangled_name);
free (fn->name);
}
/* Release all memory used. */ /* Release all memory used. */
static void static void
...@@ -1084,7 +1084,7 @@ release_structures (void) ...@@ -1084,7 +1084,7 @@ release_structures (void)
while ((fn = functions)) while ((fn = functions))
{ {
functions = fn->next; functions = fn->next;
release_function (fn); delete fn;
} }
} }
...@@ -1298,8 +1298,6 @@ read_graph_file (void) ...@@ -1298,8 +1298,6 @@ read_graph_file (void)
function_t *fn = NULL; function_t *fn = NULL;
function_t *fns = NULL; function_t *fns = NULL;
function_t **fns_end = &fns; function_t **fns_end = &fns;
unsigned src_idx = 0;
unsigned ix;
unsigned tag; unsigned tag;
if (!gcov_open (bbg_file_name, 1)) if (!gcov_open (bbg_file_name, 1))
...@@ -1343,10 +1341,10 @@ read_graph_file (void) ...@@ -1343,10 +1341,10 @@ read_graph_file (void)
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_idx = find_source (gcov_read_string ()); unsigned src_idx = find_source (gcov_read_string ());
lineno = gcov_read_unsigned (); lineno = gcov_read_unsigned ();
fn = XCNEW (function_t); fn = new function_t;
fn->name = function_name; fn->name = function_name;
if (flag_demangled_names) if (flag_demangled_names)
{ {
...@@ -1368,14 +1366,11 @@ read_graph_file (void) ...@@ -1368,14 +1366,11 @@ read_graph_file (void)
} }
else if (fn && tag == GCOV_TAG_BLOCKS) else if (fn && tag == GCOV_TAG_BLOCKS)
{ {
if (fn->blocks) if (!fn->blocks.empty ())
fnotice (stderr, "%s:already seen blocks for '%s'\n", fnotice (stderr, "%s:already seen blocks for '%s'\n",
bbg_file_name, fn->name); bbg_file_name, fn->name);
else else
{ fn->blocks.resize (gcov_read_unsigned ());
fn->num_blocks = gcov_read_unsigned ();
fn->blocks = XCNEWVEC (block_t, fn->num_blocks);
}
} }
else if (fn && tag == GCOV_TAG_ARCS) else if (fn && tag == GCOV_TAG_ARCS)
{ {
...@@ -1385,7 +1380,7 @@ read_graph_file (void) ...@@ -1385,7 +1380,7 @@ read_graph_file (void)
unsigned mark_catches = 0; unsigned mark_catches = 0;
struct arc_info *arc; struct arc_info *arc;
if (src >= fn->num_blocks || fn->blocks[src].succ) if (src >= fn->blocks.size () || fn->blocks[src].succ)
goto corrupt; goto corrupt;
while (num_dests--) while (num_dests--)
...@@ -1393,7 +1388,7 @@ read_graph_file (void) ...@@ -1393,7 +1388,7 @@ read_graph_file (void)
unsigned dest = gcov_read_unsigned (); unsigned dest = gcov_read_unsigned ();
unsigned flags = gcov_read_unsigned (); unsigned flags = gcov_read_unsigned ();
if (dest >= fn->num_blocks) if (dest >= fn->blocks.size ())
goto corrupt; goto corrupt;
arc = XCNEW (arc_t); arc = XCNEW (arc_t);
...@@ -1454,38 +1449,27 @@ read_graph_file (void) ...@@ -1454,38 +1449,27 @@ read_graph_file (void)
else if (fn && tag == GCOV_TAG_LINES) else if (fn && tag == GCOV_TAG_LINES)
{ {
unsigned blockno = gcov_read_unsigned (); unsigned blockno = gcov_read_unsigned ();
unsigned *line_nos = XCNEWVEC (unsigned, length - 1); block_t *block = &fn->blocks[blockno];
if (blockno >= fn->num_blocks || fn->blocks[blockno].u.line.encoding) if (blockno >= fn->blocks.size ())
goto corrupt; goto corrupt;
for (ix = 0; ; ) while (true)
{ {
unsigned lineno = gcov_read_unsigned (); unsigned lineno = gcov_read_unsigned ();
if (lineno) if (lineno)
{ block->locations.back ().lines.push_back (lineno);
if (!ix)
{
line_nos[ix++] = 0;
line_nos[ix++] = src_idx;
}
line_nos[ix++] = lineno;
}
else else
{ {
const char *file_name = gcov_read_string (); const char *file_name = gcov_read_string ();
if (!file_name) if (!file_name)
break; break;
src_idx = find_source (file_name); block->locations.push_back (block_location_info
line_nos[ix++] = 0; (find_source (file_name)));
line_nos[ix++] = src_idx;
} }
} }
fn->blocks[blockno].u.line.encoding = line_nos;
fn->blocks[blockno].u.line.num = ix;
} }
else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag)) else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
{ {
...@@ -1643,7 +1627,7 @@ solve_flow_graph (function_t *fn) ...@@ -1643,7 +1627,7 @@ solve_flow_graph (function_t *fn)
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. */ /* The arcs were built in reverse order. Fix that now. */
for (ix = fn->num_blocks; ix--;) for (ix = fn->blocks.size (); ix--;)
{ {
arc_t *arc_p, *arc_n; arc_t *arc_p, *arc_n;
...@@ -1664,7 +1648,7 @@ solve_flow_graph (function_t *fn) ...@@ -1664,7 +1648,7 @@ solve_flow_graph (function_t *fn)
fn->blocks[ix].pred = arc_p; fn->blocks[ix].pred = arc_p;
} }
if (fn->num_blocks < 2) if (fn->blocks.size () < 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);
else else
...@@ -1688,8 +1672,9 @@ solve_flow_graph (function_t *fn) ...@@ -1688,8 +1672,9 @@ solve_flow_graph (function_t *fn)
/* Propagate the measured counts, this must be done in the same /* Propagate the measured counts, this must be done in the same
order as the code in profile.c */ order as the code in profile.c */
for (ix = 0, blk = fn->blocks; ix != fn->num_blocks; ix++, blk++) for (unsigned i = 0; i < fn->blocks.size (); i++)
{ {
blk = &fn->blocks[i];
block_t const *prev_dst = NULL; block_t const *prev_dst = NULL;
int out_of_order = 0; int out_of_order = 0;
int non_fake_succ = 0; int non_fake_succ = 0;
...@@ -1883,8 +1868,8 @@ solve_flow_graph (function_t *fn) ...@@ -1883,8 +1868,8 @@ solve_flow_graph (function_t *fn)
/* If the graph has been correctly solved, every block will have a /* If the graph has been correctly solved, every block will have a
valid count. */ valid count. */
for (ix = 0; ix < fn->num_blocks; ix++) for (unsigned i = 0; ix < fn->blocks.size (); i++)
if (!fn->blocks[ix].count_valid) if (!fn->blocks[i].count_valid)
{ {
fnotice (stderr, "%s:graph is unsolvable for '%s'\n", fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
bbg_file_name, fn->name); bbg_file_name, fn->name);
...@@ -1898,14 +1883,14 @@ static void ...@@ -1898,14 +1883,14 @@ static void
find_exception_blocks (function_t *fn) find_exception_blocks (function_t *fn)
{ {
unsigned ix; unsigned ix;
block_t **queue = XALLOCAVEC (block_t *, fn->num_blocks); block_t **queue = XALLOCAVEC (block_t *, fn->blocks.size ());
/* First mark all blocks as exceptional. */ /* First mark all blocks as exceptional. */
for (ix = fn->num_blocks; ix--;) for (ix = fn->blocks.size (); ix--;)
fn->blocks[ix].exceptional = 1; fn->blocks[ix].exceptional = 1;
/* Now mark all the blocks reachable via non-fake edges */ /* Now mark all the blocks reachable via non-fake edges */
queue[0] = fn->blocks; queue[0] = &fn->blocks[0];
queue[0]->exceptional = 0; queue[0]->exceptional = 0;
for (ix = 1; ix;) for (ix = 1; ix;)
{ {
...@@ -2247,26 +2232,19 @@ add_line_counts (coverage_t *coverage, function_t *fn) ...@@ -2247,26 +2232,19 @@ add_line_counts (coverage_t *coverage, function_t *fn)
next. */ next. */
/* Scan each basic block. */ /* Scan each basic block. */
for (ix = 0; ix != fn->num_blocks; ix++) for (ix = 0; ix != fn->blocks.size (); ix++)
{ {
block_t *block = &fn->blocks[ix]; block_t *block = &fn->blocks[ix];
unsigned *encoding; if (block->count && ix && ix + 1 != fn->blocks.size ())
const source_t *src = NULL;
unsigned jx;
if (block->count && ix && ix + 1 != fn->num_blocks)
fn->blocks_executed++; fn->blocks_executed++;
for (jx = 0, encoding = block->u.line.encoding; for (unsigned i = 0; i < block->locations.size (); i++)
jx != block->u.line.num; jx++, encoding++)
if (!*encoding)
{ {
src = &sources[*++encoding]; const source_t *src = &sources[block->locations[i].source_file_idx];
jx++;
}
else
{
line = &src->lines[*encoding];
vector<unsigned> &lines = block->locations[i].lines;
for (unsigned j = 0; j < lines.size (); j++)
{
line = &src->lines[lines[j]];
if (coverage) if (coverage)
{ {
if (!line->exists) if (!line->exists)
...@@ -2279,11 +2257,11 @@ add_line_counts (coverage_t *coverage, function_t *fn) ...@@ -2279,11 +2257,11 @@ add_line_counts (coverage_t *coverage, function_t *fn)
line->unexceptional = 1; line->unexceptional = 1;
line->count += block->count; line->count += block->count;
} }
free (block->u.line.encoding); }
block->u.cycle.arc = NULL; block->cycle.arc = NULL;
block->u.cycle.ident = ~0U; block->cycle.ident = ~0U;
if (!ix || ix + 1 == fn->num_blocks) if (!ix || ix + 1 == fn->blocks.size ())
/* Entry or exit block */; /* Entry or exit block */;
else if (flag_all_blocks) else if (flag_all_blocks)
{ {
...@@ -2363,7 +2341,7 @@ accumulate_line_counts (source_t *src) ...@@ -2363,7 +2341,7 @@ accumulate_line_counts (source_t *src)
{ {
block_n = block->chain; block_n = block->chain;
block->chain = block_p; block->chain = block_p;
block->u.cycle.ident = ix; block->cycle.ident = ix;
} }
line->u.blocks = block_p; line->u.blocks = block_p;
...@@ -2533,7 +2511,8 @@ output_lines (FILE *gcov_file, const source_t *src) ...@@ -2533,7 +2511,8 @@ output_lines (FILE *gcov_file, const source_t *src)
fprintf (gcov_file, " returned %s", fprintf (gcov_file, " returned %s",
format_gcov (return_count, called_count, 0)); format_gcov (return_count, called_count, 0));
fprintf (gcov_file, " blocks executed %s", fprintf (gcov_file, " blocks executed %s",
format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0)); format_gcov (fn->blocks_executed, fn->blocks.size () - 2,
0));
fprintf (gcov_file, "\n"); fprintf (gcov_file, "\n");
} }
......
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