2006-08-06 Paolo Carlini <pcarlini@suse.de>
[official-gcc.git] / gcc / gcov.c
blobd8cc9bd0927dd32a08ffe297d131a9a9457338e4
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 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, 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA. */
24 /* ??? Print a list of the ten blocks with the highest execution counts,
25 and list the line numbers corresponding to those blocks. Also, perhaps
26 list the line numbers with the highest execution counts, only printing
27 the first if there are several which are all listed in the same block. */
29 /* ??? Should have an option to print the number of basic blocks, and the
30 percent of them that are covered. */
32 /* ??? Does not correctly handle the case where two .bb files refer to
33 the same included source file. For example, if one has a short
34 file containing only inline functions, which is then included in
35 two other files, then there will be two .bb files which refer to
36 the include file, but there is no way to get the total execution
37 counts for the included file, can only get execution counts for one
38 or the other of the including files. this can be fixed by --ratios
39 --long-file-names --preserve-paths and perl. */
41 /* Need an option to show individual block counts, and show
42 probabilities of fall through arcs. */
44 #include "config.h"
45 #include "system.h"
46 #include "coretypes.h"
47 #include "tm.h"
48 #include "intl.h"
49 #include "version.h"
51 #include <getopt.h>
53 #define IN_GCOV 1
54 #include "gcov-io.h"
55 #include "gcov-io.c"
57 /* The bbg file is generated by -ftest-coverage option. The da file is
58 generated by a program compiled with -fprofile-arcs. Their formats
59 are documented in gcov-io.h. */
61 /* The functions in this file for creating and solution program flow graphs
62 are very similar to functions in the gcc source file profile.c. In
63 some places we make use of the knowledge of how profile.c works to
64 select particular algorithms here. */
66 /* This is the size of the buffer used to read in source file lines. */
68 #define STRING_SIZE 200
70 struct function_info;
71 struct block_info;
72 struct source_info;
74 /* Describes an arc between two basic blocks. */
76 typedef struct arc_info
78 /* source and destination blocks. */
79 struct block_info *src;
80 struct block_info *dst;
82 /* transition counts. */
83 gcov_type count;
84 /* used in cycle search, so that we do not clobber original counts. */
85 gcov_type cs_count;
87 unsigned int count_valid : 1;
88 unsigned int on_tree : 1;
89 unsigned int fake : 1;
90 unsigned int fall_through : 1;
92 /* Arc is for a function that abnormally returns. */
93 unsigned int is_call_non_return : 1;
95 /* Arc is for catch/setjump. */
96 unsigned int is_nonlocal_return : 1;
98 /* Is an unconditional branch. */
99 unsigned int is_unconditional : 1;
101 /* Loop making arc. */
102 unsigned int cycle : 1;
104 /* Next branch on line. */
105 struct arc_info *line_next;
107 /* Links to next arc on src and dst lists. */
108 struct arc_info *succ_next;
109 struct arc_info *pred_next;
110 } arc_t;
112 /* Describes a basic block. Contains lists of arcs to successor and
113 predecessor blocks. */
115 typedef struct block_info
117 /* Chain of exit and entry arcs. */
118 arc_t *succ;
119 arc_t *pred;
121 /* Number of unprocessed exit and entry arcs. */
122 gcov_type num_succ;
123 gcov_type num_pred;
125 /* Block execution count. */
126 gcov_type count;
127 unsigned flags : 13;
128 unsigned count_valid : 1;
129 unsigned valid_chain : 1;
130 unsigned invalid_chain : 1;
132 /* Block is a call instrumenting site. */
133 unsigned is_call_site : 1; /* Does the call. */
134 unsigned is_call_return : 1; /* Is the return. */
136 /* Block is a landing pad for longjmp or throw. */
137 unsigned is_nonlocal_return : 1;
139 union
141 struct
143 /* Array of line numbers and source files. source files are
144 introduced by a linenumber of zero, the next 'line number' is
145 the number of the source file. Always starts with a source
146 file. */
147 unsigned *encoding;
148 unsigned num;
149 } line; /* Valid until blocks are linked onto lines */
150 struct
152 /* Single line graph cycle workspace. Used for all-blocks
153 mode. */
154 arc_t *arc;
155 unsigned ident;
156 } cycle; /* Used in all-blocks mode, after blocks are linked onto
157 lines. */
158 } u;
160 /* Temporary chain for solving graph, and for chaining blocks on one
161 line. */
162 struct block_info *chain;
164 } block_t;
166 /* Describes a single function. Contains an array of basic blocks. */
168 typedef struct function_info
170 /* Name of function. */
171 char *name;
172 unsigned ident;
173 unsigned checksum;
175 /* Array of basic blocks. */
176 block_t *blocks;
177 unsigned num_blocks;
178 unsigned blocks_executed;
180 /* Raw arc coverage counts. */
181 gcov_type *counts;
182 unsigned num_counts;
184 /* First line number. */
185 unsigned line;
186 struct source_info *src;
188 /* Next function in same source file. */
189 struct function_info *line_next;
191 /* Next function. */
192 struct function_info *next;
193 } function_t;
195 /* Describes coverage of a file or function. */
197 typedef struct coverage_info
199 int lines;
200 int lines_executed;
202 int branches;
203 int branches_executed;
204 int branches_taken;
206 int calls;
207 int calls_executed;
209 char *name;
210 } coverage_t;
212 /* Describes a single line of source. Contains a chain of basic blocks
213 with code on it. */
215 typedef struct line_info
217 gcov_type count; /* execution count */
218 union
220 arc_t *branches; /* branches from blocks that end on this
221 line. Used for branch-counts when not
222 all-blocks mode. */
223 block_t *blocks; /* blocks which start on this line. Used
224 in all-blocks mode. */
225 } u;
226 unsigned exists : 1;
227 } line_t;
229 /* Describes a file mentioned in the block graph. Contains an array
230 of line info. */
232 typedef struct source_info
234 /* Name of source file. */
235 char *name;
236 unsigned index;
238 /* Array of line information. */
239 line_t *lines;
240 unsigned num_lines;
242 coverage_t coverage;
244 /* Functions in this source file. These are in ascending line
245 number order. */
246 function_t *functions;
248 /* Next source file. */
249 struct source_info *next;
250 } source_t;
252 /* Holds a list of function basic block graphs. */
254 static function_t *functions;
256 /* This points to the head of the sourcefile structure list. */
258 static source_t *sources;
260 /* This holds data summary information. */
262 static struct gcov_summary object_summary;
263 static unsigned program_count;
265 /* Modification time of graph file. */
267 static time_t bbg_file_time;
269 /* Name and file pointer of the input file for the basic block graph. */
271 static char *bbg_file_name;
273 /* Stamp of the bbg file */
274 static unsigned bbg_stamp;
276 /* Name and file pointer of the input file for the arc count data. */
278 static char *da_file_name;
280 /* Output branch probabilities. */
282 static int flag_branches = 0;
284 /* Show unconditional branches too. */
285 static int flag_unconditional = 0;
287 /* Output a gcov file if this is true. This is on by default, and can
288 be turned off by the -n option. */
290 static int flag_gcov_file = 1;
292 /* For included files, make the gcov output file name include the name
293 of the input source file. For example, if x.h is included in a.c,
294 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
296 static int flag_long_names = 0;
298 /* Output count information for every basic block, not merely those
299 that contain line number information. */
301 static int flag_all_blocks = 0;
303 /* Output summary info for each function. */
305 static int flag_function_summary = 0;
307 /* Object directory file prefix. This is the directory/file where the
308 graph and data files are looked for, if nonzero. */
310 static char *object_directory = 0;
312 /* Preserve all pathname components. Needed when object files and
313 source files are in subdirectories. '/' is mangled as '#', '.' is
314 elided and '..' mangled to '^'. */
316 static int flag_preserve_paths = 0;
318 /* Output the number of times a branch was taken as opposed to the percentage
319 of times it was taken. */
321 static int flag_counts = 0;
323 /* Forward declarations. */
324 static void fnotice (FILE *, const char *, ...) ATTRIBUTE_PRINTF_2;
325 static int process_args (int, char **);
326 static void print_usage (int) ATTRIBUTE_NORETURN;
327 static void print_version (void) ATTRIBUTE_NORETURN;
328 static void process_file (const char *);
329 static void create_file_names (const char *);
330 static source_t *find_source (const char *);
331 static int read_graph_file (void);
332 static int read_count_file (void);
333 static void solve_flow_graph (function_t *);
334 static void add_branch_counts (coverage_t *, const arc_t *);
335 static void add_line_counts (coverage_t *, function_t *);
336 static void function_summary (const coverage_t *, const char *);
337 static const char *format_gcov (gcov_type, gcov_type, int);
338 static void accumulate_line_counts (source_t *);
339 static int output_branch_count (FILE *, int, const arc_t *);
340 static void output_lines (FILE *, const source_t *);
341 static char *make_gcov_file_name (const char *, const char *);
342 static void release_structures (void);
343 extern int main (int, char **);
346 main (int argc, char **argv)
348 int argno;
350 /* Unlock the stdio streams. */
351 unlock_std_streams ();
353 gcc_init_libintl ();
355 argno = process_args (argc, argv);
356 if (optind == argc)
357 print_usage (true);
359 for (; argno != argc; argno++)
361 release_structures ();
363 process_file (argv[argno]);
366 return 0;
369 static void
370 fnotice (FILE *file, const char *cmsgid, ...)
372 va_list ap;
374 va_start (ap, cmsgid);
375 vfprintf (file, _(cmsgid), ap);
376 va_end (ap);
379 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
380 otherwise the output of --help. */
382 static void
383 print_usage (int error_p)
385 FILE *file = error_p ? stderr : stdout;
386 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
388 fnotice (file, "Usage: gcov [OPTION]... SOURCEFILE\n\n");
389 fnotice (file, "Print code coverage information.\n\n");
390 fnotice (file, " -h, --help Print this help, then exit\n");
391 fnotice (file, " -v, --version Print version number, then exit\n");
392 fnotice (file, " -a, --all-blocks Show information for every basic block\n");
393 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
394 fnotice (file, " -c, --branch-counts Given counts of branches taken\n\
395 rather than percentages\n");
396 fnotice (file, " -n, --no-output Do not create an output file\n");
397 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
398 source files\n");
399 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
400 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
401 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
402 fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
403 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
404 bug_report_url);
405 exit (status);
408 /* Print version information and exit. */
410 static void
411 print_version (void)
413 fnotice (stdout, "gcov (GCC) %s\n", version_string);
414 fprintf (stdout, "Copyright %s 2006 Free Software Foundation, Inc.\n",
415 _("(C)"));
416 fnotice (stdout,
417 _("This is free software; see the source for copying conditions.\n"
418 "There is NO warranty; not even for MERCHANTABILITY or \n"
419 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
420 exit (SUCCESS_EXIT_CODE);
423 static const struct option options[] =
425 { "help", no_argument, NULL, 'h' },
426 { "version", no_argument, NULL, 'v' },
427 { "all-blocks", no_argument, NULL, 'a' },
428 { "branch-probabilities", no_argument, NULL, 'b' },
429 { "branch-counts", no_argument, NULL, 'c' },
430 { "no-output", no_argument, NULL, 'n' },
431 { "long-file-names", no_argument, NULL, 'l' },
432 { "function-summaries", no_argument, NULL, 'f' },
433 { "preserve-paths", no_argument, NULL, 'p' },
434 { "object-directory", required_argument, NULL, 'o' },
435 { "object-file", required_argument, NULL, 'o' },
436 { "unconditional-branches", no_argument, NULL, 'u' },
437 { 0, 0, 0, 0 }
440 /* Process args, return index to first non-arg. */
442 static int
443 process_args (int argc, char **argv)
445 int opt;
447 while ((opt = getopt_long (argc, argv, "abcfhlno:puv", options, NULL)) != -1)
449 switch (opt)
451 case 'a':
452 flag_all_blocks = 1;
453 break;
454 case 'b':
455 flag_branches = 1;
456 break;
457 case 'c':
458 flag_counts = 1;
459 break;
460 case 'f':
461 flag_function_summary = 1;
462 break;
463 case 'h':
464 print_usage (false);
465 /* print_usage will exit. */
466 case 'l':
467 flag_long_names = 1;
468 break;
469 case 'n':
470 flag_gcov_file = 0;
471 break;
472 case 'o':
473 object_directory = optarg;
474 break;
475 case 'p':
476 flag_preserve_paths = 1;
477 break;
478 case 'u':
479 flag_unconditional = 1;
480 break;
481 case 'v':
482 print_version ();
483 /* print_version will exit. */
484 default:
485 print_usage (true);
486 /* print_usage will exit. */
490 return optind;
493 /* Process a single source file. */
495 static void
496 process_file (const char *file_name)
498 source_t *src;
499 function_t *fn;
501 create_file_names (file_name);
502 if (read_graph_file ())
503 return;
505 if (!functions)
507 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
508 return;
511 if (read_count_file ())
512 return;
514 for (fn = functions; fn; fn = fn->next)
515 solve_flow_graph (fn);
516 for (src = sources; src; src = src->next)
517 src->lines = XCNEWVEC (line_t, src->num_lines);
518 for (fn = functions; fn; fn = fn->next)
520 coverage_t coverage;
522 memset (&coverage, 0, sizeof (coverage));
523 coverage.name = fn->name;
524 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
525 if (flag_function_summary)
527 function_summary (&coverage, "Function");
528 fnotice (stdout, "\n");
532 for (src = sources; src; src = src->next)
534 accumulate_line_counts (src);
535 function_summary (&src->coverage, "File");
536 if (flag_gcov_file)
538 char *gcov_file_name = make_gcov_file_name (file_name, src->name);
539 FILE *gcov_file = fopen (gcov_file_name, "w");
541 if (gcov_file)
543 fnotice (stdout, "%s:creating '%s'\n",
544 src->name, gcov_file_name);
545 output_lines (gcov_file, src);
546 if (ferror (gcov_file))
547 fnotice (stderr, "%s:error writing output file '%s'\n",
548 src->name, gcov_file_name);
549 fclose (gcov_file);
551 else
552 fnotice (stderr, "%s:could not open output file '%s'\n",
553 src->name, gcov_file_name);
554 free (gcov_file_name);
556 fnotice (stdout, "\n");
560 /* Release all memory used. */
562 static void
563 release_structures (void)
565 function_t *fn;
566 source_t *src;
568 free (bbg_file_name);
569 free (da_file_name);
570 da_file_name = bbg_file_name = NULL;
571 bbg_file_time = 0;
572 bbg_stamp = 0;
574 while ((src = sources))
576 sources = src->next;
578 free (src->name);
579 free (src->lines);
582 while ((fn = functions))
584 unsigned ix;
585 block_t *block;
587 functions = fn->next;
588 for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
590 arc_t *arc, *arc_n;
592 for (arc = block->succ; arc; arc = arc_n)
594 arc_n = arc->succ_next;
595 free (arc);
598 free (fn->blocks);
599 free (fn->counts);
603 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
604 is not specified, these are looked for in the current directory,
605 and named from the basename of the FILE_NAME sans extension. If
606 OBJECT_DIRECTORY is specified and is a directory, the files are in
607 that directory, but named from the basename of the FILE_NAME, sans
608 extension. Otherwise OBJECT_DIRECTORY is taken to be the name of
609 the object *file*, and the data files are named from that. */
611 static void
612 create_file_names (const char *file_name)
614 char *cptr;
615 char *name;
616 int length = strlen (file_name);
617 int base;
619 if (object_directory && object_directory[0])
621 struct stat status;
623 length += strlen (object_directory) + 2;
624 name = XNEWVEC (char, length);
625 name[0] = 0;
627 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
628 strcat (name, object_directory);
629 if (base && name[strlen (name) - 1] != '/')
630 strcat (name, "/");
632 else
634 name = XNEWVEC (char, length + 1);
635 name[0] = 0;
636 base = 1;
639 if (base)
641 /* Append source file name. */
642 cptr = strrchr (file_name, '/');
643 strcat (name, cptr ? cptr + 1 : file_name);
646 /* Remove the extension. */
647 cptr = strrchr (name, '.');
648 if (cptr)
649 *cptr = 0;
651 length = strlen (name);
653 bbg_file_name = XNEWVEC (char, length + strlen (GCOV_NOTE_SUFFIX) + 1);
654 strcpy (bbg_file_name, name);
655 strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
657 da_file_name = XNEWVEC (char, length + strlen (GCOV_DATA_SUFFIX) + 1);
658 strcpy (da_file_name, name);
659 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
661 free (name);
662 return;
665 /* Find or create a source file structure for FILE_NAME. Copies
666 FILE_NAME on creation */
668 static source_t *
669 find_source (const char *file_name)
671 source_t *src;
673 if (!file_name)
674 file_name = "<unknown>";
676 for (src = sources; src; src = src->next)
677 if (!strcmp (file_name, src->name))
678 return src;
680 src = XCNEW (source_t);
681 src->name = xstrdup (file_name);
682 src->coverage.name = src->name;
683 src->index = sources ? sources->index + 1 : 1;
684 src->next = sources;
685 sources = src;
687 return src;
690 /* Read the graph file. Return nonzero on fatal error. */
692 static int
693 read_graph_file (void)
695 unsigned version;
696 unsigned current_tag = 0;
697 struct function_info *fn = NULL;
698 source_t *src = NULL;
699 unsigned ix;
700 unsigned tag;
702 if (!gcov_open (bbg_file_name, 1))
704 fnotice (stderr, "%s:cannot open graph file\n", bbg_file_name);
705 return 1;
707 bbg_file_time = gcov_time ();
708 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
710 fnotice (stderr, "%s:not a gcov graph file\n", bbg_file_name);
711 gcov_close ();
712 return 1;
715 version = gcov_read_unsigned ();
716 if (version != GCOV_VERSION)
718 char v[4], e[4];
720 GCOV_UNSIGNED2STRING (v, version);
721 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
723 fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n",
724 bbg_file_name, v, e);
726 bbg_stamp = gcov_read_unsigned ();
728 while ((tag = gcov_read_unsigned ()))
730 unsigned length = gcov_read_unsigned ();
731 gcov_position_t base = gcov_position ();
733 if (tag == GCOV_TAG_FUNCTION)
735 char *function_name;
736 unsigned ident, checksum, lineno;
737 source_t *src;
738 function_t *probe, *prev;
740 ident = gcov_read_unsigned ();
741 checksum = gcov_read_unsigned ();
742 function_name = xstrdup (gcov_read_string ());
743 src = find_source (gcov_read_string ());
744 lineno = gcov_read_unsigned ();
746 fn = XCNEW (function_t);
747 fn->name = function_name;
748 fn->ident = ident;
749 fn->checksum = checksum;
750 fn->src = src;
751 fn->line = lineno;
753 fn->next = functions;
754 functions = fn;
755 current_tag = tag;
757 if (lineno >= src->num_lines)
758 src->num_lines = lineno + 1;
759 /* Now insert it into the source file's list of
760 functions. Normally functions will be encountered in
761 ascending order, so a simple scan is quick. */
762 for (probe = src->functions, prev = NULL;
763 probe && probe->line > lineno;
764 prev = probe, probe = probe->line_next)
765 continue;
766 fn->line_next = probe;
767 if (prev)
768 prev->line_next = fn;
769 else
770 src->functions = fn;
772 else if (fn && tag == GCOV_TAG_BLOCKS)
774 if (fn->blocks)
775 fnotice (stderr, "%s:already seen blocks for '%s'\n",
776 bbg_file_name, fn->name);
777 else
779 unsigned ix, num_blocks = GCOV_TAG_BLOCKS_NUM (length);
780 fn->num_blocks = num_blocks;
782 fn->blocks = XCNEWVEC (block_t, fn->num_blocks);
783 for (ix = 0; ix != num_blocks; ix++)
784 fn->blocks[ix].flags = gcov_read_unsigned ();
787 else if (fn && tag == GCOV_TAG_ARCS)
789 unsigned src = gcov_read_unsigned ();
790 unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
792 if (src >= fn->num_blocks || fn->blocks[src].succ)
793 goto corrupt;
795 while (num_dests--)
797 struct arc_info *arc;
798 unsigned dest = gcov_read_unsigned ();
799 unsigned flags = gcov_read_unsigned ();
801 if (dest >= fn->num_blocks)
802 goto corrupt;
803 arc = XCNEW (arc_t);
805 arc->dst = &fn->blocks[dest];
806 arc->src = &fn->blocks[src];
808 arc->count = 0;
809 arc->count_valid = 0;
810 arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
811 arc->fake = !!(flags & GCOV_ARC_FAKE);
812 arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
814 arc->succ_next = fn->blocks[src].succ;
815 fn->blocks[src].succ = arc;
816 fn->blocks[src].num_succ++;
818 arc->pred_next = fn->blocks[dest].pred;
819 fn->blocks[dest].pred = arc;
820 fn->blocks[dest].num_pred++;
822 if (arc->fake)
824 if (src)
826 /* Exceptional exit from this function, the
827 source block must be a call. */
828 fn->blocks[src].is_call_site = 1;
829 arc->is_call_non_return = 1;
831 else
833 /* Non-local return from a callee of this
834 function. The destination block is a catch or
835 setjmp. */
836 arc->is_nonlocal_return = 1;
837 fn->blocks[dest].is_nonlocal_return = 1;
841 if (!arc->on_tree)
842 fn->num_counts++;
845 else if (fn && tag == GCOV_TAG_LINES)
847 unsigned blockno = gcov_read_unsigned ();
848 unsigned *line_nos = XCNEWVEC (unsigned, length - 1);
850 if (blockno >= fn->num_blocks || fn->blocks[blockno].u.line.encoding)
851 goto corrupt;
853 for (ix = 0; ; )
855 unsigned lineno = gcov_read_unsigned ();
857 if (lineno)
859 if (!ix)
861 line_nos[ix++] = 0;
862 line_nos[ix++] = src->index;
864 line_nos[ix++] = lineno;
865 if (lineno >= src->num_lines)
866 src->num_lines = lineno + 1;
868 else
870 const char *file_name = gcov_read_string ();
872 if (!file_name)
873 break;
874 src = find_source (file_name);
876 line_nos[ix++] = 0;
877 line_nos[ix++] = src->index;
881 fn->blocks[blockno].u.line.encoding = line_nos;
882 fn->blocks[blockno].u.line.num = ix;
884 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
886 fn = NULL;
887 current_tag = 0;
889 gcov_sync (base, length);
890 if (gcov_is_error ())
892 corrupt:;
893 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
894 gcov_close ();
895 return 1;
898 gcov_close ();
900 /* We built everything backwards, so nreverse them all. */
902 /* Reverse sources. Not strictly necessary, but we'll then process
903 them in the 'expected' order. */
905 source_t *src, *src_p, *src_n;
907 for (src_p = NULL, src = sources; src; src_p = src, src = src_n)
909 src_n = src->next;
910 src->next = src_p;
912 sources = src_p;
915 /* Reverse functions. */
917 function_t *fn, *fn_p, *fn_n;
919 for (fn_p = NULL, fn = functions; fn; fn_p = fn, fn = fn_n)
921 unsigned ix;
923 fn_n = fn->next;
924 fn->next = fn_p;
926 /* Reverse the arcs. */
927 for (ix = fn->num_blocks; ix--;)
929 arc_t *arc, *arc_p, *arc_n;
931 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
932 arc_p = arc, arc = arc_n)
934 arc_n = arc->succ_next;
935 arc->succ_next = arc_p;
937 fn->blocks[ix].succ = arc_p;
939 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
940 arc_p = arc, arc = arc_n)
942 arc_n = arc->pred_next;
943 arc->pred_next = arc_p;
945 fn->blocks[ix].pred = arc_p;
948 functions = fn_p;
950 return 0;
953 /* Reads profiles from the count file and attach to each
954 function. Return nonzero if fatal error. */
956 static int
957 read_count_file (void)
959 unsigned ix;
960 unsigned version;
961 unsigned tag;
962 function_t *fn = NULL;
963 int error = 0;
965 if (!gcov_open (da_file_name, 1))
967 fnotice (stderr, "%s:cannot open data file\n", da_file_name);
968 return 1;
970 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
972 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
973 cleanup:;
974 gcov_close ();
975 return 1;
977 version = gcov_read_unsigned ();
978 if (version != GCOV_VERSION)
980 char v[4], e[4];
982 GCOV_UNSIGNED2STRING (v, version);
983 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
985 fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
986 da_file_name, v, e);
988 tag = gcov_read_unsigned ();
989 if (tag != bbg_stamp)
991 fnotice (stderr, "%s:stamp mismatch with graph file\n", da_file_name);
992 goto cleanup;
995 while ((tag = gcov_read_unsigned ()))
997 unsigned length = gcov_read_unsigned ();
998 unsigned long base = gcov_position ();
1000 if (tag == GCOV_TAG_OBJECT_SUMMARY)
1001 gcov_read_summary (&object_summary);
1002 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
1003 program_count++;
1004 else if (tag == GCOV_TAG_FUNCTION)
1006 unsigned ident = gcov_read_unsigned ();
1007 struct function_info *fn_n = functions;
1009 for (fn = fn ? fn->next : NULL; ; fn = fn->next)
1011 if (fn)
1013 else if ((fn = fn_n))
1014 fn_n = NULL;
1015 else
1017 fnotice (stderr, "%s:unknown function '%u'\n",
1018 da_file_name, ident);
1019 break;
1021 if (fn->ident == ident)
1022 break;
1025 if (!fn)
1027 else if (gcov_read_unsigned () != fn->checksum)
1029 mismatch:;
1030 fnotice (stderr, "%s:profile mismatch for '%s'\n",
1031 da_file_name, fn->name);
1032 goto cleanup;
1035 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
1037 if (length != GCOV_TAG_COUNTER_LENGTH (fn->num_counts))
1038 goto mismatch;
1040 if (!fn->counts)
1041 fn->counts = XCNEWVEC (gcov_type, fn->num_counts);
1043 for (ix = 0; ix != fn->num_counts; ix++)
1044 fn->counts[ix] += gcov_read_counter ();
1046 gcov_sync (base, length);
1047 if ((error = gcov_is_error ()))
1049 fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1050 da_file_name);
1051 goto cleanup;
1055 gcov_close ();
1056 return 0;
1059 /* Solve the flow graph. Propagate counts from the instrumented arcs
1060 to the blocks and the uninstrumented arcs. */
1062 static void
1063 solve_flow_graph (function_t *fn)
1065 unsigned ix;
1066 arc_t *arc;
1067 gcov_type *count_ptr = fn->counts;
1068 block_t *blk;
1069 block_t *valid_blocks = NULL; /* valid, but unpropagated blocks. */
1070 block_t *invalid_blocks = NULL; /* invalid, but inferable blocks. */
1072 if (fn->num_blocks < 2)
1073 fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n",
1074 bbg_file_name, fn->name);
1075 else
1077 if (fn->blocks[0].num_pred)
1078 fnotice (stderr, "%s:'%s' has arcs to entry block\n",
1079 bbg_file_name, fn->name);
1080 else
1081 /* We can't deduce the entry block counts from the lack of
1082 predecessors. */
1083 fn->blocks[0].num_pred = ~(unsigned)0;
1085 if (fn->blocks[fn->num_blocks - 1].num_succ)
1086 fnotice (stderr, "%s:'%s' has arcs from exit block\n",
1087 bbg_file_name, fn->name);
1088 else
1089 /* Likewise, we can't deduce exit block counts from the lack
1090 of its successors. */
1091 fn->blocks[fn->num_blocks - 1].num_succ = ~(unsigned)0;
1094 /* Propagate the measured counts, this must be done in the same
1095 order as the code in profile.c */
1096 for (ix = 0, blk = fn->blocks; ix != fn->num_blocks; ix++, blk++)
1098 block_t const *prev_dst = NULL;
1099 int out_of_order = 0;
1100 int non_fake_succ = 0;
1102 for (arc = blk->succ; arc; arc = arc->succ_next)
1104 if (!arc->fake)
1105 non_fake_succ++;
1107 if (!arc->on_tree)
1109 if (count_ptr)
1110 arc->count = *count_ptr++;
1111 arc->count_valid = 1;
1112 blk->num_succ--;
1113 arc->dst->num_pred--;
1115 if (prev_dst && prev_dst > arc->dst)
1116 out_of_order = 1;
1117 prev_dst = arc->dst;
1119 if (non_fake_succ == 1)
1121 /* If there is only one non-fake exit, it is an
1122 unconditional branch. */
1123 for (arc = blk->succ; arc; arc = arc->succ_next)
1124 if (!arc->fake)
1126 arc->is_unconditional = 1;
1127 /* If this block is instrumenting a call, it might be
1128 an artificial block. It is not artificial if it has
1129 a non-fallthrough exit, or the destination of this
1130 arc has more than one entry. Mark the destination
1131 block as a return site, if none of those conditions
1132 hold. */
1133 if (blk->is_call_site && arc->fall_through
1134 && arc->dst->pred == arc && !arc->pred_next)
1135 arc->dst->is_call_return = 1;
1139 /* Sort the successor arcs into ascending dst order. profile.c
1140 normally produces arcs in the right order, but sometimes with
1141 one or two out of order. We're not using a particularly
1142 smart sort. */
1143 if (out_of_order)
1145 arc_t *start = blk->succ;
1146 unsigned changes = 1;
1148 while (changes)
1150 arc_t *arc, *arc_p, *arc_n;
1152 changes = 0;
1153 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1155 if (arc->dst > arc_n->dst)
1157 changes = 1;
1158 if (arc_p)
1159 arc_p->succ_next = arc_n;
1160 else
1161 start = arc_n;
1162 arc->succ_next = arc_n->succ_next;
1163 arc_n->succ_next = arc;
1164 arc_p = arc_n;
1166 else
1168 arc_p = arc;
1169 arc = arc_n;
1173 blk->succ = start;
1176 /* Place it on the invalid chain, it will be ignored if that's
1177 wrong. */
1178 blk->invalid_chain = 1;
1179 blk->chain = invalid_blocks;
1180 invalid_blocks = blk;
1183 while (invalid_blocks || valid_blocks)
1185 while ((blk = invalid_blocks))
1187 gcov_type total = 0;
1188 const arc_t *arc;
1190 invalid_blocks = blk->chain;
1191 blk->invalid_chain = 0;
1192 if (!blk->num_succ)
1193 for (arc = blk->succ; arc; arc = arc->succ_next)
1194 total += arc->count;
1195 else if (!blk->num_pred)
1196 for (arc = blk->pred; arc; arc = arc->pred_next)
1197 total += arc->count;
1198 else
1199 continue;
1201 blk->count = total;
1202 blk->count_valid = 1;
1203 blk->chain = valid_blocks;
1204 blk->valid_chain = 1;
1205 valid_blocks = blk;
1207 while ((blk = valid_blocks))
1209 gcov_type total;
1210 arc_t *arc, *inv_arc;
1212 valid_blocks = blk->chain;
1213 blk->valid_chain = 0;
1214 if (blk->num_succ == 1)
1216 block_t *dst;
1218 total = blk->count;
1219 inv_arc = NULL;
1220 for (arc = blk->succ; arc; arc = arc->succ_next)
1222 total -= arc->count;
1223 if (!arc->count_valid)
1224 inv_arc = arc;
1226 dst = inv_arc->dst;
1227 inv_arc->count_valid = 1;
1228 inv_arc->count = total;
1229 blk->num_succ--;
1230 dst->num_pred--;
1231 if (dst->count_valid)
1233 if (dst->num_pred == 1 && !dst->valid_chain)
1235 dst->chain = valid_blocks;
1236 dst->valid_chain = 1;
1237 valid_blocks = dst;
1240 else
1242 if (!dst->num_pred && !dst->invalid_chain)
1244 dst->chain = invalid_blocks;
1245 dst->invalid_chain = 1;
1246 invalid_blocks = dst;
1250 if (blk->num_pred == 1)
1252 block_t *src;
1254 total = blk->count;
1255 inv_arc = NULL;
1256 for (arc = blk->pred; arc; arc = arc->pred_next)
1258 total -= arc->count;
1259 if (!arc->count_valid)
1260 inv_arc = arc;
1262 src = inv_arc->src;
1263 inv_arc->count_valid = 1;
1264 inv_arc->count = total;
1265 blk->num_pred--;
1266 src->num_succ--;
1267 if (src->count_valid)
1269 if (src->num_succ == 1 && !src->valid_chain)
1271 src->chain = valid_blocks;
1272 src->valid_chain = 1;
1273 valid_blocks = src;
1276 else
1278 if (!src->num_succ && !src->invalid_chain)
1280 src->chain = invalid_blocks;
1281 src->invalid_chain = 1;
1282 invalid_blocks = src;
1289 /* If the graph has been correctly solved, every block will have a
1290 valid count. */
1291 for (ix = 0; ix < fn->num_blocks; ix++)
1292 if (!fn->blocks[ix].count_valid)
1294 fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
1295 bbg_file_name, fn->name);
1296 break;
1302 /* Increment totals in COVERAGE according to arc ARC. */
1304 static void
1305 add_branch_counts (coverage_t *coverage, const arc_t *arc)
1307 if (arc->is_call_non_return)
1309 coverage->calls++;
1310 if (arc->src->count)
1311 coverage->calls_executed++;
1313 else if (!arc->is_unconditional)
1315 coverage->branches++;
1316 if (arc->src->count)
1317 coverage->branches_executed++;
1318 if (arc->count)
1319 coverage->branches_taken++;
1323 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1324 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1325 If DP is zero, no decimal point is printed. Only print 100% when
1326 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1327 format TOP. Return pointer to a static string. */
1329 static char const *
1330 format_gcov (gcov_type top, gcov_type bottom, int dp)
1332 static char buffer[20];
1334 if (dp >= 0)
1336 float ratio = bottom ? (float)top / bottom : 0;
1337 int ix;
1338 unsigned limit = 100;
1339 unsigned percent;
1341 for (ix = dp; ix--; )
1342 limit *= 10;
1344 percent = (unsigned) (ratio * limit + (float)0.5);
1345 if (percent <= 0 && top)
1346 percent = 1;
1347 else if (percent >= limit && top != bottom)
1348 percent = limit - 1;
1349 ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1350 if (dp)
1352 dp++;
1355 buffer[ix+1] = buffer[ix];
1356 ix--;
1358 while (dp--);
1359 buffer[ix + 1] = '.';
1362 else
1363 sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)top);
1365 return buffer;
1369 /* Output summary info for a function. */
1371 static void
1372 function_summary (const coverage_t *coverage, const char *title)
1374 fnotice (stdout, "%s '%s'\n", title, coverage->name);
1376 if (coverage->lines)
1377 fnotice (stdout, "Lines executed:%s of %d\n",
1378 format_gcov (coverage->lines_executed, coverage->lines, 2),
1379 coverage->lines);
1380 else
1381 fnotice (stdout, "No executable lines\n");
1383 if (flag_branches)
1385 if (coverage->branches)
1387 fnotice (stdout, "Branches executed:%s of %d\n",
1388 format_gcov (coverage->branches_executed,
1389 coverage->branches, 2),
1390 coverage->branches);
1391 fnotice (stdout, "Taken at least once:%s of %d\n",
1392 format_gcov (coverage->branches_taken,
1393 coverage->branches, 2),
1394 coverage->branches);
1396 else
1397 fnotice (stdout, "No branches\n");
1398 if (coverage->calls)
1399 fnotice (stdout, "Calls executed:%s of %d\n",
1400 format_gcov (coverage->calls_executed, coverage->calls, 2),
1401 coverage->calls);
1402 else
1403 fnotice (stdout, "No calls\n");
1407 /* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
1408 affect name generation. With preserve_paths we create a filename
1409 from all path components of the source file, replacing '/' with
1410 '#', without it we simply take the basename component. With
1411 long_output_names we prepend the processed name of the input file
1412 to each output name (except when the current source file is the
1413 input file, so you don't get a double concatenation). The two
1414 components are separated by '##'. Also '.' filename components are
1415 removed and '..' components are renamed to '^'. */
1417 static char *
1418 make_gcov_file_name (const char *input_name, const char *src_name)
1420 char *cptr;
1421 char *name = XNEWVEC (char, strlen (src_name) + strlen (input_name) + 10);
1423 name[0] = 0;
1424 if (flag_long_names && strcmp (src_name, input_name))
1426 /* Generate the input filename part. */
1427 cptr = flag_preserve_paths ? NULL : strrchr (input_name, '/');
1428 strcat (name, cptr ? cptr + 1 : input_name);
1429 strcat (name, "##");
1432 /* Generate the source filename part. */
1433 cptr = flag_preserve_paths ? NULL : strrchr (src_name, '/');
1434 strcat (name, cptr ? cptr + 1 : src_name);
1436 if (flag_preserve_paths)
1438 /* Convert '/' to '#', remove '/./', convert '/../' to '/^/' */
1439 char *prev;
1441 for (cptr = name; (cptr = strchr ((prev = cptr), '/'));)
1443 unsigned shift = 0;
1445 if (prev + 1 == cptr && prev[0] == '.')
1447 /* Remove '.' */
1448 shift = 2;
1450 else if (prev + 2 == cptr && prev[0] == '.' && prev[1] == '.')
1452 /* Convert '..' */
1453 shift = 1;
1454 prev[1] = '^';
1456 else
1457 *cptr++ = '#';
1458 if (shift)
1460 cptr = prev;
1462 prev[0] = prev[shift];
1463 while (*prev++);
1468 strcat (name, ".gcov");
1469 return name;
1472 /* Scan through the bb_data for each line in the block, increment
1473 the line number execution count indicated by the execution count of
1474 the appropriate basic block. */
1476 static void
1477 add_line_counts (coverage_t *coverage, function_t *fn)
1479 unsigned ix;
1480 line_t *line = NULL; /* This is propagated from one iteration to the
1481 next. */
1483 /* Scan each basic block. */
1484 for (ix = 0; ix != fn->num_blocks; ix++)
1486 block_t *block = &fn->blocks[ix];
1487 unsigned *encoding;
1488 const source_t *src = NULL;
1489 unsigned jx;
1491 if (block->count && ix && ix + 1 != fn->num_blocks)
1492 fn->blocks_executed++;
1493 for (jx = 0, encoding = block->u.line.encoding;
1494 jx != block->u.line.num; jx++, encoding++)
1495 if (!*encoding)
1497 unsigned src_n = *++encoding;
1499 for (src = sources; src->index != src_n; src = src->next)
1500 continue;
1501 jx++;
1503 else
1505 line = &src->lines[*encoding];
1507 if (coverage)
1509 if (!line->exists)
1510 coverage->lines++;
1511 if (!line->count && block->count)
1512 coverage->lines_executed++;
1514 line->exists = 1;
1515 line->count += block->count;
1517 free (block->u.line.encoding);
1518 block->u.cycle.arc = NULL;
1519 block->u.cycle.ident = ~0U;
1521 if (!ix || ix + 1 == fn->num_blocks)
1522 /* Entry or exit block */;
1523 else if (flag_all_blocks)
1525 line_t *block_line = line ? line : &fn->src->lines[fn->line];
1527 block->chain = block_line->u.blocks;
1528 block_line->u.blocks = block;
1530 else if (flag_branches)
1532 arc_t *arc;
1534 for (arc = block->succ; arc; arc = arc->succ_next)
1536 arc->line_next = line->u.branches;
1537 line->u.branches = arc;
1538 if (coverage && !arc->is_unconditional)
1539 add_branch_counts (coverage, arc);
1543 if (!line)
1544 fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, fn->name);
1547 /* Accumulate the line counts of a file. */
1549 static void
1550 accumulate_line_counts (source_t *src)
1552 line_t *line;
1553 function_t *fn, *fn_p, *fn_n;
1554 unsigned ix;
1556 /* Reverse the function order. */
1557 for (fn = src->functions, fn_p = NULL; fn;
1558 fn_p = fn, fn = fn_n)
1560 fn_n = fn->line_next;
1561 fn->line_next = fn_p;
1563 src->functions = fn_p;
1565 for (ix = src->num_lines, line = src->lines; ix--; line++)
1567 if (!flag_all_blocks)
1569 arc_t *arc, *arc_p, *arc_n;
1571 /* Total and reverse the branch information. */
1572 for (arc = line->u.branches, arc_p = NULL; arc;
1573 arc_p = arc, arc = arc_n)
1575 arc_n = arc->line_next;
1576 arc->line_next = arc_p;
1578 add_branch_counts (&src->coverage, arc);
1580 line->u.branches = arc_p;
1582 else if (line->u.blocks)
1584 /* The user expects the line count to be the number of times
1585 a line has been executed. Simply summing the block count
1586 will give an artificially high number. The Right Thing
1587 is to sum the entry counts to the graph of blocks on this
1588 line, then find the elementary cycles of the local graph
1589 and add the transition counts of those cycles. */
1590 block_t *block, *block_p, *block_n;
1591 gcov_type count = 0;
1593 /* Reverse the block information. */
1594 for (block = line->u.blocks, block_p = NULL; block;
1595 block_p = block, block = block_n)
1597 block_n = block->chain;
1598 block->chain = block_p;
1599 block->u.cycle.ident = ix;
1601 line->u.blocks = block_p;
1603 /* Sum the entry arcs. */
1604 for (block = line->u.blocks; block; block = block->chain)
1606 arc_t *arc;
1608 for (arc = block->pred; arc; arc = arc->pred_next)
1610 if (arc->src->u.cycle.ident != ix)
1611 count += arc->count;
1612 if (flag_branches)
1613 add_branch_counts (&src->coverage, arc);
1616 /* Initialize the cs_count. */
1617 for (arc = block->succ; arc; arc = arc->succ_next)
1618 arc->cs_count = arc->count;
1621 /* Find the loops. This uses the algorithm described in
1622 Tiernan 'An Efficient Search Algorithm to Find the
1623 Elementary Circuits of a Graph', CACM Dec 1970. We hold
1624 the P array by having each block point to the arc that
1625 connects to the previous block. The H array is implicitly
1626 held because of the arc ordering, and the block's
1627 previous arc pointer.
1629 Although the algorithm is O(N^3) for highly connected
1630 graphs, at worst we'll have O(N^2), as most blocks have
1631 only one or two exits. Most graphs will be small.
1633 For each loop we find, locate the arc with the smallest
1634 transition count, and add that to the cumulative
1635 count. Decrease flow over the cycle and remove the arc
1636 from consideration. */
1637 for (block = line->u.blocks; block; block = block->chain)
1639 block_t *head = block;
1640 arc_t *arc;
1642 next_vertex:;
1643 arc = head->succ;
1644 current_vertex:;
1645 while (arc)
1647 block_t *dst = arc->dst;
1648 if (/* Already used that arc. */
1649 arc->cycle
1650 /* Not to same graph, or before first vertex. */
1651 || dst->u.cycle.ident != ix
1652 /* Already in path. */
1653 || dst->u.cycle.arc)
1655 arc = arc->succ_next;
1656 continue;
1659 if (dst == block)
1661 /* Found a closing arc. */
1662 gcov_type cycle_count = arc->cs_count;
1663 arc_t *cycle_arc = arc;
1664 arc_t *probe_arc;
1666 /* Locate the smallest arc count of the loop. */
1667 for (dst = head; (probe_arc = dst->u.cycle.arc);
1668 dst = probe_arc->src)
1669 if (cycle_count > probe_arc->cs_count)
1671 cycle_count = probe_arc->cs_count;
1672 cycle_arc = probe_arc;
1675 count += cycle_count;
1676 cycle_arc->cycle = 1;
1678 /* Remove the flow from the cycle. */
1679 arc->cs_count -= cycle_count;
1680 for (dst = head; (probe_arc = dst->u.cycle.arc);
1681 dst = probe_arc->src)
1682 probe_arc->cs_count -= cycle_count;
1684 /* Unwind to the cyclic arc. */
1685 while (head != cycle_arc->src)
1687 arc = head->u.cycle.arc;
1688 head->u.cycle.arc = NULL;
1689 head = arc->src;
1691 /* Move on. */
1692 arc = arc->succ_next;
1693 continue;
1696 /* Add new block to chain. */
1697 dst->u.cycle.arc = arc;
1698 head = dst;
1699 goto next_vertex;
1701 /* We could not add another vertex to the path. Remove
1702 the last vertex from the list. */
1703 arc = head->u.cycle.arc;
1704 if (arc)
1706 /* It was not the first vertex. Move onto next arc. */
1707 head->u.cycle.arc = NULL;
1708 head = arc->src;
1709 arc = arc->succ_next;
1710 goto current_vertex;
1712 /* Mark this block as unusable. */
1713 block->u.cycle.ident = ~0U;
1716 line->count = count;
1719 if (line->exists)
1721 src->coverage.lines++;
1722 if (line->count)
1723 src->coverage.lines_executed++;
1728 /* Output information about ARC number IX. Returns nonzero if
1729 anything is output. */
1731 static int
1732 output_branch_count (FILE *gcov_file, int ix, const arc_t *arc)
1735 if (arc->is_call_non_return)
1737 if (arc->src->count)
1739 fnotice (gcov_file, "call %2d returned %s\n", ix,
1740 format_gcov (arc->src->count - arc->count,
1741 arc->src->count, -flag_counts));
1743 else
1744 fnotice (gcov_file, "call %2d never executed\n", ix);
1746 else if (!arc->is_unconditional)
1748 if (arc->src->count)
1749 fnotice (gcov_file, "branch %2d taken %s%s\n", ix,
1750 format_gcov (arc->count, arc->src->count, -flag_counts),
1751 arc->fall_through ? " (fallthrough)" : "");
1752 else
1753 fnotice (gcov_file, "branch %2d never executed\n", ix);
1755 else if (flag_unconditional && !arc->dst->is_call_return)
1757 if (arc->src->count)
1758 fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
1759 format_gcov (arc->count, arc->src->count, -flag_counts));
1760 else
1761 fnotice (gcov_file, "unconditional %2d never executed\n", ix);
1763 else
1764 return 0;
1765 return 1;
1769 /* Read in the source file one line at a time, and output that line to
1770 the gcov file preceded by its execution count and other
1771 information. */
1773 static void
1774 output_lines (FILE *gcov_file, const source_t *src)
1776 FILE *source_file;
1777 unsigned line_num; /* current line number. */
1778 const line_t *line; /* current line info ptr. */
1779 char string[STRING_SIZE]; /* line buffer. */
1780 char const *retval = ""; /* status of source file reading. */
1781 function_t *fn = NULL;
1783 fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->name);
1784 fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
1785 fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0, da_file_name);
1786 fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0,
1787 object_summary.ctrs[GCOV_COUNTER_ARCS].runs);
1788 fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
1790 source_file = fopen (src->name, "r");
1791 if (!source_file)
1793 fnotice (stderr, "%s:cannot open source file\n", src->name);
1794 retval = NULL;
1796 else
1798 struct stat status;
1800 if (!fstat (fileno (source_file), &status)
1801 && status.st_mtime > bbg_file_time)
1803 fnotice (stderr, "%s:source file is newer than graph file '%s'\n",
1804 src->name, bbg_file_name);
1805 fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n",
1806 "-", 0);
1810 if (flag_branches)
1811 fn = src->functions;
1813 for (line_num = 1, line = &src->lines[line_num];
1814 line_num < src->num_lines; line_num++, line++)
1816 for (; fn && fn->line == line_num; fn = fn->line_next)
1818 arc_t *arc = fn->blocks[fn->num_blocks - 1].pred;
1819 gcov_type return_count = fn->blocks[fn->num_blocks - 1].count;
1821 for (; arc; arc = arc->pred_next)
1822 if (arc->fake)
1823 return_count -= arc->count;
1825 fprintf (gcov_file, "function %s", fn->name);
1826 fprintf (gcov_file, " called %s",
1827 format_gcov (fn->blocks[0].count, 0, -1));
1828 fprintf (gcov_file, " returned %s",
1829 format_gcov (return_count, fn->blocks[0].count, 0));
1830 fprintf (gcov_file, " blocks executed %s",
1831 format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0));
1832 fprintf (gcov_file, "\n");
1835 /* For lines which don't exist in the .bb file, print '-' before
1836 the source line. For lines which exist but were never
1837 executed, print '#####' before the source line. Otherwise,
1838 print the execution count before the source line. There are
1839 16 spaces of indentation added before the source line so that
1840 tabs won't be messed up. */
1841 fprintf (gcov_file, "%9s:%5u:",
1842 !line->exists ? "-" : !line->count ? "#####"
1843 : format_gcov (line->count, 0, -1), line_num);
1845 if (retval)
1847 /* Copy source line. */
1850 retval = fgets (string, STRING_SIZE, source_file);
1851 if (!retval)
1852 break;
1853 fputs (retval, gcov_file);
1855 while (!retval[0] || retval[strlen (retval) - 1] != '\n');
1857 if (!retval)
1858 fputs ("/*EOF*/\n", gcov_file);
1860 if (flag_all_blocks)
1862 block_t *block;
1863 arc_t *arc;
1864 int ix, jx;
1866 for (ix = jx = 0, block = line->u.blocks; block;
1867 block = block->chain)
1869 if (!block->is_call_return)
1870 fprintf (gcov_file, "%9s:%5u-block %2d\n",
1871 !line->exists ? "-" : !block->count ? "$$$$$"
1872 : format_gcov (block->count, 0, -1),
1873 line_num, ix++);
1874 if (flag_branches)
1875 for (arc = block->succ; arc; arc = arc->succ_next)
1876 jx += output_branch_count (gcov_file, jx, arc);
1879 else if (flag_branches)
1881 int ix;
1882 arc_t *arc;
1884 for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
1885 ix += output_branch_count (gcov_file, ix, arc);
1889 /* Handle all remaining source lines. There may be lines after the
1890 last line of code. */
1891 if (retval)
1893 for (; (retval = fgets (string, STRING_SIZE, source_file)); line_num++)
1895 fprintf (gcov_file, "%9s:%5u:%s", "-", line_num, retval);
1897 while (!retval[0] || retval[strlen (retval) - 1] != '\n')
1899 retval = fgets (string, STRING_SIZE, source_file);
1900 if (!retval)
1901 break;
1902 fputs (retval, gcov_file);
1907 if (source_file)
1908 fclose (source_file);