gcov-io.h: Update documentation.
[gcc.git] / gcc / gcov.c
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,
4 1999, 2000, 2001, 2002, 2003 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>
8
9 Gcov is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13
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.
18
19 You should have received a copy of the GNU General Public License
20 along with Gcov; see the file COPYING. If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
23
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. */
28
29 /* ??? Should have an option to print the number of basic blocks, and the
30 percent of them that are covered. */
31
32 /* ??? Does not correctly handle the case where two .bb files refer to
33 the same included source file. For example, if one has a short
34 file containing only inline functions, which is then included in
35 two other files, then there will be two .bb files which refer to
36 the include file, but there is no way to get the total execution
37 counts for the included file, can only get execution counts for one
38 or the other of the including files. this can be fixed by --ratios
39 --long-file-names --preserve-paths and perl. */
40
41 /* Need an option to show individual block counts, and show
42 probabilities of fall through arcs. */
43
44 #include "config.h"
45 #include "system.h"
46 #include "coretypes.h"
47 #include "tm.h"
48 #include "intl.h"
49 #include "version.h"
50 #undef abort
51
52 #include <getopt.h>
53
54 #define IN_GCOV 1
55 #include "gcov-io.h"
56 #include "gcov-io.c"
57
58 /* The bbg file is generated by -ftest-coverage option. The da file is
59 generated by a program compiled with -fprofile-arcs. Their formats
60 are documented in gcov-io.h. */
61
62 /* The functions in this file for creating and solution program flow graphs
63 are very similar to functions in the gcc source file profile.c. In
64 some places we make use of the knowledge of how profile.c works to
65 select particular algorithms here. */
66
67 /* This is the size of the buffer used to read in source file lines. */
68
69 #define STRING_SIZE 200
70
71 struct function_info;
72 struct block_info;
73 struct source_info;
74
75 /* Describes an arc between two basic blocks. */
76
77 typedef struct arc_info
78 {
79 /* source and destination blocks. */
80 struct block_info *src;
81 struct block_info *dst;
82
83 /* transition counts. */
84 gcov_type count;
85
86 unsigned int count_valid : 1;
87 unsigned int on_tree : 1;
88 unsigned int fake : 1;
89 unsigned int fall_through : 1;
90
91 /* Arc is for a function that abnormally returns. */
92 unsigned int is_call_non_return : 1;
93
94 /* Arc is for catch/setjump. */
95 unsigned int is_nonlocal_return : 1;
96
97 /* Is an unconditional branch. */
98 unsigned int is_unconditional : 1;
99
100 /* Loop making arc. */
101 unsigned int cycle : 1;
102
103 /* Next branch on line. */
104 struct arc_info *line_next;
105
106 /* Links to next arc on src and dst lists. */
107 struct arc_info *succ_next;
108 struct arc_info *pred_next;
109 } arc_t;
110
111 /* Describes a basic block. Contains lists of arcs to successor and
112 predecessor blocks. */
113
114 typedef struct block_info
115 {
116 /* Chain of exit and entry arcs. */
117 arc_t *succ;
118 arc_t *pred;
119
120 /* Number of unprocessed exit and entry arcs. */
121 gcov_type num_succ;
122 gcov_type num_pred;
123
124 /* Block execution count. */
125 gcov_type count;
126 unsigned flags : 13;
127 unsigned count_valid : 1;
128 unsigned valid_chain : 1;
129 unsigned invalid_chain : 1;
130
131 /* Block is a call instrumenting site. */
132 unsigned is_call_site : 1; /* Does the call. */
133 unsigned is_call_return : 1; /* Is the return. */
134
135 /* Block is a landing pad for longjmp or throw. */
136 unsigned is_nonlocal_return : 1;
137
138 union
139 {
140 struct
141 {
142 /* Array of line numbers and source files. source files are
143 introduced by a linenumber of zero, the next 'line number' is
144 the number of the source file. Always starts with a source
145 file. */
146 unsigned *encoding;
147 unsigned num;
148 } line; /* Valid until blocks are linked onto lines */
149 struct
150 {
151 /* Single line graph cycle workspace. Used for all-blocks
152 mode. */
153 arc_t *arc;
154 unsigned ident;
155 } cycle; /* Used in all-blocks mode, after blocks are linked onto
156 lines. */
157 } u;
158
159 /* Temporary chain for solving graph, and for chaining blocks on one
160 line. */
161 struct block_info *chain;
162
163 } block_t;
164
165 /* Describes a single function. Contains an array of basic blocks. */
166
167 typedef struct function_info
168 {
169 /* Name of function. */
170 char *name;
171 unsigned ident;
172 unsigned checksum;
173
174 /* Array of basic blocks. */
175 block_t *blocks;
176 unsigned num_blocks;
177 unsigned blocks_executed;
178
179 /* Raw arc coverage counts. */
180 gcov_type *counts;
181 unsigned num_counts;
182
183 /* First line number. */
184 unsigned line;
185 struct source_info *src;
186
187 /* Next function in same source file. */
188 struct function_info *line_next;
189
190 /* Next function. */
191 struct function_info *next;
192 } function_t;
193
194 /* Describes coverage of a file or function. */
195
196 typedef struct coverage_info
197 {
198 int lines;
199 int lines_executed;
200
201 int branches;
202 int branches_executed;
203 int branches_taken;
204
205 int calls;
206 int calls_executed;
207
208 char *name;
209 } coverage_t;
210
211 /* Describes a single line of source. Contains a chain of basic blocks
212 with code on it. */
213
214 typedef struct line_info
215 {
216 gcov_type count; /* execution count */
217 union
218 {
219 arc_t *branches; /* branches from blocks that end on this
220 line. Used for branch-counts when not
221 all-blocks mode. */
222 block_t *blocks; /* blocks which start on this line. Used
223 in all-blocks mode. */
224 } u;
225 unsigned exists : 1;
226 } line_t;
227
228 /* Describes a file mentioned in the block graph. Contains an array
229 of line info. */
230
231 typedef struct source_info
232 {
233 /* Name of source file. */
234 char *name;
235 unsigned index;
236
237 /* Array of line information. */
238 line_t *lines;
239 unsigned num_lines;
240
241 coverage_t coverage;
242
243 /* Functions in this source file. These are in ascending line
244 number order. */
245 function_t *functions;
246
247 /* Next source file. */
248 struct source_info *next;
249 } source_t;
250
251 /* Holds a list of function basic block graphs. */
252
253 static function_t *functions;
254
255 /* This points to the head of the sourcefile structure list. */
256
257 static source_t *sources;
258
259 /* This holds data summary information. */
260
261 static struct gcov_summary object_summary;
262 static unsigned program_count;
263
264 /* Modification time of graph file. */
265
266 static time_t bbg_file_time;
267
268 /* Name and file pointer of the input file for the basic block graph. */
269
270 static char *bbg_file_name;
271
272 /* Stamp of the bbg file */
273 static unsigned bbg_stamp;
274
275 /* Name and file pointer of the input file for the arc count data. */
276
277 static char *da_file_name;
278
279 /* Output branch probabilities. */
280
281 static int flag_branches = 0;
282
283 /* Show unconditional branches too. */
284 static int flag_unconditional = 0;
285
286 /* Output a gcov file if this is true. This is on by default, and can
287 be turned off by the -n option. */
288
289 static int flag_gcov_file = 1;
290
291 /* For included files, make the gcov output file name include the name
292 of the input source file. For example, if x.h is included in a.c,
293 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
294
295 static int flag_long_names = 0;
296
297 /* Output count information for every basic block, not merely those
298 that contain line number information. */
299
300 static int flag_all_blocks = 0;
301
302 /* Output summary info for each function. */
303
304 static int flag_function_summary = 0;
305
306 /* Object directory file prefix. This is the directory/file where the
307 graph and data files are looked for, if nonzero. */
308
309 static char *object_directory = 0;
310
311 /* Preserve all pathname components. Needed when object files and
312 source files are in subdirectories. '/' is mangled as '#', '.' is
313 elided and '..' mangled to '^'. */
314
315 static int flag_preserve_paths = 0;
316
317 /* Output the number of times a branch was taken as opposed to the percentage
318 of times it was taken. */
319
320 static int flag_counts = 0;
321
322 /* Forward declarations. */
323 static void fnotice (FILE *, const char *, ...) ATTRIBUTE_PRINTF_2;
324 static int process_args (int, char **);
325 static void print_usage (int) ATTRIBUTE_NORETURN;
326 static void print_version (void) ATTRIBUTE_NORETURN;
327 static void process_file (const char *);
328 static void create_file_names (const char *);
329 static source_t *find_source (const char *);
330 static int read_graph_file (void);
331 static int read_count_file (void);
332 static void solve_flow_graph (function_t *);
333 static void add_branch_counts (coverage_t *, const arc_t *);
334 static void add_line_counts (coverage_t *, function_t *);
335 static void function_summary (const coverage_t *, const char *);
336 static const char *format_gcov (gcov_type, gcov_type, int);
337 static void accumulate_line_counts (source_t *);
338 static int output_branch_count (FILE *, int, const arc_t *);
339 static void output_lines (FILE *, const source_t *);
340 static char *make_gcov_file_name (const char *, const char *);
341 static void release_structures (void);
342 extern int main (int, char **);
343
344 int
345 main (int argc, char **argv)
346 {
347 int argno;
348
349 gcc_init_libintl ();
350
351 argno = process_args (argc, argv);
352 if (optind == argc)
353 print_usage (true);
354
355 for (; argno != argc; argno++)
356 {
357 release_structures ();
358
359 process_file (argv[argno]);
360 }
361
362 return 0;
363 }
364
365 static void
366 fnotice (FILE *file, const char *msgid, ...)
367 {
368 va_list ap;
369
370 va_start (ap, msgid);
371 vfprintf (file, _(msgid), ap);
372 va_end (ap);
373 }
374
375 /* More 'friendly' abort that prints the line and file.
376 config.h can #define abort fancy_abort if you like that sort of thing. */
377 extern void fancy_abort (void) ATTRIBUTE_NORETURN;
378
379 void
380 fancy_abort (void)
381 {
382 fnotice (stderr, "Internal gcov abort.\n");
383 exit (FATAL_EXIT_CODE);
384 }
385 \f
386 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
387 otherwise the output of --help. */
388
389 static void
390 print_usage (int error_p)
391 {
392 FILE *file = error_p ? stderr : stdout;
393 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
394
395 fnotice (file, "Usage: gcov [OPTION]... SOURCEFILE\n\n");
396 fnotice (file, "Print code coverage information.\n\n");
397 fnotice (file, " -h, --help Print this help, then exit\n");
398 fnotice (file, " -v, --version Print version number, then exit\n");
399 fnotice (file, " -a, --all-blocks Show information for every basic block\n");
400 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
401 fnotice (file, " -c, --branch-counts Given counts of branches taken\n\
402 rather than percentages\n");
403 fnotice (file, " -n, --no-output Do not create an output file\n");
404 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
405 source files\n");
406 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
407 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
408 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
409 fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
410 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
411 bug_report_url);
412 exit (status);
413 }
414
415 /* Print version information and exit. */
416
417 static void
418 print_version (void)
419 {
420 fnotice (stdout, "gcov (GCC) %s\n", version_string);
421 fnotice (stdout, "Copyright (C) 2003 Free Software Foundation, Inc.\n");
422 fnotice (stdout,
423 "This is free software; see the source for copying conditions.\n"
424 "There is NO warranty; not even for MERCHANTABILITY or \n"
425 "FITNESS FOR A PARTICULAR PURPOSE.\n\n");
426 exit (SUCCESS_EXIT_CODE);
427 }
428
429 static const struct option options[] =
430 {
431 { "help", no_argument, NULL, 'h' },
432 { "version", no_argument, NULL, 'v' },
433 { "all-blocks", no_argument, NULL, 'a' },
434 { "branch-probabilities", no_argument, NULL, 'b' },
435 { "branch-counts", no_argument, NULL, 'c' },
436 { "no-output", no_argument, NULL, 'n' },
437 { "long-file-names", no_argument, NULL, 'l' },
438 { "function-summaries", no_argument, NULL, 'f' },
439 { "preserve-paths", no_argument, NULL, 'p' },
440 { "object-directory", required_argument, NULL, 'o' },
441 { "object-file", required_argument, NULL, 'o' },
442 { "unconditional-branches", no_argument, NULL, 'u' },
443 { 0, 0, 0, 0 }
444 };
445
446 /* Process args, return index to first non-arg. */
447
448 static int
449 process_args (int argc, char **argv)
450 {
451 int opt;
452
453 while ((opt = getopt_long (argc, argv, "abcfhlno:puv", options, NULL)) != -1)
454 {
455 switch (opt)
456 {
457 case 'a':
458 flag_all_blocks = 1;
459 break;
460 case 'b':
461 flag_branches = 1;
462 break;
463 case 'c':
464 flag_counts = 1;
465 break;
466 case 'f':
467 flag_function_summary = 1;
468 break;
469 case 'h':
470 print_usage (false);
471 /* print_usage will exit. */
472 case 'l':
473 flag_long_names = 1;
474 break;
475 case 'n':
476 flag_gcov_file = 0;
477 break;
478 case 'o':
479 object_directory = optarg;
480 break;
481 case 'p':
482 flag_preserve_paths = 1;
483 break;
484 case 'u':
485 flag_unconditional = 1;
486 break;
487 case 'v':
488 print_version ();
489 /* print_version will exit. */
490 default:
491 print_usage (true);
492 /* print_usage will exit. */
493 }
494 }
495
496 return optind;
497 }
498
499 /* Process a single source file. */
500
501 static void
502 process_file (const char *file_name)
503 {
504 source_t *src;
505 function_t *fn;
506
507 create_file_names (file_name);
508 if (read_graph_file ())
509 return;
510
511 if (!functions)
512 {
513 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
514 return;
515 }
516
517 if (read_count_file ())
518 return;
519
520 for (fn = functions; fn; fn = fn->next)
521 solve_flow_graph (fn);
522 for (src = sources; src; src = src->next)
523 src->lines = (line_t *) xcalloc (src->num_lines, sizeof (line_t));
524 for (fn = functions; fn; fn = fn->next)
525 {
526 coverage_t coverage;
527
528 memset (&coverage, 0, sizeof (coverage));
529 coverage.name = fn->name;
530 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
531 if (flag_function_summary)
532 {
533 function_summary (&coverage, "Function");
534 fnotice (stdout, "\n");
535 }
536 }
537
538 for (src = sources; src; src = src->next)
539 {
540 accumulate_line_counts (src);
541 function_summary (&src->coverage, "File");
542 if (flag_gcov_file)
543 {
544 char *gcov_file_name = make_gcov_file_name (file_name, src->name);
545 FILE *gcov_file = fopen (gcov_file_name, "w");
546
547 if (gcov_file)
548 {
549 fnotice (stdout, "%s:creating `%s'\n",
550 src->name, gcov_file_name);
551 output_lines (gcov_file, src);
552 if (ferror (gcov_file))
553 fnotice (stderr, "%s:error writing output file `%s'\n",
554 src->name, gcov_file_name);
555 fclose (gcov_file);
556 }
557 else
558 fnotice (stderr, "%s:could not open output file `%s'\n",
559 src->name, gcov_file_name);
560 free (gcov_file_name);
561 }
562 fnotice (stdout, "\n");
563 }
564 }
565
566 /* Release all memory used. */
567
568 static void
569 release_structures (void)
570 {
571 function_t *fn;
572 source_t *src;
573
574 free (bbg_file_name);
575 free (da_file_name);
576 da_file_name = bbg_file_name = NULL;
577 bbg_file_time = 0;
578 bbg_stamp = 0;
579
580 while ((src = sources))
581 {
582 sources = src->next;
583
584 free (src->name);
585 free (src->lines);
586 }
587
588 while ((fn = functions))
589 {
590 unsigned ix;
591 block_t *block;
592
593 functions = fn->next;
594 for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
595 {
596 arc_t *arc, *arc_n;
597
598 for (arc = block->succ; arc; arc = arc_n)
599 {
600 arc_n = arc->succ_next;
601 free (arc);
602 }
603 }
604 free (fn->blocks);
605 free (fn->counts);
606 }
607 }
608
609 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
610 is not specified, these are looked for in the current directory,
611 and named from the basename of the FILE_NAME sans extension. If
612 OBJECT_DIRECTORY is specified and is a directory, the files are in
613 that directory, but named from the basename of the FILE_NAME, sans
614 extension. Otherwise OBJECT_DIRECTORY is taken to be the name of
615 the object *file*, and the data files are named from that. */
616
617 static void
618 create_file_names (const char *file_name)
619 {
620 char *cptr;
621 char *name;
622 int length = strlen (file_name);
623 int base;
624
625 if (object_directory && object_directory[0])
626 {
627 struct stat status;
628
629 length += strlen (object_directory) + 2;
630 name = xmalloc (length);
631 name[0] = 0;
632
633 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
634 strcat (name, object_directory);
635 if (base && name[strlen (name) - 1] != '/')
636 strcat (name, "/");
637 }
638 else
639 {
640 name = xmalloc (length + 1);
641 name[0] = 0;
642 base = 1;
643 }
644
645 if (base)
646 {
647 /* Append source file name. */
648 cptr = strrchr (file_name, '/');
649 strcat (name, cptr ? cptr + 1 : file_name);
650 }
651
652 /* Remove the extension. */
653 cptr = strrchr (name, '.');
654 if (cptr)
655 *cptr = 0;
656
657 length = strlen (name);
658
659 bbg_file_name = xmalloc (length + strlen (GCOV_NOTE_SUFFIX) + 1);
660 strcpy (bbg_file_name, name);
661 strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
662
663 da_file_name = xmalloc (length + strlen (GCOV_DATA_SUFFIX) + 1);
664 strcpy (da_file_name, name);
665 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
666
667 return;
668 }
669
670 /* Find or create a source file structure for FILE_NAME. Copies
671 FILE_NAME on creation */
672
673 static source_t *
674 find_source (const char *file_name)
675 {
676 source_t *src;
677
678 if (!file_name)
679 file_name = "<unknown>";
680
681 for (src = sources; src; src = src->next)
682 if (!strcmp (file_name, src->name))
683 return src;
684
685 src = (source_t *)xcalloc (1, sizeof (source_t));
686 src->name = xstrdup (file_name);
687 src->coverage.name = src->name;
688 src->index = sources ? sources->index + 1 : 1;
689 src->next = sources;
690 sources = src;
691
692 return src;
693 }
694
695 /* Read the graph file. Return nonzero on fatal error. */
696
697 static int
698 read_graph_file (void)
699 {
700 unsigned version;
701 unsigned current_tag = 0;
702 struct function_info *fn = NULL;
703 source_t *src = NULL;
704 unsigned ix;
705 unsigned tag;
706
707 if (!gcov_open (bbg_file_name, 1))
708 {
709 fnotice (stderr, "%s:cannot open graph file\n", bbg_file_name);
710 return 1;
711 }
712 bbg_file_time = gcov_time ();
713 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
714 {
715 fnotice (stderr, "%s:not a gcov graph file\n", bbg_file_name);
716 gcov_close ();
717 return 1;
718 }
719
720 version = gcov_read_unsigned ();
721 if (version != GCOV_VERSION)
722 {
723 char v[4], e[4];
724
725 GCOV_UNSIGNED2STRING (v, version);
726 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
727
728 fnotice (stderr, "%s:version `%.4s', prefer `%.4s'\n",
729 bbg_file_name, v, e);
730 }
731 bbg_stamp = gcov_read_unsigned ();
732
733 while ((tag = gcov_read_unsigned ()))
734 {
735 unsigned length = gcov_read_unsigned ();
736 gcov_position_t base = gcov_position ();
737
738 if (tag == GCOV_TAG_FUNCTION)
739 {
740 char *function_name;
741 unsigned ident, checksum, lineno;
742 source_t *src;
743 function_t *probe, *prev;
744
745 ident = gcov_read_unsigned ();
746 checksum = gcov_read_unsigned ();
747 function_name = xstrdup (gcov_read_string ());
748 src = find_source (gcov_read_string ());
749 lineno = gcov_read_unsigned ();
750
751 fn = (function_t *)xcalloc (1, sizeof (function_t));
752 fn->name = function_name;
753 fn->ident = ident;
754 fn->checksum = checksum;
755 fn->src = src;
756 fn->line = lineno;
757
758 fn->next = functions;
759 functions = fn;
760 current_tag = tag;
761
762 if (lineno >= src->num_lines)
763 src->num_lines = lineno + 1;
764 /* Now insert it into the source file's list of
765 functions. Normally functions will be encountered in
766 ascending order, so a simple scan is quick. */
767 for (probe = src->functions, prev = NULL;
768 probe && probe->line > lineno;
769 prev = probe, probe = probe->line_next)
770 continue;
771 fn->line_next = probe;
772 if (prev)
773 prev->line_next = fn;
774 else
775 src->functions = fn;
776 }
777 else if (fn && tag == GCOV_TAG_BLOCKS)
778 {
779 if (fn->blocks)
780 fnotice (stderr, "%s:already seen blocks for `%s'\n",
781 bbg_file_name, fn->name);
782 else
783 {
784 unsigned ix, num_blocks = GCOV_TAG_BLOCKS_NUM (length);
785 fn->num_blocks = num_blocks;
786
787 fn->blocks
788 = (block_t *)xcalloc (fn->num_blocks, sizeof (block_t));
789 for (ix = 0; ix != num_blocks; ix++)
790 fn->blocks[ix].flags = gcov_read_unsigned ();
791 }
792 }
793 else if (fn && tag == GCOV_TAG_ARCS)
794 {
795 unsigned src = gcov_read_unsigned ();
796 unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
797
798 if (src >= fn->num_blocks || fn->blocks[src].succ)
799 goto corrupt;
800
801 while (num_dests--)
802 {
803 struct arc_info *arc;
804 unsigned dest = gcov_read_unsigned ();
805 unsigned flags = gcov_read_unsigned ();
806
807 if (dest >= fn->num_blocks)
808 goto corrupt;
809 arc = (arc_t *) xcalloc (1, sizeof (arc_t));
810
811 arc->dst = &fn->blocks[dest];
812 arc->src = &fn->blocks[src];
813
814 arc->count = 0;
815 arc->count_valid = 0;
816 arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
817 arc->fake = !!(flags & GCOV_ARC_FAKE);
818 arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
819
820 arc->succ_next = fn->blocks[src].succ;
821 fn->blocks[src].succ = arc;
822 fn->blocks[src].num_succ++;
823
824 arc->pred_next = fn->blocks[dest].pred;
825 fn->blocks[dest].pred = arc;
826 fn->blocks[dest].num_pred++;
827
828 if (arc->fake)
829 {
830 if (src)
831 {
832 /* Exceptional exit from this function, the
833 source block must be a call. */
834 fn->blocks[src].is_call_site = 1;
835 arc->is_call_non_return = 1;
836 }
837 else
838 {
839 /* Non-local return from a callee of this
840 function. The destination block is a catch or
841 setjmp. */
842 arc->is_nonlocal_return = 1;
843 fn->blocks[dest].is_nonlocal_return = 1;
844 }
845 }
846
847 if (!arc->on_tree)
848 fn->num_counts++;
849 }
850 }
851 else if (fn && tag == GCOV_TAG_LINES)
852 {
853 unsigned blockno = gcov_read_unsigned ();
854 unsigned *line_nos
855 = (unsigned *)xcalloc (length - 1, sizeof (unsigned));
856
857 if (blockno >= fn->num_blocks || fn->blocks[blockno].u.line.encoding)
858 goto corrupt;
859
860 for (ix = 0; ; )
861 {
862 unsigned lineno = gcov_read_unsigned ();
863
864 if (lineno)
865 {
866 if (!ix)
867 {
868 line_nos[ix++] = 0;
869 line_nos[ix++] = src->index;
870 }
871 line_nos[ix++] = lineno;
872 if (lineno >= src->num_lines)
873 src->num_lines = lineno + 1;
874 }
875 else
876 {
877 const char *file_name = gcov_read_string ();
878
879 if (!file_name)
880 break;
881 src = find_source (file_name);
882
883 line_nos[ix++] = 0;
884 line_nos[ix++] = src->index;
885 }
886 }
887
888 fn->blocks[blockno].u.line.encoding = line_nos;
889 fn->blocks[blockno].u.line.num = ix;
890 }
891 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
892 {
893 fn = NULL;
894 current_tag = 0;
895 }
896 gcov_sync (base, length);
897 if (gcov_is_error ())
898 break;
899 }
900 if (!gcov_is_eof ())
901 {
902 corrupt:;
903 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
904 gcov_close ();
905 return 1;
906 }
907 gcov_close ();
908
909 /* We built everything backwards, so nreverse them all */
910
911 /* Reverse sources. Not strictly necessary, but we'll then process
912 them in the 'expected' order. */
913 {
914 source_t *src, *src_p, *src_n;
915
916 for (src_p = NULL, src = sources; src; src_p = src, src = src_n)
917 {
918 src_n = src->next;
919 src->next = src_p;
920 }
921 sources = src_p;
922 }
923
924 /* Reverse functions. */
925 {
926 function_t *fn, *fn_p, *fn_n;
927
928 for (fn_p = NULL, fn = functions; fn; fn_p = fn, fn = fn_n)
929 {
930 unsigned ix;
931
932 fn_n = fn->next;
933 fn->next = fn_p;
934
935 /* Reverse the arcs. */
936 for (ix = fn->num_blocks; ix--;)
937 {
938 arc_t *arc, *arc_p, *arc_n;
939
940 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
941 arc_p = arc, arc = arc_n)
942 {
943 arc_n = arc->succ_next;
944 arc->succ_next = arc_p;
945 }
946 fn->blocks[ix].succ = arc_p;
947
948 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
949 arc_p = arc, arc = arc_n)
950 {
951 arc_n = arc->pred_next;
952 arc->pred_next = arc_p;
953 }
954 fn->blocks[ix].pred = arc_p;
955 }
956 }
957 functions = fn_p;
958 }
959 return 0;
960 }
961
962 /* Reads profiles from the count file and attach to each
963 function. Return nonzero if fatal error. */
964
965 static int
966 read_count_file (void)
967 {
968 unsigned ix;
969 unsigned version;
970 unsigned tag;
971 function_t *fn = NULL;
972 int error = 0;
973
974 if (!gcov_open (da_file_name, 1))
975 {
976 fnotice (stderr, "%s:cannot open data file\n", da_file_name);
977 return 1;
978 }
979 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
980 {
981 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
982 cleanup:;
983 gcov_close ();
984 return 1;
985 }
986 version = gcov_read_unsigned ();
987 if (version != GCOV_VERSION)
988 {
989 char v[4], e[4];
990
991 GCOV_UNSIGNED2STRING (v, version);
992 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
993
994 fnotice (stderr, "%s:version `%.4s', prefer version `%.4s'\n",
995 da_file_name, v, e);
996 }
997 tag = gcov_read_unsigned ();
998 if (tag != bbg_stamp)
999 {
1000 fnotice (stderr, "%s:stamp mismatch with graph file\n", da_file_name);
1001 goto cleanup;
1002 }
1003
1004 while ((tag = gcov_read_unsigned ()))
1005 {
1006 unsigned length = gcov_read_unsigned ();
1007 unsigned long base = gcov_position ();
1008
1009 if (tag == GCOV_TAG_OBJECT_SUMMARY)
1010 gcov_read_summary (&object_summary);
1011 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
1012 program_count++;
1013 else if (tag == GCOV_TAG_FUNCTION)
1014 {
1015 unsigned ident = gcov_read_unsigned ();
1016 struct function_info *fn_n = functions;
1017
1018 for (fn = fn ? fn->next : NULL; ; fn = fn->next)
1019 {
1020 if (fn)
1021 ;
1022 else if ((fn = fn_n))
1023 fn_n = NULL;
1024 else
1025 {
1026 fnotice (stderr, "%s:unknown function `%u'\n",
1027 da_file_name, ident);
1028 break;
1029 }
1030 if (fn->ident == ident)
1031 break;
1032 }
1033
1034 if (!fn)
1035 ;
1036 else if (gcov_read_unsigned () != fn->checksum)
1037 {
1038 mismatch:;
1039 fnotice (stderr, "%s:profile mismatch for `%s'\n",
1040 da_file_name, fn->name);
1041 goto cleanup;
1042 }
1043 }
1044 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
1045 {
1046 if (length != GCOV_TAG_COUNTER_LENGTH (fn->num_counts))
1047 goto mismatch;
1048
1049 if (!fn->counts)
1050 fn->counts
1051 = (gcov_type *)xcalloc (fn->num_counts, sizeof (gcov_type));
1052
1053 for (ix = 0; ix != fn->num_counts; ix++)
1054 fn->counts[ix] += gcov_read_counter ();
1055 }
1056 gcov_sync (base, length);
1057 if ((error = gcov_is_error ()))
1058 break;
1059 }
1060
1061 if (!gcov_is_eof ())
1062 {
1063 fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1064 da_file_name);
1065 goto cleanup;
1066 }
1067
1068 gcov_close ();
1069 return 0;
1070 }
1071
1072 /* Solve the flow graph. Propagate counts from the instrumented arcs
1073 to the blocks and the uninstrumented arcs. */
1074
1075 static void
1076 solve_flow_graph (function_t *fn)
1077 {
1078 unsigned ix;
1079 arc_t *arc;
1080 gcov_type *count_ptr = fn->counts;
1081 block_t *blk;
1082 block_t *valid_blocks = NULL; /* valid, but unpropagated blocks. */
1083 block_t *invalid_blocks = NULL; /* invalid, but inferable blocks. */
1084
1085 if (fn->num_blocks < 2)
1086 fnotice (stderr, "%s:`%s' lacks entry and/or exit blocks\n",
1087 bbg_file_name, fn->name);
1088 else
1089 {
1090 if (fn->blocks[0].num_pred)
1091 fnotice (stderr, "%s:`%s' has arcs to entry block\n",
1092 bbg_file_name, fn->name);
1093 else
1094 /* We can't deduce the entry block counts from the lack of
1095 predecessors. */
1096 fn->blocks[0].num_pred = ~(unsigned)0;
1097
1098 if (fn->blocks[fn->num_blocks - 1].num_succ)
1099 fnotice (stderr, "%s:`%s' has arcs from exit block\n",
1100 bbg_file_name, fn->name);
1101 else
1102 /* Likewise, we can't deduce exit block counts from the lack
1103 of its successors. */
1104 fn->blocks[fn->num_blocks - 1].num_succ = ~(unsigned)0;
1105 }
1106
1107 /* Propagate the measured counts, this must be done in the same
1108 order as the code in profile.c */
1109 for (ix = 0, blk = fn->blocks; ix != fn->num_blocks; ix++, blk++)
1110 {
1111 block_t const *prev_dst = NULL;
1112 int out_of_order = 0;
1113 int non_fake_succ = 0;
1114
1115 for (arc = blk->succ; arc; arc = arc->succ_next)
1116 {
1117 if (!arc->fake)
1118 non_fake_succ++;
1119
1120 if (!arc->on_tree)
1121 {
1122 if (count_ptr)
1123 arc->count = *count_ptr++;
1124 arc->count_valid = 1;
1125 blk->num_succ--;
1126 arc->dst->num_pred--;
1127 }
1128 if (prev_dst && prev_dst > arc->dst)
1129 out_of_order = 1;
1130 prev_dst = arc->dst;
1131 }
1132 if (non_fake_succ == 1)
1133 {
1134 /* If there is only one non-fake exit, it is an
1135 unconditional branch. */
1136 for (arc = blk->succ; arc; arc = arc->succ_next)
1137 if (!arc->fake)
1138 {
1139 arc->is_unconditional = 1;
1140 /* If this block is instrumenting a call, it might be
1141 an artificial block. It is not artificial if it has
1142 a non-fallthrough exit, or the destination of this
1143 arc has more than one entry. Mark the destination
1144 block as a return site, if none of those conditions
1145 hold. */
1146 if (blk->is_call_site && arc->fall_through
1147 && arc->dst->pred == arc && !arc->pred_next)
1148 arc->dst->is_call_return = 1;
1149 }
1150 }
1151
1152 /* Sort the successor arcs into ascending dst order. profile.c
1153 normally produces arcs in the right order, but sometimes with
1154 one or two out of order. We're not using a particularly
1155 smart sort. */
1156 if (out_of_order)
1157 {
1158 arc_t *start = blk->succ;
1159 unsigned changes = 1;
1160
1161 while (changes)
1162 {
1163 arc_t *arc, *arc_p, *arc_n;
1164
1165 changes = 0;
1166 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1167 {
1168 if (arc->dst > arc_n->dst)
1169 {
1170 changes = 1;
1171 if (arc_p)
1172 arc_p->succ_next = arc_n;
1173 else
1174 start = arc_n;
1175 arc->succ_next = arc_n->succ_next;
1176 arc_n->succ_next = arc;
1177 arc_p = arc_n;
1178 }
1179 else
1180 {
1181 arc_p = arc;
1182 arc = arc_n;
1183 }
1184 }
1185 }
1186 blk->succ = start;
1187 }
1188
1189 /* Place it on the invalid chain, it will be ignored if that's
1190 wrong. */
1191 blk->invalid_chain = 1;
1192 blk->chain = invalid_blocks;
1193 invalid_blocks = blk;
1194 }
1195
1196 while (invalid_blocks || valid_blocks)
1197 {
1198 while ((blk = invalid_blocks))
1199 {
1200 gcov_type total = 0;
1201 const arc_t *arc;
1202
1203 invalid_blocks = blk->chain;
1204 blk->invalid_chain = 0;
1205 if (!blk->num_succ)
1206 for (arc = blk->succ; arc; arc = arc->succ_next)
1207 total += arc->count;
1208 else if (!blk->num_pred)
1209 for (arc = blk->pred; arc; arc = arc->pred_next)
1210 total += arc->count;
1211 else
1212 continue;
1213
1214 blk->count = total;
1215 blk->count_valid = 1;
1216 blk->chain = valid_blocks;
1217 blk->valid_chain = 1;
1218 valid_blocks = blk;
1219 }
1220 while ((blk = valid_blocks))
1221 {
1222 gcov_type total;
1223 arc_t *arc, *inv_arc;
1224
1225 valid_blocks = blk->chain;
1226 blk->valid_chain = 0;
1227 if (blk->num_succ == 1)
1228 {
1229 block_t *dst;
1230
1231 total = blk->count;
1232 inv_arc = NULL;
1233 for (arc = blk->succ; arc; arc = arc->succ_next)
1234 {
1235 total -= arc->count;
1236 if (!arc->count_valid)
1237 inv_arc = arc;
1238 }
1239 dst = inv_arc->dst;
1240 inv_arc->count_valid = 1;
1241 inv_arc->count = total;
1242 blk->num_succ--;
1243 dst->num_pred--;
1244 if (dst->count_valid)
1245 {
1246 if (dst->num_pred == 1 && !dst->valid_chain)
1247 {
1248 dst->chain = valid_blocks;
1249 dst->valid_chain = 1;
1250 valid_blocks = dst;
1251 }
1252 }
1253 else
1254 {
1255 if (!dst->num_pred && !dst->invalid_chain)
1256 {
1257 dst->chain = invalid_blocks;
1258 dst->invalid_chain = 1;
1259 invalid_blocks = dst;
1260 }
1261 }
1262 }
1263 if (blk->num_pred == 1)
1264 {
1265 block_t *src;
1266
1267 total = blk->count;
1268 inv_arc = NULL;
1269 for (arc = blk->pred; arc; arc = arc->pred_next)
1270 {
1271 total -= arc->count;
1272 if (!arc->count_valid)
1273 inv_arc = arc;
1274 }
1275 src = inv_arc->src;
1276 inv_arc->count_valid = 1;
1277 inv_arc->count = total;
1278 blk->num_pred--;
1279 src->num_succ--;
1280 if (src->count_valid)
1281 {
1282 if (src->num_succ == 1 && !src->valid_chain)
1283 {
1284 src->chain = valid_blocks;
1285 src->valid_chain = 1;
1286 valid_blocks = src;
1287 }
1288 }
1289 else
1290 {
1291 if (!src->num_succ && !src->invalid_chain)
1292 {
1293 src->chain = invalid_blocks;
1294 src->invalid_chain = 1;
1295 invalid_blocks = src;
1296 }
1297 }
1298 }
1299 }
1300 }
1301
1302 /* If the graph has been correctly solved, every block will have a
1303 valid count. */
1304 for (ix = 0; ix < fn->num_blocks; ix++)
1305 if (!fn->blocks[ix].count_valid)
1306 {
1307 fnotice (stderr, "%s:graph is unsolvable for `%s'\n",
1308 bbg_file_name, fn->name);
1309 break;
1310 }
1311 }
1312
1313 \f
1314
1315 /* Increment totals in COVERAGE according to arc ARC. */
1316
1317 static void
1318 add_branch_counts (coverage_t *coverage, const arc_t *arc)
1319 {
1320 if (arc->is_call_non_return)
1321 {
1322 coverage->calls++;
1323 if (arc->src->count)
1324 coverage->calls_executed++;
1325 }
1326 else if (!arc->is_unconditional)
1327 {
1328 coverage->branches++;
1329 if (arc->src->count)
1330 coverage->branches_executed++;
1331 if (arc->count)
1332 coverage->branches_taken++;
1333 }
1334 }
1335
1336 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1337 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1338 If DP is zero, no decimal point is printed. Only print 100% when
1339 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1340 format TOP. Return pointer to a static string. */
1341
1342 static char const *
1343 format_gcov (gcov_type top, gcov_type bottom, int dp)
1344 {
1345 static char buffer[20];
1346
1347 if (dp >= 0)
1348 {
1349 float ratio = bottom ? (float)top / bottom : 0;
1350 int ix;
1351 unsigned limit = 100;
1352 unsigned percent;
1353
1354 for (ix = dp; ix--; )
1355 limit *= 10;
1356
1357 percent = (unsigned) (ratio * limit + (float)0.5);
1358 if (percent <= 0 && top)
1359 percent = 1;
1360 else if (percent >= limit && top != bottom)
1361 percent = limit - 1;
1362 ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1363 if (dp)
1364 {
1365 dp++;
1366 do
1367 {
1368 buffer[ix+1] = buffer[ix];
1369 ix--;
1370 }
1371 while (dp--);
1372 buffer[ix + 1] = '.';
1373 }
1374 }
1375 else
1376 sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)top);
1377
1378 return buffer;
1379 }
1380
1381
1382 /* Output summary info for a function. */
1383
1384 static void
1385 function_summary (const coverage_t *coverage, const char *title)
1386 {
1387 fnotice (stdout, "%s `%s'\n", title, coverage->name);
1388
1389 if (coverage->lines)
1390 fnotice (stdout, "Lines executed:%s of %d\n",
1391 format_gcov (coverage->lines_executed, coverage->lines, 2),
1392 coverage->lines);
1393 else
1394 fnotice (stdout, "No executable lines");
1395
1396 if (flag_branches)
1397 {
1398 if (coverage->branches)
1399 {
1400 fnotice (stdout, "Branches executed:%s of %d\n",
1401 format_gcov (coverage->branches_executed,
1402 coverage->branches, 2),
1403 coverage->branches);
1404 fnotice (stdout, "Taken at least once:%s of %d\n",
1405 format_gcov (coverage->branches_taken,
1406 coverage->branches, 2),
1407 coverage->branches);
1408 }
1409 else
1410 fnotice (stdout, "No branches\n");
1411 if (coverage->calls)
1412 fnotice (stdout, "Calls executed:%s of %d\n",
1413 format_gcov (coverage->calls_executed, coverage->calls, 2),
1414 coverage->calls);
1415 else
1416 fnotice (stdout, "No calls\n");
1417 }
1418 }
1419
1420 /* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
1421 affect name generation. With preserve_paths we create a filename
1422 from all path components of the source file, replacing '/' with
1423 '#', without it we simply take the basename component. With
1424 long_output_names we prepend the processed name of the input file
1425 to each output name (except when the current source file is the
1426 input file, so you don't get a double concatenation). The two
1427 components are separated by '##'. Also '.' filename components are
1428 removed and '..' components are renamed to '^'. */
1429
1430 static char *
1431 make_gcov_file_name (const char *input_name, const char *src_name)
1432 {
1433 char *cptr;
1434 char *name = xmalloc (strlen (src_name) + strlen (input_name) + 10);
1435
1436 name[0] = 0;
1437 if (flag_long_names && strcmp (src_name, input_name))
1438 {
1439 /* Generate the input filename part. */
1440 cptr = flag_preserve_paths ? NULL : strrchr (input_name, '/');
1441 strcat (name, cptr ? cptr + 1 : input_name);
1442 strcat (name, "##");
1443 }
1444
1445 /* Generate the source filename part. */
1446 cptr = flag_preserve_paths ? NULL : strrchr (src_name, '/');
1447 strcat (name, cptr ? cptr + 1 : src_name);
1448
1449 if (flag_preserve_paths)
1450 {
1451 /* Convert '/' to '#', remove '/./', convert '/../' to '/^/' */
1452 char *prev;
1453
1454 for (cptr = name; (cptr = strchr ((prev = cptr), '/'));)
1455 {
1456 unsigned shift = 0;
1457
1458 if (prev + 1 == cptr && prev[0] == '.')
1459 {
1460 /* Remove '.' */
1461 shift = 2;
1462 }
1463 else if (prev + 2 == cptr && prev[0] == '.' && prev[1] == '.')
1464 {
1465 /* Convert '..' */
1466 shift = 1;
1467 prev[1] = '^';
1468 }
1469 else
1470 *cptr++ = '#';
1471 if (shift)
1472 {
1473 cptr = prev;
1474 do
1475 prev[0] = prev[shift];
1476 while (*prev++);
1477 }
1478 }
1479 }
1480
1481 strcat (name, ".gcov");
1482 return name;
1483 }
1484
1485 /* Scan through the bb_data for each line in the block, increment
1486 the line number execution count indicated by the execution count of
1487 the appropriate basic block. */
1488
1489 static void
1490 add_line_counts (coverage_t *coverage, function_t *fn)
1491 {
1492 unsigned ix;
1493 line_t *line = NULL; /* this is propagated from one iteration to the
1494 next. */
1495
1496 /* Scan each basic block. */
1497 for (ix = 0; ix != fn->num_blocks; ix++)
1498 {
1499 block_t *block = &fn->blocks[ix];
1500 unsigned *encoding;
1501 const source_t *src = NULL;
1502 unsigned jx;
1503
1504 if (block->count && ix && ix + 1 != fn->num_blocks)
1505 fn->blocks_executed++;
1506 for (jx = 0, encoding = block->u.line.encoding;
1507 jx != block->u.line.num; jx++, encoding++)
1508 if (!*encoding)
1509 {
1510 unsigned src_n = *++encoding;
1511
1512 for (src = sources; src->index != src_n; src = src->next)
1513 continue;
1514 jx++;
1515 }
1516 else
1517 {
1518 line = &src->lines[*encoding];
1519
1520 if (coverage)
1521 {
1522 if (!line->exists)
1523 coverage->lines++;
1524 if (!line->count && block->count)
1525 coverage->lines_executed++;
1526 }
1527 line->exists = 1;
1528 line->count += block->count;
1529 }
1530 free (block->u.line.encoding);
1531 block->u.cycle.arc = NULL;
1532 block->u.cycle.ident = ~0U;
1533
1534 if (!ix || ix + 1 == fn->num_blocks)
1535 /* Entry or exit block */;
1536 else if (flag_all_blocks)
1537 {
1538 line_t *block_line = line ? line : &fn->src->lines[fn->line];
1539
1540 block->chain = block_line->u.blocks;
1541 block_line->u.blocks = block;
1542 }
1543 else if (flag_branches)
1544 {
1545 arc_t *arc;
1546
1547 for (arc = block->succ; arc; arc = arc->succ_next)
1548 {
1549 arc->line_next = line->u.branches;
1550 line->u.branches = arc;
1551 if (coverage && !arc->is_unconditional)
1552 add_branch_counts (coverage, arc);
1553 }
1554 }
1555 }
1556 if (!line)
1557 fnotice (stderr, "%s:no lines for `%s'\n", bbg_file_name, fn->name);
1558 }
1559
1560 /* Accumulate the line counts of a file. */
1561
1562 static void
1563 accumulate_line_counts (source_t *src)
1564 {
1565 line_t *line;
1566 function_t *fn, *fn_p, *fn_n;
1567 unsigned ix;
1568
1569 /* Reverse the function order. */
1570 for (fn = src->functions, fn_p = NULL; fn;
1571 fn_p = fn, fn = fn_n)
1572 {
1573 fn_n = fn->line_next;
1574 fn->line_next = fn_p;
1575 }
1576 src->functions = fn_p;
1577
1578 for (ix = src->num_lines, line = src->lines; ix--; line++)
1579 {
1580 if (!flag_all_blocks)
1581 {
1582 arc_t *arc, *arc_p, *arc_n;
1583
1584 /* Total and reverse the branch information. */
1585 for (arc = line->u.branches, arc_p = NULL; arc;
1586 arc_p = arc, arc = arc_n)
1587 {
1588 arc_n = arc->line_next;
1589 arc->line_next = arc_p;
1590
1591 add_branch_counts (&src->coverage, arc);
1592 }
1593 line->u.branches = arc_p;
1594 }
1595 else if (line->u.blocks)
1596 {
1597 /* The user expects the line count to be the number of times
1598 a line has been executed. Simply summing the block count
1599 will give an artificially high number. The Right Thing
1600 is to sum the entry counts to the graph of blocks on this
1601 line, then find the elementary cycles of the local graph
1602 and add the transition counts of those cycles. */
1603 block_t *block, *block_p, *block_n;
1604 gcov_type count = 0;
1605
1606 /* Reverse the block information. */
1607 for (block = line->u.blocks, block_p = NULL; block;
1608 block_p = block, block = block_n)
1609 {
1610 block_n = block->chain;
1611 block->chain = block_p;
1612 block->u.cycle.ident = ix;
1613 }
1614 line->u.blocks = block_p;
1615
1616 /* Sum the entry arcs. */
1617 for (block = line->u.blocks; block; block = block->chain)
1618 {
1619 arc_t *arc;
1620
1621 for (arc = block->pred; arc; arc = arc->pred_next)
1622 {
1623 if (arc->src->u.cycle.ident != ix)
1624 count += arc->count;
1625 if (flag_branches)
1626 add_branch_counts (&src->coverage, arc);
1627 }
1628 }
1629
1630 /* Find the loops. This uses the algorithm described in
1631 Tiernan 'An Efficient Search Algorithm to Find the
1632 Elementary Circuits of a Graph', CACM Dec 1970. We hold
1633 the P array by having each block point to the arc that
1634 connects to the previous block. The H array is implicitly
1635 held because of the arc ordering, and the block's
1636 previous arc pointer.
1637
1638 Although the algorithm is O(N^3) for highly connected
1639 graphs, at worst we'll have O(N^2), as most blocks have
1640 only one or two exits. Most graphs will be small.
1641
1642 For each loop we find, locate the arc with the smallest
1643 transition count, and add that to the cumulative
1644 count. Remove the arc from consideration. */
1645 for (block = line->u.blocks; block; block = block->chain)
1646 {
1647 block_t *head = block;
1648 arc_t *arc;
1649
1650 next_vertex:;
1651 arc = head->succ;
1652 current_vertex:;
1653 while (arc)
1654 {
1655 block_t *dst = arc->dst;
1656 if (/* Already used that arc. */
1657 arc->cycle
1658 /* Not to same graph, or before first vertex. */
1659 || dst->u.cycle.ident != ix
1660 /* Already in path. */
1661 || dst->u.cycle.arc)
1662 {
1663 arc = arc->succ_next;
1664 continue;
1665 }
1666
1667 if (dst == block)
1668 {
1669 /* Found a closing arc. */
1670 gcov_type cycle_count = arc->count;
1671 arc_t *cycle_arc = arc;
1672 arc_t *probe_arc;
1673
1674 /* Locate the smallest arc count of the loop. */
1675 for (dst = head; (probe_arc = dst->u.cycle.arc);
1676 dst = probe_arc->src)
1677 if (cycle_count > probe_arc->count)
1678 {
1679 cycle_count = probe_arc->count;
1680 cycle_arc = probe_arc;
1681 }
1682
1683 count += cycle_count;
1684 cycle_arc->cycle = 1;
1685 /* Unwind to the cyclic arc. */
1686 while (head != cycle_arc->src)
1687 {
1688 arc = head->u.cycle.arc;
1689 head = arc->src;
1690 }
1691 /* Move on. */
1692 arc = arc->succ_next;
1693 continue;
1694 }
1695
1696 /* Add new block to chain. */
1697 dst->u.cycle.arc = arc;
1698 head = dst;
1699 goto next_vertex;
1700 }
1701 /* We could not add another vertex to the path. Remove
1702 the last vertex from the list. */
1703 arc = head->u.cycle.arc;
1704 if (arc)
1705 {
1706 /* It was not the first vertex. Move onto next arc. */
1707 head->u.cycle.arc = NULL;
1708 head = arc->src;
1709 arc = arc->succ_next;
1710 goto current_vertex;
1711 }
1712 /* Mark this block as unusable. */
1713 block->u.cycle.ident = ~0U;
1714 }
1715
1716 line->count = count;
1717 }
1718
1719 if (line->exists)
1720 {
1721 src->coverage.lines++;
1722 if (line->count)
1723 src->coverage.lines_executed++;
1724 }
1725 }
1726 }
1727
1728 /* Ouput information about ARC number IX. Returns nonzero if
1729 anything is output. */
1730
1731 static int
1732 output_branch_count (FILE *gcov_file, int ix, const arc_t *arc)
1733 {
1734
1735 if (arc->is_call_non_return)
1736 {
1737 if (arc->src->count)
1738 {
1739 fnotice (gcov_file, "call %2d returned %s\n", ix,
1740 format_gcov (arc->src->count - arc->count,
1741 arc->src->count, -flag_counts));
1742 }
1743 else
1744 fnotice (gcov_file, "call %2d never executed\n", ix);
1745 }
1746 else if (!arc->is_unconditional)
1747 {
1748 if (arc->src->count)
1749 fnotice (gcov_file, "branch %2d taken %s%s\n", ix,
1750 format_gcov (arc->count, arc->src->count, -flag_counts),
1751 arc->fall_through ? " (fallthrough)" : "");
1752 else
1753 fnotice (gcov_file, "branch %2d never executed\n", ix);
1754 }
1755 else if (flag_unconditional && !arc->dst->is_call_return)
1756 {
1757 if (arc->src->count)
1758 fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
1759 format_gcov (arc->count, arc->src->count, -flag_counts));
1760 else
1761 fnotice (gcov_file, "unconditional %2d never executed\n", ix);
1762 }
1763 else
1764 return 0;
1765 return 1;
1766
1767 }
1768
1769 /* Read in the source file one line at a time, and output that line to
1770 the gcov file preceded by its execution count and other
1771 information. */
1772
1773 static void
1774 output_lines (FILE *gcov_file, const source_t *src)
1775 {
1776 FILE *source_file;
1777 unsigned line_num; /* current line number. */
1778 const line_t *line; /* current line info ptr. */
1779 char string[STRING_SIZE]; /* line buffer. */
1780 char const *retval = ""; /* status of source file reading. */
1781 function_t *fn = src->functions;
1782
1783 fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->name);
1784 fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
1785 fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0, da_file_name);
1786 fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0,
1787 object_summary.ctrs[GCOV_COUNTER_ARCS].runs);
1788 fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
1789
1790 source_file = fopen (src->name, "r");
1791 if (!source_file)
1792 {
1793 fnotice (stderr, "%s:cannot open source file\n", src->name);
1794 retval = NULL;
1795 }
1796 else
1797 {
1798 struct stat status;
1799
1800 if (!fstat (fileno (source_file), &status)
1801 && status.st_mtime > bbg_file_time)
1802 {
1803 fnotice (stderr, "%s:source file is newer than graph file `%s'\n",
1804 src->name, bbg_file_name);
1805 fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n",
1806 "-", 0);
1807 }
1808 }
1809
1810 for (line_num = 1, line = &src->lines[line_num];
1811 line_num < src->num_lines; line_num++, line++)
1812 {
1813 for (; fn && fn->line == line_num; fn = fn->line_next)
1814 {
1815 arc_t *arc = fn->blocks[fn->num_blocks - 1].pred;
1816 gcov_type return_count = fn->blocks[fn->num_blocks - 1].count;
1817
1818 for (; arc; arc = arc->pred_next)
1819 if (arc->fake)
1820 return_count -= arc->count;
1821
1822 fprintf (gcov_file, "function %s", fn->name);
1823 fprintf (gcov_file, " called %s",
1824 format_gcov (fn->blocks[0].count, 0, -1));
1825 fprintf (gcov_file, " returned %s",
1826 format_gcov (return_count, fn->blocks[0].count, 0));
1827 fprintf (gcov_file, " blocks executed %s",
1828 format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0));
1829 fprintf (gcov_file, "\n");
1830 }
1831
1832 /* For lines which don't exist in the .bb file, print '-' before
1833 the source line. For lines which exist but were never
1834 executed, print '#####' before the source line. Otherwise,
1835 print the execution count before the source line. There are
1836 16 spaces of indentation added before the source line so that
1837 tabs won't be messed up. */
1838 fprintf (gcov_file, "%9s:%5u:",
1839 !line->exists ? "-" : !line->count ? "#####"
1840 : format_gcov (line->count, 0, -1), line_num);
1841
1842 if (retval)
1843 {
1844 /* Copy source line. */
1845 do
1846 {
1847 retval = fgets (string, STRING_SIZE, source_file);
1848 if (!retval)
1849 break;
1850 fputs (retval, gcov_file);
1851 }
1852 while (!retval[0] || retval[strlen (retval) - 1] != '\n');
1853 }
1854 if (!retval)
1855 fputs ("/*EOF*/\n", gcov_file);
1856
1857 if (flag_all_blocks)
1858 {
1859 block_t *block;
1860 arc_t *arc;
1861 int ix, jx;
1862
1863 for (ix = jx = 0, block = line->u.blocks; block;
1864 block = block->chain)
1865 {
1866 if (!block->is_call_return)
1867 fprintf (gcov_file, "%9s:%5u-block %2d\n",
1868 !line->exists ? "-" : !block->count ? "$$$$$"
1869 : format_gcov (block->count, 0, -1),
1870 line_num, ix++);
1871 if (flag_branches)
1872 for (arc = block->succ; arc; arc = arc->succ_next)
1873 jx += output_branch_count (gcov_file, jx, arc);
1874 }
1875 }
1876 else if (flag_branches)
1877 {
1878 int ix;
1879 arc_t *arc;
1880
1881 for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
1882 ix += output_branch_count (gcov_file, ix, arc);
1883 }
1884 }
1885
1886 /* Handle all remaining source lines. There may be lines after the
1887 last line of code. */
1888 if (retval)
1889 {
1890 for (; (retval = fgets (string, STRING_SIZE, source_file)); line_num++)
1891 {
1892 fprintf (gcov_file, "%9s:%5u:%s", "-", line_num, retval);
1893
1894 while (!retval[0] || retval[strlen (retval) - 1] != '\n')
1895 {
1896 retval = fgets (string, STRING_SIZE, source_file);
1897 if (!retval)
1898 break;
1899 fputs (retval, gcov_file);
1900 }
1901 }
1902 }
1903
1904 if (source_file)
1905 fclose (source_file);
1906 }