EnumSet*.class: Regenerate
[official-gcc.git] / gcc / gcov.c
blob34ad98dda341d1fe0a849e72b650545f76be1602
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 Free Software Foundation, Inc.
5 Contributed by James E. Wilson of Cygnus Support.
6 Mangled by Bob Manson of Cygnus Support.
7 Mangled further by Nathan Sidwell <nathan@codesourcery.com>
9 Gcov is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
14 Gcov is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Gcov; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* ??? Print a list of the ten blocks with the highest execution counts,
24 and list the line numbers corresponding to those blocks. Also, perhaps
25 list the line numbers with the highest execution counts, only printing
26 the first if there are several which are all listed in the same block. */
28 /* ??? Should have an option to print the number of basic blocks, and the
29 percent of them that are covered. */
31 /* Need an option to show individual block counts, and show
32 probabilities of fall through arcs. */
34 #include "config.h"
35 #include "system.h"
36 #include "coretypes.h"
37 #include "tm.h"
38 #include "intl.h"
39 #include "version.h"
41 #include <getopt.h>
43 #define IN_GCOV 1
44 #include "gcov-io.h"
45 #include "gcov-io.c"
47 /* The gcno file is generated by -ftest-coverage option. The gcda file is
48 generated by a program compiled with -fprofile-arcs. Their formats
49 are documented in gcov-io.h. */
51 /* The functions in this file for creating and solution program flow graphs
52 are very similar to functions in the gcc source file profile.c. In
53 some places we make use of the knowledge of how profile.c works to
54 select particular algorithms here. */
56 /* This is the size of the buffer used to read in source file lines. */
58 #define STRING_SIZE 200
60 struct function_info;
61 struct block_info;
62 struct source_info;
64 /* Describes an arc between two basic blocks. */
66 typedef struct arc_info
68 /* source and destination blocks. */
69 struct block_info *src;
70 struct block_info *dst;
72 /* transition counts. */
73 gcov_type count;
74 /* used in cycle search, so that we do not clobber original counts. */
75 gcov_type cs_count;
77 unsigned int count_valid : 1;
78 unsigned int on_tree : 1;
79 unsigned int fake : 1;
80 unsigned int fall_through : 1;
82 /* Arc is for a function that abnormally returns. */
83 unsigned int is_call_non_return : 1;
85 /* Arc is for catch/setjump. */
86 unsigned int is_nonlocal_return : 1;
88 /* Is an unconditional branch. */
89 unsigned int is_unconditional : 1;
91 /* Loop making arc. */
92 unsigned int cycle : 1;
94 /* Next branch on line. */
95 struct arc_info *line_next;
97 /* Links to next arc on src and dst lists. */
98 struct arc_info *succ_next;
99 struct arc_info *pred_next;
100 } arc_t;
102 /* Describes a basic block. Contains lists of arcs to successor and
103 predecessor blocks. */
105 typedef struct block_info
107 /* Chain of exit and entry arcs. */
108 arc_t *succ;
109 arc_t *pred;
111 /* Number of unprocessed exit and entry arcs. */
112 gcov_type num_succ;
113 gcov_type num_pred;
115 /* Block execution count. */
116 gcov_type count;
117 unsigned flags : 13;
118 unsigned count_valid : 1;
119 unsigned valid_chain : 1;
120 unsigned invalid_chain : 1;
122 /* Block is a call instrumenting site. */
123 unsigned is_call_site : 1; /* Does the call. */
124 unsigned is_call_return : 1; /* Is the return. */
126 /* Block is a landing pad for longjmp or throw. */
127 unsigned is_nonlocal_return : 1;
129 union
131 struct
133 /* Array of line numbers and source files. source files are
134 introduced by a linenumber of zero, the next 'line number' is
135 the number of the source file. Always starts with a source
136 file. */
137 unsigned *encoding;
138 unsigned num;
139 } line; /* Valid until blocks are linked onto lines */
140 struct
142 /* Single line graph cycle workspace. Used for all-blocks
143 mode. */
144 arc_t *arc;
145 unsigned ident;
146 } cycle; /* Used in all-blocks mode, after blocks are linked onto
147 lines. */
148 } u;
150 /* Temporary chain for solving graph, and for chaining blocks on one
151 line. */
152 struct block_info *chain;
154 } block_t;
156 /* Describes a single function. Contains an array of basic blocks. */
158 typedef struct function_info
160 /* Name of function. */
161 char *name;
162 unsigned ident;
163 unsigned checksum;
165 /* Array of basic blocks. */
166 block_t *blocks;
167 unsigned num_blocks;
168 unsigned blocks_executed;
170 /* Raw arc coverage counts. */
171 gcov_type *counts;
172 unsigned num_counts;
174 /* First line number. */
175 unsigned line;
176 struct source_info *src;
178 /* Next function in same source file. */
179 struct function_info *line_next;
181 /* Next function. */
182 struct function_info *next;
183 } function_t;
185 /* Describes coverage of a file or function. */
187 typedef struct coverage_info
189 int lines;
190 int lines_executed;
192 int branches;
193 int branches_executed;
194 int branches_taken;
196 int calls;
197 int calls_executed;
199 char *name;
200 } coverage_t;
202 /* Describes a single line of source. Contains a chain of basic blocks
203 with code on it. */
205 typedef struct line_info
207 gcov_type count; /* execution count */
208 union
210 arc_t *branches; /* branches from blocks that end on this
211 line. Used for branch-counts when not
212 all-blocks mode. */
213 block_t *blocks; /* blocks which start on this line. Used
214 in all-blocks mode. */
215 } u;
216 unsigned exists : 1;
217 } line_t;
219 /* Describes a file mentioned in the block graph. Contains an array
220 of line info. */
222 typedef struct source_info
224 /* Name of source file. */
225 char *name;
226 unsigned index;
227 time_t file_time;
229 /* Array of line information. */
230 line_t *lines;
231 unsigned num_lines;
233 coverage_t coverage;
235 /* Functions in this source file. These are in ascending line
236 number order. */
237 function_t *functions;
239 /* Next source file. */
240 struct source_info *next;
241 } source_t;
243 /* Holds a list of function basic block graphs. */
245 static function_t *functions;
247 /* This points to the head of the sourcefile structure list. New elements
248 are always prepended. */
250 static source_t *sources;
252 /* Next index for a source file. */
254 static unsigned source_index;
256 /* This holds data summary information. */
258 static struct gcov_summary object_summary;
259 static unsigned program_count;
261 /* Modification time of graph file. */
263 static time_t bbg_file_time;
265 /* Name and file pointer of the input file for the basic block graph. */
267 static char *bbg_file_name;
269 /* Stamp of the bbg file */
270 static unsigned bbg_stamp;
272 /* Name and file pointer of the input file for the arc count data. */
274 static char *da_file_name;
276 /* Data file is missing. */
278 static int no_data_file;
280 /* If there is several input files, compute and display results after
281 reading all data files. This way if two or more gcda file refer to
282 the same source file (eg inline subprograms in a .h file), the
283 counts are added. */
285 static int multiple_files = 0;
287 /* Output branch probabilities. */
289 static int flag_branches = 0;
291 /* Show unconditional branches too. */
292 static int flag_unconditional = 0;
294 /* Output a gcov file if this is true. This is on by default, and can
295 be turned off by the -n option. */
297 static int flag_gcov_file = 1;
299 /* For included files, make the gcov output file name include the name
300 of the input source file. For example, if x.h is included in a.c,
301 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
303 static int flag_long_names = 0;
305 /* Output count information for every basic block, not merely those
306 that contain line number information. */
308 static int flag_all_blocks = 0;
310 /* Output summary info for each function. */
312 static int flag_function_summary = 0;
314 /* Object directory file prefix. This is the directory/file where the
315 graph and data files are looked for, if nonzero. */
317 static char *object_directory = 0;
319 /* Preserve all pathname components. Needed when object files and
320 source files are in subdirectories. '/' is mangled as '#', '.' is
321 elided and '..' mangled to '^'. */
323 static int flag_preserve_paths = 0;
325 /* Output the number of times a branch was taken as opposed to the percentage
326 of times it was taken. */
328 static int flag_counts = 0;
330 /* Forward declarations. */
331 static void fnotice (FILE *, const char *, ...) ATTRIBUTE_PRINTF_2;
332 static int process_args (int, char **);
333 static void print_usage (int) ATTRIBUTE_NORETURN;
334 static void print_version (void) ATTRIBUTE_NORETURN;
335 static void process_file (const char *);
336 static void generate_results (const char *);
337 static void create_file_names (const char *);
338 static source_t *find_source (const char *);
339 static int read_graph_file (void);
340 static int read_count_file (void);
341 static void solve_flow_graph (function_t *);
342 static void add_branch_counts (coverage_t *, const arc_t *);
343 static void add_line_counts (coverage_t *, function_t *);
344 static void function_summary (const coverage_t *, const char *);
345 static const char *format_gcov (gcov_type, gcov_type, int);
346 static void accumulate_line_counts (source_t *);
347 static int output_branch_count (FILE *, int, const arc_t *);
348 static void output_lines (FILE *, const source_t *);
349 static char *make_gcov_file_name (const char *, const char *);
350 static void release_structures (void);
351 extern int main (int, char **);
354 main (int argc, char **argv)
356 int argno;
358 /* Unlock the stdio streams. */
359 unlock_std_streams ();
361 gcc_init_libintl ();
363 argno = process_args (argc, argv);
364 if (optind == argc)
365 print_usage (true);
367 if (argc - argno > 1)
368 multiple_files = 1;
370 for (; argno != argc; argno++)
371 process_file (argv[argno]);
373 generate_results (multiple_files ? NULL : argv[argc - 1]);
375 release_structures ();
377 return 0;
380 static void
381 fnotice (FILE *file, const char *cmsgid, ...)
383 va_list ap;
385 va_start (ap, cmsgid);
386 vfprintf (file, _(cmsgid), ap);
387 va_end (ap);
390 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
391 otherwise the output of --help. */
393 static void
394 print_usage (int error_p)
396 FILE *file = error_p ? stderr : stdout;
397 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
399 fnotice (file, "Usage: gcov [OPTION]... SOURCEFILE...\n\n");
400 fnotice (file, "Print code coverage information.\n\n");
401 fnotice (file, " -h, --help Print this help, then exit\n");
402 fnotice (file, " -v, --version Print version number, then exit\n");
403 fnotice (file, " -a, --all-blocks Show information for every basic block\n");
404 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
405 fnotice (file, " -c, --branch-counts Given counts of branches taken\n\
406 rather than percentages\n");
407 fnotice (file, " -n, --no-output Do not create an output file\n");
408 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
409 source files\n");
410 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
411 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
412 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
413 fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
414 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
415 bug_report_url);
416 exit (status);
419 /* Print version information and exit. */
421 static void
422 print_version (void)
424 fnotice (stdout, "gcov %s%s\n", pkgversion_string, version_string);
425 fprintf (stdout, "Copyright %s 2007 Free Software Foundation, Inc.\n",
426 _("(C)"));
427 fnotice (stdout,
428 _("This is free software; see the source for copying conditions.\n"
429 "There is NO warranty; not even for MERCHANTABILITY or \n"
430 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
431 exit (SUCCESS_EXIT_CODE);
434 static const struct option options[] =
436 { "help", no_argument, NULL, 'h' },
437 { "version", no_argument, NULL, 'v' },
438 { "all-blocks", no_argument, NULL, 'a' },
439 { "branch-probabilities", no_argument, NULL, 'b' },
440 { "branch-counts", no_argument, NULL, 'c' },
441 { "no-output", no_argument, NULL, 'n' },
442 { "long-file-names", no_argument, NULL, 'l' },
443 { "function-summaries", no_argument, NULL, 'f' },
444 { "preserve-paths", no_argument, NULL, 'p' },
445 { "object-directory", required_argument, NULL, 'o' },
446 { "object-file", required_argument, NULL, 'o' },
447 { "unconditional-branches", no_argument, NULL, 'u' },
448 { 0, 0, 0, 0 }
451 /* Process args, return index to first non-arg. */
453 static int
454 process_args (int argc, char **argv)
456 int opt;
458 while ((opt = getopt_long (argc, argv, "abcfhlno:puv", options, NULL)) != -1)
460 switch (opt)
462 case 'a':
463 flag_all_blocks = 1;
464 break;
465 case 'b':
466 flag_branches = 1;
467 break;
468 case 'c':
469 flag_counts = 1;
470 break;
471 case 'f':
472 flag_function_summary = 1;
473 break;
474 case 'h':
475 print_usage (false);
476 /* print_usage will exit. */
477 case 'l':
478 flag_long_names = 1;
479 break;
480 case 'n':
481 flag_gcov_file = 0;
482 break;
483 case 'o':
484 object_directory = optarg;
485 break;
486 case 'p':
487 flag_preserve_paths = 1;
488 break;
489 case 'u':
490 flag_unconditional = 1;
491 break;
492 case 'v':
493 print_version ();
494 /* print_version will exit. */
495 default:
496 print_usage (true);
497 /* print_usage will exit. */
501 return optind;
504 /* Process a single source file. */
506 static void
507 process_file (const char *file_name)
509 function_t *fn;
510 function_t *fn_p;
511 function_t *old_functions;
513 /* Save and clear the list of current functions. They will be appended
514 later. */
515 old_functions = functions;
516 functions = NULL;
518 create_file_names (file_name);
519 if (read_graph_file ())
520 return;
522 if (!functions)
524 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
525 return;
528 if (read_count_file ())
529 return;
531 for (fn_p = NULL, fn = functions; fn; fn_p = fn, fn = fn->next)
532 solve_flow_graph (fn);
534 if (fn_p)
535 fn_p->next = old_functions;
538 static void
539 generate_results (const char *file_name)
541 source_t *src;
542 function_t *fn;
544 for (src = sources; src; src = src->next)
545 src->lines = XCNEWVEC (line_t, src->num_lines);
546 for (fn = functions; fn; fn = fn->next)
548 coverage_t coverage;
550 memset (&coverage, 0, sizeof (coverage));
551 coverage.name = fn->name;
552 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
553 if (flag_function_summary)
555 function_summary (&coverage, "Function");
556 fnotice (stdout, "\n");
560 for (src = sources; src; src = src->next)
562 accumulate_line_counts (src);
563 function_summary (&src->coverage, "File");
564 if (flag_gcov_file)
566 char *gcov_file_name = make_gcov_file_name (file_name, src->name);
567 FILE *gcov_file = fopen (gcov_file_name, "w");
569 if (gcov_file)
571 fnotice (stdout, "%s:creating '%s'\n",
572 src->name, gcov_file_name);
573 output_lines (gcov_file, src);
574 if (ferror (gcov_file))
575 fnotice (stderr, "%s:error writing output file '%s'\n",
576 src->name, gcov_file_name);
577 fclose (gcov_file);
579 else
580 fnotice (stderr, "%s:could not open output file '%s'\n",
581 src->name, gcov_file_name);
582 free (gcov_file_name);
584 fnotice (stdout, "\n");
588 /* Release all memory used. */
590 static void
591 release_structures (void)
593 function_t *fn;
594 source_t *src;
596 while ((src = sources))
598 sources = src->next;
600 free (src->name);
601 free (src->lines);
604 while ((fn = functions))
606 unsigned ix;
607 block_t *block;
609 functions = fn->next;
610 for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
612 arc_t *arc, *arc_n;
614 for (arc = block->succ; arc; arc = arc_n)
616 arc_n = arc->succ_next;
617 free (arc);
620 free (fn->blocks);
621 free (fn->counts);
625 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
626 is not specified, these are looked for in the current directory,
627 and named from the basename of the FILE_NAME sans extension. If
628 OBJECT_DIRECTORY is specified and is a directory, the files are in
629 that directory, but named from the basename of the FILE_NAME, sans
630 extension. Otherwise OBJECT_DIRECTORY is taken to be the name of
631 the object *file*, and the data files are named from that. */
633 static void
634 create_file_names (const char *file_name)
636 char *cptr;
637 char *name;
638 int length = strlen (file_name);
639 int base;
641 /* Free previous file names. */
642 if (bbg_file_name)
643 free (bbg_file_name);
644 if (da_file_name)
645 free (da_file_name);
646 da_file_name = bbg_file_name = NULL;
647 bbg_file_time = 0;
648 bbg_stamp = 0;
650 if (object_directory && object_directory[0])
652 struct stat status;
654 length += strlen (object_directory) + 2;
655 name = XNEWVEC (char, length);
656 name[0] = 0;
658 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
659 strcat (name, object_directory);
660 if (base && name[strlen (name) - 1] != '/')
661 strcat (name, "/");
663 else
665 name = XNEWVEC (char, length + 1);
666 name[0] = 0;
667 base = 1;
670 if (base)
672 /* Append source file name. */
673 cptr = strrchr (file_name, '/');
674 strcat (name, cptr ? cptr + 1 : file_name);
677 /* Remove the extension. */
678 cptr = strrchr (name, '.');
679 if (cptr)
680 *cptr = 0;
682 length = strlen (name);
684 bbg_file_name = XNEWVEC (char, length + strlen (GCOV_NOTE_SUFFIX) + 1);
685 strcpy (bbg_file_name, name);
686 strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
688 da_file_name = XNEWVEC (char, length + strlen (GCOV_DATA_SUFFIX) + 1);
689 strcpy (da_file_name, name);
690 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
692 free (name);
693 return;
696 /* Find or create a source file structure for FILE_NAME. Copies
697 FILE_NAME on creation */
699 static source_t *
700 find_source (const char *file_name)
702 source_t *src;
703 struct stat status;
705 if (!file_name)
706 file_name = "<unknown>";
708 for (src = sources; src; src = src->next)
709 if (!strcmp (file_name, src->name))
710 break;
712 if (!src)
714 src = XCNEW (source_t);
715 src->name = xstrdup (file_name);
716 src->coverage.name = src->name;
717 src->index = source_index++;
718 src->next = sources;
719 sources = src;
721 if (!stat (file_name, &status))
722 src->file_time = status.st_mtime;
725 if (src->file_time > bbg_file_time)
727 static int info_emitted;
729 fnotice (stderr, "%s:source file is newer than graph file '%s'\n",
730 src->name, bbg_file_name);
731 if (!info_emitted)
733 fnotice (stderr,
734 "(the message is only displayed one per source file)\n");
735 info_emitted = 1;
737 src->file_time = 0;
740 return src;
743 /* Read the graph file. Return nonzero on fatal error. */
745 static int
746 read_graph_file (void)
748 unsigned version;
749 unsigned current_tag = 0;
750 struct function_info *fn = NULL;
751 function_t *old_functions_head = functions;
752 source_t *src = NULL;
753 unsigned ix;
754 unsigned tag;
756 if (!gcov_open (bbg_file_name, 1))
758 fnotice (stderr, "%s:cannot open graph file\n", bbg_file_name);
759 return 1;
761 bbg_file_time = gcov_time ();
762 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
764 fnotice (stderr, "%s:not a gcov graph file\n", bbg_file_name);
765 gcov_close ();
766 return 1;
769 version = gcov_read_unsigned ();
770 if (version != GCOV_VERSION)
772 char v[4], e[4];
774 GCOV_UNSIGNED2STRING (v, version);
775 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
777 fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n",
778 bbg_file_name, v, e);
780 bbg_stamp = gcov_read_unsigned ();
782 while ((tag = gcov_read_unsigned ()))
784 unsigned length = gcov_read_unsigned ();
785 gcov_position_t base = gcov_position ();
787 if (tag == GCOV_TAG_FUNCTION)
789 char *function_name;
790 unsigned ident, checksum, lineno;
791 source_t *src;
792 function_t *probe, *prev;
794 ident = gcov_read_unsigned ();
795 checksum = gcov_read_unsigned ();
796 function_name = xstrdup (gcov_read_string ());
797 src = find_source (gcov_read_string ());
798 lineno = gcov_read_unsigned ();
800 fn = XCNEW (function_t);
801 fn->name = function_name;
802 fn->ident = ident;
803 fn->checksum = checksum;
804 fn->src = src;
805 fn->line = lineno;
807 fn->next = functions;
808 functions = fn;
809 current_tag = tag;
811 if (lineno >= src->num_lines)
812 src->num_lines = lineno + 1;
813 /* Now insert it into the source file's list of
814 functions. Normally functions will be encountered in
815 ascending order, so a simple scan is quick. */
816 for (probe = src->functions, prev = NULL;
817 probe && probe->line > lineno;
818 prev = probe, probe = probe->line_next)
819 continue;
820 fn->line_next = probe;
821 if (prev)
822 prev->line_next = fn;
823 else
824 src->functions = fn;
826 else if (fn && tag == GCOV_TAG_BLOCKS)
828 if (fn->blocks)
829 fnotice (stderr, "%s:already seen blocks for '%s'\n",
830 bbg_file_name, fn->name);
831 else
833 unsigned ix, num_blocks = GCOV_TAG_BLOCKS_NUM (length);
834 fn->num_blocks = num_blocks;
836 fn->blocks = XCNEWVEC (block_t, fn->num_blocks);
837 for (ix = 0; ix != num_blocks; ix++)
838 fn->blocks[ix].flags = gcov_read_unsigned ();
841 else if (fn && tag == GCOV_TAG_ARCS)
843 unsigned src = gcov_read_unsigned ();
844 unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
846 if (src >= fn->num_blocks || fn->blocks[src].succ)
847 goto corrupt;
849 while (num_dests--)
851 struct arc_info *arc;
852 unsigned dest = gcov_read_unsigned ();
853 unsigned flags = gcov_read_unsigned ();
855 if (dest >= fn->num_blocks)
856 goto corrupt;
857 arc = XCNEW (arc_t);
859 arc->dst = &fn->blocks[dest];
860 arc->src = &fn->blocks[src];
862 arc->count = 0;
863 arc->count_valid = 0;
864 arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
865 arc->fake = !!(flags & GCOV_ARC_FAKE);
866 arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
868 arc->succ_next = fn->blocks[src].succ;
869 fn->blocks[src].succ = arc;
870 fn->blocks[src].num_succ++;
872 arc->pred_next = fn->blocks[dest].pred;
873 fn->blocks[dest].pred = arc;
874 fn->blocks[dest].num_pred++;
876 if (arc->fake)
878 if (src)
880 /* Exceptional exit from this function, the
881 source block must be a call. */
882 fn->blocks[src].is_call_site = 1;
883 arc->is_call_non_return = 1;
885 else
887 /* Non-local return from a callee of this
888 function. The destination block is a catch or
889 setjmp. */
890 arc->is_nonlocal_return = 1;
891 fn->blocks[dest].is_nonlocal_return = 1;
895 if (!arc->on_tree)
896 fn->num_counts++;
899 else if (fn && tag == GCOV_TAG_LINES)
901 unsigned blockno = gcov_read_unsigned ();
902 unsigned *line_nos = XCNEWVEC (unsigned, length - 1);
904 if (blockno >= fn->num_blocks || fn->blocks[blockno].u.line.encoding)
905 goto corrupt;
907 for (ix = 0; ; )
909 unsigned lineno = gcov_read_unsigned ();
911 if (lineno)
913 if (!ix)
915 line_nos[ix++] = 0;
916 line_nos[ix++] = src->index;
918 line_nos[ix++] = lineno;
919 if (lineno >= src->num_lines)
920 src->num_lines = lineno + 1;
922 else
924 const char *file_name = gcov_read_string ();
926 if (!file_name)
927 break;
928 src = find_source (file_name);
930 line_nos[ix++] = 0;
931 line_nos[ix++] = src->index;
935 fn->blocks[blockno].u.line.encoding = line_nos;
936 fn->blocks[blockno].u.line.num = ix;
938 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
940 fn = NULL;
941 current_tag = 0;
943 gcov_sync (base, length);
944 if (gcov_is_error ())
946 corrupt:;
947 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
948 gcov_close ();
949 return 1;
952 gcov_close ();
954 /* We built everything backwards, so nreverse them all. */
956 /* Reverse sources. Not strictly necessary, but we'll then process
957 them in the 'expected' order. */
959 source_t *src, *src_p, *src_n;
961 for (src_p = NULL, src = sources; src; src_p = src, src = src_n)
963 src_n = src->next;
964 src->next = src_p;
966 sources = src_p;
969 /* Reverse functions. */
971 function_t *fn, *fn_p, *fn_n;
973 for (fn_p = old_functions_head, fn = functions;
974 fn != old_functions_head;
975 fn_p = fn, fn = fn_n)
977 unsigned ix;
979 fn_n = fn->next;
980 fn->next = fn_p;
982 /* Reverse the arcs. */
983 for (ix = fn->num_blocks; ix--;)
985 arc_t *arc, *arc_p, *arc_n;
987 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
988 arc_p = arc, arc = arc_n)
990 arc_n = arc->succ_next;
991 arc->succ_next = arc_p;
993 fn->blocks[ix].succ = arc_p;
995 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
996 arc_p = arc, arc = arc_n)
998 arc_n = arc->pred_next;
999 arc->pred_next = arc_p;
1001 fn->blocks[ix].pred = arc_p;
1004 functions = fn_p;
1006 return 0;
1009 /* Reads profiles from the count file and attach to each
1010 function. Return nonzero if fatal error. */
1012 static int
1013 read_count_file (void)
1015 unsigned ix;
1016 unsigned version;
1017 unsigned tag;
1018 function_t *fn = NULL;
1019 int error = 0;
1021 if (!gcov_open (da_file_name, 1))
1023 fnotice (stderr, "%s:cannot open data file, assuming not executed\n",
1024 da_file_name);
1025 no_data_file = 1;
1026 return 0;
1028 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
1030 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
1031 cleanup:;
1032 gcov_close ();
1033 return 1;
1035 version = gcov_read_unsigned ();
1036 if (version != GCOV_VERSION)
1038 char v[4], e[4];
1040 GCOV_UNSIGNED2STRING (v, version);
1041 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1043 fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
1044 da_file_name, v, e);
1046 tag = gcov_read_unsigned ();
1047 if (tag != bbg_stamp)
1049 fnotice (stderr, "%s:stamp mismatch with graph file\n", da_file_name);
1050 goto cleanup;
1053 while ((tag = gcov_read_unsigned ()))
1055 unsigned length = gcov_read_unsigned ();
1056 unsigned long base = gcov_position ();
1058 if (tag == GCOV_TAG_OBJECT_SUMMARY)
1059 gcov_read_summary (&object_summary);
1060 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
1061 program_count++;
1062 else if (tag == GCOV_TAG_FUNCTION)
1064 unsigned ident = gcov_read_unsigned ();
1065 struct function_info *fn_n = functions;
1067 /* Try to find the function in the list.
1068 To speed up the search, first start from the last function
1069 found. */
1070 for (fn = fn ? fn->next : NULL; ; fn = fn->next)
1072 if (fn)
1074 else if ((fn = fn_n))
1075 fn_n = NULL;
1076 else
1078 fnotice (stderr, "%s:unknown function '%u'\n",
1079 da_file_name, ident);
1080 break;
1082 if (fn->ident == ident)
1083 break;
1086 if (!fn)
1088 else if (gcov_read_unsigned () != fn->checksum)
1090 mismatch:;
1091 fnotice (stderr, "%s:profile mismatch for '%s'\n",
1092 da_file_name, fn->name);
1093 goto cleanup;
1096 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
1098 if (length != GCOV_TAG_COUNTER_LENGTH (fn->num_counts))
1099 goto mismatch;
1101 if (!fn->counts)
1102 fn->counts = XCNEWVEC (gcov_type, fn->num_counts);
1104 for (ix = 0; ix != fn->num_counts; ix++)
1105 fn->counts[ix] += gcov_read_counter ();
1107 gcov_sync (base, length);
1108 if ((error = gcov_is_error ()))
1110 fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1111 da_file_name);
1112 goto cleanup;
1116 gcov_close ();
1117 return 0;
1120 /* Solve the flow graph. Propagate counts from the instrumented arcs
1121 to the blocks and the uninstrumented arcs. */
1123 static void
1124 solve_flow_graph (function_t *fn)
1126 unsigned ix;
1127 arc_t *arc;
1128 gcov_type *count_ptr = fn->counts;
1129 block_t *blk;
1130 block_t *valid_blocks = NULL; /* valid, but unpropagated blocks. */
1131 block_t *invalid_blocks = NULL; /* invalid, but inferable blocks. */
1133 if (fn->num_blocks < 2)
1134 fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n",
1135 bbg_file_name, fn->name);
1136 else
1138 if (fn->blocks[0].num_pred)
1139 fnotice (stderr, "%s:'%s' has arcs to entry block\n",
1140 bbg_file_name, fn->name);
1141 else
1142 /* We can't deduce the entry block counts from the lack of
1143 predecessors. */
1144 fn->blocks[0].num_pred = ~(unsigned)0;
1146 if (fn->blocks[fn->num_blocks - 1].num_succ)
1147 fnotice (stderr, "%s:'%s' has arcs from exit block\n",
1148 bbg_file_name, fn->name);
1149 else
1150 /* Likewise, we can't deduce exit block counts from the lack
1151 of its successors. */
1152 fn->blocks[fn->num_blocks - 1].num_succ = ~(unsigned)0;
1155 /* Propagate the measured counts, this must be done in the same
1156 order as the code in profile.c */
1157 for (ix = 0, blk = fn->blocks; ix != fn->num_blocks; ix++, blk++)
1159 block_t const *prev_dst = NULL;
1160 int out_of_order = 0;
1161 int non_fake_succ = 0;
1163 for (arc = blk->succ; arc; arc = arc->succ_next)
1165 if (!arc->fake)
1166 non_fake_succ++;
1168 if (!arc->on_tree)
1170 if (count_ptr)
1171 arc->count = *count_ptr++;
1172 arc->count_valid = 1;
1173 blk->num_succ--;
1174 arc->dst->num_pred--;
1176 if (prev_dst && prev_dst > arc->dst)
1177 out_of_order = 1;
1178 prev_dst = arc->dst;
1180 if (non_fake_succ == 1)
1182 /* If there is only one non-fake exit, it is an
1183 unconditional branch. */
1184 for (arc = blk->succ; arc; arc = arc->succ_next)
1185 if (!arc->fake)
1187 arc->is_unconditional = 1;
1188 /* If this block is instrumenting a call, it might be
1189 an artificial block. It is not artificial if it has
1190 a non-fallthrough exit, or the destination of this
1191 arc has more than one entry. Mark the destination
1192 block as a return site, if none of those conditions
1193 hold. */
1194 if (blk->is_call_site && arc->fall_through
1195 && arc->dst->pred == arc && !arc->pred_next)
1196 arc->dst->is_call_return = 1;
1200 /* Sort the successor arcs into ascending dst order. profile.c
1201 normally produces arcs in the right order, but sometimes with
1202 one or two out of order. We're not using a particularly
1203 smart sort. */
1204 if (out_of_order)
1206 arc_t *start = blk->succ;
1207 unsigned changes = 1;
1209 while (changes)
1211 arc_t *arc, *arc_p, *arc_n;
1213 changes = 0;
1214 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1216 if (arc->dst > arc_n->dst)
1218 changes = 1;
1219 if (arc_p)
1220 arc_p->succ_next = arc_n;
1221 else
1222 start = arc_n;
1223 arc->succ_next = arc_n->succ_next;
1224 arc_n->succ_next = arc;
1225 arc_p = arc_n;
1227 else
1229 arc_p = arc;
1230 arc = arc_n;
1234 blk->succ = start;
1237 /* Place it on the invalid chain, it will be ignored if that's
1238 wrong. */
1239 blk->invalid_chain = 1;
1240 blk->chain = invalid_blocks;
1241 invalid_blocks = blk;
1244 while (invalid_blocks || valid_blocks)
1246 while ((blk = invalid_blocks))
1248 gcov_type total = 0;
1249 const arc_t *arc;
1251 invalid_blocks = blk->chain;
1252 blk->invalid_chain = 0;
1253 if (!blk->num_succ)
1254 for (arc = blk->succ; arc; arc = arc->succ_next)
1255 total += arc->count;
1256 else if (!blk->num_pred)
1257 for (arc = blk->pred; arc; arc = arc->pred_next)
1258 total += arc->count;
1259 else
1260 continue;
1262 blk->count = total;
1263 blk->count_valid = 1;
1264 blk->chain = valid_blocks;
1265 blk->valid_chain = 1;
1266 valid_blocks = blk;
1268 while ((blk = valid_blocks))
1270 gcov_type total;
1271 arc_t *arc, *inv_arc;
1273 valid_blocks = blk->chain;
1274 blk->valid_chain = 0;
1275 if (blk->num_succ == 1)
1277 block_t *dst;
1279 total = blk->count;
1280 inv_arc = NULL;
1281 for (arc = blk->succ; arc; arc = arc->succ_next)
1283 total -= arc->count;
1284 if (!arc->count_valid)
1285 inv_arc = arc;
1287 dst = inv_arc->dst;
1288 inv_arc->count_valid = 1;
1289 inv_arc->count = total;
1290 blk->num_succ--;
1291 dst->num_pred--;
1292 if (dst->count_valid)
1294 if (dst->num_pred == 1 && !dst->valid_chain)
1296 dst->chain = valid_blocks;
1297 dst->valid_chain = 1;
1298 valid_blocks = dst;
1301 else
1303 if (!dst->num_pred && !dst->invalid_chain)
1305 dst->chain = invalid_blocks;
1306 dst->invalid_chain = 1;
1307 invalid_blocks = dst;
1311 if (blk->num_pred == 1)
1313 block_t *src;
1315 total = blk->count;
1316 inv_arc = NULL;
1317 for (arc = blk->pred; arc; arc = arc->pred_next)
1319 total -= arc->count;
1320 if (!arc->count_valid)
1321 inv_arc = arc;
1323 src = inv_arc->src;
1324 inv_arc->count_valid = 1;
1325 inv_arc->count = total;
1326 blk->num_pred--;
1327 src->num_succ--;
1328 if (src->count_valid)
1330 if (src->num_succ == 1 && !src->valid_chain)
1332 src->chain = valid_blocks;
1333 src->valid_chain = 1;
1334 valid_blocks = src;
1337 else
1339 if (!src->num_succ && !src->invalid_chain)
1341 src->chain = invalid_blocks;
1342 src->invalid_chain = 1;
1343 invalid_blocks = src;
1350 /* If the graph has been correctly solved, every block will have a
1351 valid count. */
1352 for (ix = 0; ix < fn->num_blocks; ix++)
1353 if (!fn->blocks[ix].count_valid)
1355 fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
1356 bbg_file_name, fn->name);
1357 break;
1363 /* Increment totals in COVERAGE according to arc ARC. */
1365 static void
1366 add_branch_counts (coverage_t *coverage, const arc_t *arc)
1368 if (arc->is_call_non_return)
1370 coverage->calls++;
1371 if (arc->src->count)
1372 coverage->calls_executed++;
1374 else if (!arc->is_unconditional)
1376 coverage->branches++;
1377 if (arc->src->count)
1378 coverage->branches_executed++;
1379 if (arc->count)
1380 coverage->branches_taken++;
1384 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1385 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1386 If DP is zero, no decimal point is printed. Only print 100% when
1387 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1388 format TOP. Return pointer to a static string. */
1390 static char const *
1391 format_gcov (gcov_type top, gcov_type bottom, int dp)
1393 static char buffer[20];
1395 if (dp >= 0)
1397 float ratio = bottom ? (float)top / bottom : 0;
1398 int ix;
1399 unsigned limit = 100;
1400 unsigned percent;
1402 for (ix = dp; ix--; )
1403 limit *= 10;
1405 percent = (unsigned) (ratio * limit + (float)0.5);
1406 if (percent <= 0 && top)
1407 percent = 1;
1408 else if (percent >= limit && top != bottom)
1409 percent = limit - 1;
1410 ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1411 if (dp)
1413 dp++;
1416 buffer[ix+1] = buffer[ix];
1417 ix--;
1419 while (dp--);
1420 buffer[ix + 1] = '.';
1423 else
1424 sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)top);
1426 return buffer;
1430 /* Output summary info for a function. */
1432 static void
1433 function_summary (const coverage_t *coverage, const char *title)
1435 fnotice (stdout, "%s '%s'\n", title, coverage->name);
1437 if (coverage->lines)
1438 fnotice (stdout, "Lines executed:%s of %d\n",
1439 format_gcov (coverage->lines_executed, coverage->lines, 2),
1440 coverage->lines);
1441 else
1442 fnotice (stdout, "No executable lines\n");
1444 if (flag_branches)
1446 if (coverage->branches)
1448 fnotice (stdout, "Branches executed:%s of %d\n",
1449 format_gcov (coverage->branches_executed,
1450 coverage->branches, 2),
1451 coverage->branches);
1452 fnotice (stdout, "Taken at least once:%s of %d\n",
1453 format_gcov (coverage->branches_taken,
1454 coverage->branches, 2),
1455 coverage->branches);
1457 else
1458 fnotice (stdout, "No branches\n");
1459 if (coverage->calls)
1460 fnotice (stdout, "Calls executed:%s of %d\n",
1461 format_gcov (coverage->calls_executed, coverage->calls, 2),
1462 coverage->calls);
1463 else
1464 fnotice (stdout, "No calls\n");
1468 /* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
1469 affect name generation. With preserve_paths we create a filename
1470 from all path components of the source file, replacing '/' with
1471 '#', without it we simply take the basename component. With
1472 long_output_names we prepend the processed name of the input file
1473 to each output name (except when the current source file is the
1474 input file, so you don't get a double concatenation). The two
1475 components are separated by '##'. Also '.' filename components are
1476 removed and '..' components are renamed to '^'. */
1478 static char *
1479 make_gcov_file_name (const char *input_name, const char *src_name)
1481 char *cptr;
1482 char *name;
1484 if (flag_long_names && input_name && strcmp (src_name, input_name))
1486 name = XNEWVEC (char, strlen (src_name) + strlen (input_name) + 10);
1487 name[0] = 0;
1488 /* Generate the input filename part. */
1489 cptr = flag_preserve_paths ? NULL : strrchr (input_name, '/');
1490 strcat (name, cptr ? cptr + 1 : input_name);
1491 strcat (name, "##");
1493 else
1495 name = XNEWVEC (char, strlen (src_name) + 10);
1496 name[0] = 0;
1499 /* Generate the source filename part. */
1500 cptr = flag_preserve_paths ? NULL : strrchr (src_name, '/');
1501 strcat (name, cptr ? cptr + 1 : src_name);
1503 if (flag_preserve_paths)
1505 /* Convert '/' to '#', remove '/./', convert '/../' to '/^/' */
1506 char *prev;
1508 for (cptr = name; (cptr = strchr ((prev = cptr), '/'));)
1510 unsigned shift = 0;
1512 if (prev + 1 == cptr && prev[0] == '.')
1514 /* Remove '.' */
1515 shift = 2;
1517 else if (prev + 2 == cptr && prev[0] == '.' && prev[1] == '.')
1519 /* Convert '..' */
1520 shift = 1;
1521 prev[1] = '^';
1523 else
1524 *cptr++ = '#';
1525 if (shift)
1527 cptr = prev;
1529 prev[0] = prev[shift];
1530 while (*prev++);
1535 strcat (name, ".gcov");
1536 return name;
1539 /* Scan through the bb_data for each line in the block, increment
1540 the line number execution count indicated by the execution count of
1541 the appropriate basic block. */
1543 static void
1544 add_line_counts (coverage_t *coverage, function_t *fn)
1546 unsigned ix;
1547 line_t *line = NULL; /* This is propagated from one iteration to the
1548 next. */
1550 /* Scan each basic block. */
1551 for (ix = 0; ix != fn->num_blocks; ix++)
1553 block_t *block = &fn->blocks[ix];
1554 unsigned *encoding;
1555 const source_t *src = NULL;
1556 unsigned jx;
1558 if (block->count && ix && ix + 1 != fn->num_blocks)
1559 fn->blocks_executed++;
1560 for (jx = 0, encoding = block->u.line.encoding;
1561 jx != block->u.line.num; jx++, encoding++)
1562 if (!*encoding)
1564 unsigned src_n = *++encoding;
1566 for (src = sources; src->index != src_n; src = src->next)
1567 continue;
1568 jx++;
1570 else
1572 line = &src->lines[*encoding];
1574 if (coverage)
1576 if (!line->exists)
1577 coverage->lines++;
1578 if (!line->count && block->count)
1579 coverage->lines_executed++;
1581 line->exists = 1;
1582 line->count += block->count;
1584 free (block->u.line.encoding);
1585 block->u.cycle.arc = NULL;
1586 block->u.cycle.ident = ~0U;
1588 if (!ix || ix + 1 == fn->num_blocks)
1589 /* Entry or exit block */;
1590 else if (flag_all_blocks)
1592 line_t *block_line = line ? line : &fn->src->lines[fn->line];
1594 block->chain = block_line->u.blocks;
1595 block_line->u.blocks = block;
1597 else if (flag_branches)
1599 arc_t *arc;
1601 for (arc = block->succ; arc; arc = arc->succ_next)
1603 arc->line_next = line->u.branches;
1604 line->u.branches = arc;
1605 if (coverage && !arc->is_unconditional)
1606 add_branch_counts (coverage, arc);
1610 if (!line)
1611 fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, fn->name);
1614 /* Accumulate the line counts of a file. */
1616 static void
1617 accumulate_line_counts (source_t *src)
1619 line_t *line;
1620 function_t *fn, *fn_p, *fn_n;
1621 unsigned ix;
1623 /* Reverse the function order. */
1624 for (fn = src->functions, fn_p = NULL; fn;
1625 fn_p = fn, fn = fn_n)
1627 fn_n = fn->line_next;
1628 fn->line_next = fn_p;
1630 src->functions = fn_p;
1632 for (ix = src->num_lines, line = src->lines; ix--; line++)
1634 if (!flag_all_blocks)
1636 arc_t *arc, *arc_p, *arc_n;
1638 /* Total and reverse the branch information. */
1639 for (arc = line->u.branches, arc_p = NULL; arc;
1640 arc_p = arc, arc = arc_n)
1642 arc_n = arc->line_next;
1643 arc->line_next = arc_p;
1645 add_branch_counts (&src->coverage, arc);
1647 line->u.branches = arc_p;
1649 else if (line->u.blocks)
1651 /* The user expects the line count to be the number of times
1652 a line has been executed. Simply summing the block count
1653 will give an artificially high number. The Right Thing
1654 is to sum the entry counts to the graph of blocks on this
1655 line, then find the elementary cycles of the local graph
1656 and add the transition counts of those cycles. */
1657 block_t *block, *block_p, *block_n;
1658 gcov_type count = 0;
1660 /* Reverse the block information. */
1661 for (block = line->u.blocks, block_p = NULL; block;
1662 block_p = block, block = block_n)
1664 block_n = block->chain;
1665 block->chain = block_p;
1666 block->u.cycle.ident = ix;
1668 line->u.blocks = block_p;
1670 /* Sum the entry arcs. */
1671 for (block = line->u.blocks; block; block = block->chain)
1673 arc_t *arc;
1675 for (arc = block->pred; arc; arc = arc->pred_next)
1677 if (arc->src->u.cycle.ident != ix)
1678 count += arc->count;
1679 if (flag_branches)
1680 add_branch_counts (&src->coverage, arc);
1683 /* Initialize the cs_count. */
1684 for (arc = block->succ; arc; arc = arc->succ_next)
1685 arc->cs_count = arc->count;
1688 /* Find the loops. This uses the algorithm described in
1689 Tiernan 'An Efficient Search Algorithm to Find the
1690 Elementary Circuits of a Graph', CACM Dec 1970. We hold
1691 the P array by having each block point to the arc that
1692 connects to the previous block. The H array is implicitly
1693 held because of the arc ordering, and the block's
1694 previous arc pointer.
1696 Although the algorithm is O(N^3) for highly connected
1697 graphs, at worst we'll have O(N^2), as most blocks have
1698 only one or two exits. Most graphs will be small.
1700 For each loop we find, locate the arc with the smallest
1701 transition count, and add that to the cumulative
1702 count. Decrease flow over the cycle and remove the arc
1703 from consideration. */
1704 for (block = line->u.blocks; block; block = block->chain)
1706 block_t *head = block;
1707 arc_t *arc;
1709 next_vertex:;
1710 arc = head->succ;
1711 current_vertex:;
1712 while (arc)
1714 block_t *dst = arc->dst;
1715 if (/* Already used that arc. */
1716 arc->cycle
1717 /* Not to same graph, or before first vertex. */
1718 || dst->u.cycle.ident != ix
1719 /* Already in path. */
1720 || dst->u.cycle.arc)
1722 arc = arc->succ_next;
1723 continue;
1726 if (dst == block)
1728 /* Found a closing arc. */
1729 gcov_type cycle_count = arc->cs_count;
1730 arc_t *cycle_arc = arc;
1731 arc_t *probe_arc;
1733 /* Locate the smallest arc count of the loop. */
1734 for (dst = head; (probe_arc = dst->u.cycle.arc);
1735 dst = probe_arc->src)
1736 if (cycle_count > probe_arc->cs_count)
1738 cycle_count = probe_arc->cs_count;
1739 cycle_arc = probe_arc;
1742 count += cycle_count;
1743 cycle_arc->cycle = 1;
1745 /* Remove the flow from the cycle. */
1746 arc->cs_count -= cycle_count;
1747 for (dst = head; (probe_arc = dst->u.cycle.arc);
1748 dst = probe_arc->src)
1749 probe_arc->cs_count -= cycle_count;
1751 /* Unwind to the cyclic arc. */
1752 while (head != cycle_arc->src)
1754 arc = head->u.cycle.arc;
1755 head->u.cycle.arc = NULL;
1756 head = arc->src;
1758 /* Move on. */
1759 arc = arc->succ_next;
1760 continue;
1763 /* Add new block to chain. */
1764 dst->u.cycle.arc = arc;
1765 head = dst;
1766 goto next_vertex;
1768 /* We could not add another vertex to the path. Remove
1769 the last vertex from the list. */
1770 arc = head->u.cycle.arc;
1771 if (arc)
1773 /* It was not the first vertex. Move onto next arc. */
1774 head->u.cycle.arc = NULL;
1775 head = arc->src;
1776 arc = arc->succ_next;
1777 goto current_vertex;
1779 /* Mark this block as unusable. */
1780 block->u.cycle.ident = ~0U;
1783 line->count = count;
1786 if (line->exists)
1788 src->coverage.lines++;
1789 if (line->count)
1790 src->coverage.lines_executed++;
1795 /* Output information about ARC number IX. Returns nonzero if
1796 anything is output. */
1798 static int
1799 output_branch_count (FILE *gcov_file, int ix, const arc_t *arc)
1802 if (arc->is_call_non_return)
1804 if (arc->src->count)
1806 fnotice (gcov_file, "call %2d returned %s\n", ix,
1807 format_gcov (arc->src->count - arc->count,
1808 arc->src->count, -flag_counts));
1810 else
1811 fnotice (gcov_file, "call %2d never executed\n", ix);
1813 else if (!arc->is_unconditional)
1815 if (arc->src->count)
1816 fnotice (gcov_file, "branch %2d taken %s%s\n", ix,
1817 format_gcov (arc->count, arc->src->count, -flag_counts),
1818 arc->fall_through ? " (fallthrough)" : "");
1819 else
1820 fnotice (gcov_file, "branch %2d never executed\n", ix);
1822 else if (flag_unconditional && !arc->dst->is_call_return)
1824 if (arc->src->count)
1825 fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
1826 format_gcov (arc->count, arc->src->count, -flag_counts));
1827 else
1828 fnotice (gcov_file, "unconditional %2d never executed\n", ix);
1830 else
1831 return 0;
1832 return 1;
1836 /* Read in the source file one line at a time, and output that line to
1837 the gcov file preceded by its execution count and other
1838 information. */
1840 static void
1841 output_lines (FILE *gcov_file, const source_t *src)
1843 FILE *source_file;
1844 unsigned line_num; /* current line number. */
1845 const line_t *line; /* current line info ptr. */
1846 char string[STRING_SIZE]; /* line buffer. */
1847 char const *retval = ""; /* status of source file reading. */
1848 function_t *fn = NULL;
1850 fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->name);
1851 if (!multiple_files)
1853 fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
1854 fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0,
1855 no_data_file ? "-" : da_file_name);
1856 fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0,
1857 object_summary.ctrs[GCOV_COUNTER_ARCS].runs);
1859 fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
1861 source_file = fopen (src->name, "r");
1862 if (!source_file)
1864 fnotice (stderr, "%s:cannot open source file\n", src->name);
1865 retval = NULL;
1867 else if (src->file_time == 0)
1868 fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n", "-", 0);
1870 if (flag_branches)
1871 fn = src->functions;
1873 for (line_num = 1, line = &src->lines[line_num];
1874 line_num < src->num_lines; line_num++, line++)
1876 for (; fn && fn->line == line_num; fn = fn->line_next)
1878 arc_t *arc = fn->blocks[fn->num_blocks - 1].pred;
1879 gcov_type return_count = fn->blocks[fn->num_blocks - 1].count;
1881 for (; arc; arc = arc->pred_next)
1882 if (arc->fake)
1883 return_count -= arc->count;
1885 fprintf (gcov_file, "function %s", fn->name);
1886 fprintf (gcov_file, " called %s",
1887 format_gcov (fn->blocks[0].count, 0, -1));
1888 fprintf (gcov_file, " returned %s",
1889 format_gcov (return_count, fn->blocks[0].count, 0));
1890 fprintf (gcov_file, " blocks executed %s",
1891 format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0));
1892 fprintf (gcov_file, "\n");
1895 /* For lines which don't exist in the .bb file, print '-' before
1896 the source line. For lines which exist but were never
1897 executed, print '#####' before the source line. Otherwise,
1898 print the execution count before the source line. There are
1899 16 spaces of indentation added before the source line so that
1900 tabs won't be messed up. */
1901 fprintf (gcov_file, "%9s:%5u:",
1902 !line->exists ? "-" : !line->count ? "#####"
1903 : format_gcov (line->count, 0, -1), line_num);
1905 if (retval)
1907 /* Copy source line. */
1910 retval = fgets (string, STRING_SIZE, source_file);
1911 if (!retval)
1912 break;
1913 fputs (retval, gcov_file);
1915 while (!retval[0] || retval[strlen (retval) - 1] != '\n');
1917 if (!retval)
1918 fputs ("/*EOF*/\n", gcov_file);
1920 if (flag_all_blocks)
1922 block_t *block;
1923 arc_t *arc;
1924 int ix, jx;
1926 for (ix = jx = 0, block = line->u.blocks; block;
1927 block = block->chain)
1929 if (!block->is_call_return)
1930 fprintf (gcov_file, "%9s:%5u-block %2d\n",
1931 !line->exists ? "-" : !block->count ? "$$$$$"
1932 : format_gcov (block->count, 0, -1),
1933 line_num, ix++);
1934 if (flag_branches)
1935 for (arc = block->succ; arc; arc = arc->succ_next)
1936 jx += output_branch_count (gcov_file, jx, arc);
1939 else if (flag_branches)
1941 int ix;
1942 arc_t *arc;
1944 for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
1945 ix += output_branch_count (gcov_file, ix, arc);
1949 /* Handle all remaining source lines. There may be lines after the
1950 last line of code. */
1951 if (retval)
1953 for (; (retval = fgets (string, STRING_SIZE, source_file)); line_num++)
1955 fprintf (gcov_file, "%9s:%5u:%s", "-", line_num, retval);
1957 while (!retval[0] || retval[strlen (retval) - 1] != '\n')
1959 retval = fgets (string, STRING_SIZE, source_file);
1960 if (!retval)
1961 break;
1962 fputs (retval, gcov_file);
1967 if (source_file)
1968 fclose (source_file);