Merged revisions 143552,143554,143557,143560,143562,143564-143567,143570-143573,14357...
[official-gcc.git] / gcc / gcov.c
blob61ac7ed697482f3be48cefae2ea004c7fc9fcfb4
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
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 /* Handle response files. */
365 expandargv (&argc, &argv);
367 argno = process_args (argc, argv);
368 if (optind == argc)
369 print_usage (true);
371 if (argc - argno > 1)
372 multiple_files = 1;
374 for (; argno != argc; argno++)
375 process_file (argv[argno]);
377 generate_results (multiple_files ? NULL : argv[argc - 1]);
379 release_structures ();
381 return 0;
384 static void
385 fnotice (FILE *file, const char *cmsgid, ...)
387 va_list ap;
389 va_start (ap, cmsgid);
390 vfprintf (file, _(cmsgid), ap);
391 va_end (ap);
394 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
395 otherwise the output of --help. */
397 static void
398 print_usage (int error_p)
400 FILE *file = error_p ? stderr : stdout;
401 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
403 fnotice (file, "Usage: gcov [OPTION]... SOURCEFILE...\n\n");
404 fnotice (file, "Print code coverage information.\n\n");
405 fnotice (file, " -h, --help Print this help, then exit\n");
406 fnotice (file, " -v, --version Print version number, then exit\n");
407 fnotice (file, " -a, --all-blocks Show information for every basic block\n");
408 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
409 fnotice (file, " -c, --branch-counts Given counts of branches taken\n\
410 rather than percentages\n");
411 fnotice (file, " -n, --no-output Do not create an output file\n");
412 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
413 source files\n");
414 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
415 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
416 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
417 fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
418 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
419 bug_report_url);
420 exit (status);
423 /* Print version information and exit. */
425 static void
426 print_version (void)
428 fnotice (stdout, "gcov %s%s\n", pkgversion_string, version_string);
429 fprintf (stdout, "Copyright %s 2009 Free Software Foundation, Inc.\n",
430 _("(C)"));
431 fnotice (stdout,
432 _("This is free software; see the source for copying conditions.\n"
433 "There is NO warranty; not even for MERCHANTABILITY or \n"
434 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
435 exit (SUCCESS_EXIT_CODE);
438 static const struct option options[] =
440 { "help", no_argument, NULL, 'h' },
441 { "version", no_argument, NULL, 'v' },
442 { "all-blocks", no_argument, NULL, 'a' },
443 { "branch-probabilities", no_argument, NULL, 'b' },
444 { "branch-counts", no_argument, NULL, 'c' },
445 { "no-output", no_argument, NULL, 'n' },
446 { "long-file-names", no_argument, NULL, 'l' },
447 { "function-summaries", no_argument, NULL, 'f' },
448 { "preserve-paths", no_argument, NULL, 'p' },
449 { "object-directory", required_argument, NULL, 'o' },
450 { "object-file", required_argument, NULL, 'o' },
451 { "unconditional-branches", no_argument, NULL, 'u' },
452 { 0, 0, 0, 0 }
455 /* Process args, return index to first non-arg. */
457 static int
458 process_args (int argc, char **argv)
460 int opt;
462 while ((opt = getopt_long (argc, argv, "abcfhlno:puv", options, NULL)) != -1)
464 switch (opt)
466 case 'a':
467 flag_all_blocks = 1;
468 break;
469 case 'b':
470 flag_branches = 1;
471 break;
472 case 'c':
473 flag_counts = 1;
474 break;
475 case 'f':
476 flag_function_summary = 1;
477 break;
478 case 'h':
479 print_usage (false);
480 /* print_usage will exit. */
481 case 'l':
482 flag_long_names = 1;
483 break;
484 case 'n':
485 flag_gcov_file = 0;
486 break;
487 case 'o':
488 object_directory = optarg;
489 break;
490 case 'p':
491 flag_preserve_paths = 1;
492 break;
493 case 'u':
494 flag_unconditional = 1;
495 break;
496 case 'v':
497 print_version ();
498 /* print_version will exit. */
499 default:
500 print_usage (true);
501 /* print_usage will exit. */
505 return optind;
508 /* Process a single source file. */
510 static void
511 process_file (const char *file_name)
513 function_t *fn;
514 function_t *fn_p;
515 function_t *old_functions;
517 /* Save and clear the list of current functions. They will be appended
518 later. */
519 old_functions = functions;
520 functions = NULL;
522 create_file_names (file_name);
523 if (read_graph_file ())
524 return;
526 if (!functions)
528 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
529 return;
532 if (read_count_file ())
533 return;
535 for (fn_p = NULL, fn = functions; fn; fn_p = fn, fn = fn->next)
536 solve_flow_graph (fn);
538 if (fn_p)
539 fn_p->next = old_functions;
542 static void
543 generate_results (const char *file_name)
545 source_t *src;
546 function_t *fn;
548 for (src = sources; src; src = src->next)
549 src->lines = XCNEWVEC (line_t, src->num_lines);
550 for (fn = functions; fn; fn = fn->next)
552 coverage_t coverage;
554 memset (&coverage, 0, sizeof (coverage));
555 coverage.name = fn->name;
556 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
557 if (flag_function_summary)
559 function_summary (&coverage, "Function");
560 fnotice (stdout, "\n");
564 for (src = sources; src; src = src->next)
566 accumulate_line_counts (src);
567 function_summary (&src->coverage, "File");
568 if (flag_gcov_file)
570 char *gcov_file_name = make_gcov_file_name (file_name, src->name);
571 FILE *gcov_file = fopen (gcov_file_name, "w");
573 if (gcov_file)
575 fnotice (stdout, "%s:creating '%s'\n",
576 src->name, gcov_file_name);
577 output_lines (gcov_file, src);
578 if (ferror (gcov_file))
579 fnotice (stderr, "%s:error writing output file '%s'\n",
580 src->name, gcov_file_name);
581 fclose (gcov_file);
583 else
584 fnotice (stderr, "%s:could not open output file '%s'\n",
585 src->name, gcov_file_name);
586 free (gcov_file_name);
588 fnotice (stdout, "\n");
592 /* Release all memory used. */
594 static void
595 release_structures (void)
597 function_t *fn;
598 source_t *src;
600 while ((src = sources))
602 sources = src->next;
604 free (src->name);
605 free (src->lines);
608 while ((fn = functions))
610 unsigned ix;
611 block_t *block;
613 functions = fn->next;
614 for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
616 arc_t *arc, *arc_n;
618 for (arc = block->succ; arc; arc = arc_n)
620 arc_n = arc->succ_next;
621 free (arc);
624 free (fn->blocks);
625 free (fn->counts);
629 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
630 is not specified, these are looked for in the current directory,
631 and named from the basename of the FILE_NAME sans extension. If
632 OBJECT_DIRECTORY is specified and is a directory, the files are in
633 that directory, but named from the basename of the FILE_NAME, sans
634 extension. Otherwise OBJECT_DIRECTORY is taken to be the name of
635 the object *file*, and the data files are named from that. */
637 static void
638 create_file_names (const char *file_name)
640 char *cptr;
641 char *name;
642 int length = strlen (file_name);
643 int base;
645 /* Free previous file names. */
646 if (bbg_file_name)
647 free (bbg_file_name);
648 if (da_file_name)
649 free (da_file_name);
650 da_file_name = bbg_file_name = NULL;
651 bbg_file_time = 0;
652 bbg_stamp = 0;
654 if (object_directory && object_directory[0])
656 struct stat status;
658 length += strlen (object_directory) + 2;
659 name = XNEWVEC (char, length);
660 name[0] = 0;
662 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
663 strcat (name, object_directory);
664 if (base && (! IS_DIR_SEPARATOR (name[strlen (name) - 1])))
665 strcat (name, "/");
667 else
669 name = XNEWVEC (char, length + 1);
670 name[0] = 0;
671 base = 1;
674 if (base)
676 /* Append source file name. */
677 const char *cptr = lbasename (file_name);
678 strcat (name, cptr ? cptr : file_name);
681 /* Remove the extension. */
682 cptr = strrchr (name, '.');
683 if (cptr)
684 *cptr = 0;
686 length = strlen (name);
688 bbg_file_name = XNEWVEC (char, length + strlen (GCOV_NOTE_SUFFIX) + 1);
689 strcpy (bbg_file_name, name);
690 strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
692 da_file_name = XNEWVEC (char, length + strlen (GCOV_DATA_SUFFIX) + 1);
693 strcpy (da_file_name, name);
694 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
696 free (name);
697 return;
700 /* Find or create a source file structure for FILE_NAME. Copies
701 FILE_NAME on creation */
703 static source_t *
704 find_source (const char *file_name)
706 source_t *src;
707 struct stat status;
709 if (!file_name)
710 file_name = "<unknown>";
712 for (src = sources; src; src = src->next)
713 if (!strcmp (file_name, src->name))
714 break;
716 if (!src)
718 src = XCNEW (source_t);
719 src->name = xstrdup (file_name);
720 src->coverage.name = src->name;
721 src->index = source_index++;
722 src->next = sources;
723 sources = src;
725 if (!stat (file_name, &status))
726 src->file_time = status.st_mtime;
729 if (src->file_time > bbg_file_time)
731 static int info_emitted;
733 fnotice (stderr, "%s:source file is newer than graph file '%s'\n",
734 src->name, bbg_file_name);
735 if (!info_emitted)
737 fnotice (stderr,
738 "(the message is only displayed one per source file)\n");
739 info_emitted = 1;
741 src->file_time = 0;
744 return src;
747 /* Read the graph file. Return nonzero on fatal error. */
749 static int
750 read_graph_file (void)
752 unsigned version;
753 unsigned current_tag = 0;
754 struct function_info *fn = NULL;
755 function_t *old_functions_head = functions;
756 source_t *src = NULL;
757 unsigned ix;
758 unsigned tag;
760 if (!gcov_open (bbg_file_name, 1))
762 fnotice (stderr, "%s:cannot open graph file\n", bbg_file_name);
763 return 1;
765 bbg_file_time = gcov_time ();
766 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
768 fnotice (stderr, "%s:not a gcov graph file\n", bbg_file_name);
769 gcov_close ();
770 return 1;
773 version = gcov_read_unsigned ();
774 if (version != GCOV_VERSION)
776 char v[4], e[4];
778 GCOV_UNSIGNED2STRING (v, version);
779 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
781 fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n",
782 bbg_file_name, v, e);
784 bbg_stamp = gcov_read_unsigned ();
786 while ((tag = gcov_read_unsigned ()))
788 unsigned length = gcov_read_unsigned ();
789 gcov_position_t base = gcov_position ();
791 if (tag == GCOV_TAG_FUNCTION)
793 char *function_name;
794 unsigned ident, checksum, lineno;
795 source_t *src;
796 function_t *probe, *prev;
798 ident = gcov_read_unsigned ();
799 checksum = gcov_read_unsigned ();
800 function_name = xstrdup (gcov_read_string ());
801 src = find_source (gcov_read_string ());
802 lineno = gcov_read_unsigned ();
804 fn = XCNEW (function_t);
805 fn->name = function_name;
806 fn->ident = ident;
807 fn->checksum = checksum;
808 fn->src = src;
809 fn->line = lineno;
811 fn->next = functions;
812 functions = fn;
813 current_tag = tag;
815 if (lineno >= src->num_lines)
816 src->num_lines = lineno + 1;
817 /* Now insert it into the source file's list of
818 functions. Normally functions will be encountered in
819 ascending order, so a simple scan is quick. */
820 for (probe = src->functions, prev = NULL;
821 probe && probe->line > lineno;
822 prev = probe, probe = probe->line_next)
823 continue;
824 fn->line_next = probe;
825 if (prev)
826 prev->line_next = fn;
827 else
828 src->functions = fn;
830 else if (fn && tag == GCOV_TAG_BLOCKS)
832 if (fn->blocks)
833 fnotice (stderr, "%s:already seen blocks for '%s'\n",
834 bbg_file_name, fn->name);
835 else
837 unsigned ix, num_blocks = GCOV_TAG_BLOCKS_NUM (length);
838 fn->num_blocks = num_blocks;
840 fn->blocks = XCNEWVEC (block_t, fn->num_blocks);
841 for (ix = 0; ix != num_blocks; ix++)
842 fn->blocks[ix].flags = gcov_read_unsigned ();
845 else if (fn && tag == GCOV_TAG_ARCS)
847 unsigned src = gcov_read_unsigned ();
848 unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
850 if (src >= fn->num_blocks || fn->blocks[src].succ)
851 goto corrupt;
853 while (num_dests--)
855 struct arc_info *arc;
856 unsigned dest = gcov_read_unsigned ();
857 unsigned flags = gcov_read_unsigned ();
859 if (dest >= fn->num_blocks)
860 goto corrupt;
861 arc = XCNEW (arc_t);
863 arc->dst = &fn->blocks[dest];
864 arc->src = &fn->blocks[src];
866 arc->count = 0;
867 arc->count_valid = 0;
868 arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
869 arc->fake = !!(flags & GCOV_ARC_FAKE);
870 arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
872 arc->succ_next = fn->blocks[src].succ;
873 fn->blocks[src].succ = arc;
874 fn->blocks[src].num_succ++;
876 arc->pred_next = fn->blocks[dest].pred;
877 fn->blocks[dest].pred = arc;
878 fn->blocks[dest].num_pred++;
880 if (arc->fake)
882 if (src)
884 /* Exceptional exit from this function, the
885 source block must be a call. */
886 fn->blocks[src].is_call_site = 1;
887 arc->is_call_non_return = 1;
889 else
891 /* Non-local return from a callee of this
892 function. The destination block is a catch or
893 setjmp. */
894 arc->is_nonlocal_return = 1;
895 fn->blocks[dest].is_nonlocal_return = 1;
899 if (!arc->on_tree)
900 fn->num_counts++;
903 else if (fn && tag == GCOV_TAG_LINES)
905 unsigned blockno = gcov_read_unsigned ();
906 unsigned *line_nos = XCNEWVEC (unsigned, length - 1);
908 if (blockno >= fn->num_blocks || fn->blocks[blockno].u.line.encoding)
909 goto corrupt;
911 for (ix = 0; ; )
913 unsigned lineno = gcov_read_unsigned ();
915 if (lineno)
917 if (!ix)
919 line_nos[ix++] = 0;
920 line_nos[ix++] = src->index;
922 line_nos[ix++] = lineno;
923 if (lineno >= src->num_lines)
924 src->num_lines = lineno + 1;
926 else
928 const char *file_name = gcov_read_string ();
930 if (!file_name)
931 break;
932 src = find_source (file_name);
934 line_nos[ix++] = 0;
935 line_nos[ix++] = src->index;
939 fn->blocks[blockno].u.line.encoding = line_nos;
940 fn->blocks[blockno].u.line.num = ix;
942 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
944 fn = NULL;
945 current_tag = 0;
947 gcov_sync (base, length);
948 if (gcov_is_error ())
950 corrupt:;
951 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
952 gcov_close ();
953 return 1;
956 gcov_close ();
958 /* We built everything backwards, so nreverse them all. */
960 /* Reverse sources. Not strictly necessary, but we'll then process
961 them in the 'expected' order. */
963 source_t *src, *src_p, *src_n;
965 for (src_p = NULL, src = sources; src; src_p = src, src = src_n)
967 src_n = src->next;
968 src->next = src_p;
970 sources = src_p;
973 /* Reverse functions. */
975 function_t *fn, *fn_p, *fn_n;
977 for (fn_p = old_functions_head, fn = functions;
978 fn != old_functions_head;
979 fn_p = fn, fn = fn_n)
981 unsigned ix;
983 fn_n = fn->next;
984 fn->next = fn_p;
986 /* Reverse the arcs. */
987 for (ix = fn->num_blocks; ix--;)
989 arc_t *arc, *arc_p, *arc_n;
991 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
992 arc_p = arc, arc = arc_n)
994 arc_n = arc->succ_next;
995 arc->succ_next = arc_p;
997 fn->blocks[ix].succ = arc_p;
999 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
1000 arc_p = arc, arc = arc_n)
1002 arc_n = arc->pred_next;
1003 arc->pred_next = arc_p;
1005 fn->blocks[ix].pred = arc_p;
1008 functions = fn_p;
1010 return 0;
1013 /* Reads profiles from the count file and attach to each
1014 function. Return nonzero if fatal error. */
1016 static int
1017 read_count_file (void)
1019 unsigned ix;
1020 unsigned version;
1021 unsigned tag;
1022 function_t *fn = NULL;
1023 int error = 0;
1025 if (!gcov_open (da_file_name, 1))
1027 fnotice (stderr, "%s:cannot open data file, assuming not executed\n",
1028 da_file_name);
1029 no_data_file = 1;
1030 return 0;
1032 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
1034 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
1035 cleanup:;
1036 gcov_close ();
1037 return 1;
1039 version = gcov_read_unsigned ();
1040 if (version != GCOV_VERSION)
1042 char v[4], e[4];
1044 GCOV_UNSIGNED2STRING (v, version);
1045 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1047 fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
1048 da_file_name, v, e);
1050 tag = gcov_read_unsigned ();
1051 if (tag != bbg_stamp)
1053 fnotice (stderr, "%s:stamp mismatch with graph file\n", da_file_name);
1054 goto cleanup;
1057 while ((tag = gcov_read_unsigned ()))
1059 unsigned length = gcov_read_unsigned ();
1060 unsigned long base = gcov_position ();
1062 if (tag == GCOV_TAG_OBJECT_SUMMARY)
1063 gcov_read_summary (&object_summary);
1064 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
1065 program_count++;
1066 else if (tag == GCOV_TAG_FUNCTION)
1068 unsigned ident = gcov_read_unsigned ();
1069 struct function_info *fn_n = functions;
1071 /* Try to find the function in the list.
1072 To speed up the search, first start from the last function
1073 found. */
1074 for (fn = fn ? fn->next : NULL; ; fn = fn->next)
1076 if (fn)
1078 else if ((fn = fn_n))
1079 fn_n = NULL;
1080 else
1082 fnotice (stderr, "%s:unknown function '%u'\n",
1083 da_file_name, ident);
1084 break;
1086 if (fn->ident == ident)
1087 break;
1090 if (!fn)
1092 else if (gcov_read_unsigned () != fn->checksum)
1094 mismatch:;
1095 fnotice (stderr, "%s:profile mismatch for '%s'\n",
1096 da_file_name, fn->name);
1097 goto cleanup;
1100 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
1102 if (length != GCOV_TAG_COUNTER_LENGTH (fn->num_counts))
1103 goto mismatch;
1105 if (!fn->counts)
1106 fn->counts = XCNEWVEC (gcov_type, fn->num_counts);
1108 for (ix = 0; ix != fn->num_counts; ix++)
1109 fn->counts[ix] += gcov_read_counter ();
1111 gcov_sync (base, length);
1112 if ((error = gcov_is_error ()))
1114 fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1115 da_file_name);
1116 goto cleanup;
1120 gcov_close ();
1121 return 0;
1124 /* Solve the flow graph. Propagate counts from the instrumented arcs
1125 to the blocks and the uninstrumented arcs. */
1127 static void
1128 solve_flow_graph (function_t *fn)
1130 unsigned ix;
1131 arc_t *arc;
1132 gcov_type *count_ptr = fn->counts;
1133 block_t *blk;
1134 block_t *valid_blocks = NULL; /* valid, but unpropagated blocks. */
1135 block_t *invalid_blocks = NULL; /* invalid, but inferable blocks. */
1137 if (fn->num_blocks < 2)
1138 fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n",
1139 bbg_file_name, fn->name);
1140 else
1142 if (fn->blocks[0].num_pred)
1143 fnotice (stderr, "%s:'%s' has arcs to entry block\n",
1144 bbg_file_name, fn->name);
1145 else
1146 /* We can't deduce the entry block counts from the lack of
1147 predecessors. */
1148 fn->blocks[0].num_pred = ~(unsigned)0;
1150 if (fn->blocks[fn->num_blocks - 1].num_succ)
1151 fnotice (stderr, "%s:'%s' has arcs from exit block\n",
1152 bbg_file_name, fn->name);
1153 else
1154 /* Likewise, we can't deduce exit block counts from the lack
1155 of its successors. */
1156 fn->blocks[fn->num_blocks - 1].num_succ = ~(unsigned)0;
1159 /* Propagate the measured counts, this must be done in the same
1160 order as the code in profile.c */
1161 for (ix = 0, blk = fn->blocks; ix != fn->num_blocks; ix++, blk++)
1163 block_t const *prev_dst = NULL;
1164 int out_of_order = 0;
1165 int non_fake_succ = 0;
1167 for (arc = blk->succ; arc; arc = arc->succ_next)
1169 if (!arc->fake)
1170 non_fake_succ++;
1172 if (!arc->on_tree)
1174 if (count_ptr)
1175 arc->count = *count_ptr++;
1176 arc->count_valid = 1;
1177 blk->num_succ--;
1178 arc->dst->num_pred--;
1180 if (prev_dst && prev_dst > arc->dst)
1181 out_of_order = 1;
1182 prev_dst = arc->dst;
1184 if (non_fake_succ == 1)
1186 /* If there is only one non-fake exit, it is an
1187 unconditional branch. */
1188 for (arc = blk->succ; arc; arc = arc->succ_next)
1189 if (!arc->fake)
1191 arc->is_unconditional = 1;
1192 /* If this block is instrumenting a call, it might be
1193 an artificial block. It is not artificial if it has
1194 a non-fallthrough exit, or the destination of this
1195 arc has more than one entry. Mark the destination
1196 block as a return site, if none of those conditions
1197 hold. */
1198 if (blk->is_call_site && arc->fall_through
1199 && arc->dst->pred == arc && !arc->pred_next)
1200 arc->dst->is_call_return = 1;
1204 /* Sort the successor arcs into ascending dst order. profile.c
1205 normally produces arcs in the right order, but sometimes with
1206 one or two out of order. We're not using a particularly
1207 smart sort. */
1208 if (out_of_order)
1210 arc_t *start = blk->succ;
1211 unsigned changes = 1;
1213 while (changes)
1215 arc_t *arc, *arc_p, *arc_n;
1217 changes = 0;
1218 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1220 if (arc->dst > arc_n->dst)
1222 changes = 1;
1223 if (arc_p)
1224 arc_p->succ_next = arc_n;
1225 else
1226 start = arc_n;
1227 arc->succ_next = arc_n->succ_next;
1228 arc_n->succ_next = arc;
1229 arc_p = arc_n;
1231 else
1233 arc_p = arc;
1234 arc = arc_n;
1238 blk->succ = start;
1241 /* Place it on the invalid chain, it will be ignored if that's
1242 wrong. */
1243 blk->invalid_chain = 1;
1244 blk->chain = invalid_blocks;
1245 invalid_blocks = blk;
1248 while (invalid_blocks || valid_blocks)
1250 while ((blk = invalid_blocks))
1252 gcov_type total = 0;
1253 const arc_t *arc;
1255 invalid_blocks = blk->chain;
1256 blk->invalid_chain = 0;
1257 if (!blk->num_succ)
1258 for (arc = blk->succ; arc; arc = arc->succ_next)
1259 total += arc->count;
1260 else if (!blk->num_pred)
1261 for (arc = blk->pred; arc; arc = arc->pred_next)
1262 total += arc->count;
1263 else
1264 continue;
1266 blk->count = total;
1267 blk->count_valid = 1;
1268 blk->chain = valid_blocks;
1269 blk->valid_chain = 1;
1270 valid_blocks = blk;
1272 while ((blk = valid_blocks))
1274 gcov_type total;
1275 arc_t *arc, *inv_arc;
1277 valid_blocks = blk->chain;
1278 blk->valid_chain = 0;
1279 if (blk->num_succ == 1)
1281 block_t *dst;
1283 total = blk->count;
1284 inv_arc = NULL;
1285 for (arc = blk->succ; arc; arc = arc->succ_next)
1287 total -= arc->count;
1288 if (!arc->count_valid)
1289 inv_arc = arc;
1291 dst = inv_arc->dst;
1292 inv_arc->count_valid = 1;
1293 inv_arc->count = total;
1294 blk->num_succ--;
1295 dst->num_pred--;
1296 if (dst->count_valid)
1298 if (dst->num_pred == 1 && !dst->valid_chain)
1300 dst->chain = valid_blocks;
1301 dst->valid_chain = 1;
1302 valid_blocks = dst;
1305 else
1307 if (!dst->num_pred && !dst->invalid_chain)
1309 dst->chain = invalid_blocks;
1310 dst->invalid_chain = 1;
1311 invalid_blocks = dst;
1315 if (blk->num_pred == 1)
1317 block_t *src;
1319 total = blk->count;
1320 inv_arc = NULL;
1321 for (arc = blk->pred; arc; arc = arc->pred_next)
1323 total -= arc->count;
1324 if (!arc->count_valid)
1325 inv_arc = arc;
1327 src = inv_arc->src;
1328 inv_arc->count_valid = 1;
1329 inv_arc->count = total;
1330 blk->num_pred--;
1331 src->num_succ--;
1332 if (src->count_valid)
1334 if (src->num_succ == 1 && !src->valid_chain)
1336 src->chain = valid_blocks;
1337 src->valid_chain = 1;
1338 valid_blocks = src;
1341 else
1343 if (!src->num_succ && !src->invalid_chain)
1345 src->chain = invalid_blocks;
1346 src->invalid_chain = 1;
1347 invalid_blocks = src;
1354 /* If the graph has been correctly solved, every block will have a
1355 valid count. */
1356 for (ix = 0; ix < fn->num_blocks; ix++)
1357 if (!fn->blocks[ix].count_valid)
1359 fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
1360 bbg_file_name, fn->name);
1361 break;
1367 /* Increment totals in COVERAGE according to arc ARC. */
1369 static void
1370 add_branch_counts (coverage_t *coverage, const arc_t *arc)
1372 if (arc->is_call_non_return)
1374 coverage->calls++;
1375 if (arc->src->count)
1376 coverage->calls_executed++;
1378 else if (!arc->is_unconditional)
1380 coverage->branches++;
1381 if (arc->src->count)
1382 coverage->branches_executed++;
1383 if (arc->count)
1384 coverage->branches_taken++;
1388 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1389 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1390 If DP is zero, no decimal point is printed. Only print 100% when
1391 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1392 format TOP. Return pointer to a static string. */
1394 static char const *
1395 format_gcov (gcov_type top, gcov_type bottom, int dp)
1397 static char buffer[20];
1399 if (dp >= 0)
1401 float ratio = bottom ? (float)top / bottom : 0;
1402 int ix;
1403 unsigned limit = 100;
1404 unsigned percent;
1406 for (ix = dp; ix--; )
1407 limit *= 10;
1409 percent = (unsigned) (ratio * limit + (float)0.5);
1410 if (percent <= 0 && top)
1411 percent = 1;
1412 else if (percent >= limit && top != bottom)
1413 percent = limit - 1;
1414 ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1415 if (dp)
1417 dp++;
1420 buffer[ix+1] = buffer[ix];
1421 ix--;
1423 while (dp--);
1424 buffer[ix + 1] = '.';
1427 else
1428 sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)top);
1430 return buffer;
1434 /* Output summary info for a function. */
1436 static void
1437 function_summary (const coverage_t *coverage, const char *title)
1439 fnotice (stdout, "%s '%s'\n", title, coverage->name);
1441 if (coverage->lines)
1442 fnotice (stdout, "Lines executed:%s of %d\n",
1443 format_gcov (coverage->lines_executed, coverage->lines, 2),
1444 coverage->lines);
1445 else
1446 fnotice (stdout, "No executable lines\n");
1448 if (flag_branches)
1450 if (coverage->branches)
1452 fnotice (stdout, "Branches executed:%s of %d\n",
1453 format_gcov (coverage->branches_executed,
1454 coverage->branches, 2),
1455 coverage->branches);
1456 fnotice (stdout, "Taken at least once:%s of %d\n",
1457 format_gcov (coverage->branches_taken,
1458 coverage->branches, 2),
1459 coverage->branches);
1461 else
1462 fnotice (stdout, "No branches\n");
1463 if (coverage->calls)
1464 fnotice (stdout, "Calls executed:%s of %d\n",
1465 format_gcov (coverage->calls_executed, coverage->calls, 2),
1466 coverage->calls);
1467 else
1468 fnotice (stdout, "No calls\n");
1472 /* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
1473 affect name generation. With preserve_paths we create a filename
1474 from all path components of the source file, replacing '/' with
1475 '#', without it we simply take the basename component. With
1476 long_output_names we prepend the processed name of the input file
1477 to each output name (except when the current source file is the
1478 input file, so you don't get a double concatenation). The two
1479 components are separated by '##'. Also '.' filename components are
1480 removed and '..' components are renamed to '^'. */
1482 static char *
1483 make_gcov_file_name (const char *input_name, const char *src_name)
1485 const char *cptr;
1486 char *name;
1488 if (flag_long_names && input_name && strcmp (src_name, input_name))
1490 name = XNEWVEC (char, strlen (src_name) + strlen (input_name) + 10);
1491 name[0] = 0;
1492 /* Generate the input filename part. */
1493 cptr = flag_preserve_paths ? NULL : lbasename (input_name);
1494 strcat (name, cptr ? cptr : input_name);
1495 strcat (name, "##");
1497 else
1499 name = XNEWVEC (char, strlen (src_name) + 10);
1500 name[0] = 0;
1503 /* Generate the source filename part. */
1505 cptr = flag_preserve_paths ? NULL : lbasename (src_name);
1506 strcat (name, cptr ? cptr : src_name);
1508 if (flag_preserve_paths)
1510 /* Convert '/' and '\' to '#', remove '/./', convert '/../' to '/^/',
1511 convert ':' to '~' on DOS based file system. */
1512 char *pnew = name, *pold = name;
1514 /* First check for leading drive separator. */
1516 while (*pold != '\0')
1518 if (*pold == '/' || *pold == '\\')
1520 *pnew++ = '#';
1521 pold++;
1523 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
1524 else if (*pold == ':')
1526 *pnew++ = '~';
1527 pold++;
1529 #endif
1530 else if ((*pold == '/' && strstr (pold, "/./") == pold)
1531 || (*pold == '\\' && strstr (pold, "\\.\\") == pold))
1532 pold += 3;
1533 else if (*pold == '/' && strstr (pold, "/../") == pold)
1535 strcpy (pnew, "/^/");
1536 pnew += 3;
1537 pold += 4;
1539 else if (*pold == '\\' && strstr (pold, "\\..\\") == pold)
1541 strcpy (pnew, "\\^\\");
1542 pnew += 3;
1543 pold += 4;
1545 else
1546 *pnew++ = *pold++;
1549 *pnew = '\0';
1552 strcat (name, ".gcov");
1553 return name;
1556 /* Scan through the bb_data for each line in the block, increment
1557 the line number execution count indicated by the execution count of
1558 the appropriate basic block. */
1560 static void
1561 add_line_counts (coverage_t *coverage, function_t *fn)
1563 unsigned ix;
1564 line_t *line = NULL; /* This is propagated from one iteration to the
1565 next. */
1567 /* Scan each basic block. */
1568 for (ix = 0; ix != fn->num_blocks; ix++)
1570 block_t *block = &fn->blocks[ix];
1571 unsigned *encoding;
1572 const source_t *src = NULL;
1573 unsigned jx;
1575 if (block->count && ix && ix + 1 != fn->num_blocks)
1576 fn->blocks_executed++;
1577 for (jx = 0, encoding = block->u.line.encoding;
1578 jx != block->u.line.num; jx++, encoding++)
1579 if (!*encoding)
1581 unsigned src_n = *++encoding;
1583 for (src = sources; src->index != src_n; src = src->next)
1584 continue;
1585 jx++;
1587 else
1589 line = &src->lines[*encoding];
1591 if (coverage)
1593 if (!line->exists)
1594 coverage->lines++;
1595 if (!line->count && block->count)
1596 coverage->lines_executed++;
1598 line->exists = 1;
1599 line->count += block->count;
1601 free (block->u.line.encoding);
1602 block->u.cycle.arc = NULL;
1603 block->u.cycle.ident = ~0U;
1605 if (!ix || ix + 1 == fn->num_blocks)
1606 /* Entry or exit block */;
1607 else if (flag_all_blocks)
1609 line_t *block_line = line ? line : &fn->src->lines[fn->line];
1611 block->chain = block_line->u.blocks;
1612 block_line->u.blocks = block;
1614 else if (flag_branches)
1616 arc_t *arc;
1618 for (arc = block->succ; arc; arc = arc->succ_next)
1620 arc->line_next = line->u.branches;
1621 line->u.branches = arc;
1622 if (coverage && !arc->is_unconditional)
1623 add_branch_counts (coverage, arc);
1627 if (!line)
1628 fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, fn->name);
1631 /* Accumulate the line counts of a file. */
1633 static void
1634 accumulate_line_counts (source_t *src)
1636 line_t *line;
1637 function_t *fn, *fn_p, *fn_n;
1638 unsigned ix;
1640 /* Reverse the function order. */
1641 for (fn = src->functions, fn_p = NULL; fn;
1642 fn_p = fn, fn = fn_n)
1644 fn_n = fn->line_next;
1645 fn->line_next = fn_p;
1647 src->functions = fn_p;
1649 for (ix = src->num_lines, line = src->lines; ix--; line++)
1651 if (!flag_all_blocks)
1653 arc_t *arc, *arc_p, *arc_n;
1655 /* Total and reverse the branch information. */
1656 for (arc = line->u.branches, arc_p = NULL; arc;
1657 arc_p = arc, arc = arc_n)
1659 arc_n = arc->line_next;
1660 arc->line_next = arc_p;
1662 add_branch_counts (&src->coverage, arc);
1664 line->u.branches = arc_p;
1666 else if (line->u.blocks)
1668 /* The user expects the line count to be the number of times
1669 a line has been executed. Simply summing the block count
1670 will give an artificially high number. The Right Thing
1671 is to sum the entry counts to the graph of blocks on this
1672 line, then find the elementary cycles of the local graph
1673 and add the transition counts of those cycles. */
1674 block_t *block, *block_p, *block_n;
1675 gcov_type count = 0;
1677 /* Reverse the block information. */
1678 for (block = line->u.blocks, block_p = NULL; block;
1679 block_p = block, block = block_n)
1681 block_n = block->chain;
1682 block->chain = block_p;
1683 block->u.cycle.ident = ix;
1685 line->u.blocks = block_p;
1687 /* Sum the entry arcs. */
1688 for (block = line->u.blocks; block; block = block->chain)
1690 arc_t *arc;
1692 for (arc = block->pred; arc; arc = arc->pred_next)
1694 if (arc->src->u.cycle.ident != ix)
1695 count += arc->count;
1696 if (flag_branches)
1697 add_branch_counts (&src->coverage, arc);
1700 /* Initialize the cs_count. */
1701 for (arc = block->succ; arc; arc = arc->succ_next)
1702 arc->cs_count = arc->count;
1705 /* Find the loops. This uses the algorithm described in
1706 Tiernan 'An Efficient Search Algorithm to Find the
1707 Elementary Circuits of a Graph', CACM Dec 1970. We hold
1708 the P array by having each block point to the arc that
1709 connects to the previous block. The H array is implicitly
1710 held because of the arc ordering, and the block's
1711 previous arc pointer.
1713 Although the algorithm is O(N^3) for highly connected
1714 graphs, at worst we'll have O(N^2), as most blocks have
1715 only one or two exits. Most graphs will be small.
1717 For each loop we find, locate the arc with the smallest
1718 transition count, and add that to the cumulative
1719 count. Decrease flow over the cycle and remove the arc
1720 from consideration. */
1721 for (block = line->u.blocks; block; block = block->chain)
1723 block_t *head = block;
1724 arc_t *arc;
1726 next_vertex:;
1727 arc = head->succ;
1728 current_vertex:;
1729 while (arc)
1731 block_t *dst = arc->dst;
1732 if (/* Already used that arc. */
1733 arc->cycle
1734 /* Not to same graph, or before first vertex. */
1735 || dst->u.cycle.ident != ix
1736 /* Already in path. */
1737 || dst->u.cycle.arc)
1739 arc = arc->succ_next;
1740 continue;
1743 if (dst == block)
1745 /* Found a closing arc. */
1746 gcov_type cycle_count = arc->cs_count;
1747 arc_t *cycle_arc = arc;
1748 arc_t *probe_arc;
1750 /* Locate the smallest arc count of the loop. */
1751 for (dst = head; (probe_arc = dst->u.cycle.arc);
1752 dst = probe_arc->src)
1753 if (cycle_count > probe_arc->cs_count)
1755 cycle_count = probe_arc->cs_count;
1756 cycle_arc = probe_arc;
1759 count += cycle_count;
1760 cycle_arc->cycle = 1;
1762 /* Remove the flow from the cycle. */
1763 arc->cs_count -= cycle_count;
1764 for (dst = head; (probe_arc = dst->u.cycle.arc);
1765 dst = probe_arc->src)
1766 probe_arc->cs_count -= cycle_count;
1768 /* Unwind to the cyclic arc. */
1769 while (head != cycle_arc->src)
1771 arc = head->u.cycle.arc;
1772 head->u.cycle.arc = NULL;
1773 head = arc->src;
1775 /* Move on. */
1776 arc = arc->succ_next;
1777 continue;
1780 /* Add new block to chain. */
1781 dst->u.cycle.arc = arc;
1782 head = dst;
1783 goto next_vertex;
1785 /* We could not add another vertex to the path. Remove
1786 the last vertex from the list. */
1787 arc = head->u.cycle.arc;
1788 if (arc)
1790 /* It was not the first vertex. Move onto next arc. */
1791 head->u.cycle.arc = NULL;
1792 head = arc->src;
1793 arc = arc->succ_next;
1794 goto current_vertex;
1796 /* Mark this block as unusable. */
1797 block->u.cycle.ident = ~0U;
1800 line->count = count;
1803 if (line->exists)
1805 src->coverage.lines++;
1806 if (line->count)
1807 src->coverage.lines_executed++;
1812 /* Output information about ARC number IX. Returns nonzero if
1813 anything is output. */
1815 static int
1816 output_branch_count (FILE *gcov_file, int ix, const arc_t *arc)
1819 if (arc->is_call_non_return)
1821 if (arc->src->count)
1823 fnotice (gcov_file, "call %2d returned %s\n", ix,
1824 format_gcov (arc->src->count - arc->count,
1825 arc->src->count, -flag_counts));
1827 else
1828 fnotice (gcov_file, "call %2d never executed\n", ix);
1830 else if (!arc->is_unconditional)
1832 if (arc->src->count)
1833 fnotice (gcov_file, "branch %2d taken %s%s\n", ix,
1834 format_gcov (arc->count, arc->src->count, -flag_counts),
1835 arc->fall_through ? " (fallthrough)" : "");
1836 else
1837 fnotice (gcov_file, "branch %2d never executed\n", ix);
1839 else if (flag_unconditional && !arc->dst->is_call_return)
1841 if (arc->src->count)
1842 fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
1843 format_gcov (arc->count, arc->src->count, -flag_counts));
1844 else
1845 fnotice (gcov_file, "unconditional %2d never executed\n", ix);
1847 else
1848 return 0;
1849 return 1;
1853 /* Read in the source file one line at a time, and output that line to
1854 the gcov file preceded by its execution count and other
1855 information. */
1857 static void
1858 output_lines (FILE *gcov_file, const source_t *src)
1860 FILE *source_file;
1861 unsigned line_num; /* current line number. */
1862 const line_t *line; /* current line info ptr. */
1863 char string[STRING_SIZE]; /* line buffer. */
1864 char const *retval = ""; /* status of source file reading. */
1865 function_t *fn = NULL;
1867 fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->name);
1868 if (!multiple_files)
1870 fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
1871 fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0,
1872 no_data_file ? "-" : da_file_name);
1873 fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0,
1874 object_summary.ctrs[GCOV_COUNTER_ARCS].runs);
1876 fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
1878 source_file = fopen (src->name, "r");
1879 if (!source_file)
1881 fnotice (stderr, "%s:cannot open source file\n", src->name);
1882 retval = NULL;
1884 else if (src->file_time == 0)
1885 fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n", "-", 0);
1887 if (flag_branches)
1888 fn = src->functions;
1890 for (line_num = 1, line = &src->lines[line_num];
1891 line_num < src->num_lines; line_num++, line++)
1893 for (; fn && fn->line == line_num; fn = fn->line_next)
1895 arc_t *arc = fn->blocks[fn->num_blocks - 1].pred;
1896 gcov_type return_count = fn->blocks[fn->num_blocks - 1].count;
1898 for (; arc; arc = arc->pred_next)
1899 if (arc->fake)
1900 return_count -= arc->count;
1902 fprintf (gcov_file, "function %s", fn->name);
1903 fprintf (gcov_file, " called %s",
1904 format_gcov (fn->blocks[0].count, 0, -1));
1905 fprintf (gcov_file, " returned %s",
1906 format_gcov (return_count, fn->blocks[0].count, 0));
1907 fprintf (gcov_file, " blocks executed %s",
1908 format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0));
1909 fprintf (gcov_file, "\n");
1912 /* For lines which don't exist in the .bb file, print '-' before
1913 the source line. For lines which exist but were never
1914 executed, print '#####' before the source line. Otherwise,
1915 print the execution count before the source line. There are
1916 16 spaces of indentation added before the source line so that
1917 tabs won't be messed up. */
1918 fprintf (gcov_file, "%9s:%5u:",
1919 !line->exists ? "-" : !line->count ? "#####"
1920 : format_gcov (line->count, 0, -1), line_num);
1922 if (retval)
1924 /* Copy source line. */
1927 retval = fgets (string, STRING_SIZE, source_file);
1928 if (!retval)
1929 break;
1930 fputs (retval, gcov_file);
1932 while (!retval[0] || retval[strlen (retval) - 1] != '\n');
1934 if (!retval)
1935 fputs ("/*EOF*/\n", gcov_file);
1937 if (flag_all_blocks)
1939 block_t *block;
1940 arc_t *arc;
1941 int ix, jx;
1943 for (ix = jx = 0, block = line->u.blocks; block;
1944 block = block->chain)
1946 if (!block->is_call_return)
1947 fprintf (gcov_file, "%9s:%5u-block %2d\n",
1948 !line->exists ? "-" : !block->count ? "$$$$$"
1949 : format_gcov (block->count, 0, -1),
1950 line_num, ix++);
1951 if (flag_branches)
1952 for (arc = block->succ; arc; arc = arc->succ_next)
1953 jx += output_branch_count (gcov_file, jx, arc);
1956 else if (flag_branches)
1958 int ix;
1959 arc_t *arc;
1961 for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
1962 ix += output_branch_count (gcov_file, ix, arc);
1966 /* Handle all remaining source lines. There may be lines after the
1967 last line of code. */
1968 if (retval)
1970 for (; (retval = fgets (string, STRING_SIZE, source_file)); line_num++)
1972 fprintf (gcov_file, "%9s:%5u:%s", "-", line_num, retval);
1974 while (!retval[0] || retval[strlen (retval) - 1] != '\n')
1976 retval = fgets (string, STRING_SIZE, source_file);
1977 if (!retval)
1978 break;
1979 fputs (retval, gcov_file);
1984 if (source_file)
1985 fclose (source_file);