2005-04-25 Paul Brook <paul@codesourcery.com>
[official-gcc.git] / gcc / gcov.c
blob6b8f3370c39519725246c976453b23e4cefc19f0
1 /* Gcov.c: prepend line execution counts and branch probabilities to a
2 source file.
3 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998,
4 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
5 Contributed by James E. Wilson of Cygnus Support.
6 Mangled by Bob Manson of Cygnus Support.
7 Mangled further by Nathan Sidwell <nathan@codesourcery.com>
9 Gcov is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
14 Gcov is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Gcov; see the file COPYING. If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
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. */
29 /* ??? Should have an option to print the number of basic blocks, and the
30 percent of them that are covered. */
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. */
41 /* Need an option to show individual block counts, and show
42 probabilities of fall through arcs. */
44 #include "config.h"
45 #include "system.h"
46 #include "coretypes.h"
47 #include "tm.h"
48 #include "intl.h"
49 #include "version.h"
51 #include <getopt.h>
53 #define IN_GCOV 1
54 #include "gcov-io.h"
55 #include "gcov-io.c"
57 /* The bbg file is generated by -ftest-coverage option. The da file is
58 generated by a program compiled with -fprofile-arcs. Their formats
59 are documented in gcov-io.h. */
61 /* The functions in this file for creating and solution program flow graphs
62 are very similar to functions in the gcc source file profile.c. In
63 some places we make use of the knowledge of how profile.c works to
64 select particular algorithms here. */
66 /* This is the size of the buffer used to read in source file lines. */
68 #define STRING_SIZE 200
70 struct function_info;
71 struct block_info;
72 struct source_info;
74 /* Describes an arc between two basic blocks. */
76 typedef struct arc_info
78 /* source and destination blocks. */
79 struct block_info *src;
80 struct block_info *dst;
82 /* transition counts. */
83 gcov_type count;
84 /* used in cycle search, so that we do not clobber original counts. */
85 gcov_type cs_count;
87 unsigned int count_valid : 1;
88 unsigned int on_tree : 1;
89 unsigned int fake : 1;
90 unsigned int fall_through : 1;
92 /* Arc is for a function that abnormally returns. */
93 unsigned int is_call_non_return : 1;
95 /* Arc is for catch/setjump. */
96 unsigned int is_nonlocal_return : 1;
98 /* Is an unconditional branch. */
99 unsigned int is_unconditional : 1;
101 /* Loop making arc. */
102 unsigned int cycle : 1;
104 /* Next branch on line. */
105 struct arc_info *line_next;
107 /* Links to next arc on src and dst lists. */
108 struct arc_info *succ_next;
109 struct arc_info *pred_next;
110 } arc_t;
112 /* Describes a basic block. Contains lists of arcs to successor and
113 predecessor blocks. */
115 typedef struct block_info
117 /* Chain of exit and entry arcs. */
118 arc_t *succ;
119 arc_t *pred;
121 /* Number of unprocessed exit and entry arcs. */
122 gcov_type num_succ;
123 gcov_type num_pred;
125 /* Block execution count. */
126 gcov_type count;
127 unsigned flags : 13;
128 unsigned count_valid : 1;
129 unsigned valid_chain : 1;
130 unsigned invalid_chain : 1;
132 /* Block is a call instrumenting site. */
133 unsigned is_call_site : 1; /* Does the call. */
134 unsigned is_call_return : 1; /* Is the return. */
136 /* Block is a landing pad for longjmp or throw. */
137 unsigned is_nonlocal_return : 1;
139 union
141 struct
143 /* Array of line numbers and source files. source files are
144 introduced by a linenumber of zero, the next 'line number' is
145 the number of the source file. Always starts with a source
146 file. */
147 unsigned *encoding;
148 unsigned num;
149 } line; /* Valid until blocks are linked onto lines */
150 struct
152 /* Single line graph cycle workspace. Used for all-blocks
153 mode. */
154 arc_t *arc;
155 unsigned ident;
156 } cycle; /* Used in all-blocks mode, after blocks are linked onto
157 lines. */
158 } u;
160 /* Temporary chain for solving graph, and for chaining blocks on one
161 line. */
162 struct block_info *chain;
164 } block_t;
166 /* Describes a single function. Contains an array of basic blocks. */
168 typedef struct function_info
170 /* Name of function. */
171 char *name;
172 unsigned ident;
173 unsigned checksum;
175 /* Array of basic blocks. */
176 block_t *blocks;
177 unsigned num_blocks;
178 unsigned blocks_executed;
180 /* Raw arc coverage counts. */
181 gcov_type *counts;
182 unsigned num_counts;
184 /* First line number. */
185 unsigned line;
186 struct source_info *src;
188 /* Next function in same source file. */
189 struct function_info *line_next;
191 /* Next function. */
192 struct function_info *next;
193 } function_t;
195 /* Describes coverage of a file or function. */
197 typedef struct coverage_info
199 int lines;
200 int lines_executed;
202 int branches;
203 int branches_executed;
204 int branches_taken;
206 int calls;
207 int calls_executed;
209 char *name;
210 } coverage_t;
212 /* Describes a single line of source. Contains a chain of basic blocks
213 with code on it. */
215 typedef struct line_info
217 gcov_type count; /* execution count */
218 union
220 arc_t *branches; /* branches from blocks that end on this
221 line. Used for branch-counts when not
222 all-blocks mode. */
223 block_t *blocks; /* blocks which start on this line. Used
224 in all-blocks mode. */
225 } u;
226 unsigned exists : 1;
227 } line_t;
229 /* Describes a file mentioned in the block graph. Contains an array
230 of line info. */
232 typedef struct source_info
234 /* Name of source file. */
235 char *name;
236 unsigned index;
238 /* Array of line information. */
239 line_t *lines;
240 unsigned num_lines;
242 coverage_t coverage;
244 /* Functions in this source file. These are in ascending line
245 number order. */
246 function_t *functions;
248 /* Next source file. */
249 struct source_info *next;
250 } source_t;
252 /* Holds a list of function basic block graphs. */
254 static function_t *functions;
256 /* This points to the head of the sourcefile structure list. */
258 static source_t *sources;
260 /* This holds data summary information. */
262 static struct gcov_summary object_summary;
263 static unsigned program_count;
265 /* Modification time of graph file. */
267 static time_t bbg_file_time;
269 /* Name and file pointer of the input file for the basic block graph. */
271 static char *bbg_file_name;
273 /* Stamp of the bbg file */
274 static unsigned bbg_stamp;
276 /* Name and file pointer of the input file for the arc count data. */
278 static char *da_file_name;
280 /* Output branch probabilities. */
282 static int flag_branches = 0;
284 /* Show unconditional branches too. */
285 static int flag_unconditional = 0;
287 /* Output a gcov file if this is true. This is on by default, and can
288 be turned off by the -n option. */
290 static int flag_gcov_file = 1;
292 /* For included files, make the gcov output file name include the name
293 of the input source file. For example, if x.h is included in a.c,
294 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
296 static int flag_long_names = 0;
298 /* Output count information for every basic block, not merely those
299 that contain line number information. */
301 static int flag_all_blocks = 0;
303 /* Output summary info for each function. */
305 static int flag_function_summary = 0;
307 /* Object directory file prefix. This is the directory/file where the
308 graph and data files are looked for, if nonzero. */
310 static char *object_directory = 0;
312 /* Preserve all pathname components. Needed when object files and
313 source files are in subdirectories. '/' is mangled as '#', '.' is
314 elided and '..' mangled to '^'. */
316 static int flag_preserve_paths = 0;
318 /* Output the number of times a branch was taken as opposed to the percentage
319 of times it was taken. */
321 static int flag_counts = 0;
323 /* Forward declarations. */
324 static void fnotice (FILE *, const char *, ...) ATTRIBUTE_PRINTF_2;
325 static int process_args (int, char **);
326 static void print_usage (int) ATTRIBUTE_NORETURN;
327 static void print_version (void) ATTRIBUTE_NORETURN;
328 static void process_file (const char *);
329 static void create_file_names (const char *);
330 static source_t *find_source (const char *);
331 static int read_graph_file (void);
332 static int read_count_file (void);
333 static void solve_flow_graph (function_t *);
334 static void add_branch_counts (coverage_t *, const arc_t *);
335 static void add_line_counts (coverage_t *, function_t *);
336 static void function_summary (const coverage_t *, const char *);
337 static const char *format_gcov (gcov_type, gcov_type, int);
338 static void accumulate_line_counts (source_t *);
339 static int output_branch_count (FILE *, int, const arc_t *);
340 static void output_lines (FILE *, const source_t *);
341 static char *make_gcov_file_name (const char *, const char *);
342 static void release_structures (void);
343 extern int main (int, char **);
346 main (int argc, char **argv)
348 int argno;
350 /* Unlock the stdio streams. */
351 unlock_stream (stdin);
352 unlock_stream (stdout);
353 unlock_stream (stderr);
355 gcc_init_libintl ();
357 argno = process_args (argc, argv);
358 if (optind == argc)
359 print_usage (true);
361 for (; argno != argc; argno++)
363 release_structures ();
365 process_file (argv[argno]);
368 return 0;
371 static void
372 fnotice (FILE *file, const char *msgid, ...)
374 va_list ap;
376 va_start (ap, msgid);
377 vfprintf (file, _(msgid), ap);
378 va_end (ap);
381 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
382 otherwise the output of --help. */
384 static void
385 print_usage (int error_p)
387 FILE *file = error_p ? stderr : stdout;
388 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
390 fnotice (file, "Usage: gcov [OPTION]... SOURCEFILE\n\n");
391 fnotice (file, "Print code coverage information.\n\n");
392 fnotice (file, " -h, --help Print this help, then exit\n");
393 fnotice (file, " -v, --version Print version number, then exit\n");
394 fnotice (file, " -a, --all-blocks Show information for every basic block\n");
395 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
396 fnotice (file, " -c, --branch-counts Given counts of branches taken\n\
397 rather than percentages\n");
398 fnotice (file, " -n, --no-output Do not create an output file\n");
399 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
400 source files\n");
401 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
402 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
403 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
404 fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
405 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
406 bug_report_url);
407 exit (status);
410 /* Print version information and exit. */
412 static void
413 print_version (void)
415 fnotice (stdout, "gcov (GCC) %s\n", version_string);
416 fprintf (stdout, "Copyright %s 2004 Free Software Foundation, Inc.\n",
417 _("(C)"));
418 fnotice (stdout,
419 _("This is free software; see the source for copying conditions.\n"
420 "There is NO warranty; not even for MERCHANTABILITY or \n"
421 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
422 exit (SUCCESS_EXIT_CODE);
425 static const struct option options[] =
427 { "help", no_argument, NULL, 'h' },
428 { "version", no_argument, NULL, 'v' },
429 { "all-blocks", no_argument, NULL, 'a' },
430 { "branch-probabilities", no_argument, NULL, 'b' },
431 { "branch-counts", no_argument, NULL, 'c' },
432 { "no-output", no_argument, NULL, 'n' },
433 { "long-file-names", no_argument, NULL, 'l' },
434 { "function-summaries", no_argument, NULL, 'f' },
435 { "preserve-paths", no_argument, NULL, 'p' },
436 { "object-directory", required_argument, NULL, 'o' },
437 { "object-file", required_argument, NULL, 'o' },
438 { "unconditional-branches", no_argument, NULL, 'u' },
439 { 0, 0, 0, 0 }
442 /* Process args, return index to first non-arg. */
444 static int
445 process_args (int argc, char **argv)
447 int opt;
449 while ((opt = getopt_long (argc, argv, "abcfhlno:puv", options, NULL)) != -1)
451 switch (opt)
453 case 'a':
454 flag_all_blocks = 1;
455 break;
456 case 'b':
457 flag_branches = 1;
458 break;
459 case 'c':
460 flag_counts = 1;
461 break;
462 case 'f':
463 flag_function_summary = 1;
464 break;
465 case 'h':
466 print_usage (false);
467 /* print_usage will exit. */
468 case 'l':
469 flag_long_names = 1;
470 break;
471 case 'n':
472 flag_gcov_file = 0;
473 break;
474 case 'o':
475 object_directory = optarg;
476 break;
477 case 'p':
478 flag_preserve_paths = 1;
479 break;
480 case 'u':
481 flag_unconditional = 1;
482 break;
483 case 'v':
484 print_version ();
485 /* print_version will exit. */
486 default:
487 print_usage (true);
488 /* print_usage will exit. */
492 return optind;
495 /* Process a single source file. */
497 static void
498 process_file (const char *file_name)
500 source_t *src;
501 function_t *fn;
503 create_file_names (file_name);
504 if (read_graph_file ())
505 return;
507 if (!functions)
509 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
510 return;
513 if (read_count_file ())
514 return;
516 for (fn = functions; fn; fn = fn->next)
517 solve_flow_graph (fn);
518 for (src = sources; src; src = src->next)
519 src->lines = xcalloc (src->num_lines, sizeof (line_t));
520 for (fn = functions; fn; fn = fn->next)
522 coverage_t coverage;
524 memset (&coverage, 0, sizeof (coverage));
525 coverage.name = fn->name;
526 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
527 if (flag_function_summary)
529 function_summary (&coverage, "Function");
530 fnotice (stdout, "\n");
534 for (src = sources; src; src = src->next)
536 accumulate_line_counts (src);
537 function_summary (&src->coverage, "File");
538 if (flag_gcov_file)
540 char *gcov_file_name = make_gcov_file_name (file_name, src->name);
541 FILE *gcov_file = fopen (gcov_file_name, "w");
543 if (gcov_file)
545 fnotice (stdout, "%s:creating '%s'\n",
546 src->name, gcov_file_name);
547 output_lines (gcov_file, src);
548 if (ferror (gcov_file))
549 fnotice (stderr, "%s:error writing output file '%s'\n",
550 src->name, gcov_file_name);
551 fclose (gcov_file);
553 else
554 fnotice (stderr, "%s:could not open output file '%s'\n",
555 src->name, gcov_file_name);
556 free (gcov_file_name);
558 fnotice (stdout, "\n");
562 /* Release all memory used. */
564 static void
565 release_structures (void)
567 function_t *fn;
568 source_t *src;
570 free (bbg_file_name);
571 free (da_file_name);
572 da_file_name = bbg_file_name = NULL;
573 bbg_file_time = 0;
574 bbg_stamp = 0;
576 while ((src = sources))
578 sources = src->next;
580 free (src->name);
581 free (src->lines);
584 while ((fn = functions))
586 unsigned ix;
587 block_t *block;
589 functions = fn->next;
590 for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
592 arc_t *arc, *arc_n;
594 for (arc = block->succ; arc; arc = arc_n)
596 arc_n = arc->succ_next;
597 free (arc);
600 free (fn->blocks);
601 free (fn->counts);
605 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
606 is not specified, these are looked for in the current directory,
607 and named from the basename of the FILE_NAME sans extension. If
608 OBJECT_DIRECTORY is specified and is a directory, the files are in
609 that directory, but named from the basename of the FILE_NAME, sans
610 extension. Otherwise OBJECT_DIRECTORY is taken to be the name of
611 the object *file*, and the data files are named from that. */
613 static void
614 create_file_names (const char *file_name)
616 char *cptr;
617 char *name;
618 int length = strlen (file_name);
619 int base;
621 if (object_directory && object_directory[0])
623 struct stat status;
625 length += strlen (object_directory) + 2;
626 name = xmalloc (length);
627 name[0] = 0;
629 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
630 strcat (name, object_directory);
631 if (base && name[strlen (name) - 1] != '/')
632 strcat (name, "/");
634 else
636 name = xmalloc (length + 1);
637 name[0] = 0;
638 base = 1;
641 if (base)
643 /* Append source file name. */
644 cptr = strrchr (file_name, '/');
645 strcat (name, cptr ? cptr + 1 : file_name);
648 /* Remove the extension. */
649 cptr = strrchr (name, '.');
650 if (cptr)
651 *cptr = 0;
653 length = strlen (name);
655 bbg_file_name = xmalloc (length + strlen (GCOV_NOTE_SUFFIX) + 1);
656 strcpy (bbg_file_name, name);
657 strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
659 da_file_name = xmalloc (length + strlen (GCOV_DATA_SUFFIX) + 1);
660 strcpy (da_file_name, name);
661 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
663 return;
666 /* Find or create a source file structure for FILE_NAME. Copies
667 FILE_NAME on creation */
669 static source_t *
670 find_source (const char *file_name)
672 source_t *src;
674 if (!file_name)
675 file_name = "<unknown>";
677 for (src = sources; src; src = src->next)
678 if (!strcmp (file_name, src->name))
679 return src;
681 src = xcalloc (1, sizeof (source_t));
682 src->name = xstrdup (file_name);
683 src->coverage.name = src->name;
684 src->index = sources ? sources->index + 1 : 1;
685 src->next = sources;
686 sources = src;
688 return src;
691 /* Read the graph file. Return nonzero on fatal error. */
693 static int
694 read_graph_file (void)
696 unsigned version;
697 unsigned current_tag = 0;
698 struct function_info *fn = NULL;
699 source_t *src = NULL;
700 unsigned ix;
701 unsigned tag;
703 if (!gcov_open (bbg_file_name, 1))
705 fnotice (stderr, "%s:cannot open graph file\n", bbg_file_name);
706 return 1;
708 bbg_file_time = gcov_time ();
709 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
711 fnotice (stderr, "%s:not a gcov graph file\n", bbg_file_name);
712 gcov_close ();
713 return 1;
716 version = gcov_read_unsigned ();
717 if (version != GCOV_VERSION)
719 char v[4], e[4];
721 GCOV_UNSIGNED2STRING (v, version);
722 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
724 fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n",
725 bbg_file_name, v, e);
727 bbg_stamp = gcov_read_unsigned ();
729 while ((tag = gcov_read_unsigned ()))
731 unsigned length = gcov_read_unsigned ();
732 gcov_position_t base = gcov_position ();
734 if (tag == GCOV_TAG_FUNCTION)
736 char *function_name;
737 unsigned ident, checksum, lineno;
738 source_t *src;
739 function_t *probe, *prev;
741 ident = gcov_read_unsigned ();
742 checksum = gcov_read_unsigned ();
743 function_name = xstrdup (gcov_read_string ());
744 src = find_source (gcov_read_string ());
745 lineno = gcov_read_unsigned ();
747 fn = xcalloc (1, sizeof (function_t));
748 fn->name = function_name;
749 fn->ident = ident;
750 fn->checksum = checksum;
751 fn->src = src;
752 fn->line = lineno;
754 fn->next = functions;
755 functions = fn;
756 current_tag = tag;
758 if (lineno >= src->num_lines)
759 src->num_lines = lineno + 1;
760 /* Now insert it into the source file's list of
761 functions. Normally functions will be encountered in
762 ascending order, so a simple scan is quick. */
763 for (probe = src->functions, prev = NULL;
764 probe && probe->line > lineno;
765 prev = probe, probe = probe->line_next)
766 continue;
767 fn->line_next = probe;
768 if (prev)
769 prev->line_next = fn;
770 else
771 src->functions = fn;
773 else if (fn && tag == GCOV_TAG_BLOCKS)
775 if (fn->blocks)
776 fnotice (stderr, "%s:already seen blocks for '%s'\n",
777 bbg_file_name, fn->name);
778 else
780 unsigned ix, num_blocks = GCOV_TAG_BLOCKS_NUM (length);
781 fn->num_blocks = num_blocks;
783 fn->blocks = xcalloc (fn->num_blocks, sizeof (block_t));
784 for (ix = 0; ix != num_blocks; ix++)
785 fn->blocks[ix].flags = gcov_read_unsigned ();
788 else if (fn && tag == GCOV_TAG_ARCS)
790 unsigned src = gcov_read_unsigned ();
791 unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
793 if (src >= fn->num_blocks || fn->blocks[src].succ)
794 goto corrupt;
796 while (num_dests--)
798 struct arc_info *arc;
799 unsigned dest = gcov_read_unsigned ();
800 unsigned flags = gcov_read_unsigned ();
802 if (dest >= fn->num_blocks)
803 goto corrupt;
804 arc = xcalloc (1, sizeof (arc_t));
806 arc->dst = &fn->blocks[dest];
807 arc->src = &fn->blocks[src];
809 arc->count = 0;
810 arc->count_valid = 0;
811 arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
812 arc->fake = !!(flags & GCOV_ARC_FAKE);
813 arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
815 arc->succ_next = fn->blocks[src].succ;
816 fn->blocks[src].succ = arc;
817 fn->blocks[src].num_succ++;
819 arc->pred_next = fn->blocks[dest].pred;
820 fn->blocks[dest].pred = arc;
821 fn->blocks[dest].num_pred++;
823 if (arc->fake)
825 if (src)
827 /* Exceptional exit from this function, the
828 source block must be a call. */
829 fn->blocks[src].is_call_site = 1;
830 arc->is_call_non_return = 1;
832 else
834 /* Non-local return from a callee of this
835 function. The destination block is a catch or
836 setjmp. */
837 arc->is_nonlocal_return = 1;
838 fn->blocks[dest].is_nonlocal_return = 1;
842 if (!arc->on_tree)
843 fn->num_counts++;
846 else if (fn && tag == GCOV_TAG_LINES)
848 unsigned blockno = gcov_read_unsigned ();
849 unsigned *line_nos = xcalloc (length - 1, sizeof (unsigned));
851 if (blockno >= fn->num_blocks || fn->blocks[blockno].u.line.encoding)
852 goto corrupt;
854 for (ix = 0; ; )
856 unsigned lineno = gcov_read_unsigned ();
858 if (lineno)
860 if (!ix)
862 line_nos[ix++] = 0;
863 line_nos[ix++] = src->index;
865 line_nos[ix++] = lineno;
866 if (lineno >= src->num_lines)
867 src->num_lines = lineno + 1;
869 else
871 const char *file_name = gcov_read_string ();
873 if (!file_name)
874 break;
875 src = find_source (file_name);
877 line_nos[ix++] = 0;
878 line_nos[ix++] = src->index;
882 fn->blocks[blockno].u.line.encoding = line_nos;
883 fn->blocks[blockno].u.line.num = ix;
885 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
887 fn = NULL;
888 current_tag = 0;
890 gcov_sync (base, length);
891 if (gcov_is_error ())
893 corrupt:;
894 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
895 gcov_close ();
896 return 1;
899 gcov_close ();
901 /* We built everything backwards, so nreverse them all. */
903 /* Reverse sources. Not strictly necessary, but we'll then process
904 them in the 'expected' order. */
906 source_t *src, *src_p, *src_n;
908 for (src_p = NULL, src = sources; src; src_p = src, src = src_n)
910 src_n = src->next;
911 src->next = src_p;
913 sources = src_p;
916 /* Reverse functions. */
918 function_t *fn, *fn_p, *fn_n;
920 for (fn_p = NULL, fn = functions; fn; fn_p = fn, fn = fn_n)
922 unsigned ix;
924 fn_n = fn->next;
925 fn->next = fn_p;
927 /* Reverse the arcs. */
928 for (ix = fn->num_blocks; ix--;)
930 arc_t *arc, *arc_p, *arc_n;
932 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
933 arc_p = arc, arc = arc_n)
935 arc_n = arc->succ_next;
936 arc->succ_next = arc_p;
938 fn->blocks[ix].succ = arc_p;
940 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
941 arc_p = arc, arc = arc_n)
943 arc_n = arc->pred_next;
944 arc->pred_next = arc_p;
946 fn->blocks[ix].pred = arc_p;
949 functions = fn_p;
951 return 0;
954 /* Reads profiles from the count file and attach to each
955 function. Return nonzero if fatal error. */
957 static int
958 read_count_file (void)
960 unsigned ix;
961 unsigned version;
962 unsigned tag;
963 function_t *fn = NULL;
964 int error = 0;
966 if (!gcov_open (da_file_name, 1))
968 fnotice (stderr, "%s:cannot open data file\n", da_file_name);
969 return 1;
971 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
973 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
974 cleanup:;
975 gcov_close ();
976 return 1;
978 version = gcov_read_unsigned ();
979 if (version != GCOV_VERSION)
981 char v[4], e[4];
983 GCOV_UNSIGNED2STRING (v, version);
984 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
986 fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
987 da_file_name, v, e);
989 tag = gcov_read_unsigned ();
990 if (tag != bbg_stamp)
992 fnotice (stderr, "%s:stamp mismatch with graph file\n", da_file_name);
993 goto cleanup;
996 while ((tag = gcov_read_unsigned ()))
998 unsigned length = gcov_read_unsigned ();
999 unsigned long base = gcov_position ();
1001 if (tag == GCOV_TAG_OBJECT_SUMMARY)
1002 gcov_read_summary (&object_summary);
1003 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
1004 program_count++;
1005 else if (tag == GCOV_TAG_FUNCTION)
1007 unsigned ident = gcov_read_unsigned ();
1008 struct function_info *fn_n = functions;
1010 for (fn = fn ? fn->next : NULL; ; fn = fn->next)
1012 if (fn)
1014 else if ((fn = fn_n))
1015 fn_n = NULL;
1016 else
1018 fnotice (stderr, "%s:unknown function '%u'\n",
1019 da_file_name, ident);
1020 break;
1022 if (fn->ident == ident)
1023 break;
1026 if (!fn)
1028 else if (gcov_read_unsigned () != fn->checksum)
1030 mismatch:;
1031 fnotice (stderr, "%s:profile mismatch for '%s'\n",
1032 da_file_name, fn->name);
1033 goto cleanup;
1036 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
1038 if (length != GCOV_TAG_COUNTER_LENGTH (fn->num_counts))
1039 goto mismatch;
1041 if (!fn->counts)
1042 fn->counts = xcalloc (fn->num_counts, sizeof (gcov_type));
1044 for (ix = 0; ix != fn->num_counts; ix++)
1045 fn->counts[ix] += gcov_read_counter ();
1047 gcov_sync (base, length);
1048 if ((error = gcov_is_error ()))
1050 fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1051 da_file_name);
1052 goto cleanup;
1056 gcov_close ();
1057 return 0;
1060 /* Solve the flow graph. Propagate counts from the instrumented arcs
1061 to the blocks and the uninstrumented arcs. */
1063 static void
1064 solve_flow_graph (function_t *fn)
1066 unsigned ix;
1067 arc_t *arc;
1068 gcov_type *count_ptr = fn->counts;
1069 block_t *blk;
1070 block_t *valid_blocks = NULL; /* valid, but unpropagated blocks. */
1071 block_t *invalid_blocks = NULL; /* invalid, but inferable blocks. */
1073 if (fn->num_blocks < 2)
1074 fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n",
1075 bbg_file_name, fn->name);
1076 else
1078 if (fn->blocks[0].num_pred)
1079 fnotice (stderr, "%s:'%s' has arcs to entry block\n",
1080 bbg_file_name, fn->name);
1081 else
1082 /* We can't deduce the entry block counts from the lack of
1083 predecessors. */
1084 fn->blocks[0].num_pred = ~(unsigned)0;
1086 if (fn->blocks[fn->num_blocks - 1].num_succ)
1087 fnotice (stderr, "%s:'%s' has arcs from exit block\n",
1088 bbg_file_name, fn->name);
1089 else
1090 /* Likewise, we can't deduce exit block counts from the lack
1091 of its successors. */
1092 fn->blocks[fn->num_blocks - 1].num_succ = ~(unsigned)0;
1095 /* Propagate the measured counts, this must be done in the same
1096 order as the code in profile.c */
1097 for (ix = 0, blk = fn->blocks; ix != fn->num_blocks; ix++, blk++)
1099 block_t const *prev_dst = NULL;
1100 int out_of_order = 0;
1101 int non_fake_succ = 0;
1103 for (arc = blk->succ; arc; arc = arc->succ_next)
1105 if (!arc->fake)
1106 non_fake_succ++;
1108 if (!arc->on_tree)
1110 if (count_ptr)
1111 arc->count = *count_ptr++;
1112 arc->count_valid = 1;
1113 blk->num_succ--;
1114 arc->dst->num_pred--;
1116 if (prev_dst && prev_dst > arc->dst)
1117 out_of_order = 1;
1118 prev_dst = arc->dst;
1120 if (non_fake_succ == 1)
1122 /* If there is only one non-fake exit, it is an
1123 unconditional branch. */
1124 for (arc = blk->succ; arc; arc = arc->succ_next)
1125 if (!arc->fake)
1127 arc->is_unconditional = 1;
1128 /* If this block is instrumenting a call, it might be
1129 an artificial block. It is not artificial if it has
1130 a non-fallthrough exit, or the destination of this
1131 arc has more than one entry. Mark the destination
1132 block as a return site, if none of those conditions
1133 hold. */
1134 if (blk->is_call_site && arc->fall_through
1135 && arc->dst->pred == arc && !arc->pred_next)
1136 arc->dst->is_call_return = 1;
1140 /* Sort the successor arcs into ascending dst order. profile.c
1141 normally produces arcs in the right order, but sometimes with
1142 one or two out of order. We're not using a particularly
1143 smart sort. */
1144 if (out_of_order)
1146 arc_t *start = blk->succ;
1147 unsigned changes = 1;
1149 while (changes)
1151 arc_t *arc, *arc_p, *arc_n;
1153 changes = 0;
1154 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1156 if (arc->dst > arc_n->dst)
1158 changes = 1;
1159 if (arc_p)
1160 arc_p->succ_next = arc_n;
1161 else
1162 start = arc_n;
1163 arc->succ_next = arc_n->succ_next;
1164 arc_n->succ_next = arc;
1165 arc_p = arc_n;
1167 else
1169 arc_p = arc;
1170 arc = arc_n;
1174 blk->succ = start;
1177 /* Place it on the invalid chain, it will be ignored if that's
1178 wrong. */
1179 blk->invalid_chain = 1;
1180 blk->chain = invalid_blocks;
1181 invalid_blocks = blk;
1184 while (invalid_blocks || valid_blocks)
1186 while ((blk = invalid_blocks))
1188 gcov_type total = 0;
1189 const arc_t *arc;
1191 invalid_blocks = blk->chain;
1192 blk->invalid_chain = 0;
1193 if (!blk->num_succ)
1194 for (arc = blk->succ; arc; arc = arc->succ_next)
1195 total += arc->count;
1196 else if (!blk->num_pred)
1197 for (arc = blk->pred; arc; arc = arc->pred_next)
1198 total += arc->count;
1199 else
1200 continue;
1202 blk->count = total;
1203 blk->count_valid = 1;
1204 blk->chain = valid_blocks;
1205 blk->valid_chain = 1;
1206 valid_blocks = blk;
1208 while ((blk = valid_blocks))
1210 gcov_type total;
1211 arc_t *arc, *inv_arc;
1213 valid_blocks = blk->chain;
1214 blk->valid_chain = 0;
1215 if (blk->num_succ == 1)
1217 block_t *dst;
1219 total = blk->count;
1220 inv_arc = NULL;
1221 for (arc = blk->succ; arc; arc = arc->succ_next)
1223 total -= arc->count;
1224 if (!arc->count_valid)
1225 inv_arc = arc;
1227 dst = inv_arc->dst;
1228 inv_arc->count_valid = 1;
1229 inv_arc->count = total;
1230 blk->num_succ--;
1231 dst->num_pred--;
1232 if (dst->count_valid)
1234 if (dst->num_pred == 1 && !dst->valid_chain)
1236 dst->chain = valid_blocks;
1237 dst->valid_chain = 1;
1238 valid_blocks = dst;
1241 else
1243 if (!dst->num_pred && !dst->invalid_chain)
1245 dst->chain = invalid_blocks;
1246 dst->invalid_chain = 1;
1247 invalid_blocks = dst;
1251 if (blk->num_pred == 1)
1253 block_t *src;
1255 total = blk->count;
1256 inv_arc = NULL;
1257 for (arc = blk->pred; arc; arc = arc->pred_next)
1259 total -= arc->count;
1260 if (!arc->count_valid)
1261 inv_arc = arc;
1263 src = inv_arc->src;
1264 inv_arc->count_valid = 1;
1265 inv_arc->count = total;
1266 blk->num_pred--;
1267 src->num_succ--;
1268 if (src->count_valid)
1270 if (src->num_succ == 1 && !src->valid_chain)
1272 src->chain = valid_blocks;
1273 src->valid_chain = 1;
1274 valid_blocks = src;
1277 else
1279 if (!src->num_succ && !src->invalid_chain)
1281 src->chain = invalid_blocks;
1282 src->invalid_chain = 1;
1283 invalid_blocks = src;
1290 /* If the graph has been correctly solved, every block will have a
1291 valid count. */
1292 for (ix = 0; ix < fn->num_blocks; ix++)
1293 if (!fn->blocks[ix].count_valid)
1295 fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
1296 bbg_file_name, fn->name);
1297 break;
1303 /* Increment totals in COVERAGE according to arc ARC. */
1305 static void
1306 add_branch_counts (coverage_t *coverage, const arc_t *arc)
1308 if (arc->is_call_non_return)
1310 coverage->calls++;
1311 if (arc->src->count)
1312 coverage->calls_executed++;
1314 else if (!arc->is_unconditional)
1316 coverage->branches++;
1317 if (arc->src->count)
1318 coverage->branches_executed++;
1319 if (arc->count)
1320 coverage->branches_taken++;
1324 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1325 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1326 If DP is zero, no decimal point is printed. Only print 100% when
1327 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1328 format TOP. Return pointer to a static string. */
1330 static char const *
1331 format_gcov (gcov_type top, gcov_type bottom, int dp)
1333 static char buffer[20];
1335 if (dp >= 0)
1337 float ratio = bottom ? (float)top / bottom : 0;
1338 int ix;
1339 unsigned limit = 100;
1340 unsigned percent;
1342 for (ix = dp; ix--; )
1343 limit *= 10;
1345 percent = (unsigned) (ratio * limit + (float)0.5);
1346 if (percent <= 0 && top)
1347 percent = 1;
1348 else if (percent >= limit && top != bottom)
1349 percent = limit - 1;
1350 ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1351 if (dp)
1353 dp++;
1356 buffer[ix+1] = buffer[ix];
1357 ix--;
1359 while (dp--);
1360 buffer[ix + 1] = '.';
1363 else
1364 sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)top);
1366 return buffer;
1370 /* Output summary info for a function. */
1372 static void
1373 function_summary (const coverage_t *coverage, const char *title)
1375 fnotice (stdout, "%s '%s'\n", title, coverage->name);
1377 if (coverage->lines)
1378 fnotice (stdout, "Lines executed:%s of %d\n",
1379 format_gcov (coverage->lines_executed, coverage->lines, 2),
1380 coverage->lines);
1381 else
1382 fnotice (stdout, "No executable lines\n");
1384 if (flag_branches)
1386 if (coverage->branches)
1388 fnotice (stdout, "Branches executed:%s of %d\n",
1389 format_gcov (coverage->branches_executed,
1390 coverage->branches, 2),
1391 coverage->branches);
1392 fnotice (stdout, "Taken at least once:%s of %d\n",
1393 format_gcov (coverage->branches_taken,
1394 coverage->branches, 2),
1395 coverage->branches);
1397 else
1398 fnotice (stdout, "No branches\n");
1399 if (coverage->calls)
1400 fnotice (stdout, "Calls executed:%s of %d\n",
1401 format_gcov (coverage->calls_executed, coverage->calls, 2),
1402 coverage->calls);
1403 else
1404 fnotice (stdout, "No calls\n");
1408 /* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
1409 affect name generation. With preserve_paths we create a filename
1410 from all path components of the source file, replacing '/' with
1411 '#', without it we simply take the basename component. With
1412 long_output_names we prepend the processed name of the input file
1413 to each output name (except when the current source file is the
1414 input file, so you don't get a double concatenation). The two
1415 components are separated by '##'. Also '.' filename components are
1416 removed and '..' components are renamed to '^'. */
1418 static char *
1419 make_gcov_file_name (const char *input_name, const char *src_name)
1421 char *cptr;
1422 char *name = xmalloc (strlen (src_name) + strlen (input_name) + 10);
1424 name[0] = 0;
1425 if (flag_long_names && strcmp (src_name, input_name))
1427 /* Generate the input filename part. */
1428 cptr = flag_preserve_paths ? NULL : strrchr (input_name, '/');
1429 strcat (name, cptr ? cptr + 1 : input_name);
1430 strcat (name, "##");
1433 /* Generate the source filename part. */
1434 cptr = flag_preserve_paths ? NULL : strrchr (src_name, '/');
1435 strcat (name, cptr ? cptr + 1 : src_name);
1437 if (flag_preserve_paths)
1439 /* Convert '/' to '#', remove '/./', convert '/../' to '/^/' */
1440 char *prev;
1442 for (cptr = name; (cptr = strchr ((prev = cptr), '/'));)
1444 unsigned shift = 0;
1446 if (prev + 1 == cptr && prev[0] == '.')
1448 /* Remove '.' */
1449 shift = 2;
1451 else if (prev + 2 == cptr && prev[0] == '.' && prev[1] == '.')
1453 /* Convert '..' */
1454 shift = 1;
1455 prev[1] = '^';
1457 else
1458 *cptr++ = '#';
1459 if (shift)
1461 cptr = prev;
1463 prev[0] = prev[shift];
1464 while (*prev++);
1469 strcat (name, ".gcov");
1470 return name;
1473 /* Scan through the bb_data for each line in the block, increment
1474 the line number execution count indicated by the execution count of
1475 the appropriate basic block. */
1477 static void
1478 add_line_counts (coverage_t *coverage, function_t *fn)
1480 unsigned ix;
1481 line_t *line = NULL; /* This is propagated from one iteration to the
1482 next. */
1484 /* Scan each basic block. */
1485 for (ix = 0; ix != fn->num_blocks; ix++)
1487 block_t *block = &fn->blocks[ix];
1488 unsigned *encoding;
1489 const source_t *src = NULL;
1490 unsigned jx;
1492 if (block->count && ix && ix + 1 != fn->num_blocks)
1493 fn->blocks_executed++;
1494 for (jx = 0, encoding = block->u.line.encoding;
1495 jx != block->u.line.num; jx++, encoding++)
1496 if (!*encoding)
1498 unsigned src_n = *++encoding;
1500 for (src = sources; src->index != src_n; src = src->next)
1501 continue;
1502 jx++;
1504 else
1506 line = &src->lines[*encoding];
1508 if (coverage)
1510 if (!line->exists)
1511 coverage->lines++;
1512 if (!line->count && block->count)
1513 coverage->lines_executed++;
1515 line->exists = 1;
1516 line->count += block->count;
1518 free (block->u.line.encoding);
1519 block->u.cycle.arc = NULL;
1520 block->u.cycle.ident = ~0U;
1522 if (!ix || ix + 1 == fn->num_blocks)
1523 /* Entry or exit block */;
1524 else if (flag_all_blocks)
1526 line_t *block_line = line ? line : &fn->src->lines[fn->line];
1528 block->chain = block_line->u.blocks;
1529 block_line->u.blocks = block;
1531 else if (flag_branches)
1533 arc_t *arc;
1535 for (arc = block->succ; arc; arc = arc->succ_next)
1537 arc->line_next = line->u.branches;
1538 line->u.branches = arc;
1539 if (coverage && !arc->is_unconditional)
1540 add_branch_counts (coverage, arc);
1544 if (!line)
1545 fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, fn->name);
1548 /* Accumulate the line counts of a file. */
1550 static void
1551 accumulate_line_counts (source_t *src)
1553 line_t *line;
1554 function_t *fn, *fn_p, *fn_n;
1555 unsigned ix;
1557 /* Reverse the function order. */
1558 for (fn = src->functions, fn_p = NULL; fn;
1559 fn_p = fn, fn = fn_n)
1561 fn_n = fn->line_next;
1562 fn->line_next = fn_p;
1564 src->functions = fn_p;
1566 for (ix = src->num_lines, line = src->lines; ix--; line++)
1568 if (!flag_all_blocks)
1570 arc_t *arc, *arc_p, *arc_n;
1572 /* Total and reverse the branch information. */
1573 for (arc = line->u.branches, arc_p = NULL; arc;
1574 arc_p = arc, arc = arc_n)
1576 arc_n = arc->line_next;
1577 arc->line_next = arc_p;
1579 add_branch_counts (&src->coverage, arc);
1581 line->u.branches = arc_p;
1583 else if (line->u.blocks)
1585 /* The user expects the line count to be the number of times
1586 a line has been executed. Simply summing the block count
1587 will give an artificially high number. The Right Thing
1588 is to sum the entry counts to the graph of blocks on this
1589 line, then find the elementary cycles of the local graph
1590 and add the transition counts of those cycles. */
1591 block_t *block, *block_p, *block_n;
1592 gcov_type count = 0;
1594 /* Reverse the block information. */
1595 for (block = line->u.blocks, block_p = NULL; block;
1596 block_p = block, block = block_n)
1598 block_n = block->chain;
1599 block->chain = block_p;
1600 block->u.cycle.ident = ix;
1602 line->u.blocks = block_p;
1604 /* Sum the entry arcs. */
1605 for (block = line->u.blocks; block; block = block->chain)
1607 arc_t *arc;
1609 for (arc = block->pred; arc; arc = arc->pred_next)
1611 if (arc->src->u.cycle.ident != ix)
1612 count += arc->count;
1613 if (flag_branches)
1614 add_branch_counts (&src->coverage, arc);
1617 /* Initialize the cs_count. */
1618 for (arc = block->succ; arc; arc = arc->succ_next)
1619 arc->cs_count = arc->count;
1622 /* Find the loops. This uses the algorithm described in
1623 Tiernan 'An Efficient Search Algorithm to Find the
1624 Elementary Circuits of a Graph', CACM Dec 1970. We hold
1625 the P array by having each block point to the arc that
1626 connects to the previous block. The H array is implicitly
1627 held because of the arc ordering, and the block's
1628 previous arc pointer.
1630 Although the algorithm is O(N^3) for highly connected
1631 graphs, at worst we'll have O(N^2), as most blocks have
1632 only one or two exits. Most graphs will be small.
1634 For each loop we find, locate the arc with the smallest
1635 transition count, and add that to the cumulative
1636 count. Decrease flow over the cycle and remove the arc
1637 from consideration. */
1638 for (block = line->u.blocks; block; block = block->chain)
1640 block_t *head = block;
1641 arc_t *arc;
1643 next_vertex:;
1644 arc = head->succ;
1645 current_vertex:;
1646 while (arc)
1648 block_t *dst = arc->dst;
1649 if (/* Already used that arc. */
1650 arc->cycle
1651 /* Not to same graph, or before first vertex. */
1652 || dst->u.cycle.ident != ix
1653 /* Already in path. */
1654 || dst->u.cycle.arc)
1656 arc = arc->succ_next;
1657 continue;
1660 if (dst == block)
1662 /* Found a closing arc. */
1663 gcov_type cycle_count = arc->cs_count;
1664 arc_t *cycle_arc = arc;
1665 arc_t *probe_arc;
1667 /* Locate the smallest arc count of the loop. */
1668 for (dst = head; (probe_arc = dst->u.cycle.arc);
1669 dst = probe_arc->src)
1670 if (cycle_count > probe_arc->cs_count)
1672 cycle_count = probe_arc->cs_count;
1673 cycle_arc = probe_arc;
1676 count += cycle_count;
1677 cycle_arc->cycle = 1;
1679 /* Remove the flow from the cycle. */
1680 arc->cs_count -= cycle_count;
1681 for (dst = head; (probe_arc = dst->u.cycle.arc);
1682 dst = probe_arc->src)
1683 probe_arc->cs_count -= cycle_count;
1685 /* Unwind to the cyclic arc. */
1686 while (head != cycle_arc->src)
1688 arc = head->u.cycle.arc;
1689 head->u.cycle.arc = NULL;
1690 head = arc->src;
1692 /* Move on. */
1693 arc = arc->succ_next;
1694 continue;
1697 /* Add new block to chain. */
1698 dst->u.cycle.arc = arc;
1699 head = dst;
1700 goto next_vertex;
1702 /* We could not add another vertex to the path. Remove
1703 the last vertex from the list. */
1704 arc = head->u.cycle.arc;
1705 if (arc)
1707 /* It was not the first vertex. Move onto next arc. */
1708 head->u.cycle.arc = NULL;
1709 head = arc->src;
1710 arc = arc->succ_next;
1711 goto current_vertex;
1713 /* Mark this block as unusable. */
1714 block->u.cycle.ident = ~0U;
1717 line->count = count;
1720 if (line->exists)
1722 src->coverage.lines++;
1723 if (line->count)
1724 src->coverage.lines_executed++;
1729 /* Output information about ARC number IX. Returns nonzero if
1730 anything is output. */
1732 static int
1733 output_branch_count (FILE *gcov_file, int ix, const arc_t *arc)
1736 if (arc->is_call_non_return)
1738 if (arc->src->count)
1740 fnotice (gcov_file, "call %2d returned %s\n", ix,
1741 format_gcov (arc->src->count - arc->count,
1742 arc->src->count, -flag_counts));
1744 else
1745 fnotice (gcov_file, "call %2d never executed\n", ix);
1747 else if (!arc->is_unconditional)
1749 if (arc->src->count)
1750 fnotice (gcov_file, "branch %2d taken %s%s\n", ix,
1751 format_gcov (arc->count, arc->src->count, -flag_counts),
1752 arc->fall_through ? " (fallthrough)" : "");
1753 else
1754 fnotice (gcov_file, "branch %2d never executed\n", ix);
1756 else if (flag_unconditional && !arc->dst->is_call_return)
1758 if (arc->src->count)
1759 fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
1760 format_gcov (arc->count, arc->src->count, -flag_counts));
1761 else
1762 fnotice (gcov_file, "unconditional %2d never executed\n", ix);
1764 else
1765 return 0;
1766 return 1;
1770 /* Read in the source file one line at a time, and output that line to
1771 the gcov file preceded by its execution count and other
1772 information. */
1774 static void
1775 output_lines (FILE *gcov_file, const source_t *src)
1777 FILE *source_file;
1778 unsigned line_num; /* current line number. */
1779 const line_t *line; /* current line info ptr. */
1780 char string[STRING_SIZE]; /* line buffer. */
1781 char const *retval = ""; /* status of source file reading. */
1782 function_t *fn = NULL;
1784 fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->name);
1785 fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
1786 fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0, da_file_name);
1787 fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0,
1788 object_summary.ctrs[GCOV_COUNTER_ARCS].runs);
1789 fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
1791 source_file = fopen (src->name, "r");
1792 if (!source_file)
1794 fnotice (stderr, "%s:cannot open source file\n", src->name);
1795 retval = NULL;
1797 else
1799 struct stat status;
1801 if (!fstat (fileno (source_file), &status)
1802 && status.st_mtime > bbg_file_time)
1804 fnotice (stderr, "%s:source file is newer than graph file '%s'\n",
1805 src->name, bbg_file_name);
1806 fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n",
1807 "-", 0);
1811 if (flag_branches)
1812 fn = src->functions;
1814 for (line_num = 1, line = &src->lines[line_num];
1815 line_num < src->num_lines; line_num++, line++)
1817 for (; fn && fn->line == line_num; fn = fn->line_next)
1819 arc_t *arc = fn->blocks[fn->num_blocks - 1].pred;
1820 gcov_type return_count = fn->blocks[fn->num_blocks - 1].count;
1822 for (; arc; arc = arc->pred_next)
1823 if (arc->fake)
1824 return_count -= arc->count;
1826 fprintf (gcov_file, "function %s", fn->name);
1827 fprintf (gcov_file, " called %s",
1828 format_gcov (fn->blocks[0].count, 0, -1));
1829 fprintf (gcov_file, " returned %s",
1830 format_gcov (return_count, fn->blocks[0].count, 0));
1831 fprintf (gcov_file, " blocks executed %s",
1832 format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0));
1833 fprintf (gcov_file, "\n");
1836 /* For lines which don't exist in the .bb file, print '-' before
1837 the source line. For lines which exist but were never
1838 executed, print '#####' before the source line. Otherwise,
1839 print the execution count before the source line. There are
1840 16 spaces of indentation added before the source line so that
1841 tabs won't be messed up. */
1842 fprintf (gcov_file, "%9s:%5u:",
1843 !line->exists ? "-" : !line->count ? "#####"
1844 : format_gcov (line->count, 0, -1), line_num);
1846 if (retval)
1848 /* Copy source line. */
1851 retval = fgets (string, STRING_SIZE, source_file);
1852 if (!retval)
1853 break;
1854 fputs (retval, gcov_file);
1856 while (!retval[0] || retval[strlen (retval) - 1] != '\n');
1858 if (!retval)
1859 fputs ("/*EOF*/\n", gcov_file);
1861 if (flag_all_blocks)
1863 block_t *block;
1864 arc_t *arc;
1865 int ix, jx;
1867 for (ix = jx = 0, block = line->u.blocks; block;
1868 block = block->chain)
1870 if (!block->is_call_return)
1871 fprintf (gcov_file, "%9s:%5u-block %2d\n",
1872 !line->exists ? "-" : !block->count ? "$$$$$"
1873 : format_gcov (block->count, 0, -1),
1874 line_num, ix++);
1875 if (flag_branches)
1876 for (arc = block->succ; arc; arc = arc->succ_next)
1877 jx += output_branch_count (gcov_file, jx, arc);
1880 else if (flag_branches)
1882 int ix;
1883 arc_t *arc;
1885 for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
1886 ix += output_branch_count (gcov_file, ix, arc);
1890 /* Handle all remaining source lines. There may be lines after the
1891 last line of code. */
1892 if (retval)
1894 for (; (retval = fgets (string, STRING_SIZE, source_file)); line_num++)
1896 fprintf (gcov_file, "%9s:%5u:%s", "-", line_num, retval);
1898 while (!retval[0] || retval[strlen (retval) - 1] != '\n')
1900 retval = fgets (string, STRING_SIZE, source_file);
1901 if (!retval)
1902 break;
1903 fputs (retval, gcov_file);
1908 if (source_file)
1909 fclose (source_file);