Add hppa-openbsd target
[official-gcc.git] / gcc / gcov.c
blobe28aac076fc10de3bf3e2d6e58dc88a9b6e1a57e
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 Free Software Foundation, Inc.
5 Contributed by James E. Wilson of Cygnus Support.
6 Mangled by Bob Manson of Cygnus Support.
8 Gcov is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
13 Gcov is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Gcov; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
23 /* ??? The code in final.c that produces the struct bb assumes that there is
24 no padding between the fields. This is not necessary true. The current
25 code can only be trusted if longs and pointers are the same size. */
27 /* ??? No need to print an execution count on every line, could just print
28 it on the first line of each block, and only print it on a subsequent
29 line in the same block if the count changes. */
31 /* ??? Print a list of the ten blocks with the highest execution counts,
32 and list the line numbers corresponding to those blocks. Also, perhaps
33 list the line numbers with the highest execution counts, only printing
34 the first if there are several which are all listed in the same block. */
36 /* ??? Should have an option to print the number of basic blocks, and the
37 percent of them that are covered. */
39 /* ??? Does not correctly handle the case where two .bb files refer to the
40 same included source file. For example, if one has a short file containing
41 only inline functions, which is then included in two other files, then
42 there will be two .bb files which refer to the include file, but there
43 is no way to get the total execution counts for the included file, can
44 only get execution counts for one or the other of the including files. */
46 #include "config.h"
47 #include "system.h"
48 #include "intl.h"
49 #include "version.h"
50 #undef abort
52 #include <getopt.h>
54 typedef HOST_WIDEST_INT gcov_type;
55 #include "gcov-io.h"
57 /* The .bb file format consists of several lists of 4-byte integers
58 which are the line numbers of each basic block in the file. Each
59 list is terminated by a zero. These lists correspond to the basic
60 blocks in the reconstructed program flow graph.
62 A line number of -1 indicates that a source file name (padded to a
63 long boundary) follows. The padded file name is followed by
64 another -1 to make it easy to scan past file names. A -2 indicates
65 that a function name (padded to a long boundary) follows; the name
66 is followed by another -2 to make it easy to scan past the function
67 name.
69 The .bbg file contains enough info to enable gcov to reconstruct the
70 program flow graph. The first word is the number of basic blocks,
71 the second word is the number of arcs, followed by the list of arcs
72 (source bb, dest bb pairs), then a -1, then the number of instrumented
73 arcs followed by the instrumented arcs, followed by another -1. This
74 is repeated for each function.
76 The .da file contains the execution count for each instrumented branch.
78 The .bb and .bbg files are created by giving GCC the -ftest-coverage option,
79 and the .da files are created when an executable compiled with
80 -fprofile-arcs is run. */
82 /* The functions in this file for creating and solution program flow graphs
83 are very similar to functions in the gcc source file profile.c. */
85 /* This is the size of the buffer used to read in source file lines. */
87 #define STRING_SIZE 200
89 /* One copy of this structure is created for each source file mentioned in the
90 .bb file. */
92 struct sourcefile
94 char *name;
95 int maxlineno;
96 struct sourcefile *next;
99 /* This points to the head of the sourcefile structure list. */
101 struct sourcefile *sources;
103 /* One of these is dynamically created whenever we identify an arc in the
104 function. */
106 struct adj_list {
107 int source;
108 int target;
109 gcov_type arc_count;
110 unsigned int count_valid : 1;
111 unsigned int on_tree : 1;
112 unsigned int fake : 1;
113 unsigned int fall_through : 1;
114 #if 0
115 /* Not needed for gcov, but defined in profile.c. */
116 rtx branch_insn;
117 #endif
118 struct adj_list *pred_next;
119 struct adj_list *succ_next;
122 /* Count the number of basic blocks, and create an array of these structures,
123 one for each bb in the function. */
125 struct bb_info {
126 struct adj_list *succ;
127 struct adj_list *pred;
128 gcov_type succ_count;
129 gcov_type pred_count;
130 gcov_type exec_count;
131 unsigned int count_valid : 1;
132 unsigned int on_tree : 1;
133 #if 0
134 /* Not needed for gcov, but defined in profile.c. */
135 rtx first_insn;
136 #endif
139 /* When outputting branch probabilities, one of these structures is created
140 for each branch/call. */
142 struct arcdata
144 gcov_type hits;
145 gcov_type total;
146 int call_insn;
147 struct arcdata *next;
150 /* Used to save the list of bb_graphs, one per function. */
152 struct bb_info_list {
153 /* Indexed by block number, holds the basic block graph for one function. */
154 struct bb_info *bb_graph;
155 int num_blocks;
156 struct bb_info_list *next;
159 /* Holds a list of function basic block graphs. */
161 static struct bb_info_list *bb_graph_list = 0;
163 /* Modification time of data files. */
165 static time_t bb_file_time;
167 /* Name and file pointer of the input file for the basic block graph. */
169 static char *bbg_file_name;
170 static FILE *bbg_file;
172 /* Name and file pointer of the input file for the arc count data. */
174 static char *da_file_name;
175 static FILE *da_file;
177 /* Name and file pointer of the input file for the basic block line counts. */
179 static char *bb_file_name;
180 static FILE *bb_file;
182 /* Holds the entire contents of the bb_file read into memory. */
184 static char *bb_data;
186 /* Size of bb_data array in longs. */
188 static long bb_data_size;
190 /* Name and file pointer of the output file. */
192 static char *gcov_file_name;
193 static FILE *gcov_file;
195 /* Name of the file mentioned on the command line. */
197 static char *input_file_name = 0;
199 /* Output branch probabilities if true. */
201 static int output_branch_probs = 0;
203 /* Output a gcov file if this is true. This is on by default, and can
204 be turned off by the -n option. */
206 static int output_gcov_file = 1;
208 /* For included files, make the gcov output file name include the name of
209 the input source file. For example, if x.h is included in a.c, then the
210 output file name is a.c.x.h.gcov instead of x.h.gcov. This works only
211 when a single source file is specified. */
213 static int output_long_names = 0;
215 /* Output summary info for each function. */
217 static int output_function_summary = 0;
219 /* Object directory file prefix. This is the directory/file
220 where .bb and .bbg files are looked for, if non-zero. */
222 static char *object_directory = 0;
224 /* Preserve all pathname components. Needed when object files and
225 source files are in subdirectories. */
226 static int preserve_paths = 0;
228 /* Output the number of times a branch was taken as opposed to the percentage
229 of times it was taken. Turned on by the -c option */
231 static int output_branch_counts = 0;
233 /* Forward declarations. */
234 static void process_args PARAMS ((int, char **));
235 static void open_files PARAMS ((void));
236 static void read_files PARAMS ((void));
237 static void scan_for_source_files PARAMS ((void));
238 static void output_data PARAMS ((void));
239 static void print_usage PARAMS ((int)) ATTRIBUTE_NORETURN;
240 static void print_version PARAMS ((void)) ATTRIBUTE_NORETURN;
241 static void init_arc PARAMS ((struct adj_list *, int, int, struct bb_info *));
242 static struct adj_list *reverse_arcs PARAMS ((struct adj_list *));
243 static gcov_type *read_profile PARAMS ((char *, long, int));
244 static void create_program_flow_graph PARAMS ((struct bb_info_list *));
245 static void solve_program_flow_graph PARAMS ((struct bb_info_list *));
246 static void calculate_branch_probs PARAMS ((struct bb_info_list *, int,
247 struct arcdata **, int));
248 static void function_summary PARAMS ((void));
249 static const char *format_hwint PARAMS ((HOST_WIDEST_INT, HOST_WIDEST_INT, int));
251 extern int main PARAMS ((int, char **));
254 main (argc, argv)
255 int argc;
256 char **argv;
258 gcc_init_libintl ();
260 process_args (argc, argv);
262 open_files ();
264 read_files ();
266 scan_for_source_files ();
268 output_data ();
270 return 0;
273 static void fnotice PARAMS ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2;
274 static void
275 fnotice VPARAMS ((FILE *file, const char *msgid, ...))
277 VA_OPEN (ap, msgid);
278 VA_FIXEDARG (ap, FILE *, file);
279 VA_FIXEDARG (ap, const char *, msgid);
281 vfprintf (file, _(msgid), ap);
282 VA_CLOSE (ap);
285 /* More 'friendly' abort that prints the line and file.
286 config.h can #define abort fancy_abort if you like that sort of thing. */
287 extern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN;
289 void
290 fancy_abort ()
292 fnotice (stderr, "Internal gcov abort.\n");
293 exit (FATAL_EXIT_CODE);
296 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
297 otherwise the output of --help. */
299 static void
300 print_usage (error_p)
301 int error_p;
303 FILE *file = error_p ? stderr : stdout;
304 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
305 fnotice (file, "Usage: gcov [OPTION]... SOURCEFILE\n\n");
306 fnotice (file, "Print code coverage information.\n\n");
307 fnotice (file, " -h, --help Print this help, then exit\n");
308 fnotice (file, " -v, --version Print version number, then exit\n");
309 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
310 fnotice (file, " -c, --branch-counts Given counts of branches taken\n\
311 rather than percentages\n");
312 fnotice (file, " -n, --no-output Do not create an output file\n");
313 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
314 source files\n");
315 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
316 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
317 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
318 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
319 GCCBUGURL);
320 exit (status);
323 /* Print version information and exit. */
325 static void
326 print_version ()
328 fnotice (stdout, "gcov (GCC) %s\n", version_string);
329 fnotice (stdout, "Copyright (C) 2001 Free Software Foundation, Inc.\n");
330 fnotice (stdout,
331 "This is free software; see the source for copying conditions. There is NO\n\
332 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
333 exit (SUCCESS_EXIT_CODE);
336 static const struct option options[] =
338 { "help", no_argument, NULL, 'h' },
339 { "version", no_argument, NULL, 'v' },
340 { "branch-probabilities", no_argument, NULL, 'b' },
341 { "branch-counts", no_argument, NULL, 'c' },
342 { "no-output", no_argument, NULL, 'n' },
343 { "long-file-names", no_argument, NULL, 'l' },
344 { "function-summaries", no_argument, NULL, 'f' },
345 { "preserve-paths", no_argument, NULL, 'p' },
346 { "object-directory", required_argument, NULL, 'o' },
347 { "object-file", required_argument, NULL, 'o' },
350 /* Parse the command line. */
352 static void
353 process_args (argc, argv)
354 int argc;
355 char **argv;
357 int opt;
359 while ((opt = getopt_long (argc, argv, "hvbclnfo:p", options, NULL)) != -1)
361 switch (opt)
363 case 'h':
364 print_usage (false);
365 /* print_usage will exit. */
366 case 'v':
367 print_version ();
368 /* print_version will exit. */
369 case 'b':
370 output_branch_probs = 1;
371 break;
372 case 'c':
373 output_branch_counts = 1;
374 break;
375 case 'n':
376 output_gcov_file = 0;
377 break;
378 case 'l':
379 output_long_names = 1;
380 break;
381 case 'f':
382 output_function_summary = 1;
383 break;
384 case 'o':
385 object_directory = optarg;
386 break;
387 case 'p':
388 preserve_paths = 1;
389 break;
390 default:
391 print_usage (true);
392 /* print_usage will exit. */
396 if (optind != argc - 1)
397 print_usage (true);
399 input_file_name = argv[optind];
403 /* Find and open the .bb, .da, and .bbg files. If OBJECT_DIRECTORY is
404 not specified, these are looked for in the current directory, and
405 named from the basename of the input_file_name sans extension. If
406 OBJECT_DIRECTORY is specified and is a directory, the files are in
407 that directory, but named from the basename of the input_file_name,
408 sans extension. Otherwise OBJECT_DIRECTORY is taken to be the name
409 of the object *file*, and the data files are named from that. */
411 static void
412 open_files ()
414 char *cptr;
415 char *name;
416 int length = strlen (input_file_name);
417 int base;
419 if (object_directory && object_directory[0])
421 struct stat status;
423 length += strlen (object_directory) + 2;
424 name = xmalloc (length);
425 name[0] = 0;
427 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
428 strcat (name, object_directory);
429 if (base && name[strlen (name) - 1] != '/')
430 strcat (name, "/");
432 else
434 name = xmalloc (length + 1);
435 name[0] = 0;
436 base = 1;
439 if (base)
441 /* Append source file name */
442 cptr = strrchr (input_file_name, '/');
443 cptr = cptr ? cptr + 1 : input_file_name;
445 strcat (name, cptr);
447 /* Remove the extension. */
448 cptr = strrchr (name, '.');
449 if (cptr)
450 *cptr = 0;
452 length = strlen (name);
453 da_file_name = xmalloc (length + 4);
454 bb_file_name = xmalloc (length + 4);
455 bbg_file_name = xmalloc (length + 5);
457 strcpy (da_file_name, name);
458 strcpy (bb_file_name, name);
459 strcpy (bbg_file_name, name);
460 strcpy (da_file_name + length, ".da");
461 strcpy (bb_file_name + length, ".bb");
462 strcpy (bbg_file_name + length, ".bbg");
464 bb_file = fopen (bb_file_name, "rb");
465 if (bb_file == NULL)
467 fnotice (stderr, "Could not open basic block file %s.\n", bb_file_name);
468 exit (FATAL_EXIT_CODE);
471 bbg_file = fopen (bbg_file_name, "rb");
472 if (bbg_file == NULL)
474 fnotice (stderr, "Could not open program flow graph file %s.\n",
475 bbg_file_name);
476 exit (FATAL_EXIT_CODE);
480 struct stat status;
482 if (!fstat (fileno (bb_file), &status))
483 bb_file_time = status.st_mtime;
486 /* If none of the functions in the file were executed, then there won't
487 be a .da file. Just assume that all counts are zero in this case. */
488 da_file = fopen (da_file_name, "rb");
489 if (da_file == NULL)
491 fnotice (stderr, "Could not open data file %s.\n", da_file_name);
492 fnotice (stderr, "Assuming that all execution counts are zero.\n");
495 /* Check for empty .bbg file. This indicates that there is no executable
496 code in this source file. */
497 /* Set the EOF condition if at the end of file. */
498 ungetc (getc (bbg_file), bbg_file);
499 if (feof (bbg_file))
501 fnotice (stderr, "No executable code associated with file %s.\n",
502 input_file_name);
503 exit (FATAL_EXIT_CODE);
507 /* Initialize a new arc. */
509 static void
510 init_arc (arcptr, source, target, bb_graph)
511 struct adj_list *arcptr;
512 int source, target;
513 struct bb_info *bb_graph;
515 arcptr->target = target;
516 arcptr->source = source;
518 arcptr->arc_count = 0;
519 arcptr->count_valid = 0;
520 arcptr->on_tree = 0;
521 arcptr->fake = 0;
522 arcptr->fall_through = 0;
524 arcptr->succ_next = bb_graph[source].succ;
525 bb_graph[source].succ = arcptr;
526 bb_graph[source].succ_count++;
528 arcptr->pred_next = bb_graph[target].pred;
529 bb_graph[target].pred = arcptr;
530 bb_graph[target].pred_count++;
534 /* Reverse the arcs on an arc list. */
536 static struct adj_list *
537 reverse_arcs (arcptr)
538 struct adj_list *arcptr;
540 struct adj_list *prev = 0;
541 struct adj_list *next;
543 for ( ; arcptr; arcptr = next)
545 next = arcptr->succ_next;
546 arcptr->succ_next = prev;
547 prev = arcptr;
550 return prev;
553 /* Reads profiles from the .da file and compute a hybrid profile. */
555 static gcov_type *
556 read_profile (function_name, cfg_checksum, instr_arcs)
557 char *function_name;
558 long cfg_checksum;
559 int instr_arcs;
561 int i;
562 int okay = 1;
563 gcov_type *profile;
564 char *function_name_buffer;
565 int function_name_buffer_len;
567 profile = xmalloc (sizeof (gcov_type) * instr_arcs);
568 function_name_buffer_len = strlen (function_name) + 1;
569 function_name_buffer = xmalloc (function_name_buffer_len + 1);
571 for (i = 0; i < instr_arcs; i++)
572 profile[i] = 0;
574 if (!da_file)
575 return profile;
577 rewind (da_file);
578 while (1)
580 long magic, extra_bytes;
581 long func_count;
582 int i;
584 if (__read_long (&magic, da_file, 4) != 0)
585 break;
587 if (magic != -123)
589 okay = 0;
590 break;
593 if (__read_long (&func_count, da_file, 4) != 0)
595 okay = 0;
596 break;
599 if (__read_long (&extra_bytes, da_file, 4) != 0)
601 okay = 0;
602 break;
605 /* skip extra data emited by __bb_exit_func. */
606 fseek (da_file, extra_bytes, SEEK_CUR);
608 for (i = 0; i < func_count; i++)
610 long arc_count;
611 long chksum;
612 int j;
614 if (__read_gcov_string
615 (function_name_buffer, function_name_buffer_len, da_file,
616 -1) != 0)
618 okay = 0;
619 break;
622 if (__read_long (&chksum, da_file, 4) != 0)
624 okay = 0;
625 break;
628 if (__read_long (&arc_count, da_file, 4) != 0)
630 okay = 0;
631 break;
634 if (strcmp (function_name_buffer, function_name) != 0
635 || arc_count != instr_arcs || chksum != cfg_checksum)
637 /* skip */
638 if (fseek (da_file, arc_count * 8, SEEK_CUR) < 0)
640 okay = 0;
641 break;
644 else
646 gcov_type tmp;
648 for (j = 0; j < arc_count; j++)
649 if (__read_gcov_type (&tmp, da_file, 8) != 0)
651 okay = 0;
652 break;
654 else
656 profile[j] += tmp;
661 if (!okay)
662 break;
666 free (function_name_buffer);
668 if (!okay)
670 fprintf (stderr, ".da file corrupted!\n");
671 free (profile);
672 abort ();
675 return profile;
678 /* Construct the program flow graph from the .bbg file, and read in the data
679 in the .da file. */
681 static void
682 create_program_flow_graph (bptr)
683 struct bb_info_list *bptr;
685 long num_blocks, number_arcs, src, dest, flag_bits, num_arcs_per_block;
686 int i;
687 struct adj_list *arcptr;
688 struct bb_info *bb_graph;
689 long cfg_checksum;
690 long instr_arcs = 0;
691 gcov_type *profile;
692 int profile_pos = 0;
693 char *function_name;
694 long function_name_len, tmp;
696 /* Read function name. */
697 __read_long (&tmp, bbg_file, 4); /* ignore -1. */
698 __read_long (&function_name_len, bbg_file, 4);
699 function_name = xmalloc (function_name_len + 1);
700 fread (function_name, 1, function_name_len + 1, bbg_file);
702 /* Skip padding. */
703 tmp = (function_name_len + 1) % 4;
705 if (tmp)
706 fseek (bbg_file, 4 - tmp, SEEK_CUR);
708 __read_long (&tmp, bbg_file, 4); /* ignore -1. */
710 /* Read the cfg checksum. */
711 __read_long (&cfg_checksum, bbg_file, 4);
713 /* Read the number of blocks. */
714 __read_long (&num_blocks, bbg_file, 4);
716 /* Create an array of size bb number of bb_info structs. */
717 bb_graph = (struct bb_info *) xcalloc (num_blocks, sizeof (struct bb_info));
719 bptr->bb_graph = bb_graph;
720 bptr->num_blocks = num_blocks;
722 /* Read and create each arc from the .bbg file. */
723 __read_long (&number_arcs, bbg_file, 4);
724 for (i = 0; i < num_blocks; i++)
726 int j;
728 __read_long (&num_arcs_per_block, bbg_file, 4);
729 for (j = 0; j < num_arcs_per_block; j++)
731 if (number_arcs-- < 0)
732 abort ();
734 src = i;
735 __read_long (&dest, bbg_file, 4);
737 arcptr = (struct adj_list *) xmalloc (sizeof (struct adj_list));
738 init_arc (arcptr, src, dest, bb_graph);
740 __read_long (&flag_bits, bbg_file, 4);
741 if (flag_bits & 0x1)
742 arcptr->on_tree++;
743 else
744 instr_arcs++;
745 arcptr->fake = !! (flag_bits & 0x2);
746 arcptr->fall_through = !! (flag_bits & 0x4);
750 if (number_arcs)
751 abort ();
753 /* Read and ignore the -1 separating the arc list from the arc list of the
754 next function. */
755 __read_long (&src, bbg_file, 4);
756 if (src != -1)
757 abort ();
759 /* Must reverse the order of all succ arcs, to ensure that they match
760 the order of the data in the .da file. */
762 for (i = 0; i < num_blocks; i++)
763 if (bb_graph[i].succ)
764 bb_graph[i].succ = reverse_arcs (bb_graph[i].succ);
766 /* Read profile from the .da file. */
768 profile = read_profile (function_name, cfg_checksum, instr_arcs);
770 /* For each arc not on the spanning tree, set its execution count from
771 the .da file. */
773 /* The first count in the .da file is the number of times that the function
774 was entered. This is the exec_count for block zero. */
776 /* This duplicates code in branch_prob in profile.c. */
778 for (i = 0; i < num_blocks; i++)
779 for (arcptr = bb_graph[i].succ; arcptr; arcptr = arcptr->succ_next)
780 if (! arcptr->on_tree)
782 arcptr->arc_count = profile[profile_pos++];
783 arcptr->count_valid = 1;
784 bb_graph[i].succ_count--;
785 bb_graph[arcptr->target].pred_count--;
787 free (profile);
788 free (function_name);
791 static void
792 solve_program_flow_graph (bptr)
793 struct bb_info_list *bptr;
795 int passes, changes;
796 gcov_type total;
797 int i;
798 struct adj_list *arcptr;
799 struct bb_info *bb_graph;
800 int num_blocks;
802 num_blocks = bptr->num_blocks;
803 bb_graph = bptr->bb_graph;
805 /* For every block in the file,
806 - if every exit/entrance arc has a known count, then set the block count
807 - if the block count is known, and every exit/entrance arc but one has
808 a known execution count, then set the count of the remaining arc
810 As arc counts are set, decrement the succ/pred count, but don't delete
811 the arc, that way we can easily tell when all arcs are known, or only
812 one arc is unknown. */
814 /* The order that the basic blocks are iterated through is important.
815 Since the code that finds spanning trees starts with block 0, low numbered
816 arcs are put on the spanning tree in preference to high numbered arcs.
817 Hence, most instrumented arcs are at the end. Graph solving works much
818 faster if we propagate numbers from the end to the start.
820 This takes an average of slightly more than 3 passes. */
822 changes = 1;
823 passes = 0;
824 while (changes)
826 passes++;
827 changes = 0;
829 for (i = num_blocks - 1; i >= 0; i--)
831 if (! bb_graph[i].count_valid)
833 if (bb_graph[i].succ_count == 0)
835 total = 0;
836 for (arcptr = bb_graph[i].succ; arcptr;
837 arcptr = arcptr->succ_next)
838 total += arcptr->arc_count;
839 bb_graph[i].exec_count = total;
840 bb_graph[i].count_valid = 1;
841 changes = 1;
843 else if (bb_graph[i].pred_count == 0)
845 total = 0;
846 for (arcptr = bb_graph[i].pred; arcptr;
847 arcptr = arcptr->pred_next)
848 total += arcptr->arc_count;
849 bb_graph[i].exec_count = total;
850 bb_graph[i].count_valid = 1;
851 changes = 1;
854 if (bb_graph[i].count_valid)
856 if (bb_graph[i].succ_count == 1)
858 total = 0;
859 /* One of the counts will be invalid, but it is zero,
860 so adding it in also doesn't hurt. */
861 for (arcptr = bb_graph[i].succ; arcptr;
862 arcptr = arcptr->succ_next)
863 total += arcptr->arc_count;
864 /* Calculate count for remaining arc by conservation. */
865 total = bb_graph[i].exec_count - total;
866 /* Search for the invalid arc, and set its count. */
867 for (arcptr = bb_graph[i].succ; arcptr;
868 arcptr = arcptr->succ_next)
869 if (! arcptr->count_valid)
870 break;
871 if (! arcptr)
872 abort ();
873 arcptr->count_valid = 1;
874 arcptr->arc_count = total;
875 bb_graph[i].succ_count--;
877 bb_graph[arcptr->target].pred_count--;
878 changes = 1;
880 if (bb_graph[i].pred_count == 1)
882 total = 0;
883 /* One of the counts will be invalid, but it is zero,
884 so adding it in also doesn't hurt. */
885 for (arcptr = bb_graph[i].pred; arcptr;
886 arcptr = arcptr->pred_next)
887 total += arcptr->arc_count;
888 /* Calculate count for remaining arc by conservation. */
889 total = bb_graph[i].exec_count - total;
890 /* Search for the invalid arc, and set its count. */
891 for (arcptr = bb_graph[i].pred; arcptr;
892 arcptr = arcptr->pred_next)
893 if (! arcptr->count_valid)
894 break;
895 if (! arcptr)
896 abort ();
897 arcptr->count_valid = 1;
898 arcptr->arc_count = total;
899 bb_graph[i].pred_count--;
901 bb_graph[arcptr->source].succ_count--;
902 changes = 1;
908 /* If the graph has been correctly solved, every block will have a
909 succ and pred count of zero. */
910 for (i = 0; i < num_blocks; i++)
911 if (bb_graph[i].succ_count || bb_graph[i].pred_count)
912 abort ();
916 static void
917 read_files ()
919 struct stat buf;
920 struct bb_info_list *list_end = 0;
921 struct bb_info_list *b_ptr;
923 while (! feof (bbg_file))
925 b_ptr = (struct bb_info_list *) xmalloc (sizeof (struct bb_info_list));
927 b_ptr->next = 0;
928 if (list_end)
929 list_end->next = b_ptr;
930 else
931 bb_graph_list = b_ptr;
932 list_end = b_ptr;
934 /* Read in the data in the .bbg file and reconstruct the program flow
935 graph for one function. */
936 create_program_flow_graph (b_ptr);
938 /* Set the EOF condition if at the end of file. */
939 ungetc (getc (bbg_file), bbg_file);
942 /* Calculate all of the basic block execution counts and branch
943 taken probabilities. */
945 for (b_ptr = bb_graph_list; b_ptr; b_ptr = b_ptr->next)
946 solve_program_flow_graph (b_ptr);
948 /* Read in all of the data from the .bb file. This info will be accessed
949 sequentially twice. */
950 stat (bb_file_name, &buf);
951 bb_data_size = buf.st_size / 4;
953 bb_data = (char *) xmalloc ((unsigned) buf.st_size);
954 fread (bb_data, sizeof (char), buf.st_size, bb_file);
956 fclose (bb_file);
957 if (da_file)
958 fclose (da_file);
959 fclose (bbg_file);
963 /* Scan the data in the .bb file to find all source files referenced,
964 and the largest line number mentioned in each one. */
966 static void
967 scan_for_source_files ()
969 struct sourcefile *s_ptr = NULL;
970 char *ptr;
971 long count;
972 long line_num;
974 /* Search the bb_data to find:
975 1) The number of sources files contained herein, and
976 2) The largest line number for each source file. */
978 ptr = bb_data;
979 sources = 0;
980 for (count = 0; count < bb_data_size; count++)
982 __fetch_long (&line_num, ptr, 4);
983 ptr += 4;
984 if (line_num == -1)
986 /* A source file name follows. Check to see if we already have
987 a sourcefile structure for this file. */
988 s_ptr = sources;
989 while (s_ptr && strcmp (s_ptr->name, ptr))
990 s_ptr = s_ptr->next;
992 if (s_ptr == 0)
994 /* No sourcefile structure for this file name exists, create
995 a new one, and append it to the front of the sources list. */
996 s_ptr = (struct sourcefile *) xmalloc (sizeof(struct sourcefile));
997 s_ptr->name = xstrdup (ptr);
998 s_ptr->maxlineno = 0;
999 s_ptr->next = sources;
1000 sources = s_ptr;
1003 /* Scan past the file name. */
1005 long delim;
1006 do {
1007 count++;
1008 __fetch_long (&delim, ptr, 4);
1009 ptr += 4;
1010 } while (delim != line_num);
1013 else if (line_num == -2)
1015 long delim;
1017 /* A function name follows. Ignore it. */
1018 do {
1019 count++;
1020 __fetch_long (&delim, ptr, 4);
1021 ptr += 4;
1022 } while (delim != line_num);
1024 /* There will be a zero before the first file name, in which case s_ptr
1025 will still be uninitialized. So, only try to set the maxlineno
1026 field if line_num is non-zero. */
1027 else if (line_num > 0)
1029 if (s_ptr->maxlineno <= line_num)
1030 s_ptr->maxlineno = line_num + 1;
1032 else if (line_num < 0)
1034 /* Don't know what this is, but it's garbage. */
1035 abort ();
1040 /* For calculating coverage at the function level. */
1042 static int function_source_lines;
1043 static int function_source_lines_executed;
1044 static int function_branches;
1045 static int function_branches_executed;
1046 static int function_branches_taken;
1047 static int function_calls;
1048 static int function_calls_executed;
1049 static char *function_name;
1051 /* Calculate the branch taken probabilities for all arcs branches at the
1052 end of this block. */
1054 static void
1055 calculate_branch_probs (current_graph, block_num, branch_probs, last_line_num)
1056 struct bb_info_list *current_graph;
1057 int block_num;
1058 struct arcdata **branch_probs;
1059 int last_line_num;
1061 gcov_type total;
1062 struct adj_list *arcptr;
1063 struct arcdata *end_ptr, *a_ptr;
1065 total = current_graph->bb_graph[block_num].exec_count;
1066 for (arcptr = current_graph->bb_graph[block_num].succ; arcptr;
1067 arcptr = arcptr->succ_next)
1069 /* Ignore fall through arcs as they aren't really branches. */
1071 if (arcptr->fall_through)
1072 continue;
1074 a_ptr = (struct arcdata *) xmalloc (sizeof (struct arcdata));
1075 a_ptr->total = total;
1076 if (total == 0)
1077 a_ptr->hits = 0;
1078 else
1079 a_ptr->hits = arcptr->arc_count;
1080 a_ptr->call_insn = arcptr->fake;
1082 if (output_function_summary)
1084 if (a_ptr->call_insn)
1086 function_calls++;
1087 if (a_ptr->total != 0)
1088 function_calls_executed++;
1090 else
1092 function_branches++;
1093 if (a_ptr->total != 0)
1094 function_branches_executed++;
1095 if (a_ptr->hits > 0)
1096 function_branches_taken++;
1100 /* Append the new branch to the end of the list. */
1101 a_ptr->next = 0;
1102 if (! branch_probs[last_line_num])
1103 branch_probs[last_line_num] = a_ptr;
1104 else
1106 end_ptr = branch_probs[last_line_num];
1107 while (end_ptr->next != 0)
1108 end_ptr = end_ptr->next;
1109 end_ptr->next = a_ptr;
1114 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1115 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1116 If DP is zero, no decimal point is printed. Only print 100% when
1117 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1118 format TOP. Return pointer to a static string. */
1120 static char const *
1121 format_hwint (top, bottom, dp)
1122 HOST_WIDEST_INT top, bottom;
1123 int dp;
1125 static char buffer[20];
1127 if (dp >= 0)
1129 float ratio = bottom ? (float)top / bottom : 0;
1130 int ix;
1131 unsigned limit = 100;
1132 unsigned percent;
1134 for (ix = dp; ix--; )
1135 limit *= 10;
1137 percent = (unsigned) (ratio * limit + (float)0.5);
1138 if (percent <= 0 && top)
1139 percent = 1;
1140 else if (percent >= limit && top != bottom)
1141 percent = limit - 1;
1142 ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1143 if (dp)
1145 dp++;
1148 buffer[ix+1] = buffer[ix];
1149 ix--;
1151 while (dp--);
1152 buffer[ix + 1] = '.';
1155 else
1156 sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, top);
1158 return buffer;
1162 /* Output summary info for a function. */
1164 static void
1165 function_summary ()
1167 if (function_source_lines)
1168 fnotice (stdout, "%s of %d source lines executed in function %s\n",
1169 format_hwint (function_source_lines_executed,
1170 function_source_lines, 2),
1171 function_source_lines, function_name);
1172 else
1173 fnotice (stdout, "No executable source lines in function %s\n",
1174 function_name);
1176 if (output_branch_probs)
1178 if (function_branches)
1180 fnotice (stdout, "%s of %d branches executed in function %s\n",
1181 format_hwint (function_branches_executed,
1182 function_branches, 2),
1183 function_branches, function_name);
1184 fnotice (stdout,
1185 "%s of %d branches taken at least once in function %s\n",
1186 format_hwint (function_branches_taken,
1187 function_branches, 2),
1188 function_branches, function_name);
1190 else
1191 fnotice (stdout, "No branches in function %s\n", function_name);
1192 if (function_calls)
1193 fnotice (stdout, "%s of %d calls executed in function %s\n",
1194 format_hwint (function_calls_executed,
1195 function_calls, 2),
1196 function_calls, function_name);
1197 else
1198 fnotice (stdout, "No calls in function %s\n", function_name);
1202 /* Calculate line execution counts, and output the data to a .tcov file. */
1204 static void
1205 output_data ()
1207 /* When scanning data, this is true only if the data applies to the
1208 current source file. */
1209 int this_file;
1210 /* An array indexed by line number which indicates how many times that line
1211 was executed. */
1212 gcov_type *line_counts;
1213 /* An array indexed by line number which indicates whether the line was
1214 present in the bb file (i.e. whether it had code associate with it).
1215 Lines never executed are those which both exist, and have zero execution
1216 counts. */
1217 char *line_exists;
1218 /* An array indexed by line number, which contains a list of branch
1219 probabilities, one for each branch on that line. */
1220 struct arcdata **branch_probs = NULL;
1221 struct sourcefile *s_ptr;
1222 char *source_file_name;
1223 FILE *source_file;
1224 struct bb_info_list *current_graph;
1225 long count;
1226 char *cptr;
1227 long block_num;
1228 long line_num;
1229 long last_line_num = 0;
1230 int i;
1231 struct arcdata *a_ptr;
1232 /* Buffer used for reading in lines from the source file. */
1233 char string[STRING_SIZE];
1234 /* For calculating coverage at the file level. */
1235 int total_source_lines;
1236 int total_source_lines_executed;
1237 int total_branches;
1238 int total_branches_executed;
1239 int total_branches_taken;
1240 int total_calls;
1241 int total_calls_executed;
1243 /* Now, for each source file, allocate an array big enough to hold a count
1244 for each line. Scan through the bb_data, and when the file name matches
1245 the current file name, then for each following line number, increment
1246 the line number execution count indicated by the execution count of
1247 the appropriate basic block. */
1249 for (s_ptr = sources; s_ptr; s_ptr = s_ptr->next)
1251 source_file_name = s_ptr->name;
1253 line_counts = (gcov_type *) xcalloc (sizeof (gcov_type), s_ptr->maxlineno);
1254 line_exists = xcalloc (1, s_ptr->maxlineno);
1255 if (output_branch_probs)
1256 branch_probs = (struct arcdata **)
1257 xcalloc (sizeof (struct arcdata *), s_ptr->maxlineno);
1259 /* There will be a zero at the beginning of the bb info, before the
1260 first list of line numbers, so must initialize block_num to 0. */
1261 block_num = 0;
1262 this_file = 0;
1263 current_graph = 0;
1265 /* Pointer into the bb_data, incremented while scanning the data. */
1266 char *ptr = bb_data;
1267 for (count = 0; count < bb_data_size; count++)
1269 long delim;
1271 __fetch_long (&line_num, ptr, 4);
1272 ptr += 4;
1273 if (line_num == -1)
1275 /* Marks the beginning of a file name. Check to see whether
1276 this is the filename we are currently collecting data for. */
1278 if (strcmp (s_ptr->name, ptr))
1279 this_file = 0;
1280 else
1281 this_file = 1;
1283 /* Scan past the file name. */
1284 do {
1285 count++;
1286 __fetch_long (&delim, ptr, 4);
1287 ptr += 4;
1288 } while (delim != line_num);
1290 else if (line_num == -2)
1292 /* Marks the start of a new function. Advance to the next
1293 program flow graph. */
1295 if (! current_graph)
1296 current_graph = bb_graph_list;
1297 else
1299 if (block_num == current_graph->num_blocks - 1)
1300 /* Last block falls through to exit. */
1302 else if (block_num == current_graph->num_blocks - 2)
1304 if (output_branch_probs && this_file)
1305 calculate_branch_probs (current_graph, block_num,
1306 branch_probs, last_line_num);
1308 else
1310 fnotice (stderr,
1311 "didn't use all bb entries of graph, function %s\n",
1312 function_name);
1313 fnotice (stderr, "block_num = %ld, num_blocks = %d\n",
1314 block_num, current_graph->num_blocks);
1317 current_graph = current_graph->next;
1318 block_num = 0;
1320 if (output_function_summary && this_file)
1321 function_summary ();
1324 if (output_function_summary)
1326 function_source_lines = 0;
1327 function_source_lines_executed = 0;
1328 function_branches = 0;
1329 function_branches_executed = 0;
1330 function_branches_taken = 0;
1331 function_calls = 0;
1332 function_calls_executed = 0;
1335 /* Save the function name for later use. */
1336 function_name = ptr;
1338 /* Scan past the file name. */
1339 do {
1340 count++;
1341 __fetch_long (&delim, ptr, 4);
1342 ptr += 4;
1343 } while (delim != line_num);
1345 else if (line_num == 0)
1347 /* Marks the end of a block. */
1349 if (block_num >= current_graph->num_blocks)
1351 fnotice (stderr, "ERROR: too many basic blocks in .bb file %s\n",
1352 function_name);
1353 abort ();
1356 if (output_branch_probs && this_file)
1357 calculate_branch_probs (current_graph, block_num,
1358 branch_probs, last_line_num);
1360 block_num++;
1362 else if (this_file)
1364 if (output_function_summary)
1366 if (line_exists[line_num] == 0)
1367 function_source_lines++;
1368 if (line_counts[line_num] == 0
1369 && current_graph->bb_graph[block_num].exec_count != 0)
1370 function_source_lines_executed++;
1373 /* Accumulate execution data for this line number. */
1375 line_counts[line_num]
1376 += current_graph->bb_graph[block_num].exec_count;
1377 line_exists[line_num] = 1;
1378 last_line_num = line_num;
1383 if (output_function_summary && this_file)
1384 function_summary ();
1386 /* Calculate summary test coverage statistics. */
1388 total_source_lines = 0;
1389 total_source_lines_executed = 0;
1390 total_branches = 0;
1391 total_branches_executed = 0;
1392 total_branches_taken = 0;
1393 total_calls = 0;
1394 total_calls_executed = 0;
1396 for (count = 1; count < s_ptr->maxlineno; count++)
1398 if (line_exists[count])
1400 total_source_lines++;
1401 if (line_counts[count])
1402 total_source_lines_executed++;
1404 if (output_branch_probs)
1406 for (a_ptr = branch_probs[count]; a_ptr; a_ptr = a_ptr->next)
1408 if (a_ptr->call_insn)
1410 total_calls++;
1411 if (a_ptr->total != 0)
1412 total_calls_executed++;
1414 else
1416 total_branches++;
1417 if (a_ptr->total != 0)
1418 total_branches_executed++;
1419 if (a_ptr->hits > 0)
1420 total_branches_taken++;
1426 if (total_source_lines)
1427 fnotice (stdout,
1428 "%s of %d source lines executed in file %s\n",
1429 format_hwint (total_source_lines_executed,
1430 total_source_lines, 2),
1431 total_source_lines, source_file_name);
1432 else
1433 fnotice (stdout, "No executable source lines in file %s\n",
1434 source_file_name);
1436 if (output_branch_probs)
1438 if (total_branches)
1440 fnotice (stdout, "%s of %d branches executed in file %s\n",
1441 format_hwint (total_branches_executed,
1442 total_branches, 2),
1443 total_branches, source_file_name);
1444 fnotice (stdout,
1445 "%s of %d branches taken at least once in file %s\n",
1446 format_hwint (total_branches_taken,
1447 total_branches, 2),
1448 total_branches, source_file_name);
1450 else
1451 fnotice (stdout, "No branches in file %s\n", source_file_name);
1452 if (total_calls)
1453 fnotice (stdout, "%s of %d calls executed in file %s\n",
1454 format_hwint (total_calls_executed, total_calls, 2),
1455 total_calls, source_file_name);
1456 else
1457 fnotice (stdout, "No calls in file %s\n", source_file_name);
1460 if (output_gcov_file)
1462 /* Now the statistics are ready. Read in the source file one line
1463 at a time, and output that line to the gcov file preceded by
1464 its execution count if non zero. */
1465 char const *retval;
1467 /* Generate an output file name. LONG_OUTPUT_NAMES and
1468 PRESERVE_PATHS affect name generation. With
1469 preserve_paths we create a filename from all path
1470 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
1473 input file to each output name (except when the current
1474 source file is the input file, so you don't get a double
1475 concatenation). The two components are separated by
1476 '##'. Also '.' filename components are removed and '..'
1477 components are renamed to '^'. */
1478 gcov_file_name = xmalloc (strlen (source_file_name)
1479 + strlen (input_file_name) + 10);
1480 gcov_file_name[0] = 0;
1481 if (output_long_names && strcmp (source_file_name, input_file_name))
1483 /* Generate the input filename part. */
1484 cptr = preserve_paths ? NULL : strrchr (input_file_name, '/');
1485 cptr = cptr ? cptr + 1 : input_file_name;
1486 strcat (gcov_file_name, cptr);
1487 strcat (gcov_file_name, "##");
1489 /* Generate the source filename part. */
1490 cptr = preserve_paths ? NULL : strrchr (source_file_name, '/');
1491 cptr = cptr ? cptr + 1 : source_file_name;
1492 strcat (gcov_file_name, cptr);
1494 if (preserve_paths)
1496 /* Convert '/' to '#', remove '/./', convert '/../' to
1497 '/^/' */
1498 char *prev;
1500 for (cptr = gcov_file_name;
1501 (cptr = strchr ((prev = cptr), '/'));)
1503 unsigned shift = 0;
1505 if (prev + 1 == cptr && prev[0] == '.')
1507 /* Remove '.' */
1508 shift = 2;
1510 else if (prev + 2 == cptr
1511 && prev[0] == '.' && prev[1] == '.')
1513 /* Convert '..' */
1514 shift = 1;
1515 prev[1] = '^';
1517 else
1518 *cptr++ = '#';
1519 if (shift)
1521 cptr = prev;
1523 prev[0] = prev[shift];
1524 while (*prev++);
1529 /* Don't strip off the ending for compatibility with tcov, since
1530 this results in confusion if there is more than one file with
1531 the same basename, e.g. tmp.c and tmp.h. */
1532 strcat (gcov_file_name, ".gcov");
1534 gcov_file = fopen (gcov_file_name, "w");
1536 if (gcov_file == NULL)
1538 fnotice (stderr, "Could not open output file %s.\n",
1539 gcov_file_name);
1540 free (line_counts);
1541 free (line_exists);
1542 continue;
1545 fnotice (stdout, "Creating %s.\n", gcov_file_name);
1547 fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, source_file_name);
1548 fprintf (gcov_file, "%9s:%5d:Object:%s\n", "-", 0, bb_file_name);
1550 source_file = fopen (source_file_name, "r");
1551 if (source_file == NULL)
1552 fnotice (stderr, "Could not open source file %s.\n",
1553 source_file_name);
1554 else
1556 struct stat status;
1558 if (!fstat (fileno (source_file), &status)
1559 && status.st_mtime > bb_file_time)
1561 fnotice (stderr, "Warning: source file %s is newer than %s\n",
1562 source_file_name, bb_file_name);
1563 fprintf (gcov_file, "%9s:%5d:Source is newer than compiler output\n", "-", 0);
1567 for (retval = source_file ? "" : NULL, count = 1;
1568 count < s_ptr->maxlineno; count++)
1570 /* For lines which don't exist in the .bb file, print
1571 '-' before the source line. For lines which exist
1572 but were never executed, print '#####' before the source
1573 line. Otherwise, print the execution count before
1574 the source line. */
1576 /* There are 16 spaces of indentation added before the source
1577 line so that tabs won't be messed up. */
1578 fprintf (gcov_file, "%9s:%5ld:",
1579 !line_exists[count] ? "-"
1580 : !line_counts[count] ? "#####"
1581 : format_hwint (line_counts[count], 0, -1), count);
1583 if (retval)
1587 retval = fgets (string, STRING_SIZE, source_file);
1588 if (!retval)
1590 fnotice (stderr,
1591 "Unexpected EOF while reading source file %s.\n",
1592 source_file_name);
1593 break;
1595 fputs (retval, gcov_file);
1597 while (!retval[0] || retval[strlen (retval) - 1] != '\n');
1599 if (!retval)
1600 fputs ("??\n", gcov_file);
1602 if (output_branch_probs)
1604 for (i = 0, a_ptr = branch_probs[count]; a_ptr;
1605 a_ptr = a_ptr->next, i++)
1607 if (a_ptr->call_insn)
1609 if (a_ptr->total == 0)
1610 fnotice (gcov_file, "call %2d never executed\n", i);
1611 else
1612 fnotice
1613 (gcov_file, "call %2d returns %s\n", i,
1614 format_hwint (a_ptr->total - a_ptr->hits,
1615 a_ptr->total,
1616 -output_branch_counts));
1618 else
1620 if (a_ptr->total == 0)
1621 fnotice (gcov_file, "branch %2d never executed\n",
1623 else
1624 fnotice
1625 (gcov_file, "branch %2d taken %s\n", i,
1626 format_hwint (a_ptr->hits, a_ptr->total,
1627 -output_branch_counts));
1633 /* Handle all remaining source lines. There may be lines
1634 after the last line of code. */
1635 if (retval)
1637 for (; (retval = fgets (string, STRING_SIZE, source_file));
1638 count++)
1640 fprintf (gcov_file, "%9s:%5ld:%s", "-", count, retval);
1642 while (!retval[0] || retval[strlen (retval) - 1] != '\n')
1644 retval = fgets (string, STRING_SIZE, source_file);
1645 if (!retval)
1646 break;
1647 fputs (retval, gcov_file);
1652 if (source_file)
1653 fclose (source_file);
1654 if (ferror (gcov_file))
1655 fnotice (stderr, "Error writing output file %s.\n",
1656 gcov_file_name);
1657 fclose (gcov_file);
1660 free (line_counts);
1661 free (line_exists);