* config/sh/sh.c (push_regs): Emit movml for interrupt handler
[official-gcc.git] / gcc / gcov.c
blob20d5fdf61e699e8ad43e160d616fa5d7e5866afd
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, 2009, 2010
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 /* Output progress indication if this is true. This is off by default
301 and can be turned on by the -d option. */
303 static int flag_display_progress = 0;
305 /* For included files, make the gcov output file name include the name
306 of the input source file. For example, if x.h is included in a.c,
307 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
309 static int flag_long_names = 0;
311 /* Output count information for every basic block, not merely those
312 that contain line number information. */
314 static int flag_all_blocks = 0;
316 /* Output summary info for each function. */
318 static int flag_function_summary = 0;
320 /* Object directory file prefix. This is the directory/file where the
321 graph and data files are looked for, if nonzero. */
323 static char *object_directory = 0;
325 /* Preserve all pathname components. Needed when object files and
326 source files are in subdirectories. '/' is mangled as '#', '.' is
327 elided and '..' mangled to '^'. */
329 static int flag_preserve_paths = 0;
331 /* Output the number of times a branch was taken as opposed to the percentage
332 of times it was taken. */
334 static int flag_counts = 0;
336 /* Forward declarations. */
337 static void fnotice (FILE *, const char *, ...) ATTRIBUTE_PRINTF_2;
338 static int process_args (int, char **);
339 static void print_usage (int) ATTRIBUTE_NORETURN;
340 static void print_version (void) ATTRIBUTE_NORETURN;
341 static void process_file (const char *);
342 static void generate_results (const char *);
343 static void create_file_names (const char *);
344 static source_t *find_source (const char *);
345 static int read_graph_file (void);
346 static int read_count_file (void);
347 static void solve_flow_graph (function_t *);
348 static void add_branch_counts (coverage_t *, const arc_t *);
349 static void add_line_counts (coverage_t *, function_t *);
350 static void function_summary (const coverage_t *, const char *);
351 static const char *format_gcov (gcov_type, gcov_type, int);
352 static void accumulate_line_counts (source_t *);
353 static int output_branch_count (FILE *, int, const arc_t *);
354 static void output_lines (FILE *, const source_t *);
355 static char *make_gcov_file_name (const char *, const char *);
356 static void release_structures (void);
357 extern int main (int, char **);
360 main (int argc, char **argv)
362 int argno;
363 int first_arg;
365 /* Unlock the stdio streams. */
366 unlock_std_streams ();
368 gcc_init_libintl ();
370 /* Handle response files. */
371 expandargv (&argc, &argv);
373 argno = process_args (argc, argv);
374 if (optind == argc)
375 print_usage (true);
377 if (argc - argno > 1)
378 multiple_files = 1;
380 first_arg = argno;
382 for (; argno != argc; argno++)
384 if (flag_display_progress)
385 printf("Processing file %d out of %d\n",
386 argno - first_arg + 1, argc - first_arg);
387 process_file (argv[argno]);
390 generate_results (multiple_files ? NULL : argv[argc - 1]);
392 release_structures ();
394 return 0;
397 static void
398 fnotice (FILE *file, const char *cmsgid, ...)
400 va_list ap;
402 va_start (ap, cmsgid);
403 vfprintf (file, _(cmsgid), ap);
404 va_end (ap);
407 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
408 otherwise the output of --help. */
410 static void
411 print_usage (int error_p)
413 FILE *file = error_p ? stderr : stdout;
414 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
416 fnotice (file, "Usage: gcov [OPTION]... SOURCEFILE...\n\n");
417 fnotice (file, "Print code coverage information.\n\n");
418 fnotice (file, " -h, --help Print this help, then exit\n");
419 fnotice (file, " -v, --version Print version number, then exit\n");
420 fnotice (file, " -a, --all-blocks Show information for every basic block\n");
421 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
422 fnotice (file, " -c, --branch-counts Given counts of branches taken\n\
423 rather than percentages\n");
424 fnotice (file, " -n, --no-output Do not create an output file\n");
425 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
426 source files\n");
427 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
428 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
429 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
430 fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
431 fnotice (file, " -d, --display-progress Display progress information\n");
432 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
433 bug_report_url);
434 exit (status);
437 /* Print version information and exit. */
439 static void
440 print_version (void)
442 fnotice (stdout, "gcov %s%s\n", pkgversion_string, version_string);
443 fprintf (stdout, "Copyright %s 2010 Free Software Foundation, Inc.\n",
444 _("(C)"));
445 fnotice (stdout,
446 _("This is free software; see the source for copying conditions.\n"
447 "There is NO warranty; not even for MERCHANTABILITY or \n"
448 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
449 exit (SUCCESS_EXIT_CODE);
452 static const struct option options[] =
454 { "help", no_argument, NULL, 'h' },
455 { "version", no_argument, NULL, 'v' },
456 { "all-blocks", no_argument, NULL, 'a' },
457 { "branch-probabilities", no_argument, NULL, 'b' },
458 { "branch-counts", no_argument, NULL, 'c' },
459 { "no-output", no_argument, NULL, 'n' },
460 { "long-file-names", no_argument, NULL, 'l' },
461 { "function-summaries", no_argument, NULL, 'f' },
462 { "preserve-paths", no_argument, NULL, 'p' },
463 { "object-directory", required_argument, NULL, 'o' },
464 { "object-file", required_argument, NULL, 'o' },
465 { "unconditional-branches", no_argument, NULL, 'u' },
466 { "display-progress", no_argument, NULL, 'd' },
467 { 0, 0, 0, 0 }
470 /* Process args, return index to first non-arg. */
472 static int
473 process_args (int argc, char **argv)
475 int opt;
477 while ((opt = getopt_long (argc, argv, "abcdfhlno:puv", options, NULL)) != -1)
479 switch (opt)
481 case 'a':
482 flag_all_blocks = 1;
483 break;
484 case 'b':
485 flag_branches = 1;
486 break;
487 case 'c':
488 flag_counts = 1;
489 break;
490 case 'f':
491 flag_function_summary = 1;
492 break;
493 case 'h':
494 print_usage (false);
495 /* print_usage will exit. */
496 case 'l':
497 flag_long_names = 1;
498 break;
499 case 'n':
500 flag_gcov_file = 0;
501 break;
502 case 'o':
503 object_directory = optarg;
504 break;
505 case 'p':
506 flag_preserve_paths = 1;
507 break;
508 case 'u':
509 flag_unconditional = 1;
510 break;
511 case 'd':
512 flag_display_progress = 1;
513 break;
514 case 'v':
515 print_version ();
516 /* print_version will exit. */
517 default:
518 print_usage (true);
519 /* print_usage will exit. */
523 return optind;
526 /* Process a single source file. */
528 static void
529 process_file (const char *file_name)
531 function_t *fn;
532 function_t *fn_p;
533 function_t *old_functions;
535 /* Save and clear the list of current functions. They will be appended
536 later. */
537 old_functions = functions;
538 functions = NULL;
540 create_file_names (file_name);
541 if (read_graph_file ())
542 return;
544 if (!functions)
546 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
547 return;
550 if (read_count_file ())
551 return;
553 for (fn_p = NULL, fn = functions; fn; fn_p = fn, fn = fn->next)
554 solve_flow_graph (fn);
556 if (fn_p)
557 fn_p->next = old_functions;
560 static void
561 generate_results (const char *file_name)
563 source_t *src;
564 function_t *fn;
566 for (src = sources; src; src = src->next)
567 src->lines = XCNEWVEC (line_t, src->num_lines);
568 for (fn = functions; fn; fn = fn->next)
570 coverage_t coverage;
572 memset (&coverage, 0, sizeof (coverage));
573 coverage.name = fn->name;
574 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
575 if (flag_function_summary)
577 function_summary (&coverage, "Function");
578 fnotice (stdout, "\n");
582 for (src = sources; src; src = src->next)
584 accumulate_line_counts (src);
585 function_summary (&src->coverage, "File");
586 if (flag_gcov_file)
588 char *gcov_file_name = make_gcov_file_name (file_name, src->name);
589 FILE *gcov_file = fopen (gcov_file_name, "w");
591 if (gcov_file)
593 fnotice (stdout, "%s:creating '%s'\n",
594 src->name, gcov_file_name);
595 output_lines (gcov_file, src);
596 if (ferror (gcov_file))
597 fnotice (stderr, "%s:error writing output file '%s'\n",
598 src->name, gcov_file_name);
599 fclose (gcov_file);
601 else
602 fnotice (stderr, "%s:could not open output file '%s'\n",
603 src->name, gcov_file_name);
604 free (gcov_file_name);
606 fnotice (stdout, "\n");
610 /* Release all memory used. */
612 static void
613 release_structures (void)
615 function_t *fn;
616 source_t *src;
618 while ((src = sources))
620 sources = src->next;
622 free (src->name);
623 free (src->lines);
626 while ((fn = functions))
628 unsigned ix;
629 block_t *block;
631 functions = fn->next;
632 for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
634 arc_t *arc, *arc_n;
636 for (arc = block->succ; arc; arc = arc_n)
638 arc_n = arc->succ_next;
639 free (arc);
642 free (fn->blocks);
643 free (fn->counts);
647 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
648 is not specified, these are looked for in the current directory,
649 and named from the basename of the FILE_NAME sans extension. If
650 OBJECT_DIRECTORY is specified and is a directory, the files are in
651 that directory, but named from the basename of the FILE_NAME, sans
652 extension. Otherwise OBJECT_DIRECTORY is taken to be the name of
653 the object *file*, and the data files are named from that. */
655 static void
656 create_file_names (const char *file_name)
658 char *cptr;
659 char *name;
660 int length = strlen (file_name);
661 int base;
663 /* Free previous file names. */
664 if (bbg_file_name)
665 free (bbg_file_name);
666 if (da_file_name)
667 free (da_file_name);
668 da_file_name = bbg_file_name = NULL;
669 bbg_file_time = 0;
670 bbg_stamp = 0;
672 if (object_directory && object_directory[0])
674 struct stat status;
676 length += strlen (object_directory) + 2;
677 name = XNEWVEC (char, length);
678 name[0] = 0;
680 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
681 strcat (name, object_directory);
682 if (base && (! IS_DIR_SEPARATOR (name[strlen (name) - 1])))
683 strcat (name, "/");
685 else
687 name = XNEWVEC (char, length + 1);
688 name[0] = 0;
689 base = 1;
692 if (base)
694 /* Append source file name. */
695 const char *cptr = lbasename (file_name);
696 strcat (name, cptr ? cptr : file_name);
699 /* Remove the extension. */
700 cptr = strrchr (name, '.');
701 if (cptr)
702 *cptr = 0;
704 length = strlen (name);
706 bbg_file_name = XNEWVEC (char, length + strlen (GCOV_NOTE_SUFFIX) + 1);
707 strcpy (bbg_file_name, name);
708 strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
710 da_file_name = XNEWVEC (char, length + strlen (GCOV_DATA_SUFFIX) + 1);
711 strcpy (da_file_name, name);
712 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
714 free (name);
715 return;
718 /* Find or create a source file structure for FILE_NAME. Copies
719 FILE_NAME on creation */
721 static source_t *
722 find_source (const char *file_name)
724 source_t *src;
725 struct stat status;
727 if (!file_name)
728 file_name = "<unknown>";
730 for (src = sources; src; src = src->next)
731 if (!strcmp (file_name, src->name))
732 break;
734 if (!src)
736 src = XCNEW (source_t);
737 src->name = xstrdup (file_name);
738 src->coverage.name = src->name;
739 src->index = source_index++;
740 src->next = sources;
741 sources = src;
743 if (!stat (file_name, &status))
744 src->file_time = status.st_mtime;
747 if (src->file_time > bbg_file_time)
749 static int info_emitted;
751 fnotice (stderr, "%s:source file is newer than graph file '%s'\n",
752 src->name, bbg_file_name);
753 if (!info_emitted)
755 fnotice (stderr,
756 "(the message is only displayed one per source file)\n");
757 info_emitted = 1;
759 src->file_time = 0;
762 return src;
765 /* Read the graph file. Return nonzero on fatal error. */
767 static int
768 read_graph_file (void)
770 unsigned version;
771 unsigned current_tag = 0;
772 struct function_info *fn = NULL;
773 function_t *old_functions_head = functions;
774 source_t *src = NULL;
775 unsigned ix;
776 unsigned tag;
778 if (!gcov_open (bbg_file_name, 1))
780 fnotice (stderr, "%s:cannot open graph file\n", bbg_file_name);
781 return 1;
783 bbg_file_time = gcov_time ();
784 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
786 fnotice (stderr, "%s:not a gcov graph file\n", bbg_file_name);
787 gcov_close ();
788 return 1;
791 version = gcov_read_unsigned ();
792 if (version != GCOV_VERSION)
794 char v[4], e[4];
796 GCOV_UNSIGNED2STRING (v, version);
797 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
799 fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n",
800 bbg_file_name, v, e);
802 bbg_stamp = gcov_read_unsigned ();
804 while ((tag = gcov_read_unsigned ()))
806 unsigned length = gcov_read_unsigned ();
807 gcov_position_t base = gcov_position ();
809 if (tag == GCOV_TAG_FUNCTION)
811 char *function_name;
812 unsigned ident, checksum, lineno;
813 source_t *src;
814 function_t *probe, *prev;
816 ident = gcov_read_unsigned ();
817 checksum = gcov_read_unsigned ();
818 function_name = xstrdup (gcov_read_string ());
819 src = find_source (gcov_read_string ());
820 lineno = gcov_read_unsigned ();
822 fn = XCNEW (function_t);
823 fn->name = function_name;
824 fn->ident = ident;
825 fn->checksum = checksum;
826 fn->src = src;
827 fn->line = lineno;
829 fn->next = functions;
830 functions = fn;
831 current_tag = tag;
833 if (lineno >= src->num_lines)
834 src->num_lines = lineno + 1;
835 /* Now insert it into the source file's list of
836 functions. Normally functions will be encountered in
837 ascending order, so a simple scan is quick. */
838 for (probe = src->functions, prev = NULL;
839 probe && probe->line > lineno;
840 prev = probe, probe = probe->line_next)
841 continue;
842 fn->line_next = probe;
843 if (prev)
844 prev->line_next = fn;
845 else
846 src->functions = fn;
848 else if (fn && tag == GCOV_TAG_BLOCKS)
850 if (fn->blocks)
851 fnotice (stderr, "%s:already seen blocks for '%s'\n",
852 bbg_file_name, fn->name);
853 else
855 unsigned ix, num_blocks = GCOV_TAG_BLOCKS_NUM (length);
856 fn->num_blocks = num_blocks;
858 fn->blocks = XCNEWVEC (block_t, fn->num_blocks);
859 for (ix = 0; ix != num_blocks; ix++)
860 fn->blocks[ix].flags = gcov_read_unsigned ();
863 else if (fn && tag == GCOV_TAG_ARCS)
865 unsigned src = gcov_read_unsigned ();
866 unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
868 if (src >= fn->num_blocks || fn->blocks[src].succ)
869 goto corrupt;
871 while (num_dests--)
873 struct arc_info *arc;
874 unsigned dest = gcov_read_unsigned ();
875 unsigned flags = gcov_read_unsigned ();
877 if (dest >= fn->num_blocks)
878 goto corrupt;
879 arc = XCNEW (arc_t);
881 arc->dst = &fn->blocks[dest];
882 arc->src = &fn->blocks[src];
884 arc->count = 0;
885 arc->count_valid = 0;
886 arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
887 arc->fake = !!(flags & GCOV_ARC_FAKE);
888 arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
890 arc->succ_next = fn->blocks[src].succ;
891 fn->blocks[src].succ = arc;
892 fn->blocks[src].num_succ++;
894 arc->pred_next = fn->blocks[dest].pred;
895 fn->blocks[dest].pred = arc;
896 fn->blocks[dest].num_pred++;
898 if (arc->fake)
900 if (src)
902 /* Exceptional exit from this function, the
903 source block must be a call. */
904 fn->blocks[src].is_call_site = 1;
905 arc->is_call_non_return = 1;
907 else
909 /* Non-local return from a callee of this
910 function. The destination block is a catch or
911 setjmp. */
912 arc->is_nonlocal_return = 1;
913 fn->blocks[dest].is_nonlocal_return = 1;
917 if (!arc->on_tree)
918 fn->num_counts++;
921 else if (fn && tag == GCOV_TAG_LINES)
923 unsigned blockno = gcov_read_unsigned ();
924 unsigned *line_nos = XCNEWVEC (unsigned, length - 1);
926 if (blockno >= fn->num_blocks || fn->blocks[blockno].u.line.encoding)
927 goto corrupt;
929 for (ix = 0; ; )
931 unsigned lineno = gcov_read_unsigned ();
933 if (lineno)
935 if (!ix)
937 line_nos[ix++] = 0;
938 line_nos[ix++] = src->index;
940 line_nos[ix++] = lineno;
941 if (lineno >= src->num_lines)
942 src->num_lines = lineno + 1;
944 else
946 const char *file_name = gcov_read_string ();
948 if (!file_name)
949 break;
950 src = find_source (file_name);
952 line_nos[ix++] = 0;
953 line_nos[ix++] = src->index;
957 fn->blocks[blockno].u.line.encoding = line_nos;
958 fn->blocks[blockno].u.line.num = ix;
960 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
962 fn = NULL;
963 current_tag = 0;
965 gcov_sync (base, length);
966 if (gcov_is_error ())
968 corrupt:;
969 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
970 gcov_close ();
971 return 1;
974 gcov_close ();
976 /* We built everything backwards, so nreverse them all. */
978 /* Reverse sources. Not strictly necessary, but we'll then process
979 them in the 'expected' order. */
981 source_t *src, *src_p, *src_n;
983 for (src_p = NULL, src = sources; src; src_p = src, src = src_n)
985 src_n = src->next;
986 src->next = src_p;
988 sources = src_p;
991 /* Reverse functions. */
993 function_t *fn, *fn_p, *fn_n;
995 for (fn_p = old_functions_head, fn = functions;
996 fn != old_functions_head;
997 fn_p = fn, fn = fn_n)
999 unsigned ix;
1001 fn_n = fn->next;
1002 fn->next = fn_p;
1004 /* Reverse the arcs. */
1005 for (ix = fn->num_blocks; ix--;)
1007 arc_t *arc, *arc_p, *arc_n;
1009 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
1010 arc_p = arc, arc = arc_n)
1012 arc_n = arc->succ_next;
1013 arc->succ_next = arc_p;
1015 fn->blocks[ix].succ = arc_p;
1017 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
1018 arc_p = arc, arc = arc_n)
1020 arc_n = arc->pred_next;
1021 arc->pred_next = arc_p;
1023 fn->blocks[ix].pred = arc_p;
1026 functions = fn_p;
1028 return 0;
1031 /* Reads profiles from the count file and attach to each
1032 function. Return nonzero if fatal error. */
1034 static int
1035 read_count_file (void)
1037 unsigned ix;
1038 unsigned version;
1039 unsigned tag;
1040 function_t *fn = NULL;
1041 int error = 0;
1043 if (!gcov_open (da_file_name, 1))
1045 fnotice (stderr, "%s:cannot open data file, assuming not executed\n",
1046 da_file_name);
1047 no_data_file = 1;
1048 return 0;
1050 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
1052 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
1053 cleanup:;
1054 gcov_close ();
1055 return 1;
1057 version = gcov_read_unsigned ();
1058 if (version != GCOV_VERSION)
1060 char v[4], e[4];
1062 GCOV_UNSIGNED2STRING (v, version);
1063 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1065 fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
1066 da_file_name, v, e);
1068 tag = gcov_read_unsigned ();
1069 if (tag != bbg_stamp)
1071 fnotice (stderr, "%s:stamp mismatch with graph file\n", da_file_name);
1072 goto cleanup;
1075 while ((tag = gcov_read_unsigned ()))
1077 unsigned length = gcov_read_unsigned ();
1078 unsigned long base = gcov_position ();
1080 if (tag == GCOV_TAG_OBJECT_SUMMARY)
1081 gcov_read_summary (&object_summary);
1082 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
1083 program_count++;
1084 else if (tag == GCOV_TAG_FUNCTION)
1087 unsigned ident = gcov_read_unsigned ();
1088 struct function_info *fn_n = functions;
1090 /* Try to find the function in the list.
1091 To speed up the search, first start from the last function
1092 found. */
1093 for (fn = fn ? fn->next : NULL; ; fn = fn->next)
1095 if (fn)
1097 else if ((fn = fn_n))
1098 fn_n = NULL;
1099 else
1101 fnotice (stderr, "%s:unknown function '%u'\n",
1102 da_file_name, ident);
1103 break;
1105 if (fn->ident == ident)
1106 break;
1110 if (!fn)
1112 else if (gcov_read_unsigned () != fn->checksum)
1114 mismatch:;
1115 fnotice (stderr, "%s:profile mismatch for '%s'\n",
1116 da_file_name, fn->name);
1117 goto cleanup;
1120 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
1122 if (length != GCOV_TAG_COUNTER_LENGTH (fn->num_counts))
1123 goto mismatch;
1125 if (!fn->counts)
1126 fn->counts = XCNEWVEC (gcov_type, fn->num_counts);
1128 for (ix = 0; ix != fn->num_counts; ix++)
1129 fn->counts[ix] += gcov_read_counter ();
1131 gcov_sync (base, length);
1132 if ((error = gcov_is_error ()))
1134 fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1135 da_file_name);
1136 goto cleanup;
1140 gcov_close ();
1141 return 0;
1144 /* Solve the flow graph. Propagate counts from the instrumented arcs
1145 to the blocks and the uninstrumented arcs. */
1147 static void
1148 solve_flow_graph (function_t *fn)
1150 unsigned ix;
1151 arc_t *arc;
1152 gcov_type *count_ptr = fn->counts;
1153 block_t *blk;
1154 block_t *valid_blocks = NULL; /* valid, but unpropagated blocks. */
1155 block_t *invalid_blocks = NULL; /* invalid, but inferable blocks. */
1157 if (fn->num_blocks < 2)
1158 fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n",
1159 bbg_file_name, fn->name);
1160 else
1162 if (fn->blocks[0].num_pred)
1163 fnotice (stderr, "%s:'%s' has arcs to entry block\n",
1164 bbg_file_name, fn->name);
1165 else
1166 /* We can't deduce the entry block counts from the lack of
1167 predecessors. */
1168 fn->blocks[0].num_pred = ~(unsigned)0;
1170 if (fn->blocks[fn->num_blocks - 1].num_succ)
1171 fnotice (stderr, "%s:'%s' has arcs from exit block\n",
1172 bbg_file_name, fn->name);
1173 else
1174 /* Likewise, we can't deduce exit block counts from the lack
1175 of its successors. */
1176 fn->blocks[fn->num_blocks - 1].num_succ = ~(unsigned)0;
1179 /* Propagate the measured counts, this must be done in the same
1180 order as the code in profile.c */
1181 for (ix = 0, blk = fn->blocks; ix != fn->num_blocks; ix++, blk++)
1183 block_t const *prev_dst = NULL;
1184 int out_of_order = 0;
1185 int non_fake_succ = 0;
1187 for (arc = blk->succ; arc; arc = arc->succ_next)
1189 if (!arc->fake)
1190 non_fake_succ++;
1192 if (!arc->on_tree)
1194 if (count_ptr)
1195 arc->count = *count_ptr++;
1196 arc->count_valid = 1;
1197 blk->num_succ--;
1198 arc->dst->num_pred--;
1200 if (prev_dst && prev_dst > arc->dst)
1201 out_of_order = 1;
1202 prev_dst = arc->dst;
1204 if (non_fake_succ == 1)
1206 /* If there is only one non-fake exit, it is an
1207 unconditional branch. */
1208 for (arc = blk->succ; arc; arc = arc->succ_next)
1209 if (!arc->fake)
1211 arc->is_unconditional = 1;
1212 /* If this block is instrumenting a call, it might be
1213 an artificial block. It is not artificial if it has
1214 a non-fallthrough exit, or the destination of this
1215 arc has more than one entry. Mark the destination
1216 block as a return site, if none of those conditions
1217 hold. */
1218 if (blk->is_call_site && arc->fall_through
1219 && arc->dst->pred == arc && !arc->pred_next)
1220 arc->dst->is_call_return = 1;
1224 /* Sort the successor arcs into ascending dst order. profile.c
1225 normally produces arcs in the right order, but sometimes with
1226 one or two out of order. We're not using a particularly
1227 smart sort. */
1228 if (out_of_order)
1230 arc_t *start = blk->succ;
1231 unsigned changes = 1;
1233 while (changes)
1235 arc_t *arc, *arc_p, *arc_n;
1237 changes = 0;
1238 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1240 if (arc->dst > arc_n->dst)
1242 changes = 1;
1243 if (arc_p)
1244 arc_p->succ_next = arc_n;
1245 else
1246 start = arc_n;
1247 arc->succ_next = arc_n->succ_next;
1248 arc_n->succ_next = arc;
1249 arc_p = arc_n;
1251 else
1253 arc_p = arc;
1254 arc = arc_n;
1258 blk->succ = start;
1261 /* Place it on the invalid chain, it will be ignored if that's
1262 wrong. */
1263 blk->invalid_chain = 1;
1264 blk->chain = invalid_blocks;
1265 invalid_blocks = blk;
1268 while (invalid_blocks || valid_blocks)
1270 while ((blk = invalid_blocks))
1272 gcov_type total = 0;
1273 const arc_t *arc;
1275 invalid_blocks = blk->chain;
1276 blk->invalid_chain = 0;
1277 if (!blk->num_succ)
1278 for (arc = blk->succ; arc; arc = arc->succ_next)
1279 total += arc->count;
1280 else if (!blk->num_pred)
1281 for (arc = blk->pred; arc; arc = arc->pred_next)
1282 total += arc->count;
1283 else
1284 continue;
1286 blk->count = total;
1287 blk->count_valid = 1;
1288 blk->chain = valid_blocks;
1289 blk->valid_chain = 1;
1290 valid_blocks = blk;
1292 while ((blk = valid_blocks))
1294 gcov_type total;
1295 arc_t *arc, *inv_arc;
1297 valid_blocks = blk->chain;
1298 blk->valid_chain = 0;
1299 if (blk->num_succ == 1)
1301 block_t *dst;
1303 total = blk->count;
1304 inv_arc = NULL;
1305 for (arc = blk->succ; arc; arc = arc->succ_next)
1307 total -= arc->count;
1308 if (!arc->count_valid)
1309 inv_arc = arc;
1311 dst = inv_arc->dst;
1312 inv_arc->count_valid = 1;
1313 inv_arc->count = total;
1314 blk->num_succ--;
1315 dst->num_pred--;
1316 if (dst->count_valid)
1318 if (dst->num_pred == 1 && !dst->valid_chain)
1320 dst->chain = valid_blocks;
1321 dst->valid_chain = 1;
1322 valid_blocks = dst;
1325 else
1327 if (!dst->num_pred && !dst->invalid_chain)
1329 dst->chain = invalid_blocks;
1330 dst->invalid_chain = 1;
1331 invalid_blocks = dst;
1335 if (blk->num_pred == 1)
1337 block_t *src;
1339 total = blk->count;
1340 inv_arc = NULL;
1341 for (arc = blk->pred; arc; arc = arc->pred_next)
1343 total -= arc->count;
1344 if (!arc->count_valid)
1345 inv_arc = arc;
1347 src = inv_arc->src;
1348 inv_arc->count_valid = 1;
1349 inv_arc->count = total;
1350 blk->num_pred--;
1351 src->num_succ--;
1352 if (src->count_valid)
1354 if (src->num_succ == 1 && !src->valid_chain)
1356 src->chain = valid_blocks;
1357 src->valid_chain = 1;
1358 valid_blocks = src;
1361 else
1363 if (!src->num_succ && !src->invalid_chain)
1365 src->chain = invalid_blocks;
1366 src->invalid_chain = 1;
1367 invalid_blocks = src;
1374 /* If the graph has been correctly solved, every block will have a
1375 valid count. */
1376 for (ix = 0; ix < fn->num_blocks; ix++)
1377 if (!fn->blocks[ix].count_valid)
1379 fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
1380 bbg_file_name, fn->name);
1381 break;
1387 /* Increment totals in COVERAGE according to arc ARC. */
1389 static void
1390 add_branch_counts (coverage_t *coverage, const arc_t *arc)
1392 if (arc->is_call_non_return)
1394 coverage->calls++;
1395 if (arc->src->count)
1396 coverage->calls_executed++;
1398 else if (!arc->is_unconditional)
1400 coverage->branches++;
1401 if (arc->src->count)
1402 coverage->branches_executed++;
1403 if (arc->count)
1404 coverage->branches_taken++;
1408 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1409 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1410 If DP is zero, no decimal point is printed. Only print 100% when
1411 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1412 format TOP. Return pointer to a static string. */
1414 static char const *
1415 format_gcov (gcov_type top, gcov_type bottom, int dp)
1417 static char buffer[20];
1419 if (dp >= 0)
1421 float ratio = bottom ? (float)top / bottom : 0;
1422 int ix;
1423 unsigned limit = 100;
1424 unsigned percent;
1426 for (ix = dp; ix--; )
1427 limit *= 10;
1429 percent = (unsigned) (ratio * limit + (float)0.5);
1430 if (percent <= 0 && top)
1431 percent = 1;
1432 else if (percent >= limit && top != bottom)
1433 percent = limit - 1;
1434 ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1435 if (dp)
1437 dp++;
1440 buffer[ix+1] = buffer[ix];
1441 ix--;
1443 while (dp--);
1444 buffer[ix + 1] = '.';
1447 else
1448 sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)top);
1450 return buffer;
1454 /* Output summary info for a function. */
1456 static void
1457 function_summary (const coverage_t *coverage, const char *title)
1459 fnotice (stdout, "%s '%s'\n", title, coverage->name);
1461 if (coverage->lines)
1462 fnotice (stdout, "Lines executed:%s of %d\n",
1463 format_gcov (coverage->lines_executed, coverage->lines, 2),
1464 coverage->lines);
1465 else
1466 fnotice (stdout, "No executable lines\n");
1468 if (flag_branches)
1470 if (coverage->branches)
1472 fnotice (stdout, "Branches executed:%s of %d\n",
1473 format_gcov (coverage->branches_executed,
1474 coverage->branches, 2),
1475 coverage->branches);
1476 fnotice (stdout, "Taken at least once:%s of %d\n",
1477 format_gcov (coverage->branches_taken,
1478 coverage->branches, 2),
1479 coverage->branches);
1481 else
1482 fnotice (stdout, "No branches\n");
1483 if (coverage->calls)
1484 fnotice (stdout, "Calls executed:%s of %d\n",
1485 format_gcov (coverage->calls_executed, coverage->calls, 2),
1486 coverage->calls);
1487 else
1488 fnotice (stdout, "No calls\n");
1492 /* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
1493 affect name generation. With preserve_paths we create a filename
1494 from all path components of the source file, replacing '/' with
1495 '#', without it we simply take the basename component. With
1496 long_output_names we prepend the processed name of the input file
1497 to each output name (except when the current source file is the
1498 input file, so you don't get a double concatenation). The two
1499 components are separated by '##'. Also '.' filename components are
1500 removed and '..' components are renamed to '^'. */
1502 static char *
1503 make_gcov_file_name (const char *input_name, const char *src_name)
1505 const char *cptr;
1506 char *name;
1508 if (flag_long_names && input_name && strcmp (src_name, input_name))
1510 name = XNEWVEC (char, strlen (src_name) + strlen (input_name) + 10);
1511 name[0] = 0;
1512 /* Generate the input filename part. */
1513 cptr = flag_preserve_paths ? NULL : lbasename (input_name);
1514 strcat (name, cptr ? cptr : input_name);
1515 strcat (name, "##");
1517 else
1519 name = XNEWVEC (char, strlen (src_name) + 10);
1520 name[0] = 0;
1523 /* Generate the source filename part. */
1525 cptr = flag_preserve_paths ? NULL : lbasename (src_name);
1526 strcat (name, cptr ? cptr : src_name);
1528 if (flag_preserve_paths)
1530 /* Convert '/' and '\' to '#', remove '/./', convert '/../' to '/^/',
1531 convert ':' to '~' on DOS based file system. */
1532 char *pnew = name, *pold = name;
1534 /* First check for leading drive separator. */
1536 while (*pold != '\0')
1538 if (*pold == '/' || *pold == '\\')
1540 *pnew++ = '#';
1541 pold++;
1543 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
1544 else if (*pold == ':')
1546 *pnew++ = '~';
1547 pold++;
1549 #endif
1550 else if ((*pold == '/' && strstr (pold, "/./") == pold)
1551 || (*pold == '\\' && strstr (pold, "\\.\\") == pold))
1552 pold += 3;
1553 else if (*pold == '/' && strstr (pold, "/../") == pold)
1555 strcpy (pnew, "/^/");
1556 pnew += 3;
1557 pold += 4;
1559 else if (*pold == '\\' && strstr (pold, "\\..\\") == pold)
1561 strcpy (pnew, "\\^\\");
1562 pnew += 3;
1563 pold += 4;
1565 else
1566 *pnew++ = *pold++;
1569 *pnew = '\0';
1572 strcat (name, ".gcov");
1573 return name;
1576 /* Scan through the bb_data for each line in the block, increment
1577 the line number execution count indicated by the execution count of
1578 the appropriate basic block. */
1580 static void
1581 add_line_counts (coverage_t *coverage, function_t *fn)
1583 unsigned ix;
1584 line_t *line = NULL; /* This is propagated from one iteration to the
1585 next. */
1587 /* Scan each basic block. */
1588 for (ix = 0; ix != fn->num_blocks; ix++)
1590 block_t *block = &fn->blocks[ix];
1591 unsigned *encoding;
1592 const source_t *src = NULL;
1593 unsigned jx;
1595 if (block->count && ix && ix + 1 != fn->num_blocks)
1596 fn->blocks_executed++;
1597 for (jx = 0, encoding = block->u.line.encoding;
1598 jx != block->u.line.num; jx++, encoding++)
1599 if (!*encoding)
1601 unsigned src_n = *++encoding;
1603 for (src = sources; src->index != src_n; src = src->next)
1604 continue;
1605 jx++;
1607 else
1609 line = &src->lines[*encoding];
1611 if (coverage)
1613 if (!line->exists)
1614 coverage->lines++;
1615 if (!line->count && block->count)
1616 coverage->lines_executed++;
1618 line->exists = 1;
1619 line->count += block->count;
1621 free (block->u.line.encoding);
1622 block->u.cycle.arc = NULL;
1623 block->u.cycle.ident = ~0U;
1625 if (!ix || ix + 1 == fn->num_blocks)
1626 /* Entry or exit block */;
1627 else if (flag_all_blocks)
1629 line_t *block_line = line ? line : &fn->src->lines[fn->line];
1631 block->chain = block_line->u.blocks;
1632 block_line->u.blocks = block;
1634 else if (flag_branches)
1636 arc_t *arc;
1638 for (arc = block->succ; arc; arc = arc->succ_next)
1640 arc->line_next = line->u.branches;
1641 line->u.branches = arc;
1642 if (coverage && !arc->is_unconditional)
1643 add_branch_counts (coverage, arc);
1647 if (!line)
1648 fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, fn->name);
1651 /* Accumulate the line counts of a file. */
1653 static void
1654 accumulate_line_counts (source_t *src)
1656 line_t *line;
1657 function_t *fn, *fn_p, *fn_n;
1658 unsigned ix;
1660 /* Reverse the function order. */
1661 for (fn = src->functions, fn_p = NULL; fn;
1662 fn_p = fn, fn = fn_n)
1664 fn_n = fn->line_next;
1665 fn->line_next = fn_p;
1667 src->functions = fn_p;
1669 for (ix = src->num_lines, line = src->lines; ix--; line++)
1671 if (!flag_all_blocks)
1673 arc_t *arc, *arc_p, *arc_n;
1675 /* Total and reverse the branch information. */
1676 for (arc = line->u.branches, arc_p = NULL; arc;
1677 arc_p = arc, arc = arc_n)
1679 arc_n = arc->line_next;
1680 arc->line_next = arc_p;
1682 add_branch_counts (&src->coverage, arc);
1684 line->u.branches = arc_p;
1686 else if (line->u.blocks)
1688 /* The user expects the line count to be the number of times
1689 a line has been executed. Simply summing the block count
1690 will give an artificially high number. The Right Thing
1691 is to sum the entry counts to the graph of blocks on this
1692 line, then find the elementary cycles of the local graph
1693 and add the transition counts of those cycles. */
1694 block_t *block, *block_p, *block_n;
1695 gcov_type count = 0;
1697 /* Reverse the block information. */
1698 for (block = line->u.blocks, block_p = NULL; block;
1699 block_p = block, block = block_n)
1701 block_n = block->chain;
1702 block->chain = block_p;
1703 block->u.cycle.ident = ix;
1705 line->u.blocks = block_p;
1707 /* Sum the entry arcs. */
1708 for (block = line->u.blocks; block; block = block->chain)
1710 arc_t *arc;
1712 for (arc = block->pred; arc; arc = arc->pred_next)
1714 if (arc->src->u.cycle.ident != ix)
1715 count += arc->count;
1716 if (flag_branches)
1717 add_branch_counts (&src->coverage, arc);
1720 /* Initialize the cs_count. */
1721 for (arc = block->succ; arc; arc = arc->succ_next)
1722 arc->cs_count = arc->count;
1725 /* Find the loops. This uses the algorithm described in
1726 Tiernan 'An Efficient Search Algorithm to Find the
1727 Elementary Circuits of a Graph', CACM Dec 1970. We hold
1728 the P array by having each block point to the arc that
1729 connects to the previous block. The H array is implicitly
1730 held because of the arc ordering, and the block's
1731 previous arc pointer.
1733 Although the algorithm is O(N^3) for highly connected
1734 graphs, at worst we'll have O(N^2), as most blocks have
1735 only one or two exits. Most graphs will be small.
1737 For each loop we find, locate the arc with the smallest
1738 transition count, and add that to the cumulative
1739 count. Decrease flow over the cycle and remove the arc
1740 from consideration. */
1741 for (block = line->u.blocks; block; block = block->chain)
1743 block_t *head = block;
1744 arc_t *arc;
1746 next_vertex:;
1747 arc = head->succ;
1748 current_vertex:;
1749 while (arc)
1751 block_t *dst = arc->dst;
1752 if (/* Already used that arc. */
1753 arc->cycle
1754 /* Not to same graph, or before first vertex. */
1755 || dst->u.cycle.ident != ix
1756 /* Already in path. */
1757 || dst->u.cycle.arc)
1759 arc = arc->succ_next;
1760 continue;
1763 if (dst == block)
1765 /* Found a closing arc. */
1766 gcov_type cycle_count = arc->cs_count;
1767 arc_t *cycle_arc = arc;
1768 arc_t *probe_arc;
1770 /* Locate the smallest arc count of the loop. */
1771 for (dst = head; (probe_arc = dst->u.cycle.arc);
1772 dst = probe_arc->src)
1773 if (cycle_count > probe_arc->cs_count)
1775 cycle_count = probe_arc->cs_count;
1776 cycle_arc = probe_arc;
1779 count += cycle_count;
1780 cycle_arc->cycle = 1;
1782 /* Remove the flow from the cycle. */
1783 arc->cs_count -= cycle_count;
1784 for (dst = head; (probe_arc = dst->u.cycle.arc);
1785 dst = probe_arc->src)
1786 probe_arc->cs_count -= cycle_count;
1788 /* Unwind to the cyclic arc. */
1789 while (head != cycle_arc->src)
1791 arc = head->u.cycle.arc;
1792 head->u.cycle.arc = NULL;
1793 head = arc->src;
1795 /* Move on. */
1796 arc = arc->succ_next;
1797 continue;
1800 /* Add new block to chain. */
1801 dst->u.cycle.arc = arc;
1802 head = dst;
1803 goto next_vertex;
1805 /* We could not add another vertex to the path. Remove
1806 the last vertex from the list. */
1807 arc = head->u.cycle.arc;
1808 if (arc)
1810 /* It was not the first vertex. Move onto next arc. */
1811 head->u.cycle.arc = NULL;
1812 head = arc->src;
1813 arc = arc->succ_next;
1814 goto current_vertex;
1816 /* Mark this block as unusable. */
1817 block->u.cycle.ident = ~0U;
1820 line->count = count;
1823 if (line->exists)
1825 src->coverage.lines++;
1826 if (line->count)
1827 src->coverage.lines_executed++;
1832 /* Output information about ARC number IX. Returns nonzero if
1833 anything is output. */
1835 static int
1836 output_branch_count (FILE *gcov_file, int ix, const arc_t *arc)
1839 if (arc->is_call_non_return)
1841 if (arc->src->count)
1843 fnotice (gcov_file, "call %2d returned %s\n", ix,
1844 format_gcov (arc->src->count - arc->count,
1845 arc->src->count, -flag_counts));
1847 else
1848 fnotice (gcov_file, "call %2d never executed\n", ix);
1850 else if (!arc->is_unconditional)
1852 if (arc->src->count)
1853 fnotice (gcov_file, "branch %2d taken %s%s\n", ix,
1854 format_gcov (arc->count, arc->src->count, -flag_counts),
1855 arc->fall_through ? " (fallthrough)" : "");
1856 else
1857 fnotice (gcov_file, "branch %2d never executed\n", ix);
1859 else if (flag_unconditional && !arc->dst->is_call_return)
1861 if (arc->src->count)
1862 fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
1863 format_gcov (arc->count, arc->src->count, -flag_counts));
1864 else
1865 fnotice (gcov_file, "unconditional %2d never executed\n", ix);
1867 else
1868 return 0;
1869 return 1;
1873 /* Read in the source file one line at a time, and output that line to
1874 the gcov file preceded by its execution count and other
1875 information. */
1877 static void
1878 output_lines (FILE *gcov_file, const source_t *src)
1880 FILE *source_file;
1881 unsigned line_num; /* current line number. */
1882 const line_t *line; /* current line info ptr. */
1883 char string[STRING_SIZE]; /* line buffer. */
1884 char const *retval = ""; /* status of source file reading. */
1885 function_t *fn = NULL;
1887 fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->name);
1888 if (!multiple_files)
1890 fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
1891 fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0,
1892 no_data_file ? "-" : da_file_name);
1893 fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0,
1894 object_summary.ctrs[GCOV_COUNTER_ARCS].runs);
1896 fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
1898 source_file = fopen (src->name, "r");
1899 if (!source_file)
1901 fnotice (stderr, "%s:cannot open source file\n", src->name);
1902 retval = NULL;
1904 else if (src->file_time == 0)
1905 fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n", "-", 0);
1907 if (flag_branches)
1908 fn = src->functions;
1910 for (line_num = 1, line = &src->lines[line_num];
1911 line_num < src->num_lines; line_num++, line++)
1913 for (; fn && fn->line == line_num; fn = fn->line_next)
1915 arc_t *arc = fn->blocks[fn->num_blocks - 1].pred;
1916 gcov_type return_count = fn->blocks[fn->num_blocks - 1].count;
1918 for (; arc; arc = arc->pred_next)
1919 if (arc->fake)
1920 return_count -= arc->count;
1922 fprintf (gcov_file, "function %s", fn->name);
1923 fprintf (gcov_file, " called %s",
1924 format_gcov (fn->blocks[0].count, 0, -1));
1925 fprintf (gcov_file, " returned %s",
1926 format_gcov (return_count, fn->blocks[0].count, 0));
1927 fprintf (gcov_file, " blocks executed %s",
1928 format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0));
1929 fprintf (gcov_file, "\n");
1932 /* For lines which don't exist in the .bb file, print '-' before
1933 the source line. For lines which exist but were never
1934 executed, print '#####' before the source line. Otherwise,
1935 print the execution count before the source line. There are
1936 16 spaces of indentation added before the source line so that
1937 tabs won't be messed up. */
1938 fprintf (gcov_file, "%9s:%5u:",
1939 !line->exists ? "-" : !line->count ? "#####"
1940 : format_gcov (line->count, 0, -1), line_num);
1942 if (retval)
1944 /* Copy source line. */
1947 retval = fgets (string, STRING_SIZE, source_file);
1948 if (!retval)
1949 break;
1950 fputs (retval, gcov_file);
1952 while (!retval[0] || retval[strlen (retval) - 1] != '\n');
1954 if (!retval)
1955 fputs ("/*EOF*/\n", gcov_file);
1957 if (flag_all_blocks)
1959 block_t *block;
1960 arc_t *arc;
1961 int ix, jx;
1963 for (ix = jx = 0, block = line->u.blocks; block;
1964 block = block->chain)
1966 if (!block->is_call_return)
1967 fprintf (gcov_file, "%9s:%5u-block %2d\n",
1968 !line->exists ? "-" : !block->count ? "$$$$$"
1969 : format_gcov (block->count, 0, -1),
1970 line_num, ix++);
1971 if (flag_branches)
1972 for (arc = block->succ; arc; arc = arc->succ_next)
1973 jx += output_branch_count (gcov_file, jx, arc);
1976 else if (flag_branches)
1978 int ix;
1979 arc_t *arc;
1981 for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
1982 ix += output_branch_count (gcov_file, ix, arc);
1986 /* Handle all remaining source lines. There may be lines after the
1987 last line of code. */
1988 if (retval)
1990 for (; (retval = fgets (string, STRING_SIZE, source_file)); line_num++)
1992 fprintf (gcov_file, "%9s:%5u:%s", "-", line_num, retval);
1994 while (!retval[0] || retval[strlen (retval) - 1] != '\n')
1996 retval = fgets (string, STRING_SIZE, source_file);
1997 if (!retval)
1998 break;
1999 fputs (retval, gcov_file);
2004 if (source_file)
2005 fclose (source_file);