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