]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/gcov.c
tree.h (default_flag_random_seed): Remove.
[thirdparty/gcc.git] / gcc / gcov.c
CommitLineData
86144b75
DE
1/* Gcov.c: prepend line execution counts and branch probabilities to a
2 source file.
3b708058 3 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998,
c4f2c499 4 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
86144b75 5 Contributed by James E. Wilson of Cygnus Support.
1d300e19 6 Mangled by Bob Manson of Cygnus Support.
4977bab6 7 Mangled further by Nathan Sidwell <nathan@codesourcery.com>
86144b75
DE
8
9Gcov is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2, or (at your option)
12any later version.
13
14Gcov is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with Gcov; see the file COPYING. If not, write to
5f38fdda
JL
21the Free Software Foundation, 59 Temple Place - Suite 330,
22Boston, MA 02111-1307, USA. */
86144b75 23
86144b75
DE
24/* ??? Print a list of the ten blocks with the highest execution counts,
25 and list the line numbers corresponding to those blocks. Also, perhaps
26 list the line numbers with the highest execution counts, only printing
27 the first if there are several which are all listed in the same block. */
28
29/* ??? Should have an option to print the number of basic blocks, and the
30 percent of them that are covered. */
31
4977bab6
ZW
32/* ??? Does not correctly handle the case where two .bb files refer to
33 the same included source file. For example, if one has a short
34 file containing only inline functions, which is then included in
35 two other files, then there will be two .bb files which refer to
36 the include file, but there is no way to get the total execution
37 counts for the included file, can only get execution counts for one
38 or the other of the including files. this can be fixed by --ratios
39 --long-file-names --preserve-paths and perl. */
40
41/* Need an option to show individual block counts, and show
42 probabilities of fall through arcs. */
86144b75 43
1d300e19 44#include "config.h"
b04cd507 45#include "system.h"
4977bab6
ZW
46#include "coretypes.h"
47#include "tm.h"
ab87f8c8 48#include "intl.h"
5735c3ea 49#include "version.h"
2a611d21 50#undef abort
86144b75 51
5735c3ea
JM
52#include <getopt.h>
53
546d2adb 54#define IN_GCOV 1
86144b75 55#include "gcov-io.h"
d79f9ec9 56#include "gcov-io.c"
86144b75 57
4977bab6
ZW
58/* The bbg file is generated by -ftest-coverage option. The da file is
59 generated by a program compiled with -fprofile-arcs. Their formats
60 are documented in gcov-io.h. */
86144b75
DE
61
62/* The functions in this file for creating and solution program flow graphs
4977bab6
ZW
63 are very similar to functions in the gcc source file profile.c. In
64 some places we make use of the knowledge of how profile.c works to
65 select particular algorithms here. */
86144b75 66
86144b75
DE
67/* This is the size of the buffer used to read in source file lines. */
68
69#define STRING_SIZE 200
70
4977bab6
ZW
71struct function_info;
72struct block_info;
27283c73 73struct source_info;
86144b75 74
4977bab6 75/* Describes an arc between two basic blocks. */
86144b75 76
4977bab6
ZW
77typedef struct arc_info
78{
32dd366d 79 /* source and destination blocks. */
4977bab6
ZW
80 struct block_info *src;
81 struct block_info *dst;
86144b75 82
4977bab6
ZW
83 /* transition counts. */
84 gcov_type count;
86144b75 85
86144b75
DE
86 unsigned int count_valid : 1;
87 unsigned int on_tree : 1;
88 unsigned int fake : 1;
89 unsigned int fall_through : 1;
86144b75 90
27283c73
NS
91 /* Arc is for a function that abnormally returns. */
92 unsigned int is_call_non_return : 1;
93
94 /* Arc is for catch/setjump. */
95 unsigned int is_nonlocal_return : 1;
96
97 /* Is an unconditional branch. */
98 unsigned int is_unconditional : 1;
99
10b7602f
NS
100 /* Loop making arc. */
101 unsigned int cycle : 1;
102
4977bab6
ZW
103 /* Next branch on line. */
104 struct arc_info *line_next;
105
106 /* Links to next arc on src and dst lists. */
107 struct arc_info *succ_next;
108 struct arc_info *pred_next;
109} arc_t;
86144b75 110
4977bab6
ZW
111/* Describes a basic block. Contains lists of arcs to successor and
112 predecessor blocks. */
86144b75 113
4977bab6 114typedef struct block_info
86144b75 115{
4977bab6
ZW
116 /* Chain of exit and entry arcs. */
117 arc_t *succ;
118 arc_t *pred;
119
32dd366d 120 /* Number of unprocessed exit and entry arcs. */
4977bab6
ZW
121 gcov_type num_succ;
122 gcov_type num_pred;
123
32dd366d 124 /* Block execution count. */
4977bab6 125 gcov_type count;
27283c73 126 unsigned flags : 13;
4977bab6
ZW
127 unsigned count_valid : 1;
128 unsigned valid_chain : 1;
129 unsigned invalid_chain : 1;
130
27283c73 131 /* Block is a call instrumenting site. */
10b7602f
NS
132 unsigned is_call_site : 1; /* Does the call. */
133 unsigned is_call_return : 1; /* Is the return. */
4977bab6 134
27283c73
NS
135 /* Block is a landing pad for longjmp or throw. */
136 unsigned is_nonlocal_return : 1;
137
138 union
139 {
140 struct
141 {
142 /* Array of line numbers and source files. source files are
143 introduced by a linenumber of zero, the next 'line number' is
144 the number of the source file. Always starts with a source
145 file. */
146 unsigned *encoding;
147 unsigned num;
148 } line; /* Valid until blocks are linked onto lines */
149 struct
150 {
10b7602f 151 /* Single line graph cycle workspace. Used for all-blocks
71c0e7fc 152 mode. */
10b7602f
NS
153 arc_t *arc;
154 unsigned ident;
155 } cycle; /* Used in all-blocks mode, after blocks are linked onto
71c0e7fc 156 lines. */
27283c73
NS
157 } u;
158
159 /* Temporary chain for solving graph, and for chaining blocks on one
160 line. */
4977bab6
ZW
161 struct block_info *chain;
162
163} block_t;
86144b75 164
4977bab6 165/* Describes a single function. Contains an array of basic blocks. */
86144b75 166
4977bab6 167typedef struct function_info
8b219a76 168{
4977bab6
ZW
169 /* Name of function. */
170 char *name;
796621e8 171 unsigned ident;
4977bab6 172 unsigned checksum;
86144b75 173
4977bab6
ZW
174 /* Array of basic blocks. */
175 block_t *blocks;
176 unsigned num_blocks;
27283c73 177 unsigned blocks_executed;
4977bab6
ZW
178
179 /* Raw arc coverage counts. */
180 gcov_type *counts;
181 unsigned num_counts;
27283c73
NS
182
183 /* First line number. */
184 unsigned line;
185 struct source_info *src;
186
187 /* Next function in same source file. */
188 struct function_info *line_next;
8b219a76 189
4977bab6
ZW
190 /* Next function. */
191 struct function_info *next;
192} function_t;
193
194/* Describes coverage of a file or function. */
195
196typedef struct coverage_info
8b219a76
NS
197{
198 int lines;
199 int lines_executed;
200
201 int branches;
202 int branches_executed;
203 int branches_taken;
204
205 int calls;
206 int calls_executed;
207
208 char *name;
4977bab6 209} coverage_t;
8b219a76 210
4977bab6
ZW
211/* Describes a single line of source. Contains a chain of basic blocks
212 with code on it. */
86144b75 213
4977bab6
ZW
214typedef struct line_info
215{
216 gcov_type count; /* execution count */
27283c73
NS
217 union
218 {
219 arc_t *branches; /* branches from blocks that end on this
220 line. Used for branch-counts when not
71c0e7fc 221 all-blocks mode. */
27283c73 222 block_t *blocks; /* blocks which start on this line. Used
71c0e7fc 223 in all-blocks mode. */
27283c73 224 } u;
4977bab6
ZW
225 unsigned exists : 1;
226} line_t;
86144b75 227
4977bab6
ZW
228/* Describes a file mentioned in the block graph. Contains an array
229 of line info. */
37b8715b 230
4977bab6
ZW
231typedef struct source_info
232{
233 /* Name of source file. */
234 char *name;
235 unsigned index;
37b8715b 236
32dd366d 237 /* Array of line information. */
4977bab6
ZW
238 line_t *lines;
239 unsigned num_lines;
86144b75 240
4977bab6 241 coverage_t coverage;
27283c73
NS
242
243 /* Functions in this source file. These are in ascending line
244 number order. */
245 function_t *functions;
4977bab6
ZW
246
247 /* Next source file. */
248 struct source_info *next;
249} source_t;
86144b75 250
4977bab6 251/* Holds a list of function basic block graphs. */
86144b75 252
4977bab6 253static function_t *functions;
86144b75 254
4977bab6 255/* This points to the head of the sourcefile structure list. */
86144b75 256
4977bab6 257static source_t *sources;
86144b75 258
27283c73
NS
259/* This holds data summary information. */
260
261static struct gcov_summary object_summary;
262static unsigned program_count;
263
32dd366d 264/* Modification time of graph file. */
86144b75 265
4977bab6 266static time_t bbg_file_time;
86144b75 267
4977bab6 268/* Name and file pointer of the input file for the basic block graph. */
86144b75 269
4977bab6 270static char *bbg_file_name;
86144b75 271
4977bab6 272/* Name and file pointer of the input file for the arc count data. */
86144b75 273
4977bab6 274static char *da_file_name;
86144b75 275
4977bab6 276/* Output branch probabilities. */
86144b75 277
4977bab6 278static int flag_branches = 0;
86144b75 279
27283c73
NS
280/* Show unconditional branches too. */
281static int flag_unconditional = 0;
282
86144b75
DE
283/* Output a gcov file if this is true. This is on by default, and can
284 be turned off by the -n option. */
285
4977bab6 286static int flag_gcov_file = 1;
86144b75 287
4977bab6
ZW
288/* For included files, make the gcov output file name include the name
289 of the input source file. For example, if x.h is included in a.c,
290 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
86144b75 291
4977bab6 292static int flag_long_names = 0;
86144b75 293
27283c73
NS
294/* Output count information for every basic block, not merely those
295 that contain line number information. */
296
297static int flag_all_blocks = 0;
298
86144b75
DE
299/* Output summary info for each function. */
300
4977bab6 301static int flag_function_summary = 0;
86144b75 302
4977bab6
ZW
303/* Object directory file prefix. This is the directory/file where the
304 graph and data files are looked for, if nonzero. */
86144b75
DE
305
306static char *object_directory = 0;
307
37b8715b 308/* Preserve all pathname components. Needed when object files and
4977bab6
ZW
309 source files are in subdirectories. '/' is mangled as '#', '.' is
310 elided and '..' mangled to '^'. */
311
312static int flag_preserve_paths = 0;
37b8715b 313
8bfa6fc5 314/* Output the number of times a branch was taken as opposed to the percentage
32dd366d 315 of times it was taken. */
23190837 316
4977bab6 317static int flag_counts = 0;
8bfa6fc5 318
86144b75 319/* Forward declarations. */
4977bab6
ZW
320static void fnotice PARAMS ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2;
321static int process_args PARAMS ((int, char **));
5735c3ea
JM
322static void print_usage PARAMS ((int)) ATTRIBUTE_NORETURN;
323static void print_version PARAMS ((void)) ATTRIBUTE_NORETURN;
4977bab6
ZW
324static void process_file PARAMS ((const char *));
325static void create_file_names PARAMS ((const char *));
94de45d9 326static source_t *find_source PARAMS ((const char *));
4977bab6
ZW
327static int read_graph_file PARAMS ((void));
328static int read_count_file PARAMS ((void));
329static void solve_flow_graph PARAMS ((function_t *));
330static void add_branch_counts PARAMS ((coverage_t *, const arc_t *));
27283c73 331static void add_line_counts PARAMS ((coverage_t *, function_t *));
4977bab6
ZW
332static void function_summary PARAMS ((const coverage_t *, const char *));
333static const char *format_gcov PARAMS ((gcov_type, gcov_type, int));
334static void accumulate_line_counts PARAMS ((source_t *));
27283c73 335static int output_branch_count PARAMS ((FILE *, int, const arc_t *));
4977bab6
ZW
336static void output_lines PARAMS ((FILE *, const source_t *));
337static char *make_gcov_file_name PARAMS ((const char *, const char *));
338static void release_structures PARAMS ((void));
711d877c 339extern int main PARAMS ((int, char **));
86144b75
DE
340
341int
342main (argc, argv)
343 int argc;
344 char **argv;
345{
4977bab6 346 int argno;
8b219a76 347
191bf464 348 gcc_init_libintl ();
ab87f8c8 349
4977bab6
ZW
350 argno = process_args (argc, argv);
351 if (optind == argc)
352 print_usage (true);
86144b75 353
4977bab6
ZW
354 for (; argno != argc; argno++)
355 {
356 release_structures ();
357
358 process_file (argv[argno]);
359 }
360
86144b75
DE
361 return 0;
362}
363
ab87f8c8 364static void
e34d07f2 365fnotice (FILE *file, const char *msgid, ...)
ab87f8c8 366{
e34d07f2
KG
367 va_list ap;
368
369 va_start (ap, msgid);
644f3d7e 370 vfprintf (file, _(msgid), ap);
e34d07f2 371 va_end (ap);
ab87f8c8
JL
372}
373
86144b75
DE
374/* More 'friendly' abort that prints the line and file.
375 config.h can #define abort fancy_abort if you like that sort of thing. */
711d877c 376extern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN;
86144b75
DE
377
378void
379fancy_abort ()
380{
14a774a9 381 fnotice (stderr, "Internal gcov abort.\n");
86144b75
DE
382 exit (FATAL_EXIT_CODE);
383}
384\f
5735c3ea
JM
385/* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
386 otherwise the output of --help. */
86144b75
DE
387
388static void
5735c3ea
JM
389print_usage (error_p)
390 int error_p;
86144b75 391{
5735c3ea
JM
392 FILE *file = error_p ? stderr : stdout;
393 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
4977bab6 394
5735c3ea
JM
395 fnotice (file, "Usage: gcov [OPTION]... SOURCEFILE\n\n");
396 fnotice (file, "Print code coverage information.\n\n");
397 fnotice (file, " -h, --help Print this help, then exit\n");
398 fnotice (file, " -v, --version Print version number, then exit\n");
27283c73 399 fnotice (file, " -a, --all-blocks Show information for every basic block\n");
5735c3ea
JM
400 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
401 fnotice (file, " -c, --branch-counts Given counts of branches taken\n\
402 rather than percentages\n");
403 fnotice (file, " -n, --no-output Do not create an output file\n");
404 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
405 source files\n");
406 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
37b8715b
NS
407 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
408 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
27283c73 409 fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
5735c3ea 410 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
a976603e 411 bug_report_url);
5735c3ea
JM
412 exit (status);
413}
414
415/* Print version information and exit. */
416
417static void
418print_version ()
419{
4977bab6
ZW
420 char v[4];
421 unsigned version = GCOV_VERSION;
422 unsigned ix;
423
424 for (ix = 4; ix--; version >>= 8)
425 v[ix] = version;
426 fnotice (stdout, "gcov %.4s (GCC %s)\n", v, version_string);
427 fnotice (stdout, "Copyright (C) 2002 Free Software Foundation, Inc.\n");
5735c3ea
JM
428 fnotice (stdout,
429 "This is free software; see the source for copying conditions. There is NO\n\
430warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
431 exit (SUCCESS_EXIT_CODE);
86144b75
DE
432}
433
5735c3ea
JM
434static const struct option options[] =
435{
436 { "help", no_argument, NULL, 'h' },
437 { "version", no_argument, NULL, 'v' },
27283c73 438 { "all-blocks", no_argument, NULL, 'a' },
5735c3ea
JM
439 { "branch-probabilities", no_argument, NULL, 'b' },
440 { "branch-counts", no_argument, NULL, 'c' },
441 { "no-output", no_argument, NULL, 'n' },
442 { "long-file-names", no_argument, NULL, 'l' },
443 { "function-summaries", no_argument, NULL, 'f' },
37b8715b
NS
444 { "preserve-paths", no_argument, NULL, 'p' },
445 { "object-directory", required_argument, NULL, 'o' },
446 { "object-file", required_argument, NULL, 'o' },
27283c73 447 { "unconditional-branches", no_argument, NULL, 'u' },
d90f9882 448 { 0, 0, 0, 0 }
5735c3ea
JM
449};
450
4977bab6 451/* Process args, return index to first non-arg. */
86144b75 452
4977bab6 453static int
86144b75
DE
454process_args (argc, argv)
455 int argc;
456 char **argv;
457{
5735c3ea 458 int opt;
86144b75 459
27283c73 460 while ((opt = getopt_long (argc, argv, "abcfhlno:puv", options, NULL)) != -1)
86144b75 461 {
5735c3ea 462 switch (opt)
86144b75 463 {
27283c73
NS
464 case 'a':
465 flag_all_blocks = 1;
466 break;
5735c3ea 467 case 'b':
4977bab6 468 flag_branches = 1;
5735c3ea
JM
469 break;
470 case 'c':
4977bab6 471 flag_counts = 1;
5735c3ea 472 break;
27283c73
NS
473 case 'f':
474 flag_function_summary = 1;
5735c3ea 475 break;
27283c73
NS
476 case 'h':
477 print_usage (false);
478 /* print_usage will exit. */
5735c3ea 479 case 'l':
4977bab6 480 flag_long_names = 1;
5735c3ea 481 break;
27283c73
NS
482 case 'n':
483 flag_gcov_file = 0;
5735c3ea
JM
484 break;
485 case 'o':
486 object_directory = optarg;
487 break;
37b8715b 488 case 'p':
4977bab6 489 flag_preserve_paths = 1;
37b8715b 490 break;
27283c73
NS
491 case 'u':
492 flag_unconditional = 1;
493 break;
494 case 'v':
495 print_version ();
496 /* print_version will exit. */
5735c3ea
JM
497 default:
498 print_usage (true);
499 /* print_usage will exit. */
86144b75 500 }
86144b75
DE
501 }
502
4977bab6
ZW
503 return optind;
504}
505
506/* Process a single source file. */
5735c3ea 507
4977bab6
ZW
508static void
509process_file (file_name)
510 const char *file_name;
511{
512 source_t *src;
513 function_t *fn;
514
515 create_file_names (file_name);
516 if (read_graph_file ())
517 return;
518
519 if (!functions)
520 {
521 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
522 return;
523 }
524
525 if (read_count_file ())
526 return;
527
528 for (fn = functions; fn; fn = fn->next)
529 solve_flow_graph (fn);
530 for (src = sources; src; src = src->next)
531 src->lines = (line_t *) xcalloc (src->num_lines, sizeof (line_t));
532 for (fn = functions; fn; fn = fn->next)
533 {
534 coverage_t coverage;
535
536 memset (&coverage, 0, sizeof (coverage));
537 coverage.name = fn->name;
538 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
539 if (flag_function_summary)
540 {
541 function_summary (&coverage, "Function");
542 fnotice (stdout, "\n");
543 }
544 }
545
546 for (src = sources; src; src = src->next)
547 {
548 accumulate_line_counts (src);
549 function_summary (&src->coverage, "File");
550 if (flag_gcov_file)
551 {
552 char *gcov_file_name = make_gcov_file_name (file_name, src->name);
553 FILE *gcov_file = fopen (gcov_file_name, "w");
554
555 if (gcov_file)
556 {
557 fnotice (stdout, "%s:creating `%s'\n",
558 src->name, gcov_file_name);
559 output_lines (gcov_file, src);
560 if (ferror (gcov_file))
561 fnotice (stderr, "%s:error writing output file `%s'\n",
562 src->name, gcov_file_name);
563 fclose (gcov_file);
564 }
565 else
566 fnotice (stderr, "%s:could not open output file `%s'\n",
567 src->name, gcov_file_name);
568 free (gcov_file_name);
569 }
570 fnotice (stdout, "\n");
571 }
86144b75
DE
572}
573
4977bab6 574/* Release all memory used. */
86144b75 575
4977bab6
ZW
576static void
577release_structures ()
578{
579 function_t *fn;
580 source_t *src;
581
582 free (bbg_file_name);
583 free (da_file_name);
584 da_file_name = bbg_file_name = NULL;
585 bbg_file_time = 0;
586
587 while ((src = sources))
588 {
589 sources = src->next;
590
591 free (src->name);
592 free (src->lines);
593 }
594
595 while ((fn = functions))
596 {
597 unsigned ix;
598 block_t *block;
599
600 functions = fn->next;
601 for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
602 {
603 arc_t *arc, *arc_n;
604
605 for (arc = block->succ; arc; arc = arc_n)
606 {
607 arc_n = arc->succ_next;
608 free (arc);
609 }
4977bab6
ZW
610 }
611 free (fn->blocks);
612 free (fn->counts);
613 }
614}
615
616/* Generate the names of the graph and data files. If OBJECT_DIRECTORY
617 is not specified, these are looked for in the current directory,
618 and named from the basename of the FILE_NAME sans extension. If
37b8715b 619 OBJECT_DIRECTORY is specified and is a directory, the files are in
4977bab6
ZW
620 that directory, but named from the basename of the FILE_NAME, sans
621 extension. Otherwise OBJECT_DIRECTORY is taken to be the name of
622 the object *file*, and the data files are named from that. */
86144b75
DE
623
624static void
4977bab6
ZW
625create_file_names (file_name)
626 const char *file_name;
86144b75 627{
86144b75 628 char *cptr;
37b8715b 629 char *name;
4977bab6 630 int length = strlen (file_name);
37b8715b
NS
631 int base;
632
633 if (object_directory && object_directory[0])
86144b75 634 {
37b8715b
NS
635 struct stat status;
636
637 length += strlen (object_directory) + 2;
638 name = xmalloc (length);
639 name[0] = 0;
640
641 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
642 strcat (name, object_directory);
643 if (base && name[strlen (name) - 1] != '/')
644 strcat (name, "/");
86144b75
DE
645 }
646 else
647 {
37b8715b
NS
648 name = xmalloc (length + 1);
649 name[0] = 0;
650 base = 1;
86144b75 651 }
37b8715b
NS
652
653 if (base)
654 {
f9da5064 655 /* Append source file name. */
4977bab6
ZW
656 cptr = strrchr (file_name, '/');
657 strcat (name, cptr ? cptr + 1 : file_name);
37b8715b 658 }
4977bab6 659
4b7e68e7 660 /* Remove the extension. */
37b8715b 661 cptr = strrchr (name, '.');
86144b75 662 if (cptr)
37b8715b
NS
663 *cptr = 0;
664
665 length = strlen (name);
37b8715b 666
4977bab6
ZW
667 bbg_file_name = xmalloc (length + strlen (GCOV_GRAPH_SUFFIX) + 1);
668 strcpy (bbg_file_name, name);
669 strcpy (bbg_file_name + length, GCOV_GRAPH_SUFFIX);
37b8715b 670
4977bab6
ZW
671 da_file_name = xmalloc (length + strlen (GCOV_DATA_SUFFIX) + 1);
672 strcpy (da_file_name, name);
673 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
37b8715b 674
4977bab6 675 return;
86144b75 676}
86144b75 677
94de45d9
NS
678/* Find or create a source file structure for FILE_NAME. Copies
679 FILE_NAME on creation */
27283c73
NS
680
681static source_t *
682find_source (file_name)
94de45d9 683 const char *file_name;
27283c73 684{
27283c73 685 source_t *src;
94de45d9
NS
686
687 if (!file_name)
688 file_name = "<unknown>";
27283c73
NS
689
690 for (src = sources; src; src = src->next)
691 if (!strcmp (file_name, src->name))
94de45d9
NS
692 return src;
693
694 src = (source_t *)xcalloc (1, sizeof (source_t));
695 src->name = xstrdup (file_name);
696 src->coverage.name = src->name;
697 src->index = sources ? sources->index + 1 : 1;
698 src->next = sources;
699 sources = src;
700
27283c73
NS
701 return src;
702}
703
272d0bee 704/* Read the graph file. Return nonzero on fatal error. */
86144b75 705
4977bab6
ZW
706static int
707read_graph_file ()
86144b75 708{
94de45d9 709 unsigned version;
4977bab6 710 unsigned current_tag = 0;
4977bab6
ZW
711 struct function_info *fn = NULL;
712 source_t *src = NULL;
713 unsigned ix;
7d63a2fa
NS
714 unsigned tag;
715
546d2adb 716 if (!gcov_open (bbg_file_name, 1))
86144b75 717 {
4977bab6
ZW
718 fnotice (stderr, "%s:cannot open graph file\n", bbg_file_name);
719 return 1;
86144b75 720 }
546d2adb 721 bbg_file_time = gcov_time ();
94de45d9 722 if (gcov_read_unsigned () != GCOV_GRAPH_MAGIC)
b7c9bf28 723 {
4977bab6 724 fnotice (stderr, "%s:not a gcov graph file\n", bbg_file_name);
546d2adb 725 gcov_close ();
4977bab6
ZW
726 return 1;
727 }
b7c9bf28 728
94de45d9
NS
729 version = gcov_read_unsigned ();
730 if (version != GCOV_VERSION)
4977bab6
ZW
731 {
732 char v[4], e[4];
94de45d9 733 unsigned required = GCOV_VERSION;
4977bab6 734
94de45d9 735 for (ix = 4; ix--; required >>= 8, version >>= 8)
b7c9bf28 736 {
4977bab6 737 v[ix] = version;
94de45d9 738 e[ix] = required;
b7c9bf28 739 }
4977bab6
ZW
740 fnotice (stderr, "%s:version `%.4s', prefer `%.4s'\n",
741 bbg_file_name, v, e);
742 }
743
7d63a2fa 744 while ((tag = gcov_read_unsigned ()))
4977bab6 745 {
94de45d9 746 unsigned length = gcov_read_unsigned ();
7d63a2fa 747 gcov_position_t base = gcov_position ();
796621e8 748
4977bab6 749 if (tag == GCOV_TAG_FUNCTION)
b7c9bf28 750 {
94de45d9 751 char *function_name;
796621e8 752 unsigned ident, checksum, lineno;
27283c73
NS
753 source_t *src;
754 function_t *probe, *prev;
4977bab6 755
796621e8 756 ident = gcov_read_unsigned ();
94de45d9 757 checksum = gcov_read_unsigned ();
796621e8 758 function_name = xstrdup (gcov_read_string ());
94de45d9
NS
759 src = find_source (gcov_read_string ());
760 lineno = gcov_read_unsigned ();
761
4977bab6
ZW
762 fn = (function_t *)xcalloc (1, sizeof (function_t));
763 fn->name = function_name;
796621e8 764 fn->ident = ident;
4977bab6 765 fn->checksum = checksum;
27283c73
NS
766 fn->src = src;
767 fn->line = lineno;
4977bab6
ZW
768
769 fn->next = functions;
770 functions = fn;
771 current_tag = tag;
27283c73
NS
772
773 if (lineno >= src->num_lines)
774 src->num_lines = lineno + 1;
775 /* Now insert it into the source file's list of
776 functions. Normally functions will be encountered in
777 ascending order, so a simple scan is quick. */
778 for (probe = src->functions, prev = NULL;
779 probe && probe->line > lineno;
780 prev = probe, probe = probe->line_next)
781 continue;
782 fn->line_next = probe;
783 if (prev)
784 prev->line_next = fn;
785 else
786 src->functions = fn;
b7c9bf28 787 }
4977bab6 788 else if (fn && tag == GCOV_TAG_BLOCKS)
b7c9bf28 789 {
4977bab6
ZW
790 if (fn->blocks)
791 fnotice (stderr, "%s:already seen blocks for `%s'\n",
792 bbg_file_name, fn->name);
793 else
b7c9bf28 794 {
27283c73
NS
795 unsigned ix, num_blocks = length / 4;
796 fn->num_blocks = num_blocks;
797
4977bab6
ZW
798 fn->blocks
799 = (block_t *)xcalloc (fn->num_blocks, sizeof (block_t));
27283c73 800 for (ix = 0; ix != num_blocks; ix++)
94de45d9 801 fn->blocks[ix].flags = gcov_read_unsigned ();
b7c9bf28 802 }
4977bab6
ZW
803 }
804 else if (fn && tag == GCOV_TAG_ARCS)
805 {
94de45d9 806 unsigned src = gcov_read_unsigned ();
4977bab6 807 unsigned num_dests = (length - 4) / 8;
4977bab6 808
94de45d9 809 if (src >= fn->num_blocks || fn->blocks[src].succ)
4977bab6
ZW
810 goto corrupt;
811
812 while (num_dests--)
b7c9bf28 813 {
4977bab6 814 struct arc_info *arc;
94de45d9
NS
815 unsigned dest = gcov_read_unsigned ();
816 unsigned flags = gcov_read_unsigned ();
4977bab6 817
94de45d9 818 if (dest >= fn->num_blocks)
4977bab6
ZW
819 goto corrupt;
820 arc = (arc_t *) xcalloc (1, sizeof (arc_t));
821
822 arc->dst = &fn->blocks[dest];
823 arc->src = &fn->blocks[src];
824
825 arc->count = 0;
826 arc->count_valid = 0;
827 arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
828 arc->fake = !!(flags & GCOV_ARC_FAKE);
829 arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
830
831 arc->succ_next = fn->blocks[src].succ;
832 fn->blocks[src].succ = arc;
833 fn->blocks[src].num_succ++;
834
835 arc->pred_next = fn->blocks[dest].pred;
836 fn->blocks[dest].pred = arc;
837 fn->blocks[dest].num_pred++;
838
27283c73
NS
839 if (arc->fake)
840 {
841 if (src)
842 {
843 /* Exceptional exit from this function, the
844 source block must be a call. */
845 fn->blocks[src].is_call_site = 1;
846 arc->is_call_non_return = 1;
847 }
848 else
849 {
850 /* Non-local return from a callee of this
851 function. The destination block is a catch or
852 setjmp. */
853 arc->is_nonlocal_return = 1;
854 fn->blocks[dest].is_nonlocal_return = 1;
855 }
856 }
4977bab6
ZW
857
858 if (!arc->on_tree)
859 fn->num_counts++;
b7c9bf28 860 }
4977bab6
ZW
861 }
862 else if (fn && tag == GCOV_TAG_LINES)
863 {
94de45d9 864 unsigned blockno = gcov_read_unsigned ();
4977bab6
ZW
865 unsigned *line_nos
866 = (unsigned *)xcalloc ((length - 4) / 4, sizeof (unsigned));
867
94de45d9 868 if (blockno >= fn->num_blocks || fn->blocks[blockno].u.line.encoding)
4977bab6
ZW
869 goto corrupt;
870
871 for (ix = 0; ; )
b7c9bf28 872 {
94de45d9 873 unsigned lineno = gcov_read_unsigned ();
4977bab6 874
4977bab6 875 if (lineno)
b7c9bf28 876 {
4977bab6
ZW
877 if (!ix)
878 {
879 line_nos[ix++] = 0;
880 line_nos[ix++] = src->index;
881 }
882 line_nos[ix++] = lineno;
883 if (lineno >= src->num_lines)
884 src->num_lines = lineno + 1;
b7c9bf28 885 }
4977bab6
ZW
886 else
887 {
94de45d9 888 const char *file_name = gcov_read_string ();
4977bab6 889
4977bab6 890 if (!file_name)
b7c9bf28 891 break;
27283c73
NS
892 src = find_source (file_name);
893
4977bab6
ZW
894 line_nos[ix++] = 0;
895 line_nos[ix++] = src->index;
896 }
b7c9bf28 897 }
4977bab6 898
27283c73
NS
899 fn->blocks[blockno].u.line.encoding = line_nos;
900 fn->blocks[blockno].u.line.num = ix;
4977bab6
ZW
901 }
902 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
903 {
904 fn = NULL;
905 current_tag = 0;
906 }
474f141e 907 gcov_sync (base, length);
94de45d9 908 if (gcov_is_error ())
7d63a2fa
NS
909 break;
910 }
911 if (!gcov_is_eof ())
912 {
913 corrupt:;
914 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
915 gcov_close ();
916 return 1;
b7c9bf28 917 }
546d2adb 918 gcov_close ();
4977bab6
ZW
919
920 /* We built everything backwards, so nreverse them all */
921
922 /* Reverse sources. Not strictly necessary, but we'll then process
923 them in the 'expected' order. */
924 {
925 source_t *src, *src_p, *src_n;
926
927 for (src_p = NULL, src = sources; src; src_p = src, src = src_n)
928 {
929 src_n = src->next;
930 src->next = src_p;
931 }
932 sources = src_p;
933 }
b7c9bf28 934
4977bab6
ZW
935 /* Reverse functions. */
936 {
937 function_t *fn, *fn_p, *fn_n;
b7c9bf28 938
4977bab6
ZW
939 for (fn_p = NULL, fn = functions; fn; fn_p = fn, fn = fn_n)
940 {
941 unsigned ix;
942
943 fn_n = fn->next;
944 fn->next = fn_p;
b7c9bf28 945
f9da5064 946 /* Reverse the arcs. */
4977bab6
ZW
947 for (ix = fn->num_blocks; ix--;)
948 {
949 arc_t *arc, *arc_p, *arc_n;
950
951 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
952 arc_p = arc, arc = arc_n)
953 {
954 arc_n = arc->succ_next;
955 arc->succ_next = arc_p;
956 }
957 fn->blocks[ix].succ = arc_p;
958
959 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
960 arc_p = arc, arc = arc_n)
961 {
962 arc_n = arc->pred_next;
963 arc->pred_next = arc_p;
964 }
965 fn->blocks[ix].pred = arc_p;
966 }
967 }
968 functions = fn_p;
969 }
970 return 0;
b7c9bf28 971}
86144b75 972
4977bab6 973/* Reads profiles from the count file and attach to each
272d0bee 974 function. Return nonzero if fatal error. */
86144b75 975
4977bab6
ZW
976static int
977read_count_file ()
86144b75 978{
4977bab6 979 unsigned ix;
94de45d9 980 unsigned version;
7d63a2fa 981 unsigned tag;
4977bab6 982 function_t *fn = NULL;
7d63a2fa 983 int error = 0;
4977bab6 984
546d2adb 985 if (!gcov_open (da_file_name, 1))
86144b75 986 {
4977bab6
ZW
987 fnotice (stderr, "%s:cannot open data file\n", da_file_name);
988 return 1;
989 }
94de45d9 990 if (gcov_read_unsigned () != GCOV_DATA_MAGIC)
4977bab6
ZW
991 {
992 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
993 cleanup:;
546d2adb 994 gcov_close ();
4977bab6
ZW
995 return 1;
996 }
94de45d9
NS
997 version = gcov_read_unsigned ();
998 if (version != GCOV_VERSION)
4977bab6
ZW
999 {
1000 char v[4], e[4];
94de45d9 1001 unsigned desired = GCOV_VERSION;
4977bab6 1002
94de45d9 1003 for (ix = 4; ix--; desired >>= 8, version >>= 8)
86144b75 1004 {
4977bab6 1005 v[ix] = version;
94de45d9 1006 e[ix] = desired;
86144b75 1007 }
4977bab6
ZW
1008 fnotice (stderr, "%s:version `%.4s', prefer version `%.4s'\n",
1009 da_file_name, v, e);
86144b75 1010 }
4977bab6 1011
7d63a2fa 1012 while ((tag = gcov_read_unsigned ()))
4977bab6 1013 {
94de45d9
NS
1014 unsigned length = gcov_read_unsigned ();
1015 unsigned long base = gcov_position ();
94de45d9 1016
27283c73 1017 if (tag == GCOV_TAG_OBJECT_SUMMARY)
94de45d9 1018 gcov_read_summary (&object_summary);
cdb23767 1019 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
94de45d9 1020 program_count++;
27283c73 1021 else if (tag == GCOV_TAG_FUNCTION)
86144b75 1022 {
796621e8 1023 unsigned ident = gcov_read_unsigned ();
4977bab6 1024 struct function_info *fn_n = functions;
4977bab6
ZW
1025
1026 for (fn = fn ? fn->next : NULL; ; fn = fn->next)
86144b75 1027 {
4977bab6
ZW
1028 if (fn)
1029 ;
1030 else if ((fn = fn_n))
1031 fn_n = NULL;
1032 else
86144b75 1033 {
796621e8
NS
1034 fnotice (stderr, "%s:unknown function `%u'\n",
1035 da_file_name, ident);
4977bab6 1036 break;
86144b75 1037 }
796621e8 1038 if (fn->ident == ident)
4977bab6 1039 break;
86144b75 1040 }
4977bab6
ZW
1041
1042 if (!fn)
1043 ;
94de45d9 1044 else if (gcov_read_unsigned () != fn->checksum)
86144b75 1045 {
4977bab6
ZW
1046 mismatch:;
1047 fnotice (stderr, "%s:profile mismatch for `%s'\n",
94de45d9 1048 da_file_name, fn->name);
4977bab6
ZW
1049 goto cleanup;
1050 }
1051 }
cdb23767 1052 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
4977bab6
ZW
1053 {
1054 if (length != 8 * fn->num_counts)
1055 goto mismatch;
1056
1057 if (!fn->counts)
1058 fn->counts
1059 = (gcov_type *)xcalloc (fn->num_counts, sizeof (gcov_type));
1060
1061 for (ix = 0; ix != fn->num_counts; ix++)
94de45d9
NS
1062 fn->counts[ix] += gcov_read_counter ();
1063 }
474f141e 1064 gcov_sync (base, length);
94de45d9 1065 if ((error = gcov_is_error ()))
7d63a2fa 1066 break;
86144b75 1067 }
23190837 1068
7d63a2fa
NS
1069 if (!gcov_is_eof ())
1070 {
1071 fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1072 da_file_name);
1073 goto cleanup;
1074 }
1075
546d2adb 1076 gcov_close ();
4977bab6 1077 return 0;
86144b75
DE
1078}
1079
4977bab6
ZW
1080/* Solve the flow graph. Propagate counts from the instrumented arcs
1081 to the blocks and the uninstrumented arcs. */
86144b75
DE
1082
1083static void
4977bab6
ZW
1084solve_flow_graph (fn)
1085 function_t *fn;
86144b75 1086{
4977bab6
ZW
1087 unsigned ix;
1088 arc_t *arc;
1089 gcov_type *count_ptr = fn->counts;
27283c73 1090 block_t *blk;
32dd366d
KH
1091 block_t *valid_blocks = NULL; /* valid, but unpropagated blocks. */
1092 block_t *invalid_blocks = NULL; /* invalid, but inferable blocks. */
4977bab6
ZW
1093
1094 if (fn->num_blocks < 2)
1095 fnotice (stderr, "%s:`%s' lacks entry and/or exit blocks\n",
1096 bbg_file_name, fn->name);
1097 else
86144b75 1098 {
4977bab6
ZW
1099 if (fn->blocks[0].num_pred)
1100 fnotice (stderr, "%s:`%s' has arcs to entry block\n",
1101 bbg_file_name, fn->name);
86144b75 1102 else
4977bab6
ZW
1103 /* We can't deduce the entry block counts from the lack of
1104 predecessors. */
1105 fn->blocks[0].num_pred = ~(unsigned)0;
1106
1107 if (fn->blocks[fn->num_blocks - 1].num_succ)
1108 fnotice (stderr, "%s:`%s' has arcs from exit block\n",
1109 bbg_file_name, fn->name);
1110 else
1111 /* Likewise, we can't deduce exit block counts from the lack
1112 of its successors. */
1113 fn->blocks[fn->num_blocks - 1].num_succ = ~(unsigned)0;
86144b75
DE
1114 }
1115
4977bab6
ZW
1116 /* Propagate the measured counts, this must be done in the same
1117 order as the code in profile.c */
27283c73 1118 for (ix = 0, blk = fn->blocks; ix != fn->num_blocks; ix++, blk++)
86144b75 1119 {
4977bab6
ZW
1120 block_t const *prev_dst = NULL;
1121 int out_of_order = 0;
27283c73 1122 int non_fake_succ = 0;
4977bab6 1123
27283c73 1124 for (arc = blk->succ; arc; arc = arc->succ_next)
86144b75 1125 {
27283c73
NS
1126 if (!arc->fake)
1127 non_fake_succ++;
1128
4977bab6 1129 if (!arc->on_tree)
86144b75 1130 {
4977bab6
ZW
1131 if (count_ptr)
1132 arc->count = *count_ptr++;
1133 arc->count_valid = 1;
27283c73 1134 blk->num_succ--;
4977bab6 1135 arc->dst->num_pred--;
86144b75 1136 }
4977bab6
ZW
1137 if (prev_dst && prev_dst > arc->dst)
1138 out_of_order = 1;
1139 prev_dst = arc->dst;
86144b75 1140 }
27283c73
NS
1141 if (non_fake_succ == 1)
1142 {
1143 /* If there is only one non-fake exit, it is an
1144 unconditional branch. */
1145 for (arc = blk->succ; arc; arc = arc->succ_next)
1146 if (!arc->fake)
1147 {
1148 arc->is_unconditional = 1;
1149 /* If this block is instrumenting a call, it might be
e0bb17a8 1150 an artificial block. It is not artificial if it has
10b7602f
NS
1151 a non-fallthrough exit, or the destination of this
1152 arc has more than one entry. Mark the destination
1153 block as a return site, if none of those conditions
1154 hold. */
1155 if (blk->is_call_site && arc->fall_through
1156 && arc->dst->pred == arc && !arc->pred_next)
1157 arc->dst->is_call_return = 1;
27283c73
NS
1158 }
1159 }
4977bab6
ZW
1160
1161 /* Sort the successor arcs into ascending dst order. profile.c
1162 normally produces arcs in the right order, but sometimes with
1163 one or two out of order. We're not using a particularly
32dd366d 1164 smart sort. */
4977bab6 1165 if (out_of_order)
86144b75 1166 {
27283c73 1167 arc_t *start = blk->succ;
4977bab6
ZW
1168 unsigned changes = 1;
1169
1170 while (changes)
1171 {
1172 arc_t *arc, *arc_p, *arc_n;
1173
1174 changes = 0;
1175 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1176 {
1177 if (arc->dst > arc_n->dst)
1178 {
1179 changes = 1;
1180 if (arc_p)
1181 arc_p->succ_next = arc_n;
1182 else
1183 start = arc_n;
1184 arc->succ_next = arc_n->succ_next;
1185 arc_n->succ_next = arc;
1186 arc_p = arc_n;
1187 }
1188 else
1189 {
1190 arc_p = arc;
1191 arc = arc_n;
1192 }
1193 }
1194 }
27283c73 1195 blk->succ = start;
86144b75 1196 }
4977bab6
ZW
1197
1198 /* Place it on the invalid chain, it will be ignored if that's
1199 wrong. */
27283c73
NS
1200 blk->invalid_chain = 1;
1201 blk->chain = invalid_blocks;
1202 invalid_blocks = blk;
4977bab6
ZW
1203 }
1204
1205 while (invalid_blocks || valid_blocks)
1206 {
4977bab6 1207 while ((blk = invalid_blocks))
86144b75 1208 {
4977bab6
ZW
1209 gcov_type total = 0;
1210 const arc_t *arc;
1211
1212 invalid_blocks = blk->chain;
1213 blk->invalid_chain = 0;
1214 if (!blk->num_succ)
1215 for (arc = blk->succ; arc; arc = arc->succ_next)
1216 total += arc->count;
1217 else if (!blk->num_pred)
1218 for (arc = blk->pred; arc; arc = arc->pred_next)
1219 total += arc->count;
1220 else
1221 continue;
1222
1223 blk->count = total;
1224 blk->count_valid = 1;
1225 blk->chain = valid_blocks;
1226 blk->valid_chain = 1;
1227 valid_blocks = blk;
86144b75 1228 }
4977bab6 1229 while ((blk = valid_blocks))
86144b75 1230 {
4977bab6
ZW
1231 gcov_type total;
1232 arc_t *arc, *inv_arc;
1233
1234 valid_blocks = blk->chain;
1235 blk->valid_chain = 0;
1236 if (blk->num_succ == 1)
1237 {
1238 block_t *dst;
1239
1240 total = blk->count;
1241 inv_arc = NULL;
1242 for (arc = blk->succ; arc; arc = arc->succ_next)
1243 {
1244 total -= arc->count;
1245 if (!arc->count_valid)
1246 inv_arc = arc;
1247 }
1248 dst = inv_arc->dst;
1249 inv_arc->count_valid = 1;
1250 inv_arc->count = total;
1251 blk->num_succ--;
1252 dst->num_pred--;
1253 if (dst->count_valid)
1254 {
1255 if (dst->num_pred == 1 && !dst->valid_chain)
1256 {
1257 dst->chain = valid_blocks;
1258 dst->valid_chain = 1;
1259 valid_blocks = dst;
1260 }
1261 }
1262 else
1263 {
1264 if (!dst->num_pred && !dst->invalid_chain)
1265 {
1266 dst->chain = invalid_blocks;
1267 dst->invalid_chain = 1;
1268 invalid_blocks = dst;
1269 }
1270 }
1271 }
1272 if (blk->num_pred == 1)
1273 {
1274 block_t *src;
1275
1276 total = blk->count;
1277 inv_arc = NULL;
1278 for (arc = blk->pred; arc; arc = arc->pred_next)
1279 {
1280 total -= arc->count;
1281 if (!arc->count_valid)
1282 inv_arc = arc;
1283 }
1284 src = inv_arc->src;
1285 inv_arc->count_valid = 1;
1286 inv_arc->count = total;
1287 blk->num_pred--;
1288 src->num_succ--;
1289 if (src->count_valid)
1290 {
1291 if (src->num_succ == 1 && !src->valid_chain)
1292 {
1293 src->chain = valid_blocks;
1294 src->valid_chain = 1;
1295 valid_blocks = src;
1296 }
1297 }
1298 else
1299 {
1300 if (!src->num_succ && !src->invalid_chain)
1301 {
1302 src->chain = invalid_blocks;
1303 src->invalid_chain = 1;
1304 invalid_blocks = src;
1305 }
1306 }
1307 }
86144b75
DE
1308 }
1309 }
4977bab6
ZW
1310
1311 /* If the graph has been correctly solved, every block will have a
1312 valid count. */
1313 for (ix = 0; ix < fn->num_blocks; ix++)
1314 if (!fn->blocks[ix].count_valid)
1315 {
1316 fnotice (stderr, "%s:graph is unsolvable for `%s'\n",
1317 bbg_file_name, fn->name);
1318 break;
1319 }
86144b75 1320}
4977bab6 1321
86144b75 1322\f
86144b75 1323
4977bab6 1324/* Increment totals in COVERAGE according to arc ARC. */
8b219a76
NS
1325
1326static void
4977bab6
ZW
1327add_branch_counts (coverage, arc)
1328 coverage_t *coverage;
1329 const arc_t *arc;
8b219a76 1330{
27283c73 1331 if (arc->is_call_non_return)
8b219a76 1332 {
4977bab6
ZW
1333 coverage->calls++;
1334 if (arc->src->count)
1335 coverage->calls_executed++;
8b219a76 1336 }
27283c73 1337 else if (!arc->is_unconditional)
8b219a76 1338 {
4977bab6
ZW
1339 coverage->branches++;
1340 if (arc->src->count)
1341 coverage->branches_executed++;
1342 if (arc->count)
1343 coverage->branches_taken++;
86144b75
DE
1344 }
1345}
1346
37b8715b
NS
1347/* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1348 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1349 If DP is zero, no decimal point is printed. Only print 100% when
1350 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1351 format TOP. Return pointer to a static string. */
1352
1353static char const *
4977bab6
ZW
1354format_gcov (top, bottom, dp)
1355 gcov_type top, bottom;
37b8715b
NS
1356 int dp;
1357{
1358 static char buffer[20];
1359
1360 if (dp >= 0)
1361 {
1362 float ratio = bottom ? (float)top / bottom : 0;
1363 int ix;
1364 unsigned limit = 100;
1365 unsigned percent;
1366
1367 for (ix = dp; ix--; )
1368 limit *= 10;
1369
d19202ba
NS
1370 percent = (unsigned) (ratio * limit + (float)0.5);
1371 if (percent <= 0 && top)
37b8715b 1372 percent = 1;
d19202ba 1373 else if (percent >= limit && top != bottom)
37b8715b
NS
1374 percent = limit - 1;
1375 ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1376 if (dp)
1377 {
1378 dp++;
1379 do
1380 {
1381 buffer[ix+1] = buffer[ix];
1382 ix--;
1383 }
1384 while (dp--);
1385 buffer[ix + 1] = '.';
1386 }
1387 }
1388 else
4977bab6 1389 sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)top);
37b8715b
NS
1390
1391 return buffer;
1392}
1393
1394
86144b75
DE
1395/* Output summary info for a function. */
1396
1397static void
4977bab6
ZW
1398function_summary (coverage, title)
1399 const coverage_t *coverage;
8b219a76 1400 const char *title;
86144b75 1401{
4977bab6
ZW
1402 fnotice (stdout, "%s `%s'\n", title, coverage->name);
1403
1404 if (coverage->lines)
1405 fnotice (stdout, "Lines executed:%s of %d\n",
1406 format_gcov (coverage->lines_executed, coverage->lines, 2),
1407 coverage->lines);
86144b75 1408 else
4977bab6 1409 fnotice (stdout, "No executable lines");
86144b75 1410
4977bab6 1411 if (flag_branches)
86144b75 1412 {
4977bab6 1413 if (coverage->branches)
86144b75 1414 {
4977bab6
ZW
1415 fnotice (stdout, "Branches executed:%s of %d\n",
1416 format_gcov (coverage->branches_executed,
1417 coverage->branches, 2),
1418 coverage->branches);
1419 fnotice (stdout, "Taken at least once:%s of %d\n",
1420 format_gcov (coverage->branches_taken,
1421 coverage->branches, 2),
1422 coverage->branches);
86144b75
DE
1423 }
1424 else
4977bab6
ZW
1425 fnotice (stdout, "No branches\n");
1426 if (coverage->calls)
1427 fnotice (stdout, "Calls executed:%s of %d\n",
1428 format_gcov (coverage->calls_executed, coverage->calls, 2),
1429 coverage->calls);
86144b75 1430 else
4977bab6 1431 fnotice (stdout, "No calls\n");
8b219a76
NS
1432 }
1433}
1434
1435/* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
1436 affect name generation. With preserve_paths we create a filename
1437 from all path components of the source file, replacing '/' with
1438 '#', without it we simply take the basename component. With
1439 long_output_names we prepend the processed name of the input file
1440 to each output name (except when the current source file is the
1441 input file, so you don't get a double concatenation). The two
1442 components are separated by '##'. Also '.' filename components are
4b7e68e7 1443 removed and '..' components are renamed to '^'. */
8b219a76
NS
1444
1445static char *
4977bab6
ZW
1446make_gcov_file_name (input_name, src_name)
1447 const char *input_name;
1448 const char *src_name;
8b219a76
NS
1449{
1450 char *cptr;
4977bab6 1451 char *name = xmalloc (strlen (src_name) + strlen (input_name) + 10);
8b219a76
NS
1452
1453 name[0] = 0;
4977bab6 1454 if (flag_long_names && strcmp (src_name, input_name))
8b219a76
NS
1455 {
1456 /* Generate the input filename part. */
4977bab6
ZW
1457 cptr = flag_preserve_paths ? NULL : strrchr (input_name, '/');
1458 strcat (name, cptr ? cptr + 1 : input_name);
8b219a76
NS
1459 strcat (name, "##");
1460 }
1461
4b7e68e7 1462 /* Generate the source filename part. */
4977bab6
ZW
1463 cptr = flag_preserve_paths ? NULL : strrchr (src_name, '/');
1464 strcat (name, cptr ? cptr + 1 : src_name);
8b219a76 1465
4977bab6 1466 if (flag_preserve_paths)
8b219a76
NS
1467 {
1468 /* Convert '/' to '#', remove '/./', convert '/../' to '/^/' */
1469 char *prev;
1470
1471 for (cptr = name; (cptr = strchr ((prev = cptr), '/'));)
1472 {
1473 unsigned shift = 0;
1474
1475 if (prev + 1 == cptr && prev[0] == '.')
1476 {
1477 /* Remove '.' */
1478 shift = 2;
1479 }
1480 else if (prev + 2 == cptr && prev[0] == '.' && prev[1] == '.')
1481 {
1482 /* Convert '..' */
1483 shift = 1;
1484 prev[1] = '^';
1485 }
1486 else
1487 *cptr++ = '#';
1488 if (shift)
1489 {
1490 cptr = prev;
1491 do
1492 prev[0] = prev[shift];
1493 while (*prev++);
1494 }
1495 }
86144b75 1496 }
8b219a76 1497
8b219a76
NS
1498 strcat (name, ".gcov");
1499 return name;
86144b75
DE
1500}
1501
4977bab6 1502/* Scan through the bb_data for each line in the block, increment
8b219a76
NS
1503 the line number execution count indicated by the execution count of
1504 the appropriate basic block. */
86144b75
DE
1505
1506static void
4977bab6
ZW
1507add_line_counts (coverage, fn)
1508 coverage_t *coverage;
27283c73 1509 function_t *fn;
86144b75 1510{
4977bab6
ZW
1511 unsigned ix;
1512 line_t *line = NULL; /* this is propagated from one iteration to the
1513 next. */
1514
32dd366d 1515 /* Scan each basic block. */
4977bab6 1516 for (ix = 0; ix != fn->num_blocks; ix++)
86144b75 1517 {
27283c73 1518 block_t *block = &fn->blocks[ix];
4977bab6
ZW
1519 unsigned *encoding;
1520 const source_t *src = NULL;
1521 unsigned jx;
1522
27283c73
NS
1523 if (block->count && ix && ix + 1 != fn->num_blocks)
1524 fn->blocks_executed++;
1525 for (jx = 0, encoding = block->u.line.encoding;
1526 jx != block->u.line.num; jx++, encoding++)
4977bab6
ZW
1527 if (!*encoding)
1528 {
1529 unsigned src_n = *++encoding;
86144b75 1530
4977bab6
ZW
1531 for (src = sources; src->index != src_n; src = src->next)
1532 continue;
1533 jx++;
1534 }
1535 else
1536 {
1537 line = &src->lines[*encoding];
1538
1539 if (coverage)
1540 {
1541 if (!line->exists)
1542 coverage->lines++;
27283c73 1543 if (!line->count && block->count)
4977bab6
ZW
1544 coverage->lines_executed++;
1545 }
1546 line->exists = 1;
1547 line->count += block->count;
1548 }
27283c73 1549 free (block->u.line.encoding);
10b7602f
NS
1550 block->u.cycle.arc = NULL;
1551 block->u.cycle.ident = ~0U;
1552
27283c73
NS
1553 if (!ix || ix + 1 == fn->num_blocks)
1554 /* Entry or exit block */;
1555 else if (flag_all_blocks)
86144b75 1556 {
10b7602f 1557 line_t *block_line = line ? line : &fn->src->lines[fn->line];
8b219a76 1558
10b7602f
NS
1559 block->chain = block_line->u.blocks;
1560 block_line->u.blocks = block;
27283c73
NS
1561 }
1562 else if (flag_branches)
1563 {
1564 arc_t *arc;
1565
4977bab6 1566 for (arc = block->succ; arc; arc = arc->succ_next)
86144b75 1567 {
27283c73
NS
1568 arc->line_next = line->u.branches;
1569 line->u.branches = arc;
1570 if (coverage && !arc->is_unconditional)
4977bab6 1571 add_branch_counts (coverage, arc);
86144b75 1572 }
8b219a76
NS
1573 }
1574 }
4977bab6
ZW
1575 if (!line)
1576 fnotice (stderr, "%s:no lines for `%s'\n", bbg_file_name, fn->name);
1577}
1578
32dd366d 1579/* Accumulate the line counts of a file. */
4977bab6
ZW
1580
1581static void
1582accumulate_line_counts (src)
1583 source_t *src;
1584{
1585 line_t *line;
27283c73 1586 function_t *fn, *fn_p, *fn_n;
4977bab6 1587 unsigned ix;
27283c73
NS
1588
1589 /* Reverse the function order. */
1590 for (fn = src->functions, fn_p = NULL; fn;
1591 fn_p = fn, fn = fn_n)
1592 {
1593 fn_n = fn->line_next;
1594 fn->line_next = fn_p;
1595 }
1596 src->functions = fn_p;
8b219a76 1597
4977bab6 1598 for (ix = src->num_lines, line = src->lines; ix--; line++)
8b219a76 1599 {
27283c73 1600 if (!flag_all_blocks)
8b219a76 1601 {
27283c73
NS
1602 arc_t *arc, *arc_p, *arc_n;
1603
1604 /* Total and reverse the branch information. */
1605 for (arc = line->u.branches, arc_p = NULL; arc;
1606 arc_p = arc, arc = arc_n)
1607 {
1608 arc_n = arc->line_next;
1609 arc->line_next = arc_p;
1610
1611 add_branch_counts (&src->coverage, arc);
1612 }
1613 line->u.branches = arc_p;
8b219a76 1614 }
27283c73
NS
1615 else if (line->u.blocks)
1616 {
1617 /* The user expects the line count to be the number of times
1618 a line has been executed. Simply summing the block count
1619 will give an artificially high number. The Right Thing
10b7602f
NS
1620 is to sum the entry counts to the graph of blocks on this
1621 line, then find the elementary cycles of the local graph
1622 and add the transition counts of those cycles. */
27283c73 1623 block_t *block, *block_p, *block_n;
27283c73
NS
1624 gcov_type count = 0;
1625
f9da5064 1626 /* Reverse the block information. */
27283c73
NS
1627 for (block = line->u.blocks, block_p = NULL; block;
1628 block_p = block, block = block_n)
1629 {
1630 block_n = block->chain;
1631 block->chain = block_p;
10b7602f 1632 block->u.cycle.ident = ix;
27283c73
NS
1633 }
1634 line->u.blocks = block_p;
10b7602f
NS
1635
1636 /* Sum the entry arcs. */
1637 for (block = line->u.blocks; block; block = block->chain)
1638 {
1639 arc_t *arc;
86144b75 1640
10b7602f
NS
1641 for (arc = block->pred; arc; arc = arc->pred_next)
1642 {
1643 if (arc->src->u.cycle.ident != ix)
1644 count += arc->count;
1645 if (flag_branches)
1646 add_branch_counts (&src->coverage, arc);
1647 }
1648 }
1649
1650 /* Find the loops. This uses the algorithm described in
1651 Tiernan 'An Efficient Search Algorithm to Find the
1652 Elementary Circuits of a Graph', CACM Dec 1970. We hold
1653 the P array by having each block point to the arc that
1654 connects to the previous block. The H array is implicitly
1655 held because of the arc ordering, and the block's
1656 previous arc pointer.
1657
1658 Although the algorithm is O(N^3) for highly connected
1659 graphs, at worst we'll have O(N^2), as most blocks have
1660 only one or two exits. Most graphs will be small.
1661
1662 For each loop we find, locate the arc with the smallest
1663 transition count, and add that to the cumulative
1664 count. Remove the arc from consideration. */
1665 for (block = line->u.blocks; block; block = block->chain)
27283c73 1666 {
10b7602f
NS
1667 block_t *head = block;
1668 arc_t *arc;
27283c73 1669
10b7602f
NS
1670 next_vertex:;
1671 arc = head->succ;
1672 current_vertex:;
1673 while (arc)
27283c73 1674 {
10b7602f
NS
1675 block_t *dst = arc->dst;
1676 if (/* Already used that arc. */
1677 arc->cycle
1678 /* Not to same graph, or before first vertex. */
1679 || dst->u.cycle.ident != ix
1680 /* Already in path. */
1681 || dst->u.cycle.arc)
1682 {
1683 arc = arc->succ_next;
1684 continue;
1685 }
27283c73 1686
10b7602f 1687 if (dst == block)
27283c73 1688 {
10b7602f
NS
1689 /* Found a closing arc. */
1690 gcov_type cycle_count = arc->count;
1691 arc_t *cycle_arc = arc;
1692 arc_t *probe_arc;
27283c73 1693
71c0e7fc 1694 /* Locate the smallest arc count of the loop. */
10b7602f
NS
1695 for (dst = head; (probe_arc = dst->u.cycle.arc);
1696 dst = probe_arc->src)
1697 if (cycle_count > probe_arc->count)
1698 {
1699 cycle_count = probe_arc->count;
1700 cycle_arc = probe_arc;
1701 }
1702
1703 count += cycle_count;
1704 cycle_arc->cycle = 1;
1705 /* Unwind to the cyclic arc. */
1706 while (head != cycle_arc->src)
27283c73 1707 {
10b7602f
NS
1708 arc = head->u.cycle.arc;
1709 head = arc->src;
27283c73 1710 }
10b7602f
NS
1711 /* Move on. */
1712 arc = arc->succ_next;
1713 continue;
27283c73 1714 }
10b7602f
NS
1715
1716 /* Add new block to chain. */
1717 dst->u.cycle.arc = arc;
1718 head = dst;
1719 goto next_vertex;
27283c73 1720 }
10b7602f
NS
1721 /* We could not add another vertex to the path. Remove
1722 the last vertex from the list. */
1723 arc = head->u.cycle.arc;
1724 if (arc)
27283c73 1725 {
71c0e7fc 1726 /* It was not the first vertex. Move onto next arc. */
10b7602f
NS
1727 head->u.cycle.arc = NULL;
1728 head = arc->src;
1729 arc = arc->succ_next;
1730 goto current_vertex;
27283c73 1731 }
10b7602f
NS
1732 /* Mark this block as unusable. */
1733 block->u.cycle.ident = ~0U;
27283c73 1734 }
10b7602f 1735
27283c73
NS
1736 line->count = count;
1737 }
1738
4977bab6 1739 if (line->exists)
8b219a76 1740 {
4977bab6
ZW
1741 src->coverage.lines++;
1742 if (line->count)
1743 src->coverage.lines_executed++;
8b219a76 1744 }
8b219a76
NS
1745 }
1746}
86144b75 1747
6356f892 1748/* Ouput information about ARC number IX. Returns nonzero if
27283c73
NS
1749 anything is output. */
1750
1751static int
1752output_branch_count (gcov_file, ix, arc)
1753 FILE *gcov_file;
1754 int ix;
1755 const arc_t *arc;
1756{
1757
1758 if (arc->is_call_non_return)
1759 {
1760 if (arc->src->count)
1761 {
1762 fnotice (gcov_file, "call %2d returned %s\n", ix,
1763 format_gcov (arc->src->count - arc->count,
1764 arc->src->count, -flag_counts));
1765 }
1766 else
1767 fnotice (gcov_file, "call %2d never executed\n", ix);
1768 }
1769 else if (!arc->is_unconditional)
1770 {
1771 if (arc->src->count)
1772 fnotice (gcov_file, "branch %2d taken %s%s\n", ix,
1773 format_gcov (arc->count, arc->src->count, -flag_counts),
1774 arc->fall_through ? " (fallthrough)" : "");
1775 else
1776 fnotice (gcov_file, "branch %2d never executed\n", ix);
1777 }
10b7602f 1778 else if (flag_unconditional && !arc->dst->is_call_return)
27283c73
NS
1779 {
1780 if (arc->src->count)
1781 fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
1782 format_gcov (arc->count, arc->src->count, -flag_counts));
1783 else
1784 fnotice (gcov_file, "unconditional %2d never executed\n", ix);
1785 }
1786 else
1787 return 0;
1788 return 1;
1789
1790}
1791
8b219a76
NS
1792/* Read in the source file one line at a time, and output that line to
1793 the gcov file preceded by its execution count and other
1794 information. */
86144b75 1795
8b219a76 1796static void
4977bab6 1797output_lines (gcov_file, src)
8b219a76 1798 FILE *gcov_file;
4977bab6 1799 const source_t *src;
8b219a76
NS
1800{
1801 FILE *source_file;
4977bab6
ZW
1802 unsigned line_num; /* current line number. */
1803 const line_t *line; /* current line info ptr. */
1804 char string[STRING_SIZE]; /* line buffer. */
1805 char const *retval = ""; /* status of source file reading. */
27283c73 1806 function_t *fn = src->functions;
4977bab6
ZW
1807
1808 fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->name);
1809 fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
1810 fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0, da_file_name);
cdb23767
NS
1811 fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0,
1812 object_summary.ctrs[GCOV_COUNTER_ARCS].runs);
27283c73 1813 fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
8b219a76 1814
4977bab6 1815 source_file = fopen (src->name, "r");
8b219a76
NS
1816 if (!source_file)
1817 {
4977bab6 1818 fnotice (stderr, "%s:cannot open source file\n", src->name);
8b219a76
NS
1819 retval = NULL;
1820 }
1821 else
1822 {
1823 struct stat status;
1824
1825 if (!fstat (fileno (source_file), &status)
4977bab6 1826 && status.st_mtime > bbg_file_time)
8b219a76 1827 {
4977bab6
ZW
1828 fnotice (stderr, "%s:source file is newer than graph file `%s'\n",
1829 src->name, bbg_file_name);
1830 fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n",
8b219a76
NS
1831 "-", 0);
1832 }
1833 }
1834
4977bab6
ZW
1835 for (line_num = 1, line = &src->lines[line_num];
1836 line_num < src->num_lines; line_num++, line++)
8b219a76 1837 {
27283c73
NS
1838 for (; fn && fn->line == line_num; fn = fn->line_next)
1839 {
1840 arc_t *arc = fn->blocks[fn->num_blocks - 1].pred;
1841 gcov_type return_count = fn->blocks[fn->num_blocks - 1].count;
1842
1843 for (; arc; arc = arc->pred_next)
1844 if (arc->fake)
1845 return_count -= arc->count;
1846
1847 fprintf (gcov_file, "function %s", fn->name);
1848 fprintf (gcov_file, " called %s",
1849 format_gcov (fn->blocks[0].count, 0, -1));
1850 fprintf (gcov_file, " returned %s",
1851 format_gcov (return_count, fn->blocks[0].count, 0));
1852 fprintf (gcov_file, " blocks executed %s",
1853 format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0));
1854 fprintf (gcov_file, "\n");
1855 }
1856
8b219a76
NS
1857 /* For lines which don't exist in the .bb file, print '-' before
1858 the source line. For lines which exist but were never
1859 executed, print '#####' before the source line. Otherwise,
1860 print the execution count before the source line. There are
1861 16 spaces of indentation added before the source line so that
1862 tabs won't be messed up. */
4977bab6
ZW
1863 fprintf (gcov_file, "%9s:%5u:",
1864 !line->exists ? "-" : !line->count ? "#####"
1865 : format_gcov (line->count, 0, -1), line_num);
8b219a76
NS
1866
1867 if (retval)
1868 {
1869 /* Copy source line. */
1870 do
1871 {
1872 retval = fgets (string, STRING_SIZE, source_file);
1873 if (!retval)
299f79b5 1874 break;
8b219a76 1875 fputs (retval, gcov_file);
37b8715b 1876 }
8b219a76
NS
1877 while (!retval[0] || retval[strlen (retval) - 1] != '\n');
1878 }
1879 if (!retval)
299f79b5 1880 fputs ("/*EOF*/\n", gcov_file);
27283c73
NS
1881
1882 if (flag_all_blocks)
8b219a76 1883 {
27283c73 1884 block_t *block;
10b7602f 1885 arc_t *arc;
27283c73 1886 int ix, jx;
37b8715b 1887
27283c73
NS
1888 for (ix = jx = 0, block = line->u.blocks; block;
1889 block = block->chain)
37b8715b 1890 {
10b7602f 1891 if (!block->is_call_return)
27283c73
NS
1892 fprintf (gcov_file, "%9s:%5u-block %2d\n",
1893 !line->exists ? "-" : !block->count ? "$$$$$"
10b7602f
NS
1894 : format_gcov (block->count, 0, -1),
1895 line_num, ix++);
27283c73
NS
1896 if (flag_branches)
1897 for (arc = block->succ; arc; arc = arc->succ_next)
1898 jx += output_branch_count (gcov_file, jx, arc);
86144b75 1899 }
8b219a76 1900 }
27283c73
NS
1901 else if (flag_branches)
1902 {
1903 int ix;
1904 arc_t *arc;
1905
1906 for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
1907 ix += output_branch_count (gcov_file, ix, arc);
1908 }
8b219a76
NS
1909 }
1910
1911 /* Handle all remaining source lines. There may be lines after the
1912 last line of code. */
1913 if (retval)
1914 {
1915 for (; (retval = fgets (string, STRING_SIZE, source_file)); line_num++)
1916 {
4977bab6 1917 fprintf (gcov_file, "%9s:%5u:%s", "-", line_num, retval);
8b219a76
NS
1918
1919 while (!retval[0] || retval[strlen (retval) - 1] != '\n')
37b8715b 1920 {
8b219a76
NS
1921 retval = fgets (string, STRING_SIZE, source_file);
1922 if (!retval)
1923 break;
1924 fputs (retval, gcov_file);
37b8715b 1925 }
8b219a76
NS
1926 }
1927 }
1928
1929 if (source_file)
1930 fclose (source_file);
1931}