Mark as release
[official-gcc.git] / gcc / gcov.c
blob3815c33c5311757edd174dd20cd018ee9cc11534
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, 1999,
4 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 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 3, 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 COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* ??? Print a list of the ten blocks with the highest execution counts,
24 and list the line numbers corresponding to those blocks. Also, perhaps
25 list the line numbers with the highest execution counts, only printing
26 the first if there are several which are all listed in the same block. */
28 /* ??? Should have an option to print the number of basic blocks, and the
29 percent of them that are covered. */
31 /* ??? Does not correctly handle the case where two .bb files refer to
32 the same included source file. For example, if one has a short
33 file containing only inline functions, which is then included in
34 two other files, then there will be two .bb files which refer to
35 the include file, but there is no way to get the total execution
36 counts for the included file, can only get execution counts for one
37 or the other of the including files. this can be fixed by --ratios
38 --long-file-names --preserve-paths and perl. */
40 /* Need an option to show individual block counts, and show
41 probabilities of fall through arcs. */
43 #include "config.h"
44 #include "system.h"
45 #include "coretypes.h"
46 #include "tm.h"
47 #include "intl.h"
48 #include "version.h"
50 #include <getopt.h>
52 #define IN_GCOV 1
53 #include "gcov-io.h"
54 #include "gcov-io.c"
56 /* The bbg file is generated by -ftest-coverage option. The da file is
57 generated by a program compiled with -fprofile-arcs. Their formats
58 are documented in gcov-io.h. */
60 /* The functions in this file for creating and solution program flow graphs
61 are very similar to functions in the gcc source file profile.c. In
62 some places we make use of the knowledge of how profile.c works to
63 select particular algorithms here. */
65 /* This is the size of the buffer used to read in source file lines. */
67 #define STRING_SIZE 200
69 struct function_info;
70 struct block_info;
71 struct source_info;
73 /* Describes an arc between two basic blocks. */
75 typedef struct arc_info
77 /* source and destination blocks. */
78 struct block_info *src;
79 struct block_info *dst;
81 /* transition counts. */
82 gcov_type count;
83 /* used in cycle search, so that we do not clobber original counts. */
84 gcov_type cs_count;
86 unsigned int count_valid : 1;
87 unsigned int on_tree : 1;
88 unsigned int fake : 1;
89 unsigned int fall_through : 1;
91 /* Arc is for a function that abnormally returns. */
92 unsigned int is_call_non_return : 1;
94 /* Arc is for catch/setjump. */
95 unsigned int is_nonlocal_return : 1;
97 /* Is an unconditional branch. */
98 unsigned int is_unconditional : 1;
100 /* Loop making arc. */
101 unsigned int cycle : 1;
103 /* Next branch on line. */
104 struct arc_info *line_next;
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;
111 /* Describes a basic block. Contains lists of arcs to successor and
112 predecessor blocks. */
114 typedef struct block_info
116 /* Chain of exit and entry arcs. */
117 arc_t *succ;
118 arc_t *pred;
120 /* Number of unprocessed exit and entry arcs. */
121 gcov_type num_succ;
122 gcov_type num_pred;
124 /* Block execution count. */
125 gcov_type count;
126 unsigned flags : 13;
127 unsigned count_valid : 1;
128 unsigned valid_chain : 1;
129 unsigned invalid_chain : 1;
131 /* Block is a call instrumenting site. */
132 unsigned is_call_site : 1; /* Does the call. */
133 unsigned is_call_return : 1; /* Is the return. */
135 /* Block is a landing pad for longjmp or throw. */
136 unsigned is_nonlocal_return : 1;
138 union
140 struct
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
151 /* Single line graph cycle workspace. Used for all-blocks
152 mode. */
153 arc_t *arc;
154 unsigned ident;
155 } cycle; /* Used in all-blocks mode, after blocks are linked onto
156 lines. */
157 } u;
159 /* Temporary chain for solving graph, and for chaining blocks on one
160 line. */
161 struct block_info *chain;
163 } block_t;
165 /* Describes a single function. Contains an array of basic blocks. */
167 typedef struct function_info
169 /* Name of function. */
170 char *name;
171 unsigned ident;
172 unsigned checksum;
174 /* Array of basic blocks. */
175 block_t *blocks;
176 unsigned num_blocks;
177 unsigned blocks_executed;
179 /* Raw arc coverage counts. */
180 gcov_type *counts;
181 unsigned num_counts;
183 /* First line number. */
184 unsigned line;
185 struct source_info *src;
187 /* Next function in same source file. */
188 struct function_info *line_next;
190 /* Next function. */
191 struct function_info *next;
192 } function_t;
194 /* Describes coverage of a file or function. */
196 typedef struct coverage_info
198 int lines;
199 int lines_executed;
201 int branches;
202 int branches_executed;
203 int branches_taken;
205 int calls;
206 int calls_executed;
208 char *name;
209 } coverage_t;
211 /* Describes a single line of source. Contains a chain of basic blocks
212 with code on it. */
214 typedef struct line_info
216 gcov_type count; /* execution count */
217 union
219 arc_t *branches; /* branches from blocks that end on this
220 line. Used for branch-counts when not
221 all-blocks mode. */
222 block_t *blocks; /* blocks which start on this line. Used
223 in all-blocks mode. */
224 } u;
225 unsigned exists : 1;
226 } line_t;
228 /* Describes a file mentioned in the block graph. Contains an array
229 of line info. */
231 typedef struct source_info
233 /* Name of source file. */
234 char *name;
235 unsigned index;
237 /* Array of line information. */
238 line_t *lines;
239 unsigned num_lines;
241 coverage_t coverage;
243 /* Functions in this source file. These are in ascending line
244 number order. */
245 function_t *functions;
247 /* Next source file. */
248 struct source_info *next;
249 } source_t;
251 /* Holds a list of function basic block graphs. */
253 static function_t *functions;
255 /* This points to the head of the sourcefile structure list. */
257 static source_t *sources;
259 /* This holds data summary information. */
261 static struct gcov_summary object_summary;
262 static unsigned program_count;
264 /* Modification time of graph file. */
266 static time_t bbg_file_time;
268 /* Name and file pointer of the input file for the basic block graph. */
270 static char *bbg_file_name;
272 /* Stamp of the bbg file */
273 static unsigned bbg_stamp;
275 /* Name and file pointer of the input file for the arc count data. */
277 static char *da_file_name;
279 /* Data file is missing. */
281 static int no_data_file;
283 /* Output branch probabilities. */
285 static int flag_branches = 0;
287 /* Show unconditional branches too. */
288 static int flag_unconditional = 0;
290 /* Output a gcov file if this is true. This is on by default, and can
291 be turned off by the -n option. */
293 static int flag_gcov_file = 1;
295 /* For included files, make the gcov output file name include the name
296 of the input source file. For example, if x.h is included in a.c,
297 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
299 static int flag_long_names = 0;
301 /* Output count information for every basic block, not merely those
302 that contain line number information. */
304 static int flag_all_blocks = 0;
306 /* Output summary info for each function. */
308 static int flag_function_summary = 0;
310 /* Object directory file prefix. This is the directory/file where the
311 graph and data files are looked for, if nonzero. */
313 static char *object_directory = 0;
315 /* Preserve all pathname components. Needed when object files and
316 source files are in subdirectories. '/' is mangled as '#', '.' is
317 elided and '..' mangled to '^'. */
319 static int flag_preserve_paths = 0;
321 /* Output the number of times a branch was taken as opposed to the percentage
322 of times it was taken. */
324 static int flag_counts = 0;
326 /* Forward declarations. */
327 static void fnotice (FILE *, const char *, ...) ATTRIBUTE_PRINTF_2;
328 static int process_args (int, char **);
329 static void print_usage (int) ATTRIBUTE_NORETURN;
330 static void print_version (void) ATTRIBUTE_NORETURN;
331 static void process_file (const char *);
332 static void create_file_names (const char *);
333 static source_t *find_source (const char *);
334 static int read_graph_file (void);
335 static int read_count_file (void);
336 static void solve_flow_graph (function_t *);
337 static void add_branch_counts (coverage_t *, const arc_t *);
338 static void add_line_counts (coverage_t *, function_t *);
339 static void function_summary (const coverage_t *, const char *);
340 static const char *format_gcov (gcov_type, gcov_type, int);
341 static void accumulate_line_counts (source_t *);
342 static int output_branch_count (FILE *, int, const arc_t *);
343 static void output_lines (FILE *, const source_t *);
344 static char *make_gcov_file_name (const char *, const char *);
345 static void release_structures (void);
346 extern int main (int, char **);
349 main (int argc, char **argv)
351 int argno;
353 /* Unlock the stdio streams. */
354 unlock_std_streams ();
356 gcc_init_libintl ();
358 argno = process_args (argc, argv);
359 if (optind == argc)
360 print_usage (true);
362 for (; argno != argc; argno++)
364 release_structures ();
366 process_file (argv[argno]);
369 return 0;
372 static void
373 fnotice (FILE *file, const char *cmsgid, ...)
375 va_list ap;
377 va_start (ap, cmsgid);
378 vfprintf (file, _(cmsgid), ap);
379 va_end (ap);
382 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
383 otherwise the output of --help. */
385 static void
386 print_usage (int error_p)
388 FILE *file = error_p ? stderr : stdout;
389 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
391 fnotice (file, "Usage: gcov [OPTION]... SOURCEFILE\n\n");
392 fnotice (file, "Print code coverage information.\n\n");
393 fnotice (file, " -h, --help Print this help, then exit\n");
394 fnotice (file, " -v, --version Print version number, then exit\n");
395 fnotice (file, " -a, --all-blocks Show information for every basic block\n");
396 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
397 fnotice (file, " -c, --branch-counts Given counts of branches taken\n\
398 rather than percentages\n");
399 fnotice (file, " -n, --no-output Do not create an output file\n");
400 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
401 source files\n");
402 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
403 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
404 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
405 fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
406 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
407 bug_report_url);
408 exit (status);
411 /* Print version information and exit. */
413 static void
414 print_version (void)
416 fnotice (stdout, "gcov (GCC) %s\n", version_string);
417 fprintf (stdout, "Copyright %s 2006 Free Software Foundation, Inc.\n",
418 _("(C)"));
419 fnotice (stdout,
420 _("This is free software; see the source for copying conditions.\n"
421 "There is NO warranty; not even for MERCHANTABILITY or \n"
422 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
423 exit (SUCCESS_EXIT_CODE);
426 static const struct option options[] =
428 { "help", no_argument, NULL, 'h' },
429 { "version", no_argument, NULL, 'v' },
430 { "all-blocks", no_argument, NULL, 'a' },
431 { "branch-probabilities", no_argument, NULL, 'b' },
432 { "branch-counts", no_argument, NULL, 'c' },
433 { "no-output", no_argument, NULL, 'n' },
434 { "long-file-names", no_argument, NULL, 'l' },
435 { "function-summaries", no_argument, NULL, 'f' },
436 { "preserve-paths", no_argument, NULL, 'p' },
437 { "object-directory", required_argument, NULL, 'o' },
438 { "object-file", required_argument, NULL, 'o' },
439 { "unconditional-branches", no_argument, NULL, 'u' },
440 { 0, 0, 0, 0 }
443 /* Process args, return index to first non-arg. */
445 static int
446 process_args (int argc, char **argv)
448 int opt;
450 while ((opt = getopt_long (argc, argv, "abcfhlno:puv", options, NULL)) != -1)
452 switch (opt)
454 case 'a':
455 flag_all_blocks = 1;
456 break;
457 case 'b':
458 flag_branches = 1;
459 break;
460 case 'c':
461 flag_counts = 1;
462 break;
463 case 'f':
464 flag_function_summary = 1;
465 break;
466 case 'h':
467 print_usage (false);
468 /* print_usage will exit. */
469 case 'l':
470 flag_long_names = 1;
471 break;
472 case 'n':
473 flag_gcov_file = 0;
474 break;
475 case 'o':
476 object_directory = optarg;
477 break;
478 case 'p':
479 flag_preserve_paths = 1;
480 break;
481 case 'u':
482 flag_unconditional = 1;
483 break;
484 case 'v':
485 print_version ();
486 /* print_version will exit. */
487 default:
488 print_usage (true);
489 /* print_usage will exit. */
493 return optind;
496 /* Process a single source file. */
498 static void
499 process_file (const char *file_name)
501 source_t *src;
502 function_t *fn;
504 create_file_names (file_name);
505 if (read_graph_file ())
506 return;
508 if (!functions)
510 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
511 return;
514 if (read_count_file ())
515 return;
517 for (fn = functions; fn; fn = fn->next)
518 solve_flow_graph (fn);
519 for (src = sources; src; src = src->next)
520 src->lines = XCNEWVEC (line_t, src->num_lines);
521 for (fn = functions; fn; fn = fn->next)
523 coverage_t coverage;
525 memset (&coverage, 0, sizeof (coverage));
526 coverage.name = fn->name;
527 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
528 if (flag_function_summary)
530 function_summary (&coverage, "Function");
531 fnotice (stdout, "\n");
535 for (src = sources; src; src = src->next)
537 accumulate_line_counts (src);
538 function_summary (&src->coverage, "File");
539 if (flag_gcov_file)
541 char *gcov_file_name = make_gcov_file_name (file_name, src->name);
542 FILE *gcov_file = fopen (gcov_file_name, "w");
544 if (gcov_file)
546 fnotice (stdout, "%s:creating '%s'\n",
547 src->name, gcov_file_name);
548 output_lines (gcov_file, src);
549 if (ferror (gcov_file))
550 fnotice (stderr, "%s:error writing output file '%s'\n",
551 src->name, gcov_file_name);
552 fclose (gcov_file);
554 else
555 fnotice (stderr, "%s:could not open output file '%s'\n",
556 src->name, gcov_file_name);
557 free (gcov_file_name);
559 fnotice (stdout, "\n");
563 /* Release all memory used. */
565 static void
566 release_structures (void)
568 function_t *fn;
569 source_t *src;
571 free (bbg_file_name);
572 free (da_file_name);
573 da_file_name = bbg_file_name = NULL;
574 bbg_file_time = 0;
575 bbg_stamp = 0;
577 while ((src = sources))
579 sources = src->next;
581 free (src->name);
582 free (src->lines);
585 while ((fn = functions))
587 unsigned ix;
588 block_t *block;
590 functions = fn->next;
591 for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
593 arc_t *arc, *arc_n;
595 for (arc = block->succ; arc; arc = arc_n)
597 arc_n = arc->succ_next;
598 free (arc);
601 free (fn->blocks);
602 free (fn->counts);
606 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
607 is not specified, these are looked for in the current directory,
608 and named from the basename of the FILE_NAME sans extension. If
609 OBJECT_DIRECTORY is specified and is a directory, the files are in
610 that directory, but named from the basename of the FILE_NAME, sans
611 extension. Otherwise OBJECT_DIRECTORY is taken to be the name of
612 the object *file*, and the data files are named from that. */
614 static void
615 create_file_names (const char *file_name)
617 char *cptr;
618 char *name;
619 int length = strlen (file_name);
620 int base;
622 if (object_directory && object_directory[0])
624 struct stat status;
626 length += strlen (object_directory) + 2;
627 name = XNEWVEC (char, length);
628 name[0] = 0;
630 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
631 strcat (name, object_directory);
632 if (base && name[strlen (name) - 1] != '/')
633 strcat (name, "/");
635 else
637 name = XNEWVEC (char, length + 1);
638 name[0] = 0;
639 base = 1;
642 if (base)
644 /* Append source file name. */
645 cptr = strrchr (file_name, '/');
646 strcat (name, cptr ? cptr + 1 : file_name);
649 /* Remove the extension. */
650 cptr = strrchr (name, '.');
651 if (cptr)
652 *cptr = 0;
654 length = strlen (name);
656 bbg_file_name = XNEWVEC (char, length + strlen (GCOV_NOTE_SUFFIX) + 1);
657 strcpy (bbg_file_name, name);
658 strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
660 da_file_name = XNEWVEC (char, length + strlen (GCOV_DATA_SUFFIX) + 1);
661 strcpy (da_file_name, name);
662 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
664 free (name);
665 return;
668 /* Find or create a source file structure for FILE_NAME. Copies
669 FILE_NAME on creation */
671 static source_t *
672 find_source (const char *file_name)
674 source_t *src;
676 if (!file_name)
677 file_name = "<unknown>";
679 for (src = sources; src; src = src->next)
680 if (!strcmp (file_name, src->name))
681 return src;
683 src = XCNEW (source_t);
684 src->name = xstrdup (file_name);
685 src->coverage.name = src->name;
686 src->index = sources ? sources->index + 1 : 1;
687 src->next = sources;
688 sources = src;
690 return src;
693 /* Read the graph file. Return nonzero on fatal error. */
695 static int
696 read_graph_file (void)
698 unsigned version;
699 unsigned current_tag = 0;
700 struct function_info *fn = NULL;
701 source_t *src = NULL;
702 unsigned ix;
703 unsigned tag;
705 if (!gcov_open (bbg_file_name, 1))
707 fnotice (stderr, "%s:cannot open graph file\n", bbg_file_name);
708 return 1;
710 bbg_file_time = gcov_time ();
711 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
713 fnotice (stderr, "%s:not a gcov graph file\n", bbg_file_name);
714 gcov_close ();
715 return 1;
718 version = gcov_read_unsigned ();
719 if (version != GCOV_VERSION)
721 char v[4], e[4];
723 GCOV_UNSIGNED2STRING (v, version);
724 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
726 fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n",
727 bbg_file_name, v, e);
729 bbg_stamp = gcov_read_unsigned ();
731 while ((tag = gcov_read_unsigned ()))
733 unsigned length = gcov_read_unsigned ();
734 gcov_position_t base = gcov_position ();
736 if (tag == GCOV_TAG_FUNCTION)
738 char *function_name;
739 unsigned ident, checksum, lineno;
740 source_t *src;
741 function_t *probe, *prev;
743 ident = gcov_read_unsigned ();
744 checksum = gcov_read_unsigned ();
745 function_name = xstrdup (gcov_read_string ());
746 src = find_source (gcov_read_string ());
747 lineno = gcov_read_unsigned ();
749 fn = XCNEW (function_t);
750 fn->name = function_name;
751 fn->ident = ident;
752 fn->checksum = checksum;
753 fn->src = src;
754 fn->line = lineno;
756 fn->next = functions;
757 functions = fn;
758 current_tag = tag;
760 if (lineno >= src->num_lines)
761 src->num_lines = lineno + 1;
762 /* Now insert it into the source file's list of
763 functions. Normally functions will be encountered in
764 ascending order, so a simple scan is quick. */
765 for (probe = src->functions, prev = NULL;
766 probe && probe->line > lineno;
767 prev = probe, probe = probe->line_next)
768 continue;
769 fn->line_next = probe;
770 if (prev)
771 prev->line_next = fn;
772 else
773 src->functions = fn;
775 else if (fn && tag == GCOV_TAG_BLOCKS)
777 if (fn->blocks)
778 fnotice (stderr, "%s:already seen blocks for '%s'\n",
779 bbg_file_name, fn->name);
780 else
782 unsigned ix, num_blocks = GCOV_TAG_BLOCKS_NUM (length);
783 fn->num_blocks = num_blocks;
785 fn->blocks = XCNEWVEC (block_t, fn->num_blocks);
786 for (ix = 0; ix != num_blocks; ix++)
787 fn->blocks[ix].flags = gcov_read_unsigned ();
790 else if (fn && tag == GCOV_TAG_ARCS)
792 unsigned src = gcov_read_unsigned ();
793 unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
795 if (src >= fn->num_blocks || fn->blocks[src].succ)
796 goto corrupt;
798 while (num_dests--)
800 struct arc_info *arc;
801 unsigned dest = gcov_read_unsigned ();
802 unsigned flags = gcov_read_unsigned ();
804 if (dest >= fn->num_blocks)
805 goto corrupt;
806 arc = XCNEW (arc_t);
808 arc->dst = &fn->blocks[dest];
809 arc->src = &fn->blocks[src];
811 arc->count = 0;
812 arc->count_valid = 0;
813 arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
814 arc->fake = !!(flags & GCOV_ARC_FAKE);
815 arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
817 arc->succ_next = fn->blocks[src].succ;
818 fn->blocks[src].succ = arc;
819 fn->blocks[src].num_succ++;
821 arc->pred_next = fn->blocks[dest].pred;
822 fn->blocks[dest].pred = arc;
823 fn->blocks[dest].num_pred++;
825 if (arc->fake)
827 if (src)
829 /* Exceptional exit from this function, the
830 source block must be a call. */
831 fn->blocks[src].is_call_site = 1;
832 arc->is_call_non_return = 1;
834 else
836 /* Non-local return from a callee of this
837 function. The destination block is a catch or
838 setjmp. */
839 arc->is_nonlocal_return = 1;
840 fn->blocks[dest].is_nonlocal_return = 1;
844 if (!arc->on_tree)
845 fn->num_counts++;
848 else if (fn && tag == GCOV_TAG_LINES)
850 unsigned blockno = gcov_read_unsigned ();
851 unsigned *line_nos = XCNEWVEC (unsigned, length - 1);
853 if (blockno >= fn->num_blocks || fn->blocks[blockno].u.line.encoding)
854 goto corrupt;
856 for (ix = 0; ; )
858 unsigned lineno = gcov_read_unsigned ();
860 if (lineno)
862 if (!ix)
864 line_nos[ix++] = 0;
865 line_nos[ix++] = src->index;
867 line_nos[ix++] = lineno;
868 if (lineno >= src->num_lines)
869 src->num_lines = lineno + 1;
871 else
873 const char *file_name = gcov_read_string ();
875 if (!file_name)
876 break;
877 src = find_source (file_name);
879 line_nos[ix++] = 0;
880 line_nos[ix++] = src->index;
884 fn->blocks[blockno].u.line.encoding = line_nos;
885 fn->blocks[blockno].u.line.num = ix;
887 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
889 fn = NULL;
890 current_tag = 0;
892 gcov_sync (base, length);
893 if (gcov_is_error ())
895 corrupt:;
896 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
897 gcov_close ();
898 return 1;
901 gcov_close ();
903 /* We built everything backwards, so nreverse them all. */
905 /* Reverse sources. Not strictly necessary, but we'll then process
906 them in the 'expected' order. */
908 source_t *src, *src_p, *src_n;
910 for (src_p = NULL, src = sources; src; src_p = src, src = src_n)
912 src_n = src->next;
913 src->next = src_p;
915 sources = src_p;
918 /* Reverse functions. */
920 function_t *fn, *fn_p, *fn_n;
922 for (fn_p = NULL, fn = functions; fn; fn_p = fn, fn = fn_n)
924 unsigned ix;
926 fn_n = fn->next;
927 fn->next = fn_p;
929 /* Reverse the arcs. */
930 for (ix = fn->num_blocks; ix--;)
932 arc_t *arc, *arc_p, *arc_n;
934 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
935 arc_p = arc, arc = arc_n)
937 arc_n = arc->succ_next;
938 arc->succ_next = arc_p;
940 fn->blocks[ix].succ = arc_p;
942 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
943 arc_p = arc, arc = arc_n)
945 arc_n = arc->pred_next;
946 arc->pred_next = arc_p;
948 fn->blocks[ix].pred = arc_p;
951 functions = fn_p;
953 return 0;
956 /* Reads profiles from the count file and attach to each
957 function. Return nonzero if fatal error. */
959 static int
960 read_count_file (void)
962 unsigned ix;
963 unsigned version;
964 unsigned tag;
965 function_t *fn = NULL;
966 int error = 0;
968 if (!gcov_open (da_file_name, 1))
970 fnotice (stderr, "%s:cannot open data file, assuming not executed\n",
971 da_file_name);
972 no_data_file = 1;
973 return 0;
975 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
977 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
978 cleanup:;
979 gcov_close ();
980 return 1;
982 version = gcov_read_unsigned ();
983 if (version != GCOV_VERSION)
985 char v[4], e[4];
987 GCOV_UNSIGNED2STRING (v, version);
988 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
990 fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
991 da_file_name, v, e);
993 tag = gcov_read_unsigned ();
994 if (tag != bbg_stamp)
996 fnotice (stderr, "%s:stamp mismatch with graph file\n", da_file_name);
997 goto cleanup;
1000 while ((tag = gcov_read_unsigned ()))
1002 unsigned length = gcov_read_unsigned ();
1003 unsigned long base = gcov_position ();
1005 if (tag == GCOV_TAG_OBJECT_SUMMARY)
1006 gcov_read_summary (&object_summary);
1007 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
1008 program_count++;
1009 else if (tag == GCOV_TAG_FUNCTION)
1011 unsigned ident = gcov_read_unsigned ();
1012 struct function_info *fn_n = functions;
1014 for (fn = fn ? fn->next : NULL; ; fn = fn->next)
1016 if (fn)
1018 else if ((fn = fn_n))
1019 fn_n = NULL;
1020 else
1022 fnotice (stderr, "%s:unknown function '%u'\n",
1023 da_file_name, ident);
1024 break;
1026 if (fn->ident == ident)
1027 break;
1030 if (!fn)
1032 else if (gcov_read_unsigned () != fn->checksum)
1034 mismatch:;
1035 fnotice (stderr, "%s:profile mismatch for '%s'\n",
1036 da_file_name, fn->name);
1037 goto cleanup;
1040 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
1042 if (length != GCOV_TAG_COUNTER_LENGTH (fn->num_counts))
1043 goto mismatch;
1045 if (!fn->counts)
1046 fn->counts = XCNEWVEC (gcov_type, fn->num_counts);
1048 for (ix = 0; ix != fn->num_counts; ix++)
1049 fn->counts[ix] += gcov_read_counter ();
1051 gcov_sync (base, length);
1052 if ((error = gcov_is_error ()))
1054 fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1055 da_file_name);
1056 goto cleanup;
1060 gcov_close ();
1061 return 0;
1064 /* Solve the flow graph. Propagate counts from the instrumented arcs
1065 to the blocks and the uninstrumented arcs. */
1067 static void
1068 solve_flow_graph (function_t *fn)
1070 unsigned ix;
1071 arc_t *arc;
1072 gcov_type *count_ptr = fn->counts;
1073 block_t *blk;
1074 block_t *valid_blocks = NULL; /* valid, but unpropagated blocks. */
1075 block_t *invalid_blocks = NULL; /* invalid, but inferable blocks. */
1077 if (fn->num_blocks < 2)
1078 fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n",
1079 bbg_file_name, fn->name);
1080 else
1082 if (fn->blocks[0].num_pred)
1083 fnotice (stderr, "%s:'%s' has arcs to entry block\n",
1084 bbg_file_name, fn->name);
1085 else
1086 /* We can't deduce the entry block counts from the lack of
1087 predecessors. */
1088 fn->blocks[0].num_pred = ~(unsigned)0;
1090 if (fn->blocks[fn->num_blocks - 1].num_succ)
1091 fnotice (stderr, "%s:'%s' has arcs from exit block\n",
1092 bbg_file_name, fn->name);
1093 else
1094 /* Likewise, we can't deduce exit block counts from the lack
1095 of its successors. */
1096 fn->blocks[fn->num_blocks - 1].num_succ = ~(unsigned)0;
1099 /* Propagate the measured counts, this must be done in the same
1100 order as the code in profile.c */
1101 for (ix = 0, blk = fn->blocks; ix != fn->num_blocks; ix++, blk++)
1103 block_t const *prev_dst = NULL;
1104 int out_of_order = 0;
1105 int non_fake_succ = 0;
1107 for (arc = blk->succ; arc; arc = arc->succ_next)
1109 if (!arc->fake)
1110 non_fake_succ++;
1112 if (!arc->on_tree)
1114 if (count_ptr)
1115 arc->count = *count_ptr++;
1116 arc->count_valid = 1;
1117 blk->num_succ--;
1118 arc->dst->num_pred--;
1120 if (prev_dst && prev_dst > arc->dst)
1121 out_of_order = 1;
1122 prev_dst = arc->dst;
1124 if (non_fake_succ == 1)
1126 /* If there is only one non-fake exit, it is an
1127 unconditional branch. */
1128 for (arc = blk->succ; arc; arc = arc->succ_next)
1129 if (!arc->fake)
1131 arc->is_unconditional = 1;
1132 /* If this block is instrumenting a call, it might be
1133 an artificial block. It is not artificial if it has
1134 a non-fallthrough exit, or the destination of this
1135 arc has more than one entry. Mark the destination
1136 block as a return site, if none of those conditions
1137 hold. */
1138 if (blk->is_call_site && arc->fall_through
1139 && arc->dst->pred == arc && !arc->pred_next)
1140 arc->dst->is_call_return = 1;
1144 /* Sort the successor arcs into ascending dst order. profile.c
1145 normally produces arcs in the right order, but sometimes with
1146 one or two out of order. We're not using a particularly
1147 smart sort. */
1148 if (out_of_order)
1150 arc_t *start = blk->succ;
1151 unsigned changes = 1;
1153 while (changes)
1155 arc_t *arc, *arc_p, *arc_n;
1157 changes = 0;
1158 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1160 if (arc->dst > arc_n->dst)
1162 changes = 1;
1163 if (arc_p)
1164 arc_p->succ_next = arc_n;
1165 else
1166 start = arc_n;
1167 arc->succ_next = arc_n->succ_next;
1168 arc_n->succ_next = arc;
1169 arc_p = arc_n;
1171 else
1173 arc_p = arc;
1174 arc = arc_n;
1178 blk->succ = start;
1181 /* Place it on the invalid chain, it will be ignored if that's
1182 wrong. */
1183 blk->invalid_chain = 1;
1184 blk->chain = invalid_blocks;
1185 invalid_blocks = blk;
1188 while (invalid_blocks || valid_blocks)
1190 while ((blk = invalid_blocks))
1192 gcov_type total = 0;
1193 const arc_t *arc;
1195 invalid_blocks = blk->chain;
1196 blk->invalid_chain = 0;
1197 if (!blk->num_succ)
1198 for (arc = blk->succ; arc; arc = arc->succ_next)
1199 total += arc->count;
1200 else if (!blk->num_pred)
1201 for (arc = blk->pred; arc; arc = arc->pred_next)
1202 total += arc->count;
1203 else
1204 continue;
1206 blk->count = total;
1207 blk->count_valid = 1;
1208 blk->chain = valid_blocks;
1209 blk->valid_chain = 1;
1210 valid_blocks = blk;
1212 while ((blk = valid_blocks))
1214 gcov_type total;
1215 arc_t *arc, *inv_arc;
1217 valid_blocks = blk->chain;
1218 blk->valid_chain = 0;
1219 if (blk->num_succ == 1)
1221 block_t *dst;
1223 total = blk->count;
1224 inv_arc = NULL;
1225 for (arc = blk->succ; arc; arc = arc->succ_next)
1227 total -= arc->count;
1228 if (!arc->count_valid)
1229 inv_arc = arc;
1231 dst = inv_arc->dst;
1232 inv_arc->count_valid = 1;
1233 inv_arc->count = total;
1234 blk->num_succ--;
1235 dst->num_pred--;
1236 if (dst->count_valid)
1238 if (dst->num_pred == 1 && !dst->valid_chain)
1240 dst->chain = valid_blocks;
1241 dst->valid_chain = 1;
1242 valid_blocks = dst;
1245 else
1247 if (!dst->num_pred && !dst->invalid_chain)
1249 dst->chain = invalid_blocks;
1250 dst->invalid_chain = 1;
1251 invalid_blocks = dst;
1255 if (blk->num_pred == 1)
1257 block_t *src;
1259 total = blk->count;
1260 inv_arc = NULL;
1261 for (arc = blk->pred; arc; arc = arc->pred_next)
1263 total -= arc->count;
1264 if (!arc->count_valid)
1265 inv_arc = arc;
1267 src = inv_arc->src;
1268 inv_arc->count_valid = 1;
1269 inv_arc->count = total;
1270 blk->num_pred--;
1271 src->num_succ--;
1272 if (src->count_valid)
1274 if (src->num_succ == 1 && !src->valid_chain)
1276 src->chain = valid_blocks;
1277 src->valid_chain = 1;
1278 valid_blocks = src;
1281 else
1283 if (!src->num_succ && !src->invalid_chain)
1285 src->chain = invalid_blocks;
1286 src->invalid_chain = 1;
1287 invalid_blocks = src;
1294 /* If the graph has been correctly solved, every block will have a
1295 valid count. */
1296 for (ix = 0; ix < fn->num_blocks; ix++)
1297 if (!fn->blocks[ix].count_valid)
1299 fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
1300 bbg_file_name, fn->name);
1301 break;
1307 /* Increment totals in COVERAGE according to arc ARC. */
1309 static void
1310 add_branch_counts (coverage_t *coverage, const arc_t *arc)
1312 if (arc->is_call_non_return)
1314 coverage->calls++;
1315 if (arc->src->count)
1316 coverage->calls_executed++;
1318 else if (!arc->is_unconditional)
1320 coverage->branches++;
1321 if (arc->src->count)
1322 coverage->branches_executed++;
1323 if (arc->count)
1324 coverage->branches_taken++;
1328 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1329 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1330 If DP is zero, no decimal point is printed. Only print 100% when
1331 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1332 format TOP. Return pointer to a static string. */
1334 static char const *
1335 format_gcov (gcov_type top, gcov_type bottom, int dp)
1337 static char buffer[20];
1339 if (dp >= 0)
1341 float ratio = bottom ? (float)top / bottom : 0;
1342 int ix;
1343 unsigned limit = 100;
1344 unsigned percent;
1346 for (ix = dp; ix--; )
1347 limit *= 10;
1349 percent = (unsigned) (ratio * limit + (float)0.5);
1350 if (percent <= 0 && top)
1351 percent = 1;
1352 else if (percent >= limit && top != bottom)
1353 percent = limit - 1;
1354 ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1355 if (dp)
1357 dp++;
1360 buffer[ix+1] = buffer[ix];
1361 ix--;
1363 while (dp--);
1364 buffer[ix + 1] = '.';
1367 else
1368 sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)top);
1370 return buffer;
1374 /* Output summary info for a function. */
1376 static void
1377 function_summary (const coverage_t *coverage, const char *title)
1379 fnotice (stdout, "%s '%s'\n", title, coverage->name);
1381 if (coverage->lines)
1382 fnotice (stdout, "Lines executed:%s of %d\n",
1383 format_gcov (coverage->lines_executed, coverage->lines, 2),
1384 coverage->lines);
1385 else
1386 fnotice (stdout, "No executable lines\n");
1388 if (flag_branches)
1390 if (coverage->branches)
1392 fnotice (stdout, "Branches executed:%s of %d\n",
1393 format_gcov (coverage->branches_executed,
1394 coverage->branches, 2),
1395 coverage->branches);
1396 fnotice (stdout, "Taken at least once:%s of %d\n",
1397 format_gcov (coverage->branches_taken,
1398 coverage->branches, 2),
1399 coverage->branches);
1401 else
1402 fnotice (stdout, "No branches\n");
1403 if (coverage->calls)
1404 fnotice (stdout, "Calls executed:%s of %d\n",
1405 format_gcov (coverage->calls_executed, coverage->calls, 2),
1406 coverage->calls);
1407 else
1408 fnotice (stdout, "No calls\n");
1412 /* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
1413 affect name generation. With preserve_paths we create a filename
1414 from all path components of the source file, replacing '/' with
1415 '#', without it we simply take the basename component. With
1416 long_output_names we prepend the processed name of the input file
1417 to each output name (except when the current source file is the
1418 input file, so you don't get a double concatenation). The two
1419 components are separated by '##'. Also '.' filename components are
1420 removed and '..' components are renamed to '^'. */
1422 static char *
1423 make_gcov_file_name (const char *input_name, const char *src_name)
1425 char *cptr;
1426 char *name = XNEWVEC (char, strlen (src_name) + strlen (input_name) + 10);
1428 name[0] = 0;
1429 if (flag_long_names && strcmp (src_name, input_name))
1431 /* Generate the input filename part. */
1432 cptr = flag_preserve_paths ? NULL : strrchr (input_name, '/');
1433 strcat (name, cptr ? cptr + 1 : input_name);
1434 strcat (name, "##");
1437 /* Generate the source filename part. */
1438 cptr = flag_preserve_paths ? NULL : strrchr (src_name, '/');
1439 strcat (name, cptr ? cptr + 1 : src_name);
1441 if (flag_preserve_paths)
1443 /* Convert '/' to '#', remove '/./', convert '/../' to '/^/' */
1444 char *prev;
1446 for (cptr = name; (cptr = strchr ((prev = cptr), '/'));)
1448 unsigned shift = 0;
1450 if (prev + 1 == cptr && prev[0] == '.')
1452 /* Remove '.' */
1453 shift = 2;
1455 else if (prev + 2 == cptr && prev[0] == '.' && prev[1] == '.')
1457 /* Convert '..' */
1458 shift = 1;
1459 prev[1] = '^';
1461 else
1462 *cptr++ = '#';
1463 if (shift)
1465 cptr = prev;
1467 prev[0] = prev[shift];
1468 while (*prev++);
1473 strcat (name, ".gcov");
1474 return name;
1477 /* Scan through the bb_data for each line in the block, increment
1478 the line number execution count indicated by the execution count of
1479 the appropriate basic block. */
1481 static void
1482 add_line_counts (coverage_t *coverage, function_t *fn)
1484 unsigned ix;
1485 line_t *line = NULL; /* This is propagated from one iteration to the
1486 next. */
1488 /* Scan each basic block. */
1489 for (ix = 0; ix != fn->num_blocks; ix++)
1491 block_t *block = &fn->blocks[ix];
1492 unsigned *encoding;
1493 const source_t *src = NULL;
1494 unsigned jx;
1496 if (block->count && ix && ix + 1 != fn->num_blocks)
1497 fn->blocks_executed++;
1498 for (jx = 0, encoding = block->u.line.encoding;
1499 jx != block->u.line.num; jx++, encoding++)
1500 if (!*encoding)
1502 unsigned src_n = *++encoding;
1504 for (src = sources; src->index != src_n; src = src->next)
1505 continue;
1506 jx++;
1508 else
1510 line = &src->lines[*encoding];
1512 if (coverage)
1514 if (!line->exists)
1515 coverage->lines++;
1516 if (!line->count && block->count)
1517 coverage->lines_executed++;
1519 line->exists = 1;
1520 line->count += block->count;
1522 free (block->u.line.encoding);
1523 block->u.cycle.arc = NULL;
1524 block->u.cycle.ident = ~0U;
1526 if (!ix || ix + 1 == fn->num_blocks)
1527 /* Entry or exit block */;
1528 else if (flag_all_blocks)
1530 line_t *block_line = line ? line : &fn->src->lines[fn->line];
1532 block->chain = block_line->u.blocks;
1533 block_line->u.blocks = block;
1535 else if (flag_branches)
1537 arc_t *arc;
1539 for (arc = block->succ; arc; arc = arc->succ_next)
1541 arc->line_next = line->u.branches;
1542 line->u.branches = arc;
1543 if (coverage && !arc->is_unconditional)
1544 add_branch_counts (coverage, arc);
1548 if (!line)
1549 fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, fn->name);
1552 /* Accumulate the line counts of a file. */
1554 static void
1555 accumulate_line_counts (source_t *src)
1557 line_t *line;
1558 function_t *fn, *fn_p, *fn_n;
1559 unsigned ix;
1561 /* Reverse the function order. */
1562 for (fn = src->functions, fn_p = NULL; fn;
1563 fn_p = fn, fn = fn_n)
1565 fn_n = fn->line_next;
1566 fn->line_next = fn_p;
1568 src->functions = fn_p;
1570 for (ix = src->num_lines, line = src->lines; ix--; line++)
1572 if (!flag_all_blocks)
1574 arc_t *arc, *arc_p, *arc_n;
1576 /* Total and reverse the branch information. */
1577 for (arc = line->u.branches, arc_p = NULL; arc;
1578 arc_p = arc, arc = arc_n)
1580 arc_n = arc->line_next;
1581 arc->line_next = arc_p;
1583 add_branch_counts (&src->coverage, arc);
1585 line->u.branches = arc_p;
1587 else if (line->u.blocks)
1589 /* The user expects the line count to be the number of times
1590 a line has been executed. Simply summing the block count
1591 will give an artificially high number. The Right Thing
1592 is to sum the entry counts to the graph of blocks on this
1593 line, then find the elementary cycles of the local graph
1594 and add the transition counts of those cycles. */
1595 block_t *block, *block_p, *block_n;
1596 gcov_type count = 0;
1598 /* Reverse the block information. */
1599 for (block = line->u.blocks, block_p = NULL; block;
1600 block_p = block, block = block_n)
1602 block_n = block->chain;
1603 block->chain = block_p;
1604 block->u.cycle.ident = ix;
1606 line->u.blocks = block_p;
1608 /* Sum the entry arcs. */
1609 for (block = line->u.blocks; block; block = block->chain)
1611 arc_t *arc;
1613 for (arc = block->pred; arc; arc = arc->pred_next)
1615 if (arc->src->u.cycle.ident != ix)
1616 count += arc->count;
1617 if (flag_branches)
1618 add_branch_counts (&src->coverage, arc);
1621 /* Initialize the cs_count. */
1622 for (arc = block->succ; arc; arc = arc->succ_next)
1623 arc->cs_count = arc->count;
1626 /* Find the loops. This uses the algorithm described in
1627 Tiernan 'An Efficient Search Algorithm to Find the
1628 Elementary Circuits of a Graph', CACM Dec 1970. We hold
1629 the P array by having each block point to the arc that
1630 connects to the previous block. The H array is implicitly
1631 held because of the arc ordering, and the block's
1632 previous arc pointer.
1634 Although the algorithm is O(N^3) for highly connected
1635 graphs, at worst we'll have O(N^2), as most blocks have
1636 only one or two exits. Most graphs will be small.
1638 For each loop we find, locate the arc with the smallest
1639 transition count, and add that to the cumulative
1640 count. Decrease flow over the cycle and remove the arc
1641 from consideration. */
1642 for (block = line->u.blocks; block; block = block->chain)
1644 block_t *head = block;
1645 arc_t *arc;
1647 next_vertex:;
1648 arc = head->succ;
1649 current_vertex:;
1650 while (arc)
1652 block_t *dst = arc->dst;
1653 if (/* Already used that arc. */
1654 arc->cycle
1655 /* Not to same graph, or before first vertex. */
1656 || dst->u.cycle.ident != ix
1657 /* Already in path. */
1658 || dst->u.cycle.arc)
1660 arc = arc->succ_next;
1661 continue;
1664 if (dst == block)
1666 /* Found a closing arc. */
1667 gcov_type cycle_count = arc->cs_count;
1668 arc_t *cycle_arc = arc;
1669 arc_t *probe_arc;
1671 /* Locate the smallest arc count of the loop. */
1672 for (dst = head; (probe_arc = dst->u.cycle.arc);
1673 dst = probe_arc->src)
1674 if (cycle_count > probe_arc->cs_count)
1676 cycle_count = probe_arc->cs_count;
1677 cycle_arc = probe_arc;
1680 count += cycle_count;
1681 cycle_arc->cycle = 1;
1683 /* Remove the flow from the cycle. */
1684 arc->cs_count -= cycle_count;
1685 for (dst = head; (probe_arc = dst->u.cycle.arc);
1686 dst = probe_arc->src)
1687 probe_arc->cs_count -= cycle_count;
1689 /* Unwind to the cyclic arc. */
1690 while (head != cycle_arc->src)
1692 arc = head->u.cycle.arc;
1693 head->u.cycle.arc = NULL;
1694 head = arc->src;
1696 /* Move on. */
1697 arc = arc->succ_next;
1698 continue;
1701 /* Add new block to chain. */
1702 dst->u.cycle.arc = arc;
1703 head = dst;
1704 goto next_vertex;
1706 /* We could not add another vertex to the path. Remove
1707 the last vertex from the list. */
1708 arc = head->u.cycle.arc;
1709 if (arc)
1711 /* It was not the first vertex. Move onto next arc. */
1712 head->u.cycle.arc = NULL;
1713 head = arc->src;
1714 arc = arc->succ_next;
1715 goto current_vertex;
1717 /* Mark this block as unusable. */
1718 block->u.cycle.ident = ~0U;
1721 line->count = count;
1724 if (line->exists)
1726 src->coverage.lines++;
1727 if (line->count)
1728 src->coverage.lines_executed++;
1733 /* Output information about ARC number IX. Returns nonzero if
1734 anything is output. */
1736 static int
1737 output_branch_count (FILE *gcov_file, int ix, const arc_t *arc)
1740 if (arc->is_call_non_return)
1742 if (arc->src->count)
1744 fnotice (gcov_file, "call %2d returned %s\n", ix,
1745 format_gcov (arc->src->count - arc->count,
1746 arc->src->count, -flag_counts));
1748 else
1749 fnotice (gcov_file, "call %2d never executed\n", ix);
1751 else if (!arc->is_unconditional)
1753 if (arc->src->count)
1754 fnotice (gcov_file, "branch %2d taken %s%s\n", ix,
1755 format_gcov (arc->count, arc->src->count, -flag_counts),
1756 arc->fall_through ? " (fallthrough)" : "");
1757 else
1758 fnotice (gcov_file, "branch %2d never executed\n", ix);
1760 else if (flag_unconditional && !arc->dst->is_call_return)
1762 if (arc->src->count)
1763 fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
1764 format_gcov (arc->count, arc->src->count, -flag_counts));
1765 else
1766 fnotice (gcov_file, "unconditional %2d never executed\n", ix);
1768 else
1769 return 0;
1770 return 1;
1774 /* Read in the source file one line at a time, and output that line to
1775 the gcov file preceded by its execution count and other
1776 information. */
1778 static void
1779 output_lines (FILE *gcov_file, const source_t *src)
1781 FILE *source_file;
1782 unsigned line_num; /* current line number. */
1783 const line_t *line; /* current line info ptr. */
1784 char string[STRING_SIZE]; /* line buffer. */
1785 char const *retval = ""; /* status of source file reading. */
1786 function_t *fn = NULL;
1788 fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->name);
1789 fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
1790 fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0,
1791 no_data_file ? "-" : da_file_name);
1792 fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0,
1793 object_summary.ctrs[GCOV_COUNTER_ARCS].runs);
1794 fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
1796 source_file = fopen (src->name, "r");
1797 if (!source_file)
1799 fnotice (stderr, "%s:cannot open source file\n", src->name);
1800 retval = NULL;
1802 else
1804 struct stat status;
1806 if (!fstat (fileno (source_file), &status)
1807 && status.st_mtime > bbg_file_time)
1809 fnotice (stderr, "%s:source file is newer than graph file '%s'\n",
1810 src->name, bbg_file_name);
1811 fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n",
1812 "-", 0);
1816 if (flag_branches)
1817 fn = src->functions;
1819 for (line_num = 1, line = &src->lines[line_num];
1820 line_num < src->num_lines; line_num++, line++)
1822 for (; fn && fn->line == line_num; fn = fn->line_next)
1824 arc_t *arc = fn->blocks[fn->num_blocks - 1].pred;
1825 gcov_type return_count = fn->blocks[fn->num_blocks - 1].count;
1827 for (; arc; arc = arc->pred_next)
1828 if (arc->fake)
1829 return_count -= arc->count;
1831 fprintf (gcov_file, "function %s", fn->name);
1832 fprintf (gcov_file, " called %s",
1833 format_gcov (fn->blocks[0].count, 0, -1));
1834 fprintf (gcov_file, " returned %s",
1835 format_gcov (return_count, fn->blocks[0].count, 0));
1836 fprintf (gcov_file, " blocks executed %s",
1837 format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0));
1838 fprintf (gcov_file, "\n");
1841 /* For lines which don't exist in the .bb file, print '-' before
1842 the source line. For lines which exist but were never
1843 executed, print '#####' before the source line. Otherwise,
1844 print the execution count before the source line. There are
1845 16 spaces of indentation added before the source line so that
1846 tabs won't be messed up. */
1847 fprintf (gcov_file, "%9s:%5u:",
1848 !line->exists ? "-" : !line->count ? "#####"
1849 : format_gcov (line->count, 0, -1), line_num);
1851 if (retval)
1853 /* Copy source line. */
1856 retval = fgets (string, STRING_SIZE, source_file);
1857 if (!retval)
1858 break;
1859 fputs (retval, gcov_file);
1861 while (!retval[0] || retval[strlen (retval) - 1] != '\n');
1863 if (!retval)
1864 fputs ("/*EOF*/\n", gcov_file);
1866 if (flag_all_blocks)
1868 block_t *block;
1869 arc_t *arc;
1870 int ix, jx;
1872 for (ix = jx = 0, block = line->u.blocks; block;
1873 block = block->chain)
1875 if (!block->is_call_return)
1876 fprintf (gcov_file, "%9s:%5u-block %2d\n",
1877 !line->exists ? "-" : !block->count ? "$$$$$"
1878 : format_gcov (block->count, 0, -1),
1879 line_num, ix++);
1880 if (flag_branches)
1881 for (arc = block->succ; arc; arc = arc->succ_next)
1882 jx += output_branch_count (gcov_file, jx, arc);
1885 else if (flag_branches)
1887 int ix;
1888 arc_t *arc;
1890 for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
1891 ix += output_branch_count (gcov_file, ix, arc);
1895 /* Handle all remaining source lines. There may be lines after the
1896 last line of code. */
1897 if (retval)
1899 for (; (retval = fgets (string, STRING_SIZE, source_file)); line_num++)
1901 fprintf (gcov_file, "%9s:%5u:%s", "-", line_num, retval);
1903 while (!retval[0] || retval[strlen (retval) - 1] != '\n')
1905 retval = fgets (string, STRING_SIZE, source_file);
1906 if (!retval)
1907 break;
1908 fputs (retval, gcov_file);
1913 if (source_file)
1914 fclose (source_file);