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