2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / gcc / gcov.c
blobf95334a4319fcc2a287b80d6febad360794d344e
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 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"
50 #undef abort
52 #include <getopt.h>
54 #define IN_GCOV 1
55 #include "gcov-io.h"
56 #include "gcov-io.c"
58 /* The bbg file is generated by -ftest-coverage option. The da file is
59 generated by a program compiled with -fprofile-arcs. Their formats
60 are documented in gcov-io.h. */
62 /* The functions in this file for creating and solution program flow graphs
63 are very similar to functions in the gcc source file profile.c. In
64 some places we make use of the knowledge of how profile.c works to
65 select particular algorithms here. */
67 /* This is the size of the buffer used to read in source file lines. */
69 #define STRING_SIZE 200
71 struct function_info;
72 struct block_info;
73 struct source_info;
75 /* Describes an arc between two basic blocks. */
77 typedef struct arc_info
79 /* source and destination blocks. */
80 struct block_info *src;
81 struct block_info *dst;
83 /* transition counts. */
84 gcov_type count;
85 /* used in cycle search, so that we do not clobber original counts. */
86 gcov_type cs_count;
88 unsigned int count_valid : 1;
89 unsigned int on_tree : 1;
90 unsigned int fake : 1;
91 unsigned int fall_through : 1;
93 /* Arc is for a function that abnormally returns. */
94 unsigned int is_call_non_return : 1;
96 /* Arc is for catch/setjump. */
97 unsigned int is_nonlocal_return : 1;
99 /* Is an unconditional branch. */
100 unsigned int is_unconditional : 1;
102 /* Loop making arc. */
103 unsigned int cycle : 1;
105 /* Next branch on line. */
106 struct arc_info *line_next;
108 /* Links to next arc on src and dst lists. */
109 struct arc_info *succ_next;
110 struct arc_info *pred_next;
111 } arc_t;
113 /* Describes a basic block. Contains lists of arcs to successor and
114 predecessor blocks. */
116 typedef struct block_info
118 /* Chain of exit and entry arcs. */
119 arc_t *succ;
120 arc_t *pred;
122 /* Number of unprocessed exit and entry arcs. */
123 gcov_type num_succ;
124 gcov_type num_pred;
126 /* Block execution count. */
127 gcov_type count;
128 unsigned flags : 13;
129 unsigned count_valid : 1;
130 unsigned valid_chain : 1;
131 unsigned invalid_chain : 1;
133 /* Block is a call instrumenting site. */
134 unsigned is_call_site : 1; /* Does the call. */
135 unsigned is_call_return : 1; /* Is the return. */
137 /* Block is a landing pad for longjmp or throw. */
138 unsigned is_nonlocal_return : 1;
140 union
142 struct
144 /* Array of line numbers and source files. source files are
145 introduced by a linenumber of zero, the next 'line number' is
146 the number of the source file. Always starts with a source
147 file. */
148 unsigned *encoding;
149 unsigned num;
150 } line; /* Valid until blocks are linked onto lines */
151 struct
153 /* Single line graph cycle workspace. Used for all-blocks
154 mode. */
155 arc_t *arc;
156 unsigned ident;
157 } cycle; /* Used in all-blocks mode, after blocks are linked onto
158 lines. */
159 } u;
161 /* Temporary chain for solving graph, and for chaining blocks on one
162 line. */
163 struct block_info *chain;
165 } block_t;
167 /* Describes a single function. Contains an array of basic blocks. */
169 typedef struct function_info
171 /* Name of function. */
172 char *name;
173 unsigned ident;
174 unsigned checksum;
176 /* Array of basic blocks. */
177 block_t *blocks;
178 unsigned num_blocks;
179 unsigned blocks_executed;
181 /* Raw arc coverage counts. */
182 gcov_type *counts;
183 unsigned num_counts;
185 /* First line number. */
186 unsigned line;
187 struct source_info *src;
189 /* Next function in same source file. */
190 struct function_info *line_next;
192 /* Next function. */
193 struct function_info *next;
194 } function_t;
196 /* Describes coverage of a file or function. */
198 typedef struct coverage_info
200 int lines;
201 int lines_executed;
203 int branches;
204 int branches_executed;
205 int branches_taken;
207 int calls;
208 int calls_executed;
210 char *name;
211 } coverage_t;
213 /* Describes a single line of source. Contains a chain of basic blocks
214 with code on it. */
216 typedef struct line_info
218 gcov_type count; /* execution count */
219 union
221 arc_t *branches; /* branches from blocks that end on this
222 line. Used for branch-counts when not
223 all-blocks mode. */
224 block_t *blocks; /* blocks which start on this line. Used
225 in all-blocks mode. */
226 } u;
227 unsigned exists : 1;
228 } line_t;
230 /* Describes a file mentioned in the block graph. Contains an array
231 of line info. */
233 typedef struct source_info
235 /* Name of source file. */
236 char *name;
237 unsigned index;
239 /* Array of line information. */
240 line_t *lines;
241 unsigned num_lines;
243 coverage_t coverage;
245 /* Functions in this source file. These are in ascending line
246 number order. */
247 function_t *functions;
249 /* Next source file. */
250 struct source_info *next;
251 } source_t;
253 /* Holds a list of function basic block graphs. */
255 static function_t *functions;
257 /* This points to the head of the sourcefile structure list. */
259 static source_t *sources;
261 /* This holds data summary information. */
263 static struct gcov_summary object_summary;
264 static unsigned program_count;
266 /* Modification time of graph file. */
268 static time_t bbg_file_time;
270 /* Name and file pointer of the input file for the basic block graph. */
272 static char *bbg_file_name;
274 /* Stamp of the bbg file */
275 static unsigned bbg_stamp;
277 /* Name and file pointer of the input file for the arc count data. */
279 static char *da_file_name;
281 /* Output branch probabilities. */
283 static int flag_branches = 0;
285 /* Show unconditional branches too. */
286 static int flag_unconditional = 0;
288 /* Output a gcov file if this is true. This is on by default, and can
289 be turned off by the -n option. */
291 static int flag_gcov_file = 1;
293 /* For included files, make the gcov output file name include the name
294 of the input source file. For example, if x.h is included in a.c,
295 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
297 static int flag_long_names = 0;
299 /* Output count information for every basic block, not merely those
300 that contain line number information. */
302 static int flag_all_blocks = 0;
304 /* Output summary info for each function. */
306 static int flag_function_summary = 0;
308 /* Object directory file prefix. This is the directory/file where the
309 graph and data files are looked for, if nonzero. */
311 static char *object_directory = 0;
313 /* Preserve all pathname components. Needed when object files and
314 source files are in subdirectories. '/' is mangled as '#', '.' is
315 elided and '..' mangled to '^'. */
317 static int flag_preserve_paths = 0;
319 /* Output the number of times a branch was taken as opposed to the percentage
320 of times it was taken. */
322 static int flag_counts = 0;
324 /* Forward declarations. */
325 static void fnotice (FILE *, const char *, ...) ATTRIBUTE_PRINTF_2;
326 static int process_args (int, char **);
327 static void print_usage (int) ATTRIBUTE_NORETURN;
328 static void print_version (void) ATTRIBUTE_NORETURN;
329 static void process_file (const char *);
330 static void create_file_names (const char *);
331 static source_t *find_source (const char *);
332 static int read_graph_file (void);
333 static int read_count_file (void);
334 static void solve_flow_graph (function_t *);
335 static void add_branch_counts (coverage_t *, const arc_t *);
336 static void add_line_counts (coverage_t *, function_t *);
337 static void function_summary (const coverage_t *, const char *);
338 static const char *format_gcov (gcov_type, gcov_type, int);
339 static void accumulate_line_counts (source_t *);
340 static int output_branch_count (FILE *, int, const arc_t *);
341 static void output_lines (FILE *, const source_t *);
342 static char *make_gcov_file_name (const char *, const char *);
343 static void release_structures (void);
344 extern int main (int, char **);
347 main (int argc, char **argv)
349 int argno;
351 gcc_init_libintl ();
353 argno = process_args (argc, argv);
354 if (optind == argc)
355 print_usage (true);
357 for (; argno != argc; argno++)
359 release_structures ();
361 process_file (argv[argno]);
364 return 0;
367 static void
368 fnotice (FILE *file, const char *msgid, ...)
370 va_list ap;
372 va_start (ap, msgid);
373 vfprintf (file, _(msgid), ap);
374 va_end (ap);
377 /* More 'friendly' abort that prints the line and file.
378 config.h can #define abort fancy_abort if you like that sort of thing. */
379 extern void fancy_abort (void) ATTRIBUTE_NORETURN;
381 void
382 fancy_abort (void)
384 fnotice (stderr, "Internal gcov abort.\n");
385 exit (FATAL_EXIT_CODE);
388 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
389 otherwise the output of --help. */
391 static void
392 print_usage (int error_p)
394 FILE *file = error_p ? stderr : stdout;
395 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
397 fnotice (file, "Usage: gcov [OPTION]... SOURCEFILE\n\n");
398 fnotice (file, "Print code coverage information.\n\n");
399 fnotice (file, " -h, --help Print this help, then exit\n");
400 fnotice (file, " -v, --version Print version number, then exit\n");
401 fnotice (file, " -a, --all-blocks Show information for every basic block\n");
402 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
403 fnotice (file, " -c, --branch-counts Given counts of branches taken\n\
404 rather than percentages\n");
405 fnotice (file, " -n, --no-output Do not create an output file\n");
406 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
407 source files\n");
408 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
409 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
410 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
411 fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
412 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
413 bug_report_url);
414 exit (status);
417 /* Print version information and exit. */
419 static void
420 print_version (void)
422 fnotice (stdout, "gcov (GCC) %s\n", version_string);
423 fnotice (stdout, "Copyright (C) 2003 Free Software Foundation, Inc.\n");
424 fnotice (stdout,
425 "This is free software; see the source for copying conditions.\n"
426 "There is NO warranty; not even for MERCHANTABILITY or \n"
427 "FITNESS FOR A PARTICULAR PURPOSE.\n\n");
428 exit (SUCCESS_EXIT_CODE);
431 static const struct option options[] =
433 { "help", no_argument, NULL, 'h' },
434 { "version", no_argument, NULL, 'v' },
435 { "all-blocks", no_argument, NULL, 'a' },
436 { "branch-probabilities", no_argument, NULL, 'b' },
437 { "branch-counts", no_argument, NULL, 'c' },
438 { "no-output", no_argument, NULL, 'n' },
439 { "long-file-names", no_argument, NULL, 'l' },
440 { "function-summaries", no_argument, NULL, 'f' },
441 { "preserve-paths", no_argument, NULL, 'p' },
442 { "object-directory", required_argument, NULL, 'o' },
443 { "object-file", required_argument, NULL, 'o' },
444 { "unconditional-branches", no_argument, NULL, 'u' },
445 { 0, 0, 0, 0 }
448 /* Process args, return index to first non-arg. */
450 static int
451 process_args (int argc, char **argv)
453 int opt;
455 while ((opt = getopt_long (argc, argv, "abcfhlno:puv", options, NULL)) != -1)
457 switch (opt)
459 case 'a':
460 flag_all_blocks = 1;
461 break;
462 case 'b':
463 flag_branches = 1;
464 break;
465 case 'c':
466 flag_counts = 1;
467 break;
468 case 'f':
469 flag_function_summary = 1;
470 break;
471 case 'h':
472 print_usage (false);
473 /* print_usage will exit. */
474 case 'l':
475 flag_long_names = 1;
476 break;
477 case 'n':
478 flag_gcov_file = 0;
479 break;
480 case 'o':
481 object_directory = optarg;
482 break;
483 case 'p':
484 flag_preserve_paths = 1;
485 break;
486 case 'u':
487 flag_unconditional = 1;
488 break;
489 case 'v':
490 print_version ();
491 /* print_version will exit. */
492 default:
493 print_usage (true);
494 /* print_usage will exit. */
498 return optind;
501 /* Process a single source file. */
503 static void
504 process_file (const char *file_name)
506 source_t *src;
507 function_t *fn;
509 create_file_names (file_name);
510 if (read_graph_file ())
511 return;
513 if (!functions)
515 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
516 return;
519 if (read_count_file ())
520 return;
522 for (fn = functions; fn; fn = fn->next)
523 solve_flow_graph (fn);
524 for (src = sources; src; src = src->next)
525 src->lines = xcalloc (src->num_lines, sizeof (line_t));
526 for (fn = functions; fn; fn = fn->next)
528 coverage_t coverage;
530 memset (&coverage, 0, sizeof (coverage));
531 coverage.name = fn->name;
532 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
533 if (flag_function_summary)
535 function_summary (&coverage, "Function");
536 fnotice (stdout, "\n");
540 for (src = sources; src; src = src->next)
542 accumulate_line_counts (src);
543 function_summary (&src->coverage, "File");
544 if (flag_gcov_file)
546 char *gcov_file_name = make_gcov_file_name (file_name, src->name);
547 FILE *gcov_file = fopen (gcov_file_name, "w");
549 if (gcov_file)
551 fnotice (stdout, "%s:creating `%s'\n",
552 src->name, gcov_file_name);
553 output_lines (gcov_file, src);
554 if (ferror (gcov_file))
555 fnotice (stderr, "%s:error writing output file `%s'\n",
556 src->name, gcov_file_name);
557 fclose (gcov_file);
559 else
560 fnotice (stderr, "%s:could not open output file `%s'\n",
561 src->name, gcov_file_name);
562 free (gcov_file_name);
564 fnotice (stdout, "\n");
568 /* Release all memory used. */
570 static void
571 release_structures (void)
573 function_t *fn;
574 source_t *src;
576 free (bbg_file_name);
577 free (da_file_name);
578 da_file_name = bbg_file_name = NULL;
579 bbg_file_time = 0;
580 bbg_stamp = 0;
582 while ((src = sources))
584 sources = src->next;
586 free (src->name);
587 free (src->lines);
590 while ((fn = functions))
592 unsigned ix;
593 block_t *block;
595 functions = fn->next;
596 for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
598 arc_t *arc, *arc_n;
600 for (arc = block->succ; arc; arc = arc_n)
602 arc_n = arc->succ_next;
603 free (arc);
606 free (fn->blocks);
607 free (fn->counts);
611 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
612 is not specified, these are looked for in the current directory,
613 and named from the basename of the FILE_NAME sans extension. If
614 OBJECT_DIRECTORY is specified and is a directory, the files are in
615 that directory, but named from the basename of the FILE_NAME, sans
616 extension. Otherwise OBJECT_DIRECTORY is taken to be the name of
617 the object *file*, and the data files are named from that. */
619 static void
620 create_file_names (const char *file_name)
622 char *cptr;
623 char *name;
624 int length = strlen (file_name);
625 int base;
627 if (object_directory && object_directory[0])
629 struct stat status;
631 length += strlen (object_directory) + 2;
632 name = xmalloc (length);
633 name[0] = 0;
635 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
636 strcat (name, object_directory);
637 if (base && name[strlen (name) - 1] != '/')
638 strcat (name, "/");
640 else
642 name = xmalloc (length + 1);
643 name[0] = 0;
644 base = 1;
647 if (base)
649 /* Append source file name. */
650 cptr = strrchr (file_name, '/');
651 strcat (name, cptr ? cptr + 1 : file_name);
654 /* Remove the extension. */
655 cptr = strrchr (name, '.');
656 if (cptr)
657 *cptr = 0;
659 length = strlen (name);
661 bbg_file_name = xmalloc (length + strlen (GCOV_NOTE_SUFFIX) + 1);
662 strcpy (bbg_file_name, name);
663 strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
665 da_file_name = xmalloc (length + strlen (GCOV_DATA_SUFFIX) + 1);
666 strcpy (da_file_name, name);
667 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
669 return;
672 /* Find or create a source file structure for FILE_NAME. Copies
673 FILE_NAME on creation */
675 static source_t *
676 find_source (const char *file_name)
678 source_t *src;
680 if (!file_name)
681 file_name = "<unknown>";
683 for (src = sources; src; src = src->next)
684 if (!strcmp (file_name, src->name))
685 return src;
687 src = xcalloc (1, sizeof (source_t));
688 src->name = xstrdup (file_name);
689 src->coverage.name = src->name;
690 src->index = sources ? sources->index + 1 : 1;
691 src->next = sources;
692 sources = src;
694 return src;
697 /* Read the graph file. Return nonzero on fatal error. */
699 static int
700 read_graph_file (void)
702 unsigned version;
703 unsigned current_tag = 0;
704 struct function_info *fn = NULL;
705 source_t *src = NULL;
706 unsigned ix;
707 unsigned tag;
709 if (!gcov_open (bbg_file_name, 1))
711 fnotice (stderr, "%s:cannot open graph file\n", bbg_file_name);
712 return 1;
714 bbg_file_time = gcov_time ();
715 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
717 fnotice (stderr, "%s:not a gcov graph file\n", bbg_file_name);
718 gcov_close ();
719 return 1;
722 version = gcov_read_unsigned ();
723 if (version != GCOV_VERSION)
725 char v[4], e[4];
727 GCOV_UNSIGNED2STRING (v, version);
728 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
730 fnotice (stderr, "%s:version `%.4s', prefer `%.4s'\n",
731 bbg_file_name, v, e);
733 bbg_stamp = gcov_read_unsigned ();
735 while ((tag = gcov_read_unsigned ()))
737 unsigned length = gcov_read_unsigned ();
738 gcov_position_t base = gcov_position ();
740 if (tag == GCOV_TAG_FUNCTION)
742 char *function_name;
743 unsigned ident, checksum, lineno;
744 source_t *src;
745 function_t *probe, *prev;
747 ident = gcov_read_unsigned ();
748 checksum = gcov_read_unsigned ();
749 function_name = xstrdup (gcov_read_string ());
750 src = find_source (gcov_read_string ());
751 lineno = gcov_read_unsigned ();
753 fn = xcalloc (1, sizeof (function_t));
754 fn->name = function_name;
755 fn->ident = ident;
756 fn->checksum = checksum;
757 fn->src = src;
758 fn->line = lineno;
760 fn->next = functions;
761 functions = fn;
762 current_tag = tag;
764 if (lineno >= src->num_lines)
765 src->num_lines = lineno + 1;
766 /* Now insert it into the source file's list of
767 functions. Normally functions will be encountered in
768 ascending order, so a simple scan is quick. */
769 for (probe = src->functions, prev = NULL;
770 probe && probe->line > lineno;
771 prev = probe, probe = probe->line_next)
772 continue;
773 fn->line_next = probe;
774 if (prev)
775 prev->line_next = fn;
776 else
777 src->functions = fn;
779 else if (fn && tag == GCOV_TAG_BLOCKS)
781 if (fn->blocks)
782 fnotice (stderr, "%s:already seen blocks for `%s'\n",
783 bbg_file_name, fn->name);
784 else
786 unsigned ix, num_blocks = GCOV_TAG_BLOCKS_NUM (length);
787 fn->num_blocks = num_blocks;
789 fn->blocks = xcalloc (fn->num_blocks, sizeof (block_t));
790 for (ix = 0; ix != num_blocks; ix++)
791 fn->blocks[ix].flags = gcov_read_unsigned ();
794 else if (fn && tag == GCOV_TAG_ARCS)
796 unsigned src = gcov_read_unsigned ();
797 unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
799 if (src >= fn->num_blocks || fn->blocks[src].succ)
800 goto corrupt;
802 while (num_dests--)
804 struct arc_info *arc;
805 unsigned dest = gcov_read_unsigned ();
806 unsigned flags = gcov_read_unsigned ();
808 if (dest >= fn->num_blocks)
809 goto corrupt;
810 arc = xcalloc (1, sizeof (arc_t));
812 arc->dst = &fn->blocks[dest];
813 arc->src = &fn->blocks[src];
815 arc->count = 0;
816 arc->count_valid = 0;
817 arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
818 arc->fake = !!(flags & GCOV_ARC_FAKE);
819 arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
821 arc->succ_next = fn->blocks[src].succ;
822 fn->blocks[src].succ = arc;
823 fn->blocks[src].num_succ++;
825 arc->pred_next = fn->blocks[dest].pred;
826 fn->blocks[dest].pred = arc;
827 fn->blocks[dest].num_pred++;
829 if (arc->fake)
831 if (src)
833 /* Exceptional exit from this function, the
834 source block must be a call. */
835 fn->blocks[src].is_call_site = 1;
836 arc->is_call_non_return = 1;
838 else
840 /* Non-local return from a callee of this
841 function. The destination block is a catch or
842 setjmp. */
843 arc->is_nonlocal_return = 1;
844 fn->blocks[dest].is_nonlocal_return = 1;
848 if (!arc->on_tree)
849 fn->num_counts++;
852 else if (fn && tag == GCOV_TAG_LINES)
854 unsigned blockno = gcov_read_unsigned ();
855 unsigned *line_nos = xcalloc (length - 1, sizeof (unsigned));
857 if (blockno >= fn->num_blocks || fn->blocks[blockno].u.line.encoding)
858 goto corrupt;
860 for (ix = 0; ; )
862 unsigned lineno = gcov_read_unsigned ();
864 if (lineno)
866 if (!ix)
868 line_nos[ix++] = 0;
869 line_nos[ix++] = src->index;
871 line_nos[ix++] = lineno;
872 if (lineno >= src->num_lines)
873 src->num_lines = lineno + 1;
875 else
877 const char *file_name = gcov_read_string ();
879 if (!file_name)
880 break;
881 src = find_source (file_name);
883 line_nos[ix++] = 0;
884 line_nos[ix++] = src->index;
888 fn->blocks[blockno].u.line.encoding = line_nos;
889 fn->blocks[blockno].u.line.num = ix;
891 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
893 fn = NULL;
894 current_tag = 0;
896 gcov_sync (base, length);
897 if (gcov_is_error ())
898 break;
900 if (!gcov_is_eof ())
902 corrupt:;
903 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
904 gcov_close ();
905 return 1;
907 gcov_close ();
909 /* We built everything backwards, so nreverse them all. */
911 /* Reverse sources. Not strictly necessary, but we'll then process
912 them in the 'expected' order. */
914 source_t *src, *src_p, *src_n;
916 for (src_p = NULL, src = sources; src; src_p = src, src = src_n)
918 src_n = src->next;
919 src->next = src_p;
921 sources = src_p;
924 /* Reverse functions. */
926 function_t *fn, *fn_p, *fn_n;
928 for (fn_p = NULL, fn = functions; fn; fn_p = fn, fn = fn_n)
930 unsigned ix;
932 fn_n = fn->next;
933 fn->next = fn_p;
935 /* Reverse the arcs. */
936 for (ix = fn->num_blocks; ix--;)
938 arc_t *arc, *arc_p, *arc_n;
940 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
941 arc_p = arc, arc = arc_n)
943 arc_n = arc->succ_next;
944 arc->succ_next = arc_p;
946 fn->blocks[ix].succ = arc_p;
948 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
949 arc_p = arc, arc = arc_n)
951 arc_n = arc->pred_next;
952 arc->pred_next = arc_p;
954 fn->blocks[ix].pred = arc_p;
957 functions = fn_p;
959 return 0;
962 /* Reads profiles from the count file and attach to each
963 function. Return nonzero if fatal error. */
965 static int
966 read_count_file (void)
968 unsigned ix;
969 unsigned version;
970 unsigned tag;
971 function_t *fn = NULL;
972 int error = 0;
974 if (!gcov_open (da_file_name, 1))
976 fnotice (stderr, "%s:cannot open data file\n", da_file_name);
977 return 1;
979 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
981 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
982 cleanup:;
983 gcov_close ();
984 return 1;
986 version = gcov_read_unsigned ();
987 if (version != GCOV_VERSION)
989 char v[4], e[4];
991 GCOV_UNSIGNED2STRING (v, version);
992 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
994 fnotice (stderr, "%s:version `%.4s', prefer version `%.4s'\n",
995 da_file_name, v, e);
997 tag = gcov_read_unsigned ();
998 if (tag != bbg_stamp)
1000 fnotice (stderr, "%s:stamp mismatch with graph file\n", da_file_name);
1001 goto cleanup;
1004 while ((tag = gcov_read_unsigned ()))
1006 unsigned length = gcov_read_unsigned ();
1007 unsigned long base = gcov_position ();
1009 if (tag == GCOV_TAG_OBJECT_SUMMARY)
1010 gcov_read_summary (&object_summary);
1011 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
1012 program_count++;
1013 else if (tag == GCOV_TAG_FUNCTION)
1015 unsigned ident = gcov_read_unsigned ();
1016 struct function_info *fn_n = functions;
1018 for (fn = fn ? fn->next : NULL; ; fn = fn->next)
1020 if (fn)
1022 else if ((fn = fn_n))
1023 fn_n = NULL;
1024 else
1026 fnotice (stderr, "%s:unknown function `%u'\n",
1027 da_file_name, ident);
1028 break;
1030 if (fn->ident == ident)
1031 break;
1034 if (!fn)
1036 else if (gcov_read_unsigned () != fn->checksum)
1038 mismatch:;
1039 fnotice (stderr, "%s:profile mismatch for `%s'\n",
1040 da_file_name, fn->name);
1041 goto cleanup;
1044 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
1046 if (length != GCOV_TAG_COUNTER_LENGTH (fn->num_counts))
1047 goto mismatch;
1049 if (!fn->counts)
1050 fn->counts = xcalloc (fn->num_counts, sizeof (gcov_type));
1052 for (ix = 0; ix != fn->num_counts; ix++)
1053 fn->counts[ix] += gcov_read_counter ();
1055 gcov_sync (base, length);
1056 if ((error = gcov_is_error ()))
1057 break;
1060 if (!gcov_is_eof ())
1062 fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1063 da_file_name);
1064 goto cleanup;
1067 gcov_close ();
1068 return 0;
1071 /* Solve the flow graph. Propagate counts from the instrumented arcs
1072 to the blocks and the uninstrumented arcs. */
1074 static void
1075 solve_flow_graph (function_t *fn)
1077 unsigned ix;
1078 arc_t *arc;
1079 gcov_type *count_ptr = fn->counts;
1080 block_t *blk;
1081 block_t *valid_blocks = NULL; /* valid, but unpropagated blocks. */
1082 block_t *invalid_blocks = NULL; /* invalid, but inferable blocks. */
1084 if (fn->num_blocks < 2)
1085 fnotice (stderr, "%s:`%s' lacks entry and/or exit blocks\n",
1086 bbg_file_name, fn->name);
1087 else
1089 if (fn->blocks[0].num_pred)
1090 fnotice (stderr, "%s:`%s' has arcs to entry block\n",
1091 bbg_file_name, fn->name);
1092 else
1093 /* We can't deduce the entry block counts from the lack of
1094 predecessors. */
1095 fn->blocks[0].num_pred = ~(unsigned)0;
1097 if (fn->blocks[fn->num_blocks - 1].num_succ)
1098 fnotice (stderr, "%s:`%s' has arcs from exit block\n",
1099 bbg_file_name, fn->name);
1100 else
1101 /* Likewise, we can't deduce exit block counts from the lack
1102 of its successors. */
1103 fn->blocks[fn->num_blocks - 1].num_succ = ~(unsigned)0;
1106 /* Propagate the measured counts, this must be done in the same
1107 order as the code in profile.c */
1108 for (ix = 0, blk = fn->blocks; ix != fn->num_blocks; ix++, blk++)
1110 block_t const *prev_dst = NULL;
1111 int out_of_order = 0;
1112 int non_fake_succ = 0;
1114 for (arc = blk->succ; arc; arc = arc->succ_next)
1116 if (!arc->fake)
1117 non_fake_succ++;
1119 if (!arc->on_tree)
1121 if (count_ptr)
1122 arc->count = *count_ptr++;
1123 arc->count_valid = 1;
1124 blk->num_succ--;
1125 arc->dst->num_pred--;
1127 if (prev_dst && prev_dst > arc->dst)
1128 out_of_order = 1;
1129 prev_dst = arc->dst;
1131 if (non_fake_succ == 1)
1133 /* If there is only one non-fake exit, it is an
1134 unconditional branch. */
1135 for (arc = blk->succ; arc; arc = arc->succ_next)
1136 if (!arc->fake)
1138 arc->is_unconditional = 1;
1139 /* If this block is instrumenting a call, it might be
1140 an artificial block. It is not artificial if it has
1141 a non-fallthrough exit, or the destination of this
1142 arc has more than one entry. Mark the destination
1143 block as a return site, if none of those conditions
1144 hold. */
1145 if (blk->is_call_site && arc->fall_through
1146 && arc->dst->pred == arc && !arc->pred_next)
1147 arc->dst->is_call_return = 1;
1151 /* Sort the successor arcs into ascending dst order. profile.c
1152 normally produces arcs in the right order, but sometimes with
1153 one or two out of order. We're not using a particularly
1154 smart sort. */
1155 if (out_of_order)
1157 arc_t *start = blk->succ;
1158 unsigned changes = 1;
1160 while (changes)
1162 arc_t *arc, *arc_p, *arc_n;
1164 changes = 0;
1165 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1167 if (arc->dst > arc_n->dst)
1169 changes = 1;
1170 if (arc_p)
1171 arc_p->succ_next = arc_n;
1172 else
1173 start = arc_n;
1174 arc->succ_next = arc_n->succ_next;
1175 arc_n->succ_next = arc;
1176 arc_p = arc_n;
1178 else
1180 arc_p = arc;
1181 arc = arc_n;
1185 blk->succ = start;
1188 /* Place it on the invalid chain, it will be ignored if that's
1189 wrong. */
1190 blk->invalid_chain = 1;
1191 blk->chain = invalid_blocks;
1192 invalid_blocks = blk;
1195 while (invalid_blocks || valid_blocks)
1197 while ((blk = invalid_blocks))
1199 gcov_type total = 0;
1200 const arc_t *arc;
1202 invalid_blocks = blk->chain;
1203 blk->invalid_chain = 0;
1204 if (!blk->num_succ)
1205 for (arc = blk->succ; arc; arc = arc->succ_next)
1206 total += arc->count;
1207 else if (!blk->num_pred)
1208 for (arc = blk->pred; arc; arc = arc->pred_next)
1209 total += arc->count;
1210 else
1211 continue;
1213 blk->count = total;
1214 blk->count_valid = 1;
1215 blk->chain = valid_blocks;
1216 blk->valid_chain = 1;
1217 valid_blocks = blk;
1219 while ((blk = valid_blocks))
1221 gcov_type total;
1222 arc_t *arc, *inv_arc;
1224 valid_blocks = blk->chain;
1225 blk->valid_chain = 0;
1226 if (blk->num_succ == 1)
1228 block_t *dst;
1230 total = blk->count;
1231 inv_arc = NULL;
1232 for (arc = blk->succ; arc; arc = arc->succ_next)
1234 total -= arc->count;
1235 if (!arc->count_valid)
1236 inv_arc = arc;
1238 dst = inv_arc->dst;
1239 inv_arc->count_valid = 1;
1240 inv_arc->count = total;
1241 blk->num_succ--;
1242 dst->num_pred--;
1243 if (dst->count_valid)
1245 if (dst->num_pred == 1 && !dst->valid_chain)
1247 dst->chain = valid_blocks;
1248 dst->valid_chain = 1;
1249 valid_blocks = dst;
1252 else
1254 if (!dst->num_pred && !dst->invalid_chain)
1256 dst->chain = invalid_blocks;
1257 dst->invalid_chain = 1;
1258 invalid_blocks = dst;
1262 if (blk->num_pred == 1)
1264 block_t *src;
1266 total = blk->count;
1267 inv_arc = NULL;
1268 for (arc = blk->pred; arc; arc = arc->pred_next)
1270 total -= arc->count;
1271 if (!arc->count_valid)
1272 inv_arc = arc;
1274 src = inv_arc->src;
1275 inv_arc->count_valid = 1;
1276 inv_arc->count = total;
1277 blk->num_pred--;
1278 src->num_succ--;
1279 if (src->count_valid)
1281 if (src->num_succ == 1 && !src->valid_chain)
1283 src->chain = valid_blocks;
1284 src->valid_chain = 1;
1285 valid_blocks = src;
1288 else
1290 if (!src->num_succ && !src->invalid_chain)
1292 src->chain = invalid_blocks;
1293 src->invalid_chain = 1;
1294 invalid_blocks = src;
1301 /* If the graph has been correctly solved, every block will have a
1302 valid count. */
1303 for (ix = 0; ix < fn->num_blocks; ix++)
1304 if (!fn->blocks[ix].count_valid)
1306 fnotice (stderr, "%s:graph is unsolvable for `%s'\n",
1307 bbg_file_name, fn->name);
1308 break;
1314 /* Increment totals in COVERAGE according to arc ARC. */
1316 static void
1317 add_branch_counts (coverage_t *coverage, const arc_t *arc)
1319 if (arc->is_call_non_return)
1321 coverage->calls++;
1322 if (arc->src->count)
1323 coverage->calls_executed++;
1325 else if (!arc->is_unconditional)
1327 coverage->branches++;
1328 if (arc->src->count)
1329 coverage->branches_executed++;
1330 if (arc->count)
1331 coverage->branches_taken++;
1335 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1336 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1337 If DP is zero, no decimal point is printed. Only print 100% when
1338 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1339 format TOP. Return pointer to a static string. */
1341 static char const *
1342 format_gcov (gcov_type top, gcov_type bottom, int dp)
1344 static char buffer[20];
1346 if (dp >= 0)
1348 float ratio = bottom ? (float)top / bottom : 0;
1349 int ix;
1350 unsigned limit = 100;
1351 unsigned percent;
1353 for (ix = dp; ix--; )
1354 limit *= 10;
1356 percent = (unsigned) (ratio * limit + (float)0.5);
1357 if (percent <= 0 && top)
1358 percent = 1;
1359 else if (percent >= limit && top != bottom)
1360 percent = limit - 1;
1361 ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1362 if (dp)
1364 dp++;
1367 buffer[ix+1] = buffer[ix];
1368 ix--;
1370 while (dp--);
1371 buffer[ix + 1] = '.';
1374 else
1375 sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)top);
1377 return buffer;
1381 /* Output summary info for a function. */
1383 static void
1384 function_summary (const coverage_t *coverage, const char *title)
1386 fnotice (stdout, "%s `%s'\n", title, coverage->name);
1388 if (coverage->lines)
1389 fnotice (stdout, "Lines executed:%s of %d\n",
1390 format_gcov (coverage->lines_executed, coverage->lines, 2),
1391 coverage->lines);
1392 else
1393 fnotice (stdout, "No executable lines");
1395 if (flag_branches)
1397 if (coverage->branches)
1399 fnotice (stdout, "Branches executed:%s of %d\n",
1400 format_gcov (coverage->branches_executed,
1401 coverage->branches, 2),
1402 coverage->branches);
1403 fnotice (stdout, "Taken at least once:%s of %d\n",
1404 format_gcov (coverage->branches_taken,
1405 coverage->branches, 2),
1406 coverage->branches);
1408 else
1409 fnotice (stdout, "No branches\n");
1410 if (coverage->calls)
1411 fnotice (stdout, "Calls executed:%s of %d\n",
1412 format_gcov (coverage->calls_executed, coverage->calls, 2),
1413 coverage->calls);
1414 else
1415 fnotice (stdout, "No calls\n");
1419 /* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
1420 affect name generation. With preserve_paths we create a filename
1421 from all path components of the source file, replacing '/' with
1422 '#', without it we simply take the basename component. With
1423 long_output_names we prepend the processed name of the input file
1424 to each output name (except when the current source file is the
1425 input file, so you don't get a double concatenation). The two
1426 components are separated by '##'. Also '.' filename components are
1427 removed and '..' components are renamed to '^'. */
1429 static char *
1430 make_gcov_file_name (const char *input_name, const char *src_name)
1432 char *cptr;
1433 char *name = xmalloc (strlen (src_name) + strlen (input_name) + 10);
1435 name[0] = 0;
1436 if (flag_long_names && strcmp (src_name, input_name))
1438 /* Generate the input filename part. */
1439 cptr = flag_preserve_paths ? NULL : strrchr (input_name, '/');
1440 strcat (name, cptr ? cptr + 1 : input_name);
1441 strcat (name, "##");
1444 /* Generate the source filename part. */
1445 cptr = flag_preserve_paths ? NULL : strrchr (src_name, '/');
1446 strcat (name, cptr ? cptr + 1 : src_name);
1448 if (flag_preserve_paths)
1450 /* Convert '/' to '#', remove '/./', convert '/../' to '/^/' */
1451 char *prev;
1453 for (cptr = name; (cptr = strchr ((prev = cptr), '/'));)
1455 unsigned shift = 0;
1457 if (prev + 1 == cptr && prev[0] == '.')
1459 /* Remove '.' */
1460 shift = 2;
1462 else if (prev + 2 == cptr && prev[0] == '.' && prev[1] == '.')
1464 /* Convert '..' */
1465 shift = 1;
1466 prev[1] = '^';
1468 else
1469 *cptr++ = '#';
1470 if (shift)
1472 cptr = prev;
1474 prev[0] = prev[shift];
1475 while (*prev++);
1480 strcat (name, ".gcov");
1481 return name;
1484 /* Scan through the bb_data for each line in the block, increment
1485 the line number execution count indicated by the execution count of
1486 the appropriate basic block. */
1488 static void
1489 add_line_counts (coverage_t *coverage, function_t *fn)
1491 unsigned ix;
1492 line_t *line = NULL; /* This is propagated from one iteration to the
1493 next. */
1495 /* Scan each basic block. */
1496 for (ix = 0; ix != fn->num_blocks; ix++)
1498 block_t *block = &fn->blocks[ix];
1499 unsigned *encoding;
1500 const source_t *src = NULL;
1501 unsigned jx;
1503 if (block->count && ix && ix + 1 != fn->num_blocks)
1504 fn->blocks_executed++;
1505 for (jx = 0, encoding = block->u.line.encoding;
1506 jx != block->u.line.num; jx++, encoding++)
1507 if (!*encoding)
1509 unsigned src_n = *++encoding;
1511 for (src = sources; src->index != src_n; src = src->next)
1512 continue;
1513 jx++;
1515 else
1517 line = &src->lines[*encoding];
1519 if (coverage)
1521 if (!line->exists)
1522 coverage->lines++;
1523 if (!line->count && block->count)
1524 coverage->lines_executed++;
1526 line->exists = 1;
1527 line->count += block->count;
1529 free (block->u.line.encoding);
1530 block->u.cycle.arc = NULL;
1531 block->u.cycle.ident = ~0U;
1533 if (!ix || ix + 1 == fn->num_blocks)
1534 /* Entry or exit block */;
1535 else if (flag_all_blocks)
1537 line_t *block_line = line ? line : &fn->src->lines[fn->line];
1539 block->chain = block_line->u.blocks;
1540 block_line->u.blocks = block;
1542 else if (flag_branches)
1544 arc_t *arc;
1546 for (arc = block->succ; arc; arc = arc->succ_next)
1548 arc->line_next = line->u.branches;
1549 line->u.branches = arc;
1550 if (coverage && !arc->is_unconditional)
1551 add_branch_counts (coverage, arc);
1555 if (!line)
1556 fnotice (stderr, "%s:no lines for `%s'\n", bbg_file_name, fn->name);
1559 /* Accumulate the line counts of a file. */
1561 static void
1562 accumulate_line_counts (source_t *src)
1564 line_t *line;
1565 function_t *fn, *fn_p, *fn_n;
1566 unsigned ix;
1568 /* Reverse the function order. */
1569 for (fn = src->functions, fn_p = NULL; fn;
1570 fn_p = fn, fn = fn_n)
1572 fn_n = fn->line_next;
1573 fn->line_next = fn_p;
1575 src->functions = fn_p;
1577 for (ix = src->num_lines, line = src->lines; ix--; line++)
1579 if (!flag_all_blocks)
1581 arc_t *arc, *arc_p, *arc_n;
1583 /* Total and reverse the branch information. */
1584 for (arc = line->u.branches, arc_p = NULL; arc;
1585 arc_p = arc, arc = arc_n)
1587 arc_n = arc->line_next;
1588 arc->line_next = arc_p;
1590 add_branch_counts (&src->coverage, arc);
1592 line->u.branches = arc_p;
1594 else if (line->u.blocks)
1596 /* The user expects the line count to be the number of times
1597 a line has been executed. Simply summing the block count
1598 will give an artificially high number. The Right Thing
1599 is to sum the entry counts to the graph of blocks on this
1600 line, then find the elementary cycles of the local graph
1601 and add the transition counts of those cycles. */
1602 block_t *block, *block_p, *block_n;
1603 gcov_type count = 0;
1605 /* Reverse the block information. */
1606 for (block = line->u.blocks, block_p = NULL; block;
1607 block_p = block, block = block_n)
1609 block_n = block->chain;
1610 block->chain = block_p;
1611 block->u.cycle.ident = ix;
1613 line->u.blocks = block_p;
1615 /* Sum the entry arcs. */
1616 for (block = line->u.blocks; block; block = block->chain)
1618 arc_t *arc;
1620 for (arc = block->pred; arc; arc = arc->pred_next)
1622 if (arc->src->u.cycle.ident != ix)
1623 count += arc->count;
1624 if (flag_branches)
1625 add_branch_counts (&src->coverage, arc);
1628 /* Initialize the cs_count. */
1629 for (arc = block->succ; arc; arc = arc->succ_next)
1630 arc->cs_count = arc->count;
1633 /* Find the loops. This uses the algorithm described in
1634 Tiernan 'An Efficient Search Algorithm to Find the
1635 Elementary Circuits of a Graph', CACM Dec 1970. We hold
1636 the P array by having each block point to the arc that
1637 connects to the previous block. The H array is implicitly
1638 held because of the arc ordering, and the block's
1639 previous arc pointer.
1641 Although the algorithm is O(N^3) for highly connected
1642 graphs, at worst we'll have O(N^2), as most blocks have
1643 only one or two exits. Most graphs will be small.
1645 For each loop we find, locate the arc with the smallest
1646 transition count, and add that to the cumulative
1647 count. Decrease flow over the cycle and remove the arc
1648 from consideration. */
1649 for (block = line->u.blocks; block; block = block->chain)
1651 block_t *head = block;
1652 arc_t *arc;
1654 next_vertex:;
1655 arc = head->succ;
1656 current_vertex:;
1657 while (arc)
1659 block_t *dst = arc->dst;
1660 if (/* Already used that arc. */
1661 arc->cycle
1662 /* Not to same graph, or before first vertex. */
1663 || dst->u.cycle.ident != ix
1664 /* Already in path. */
1665 || dst->u.cycle.arc)
1667 arc = arc->succ_next;
1668 continue;
1671 if (dst == block)
1673 /* Found a closing arc. */
1674 gcov_type cycle_count = arc->cs_count;
1675 arc_t *cycle_arc = arc;
1676 arc_t *probe_arc;
1678 /* Locate the smallest arc count of the loop. */
1679 for (dst = head; (probe_arc = dst->u.cycle.arc);
1680 dst = probe_arc->src)
1681 if (cycle_count > probe_arc->cs_count)
1683 cycle_count = probe_arc->cs_count;
1684 cycle_arc = probe_arc;
1687 count += cycle_count;
1688 cycle_arc->cycle = 1;
1690 /* Remove the flow from the cycle. */
1691 arc->cs_count -= cycle_count;
1692 for (dst = head; (probe_arc = dst->u.cycle.arc);
1693 dst = probe_arc->src)
1694 probe_arc->cs_count -= cycle_count;
1696 /* Unwind to the cyclic arc. */
1697 while (head != cycle_arc->src)
1699 arc = head->u.cycle.arc;
1700 head->u.cycle.arc = NULL;
1701 head = arc->src;
1703 /* Move on. */
1704 arc = arc->succ_next;
1705 continue;
1708 /* Add new block to chain. */
1709 dst->u.cycle.arc = arc;
1710 head = dst;
1711 goto next_vertex;
1713 /* We could not add another vertex to the path. Remove
1714 the last vertex from the list. */
1715 arc = head->u.cycle.arc;
1716 if (arc)
1718 /* It was not the first vertex. Move onto next arc. */
1719 head->u.cycle.arc = NULL;
1720 head = arc->src;
1721 arc = arc->succ_next;
1722 goto current_vertex;
1724 /* Mark this block as unusable. */
1725 block->u.cycle.ident = ~0U;
1728 line->count = count;
1731 if (line->exists)
1733 src->coverage.lines++;
1734 if (line->count)
1735 src->coverage.lines_executed++;
1740 /* Ouput information about ARC number IX. Returns nonzero if
1741 anything is output. */
1743 static int
1744 output_branch_count (FILE *gcov_file, int ix, const arc_t *arc)
1747 if (arc->is_call_non_return)
1749 if (arc->src->count)
1751 fnotice (gcov_file, "call %2d returned %s\n", ix,
1752 format_gcov (arc->src->count - arc->count,
1753 arc->src->count, -flag_counts));
1755 else
1756 fnotice (gcov_file, "call %2d never executed\n", ix);
1758 else if (!arc->is_unconditional)
1760 if (arc->src->count)
1761 fnotice (gcov_file, "branch %2d taken %s%s\n", ix,
1762 format_gcov (arc->count, arc->src->count, -flag_counts),
1763 arc->fall_through ? " (fallthrough)" : "");
1764 else
1765 fnotice (gcov_file, "branch %2d never executed\n", ix);
1767 else if (flag_unconditional && !arc->dst->is_call_return)
1769 if (arc->src->count)
1770 fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
1771 format_gcov (arc->count, arc->src->count, -flag_counts));
1772 else
1773 fnotice (gcov_file, "unconditional %2d never executed\n", ix);
1775 else
1776 return 0;
1777 return 1;
1781 /* Read in the source file one line at a time, and output that line to
1782 the gcov file preceded by its execution count and other
1783 information. */
1785 static void
1786 output_lines (FILE *gcov_file, const source_t *src)
1788 FILE *source_file;
1789 unsigned line_num; /* current line number. */
1790 const line_t *line; /* current line info ptr. */
1791 char string[STRING_SIZE]; /* line buffer. */
1792 char const *retval = ""; /* status of source file reading. */
1793 function_t *fn = src->functions;
1795 fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->name);
1796 fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
1797 fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0, da_file_name);
1798 fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0,
1799 object_summary.ctrs[GCOV_COUNTER_ARCS].runs);
1800 fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
1802 source_file = fopen (src->name, "r");
1803 if (!source_file)
1805 fnotice (stderr, "%s:cannot open source file\n", src->name);
1806 retval = NULL;
1808 else
1810 struct stat status;
1812 if (!fstat (fileno (source_file), &status)
1813 && status.st_mtime > bbg_file_time)
1815 fnotice (stderr, "%s:source file is newer than graph file `%s'\n",
1816 src->name, bbg_file_name);
1817 fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n",
1818 "-", 0);
1822 for (line_num = 1, line = &src->lines[line_num];
1823 line_num < src->num_lines; line_num++, line++)
1825 for (; fn && fn->line == line_num; fn = fn->line_next)
1827 arc_t *arc = fn->blocks[fn->num_blocks - 1].pred;
1828 gcov_type return_count = fn->blocks[fn->num_blocks - 1].count;
1830 for (; arc; arc = arc->pred_next)
1831 if (arc->fake)
1832 return_count -= arc->count;
1834 fprintf (gcov_file, "function %s", fn->name);
1835 fprintf (gcov_file, " called %s",
1836 format_gcov (fn->blocks[0].count, 0, -1));
1837 fprintf (gcov_file, " returned %s",
1838 format_gcov (return_count, fn->blocks[0].count, 0));
1839 fprintf (gcov_file, " blocks executed %s",
1840 format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0));
1841 fprintf (gcov_file, "\n");
1844 /* For lines which don't exist in the .bb file, print '-' before
1845 the source line. For lines which exist but were never
1846 executed, print '#####' before the source line. Otherwise,
1847 print the execution count before the source line. There are
1848 16 spaces of indentation added before the source line so that
1849 tabs won't be messed up. */
1850 fprintf (gcov_file, "%9s:%5u:",
1851 !line->exists ? "-" : !line->count ? "#####"
1852 : format_gcov (line->count, 0, -1), line_num);
1854 if (retval)
1856 /* Copy source line. */
1859 retval = fgets (string, STRING_SIZE, source_file);
1860 if (!retval)
1861 break;
1862 fputs (retval, gcov_file);
1864 while (!retval[0] || retval[strlen (retval) - 1] != '\n');
1866 if (!retval)
1867 fputs ("/*EOF*/\n", gcov_file);
1869 if (flag_all_blocks)
1871 block_t *block;
1872 arc_t *arc;
1873 int ix, jx;
1875 for (ix = jx = 0, block = line->u.blocks; block;
1876 block = block->chain)
1878 if (!block->is_call_return)
1879 fprintf (gcov_file, "%9s:%5u-block %2d\n",
1880 !line->exists ? "-" : !block->count ? "$$$$$"
1881 : format_gcov (block->count, 0, -1),
1882 line_num, ix++);
1883 if (flag_branches)
1884 for (arc = block->succ; arc; arc = arc->succ_next)
1885 jx += output_branch_count (gcov_file, jx, arc);
1888 else if (flag_branches)
1890 int ix;
1891 arc_t *arc;
1893 for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
1894 ix += output_branch_count (gcov_file, ix, arc);
1898 /* Handle all remaining source lines. There may be lines after the
1899 last line of code. */
1900 if (retval)
1902 for (; (retval = fgets (string, STRING_SIZE, source_file)); line_num++)
1904 fprintf (gcov_file, "%9s:%5u:%s", "-", line_num, retval);
1906 while (!retval[0] || retval[strlen (retval) - 1] != '\n')
1908 retval = fgets (string, STRING_SIZE, source_file);
1909 if (!retval)
1910 break;
1911 fputs (retval, gcov_file);
1916 if (source_file)
1917 fclose (source_file);