gcc/cp/
[official-gcc.git] / gcc / gcov.c
bloba6cabe84d033344384899b4e5688d21beb63593a
1 /* Gcov.c: prepend line execution counts and branch probabilities to a
2 source file.
3 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
4 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
5 Free Software Foundation, Inc.
6 Contributed by James E. Wilson of Cygnus Support.
7 Mangled by Bob Manson of Cygnus Support.
8 Mangled further by Nathan Sidwell <nathan@codesourcery.com>
10 Gcov is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3, or (at your option)
13 any later version.
15 Gcov is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with Gcov; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
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 /* Need an option to show individual block counts, and show
33 probabilities of fall through arcs. */
35 #include "config.h"
36 #include "system.h"
37 #include "coretypes.h"
38 #include "tm.h"
39 #include "intl.h"
40 #include "version.h"
42 #include <getopt.h>
44 #define IN_GCOV 1
45 #include "gcov-io.h"
46 #include "gcov-io.c"
48 /* The gcno file is generated by -ftest-coverage option. The gcda file is
49 generated by a program compiled with -fprofile-arcs. Their formats
50 are documented in gcov-io.h. */
52 /* The functions in this file for creating and solution program flow graphs
53 are very similar to functions in the gcc source file profile.c. In
54 some places we make use of the knowledge of how profile.c works to
55 select particular algorithms here. */
57 /* This is the size of the buffer used to read in source file lines. */
59 #define STRING_SIZE 200
61 struct function_info;
62 struct block_info;
63 struct source_info;
65 /* Describes an arc between two basic blocks. */
67 typedef struct arc_info
69 /* source and destination blocks. */
70 struct block_info *src;
71 struct block_info *dst;
73 /* transition counts. */
74 gcov_type count;
75 /* used in cycle search, so that we do not clobber original counts. */
76 gcov_type cs_count;
78 unsigned int count_valid : 1;
79 unsigned int on_tree : 1;
80 unsigned int fake : 1;
81 unsigned int fall_through : 1;
83 /* Arc is for a function that abnormally returns. */
84 unsigned int is_call_non_return : 1;
86 /* Arc is for catch/setjmp. */
87 unsigned int is_nonlocal_return : 1;
89 /* Is an unconditional branch. */
90 unsigned int is_unconditional : 1;
92 /* Loop making arc. */
93 unsigned int cycle : 1;
95 /* Next branch on line. */
96 struct arc_info *line_next;
98 /* Links to next arc on src and dst lists. */
99 struct arc_info *succ_next;
100 struct arc_info *pred_next;
101 } arc_t;
103 /* Describes a basic block. Contains lists of arcs to successor and
104 predecessor blocks. */
106 typedef struct block_info
108 /* Chain of exit and entry arcs. */
109 arc_t *succ;
110 arc_t *pred;
112 /* Number of unprocessed exit and entry arcs. */
113 gcov_type num_succ;
114 gcov_type num_pred;
116 /* Block execution count. */
117 gcov_type count;
118 unsigned flags : 13;
119 unsigned count_valid : 1;
120 unsigned valid_chain : 1;
121 unsigned invalid_chain : 1;
123 /* Block is a call instrumenting site. */
124 unsigned is_call_site : 1; /* Does the call. */
125 unsigned is_call_return : 1; /* Is the return. */
127 /* Block is a landing pad for longjmp or throw. */
128 unsigned is_nonlocal_return : 1;
130 union
132 struct
134 /* Array of line numbers and source files. source files are
135 introduced by a linenumber of zero, the next 'line number' is
136 the number of the source file. Always starts with a source
137 file. */
138 unsigned *encoding;
139 unsigned num;
140 } line; /* Valid until blocks are linked onto lines */
141 struct
143 /* Single line graph cycle workspace. Used for all-blocks
144 mode. */
145 arc_t *arc;
146 unsigned ident;
147 } cycle; /* Used in all-blocks mode, after blocks are linked onto
148 lines. */
149 } u;
151 /* Temporary chain for solving graph, and for chaining blocks on one
152 line. */
153 struct block_info *chain;
155 } block_t;
157 /* Describes a single function. Contains an array of basic blocks. */
159 typedef struct function_info
161 /* Name of function. */
162 char *name;
163 unsigned ident;
164 unsigned checksum;
166 /* Array of basic blocks. */
167 block_t *blocks;
168 unsigned num_blocks;
169 unsigned blocks_executed;
171 /* Raw arc coverage counts. */
172 gcov_type *counts;
173 unsigned num_counts;
175 /* First line number. */
176 unsigned line;
177 struct source_info *src;
179 /* Next function in same source file. */
180 struct function_info *line_next;
182 /* Next function. */
183 struct function_info *next;
184 } function_t;
186 /* Describes coverage of a file or function. */
188 typedef struct coverage_info
190 int lines;
191 int lines_executed;
193 int branches;
194 int branches_executed;
195 int branches_taken;
197 int calls;
198 int calls_executed;
200 char *name;
201 } coverage_t;
203 /* Describes a single line of source. Contains a chain of basic blocks
204 with code on it. */
206 typedef struct line_info
208 gcov_type count; /* execution count */
209 union
211 arc_t *branches; /* branches from blocks that end on this
212 line. Used for branch-counts when not
213 all-blocks mode. */
214 block_t *blocks; /* blocks which start on this line. Used
215 in all-blocks mode. */
216 } u;
217 unsigned exists : 1;
218 } line_t;
220 /* Describes a file mentioned in the block graph. Contains an array
221 of line info. */
223 typedef struct source_info
225 /* Name of source file. */
226 char *name;
227 unsigned index;
228 time_t file_time;
230 /* Array of line information. */
231 line_t *lines;
232 unsigned num_lines;
234 coverage_t coverage;
236 /* Functions in this source file. These are in ascending line
237 number order. */
238 function_t *functions;
240 /* Next source file. */
241 struct source_info *next;
242 } source_t;
244 /* Holds a list of function basic block graphs. */
246 static function_t *functions;
248 /* This points to the head of the sourcefile structure list. New elements
249 are always prepended. */
251 static source_t *sources;
253 /* Next index for a source file. */
255 static unsigned source_index;
257 /* This holds data summary information. */
259 static struct gcov_summary object_summary;
260 static unsigned program_count;
262 /* Modification time of graph file. */
264 static time_t bbg_file_time;
266 /* Name and file pointer of the input file for the basic block graph. */
268 static char *bbg_file_name;
270 /* Stamp of the bbg file */
271 static unsigned bbg_stamp;
273 /* Name and file pointer of the input file for the arc count data. */
275 static char *da_file_name;
277 /* Data file is missing. */
279 static int no_data_file;
281 /* If there is several input files, compute and display results after
282 reading all data files. This way if two or more gcda file refer to
283 the same source file (eg inline subprograms in a .h file), the
284 counts are added. */
286 static int multiple_files = 0;
288 /* Output branch probabilities. */
290 static int flag_branches = 0;
292 /* Show unconditional branches too. */
293 static int flag_unconditional = 0;
295 /* Output a gcov file if this is true. This is on by default, and can
296 be turned off by the -n option. */
298 static int flag_gcov_file = 1;
300 /* For included files, make the gcov output file name include the name
301 of the input source file. For example, if x.h is included in a.c,
302 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
304 static int flag_long_names = 0;
306 /* Output count information for every basic block, not merely those
307 that contain line number information. */
309 static int flag_all_blocks = 0;
311 /* Output summary info for each function. */
313 static int flag_function_summary = 0;
315 /* Object directory file prefix. This is the directory/file where the
316 graph and data files are looked for, if nonzero. */
318 static char *object_directory = 0;
320 /* Preserve all pathname components. Needed when object files and
321 source files are in subdirectories. '/' is mangled as '#', '.' is
322 elided and '..' mangled to '^'. */
324 static int flag_preserve_paths = 0;
326 /* Output the number of times a branch was taken as opposed to the percentage
327 of times it was taken. */
329 static int flag_counts = 0;
331 /* Forward declarations. */
332 static void fnotice (FILE *, const char *, ...) ATTRIBUTE_PRINTF_2;
333 static int process_args (int, char **);
334 static void print_usage (int) ATTRIBUTE_NORETURN;
335 static void print_version (void) ATTRIBUTE_NORETURN;
336 static void process_file (const char *);
337 static void generate_results (const char *);
338 static void create_file_names (const char *);
339 static source_t *find_source (const char *);
340 static int read_graph_file (void);
341 static int read_count_file (void);
342 static void solve_flow_graph (function_t *);
343 static void add_branch_counts (coverage_t *, const arc_t *);
344 static void add_line_counts (coverage_t *, function_t *);
345 static void function_summary (const coverage_t *, const char *);
346 static const char *format_gcov (gcov_type, gcov_type, int);
347 static void accumulate_line_counts (source_t *);
348 static int output_branch_count (FILE *, int, const arc_t *);
349 static void output_lines (FILE *, const source_t *);
350 static char *make_gcov_file_name (const char *, const char *);
351 static void release_structures (void);
352 extern int main (int, char **);
355 main (int argc, char **argv)
357 int argno;
359 /* Unlock the stdio streams. */
360 unlock_std_streams ();
362 gcc_init_libintl ();
364 argno = process_args (argc, argv);
365 if (optind == argc)
366 print_usage (true);
368 if (argc - argno > 1)
369 multiple_files = 1;
371 for (; argno != argc; argno++)
372 process_file (argv[argno]);
374 generate_results (multiple_files ? NULL : argv[argc - 1]);
376 release_structures ();
378 return 0;
381 static void
382 fnotice (FILE *file, const char *cmsgid, ...)
384 va_list ap;
386 va_start (ap, cmsgid);
387 vfprintf (file, _(cmsgid), ap);
388 va_end (ap);
391 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
392 otherwise the output of --help. */
394 static void
395 print_usage (int error_p)
397 FILE *file = error_p ? stderr : stdout;
398 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
400 fnotice (file, "Usage: gcov [OPTION]... SOURCEFILE...\n\n");
401 fnotice (file, "Print code coverage information.\n\n");
402 fnotice (file, " -h, --help Print this help, then exit\n");
403 fnotice (file, " -v, --version Print version number, then exit\n");
404 fnotice (file, " -a, --all-blocks Show information for every basic block\n");
405 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
406 fnotice (file, " -c, --branch-counts Given counts of branches taken\n\
407 rather than percentages\n");
408 fnotice (file, " -n, --no-output Do not create an output file\n");
409 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
410 source files\n");
411 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
412 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
413 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
414 fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
415 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
416 bug_report_url);
417 exit (status);
420 /* Print version information and exit. */
422 static void
423 print_version (void)
425 fnotice (stdout, "gcov %s%s\n", pkgversion_string, version_string);
426 fprintf (stdout, "Copyright %s 2008 Free Software Foundation, Inc.\n",
427 _("(C)"));
428 fnotice (stdout,
429 _("This is free software; see the source for copying conditions.\n"
430 "There is NO warranty; not even for MERCHANTABILITY or \n"
431 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
432 exit (SUCCESS_EXIT_CODE);
435 static const struct option options[] =
437 { "help", no_argument, NULL, 'h' },
438 { "version", no_argument, NULL, 'v' },
439 { "all-blocks", no_argument, NULL, 'a' },
440 { "branch-probabilities", no_argument, NULL, 'b' },
441 { "branch-counts", no_argument, NULL, 'c' },
442 { "no-output", no_argument, NULL, 'n' },
443 { "long-file-names", no_argument, NULL, 'l' },
444 { "function-summaries", no_argument, NULL, 'f' },
445 { "preserve-paths", no_argument, NULL, 'p' },
446 { "object-directory", required_argument, NULL, 'o' },
447 { "object-file", required_argument, NULL, 'o' },
448 { "unconditional-branches", no_argument, NULL, 'u' },
449 { 0, 0, 0, 0 }
452 /* Process args, return index to first non-arg. */
454 static int
455 process_args (int argc, char **argv)
457 int opt;
459 while ((opt = getopt_long (argc, argv, "abcfhlno:puv", options, NULL)) != -1)
461 switch (opt)
463 case 'a':
464 flag_all_blocks = 1;
465 break;
466 case 'b':
467 flag_branches = 1;
468 break;
469 case 'c':
470 flag_counts = 1;
471 break;
472 case 'f':
473 flag_function_summary = 1;
474 break;
475 case 'h':
476 print_usage (false);
477 /* print_usage will exit. */
478 case 'l':
479 flag_long_names = 1;
480 break;
481 case 'n':
482 flag_gcov_file = 0;
483 break;
484 case 'o':
485 object_directory = optarg;
486 break;
487 case 'p':
488 flag_preserve_paths = 1;
489 break;
490 case 'u':
491 flag_unconditional = 1;
492 break;
493 case 'v':
494 print_version ();
495 /* print_version will exit. */
496 default:
497 print_usage (true);
498 /* print_usage will exit. */
502 return optind;
505 /* Process a single source file. */
507 static void
508 process_file (const char *file_name)
510 function_t *fn;
511 function_t *fn_p;
512 function_t *old_functions;
514 /* Save and clear the list of current functions. They will be appended
515 later. */
516 old_functions = functions;
517 functions = NULL;
519 create_file_names (file_name);
520 if (read_graph_file ())
521 return;
523 if (!functions)
525 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
526 return;
529 if (read_count_file ())
530 return;
532 for (fn_p = NULL, fn = functions; fn; fn_p = fn, fn = fn->next)
533 solve_flow_graph (fn);
535 if (fn_p)
536 fn_p->next = old_functions;
539 static void
540 generate_results (const char *file_name)
542 source_t *src;
543 function_t *fn;
545 for (src = sources; src; src = src->next)
546 src->lines = XCNEWVEC (line_t, src->num_lines);
547 for (fn = functions; fn; fn = fn->next)
549 coverage_t coverage;
551 memset (&coverage, 0, sizeof (coverage));
552 coverage.name = fn->name;
553 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
554 if (flag_function_summary)
556 function_summary (&coverage, "Function");
557 fnotice (stdout, "\n");
561 for (src = sources; src; src = src->next)
563 accumulate_line_counts (src);
564 function_summary (&src->coverage, "File");
565 if (flag_gcov_file)
567 char *gcov_file_name = make_gcov_file_name (file_name, src->name);
568 FILE *gcov_file = fopen (gcov_file_name, "w");
570 if (gcov_file)
572 fnotice (stdout, "%s:creating '%s'\n",
573 src->name, gcov_file_name);
574 output_lines (gcov_file, src);
575 if (ferror (gcov_file))
576 fnotice (stderr, "%s:error writing output file '%s'\n",
577 src->name, gcov_file_name);
578 fclose (gcov_file);
580 else
581 fnotice (stderr, "%s:could not open output file '%s'\n",
582 src->name, gcov_file_name);
583 free (gcov_file_name);
585 fnotice (stdout, "\n");
589 /* Release all memory used. */
591 static void
592 release_structures (void)
594 function_t *fn;
595 source_t *src;
597 while ((src = sources))
599 sources = src->next;
601 free (src->name);
602 free (src->lines);
605 while ((fn = functions))
607 unsigned ix;
608 block_t *block;
610 functions = fn->next;
611 for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
613 arc_t *arc, *arc_n;
615 for (arc = block->succ; arc; arc = arc_n)
617 arc_n = arc->succ_next;
618 free (arc);
621 free (fn->blocks);
622 free (fn->counts);
626 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
627 is not specified, these are looked for in the current directory,
628 and named from the basename of the FILE_NAME sans extension. If
629 OBJECT_DIRECTORY is specified and is a directory, the files are in
630 that directory, but named from the basename of the FILE_NAME, sans
631 extension. Otherwise OBJECT_DIRECTORY is taken to be the name of
632 the object *file*, and the data files are named from that. */
634 static void
635 create_file_names (const char *file_name)
637 char *cptr;
638 char *name;
639 int length = strlen (file_name);
640 int base;
642 /* Free previous file names. */
643 if (bbg_file_name)
644 free (bbg_file_name);
645 if (da_file_name)
646 free (da_file_name);
647 da_file_name = bbg_file_name = NULL;
648 bbg_file_time = 0;
649 bbg_stamp = 0;
651 if (object_directory && object_directory[0])
653 struct stat status;
655 length += strlen (object_directory) + 2;
656 name = XNEWVEC (char, length);
657 name[0] = 0;
659 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
660 strcat (name, object_directory);
661 if (base && name[strlen (name) - 1] != '/')
662 strcat (name, "/");
664 else
666 name = XNEWVEC (char, length + 1);
667 name[0] = 0;
668 base = 1;
671 if (base)
673 /* Append source file name. */
674 cptr = strrchr (file_name, '/');
675 strcat (name, cptr ? cptr + 1 : file_name);
678 /* Remove the extension. */
679 cptr = strrchr (name, '.');
680 if (cptr)
681 *cptr = 0;
683 length = strlen (name);
685 bbg_file_name = XNEWVEC (char, length + strlen (GCOV_NOTE_SUFFIX) + 1);
686 strcpy (bbg_file_name, name);
687 strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
689 da_file_name = XNEWVEC (char, length + strlen (GCOV_DATA_SUFFIX) + 1);
690 strcpy (da_file_name, name);
691 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
693 free (name);
694 return;
697 /* Find or create a source file structure for FILE_NAME. Copies
698 FILE_NAME on creation */
700 static source_t *
701 find_source (const char *file_name)
703 source_t *src;
704 struct stat status;
706 if (!file_name)
707 file_name = "<unknown>";
709 for (src = sources; src; src = src->next)
710 if (!strcmp (file_name, src->name))
711 break;
713 if (!src)
715 src = XCNEW (source_t);
716 src->name = xstrdup (file_name);
717 src->coverage.name = src->name;
718 src->index = source_index++;
719 src->next = sources;
720 sources = src;
722 if (!stat (file_name, &status))
723 src->file_time = status.st_mtime;
726 if (src->file_time > bbg_file_time)
728 static int info_emitted;
730 fnotice (stderr, "%s:source file is newer than graph file '%s'\n",
731 src->name, bbg_file_name);
732 if (!info_emitted)
734 fnotice (stderr,
735 "(the message is only displayed one per source file)\n");
736 info_emitted = 1;
738 src->file_time = 0;
741 return src;
744 /* Read the graph file. Return nonzero on fatal error. */
746 static int
747 read_graph_file (void)
749 unsigned version;
750 unsigned current_tag = 0;
751 struct function_info *fn = NULL;
752 function_t *old_functions_head = functions;
753 source_t *src = NULL;
754 unsigned ix;
755 unsigned tag;
757 if (!gcov_open (bbg_file_name, 1))
759 fnotice (stderr, "%s:cannot open graph file\n", bbg_file_name);
760 return 1;
762 bbg_file_time = gcov_time ();
763 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
765 fnotice (stderr, "%s:not a gcov graph file\n", bbg_file_name);
766 gcov_close ();
767 return 1;
770 version = gcov_read_unsigned ();
771 if (version != GCOV_VERSION)
773 char v[4], e[4];
775 GCOV_UNSIGNED2STRING (v, version);
776 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
778 fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n",
779 bbg_file_name, v, e);
781 bbg_stamp = gcov_read_unsigned ();
783 while ((tag = gcov_read_unsigned ()))
785 unsigned length = gcov_read_unsigned ();
786 gcov_position_t base = gcov_position ();
788 if (tag == GCOV_TAG_FUNCTION)
790 char *function_name;
791 unsigned ident, checksum, lineno;
792 source_t *src;
793 function_t *probe, *prev;
795 ident = gcov_read_unsigned ();
796 checksum = gcov_read_unsigned ();
797 function_name = xstrdup (gcov_read_string ());
798 src = find_source (gcov_read_string ());
799 lineno = gcov_read_unsigned ();
801 fn = XCNEW (function_t);
802 fn->name = function_name;
803 fn->ident = ident;
804 fn->checksum = checksum;
805 fn->src = src;
806 fn->line = lineno;
808 fn->next = functions;
809 functions = fn;
810 current_tag = tag;
812 if (lineno >= src->num_lines)
813 src->num_lines = lineno + 1;
814 /* Now insert it into the source file's list of
815 functions. Normally functions will be encountered in
816 ascending order, so a simple scan is quick. */
817 for (probe = src->functions, prev = NULL;
818 probe && probe->line > lineno;
819 prev = probe, probe = probe->line_next)
820 continue;
821 fn->line_next = probe;
822 if (prev)
823 prev->line_next = fn;
824 else
825 src->functions = fn;
827 else if (fn && tag == GCOV_TAG_BLOCKS)
829 if (fn->blocks)
830 fnotice (stderr, "%s:already seen blocks for '%s'\n",
831 bbg_file_name, fn->name);
832 else
834 unsigned ix, num_blocks = GCOV_TAG_BLOCKS_NUM (length);
835 fn->num_blocks = num_blocks;
837 fn->blocks = XCNEWVEC (block_t, fn->num_blocks);
838 for (ix = 0; ix != num_blocks; ix++)
839 fn->blocks[ix].flags = gcov_read_unsigned ();
842 else if (fn && tag == GCOV_TAG_ARCS)
844 unsigned src = gcov_read_unsigned ();
845 unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
847 if (src >= fn->num_blocks || fn->blocks[src].succ)
848 goto corrupt;
850 while (num_dests--)
852 struct arc_info *arc;
853 unsigned dest = gcov_read_unsigned ();
854 unsigned flags = gcov_read_unsigned ();
856 if (dest >= fn->num_blocks)
857 goto corrupt;
858 arc = XCNEW (arc_t);
860 arc->dst = &fn->blocks[dest];
861 arc->src = &fn->blocks[src];
863 arc->count = 0;
864 arc->count_valid = 0;
865 arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
866 arc->fake = !!(flags & GCOV_ARC_FAKE);
867 arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
869 arc->succ_next = fn->blocks[src].succ;
870 fn->blocks[src].succ = arc;
871 fn->blocks[src].num_succ++;
873 arc->pred_next = fn->blocks[dest].pred;
874 fn->blocks[dest].pred = arc;
875 fn->blocks[dest].num_pred++;
877 if (arc->fake)
879 if (src)
881 /* Exceptional exit from this function, the
882 source block must be a call. */
883 fn->blocks[src].is_call_site = 1;
884 arc->is_call_non_return = 1;
886 else
888 /* Non-local return from a callee of this
889 function. The destination block is a catch or
890 setjmp. */
891 arc->is_nonlocal_return = 1;
892 fn->blocks[dest].is_nonlocal_return = 1;
896 if (!arc->on_tree)
897 fn->num_counts++;
900 else if (fn && tag == GCOV_TAG_LINES)
902 unsigned blockno = gcov_read_unsigned ();
903 unsigned *line_nos = XCNEWVEC (unsigned, length - 1);
905 if (blockno >= fn->num_blocks || fn->blocks[blockno].u.line.encoding)
906 goto corrupt;
908 for (ix = 0; ; )
910 unsigned lineno = gcov_read_unsigned ();
912 if (lineno)
914 if (!ix)
916 line_nos[ix++] = 0;
917 line_nos[ix++] = src->index;
919 line_nos[ix++] = lineno;
920 if (lineno >= src->num_lines)
921 src->num_lines = lineno + 1;
923 else
925 const char *file_name = gcov_read_string ();
927 if (!file_name)
928 break;
929 src = find_source (file_name);
931 line_nos[ix++] = 0;
932 line_nos[ix++] = src->index;
936 fn->blocks[blockno].u.line.encoding = line_nos;
937 fn->blocks[blockno].u.line.num = ix;
939 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
941 fn = NULL;
942 current_tag = 0;
944 gcov_sync (base, length);
945 if (gcov_is_error ())
947 corrupt:;
948 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
949 gcov_close ();
950 return 1;
953 gcov_close ();
955 /* We built everything backwards, so nreverse them all. */
957 /* Reverse sources. Not strictly necessary, but we'll then process
958 them in the 'expected' order. */
960 source_t *src, *src_p, *src_n;
962 for (src_p = NULL, src = sources; src; src_p = src, src = src_n)
964 src_n = src->next;
965 src->next = src_p;
967 sources = src_p;
970 /* Reverse functions. */
972 function_t *fn, *fn_p, *fn_n;
974 for (fn_p = old_functions_head, fn = functions;
975 fn != old_functions_head;
976 fn_p = fn, fn = fn_n)
978 unsigned ix;
980 fn_n = fn->next;
981 fn->next = fn_p;
983 /* Reverse the arcs. */
984 for (ix = fn->num_blocks; ix--;)
986 arc_t *arc, *arc_p, *arc_n;
988 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
989 arc_p = arc, arc = arc_n)
991 arc_n = arc->succ_next;
992 arc->succ_next = arc_p;
994 fn->blocks[ix].succ = arc_p;
996 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
997 arc_p = arc, arc = arc_n)
999 arc_n = arc->pred_next;
1000 arc->pred_next = arc_p;
1002 fn->blocks[ix].pred = arc_p;
1005 functions = fn_p;
1007 return 0;
1010 /* Reads profiles from the count file and attach to each
1011 function. Return nonzero if fatal error. */
1013 static int
1014 read_count_file (void)
1016 unsigned ix;
1017 unsigned version;
1018 unsigned tag;
1019 function_t *fn = NULL;
1020 int error = 0;
1022 if (!gcov_open (da_file_name, 1))
1024 fnotice (stderr, "%s:cannot open data file, assuming not executed\n",
1025 da_file_name);
1026 no_data_file = 1;
1027 return 0;
1029 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
1031 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
1032 cleanup:;
1033 gcov_close ();
1034 return 1;
1036 version = gcov_read_unsigned ();
1037 if (version != GCOV_VERSION)
1039 char v[4], e[4];
1041 GCOV_UNSIGNED2STRING (v, version);
1042 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1044 fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
1045 da_file_name, v, e);
1047 tag = gcov_read_unsigned ();
1048 if (tag != bbg_stamp)
1050 fnotice (stderr, "%s:stamp mismatch with graph file\n", da_file_name);
1051 goto cleanup;
1054 while ((tag = gcov_read_unsigned ()))
1056 unsigned length = gcov_read_unsigned ();
1057 unsigned long base = gcov_position ();
1059 if (tag == GCOV_TAG_OBJECT_SUMMARY)
1060 gcov_read_summary (&object_summary);
1061 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
1062 program_count++;
1063 else if (tag == GCOV_TAG_FUNCTION)
1065 unsigned ident = gcov_read_unsigned ();
1066 struct function_info *fn_n = functions;
1068 /* Try to find the function in the list.
1069 To speed up the search, first start from the last function
1070 found. */
1071 for (fn = fn ? fn->next : NULL; ; fn = fn->next)
1073 if (fn)
1075 else if ((fn = fn_n))
1076 fn_n = NULL;
1077 else
1079 fnotice (stderr, "%s:unknown function '%u'\n",
1080 da_file_name, ident);
1081 break;
1083 if (fn->ident == ident)
1084 break;
1087 if (!fn)
1089 else if (gcov_read_unsigned () != fn->checksum)
1091 mismatch:;
1092 fnotice (stderr, "%s:profile mismatch for '%s'\n",
1093 da_file_name, fn->name);
1094 goto cleanup;
1097 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
1099 if (length != GCOV_TAG_COUNTER_LENGTH (fn->num_counts))
1100 goto mismatch;
1102 if (!fn->counts)
1103 fn->counts = XCNEWVEC (gcov_type, fn->num_counts);
1105 for (ix = 0; ix != fn->num_counts; ix++)
1106 fn->counts[ix] += gcov_read_counter ();
1108 gcov_sync (base, length);
1109 if ((error = gcov_is_error ()))
1111 fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1112 da_file_name);
1113 goto cleanup;
1117 gcov_close ();
1118 return 0;
1121 /* Solve the flow graph. Propagate counts from the instrumented arcs
1122 to the blocks and the uninstrumented arcs. */
1124 static void
1125 solve_flow_graph (function_t *fn)
1127 unsigned ix;
1128 arc_t *arc;
1129 gcov_type *count_ptr = fn->counts;
1130 block_t *blk;
1131 block_t *valid_blocks = NULL; /* valid, but unpropagated blocks. */
1132 block_t *invalid_blocks = NULL; /* invalid, but inferable blocks. */
1134 if (fn->num_blocks < 2)
1135 fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n",
1136 bbg_file_name, fn->name);
1137 else
1139 if (fn->blocks[0].num_pred)
1140 fnotice (stderr, "%s:'%s' has arcs to entry block\n",
1141 bbg_file_name, fn->name);
1142 else
1143 /* We can't deduce the entry block counts from the lack of
1144 predecessors. */
1145 fn->blocks[0].num_pred = ~(unsigned)0;
1147 if (fn->blocks[fn->num_blocks - 1].num_succ)
1148 fnotice (stderr, "%s:'%s' has arcs from exit block\n",
1149 bbg_file_name, fn->name);
1150 else
1151 /* Likewise, we can't deduce exit block counts from the lack
1152 of its successors. */
1153 fn->blocks[fn->num_blocks - 1].num_succ = ~(unsigned)0;
1156 /* Propagate the measured counts, this must be done in the same
1157 order as the code in profile.c */
1158 for (ix = 0, blk = fn->blocks; ix != fn->num_blocks; ix++, blk++)
1160 block_t const *prev_dst = NULL;
1161 int out_of_order = 0;
1162 int non_fake_succ = 0;
1164 for (arc = blk->succ; arc; arc = arc->succ_next)
1166 if (!arc->fake)
1167 non_fake_succ++;
1169 if (!arc->on_tree)
1171 if (count_ptr)
1172 arc->count = *count_ptr++;
1173 arc->count_valid = 1;
1174 blk->num_succ--;
1175 arc->dst->num_pred--;
1177 if (prev_dst && prev_dst > arc->dst)
1178 out_of_order = 1;
1179 prev_dst = arc->dst;
1181 if (non_fake_succ == 1)
1183 /* If there is only one non-fake exit, it is an
1184 unconditional branch. */
1185 for (arc = blk->succ; arc; arc = arc->succ_next)
1186 if (!arc->fake)
1188 arc->is_unconditional = 1;
1189 /* If this block is instrumenting a call, it might be
1190 an artificial block. It is not artificial if it has
1191 a non-fallthrough exit, or the destination of this
1192 arc has more than one entry. Mark the destination
1193 block as a return site, if none of those conditions
1194 hold. */
1195 if (blk->is_call_site && arc->fall_through
1196 && arc->dst->pred == arc && !arc->pred_next)
1197 arc->dst->is_call_return = 1;
1201 /* Sort the successor arcs into ascending dst order. profile.c
1202 normally produces arcs in the right order, but sometimes with
1203 one or two out of order. We're not using a particularly
1204 smart sort. */
1205 if (out_of_order)
1207 arc_t *start = blk->succ;
1208 unsigned changes = 1;
1210 while (changes)
1212 arc_t *arc, *arc_p, *arc_n;
1214 changes = 0;
1215 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1217 if (arc->dst > arc_n->dst)
1219 changes = 1;
1220 if (arc_p)
1221 arc_p->succ_next = arc_n;
1222 else
1223 start = arc_n;
1224 arc->succ_next = arc_n->succ_next;
1225 arc_n->succ_next = arc;
1226 arc_p = arc_n;
1228 else
1230 arc_p = arc;
1231 arc = arc_n;
1235 blk->succ = start;
1238 /* Place it on the invalid chain, it will be ignored if that's
1239 wrong. */
1240 blk->invalid_chain = 1;
1241 blk->chain = invalid_blocks;
1242 invalid_blocks = blk;
1245 while (invalid_blocks || valid_blocks)
1247 while ((blk = invalid_blocks))
1249 gcov_type total = 0;
1250 const arc_t *arc;
1252 invalid_blocks = blk->chain;
1253 blk->invalid_chain = 0;
1254 if (!blk->num_succ)
1255 for (arc = blk->succ; arc; arc = arc->succ_next)
1256 total += arc->count;
1257 else if (!blk->num_pred)
1258 for (arc = blk->pred; arc; arc = arc->pred_next)
1259 total += arc->count;
1260 else
1261 continue;
1263 blk->count = total;
1264 blk->count_valid = 1;
1265 blk->chain = valid_blocks;
1266 blk->valid_chain = 1;
1267 valid_blocks = blk;
1269 while ((blk = valid_blocks))
1271 gcov_type total;
1272 arc_t *arc, *inv_arc;
1274 valid_blocks = blk->chain;
1275 blk->valid_chain = 0;
1276 if (blk->num_succ == 1)
1278 block_t *dst;
1280 total = blk->count;
1281 inv_arc = NULL;
1282 for (arc = blk->succ; arc; arc = arc->succ_next)
1284 total -= arc->count;
1285 if (!arc->count_valid)
1286 inv_arc = arc;
1288 dst = inv_arc->dst;
1289 inv_arc->count_valid = 1;
1290 inv_arc->count = total;
1291 blk->num_succ--;
1292 dst->num_pred--;
1293 if (dst->count_valid)
1295 if (dst->num_pred == 1 && !dst->valid_chain)
1297 dst->chain = valid_blocks;
1298 dst->valid_chain = 1;
1299 valid_blocks = dst;
1302 else
1304 if (!dst->num_pred && !dst->invalid_chain)
1306 dst->chain = invalid_blocks;
1307 dst->invalid_chain = 1;
1308 invalid_blocks = dst;
1312 if (blk->num_pred == 1)
1314 block_t *src;
1316 total = blk->count;
1317 inv_arc = NULL;
1318 for (arc = blk->pred; arc; arc = arc->pred_next)
1320 total -= arc->count;
1321 if (!arc->count_valid)
1322 inv_arc = arc;
1324 src = inv_arc->src;
1325 inv_arc->count_valid = 1;
1326 inv_arc->count = total;
1327 blk->num_pred--;
1328 src->num_succ--;
1329 if (src->count_valid)
1331 if (src->num_succ == 1 && !src->valid_chain)
1333 src->chain = valid_blocks;
1334 src->valid_chain = 1;
1335 valid_blocks = src;
1338 else
1340 if (!src->num_succ && !src->invalid_chain)
1342 src->chain = invalid_blocks;
1343 src->invalid_chain = 1;
1344 invalid_blocks = src;
1351 /* If the graph has been correctly solved, every block will have a
1352 valid count. */
1353 for (ix = 0; ix < fn->num_blocks; ix++)
1354 if (!fn->blocks[ix].count_valid)
1356 fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
1357 bbg_file_name, fn->name);
1358 break;
1364 /* Increment totals in COVERAGE according to arc ARC. */
1366 static void
1367 add_branch_counts (coverage_t *coverage, const arc_t *arc)
1369 if (arc->is_call_non_return)
1371 coverage->calls++;
1372 if (arc->src->count)
1373 coverage->calls_executed++;
1375 else if (!arc->is_unconditional)
1377 coverage->branches++;
1378 if (arc->src->count)
1379 coverage->branches_executed++;
1380 if (arc->count)
1381 coverage->branches_taken++;
1385 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1386 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1387 If DP is zero, no decimal point is printed. Only print 100% when
1388 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1389 format TOP. Return pointer to a static string. */
1391 static char const *
1392 format_gcov (gcov_type top, gcov_type bottom, int dp)
1394 static char buffer[20];
1396 if (dp >= 0)
1398 float ratio = bottom ? (float)top / bottom : 0;
1399 int ix;
1400 unsigned limit = 100;
1401 unsigned percent;
1403 for (ix = dp; ix--; )
1404 limit *= 10;
1406 percent = (unsigned) (ratio * limit + (float)0.5);
1407 if (percent <= 0 && top)
1408 percent = 1;
1409 else if (percent >= limit && top != bottom)
1410 percent = limit - 1;
1411 ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1412 if (dp)
1414 dp++;
1417 buffer[ix+1] = buffer[ix];
1418 ix--;
1420 while (dp--);
1421 buffer[ix + 1] = '.';
1424 else
1425 sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)top);
1427 return buffer;
1431 /* Output summary info for a function. */
1433 static void
1434 function_summary (const coverage_t *coverage, const char *title)
1436 fnotice (stdout, "%s '%s'\n", title, coverage->name);
1438 if (coverage->lines)
1439 fnotice (stdout, "Lines executed:%s of %d\n",
1440 format_gcov (coverage->lines_executed, coverage->lines, 2),
1441 coverage->lines);
1442 else
1443 fnotice (stdout, "No executable lines\n");
1445 if (flag_branches)
1447 if (coverage->branches)
1449 fnotice (stdout, "Branches executed:%s of %d\n",
1450 format_gcov (coverage->branches_executed,
1451 coverage->branches, 2),
1452 coverage->branches);
1453 fnotice (stdout, "Taken at least once:%s of %d\n",
1454 format_gcov (coverage->branches_taken,
1455 coverage->branches, 2),
1456 coverage->branches);
1458 else
1459 fnotice (stdout, "No branches\n");
1460 if (coverage->calls)
1461 fnotice (stdout, "Calls executed:%s of %d\n",
1462 format_gcov (coverage->calls_executed, coverage->calls, 2),
1463 coverage->calls);
1464 else
1465 fnotice (stdout, "No calls\n");
1469 /* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
1470 affect name generation. With preserve_paths we create a filename
1471 from all path components of the source file, replacing '/' with
1472 '#', without it we simply take the basename component. With
1473 long_output_names we prepend the processed name of the input file
1474 to each output name (except when the current source file is the
1475 input file, so you don't get a double concatenation). The two
1476 components are separated by '##'. Also '.' filename components are
1477 removed and '..' components are renamed to '^'. */
1479 static char *
1480 make_gcov_file_name (const char *input_name, const char *src_name)
1482 char *cptr;
1483 char *name;
1485 if (flag_long_names && input_name && strcmp (src_name, input_name))
1487 name = XNEWVEC (char, strlen (src_name) + strlen (input_name) + 10);
1488 name[0] = 0;
1489 /* Generate the input filename part. */
1490 cptr = flag_preserve_paths ? NULL : strrchr (input_name, '/');
1491 strcat (name, cptr ? cptr + 1 : input_name);
1492 strcat (name, "##");
1494 else
1496 name = XNEWVEC (char, strlen (src_name) + 10);
1497 name[0] = 0;
1500 /* Generate the source filename part. */
1501 cptr = flag_preserve_paths ? NULL : strrchr (src_name, '/');
1502 strcat (name, cptr ? cptr + 1 : src_name);
1504 if (flag_preserve_paths)
1506 /* Convert '/' to '#', remove '/./', convert '/../' to '/^/' */
1507 char *prev;
1509 for (cptr = name; (cptr = strchr ((prev = cptr), '/'));)
1511 unsigned shift = 0;
1513 if (prev + 1 == cptr && prev[0] == '.')
1515 /* Remove '.' */
1516 shift = 2;
1518 else if (prev + 2 == cptr && prev[0] == '.' && prev[1] == '.')
1520 /* Convert '..' */
1521 shift = 1;
1522 prev[1] = '^';
1524 else
1525 *cptr++ = '#';
1526 if (shift)
1528 cptr = prev;
1530 prev[0] = prev[shift];
1531 while (*prev++);
1536 strcat (name, ".gcov");
1537 return name;
1540 /* Scan through the bb_data for each line in the block, increment
1541 the line number execution count indicated by the execution count of
1542 the appropriate basic block. */
1544 static void
1545 add_line_counts (coverage_t *coverage, function_t *fn)
1547 unsigned ix;
1548 line_t *line = NULL; /* This is propagated from one iteration to the
1549 next. */
1551 /* Scan each basic block. */
1552 for (ix = 0; ix != fn->num_blocks; ix++)
1554 block_t *block = &fn->blocks[ix];
1555 unsigned *encoding;
1556 const source_t *src = NULL;
1557 unsigned jx;
1559 if (block->count && ix && ix + 1 != fn->num_blocks)
1560 fn->blocks_executed++;
1561 for (jx = 0, encoding = block->u.line.encoding;
1562 jx != block->u.line.num; jx++, encoding++)
1563 if (!*encoding)
1565 unsigned src_n = *++encoding;
1567 for (src = sources; src->index != src_n; src = src->next)
1568 continue;
1569 jx++;
1571 else
1573 line = &src->lines[*encoding];
1575 if (coverage)
1577 if (!line->exists)
1578 coverage->lines++;
1579 if (!line->count && block->count)
1580 coverage->lines_executed++;
1582 line->exists = 1;
1583 line->count += block->count;
1585 free (block->u.line.encoding);
1586 block->u.cycle.arc = NULL;
1587 block->u.cycle.ident = ~0U;
1589 if (!ix || ix + 1 == fn->num_blocks)
1590 /* Entry or exit block */;
1591 else if (flag_all_blocks)
1593 line_t *block_line = line ? line : &fn->src->lines[fn->line];
1595 block->chain = block_line->u.blocks;
1596 block_line->u.blocks = block;
1598 else if (flag_branches)
1600 arc_t *arc;
1602 for (arc = block->succ; arc; arc = arc->succ_next)
1604 arc->line_next = line->u.branches;
1605 line->u.branches = arc;
1606 if (coverage && !arc->is_unconditional)
1607 add_branch_counts (coverage, arc);
1611 if (!line)
1612 fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, fn->name);
1615 /* Accumulate the line counts of a file. */
1617 static void
1618 accumulate_line_counts (source_t *src)
1620 line_t *line;
1621 function_t *fn, *fn_p, *fn_n;
1622 unsigned ix;
1624 /* Reverse the function order. */
1625 for (fn = src->functions, fn_p = NULL; fn;
1626 fn_p = fn, fn = fn_n)
1628 fn_n = fn->line_next;
1629 fn->line_next = fn_p;
1631 src->functions = fn_p;
1633 for (ix = src->num_lines, line = src->lines; ix--; line++)
1635 if (!flag_all_blocks)
1637 arc_t *arc, *arc_p, *arc_n;
1639 /* Total and reverse the branch information. */
1640 for (arc = line->u.branches, arc_p = NULL; arc;
1641 arc_p = arc, arc = arc_n)
1643 arc_n = arc->line_next;
1644 arc->line_next = arc_p;
1646 add_branch_counts (&src->coverage, arc);
1648 line->u.branches = arc_p;
1650 else if (line->u.blocks)
1652 /* The user expects the line count to be the number of times
1653 a line has been executed. Simply summing the block count
1654 will give an artificially high number. The Right Thing
1655 is to sum the entry counts to the graph of blocks on this
1656 line, then find the elementary cycles of the local graph
1657 and add the transition counts of those cycles. */
1658 block_t *block, *block_p, *block_n;
1659 gcov_type count = 0;
1661 /* Reverse the block information. */
1662 for (block = line->u.blocks, block_p = NULL; block;
1663 block_p = block, block = block_n)
1665 block_n = block->chain;
1666 block->chain = block_p;
1667 block->u.cycle.ident = ix;
1669 line->u.blocks = block_p;
1671 /* Sum the entry arcs. */
1672 for (block = line->u.blocks; block; block = block->chain)
1674 arc_t *arc;
1676 for (arc = block->pred; arc; arc = arc->pred_next)
1678 if (arc->src->u.cycle.ident != ix)
1679 count += arc->count;
1680 if (flag_branches)
1681 add_branch_counts (&src->coverage, arc);
1684 /* Initialize the cs_count. */
1685 for (arc = block->succ; arc; arc = arc->succ_next)
1686 arc->cs_count = arc->count;
1689 /* Find the loops. This uses the algorithm described in
1690 Tiernan 'An Efficient Search Algorithm to Find the
1691 Elementary Circuits of a Graph', CACM Dec 1970. We hold
1692 the P array by having each block point to the arc that
1693 connects to the previous block. The H array is implicitly
1694 held because of the arc ordering, and the block's
1695 previous arc pointer.
1697 Although the algorithm is O(N^3) for highly connected
1698 graphs, at worst we'll have O(N^2), as most blocks have
1699 only one or two exits. Most graphs will be small.
1701 For each loop we find, locate the arc with the smallest
1702 transition count, and add that to the cumulative
1703 count. Decrease flow over the cycle and remove the arc
1704 from consideration. */
1705 for (block = line->u.blocks; block; block = block->chain)
1707 block_t *head = block;
1708 arc_t *arc;
1710 next_vertex:;
1711 arc = head->succ;
1712 current_vertex:;
1713 while (arc)
1715 block_t *dst = arc->dst;
1716 if (/* Already used that arc. */
1717 arc->cycle
1718 /* Not to same graph, or before first vertex. */
1719 || dst->u.cycle.ident != ix
1720 /* Already in path. */
1721 || dst->u.cycle.arc)
1723 arc = arc->succ_next;
1724 continue;
1727 if (dst == block)
1729 /* Found a closing arc. */
1730 gcov_type cycle_count = arc->cs_count;
1731 arc_t *cycle_arc = arc;
1732 arc_t *probe_arc;
1734 /* Locate the smallest arc count of the loop. */
1735 for (dst = head; (probe_arc = dst->u.cycle.arc);
1736 dst = probe_arc->src)
1737 if (cycle_count > probe_arc->cs_count)
1739 cycle_count = probe_arc->cs_count;
1740 cycle_arc = probe_arc;
1743 count += cycle_count;
1744 cycle_arc->cycle = 1;
1746 /* Remove the flow from the cycle. */
1747 arc->cs_count -= cycle_count;
1748 for (dst = head; (probe_arc = dst->u.cycle.arc);
1749 dst = probe_arc->src)
1750 probe_arc->cs_count -= cycle_count;
1752 /* Unwind to the cyclic arc. */
1753 while (head != cycle_arc->src)
1755 arc = head->u.cycle.arc;
1756 head->u.cycle.arc = NULL;
1757 head = arc->src;
1759 /* Move on. */
1760 arc = arc->succ_next;
1761 continue;
1764 /* Add new block to chain. */
1765 dst->u.cycle.arc = arc;
1766 head = dst;
1767 goto next_vertex;
1769 /* We could not add another vertex to the path. Remove
1770 the last vertex from the list. */
1771 arc = head->u.cycle.arc;
1772 if (arc)
1774 /* It was not the first vertex. Move onto next arc. */
1775 head->u.cycle.arc = NULL;
1776 head = arc->src;
1777 arc = arc->succ_next;
1778 goto current_vertex;
1780 /* Mark this block as unusable. */
1781 block->u.cycle.ident = ~0U;
1784 line->count = count;
1787 if (line->exists)
1789 src->coverage.lines++;
1790 if (line->count)
1791 src->coverage.lines_executed++;
1796 /* Output information about ARC number IX. Returns nonzero if
1797 anything is output. */
1799 static int
1800 output_branch_count (FILE *gcov_file, int ix, const arc_t *arc)
1803 if (arc->is_call_non_return)
1805 if (arc->src->count)
1807 fnotice (gcov_file, "call %2d returned %s\n", ix,
1808 format_gcov (arc->src->count - arc->count,
1809 arc->src->count, -flag_counts));
1811 else
1812 fnotice (gcov_file, "call %2d never executed\n", ix);
1814 else if (!arc->is_unconditional)
1816 if (arc->src->count)
1817 fnotice (gcov_file, "branch %2d taken %s%s\n", ix,
1818 format_gcov (arc->count, arc->src->count, -flag_counts),
1819 arc->fall_through ? " (fallthrough)" : "");
1820 else
1821 fnotice (gcov_file, "branch %2d never executed\n", ix);
1823 else if (flag_unconditional && !arc->dst->is_call_return)
1825 if (arc->src->count)
1826 fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
1827 format_gcov (arc->count, arc->src->count, -flag_counts));
1828 else
1829 fnotice (gcov_file, "unconditional %2d never executed\n", ix);
1831 else
1832 return 0;
1833 return 1;
1837 /* Read in the source file one line at a time, and output that line to
1838 the gcov file preceded by its execution count and other
1839 information. */
1841 static void
1842 output_lines (FILE *gcov_file, const source_t *src)
1844 FILE *source_file;
1845 unsigned line_num; /* current line number. */
1846 const line_t *line; /* current line info ptr. */
1847 char string[STRING_SIZE]; /* line buffer. */
1848 char const *retval = ""; /* status of source file reading. */
1849 function_t *fn = NULL;
1851 fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->name);
1852 if (!multiple_files)
1854 fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
1855 fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0,
1856 no_data_file ? "-" : da_file_name);
1857 fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0,
1858 object_summary.ctrs[GCOV_COUNTER_ARCS].runs);
1860 fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
1862 source_file = fopen (src->name, "r");
1863 if (!source_file)
1865 fnotice (stderr, "%s:cannot open source file\n", src->name);
1866 retval = NULL;
1868 else if (src->file_time == 0)
1869 fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n", "-", 0);
1871 if (flag_branches)
1872 fn = src->functions;
1874 for (line_num = 1, line = &src->lines[line_num];
1875 line_num < src->num_lines; line_num++, line++)
1877 for (; fn && fn->line == line_num; fn = fn->line_next)
1879 arc_t *arc = fn->blocks[fn->num_blocks - 1].pred;
1880 gcov_type return_count = fn->blocks[fn->num_blocks - 1].count;
1882 for (; arc; arc = arc->pred_next)
1883 if (arc->fake)
1884 return_count -= arc->count;
1886 fprintf (gcov_file, "function %s", fn->name);
1887 fprintf (gcov_file, " called %s",
1888 format_gcov (fn->blocks[0].count, 0, -1));
1889 fprintf (gcov_file, " returned %s",
1890 format_gcov (return_count, fn->blocks[0].count, 0));
1891 fprintf (gcov_file, " blocks executed %s",
1892 format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0));
1893 fprintf (gcov_file, "\n");
1896 /* For lines which don't exist in the .bb file, print '-' before
1897 the source line. For lines which exist but were never
1898 executed, print '#####' before the source line. Otherwise,
1899 print the execution count before the source line. There are
1900 16 spaces of indentation added before the source line so that
1901 tabs won't be messed up. */
1902 fprintf (gcov_file, "%9s:%5u:",
1903 !line->exists ? "-" : !line->count ? "#####"
1904 : format_gcov (line->count, 0, -1), line_num);
1906 if (retval)
1908 /* Copy source line. */
1911 retval = fgets (string, STRING_SIZE, source_file);
1912 if (!retval)
1913 break;
1914 fputs (retval, gcov_file);
1916 while (!retval[0] || retval[strlen (retval) - 1] != '\n');
1918 if (!retval)
1919 fputs ("/*EOF*/\n", gcov_file);
1921 if (flag_all_blocks)
1923 block_t *block;
1924 arc_t *arc;
1925 int ix, jx;
1927 for (ix = jx = 0, block = line->u.blocks; block;
1928 block = block->chain)
1930 if (!block->is_call_return)
1931 fprintf (gcov_file, "%9s:%5u-block %2d\n",
1932 !line->exists ? "-" : !block->count ? "$$$$$"
1933 : format_gcov (block->count, 0, -1),
1934 line_num, ix++);
1935 if (flag_branches)
1936 for (arc = block->succ; arc; arc = arc->succ_next)
1937 jx += output_branch_count (gcov_file, jx, arc);
1940 else if (flag_branches)
1942 int ix;
1943 arc_t *arc;
1945 for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
1946 ix += output_branch_count (gcov_file, ix, arc);
1950 /* Handle all remaining source lines. There may be lines after the
1951 last line of code. */
1952 if (retval)
1954 for (; (retval = fgets (string, STRING_SIZE, source_file)); line_num++)
1956 fprintf (gcov_file, "%9s:%5u:%s", "-", line_num, retval);
1958 while (!retval[0] || retval[strlen (retval) - 1] != '\n')
1960 retval = fgets (string, STRING_SIZE, source_file);
1961 if (!retval)
1962 break;
1963 fputs (retval, gcov_file);
1968 if (source_file)
1969 fclose (source_file);