gcov.c: Add -a & -u options.
* gcov.c: Add -a & -u options. (struct arc_info): Add local_span, is_call_non_return, is_nonlocal_return, is_unconditional flags, remove is_call flag. (struct block_info): Add flags, is_call_site, is_nonlocal_return members. Make encodings a union with span member. (struct function_info): Add blocks_executed, line, src, line_next members. (struct coverage_info): Make branches a union with blocks member. (struct source_info): Add functions member. (object_summary, program_count): New global variables. (flag_all_blocks, flag_unconditional): New flags. (find_source, output_branch_count): New functions. (print_usage): Adjust. (options): Adjust. (process_args): Adjust. (read_graph_file) <GCOV_TAG_FUNCTION>: Adjust. <GCOV_TAG_BLOCKS>: Read flags. <GCOV_TAG_LINES>: Adjust. (read_count_file): Process SUMMARY tags. (solve_flow_graph): Set is_unconditional and clear is_call_site appropriately. (add_branch_counts): Adjust. Don't count unconditional branches. (add_line_counts): Deal with all-blocks mode, accumulate block coverage. (accumulate_line_counts): Adjust, generate local spanning tree for all-blocks mode. (output_lines): Adjust. * profile.c (branch_prob): Alter GCOV_FUNCTION_TAG record. * doc/gcov.texi: Document. testsuite: * lib/gcov.exp: Adjust call return testing strings. * g77.dg/gcov/gcov-1.f: Don't expect unconditional branches. From-SVN: r65090
This commit is contained in:
parent
212d93131f
commit
27283c7340
|
@ -1,3 +1,35 @@
|
|||
2003-03-31 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
* gcov.c: Add -a & -u options.
|
||||
(struct arc_info): Add local_span, is_call_non_return,
|
||||
is_nonlocal_return, is_unconditional flags, remove is_call flag.
|
||||
(struct block_info): Add flags, is_call_site, is_nonlocal_return
|
||||
members. Make encodings a union with span member.
|
||||
(struct function_info): Add blocks_executed, line, src, line_next
|
||||
members.
|
||||
(struct coverage_info): Make branches a union with blocks member.
|
||||
(struct source_info): Add functions member.
|
||||
(object_summary, program_count): New global variables.
|
||||
(flag_all_blocks, flag_unconditional): New flags.
|
||||
(find_source, output_branch_count): New functions.
|
||||
(print_usage): Adjust.
|
||||
(options): Adjust.
|
||||
(process_args): Adjust.
|
||||
(read_graph_file) <GCOV_TAG_FUNCTION>: Adjust.
|
||||
<GCOV_TAG_BLOCKS>: Read flags.
|
||||
<GCOV_TAG_LINES>: Adjust.
|
||||
(read_count_file): Process SUMMARY tags.
|
||||
(solve_flow_graph): Set is_unconditional and clear is_call_site
|
||||
appropriately.
|
||||
(add_branch_counts): Adjust. Don't count unconditional branches.
|
||||
(add_line_counts): Deal with all-blocks mode, accumulate block
|
||||
coverage.
|
||||
(accumulate_line_counts): Adjust, generate local spanning tree for
|
||||
all-blocks mode.
|
||||
(output_lines): Adjust.
|
||||
* profile.c (branch_prob): Alter GCOV_FUNCTION_TAG record.
|
||||
* doc/gcov.texi: Document.
|
||||
|
||||
2003-03-31 Kazu Hirata <kazu@cs.umass.edu>
|
||||
|
||||
* config/h8300/h8300.md: Organize peephole2's that trasform
|
||||
|
|
|
@ -120,6 +120,7 @@ gcov @r{[}@var{options}@r{]} @var{sourcefile}
|
|||
@ignore
|
||||
@c man begin SYNOPSIS
|
||||
gcov [@option{-v}|@option{--version}] [@option{-h}|@option{--help}]
|
||||
[@option{-a}|@option{--all-blocks}]
|
||||
[@option{-b}|@option{--branch-probabilities}]
|
||||
[@option{-c}|@option{--branch-counts}]
|
||||
[@option{-n}|@option{--no-output}]
|
||||
|
@ -127,6 +128,7 @@ gcov [@option{-v}|@option{--version}] [@option{-h}|@option{--help}]
|
|||
[@option{-p}|@option{--preserve-paths}]
|
||||
[@option{-f}|@option{--function-summaries}]
|
||||
[@option{-o}|@option{--object-directory} @var{directory|file}] @var{sourcefile}
|
||||
[@option{-u}|@option{--unconditional-branches}]
|
||||
@c man end
|
||||
@c man begin SEEALSO
|
||||
gpl(7), gfdl(7), fsf-funding(7), gcc(1) and the Info entry for @file{gcc}.
|
||||
|
@ -145,11 +147,23 @@ exit without doing any further processing.
|
|||
Display the @command{gcov} version number (on the standard output),
|
||||
and exit without doing any further processing.
|
||||
|
||||
@item -a
|
||||
@itemx --all-blocks
|
||||
Write individual execution counts for every basic block. Normally gcov
|
||||
outputs execution counts only for the main blocks of a line. With this
|
||||
option you can determine if blocks within a single line are not being
|
||||
executed. In this mode each block is shown, and contributes to the
|
||||
occupancy and execution count of, the first line of source that it
|
||||
contains. A multi-line block will only contribute to that first line,
|
||||
and other lines will not be show to contain code, unless a subsequent
|
||||
block begins on those lines.
|
||||
|
||||
@item -b
|
||||
@itemx --branch-probabilities
|
||||
Write branch frequencies to the output file, and write branch summary
|
||||
info to the standard output. This option allows you to see how often
|
||||
each branch in your program was taken.
|
||||
each branch in your program was taken. Unconditional branches will not
|
||||
be shown, unless the @option{-u} option is given.
|
||||
|
||||
@item -c
|
||||
@itemx --branch-counts
|
||||
|
@ -192,6 +206,11 @@ source file name, without its extension. If a file is specified here,
|
|||
the data files are named after that file, without its extension. If this
|
||||
option is not supplied, it defaults to the current directory.
|
||||
|
||||
@item -u
|
||||
@itemx --unconditional-branches
|
||||
When branch counts are given, include those of unconditional branches.
|
||||
Unconditional branches are normally not interesting.
|
||||
|
||||
@end table
|
||||
|
||||
Gcov should be run with the current directory the same as that when you
|
||||
|
@ -248,10 +267,14 @@ Here is a sample:
|
|||
|
||||
@smallexample
|
||||
-: 0:Source:tmp.c
|
||||
-: 0:Object:tmp.bb
|
||||
-: 0:Graph:tmp.bbg
|
||||
-: 0:Data:tmp.da
|
||||
-: 0:Runs:1
|
||||
-: 0:Programs:1
|
||||
-: 1:#include <stdio.h>
|
||||
-: 2:
|
||||
-: 3:int main (void)
|
||||
function main called 1 returned 1 blocks executed 75%
|
||||
1: 4:@{
|
||||
1: 5: int i, total;
|
||||
-: 6:
|
||||
|
@ -265,9 +288,47 @@ Here is a sample:
|
|||
-: 14: else
|
||||
1: 15: printf ("Success\n");
|
||||
1: 16: return 0;
|
||||
1: 17:@}
|
||||
-: 17:@}
|
||||
@end smallexample
|
||||
|
||||
When you use the @option{-a} option, you will get individual block
|
||||
counts, and the output looks like this:
|
||||
|
||||
@smallexample
|
||||
-: 0:Source:tmp.c
|
||||
-: 0:Graph:tmp.bbg
|
||||
-: 0:Data:tmp.da
|
||||
-: 0:Runs:1
|
||||
-: 0:Programs:1
|
||||
-: 1:#include <stdio.h>
|
||||
-: 2:
|
||||
-: 3:int main (void)
|
||||
function main called 1 returned 1 blocks executed 75%
|
||||
1: 4:@{
|
||||
1: 4-block 0
|
||||
1: 5: int i, total;
|
||||
-: 6:
|
||||
1: 7: total = 0;
|
||||
-: 8:
|
||||
11: 9: for (i = 0; i < 10; i++)
|
||||
11: 9-block 0
|
||||
10: 10: total += i;
|
||||
10: 10-block 0
|
||||
-: 11:
|
||||
1: 12: if (total != 45)
|
||||
1: 12-block 0
|
||||
#####: 13: printf ("Failure\n");
|
||||
$$$$$: 13-block 0
|
||||
-: 14: else
|
||||
1: 15: printf ("Success\n");
|
||||
1: 15-block 0
|
||||
1: 16: return 0;
|
||||
1: 16-block 0
|
||||
-: 17:@}
|
||||
@end smallexample
|
||||
|
||||
As you can see, line 13 contains a basic block that was not executed.
|
||||
|
||||
@need 450
|
||||
When you use the @option{-b} option, your output looks like this:
|
||||
|
||||
|
@ -284,31 +345,34 @@ Here is a sample of a resulting @file{tmp.c.gcov} file:
|
|||
|
||||
@smallexample
|
||||
-: 0:Source:tmp.c
|
||||
-: 0:Object:tmp.bb
|
||||
-: 0:Graph:tmp.bbg
|
||||
-: 0:Data:tmp.da
|
||||
-: 0:Runs:1
|
||||
-: 0:Programs:1
|
||||
-: 1:#include <stdio.h>
|
||||
-: 2:
|
||||
-: 3:int main (void)
|
||||
function main called 1 returned 1 blocks executed 75%
|
||||
1: 4:@{
|
||||
1: 5: int i, total;
|
||||
-: 6:
|
||||
1: 7: total = 0;
|
||||
-: 8:
|
||||
11: 9: for (i = 0; i < 10; i++)
|
||||
branch 0: taken 90%
|
||||
branch 1: taken 100%
|
||||
branch 2: taken 100%
|
||||
branch 0 taken 91% (fallthrough)
|
||||
branch 1 taken 9%
|
||||
10: 10: total += i;
|
||||
-: 11:
|
||||
1: 12: if (total != 45)
|
||||
branch 0: taken 100%
|
||||
branch 0 taken 0% (fallthrough)
|
||||
branch 1 taken 100%
|
||||
#####: 13: printf ("Failure\n");
|
||||
call 0: never executed
|
||||
branch 1: never executed
|
||||
call 0 never executed
|
||||
-: 14: else
|
||||
1: 15: printf ("Success\n");
|
||||
call 0: returns 100%
|
||||
call 0 called 1 returned 100%
|
||||
1: 16: return 0;
|
||||
1: 17:@}
|
||||
-: 17:@}
|
||||
@end smallexample
|
||||
|
||||
For each basic block, a line is printed after the last line of the basic
|
||||
|
|
|
@ -90,6 +90,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
|||
bbg: function-graph*
|
||||
function-graph: announce_function basic_blocks {arcs | lines}*
|
||||
announce_function: header string:name int32:checksum
|
||||
string:source int32:lineno
|
||||
basic_block: header int32:flags*
|
||||
arcs: header int32:block_no arc*
|
||||
arc: int32:dest_block int32:flags
|
||||
|
@ -121,7 +122,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
|||
summary: in32:checksum int32:runs int32:arcs int64:sum int64:max \
|
||||
int64:max_sum int64:sum_max
|
||||
|
||||
The ANNOUNCE_FUNCTION record is the same as that in the BBG file.
|
||||
The ANNOUNCE_FUNCTION record is the same as that in the BBG 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 program. The checksum is used for
|
||||
|
@ -195,7 +197,7 @@ typedef long long gcov_type;
|
|||
(GCOV_TAG_MASK (TAG) > GCOV_TAG_MASK (SUB))
|
||||
|
||||
/* Basic block flags. */
|
||||
#define GCOV_BLOCK_UNEXPECTED (1 << 0)
|
||||
#define GCOV_BLOCK_UNEXPECTED (1 << 1)
|
||||
|
||||
/* Arc flags. */
|
||||
#define GCOV_ARC_ON_TREE (1 << 0)
|
||||
|
|
568
gcc/gcov.c
568
gcc/gcov.c
|
@ -69,6 +69,7 @@ typedef HOST_WIDEST_INT gcov_type;
|
|||
|
||||
struct function_info;
|
||||
struct block_info;
|
||||
struct source_info;
|
||||
|
||||
/* Describes an arc between two basic blocks. */
|
||||
|
||||
|
@ -86,8 +87,17 @@ typedef struct arc_info
|
|||
unsigned int fake : 1;
|
||||
unsigned int fall_through : 1;
|
||||
|
||||
/* Arc to a call. */
|
||||
unsigned int is_call : 1;
|
||||
/* Arc is for a function that abnormally returns. */
|
||||
unsigned int is_call_non_return : 1;
|
||||
|
||||
/* Arc is for catch/setjump. */
|
||||
unsigned int is_nonlocal_return : 1;
|
||||
|
||||
/* Is an unconditional branch. */
|
||||
unsigned int is_unconditional : 1;
|
||||
|
||||
/* Arc on the local block spanning tree. */
|
||||
unsigned int local_span : 1;
|
||||
|
||||
/* Next branch on line. */
|
||||
struct arc_info *line_next;
|
||||
|
@ -112,17 +122,39 @@ typedef struct block_info
|
|||
|
||||
/* Block execution count. */
|
||||
gcov_type count;
|
||||
unsigned flags : 13;
|
||||
unsigned count_valid : 1;
|
||||
unsigned valid_chain : 1;
|
||||
unsigned invalid_chain : 1;
|
||||
|
||||
/* 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_encodings;
|
||||
/* Block is a call instrumenting site. */
|
||||
unsigned is_call_site : 1;
|
||||
|
||||
/* Temporary chain for solving graph. */
|
||||
/* Block is a landing pad for longjmp or throw. */
|
||||
unsigned is_nonlocal_return : 1;
|
||||
|
||||
union
|
||||
{
|
||||
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
|
||||
{
|
||||
/* Single line spanning tree workspace. Used for all-blocks mode. */
|
||||
struct block_info *root;
|
||||
unsigned siblings;
|
||||
} span; /* Used in all-blocks mode, after blocks are linked onto
|
||||
lines. */
|
||||
} u;
|
||||
|
||||
/* Temporary chain for solving graph, and for chaining blocks on one
|
||||
line. */
|
||||
struct block_info *chain;
|
||||
|
||||
} block_t;
|
||||
|
@ -138,10 +170,18 @@ typedef struct function_info
|
|||
/* Array of basic blocks. */
|
||||
block_t *blocks;
|
||||
unsigned num_blocks;
|
||||
unsigned blocks_executed;
|
||||
|
||||
/* Raw arc coverage counts. */
|
||||
gcov_type *counts;
|
||||
unsigned num_counts;
|
||||
|
||||
/* First line number. */
|
||||
unsigned line;
|
||||
struct source_info *src;
|
||||
|
||||
/* Next function in same source file. */
|
||||
struct function_info *line_next;
|
||||
|
||||
/* Next function. */
|
||||
struct function_info *next;
|
||||
|
@ -170,8 +210,14 @@ typedef struct coverage_info
|
|||
typedef struct line_info
|
||||
{
|
||||
gcov_type count; /* execution count */
|
||||
arc_t *branches; /* branches from blocks that end on this
|
||||
line. */
|
||||
union
|
||||
{
|
||||
arc_t *branches; /* branches from blocks that end on this
|
||||
line. Used for branch-counts when not
|
||||
all-blocks mode. */
|
||||
block_t *blocks; /* blocks which start on this line. Used
|
||||
in all-blocks mode. */
|
||||
} u;
|
||||
unsigned exists : 1;
|
||||
} line_t;
|
||||
|
||||
|
@ -189,6 +235,10 @@ typedef struct source_info
|
|||
unsigned num_lines;
|
||||
|
||||
coverage_t coverage;
|
||||
|
||||
/* Functions in this source file. These are in ascending line
|
||||
number order. */
|
||||
function_t *functions;
|
||||
|
||||
/* Next source file. */
|
||||
struct source_info *next;
|
||||
|
@ -202,6 +252,11 @@ static function_t *functions;
|
|||
|
||||
static source_t *sources;
|
||||
|
||||
/* This holds data summary information. */
|
||||
|
||||
static struct gcov_summary object_summary;
|
||||
static unsigned program_count;
|
||||
|
||||
/* Modification time of graph file. */
|
||||
|
||||
static time_t bbg_file_time;
|
||||
|
@ -218,6 +273,9 @@ static char *da_file_name;
|
|||
|
||||
static int flag_branches = 0;
|
||||
|
||||
/* Show unconditional branches too. */
|
||||
static int flag_unconditional = 0;
|
||||
|
||||
/* Output a gcov file if this is true. This is on by default, and can
|
||||
be turned off by the -n option. */
|
||||
|
||||
|
@ -229,6 +287,11 @@ static int flag_gcov_file = 1;
|
|||
|
||||
static int flag_long_names = 0;
|
||||
|
||||
/* Output count information for every basic block, not merely those
|
||||
that contain line number information. */
|
||||
|
||||
static int flag_all_blocks = 0;
|
||||
|
||||
/* Output summary info for each function. */
|
||||
|
||||
static int flag_function_summary = 0;
|
||||
|
@ -256,14 +319,16 @@ static void print_usage PARAMS ((int)) ATTRIBUTE_NORETURN;
|
|||
static void print_version PARAMS ((void)) ATTRIBUTE_NORETURN;
|
||||
static void process_file PARAMS ((const char *));
|
||||
static void create_file_names PARAMS ((const char *));
|
||||
static source_t *find_source PARAMS ((char *));
|
||||
static int read_graph_file PARAMS ((void));
|
||||
static int read_count_file PARAMS ((void));
|
||||
static void solve_flow_graph PARAMS ((function_t *));
|
||||
static void add_branch_counts PARAMS ((coverage_t *, const arc_t *));
|
||||
static void add_line_counts PARAMS ((coverage_t *, const function_t *));
|
||||
static void add_line_counts PARAMS ((coverage_t *, function_t *));
|
||||
static void function_summary PARAMS ((const coverage_t *, const char *));
|
||||
static const char *format_gcov PARAMS ((gcov_type, gcov_type, int));
|
||||
static void accumulate_line_counts PARAMS ((source_t *));
|
||||
static int output_branch_count PARAMS ((FILE *, int, const arc_t *));
|
||||
static void output_lines PARAMS ((FILE *, const source_t *));
|
||||
static char *make_gcov_file_name PARAMS ((const char *, const char *));
|
||||
static void release_structures PARAMS ((void));
|
||||
|
@ -328,6 +393,7 @@ print_usage (error_p)
|
|||
fnotice (file, "Print code coverage information.\n\n");
|
||||
fnotice (file, " -h, --help Print this help, then exit\n");
|
||||
fnotice (file, " -v, --version Print version number, then exit\n");
|
||||
fnotice (file, " -a, --all-blocks Show information for every basic block\n");
|
||||
fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
|
||||
fnotice (file, " -c, --branch-counts Given counts of branches taken\n\
|
||||
rather than percentages\n");
|
||||
|
@ -337,6 +403,7 @@ print_usage (error_p)
|
|||
fnotice (file, " -f, --function-summaries Output summaries for each function\n");
|
||||
fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
|
||||
fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
|
||||
fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
|
||||
fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
|
||||
bug_report_url);
|
||||
exit (status);
|
||||
|
@ -365,6 +432,7 @@ static const struct option options[] =
|
|||
{
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, 'v' },
|
||||
{ "all-blocks", no_argument, NULL, 'a' },
|
||||
{ "branch-probabilities", no_argument, NULL, 'b' },
|
||||
{ "branch-counts", no_argument, NULL, 'c' },
|
||||
{ "no-output", no_argument, NULL, 'n' },
|
||||
|
@ -373,6 +441,7 @@ static const struct option options[] =
|
|||
{ "preserve-paths", no_argument, NULL, 'p' },
|
||||
{ "object-directory", required_argument, NULL, 'o' },
|
||||
{ "object-file", required_argument, NULL, 'o' },
|
||||
{ "unconditional-branches", no_argument, NULL, 'u' },
|
||||
};
|
||||
|
||||
/* Process args, return index to first non-arg. */
|
||||
|
@ -384,30 +453,30 @@ process_args (argc, argv)
|
|||
{
|
||||
int opt;
|
||||
|
||||
while ((opt = getopt_long (argc, argv, "hvbclnfo:p", options, NULL)) != -1)
|
||||
while ((opt = getopt_long (argc, argv, "abcfhlno:puv", options, NULL)) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'h':
|
||||
print_usage (false);
|
||||
/* print_usage will exit. */
|
||||
case 'v':
|
||||
print_version ();
|
||||
/* print_version will exit. */
|
||||
case 'a':
|
||||
flag_all_blocks = 1;
|
||||
break;
|
||||
case 'b':
|
||||
flag_branches = 1;
|
||||
break;
|
||||
case 'c':
|
||||
flag_counts = 1;
|
||||
break;
|
||||
case 'n':
|
||||
flag_gcov_file = 0;
|
||||
case 'f':
|
||||
flag_function_summary = 1;
|
||||
break;
|
||||
case 'h':
|
||||
print_usage (false);
|
||||
/* print_usage will exit. */
|
||||
case 'l':
|
||||
flag_long_names = 1;
|
||||
break;
|
||||
case 'f':
|
||||
flag_function_summary = 1;
|
||||
case 'n':
|
||||
flag_gcov_file = 0;
|
||||
break;
|
||||
case 'o':
|
||||
object_directory = optarg;
|
||||
|
@ -415,6 +484,12 @@ process_args (argc, argv)
|
|||
case 'p':
|
||||
flag_preserve_paths = 1;
|
||||
break;
|
||||
case 'u':
|
||||
flag_unconditional = 1;
|
||||
break;
|
||||
case 'v':
|
||||
print_version ();
|
||||
/* print_version will exit. */
|
||||
default:
|
||||
print_usage (true);
|
||||
/* print_usage will exit. */
|
||||
|
@ -528,7 +603,6 @@ release_structures ()
|
|||
arc_n = arc->succ_next;
|
||||
free (arc);
|
||||
}
|
||||
free (block->encoding);
|
||||
}
|
||||
free (fn->blocks);
|
||||
free (fn->counts);
|
||||
|
@ -597,6 +671,34 @@ create_file_names (file_name)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Find or create a source file structure for FILE_NAME. Free
|
||||
FILE_NAME appropriately */
|
||||
|
||||
static source_t *
|
||||
find_source (file_name)
|
||||
char *file_name;
|
||||
{
|
||||
|
||||
source_t *src;
|
||||
|
||||
for (src = sources; src; src = src->next)
|
||||
if (!strcmp (file_name, src->name))
|
||||
{
|
||||
free (file_name);
|
||||
break;
|
||||
}
|
||||
if (!src)
|
||||
{
|
||||
src = (source_t *)xcalloc (1, sizeof (source_t));
|
||||
src->name = file_name;
|
||||
src->coverage.name = file_name;
|
||||
src->index = sources ? sources->index + 1 : 1;
|
||||
src->next = sources;
|
||||
sources = src;
|
||||
}
|
||||
return src;
|
||||
}
|
||||
|
||||
/* Read the graph file. Return nonzero on fatal error. */
|
||||
|
||||
static int
|
||||
|
@ -650,22 +752,45 @@ read_graph_file ()
|
|||
goto corrupt;
|
||||
|
||||
base = gcov_save_position (file);
|
||||
|
||||
|
||||
if (tag == GCOV_TAG_FUNCTION)
|
||||
{
|
||||
char *function_name = NULL;
|
||||
unsigned checksum;
|
||||
char *function_file = NULL;
|
||||
unsigned checksum, lineno;
|
||||
source_t *src;
|
||||
function_t *probe, *prev;
|
||||
|
||||
if (gcov_read_string (file, &function_name, NULL)
|
||||
|| gcov_read_unsigned (file, &checksum))
|
||||
|| gcov_read_unsigned (file, &checksum)
|
||||
|| gcov_read_string (file, &function_file, NULL)
|
||||
|| gcov_read_unsigned (file, &lineno))
|
||||
goto corrupt;
|
||||
src = find_source (function_file);
|
||||
fn = (function_t *)xcalloc (1, sizeof (function_t));
|
||||
fn->name = function_name;
|
||||
fn->checksum = checksum;
|
||||
fn->src = src;
|
||||
fn->line = lineno;
|
||||
|
||||
fn->next = functions;
|
||||
functions = fn;
|
||||
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)
|
||||
{
|
||||
|
@ -674,9 +799,19 @@ read_graph_file ()
|
|||
bbg_file_name, fn->name);
|
||||
else
|
||||
{
|
||||
fn->num_blocks = length / 4;
|
||||
unsigned ix, num_blocks = length / 4;
|
||||
fn->num_blocks = num_blocks;
|
||||
|
||||
fn->blocks
|
||||
= (block_t *)xcalloc (fn->num_blocks, sizeof (block_t));
|
||||
for (ix = 0; ix != num_blocks; ix++)
|
||||
{
|
||||
unsigned flags;
|
||||
|
||||
if (gcov_read_unsigned (file, &flags))
|
||||
goto corrupt;
|
||||
fn->blocks[ix].flags = flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (fn && tag == GCOV_TAG_ARCS)
|
||||
|
@ -717,7 +852,24 @@ read_graph_file ()
|
|||
fn->blocks[dest].pred = arc;
|
||||
fn->blocks[dest].num_pred++;
|
||||
|
||||
arc->is_call = arc->fake;
|
||||
if (arc->fake)
|
||||
{
|
||||
if (src)
|
||||
{
|
||||
/* Exceptional exit from this function, the
|
||||
source block must be a call. */
|
||||
fn->blocks[src].is_call_site = 1;
|
||||
arc->is_call_non_return = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Non-local return from a callee of this
|
||||
function. The destination block is a catch or
|
||||
setjmp. */
|
||||
arc->is_nonlocal_return = 1;
|
||||
fn->blocks[dest].is_nonlocal_return = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!arc->on_tree)
|
||||
fn->num_counts++;
|
||||
|
@ -731,7 +883,7 @@ read_graph_file ()
|
|||
|
||||
if (gcov_read_unsigned (file, &blockno)
|
||||
|| blockno >= fn->num_blocks
|
||||
|| fn->blocks[blockno].encoding)
|
||||
|| fn->blocks[blockno].u.line.encoding)
|
||||
goto corrupt;
|
||||
|
||||
for (ix = 0; ; )
|
||||
|
@ -759,28 +911,15 @@ read_graph_file ()
|
|||
goto corrupt;
|
||||
if (!file_name)
|
||||
break;
|
||||
for (src = sources; src; src = src->next)
|
||||
if (!strcmp (file_name, src->name))
|
||||
{
|
||||
free (file_name);
|
||||
break;
|
||||
}
|
||||
if (!src)
|
||||
{
|
||||
src = (source_t *)xcalloc (1, sizeof (source_t));
|
||||
src->name = file_name;
|
||||
src->coverage.name = file_name;
|
||||
src->index = sources ? sources->index + 1 : 1;
|
||||
src->next = sources;
|
||||
sources = src;
|
||||
}
|
||||
src = find_source (file_name);
|
||||
|
||||
line_nos[ix++] = 0;
|
||||
line_nos[ix++] = src->index;
|
||||
}
|
||||
}
|
||||
|
||||
fn->blocks[blockno].encoding = line_nos;
|
||||
fn->blocks[blockno].num_encodings = ix;
|
||||
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))
|
||||
{
|
||||
|
@ -906,7 +1045,15 @@ read_count_file ()
|
|||
goto cleanup;
|
||||
}
|
||||
base = gcov_save_position (file);
|
||||
if (tag == GCOV_TAG_FUNCTION)
|
||||
if (tag == GCOV_TAG_OBJECT_SUMMARY)
|
||||
{
|
||||
if (gcov_read_summary (file, &object_summary))
|
||||
goto corrupt;
|
||||
}
|
||||
else if (tag == GCOV_TAG_PROGRAM_SUMMARY
|
||||
|| tag == GCOV_TAG_INCORRECT_SUMMARY)
|
||||
program_count++;
|
||||
else if (tag == GCOV_TAG_FUNCTION)
|
||||
{
|
||||
unsigned checksum;
|
||||
struct function_info *fn_n = functions;
|
||||
|
@ -977,6 +1124,7 @@ solve_flow_graph (fn)
|
|||
unsigned ix;
|
||||
arc_t *arc;
|
||||
gcov_type *count_ptr = fn->counts;
|
||||
block_t *blk;
|
||||
block_t *valid_blocks = NULL; /* valid, but unpropagated blocks. */
|
||||
block_t *invalid_blocks = NULL; /* invalid, but inferable blocks. */
|
||||
|
||||
|
@ -1004,25 +1152,50 @@ solve_flow_graph (fn)
|
|||
|
||||
/* Propagate the measured counts, this must be done in the same
|
||||
order as the code in profile.c */
|
||||
for (ix = 0; ix != fn->num_blocks; ix++)
|
||||
for (ix = 0, blk = fn->blocks; ix != fn->num_blocks; ix++, blk++)
|
||||
{
|
||||
block_t const *prev_dst = NULL;
|
||||
int out_of_order = 0;
|
||||
int non_fake_succ = 0;
|
||||
|
||||
for (arc = fn->blocks[ix].succ; arc; arc = arc->succ_next)
|
||||
for (arc = blk->succ; arc; arc = arc->succ_next)
|
||||
{
|
||||
if (!arc->fake)
|
||||
non_fake_succ++;
|
||||
|
||||
if (!arc->on_tree)
|
||||
{
|
||||
if (count_ptr)
|
||||
arc->count = *count_ptr++;
|
||||
arc->count_valid = 1;
|
||||
fn->blocks[ix].num_succ--;
|
||||
blk->num_succ--;
|
||||
arc->dst->num_pred--;
|
||||
}
|
||||
if (prev_dst && prev_dst > arc->dst)
|
||||
out_of_order = 1;
|
||||
prev_dst = arc->dst;
|
||||
}
|
||||
if (non_fake_succ == 1)
|
||||
{
|
||||
/* If there is only one non-fake exit, it is an
|
||||
unconditional branch. */
|
||||
for (arc = blk->succ; arc; arc = arc->succ_next)
|
||||
if (!arc->fake)
|
||||
{
|
||||
arc->is_unconditional = 1;
|
||||
/* If this block is instrumenting a call, it might be
|
||||
an artifical block. It is not artificial if it has
|
||||
a non-fallthrough exit, or the destination of the
|
||||
exit has more than one entry. */
|
||||
if (!arc->fall_through
|
||||
|| arc->dst->pred != arc || arc->pred_next)
|
||||
blk->is_call_site = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* If there is more than one exit, it cannot be an artificial
|
||||
call instrumenting site. */
|
||||
blk->is_call_site = 0;
|
||||
|
||||
/* Sort the successor arcs into ascending dst order. profile.c
|
||||
normally produces arcs in the right order, but sometimes with
|
||||
|
@ -1030,7 +1203,7 @@ solve_flow_graph (fn)
|
|||
smart sort. */
|
||||
if (out_of_order)
|
||||
{
|
||||
arc_t *start = fn->blocks[ix].succ;
|
||||
arc_t *start = blk->succ;
|
||||
unsigned changes = 1;
|
||||
|
||||
while (changes)
|
||||
|
@ -1058,20 +1231,18 @@ solve_flow_graph (fn)
|
|||
}
|
||||
}
|
||||
}
|
||||
fn->blocks[ix].succ = start;
|
||||
blk->succ = start;
|
||||
}
|
||||
|
||||
/* Place it on the invalid chain, it will be ignored if that's
|
||||
wrong. */
|
||||
fn->blocks[ix].invalid_chain = 1;
|
||||
fn->blocks[ix].chain = invalid_blocks;
|
||||
invalid_blocks = &fn->blocks[ix];
|
||||
blk->invalid_chain = 1;
|
||||
blk->chain = invalid_blocks;
|
||||
invalid_blocks = blk;
|
||||
}
|
||||
|
||||
while (invalid_blocks || valid_blocks)
|
||||
{
|
||||
block_t *blk;
|
||||
|
||||
while ((blk = invalid_blocks))
|
||||
{
|
||||
gcov_type total = 0;
|
||||
|
@ -1196,13 +1367,13 @@ add_branch_counts (coverage, arc)
|
|||
coverage_t *coverage;
|
||||
const arc_t *arc;
|
||||
{
|
||||
if (arc->is_call)
|
||||
if (arc->is_call_non_return)
|
||||
{
|
||||
coverage->calls++;
|
||||
if (arc->src->count)
|
||||
coverage->calls_executed++;
|
||||
}
|
||||
else
|
||||
else if (!arc->is_unconditional)
|
||||
{
|
||||
coverage->branches++;
|
||||
if (arc->src->count)
|
||||
|
@ -1374,7 +1545,7 @@ make_gcov_file_name (input_name, src_name)
|
|||
static void
|
||||
add_line_counts (coverage, fn)
|
||||
coverage_t *coverage;
|
||||
const function_t *fn;
|
||||
function_t *fn;
|
||||
{
|
||||
unsigned ix;
|
||||
line_t *line = NULL; /* this is propagated from one iteration to the
|
||||
|
@ -1383,13 +1554,16 @@ add_line_counts (coverage, fn)
|
|||
/* Scan each basic block. */
|
||||
for (ix = 0; ix != fn->num_blocks; ix++)
|
||||
{
|
||||
const block_t *block = &fn->blocks[ix];
|
||||
block_t *block = &fn->blocks[ix];
|
||||
unsigned *encoding;
|
||||
const source_t *src = NULL;
|
||||
unsigned jx;
|
||||
line_t *first_line = NULL;
|
||||
|
||||
for (jx = 0, encoding = block->encoding;
|
||||
jx != block->num_encodings; jx++, encoding++)
|
||||
if (block->count && ix && ix + 1 != fn->num_blocks)
|
||||
fn->blocks_executed++;
|
||||
for (jx = 0, encoding = block->u.line.encoding;
|
||||
jx != block->u.line.num; jx++, encoding++)
|
||||
if (!*encoding)
|
||||
{
|
||||
unsigned src_n = *++encoding;
|
||||
|
@ -1406,26 +1580,38 @@ add_line_counts (coverage, fn)
|
|||
{
|
||||
if (!line->exists)
|
||||
coverage->lines++;
|
||||
if (!line->count && block->count)
|
||||
if (!line->count && block->count)
|
||||
coverage->lines_executed++;
|
||||
}
|
||||
line->exists = 1;
|
||||
line->count += block->count;
|
||||
if (!first_line)
|
||||
first_line = line;
|
||||
}
|
||||
|
||||
if (line && flag_branches)
|
||||
free (block->u.line.encoding);
|
||||
block->u.span.root = NULL;
|
||||
if (!first_line)
|
||||
first_line = line;
|
||||
|
||||
if (!ix || ix + 1 == fn->num_blocks)
|
||||
/* Entry or exit block */;
|
||||
else if (flag_all_blocks)
|
||||
{
|
||||
if (!first_line)
|
||||
first_line = &fn->src->lines[fn->line];
|
||||
|
||||
block->chain = first_line->u.blocks;
|
||||
first_line->u.blocks = block;
|
||||
}
|
||||
else if (flag_branches)
|
||||
{
|
||||
arc_t *arc;
|
||||
|
||||
|
||||
for (arc = block->succ; arc; arc = arc->succ_next)
|
||||
{
|
||||
/* Ignore fall through arcs as they aren't really branches. */
|
||||
if (arc->fall_through)
|
||||
continue;
|
||||
|
||||
arc->line_next = line->branches;
|
||||
line->branches = arc;
|
||||
if (coverage)
|
||||
arc->line_next = line->u.branches;
|
||||
line->u.branches = arc;
|
||||
if (coverage && !arc->is_unconditional)
|
||||
add_branch_counts (coverage, arc);
|
||||
}
|
||||
}
|
||||
|
@ -1441,22 +1627,123 @@ accumulate_line_counts (src)
|
|||
source_t *src;
|
||||
{
|
||||
line_t *line;
|
||||
function_t *fn, *fn_p, *fn_n;
|
||||
unsigned ix;
|
||||
|
||||
/* Reverse the function order. */
|
||||
for (fn = src->functions, fn_p = NULL; fn;
|
||||
fn_p = fn, fn = fn_n)
|
||||
{
|
||||
fn_n = fn->line_next;
|
||||
fn->line_next = fn_p;
|
||||
}
|
||||
src->functions = fn_p;
|
||||
|
||||
for (ix = src->num_lines, line = src->lines; ix--; line++)
|
||||
{
|
||||
arc_t *arc, *arc_p, *arc_n;
|
||||
|
||||
/* Total and reverse the branch information. */
|
||||
for (arc = line->branches, arc_p = NULL; arc; arc_p = arc, arc = arc_n)
|
||||
if (!flag_all_blocks)
|
||||
{
|
||||
arc_n = arc->line_next;
|
||||
arc->line_next = arc_p;
|
||||
|
||||
add_branch_counts (&src->coverage, arc);
|
||||
arc_t *arc, *arc_p, *arc_n;
|
||||
|
||||
/* Total and reverse the branch information. */
|
||||
for (arc = line->u.branches, arc_p = NULL; arc;
|
||||
arc_p = arc, arc = arc_n)
|
||||
{
|
||||
arc_n = arc->line_next;
|
||||
arc->line_next = arc_p;
|
||||
|
||||
add_branch_counts (&src->coverage, arc);
|
||||
}
|
||||
line->u.branches = arc_p;
|
||||
}
|
||||
line->branches = arc_p;
|
||||
else if (line->u.blocks)
|
||||
{
|
||||
/* The user expects the line count to be the number of times
|
||||
a line has been executed. Simply summing the block count
|
||||
will give an artificially high number. The Right Thing
|
||||
is to generate the spanning tree of the blocks on this
|
||||
line, and the sum the entry arcs to that tree. */
|
||||
block_t *block, *block_p, *block_n;
|
||||
int changes = 1;
|
||||
gcov_type count = 0;
|
||||
|
||||
/* Reverse the block information */
|
||||
for (block = line->u.blocks, block_p = NULL; block;
|
||||
block_p = block, block = block_n)
|
||||
{
|
||||
block_n = block->chain;
|
||||
block->chain = block_p;
|
||||
/* Each block is it's own spanning tree, with no siblings */
|
||||
block->u.span.root = block;
|
||||
block->u.span.siblings = 0;
|
||||
}
|
||||
line->u.blocks = block_p;
|
||||
|
||||
while (changes)
|
||||
{
|
||||
changes = 0;
|
||||
|
||||
for (block = line->u.blocks; block; block = block->chain)
|
||||
{
|
||||
arc_t *arc;
|
||||
|
||||
for (arc = block->succ; arc; arc = arc->succ_next)
|
||||
{
|
||||
block_t *dst = arc->dst;
|
||||
|
||||
if (!dst->u.span.root)
|
||||
/* Not on this line. */;
|
||||
else if (dst->u.span.root == block->u.span.root)
|
||||
/* Same spanning tree. */;
|
||||
else
|
||||
{
|
||||
block_t *root = block->u.span.root;
|
||||
block_t *dst_root = dst->u.span.root;
|
||||
|
||||
/* Join spanning trees */
|
||||
if (root->u.span.siblings && !dst_root->u.span.root)
|
||||
{
|
||||
root = dst->u.span.root;
|
||||
dst_root = block->u.span.root;
|
||||
}
|
||||
|
||||
dst->u.span.root = root;
|
||||
root->u.span.siblings += 1 + dst->u.span.siblings;
|
||||
if (dst->u.span.siblings)
|
||||
{
|
||||
block_t *dst_sib;
|
||||
|
||||
dst->u.span.siblings = 0;
|
||||
for (dst_sib = line->u.blocks; dst_sib;
|
||||
dst_sib = dst_sib->chain)
|
||||
if (dst_sib->u.span.root == dst_root)
|
||||
dst_sib->u.span.root = root;
|
||||
}
|
||||
arc->local_span = 1;
|
||||
changes = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now sum the entry counts */
|
||||
for (block = line->u.blocks; block; block = block->chain)
|
||||
{
|
||||
arc_t *arc;
|
||||
|
||||
for (arc = block->succ; arc; arc = arc->succ_next)
|
||||
{
|
||||
if (!arc->local_span)
|
||||
count += arc->count;
|
||||
if (flag_branches)
|
||||
add_branch_counts (&src->coverage, arc);
|
||||
}
|
||||
block->u.span.root = NULL;
|
||||
}
|
||||
|
||||
line->count = count;
|
||||
}
|
||||
|
||||
if (line->exists)
|
||||
{
|
||||
src->coverage.lines++;
|
||||
|
@ -1466,6 +1753,50 @@ accumulate_line_counts (src)
|
|||
}
|
||||
}
|
||||
|
||||
/* Ouput information about ARC number IX. Returns non-zero if
|
||||
anything is output. */
|
||||
|
||||
static int
|
||||
output_branch_count (gcov_file, ix, arc)
|
||||
FILE *gcov_file;
|
||||
int ix;
|
||||
const arc_t *arc;
|
||||
{
|
||||
|
||||
if (arc->is_call_non_return)
|
||||
{
|
||||
if (arc->src->count)
|
||||
{
|
||||
fnotice (gcov_file, "call %2d returned %s\n", ix,
|
||||
format_gcov (arc->src->count - arc->count,
|
||||
arc->src->count, -flag_counts));
|
||||
}
|
||||
else
|
||||
fnotice (gcov_file, "call %2d never executed\n", ix);
|
||||
}
|
||||
else if (!arc->is_unconditional)
|
||||
{
|
||||
if (arc->src->count)
|
||||
fnotice (gcov_file, "branch %2d taken %s%s\n", ix,
|
||||
format_gcov (arc->count, arc->src->count, -flag_counts),
|
||||
arc->fall_through ? " (fallthrough)" : "");
|
||||
else
|
||||
fnotice (gcov_file, "branch %2d never executed\n", ix);
|
||||
}
|
||||
else if (flag_unconditional && !arc->src->is_call_site)
|
||||
{
|
||||
if (arc->src->count)
|
||||
fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
|
||||
format_gcov (arc->count, arc->src->count, -flag_counts));
|
||||
else
|
||||
fnotice (gcov_file, "unconditional %2d never executed\n", ix);
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/* Read in the source file one line at a time, and output that line to
|
||||
the gcov file preceded by its execution count and other
|
||||
information. */
|
||||
|
@ -1480,10 +1811,13 @@ output_lines (gcov_file, src)
|
|||
const line_t *line; /* current line info ptr. */
|
||||
char string[STRING_SIZE]; /* line buffer. */
|
||||
char const *retval = ""; /* status of source file reading. */
|
||||
function_t *fn = src->functions;
|
||||
|
||||
fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->name);
|
||||
fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
|
||||
fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0, da_file_name);
|
||||
fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0, object_summary.runs);
|
||||
fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
|
||||
|
||||
source_file = fopen (src->name, "r");
|
||||
if (!source_file)
|
||||
|
@ -1508,6 +1842,25 @@ output_lines (gcov_file, src)
|
|||
for (line_num = 1, line = &src->lines[line_num];
|
||||
line_num < src->num_lines; line_num++, line++)
|
||||
{
|
||||
for (; fn && fn->line == line_num; fn = fn->line_next)
|
||||
{
|
||||
arc_t *arc = fn->blocks[fn->num_blocks - 1].pred;
|
||||
gcov_type return_count = fn->blocks[fn->num_blocks - 1].count;
|
||||
|
||||
for (; arc; arc = arc->pred_next)
|
||||
if (arc->fake)
|
||||
return_count -= arc->count;
|
||||
|
||||
fprintf (gcov_file, "function %s", fn->name);
|
||||
fprintf (gcov_file, " called %s",
|
||||
format_gcov (fn->blocks[0].count, 0, -1));
|
||||
fprintf (gcov_file, " returned %s",
|
||||
format_gcov (return_count, fn->blocks[0].count, 0));
|
||||
fprintf (gcov_file, " blocks executed %s",
|
||||
format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0));
|
||||
fprintf (gcov_file, "\n");
|
||||
}
|
||||
|
||||
/* For lines which don't exist in the .bb file, print '-' before
|
||||
the source line. For lines which exist but were never
|
||||
executed, print '#####' before the source line. Otherwise,
|
||||
|
@ -1535,36 +1888,33 @@ output_lines (gcov_file, src)
|
|||
}
|
||||
if (!retval)
|
||||
fputs ("??\n", gcov_file);
|
||||
|
||||
if (flag_branches)
|
||||
|
||||
if (flag_all_blocks)
|
||||
{
|
||||
block_t *block;
|
||||
int ix, jx;
|
||||
|
||||
for (ix = jx = 0, block = line->u.blocks; block;
|
||||
block = block->chain)
|
||||
{
|
||||
arc_t *arc;
|
||||
|
||||
if (!block->is_call_site)
|
||||
fprintf (gcov_file, "%9s:%5u-block %2d\n",
|
||||
!line->exists ? "-" : !block->count ? "$$$$$"
|
||||
: format_gcov (block->count, 0, -1), line_num, ix++);
|
||||
if (flag_branches)
|
||||
for (arc = block->succ; arc; arc = arc->succ_next)
|
||||
jx += output_branch_count (gcov_file, jx, arc);
|
||||
}
|
||||
}
|
||||
else if (flag_branches)
|
||||
{
|
||||
int ix;
|
||||
arc_t *arc;
|
||||
|
||||
for (ix = 0, arc = line->branches; arc; arc = arc->line_next, ix++)
|
||||
{
|
||||
if (arc->is_call)
|
||||
{
|
||||
if (arc->src->count)
|
||||
fnotice
|
||||
(gcov_file, "call %2d returns %s\n", ix,
|
||||
format_gcov (arc->src->count - arc->count,
|
||||
arc->src->count,
|
||||
-flag_counts));
|
||||
else
|
||||
fnotice (gcov_file, "call %2d never executed\n", ix);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (arc->src->count)
|
||||
fnotice
|
||||
(gcov_file, "branch %2d taken %s\n", ix,
|
||||
format_gcov (arc->count, arc->src->count,
|
||||
-flag_counts));
|
||||
else
|
||||
fnotice (gcov_file, "branch %2d never executed\n", ix);
|
||||
}
|
||||
}
|
||||
for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
|
||||
ix += output_branch_count (gcov_file, ix, arc);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -926,7 +926,7 @@ branch_prob ()
|
|||
unsigned num_edges, ignored_edges;
|
||||
struct edge_list *el;
|
||||
const char *name = IDENTIFIER_POINTER
|
||||
(DECL_ASSEMBLER_NAME (current_function_decl));
|
||||
(DECL_ASSEMBLER_NAME (current_function_decl));
|
||||
|
||||
profile_info.current_function_cfg_checksum = compute_checksum ();
|
||||
for (i = 0; i < profile_info.n_sections; i++)
|
||||
|
@ -1086,6 +1086,8 @@ branch_prob ()
|
|||
if (flag_test_coverage && bbg_file)
|
||||
{
|
||||
long offset;
|
||||
const char *file = DECL_SOURCE_FILE (current_function_decl);
|
||||
unsigned line = DECL_SOURCE_LINE (current_function_decl);
|
||||
|
||||
/* Announce function */
|
||||
if (gcov_write_unsigned (bbg_file, GCOV_TAG_FUNCTION)
|
||||
|
@ -1094,6 +1096,8 @@ branch_prob ()
|
|||
strlen (name))
|
||||
|| gcov_write_unsigned (bbg_file,
|
||||
profile_info.current_function_cfg_checksum)
|
||||
|| gcov_write_string (bbg_file, file, strlen (file))
|
||||
|| gcov_write_unsigned (bbg_file, line)
|
||||
|| gcov_write_length (bbg_file, offset))
|
||||
goto bbg_error;
|
||||
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2003-03-31 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
* lib/gcov.exp: Adjust call return testing strings.
|
||||
* g77.dg/gcov/gcov-1.f: Don't expect unconditional branches.
|
||||
|
||||
2003-03-31 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* gcc.dg/builtins-3.c: Add new tests for sin and cos.
|
||||
|
|
|
@ -118,9 +118,7 @@ C Test simple GOTO.
|
|||
if (f .ne. 0) goto 100 ! count(2)
|
||||
! branch(end)
|
||||
gt1 = 1 ! count(1)
|
||||
! branch(100)
|
||||
goto 101 ! count(1)
|
||||
! branch(end)
|
||||
100 gt1 = 2 ! count(1)
|
||||
101 continue ! count(2)
|
||||
end
|
||||
|
@ -136,9 +134,7 @@ C Test simple GOTO again, this time out of a DO loop.
|
|||
if (i .eq. f) goto 100 ! count(19)
|
||||
end do
|
||||
gt2 = 4 ! count(1)
|
||||
! branch(100)
|
||||
goto 101 ! count(1)
|
||||
! branch(end)
|
||||
100 gt2 = 8 ! count(1)
|
||||
101 continue ! count(2)
|
||||
end
|
||||
|
@ -149,17 +145,13 @@ C Test computed GOTO.
|
|||
integer i
|
||||
goto (101, 102, 103, 104), i ! count(2)
|
||||
gt3 = 8 ! count(1)
|
||||
! branch(100)
|
||||
goto 105 ! count(1)
|
||||
! branch(end)
|
||||
101 gt3 = 1024
|
||||
goto 105
|
||||
102 gt3 = 2048
|
||||
goto 105
|
||||
103 gt3 = 16 ! count(1)
|
||||
! branch(100)
|
||||
goto 105 ! count(1)
|
||||
! branch(end)
|
||||
104 gt3 = 4096
|
||||
goto 105
|
||||
105 gt3 = gt3 * 2 ! count(2)
|
||||
|
|
|
@ -168,7 +168,7 @@ proc verify-calls { testcase file } {
|
|||
set n 0
|
||||
while { [gets $fd line] >= 0 } {
|
||||
regexp "^\[^:\]+: *(\[0-9\]+):" "$line" all n
|
||||
if [regexp "returns" $line] {
|
||||
if [regexp "return" $line] {
|
||||
verbose "Processing returns line $n: $line" 3
|
||||
if [regexp "returns\\((\[0-9 \]+)\\)" "$line" all new_shouldbe] {
|
||||
# All percentages in the current list should have been seen.
|
||||
|
@ -179,12 +179,12 @@ proc verify-calls { testcase file } {
|
|||
}
|
||||
# Record the percentages to check for.
|
||||
set shouldbe $new_shouldbe
|
||||
} elseif [regexp "call +\[0-9\]+ returns (-\[0-9\]+)%" "$line" \
|
||||
} elseif [regexp "call +\[0-9\]+ returned (-\[0-9\]+)%" "$line" \
|
||||
all returns] {
|
||||
# Percentages should never be negative.
|
||||
fail "$n: negative percentage: $returns"
|
||||
incr failed
|
||||
} elseif [regexp "call +\[0-9\]+ returns (\[0-9\]+)%" "$line" \
|
||||
} elseif [regexp "call +\[0-9\]+ returned (\[0-9\]+)%" "$line" \
|
||||
all returns] {
|
||||
# For branches we check that percentages are not greater than
|
||||
# 100 but call return percentages can be, as for setjmp(), so
|
||||
|
|
Loading…
Reference in New Issue