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