Fix type.
[official-gcc.git] / gcc / gcov.c
blob94f9baad40b8cb3c1fe64bb2262dfbc45fd053c6
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
108 int source;
109 int target;
110 gcov_type arc_count;
111 unsigned int count_valid : 1;
112 unsigned int on_tree : 1;
113 unsigned int fake : 1;
114 unsigned int fall_through : 1;
115 #if 0
116 /* Not needed for gcov, but defined in profile.c. */
117 rtx branch_insn;
118 #endif
119 struct adj_list *pred_next;
120 struct adj_list *succ_next;
123 /* Count the number of basic blocks, and create an array of these structures,
124 one for each bb in the function. */
126 struct bb_info
128 struct adj_list *succ;
129 struct adj_list *pred;
130 gcov_type succ_count;
131 gcov_type pred_count;
132 gcov_type exec_count;
133 unsigned int count_valid : 1;
134 unsigned int on_tree : 1;
135 #if 0
136 /* Not needed for gcov, but defined in profile.c. */
137 rtx first_insn;
138 #endif
141 /* When outputting branch probabilities, one of these structures is created
142 for each branch/call. */
144 struct arcdata
146 gcov_type hits;
147 gcov_type total;
148 int call_insn;
149 struct arcdata *next;
152 /* Used to save the list of bb_graphs, one per function. */
154 struct bb_info_list
156 /* Indexed by block number, holds the basic block graph for one function. */
157 struct bb_info *bb_graph;
158 int num_blocks;
159 struct bb_info_list *next;
162 /* Used to hold information about each line. */
163 struct line_info
165 gcov_type count; /* execution count */
166 struct arcdata *branches; /* list of branch probabilities for line. */
167 unsigned exists : 1; /* has code associated with it. */
170 struct coverage
172 int lines;
173 int lines_executed;
175 int branches;
176 int branches_executed;
177 int branches_taken;
179 int calls;
180 int calls_executed;
182 char *name;
185 /* Holds a list of function basic block graphs. */
187 static struct bb_info_list *bb_graph_list = 0;
189 /* Modification time of data files. */
191 static time_t bb_file_time;
193 /* Name and file pointer of the input file for the basic block graph. */
195 static char *bbg_file_name;
196 static FILE *bbg_file;
198 /* Name and file pointer of the input file for the arc count data. */
200 static char *da_file_name;
201 static FILE *da_file;
203 /* Name and file pointer of the input file for the basic block line counts. */
205 static char *bb_file_name;
206 static FILE *bb_file;
208 /* Holds the entire contents of the bb_file read into memory. */
210 static char *bb_data;
212 /* Size of bb_data array in longs. */
214 static long bb_data_size;
216 /* Name of the file mentioned on the command line. */
218 static char *input_file_name = 0;
220 /* Output branch probabilities if true. */
222 static int output_branch_probs = 0;
224 /* Output a gcov file if this is true. This is on by default, and can
225 be turned off by the -n option. */
227 static int output_gcov_file = 1;
229 /* For included files, make the gcov output file name include the name of
230 the input source file. For example, if x.h is included in a.c, then the
231 output file name is a.c.x.h.gcov instead of x.h.gcov. This works only
232 when a single source file is specified. */
234 static int output_long_names = 0;
236 /* Output summary info for each function. */
238 static int output_function_summary = 0;
240 /* Object directory file prefix. This is the directory/file
241 where .bb and .bbg files are looked for, if nonzero. */
243 static char *object_directory = 0;
245 /* Preserve all pathname components. Needed when object files and
246 source files are in subdirectories. */
247 static int preserve_paths = 0;
249 /* Output the number of times a branch was taken as opposed to the percentage
250 of times it was taken. Turned on by the -c option */
252 static int output_branch_counts = 0;
254 /* Forward declarations. */
255 static void process_args PARAMS ((int, char **));
256 static void open_files PARAMS ((void));
257 static void read_files PARAMS ((void));
258 static void scan_for_source_files PARAMS ((void));
259 static void output_data PARAMS ((struct sourcefile *));
260 static void print_usage PARAMS ((int)) ATTRIBUTE_NORETURN;
261 static void print_version PARAMS ((void)) ATTRIBUTE_NORETURN;
262 static void init_arc PARAMS ((struct adj_list *, int, int, struct bb_info *));
263 static struct adj_list *reverse_arcs PARAMS ((struct adj_list *));
264 static gcov_type *read_profile PARAMS ((char *, long, int));
265 static void create_program_flow_graph PARAMS ((struct bb_info_list *));
266 static void solve_program_flow_graph PARAMS ((struct bb_info_list *));
267 static void accumulate_branch_counts PARAMS ((struct coverage *,
268 struct arcdata *));
269 static void calculate_branch_probs PARAMS ((struct bb_info *,
270 struct line_info *,
271 struct coverage *));
272 static void function_summary PARAMS ((struct coverage *, const char *));
273 static void init_line_info PARAMS ((struct line_info *,
274 struct coverage *, long));
275 static void output_line_info PARAMS ((FILE *, const struct line_info *,
276 const struct coverage *, long));
277 static char *make_gcov_file_name PARAMS ((char *));
278 static const char *format_hwint PARAMS ((HOST_WIDEST_INT, HOST_WIDEST_INT,
279 int));
281 extern int main PARAMS ((int, char **));
284 main (argc, argv)
285 int argc;
286 char **argv;
288 struct sourcefile *s_ptr;
290 gcc_init_libintl ();
292 process_args (argc, argv);
294 open_files ();
296 read_files ();
298 scan_for_source_files ();
300 for (s_ptr = sources; s_ptr; s_ptr = s_ptr->next)
301 output_data (s_ptr);
303 return 0;
306 static void fnotice PARAMS ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2;
307 static void
308 fnotice VPARAMS ((FILE *file, const char *msgid, ...))
310 VA_OPEN (ap, msgid);
311 VA_FIXEDARG (ap, FILE *, file);
312 VA_FIXEDARG (ap, const char *, msgid);
314 vfprintf (file, _(msgid), ap);
315 VA_CLOSE (ap);
318 /* More 'friendly' abort that prints the line and file.
319 config.h can #define abort fancy_abort if you like that sort of thing. */
320 extern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN;
322 void
323 fancy_abort ()
325 fnotice (stderr, "Internal gcov abort.\n");
326 exit (FATAL_EXIT_CODE);
329 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
330 otherwise the output of --help. */
332 static void
333 print_usage (error_p)
334 int error_p;
336 FILE *file = error_p ? stderr : stdout;
337 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
338 fnotice (file, "Usage: gcov [OPTION]... SOURCEFILE\n\n");
339 fnotice (file, "Print code coverage information.\n\n");
340 fnotice (file, " -h, --help Print this help, then exit\n");
341 fnotice (file, " -v, --version Print version number, then exit\n");
342 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
343 fnotice (file, " -c, --branch-counts Given counts of branches taken\n\
344 rather than percentages\n");
345 fnotice (file, " -n, --no-output Do not create an output file\n");
346 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
347 source files\n");
348 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
349 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
350 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
351 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
352 bug_report_url);
353 exit (status);
356 /* Print version information and exit. */
358 static void
359 print_version ()
361 fnotice (stdout, "gcov (GCC) %s\n", version_string);
362 fnotice (stdout, "Copyright (C) 2001 Free Software Foundation, Inc.\n");
363 fnotice (stdout,
364 "This is free software; see the source for copying conditions. There is NO\n\
365 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
366 exit (SUCCESS_EXIT_CODE);
369 static const struct option options[] =
371 { "help", no_argument, NULL, 'h' },
372 { "version", no_argument, NULL, 'v' },
373 { "branch-probabilities", no_argument, NULL, 'b' },
374 { "branch-counts", no_argument, NULL, 'c' },
375 { "no-output", no_argument, NULL, 'n' },
376 { "long-file-names", no_argument, NULL, 'l' },
377 { "function-summaries", no_argument, NULL, 'f' },
378 { "preserve-paths", no_argument, NULL, 'p' },
379 { "object-directory", required_argument, NULL, 'o' },
380 { "object-file", required_argument, NULL, 'o' },
383 /* Parse the command line. */
385 static void
386 process_args (argc, argv)
387 int argc;
388 char **argv;
390 int opt;
392 while ((opt = getopt_long (argc, argv, "hvbclnfo:p", options, NULL)) != -1)
394 switch (opt)
396 case 'h':
397 print_usage (false);
398 /* print_usage will exit. */
399 case 'v':
400 print_version ();
401 /* print_version will exit. */
402 case 'b':
403 output_branch_probs = 1;
404 break;
405 case 'c':
406 output_branch_counts = 1;
407 break;
408 case 'n':
409 output_gcov_file = 0;
410 break;
411 case 'l':
412 output_long_names = 1;
413 break;
414 case 'f':
415 output_function_summary = 1;
416 break;
417 case 'o':
418 object_directory = optarg;
419 break;
420 case 'p':
421 preserve_paths = 1;
422 break;
423 default:
424 print_usage (true);
425 /* print_usage will exit. */
429 if (optind != argc - 1)
430 print_usage (true);
432 input_file_name = argv[optind];
436 /* Find and open the .bb, .da, and .bbg files. If OBJECT_DIRECTORY is
437 not specified, these are looked for in the current directory, and
438 named from the basename of the input_file_name sans extension. If
439 OBJECT_DIRECTORY is specified and is a directory, the files are in
440 that directory, but named from the basename of the input_file_name,
441 sans extension. Otherwise OBJECT_DIRECTORY is taken to be the name
442 of the object *file*, and the data files are named from that. */
444 static void
445 open_files ()
447 char *cptr;
448 char *name;
449 int length = strlen (input_file_name);
450 int base;
452 if (object_directory && object_directory[0])
454 struct stat status;
456 length += strlen (object_directory) + 2;
457 name = xmalloc (length);
458 name[0] = 0;
460 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
461 strcat (name, object_directory);
462 if (base && name[strlen (name) - 1] != '/')
463 strcat (name, "/");
465 else
467 name = xmalloc (length + 1);
468 name[0] = 0;
469 base = 1;
472 if (base)
474 /* Append source file name */
475 cptr = strrchr (input_file_name, '/');
476 cptr = cptr ? cptr + 1 : input_file_name;
478 strcat (name, cptr);
480 /* Remove the extension. */
481 cptr = strrchr (name, '.');
482 if (cptr)
483 *cptr = 0;
485 length = strlen (name);
486 da_file_name = xmalloc (length + 4);
487 bb_file_name = xmalloc (length + 4);
488 bbg_file_name = xmalloc (length + 5);
490 strcpy (da_file_name, name);
491 strcpy (bb_file_name, name);
492 strcpy (bbg_file_name, name);
493 strcpy (da_file_name + length, ".da");
494 strcpy (bb_file_name + length, ".bb");
495 strcpy (bbg_file_name + length, ".bbg");
497 bb_file = fopen (bb_file_name, "rb");
498 if (bb_file == NULL)
500 fnotice (stderr, "Could not open basic block file %s.\n", bb_file_name);
501 exit (FATAL_EXIT_CODE);
504 bbg_file = fopen (bbg_file_name, "rb");
505 if (bbg_file == NULL)
507 fnotice (stderr, "Could not open program flow graph file %s.\n",
508 bbg_file_name);
509 exit (FATAL_EXIT_CODE);
513 struct stat status;
515 if (!fstat (fileno (bb_file), &status))
516 bb_file_time = status.st_mtime;
519 /* If none of the functions in the file were executed, then there won't
520 be a .da file. Just assume that all counts are zero in this case. */
521 da_file = fopen (da_file_name, "rb");
522 if (da_file == NULL)
524 fnotice (stderr, "Could not open data file %s.\n", da_file_name);
525 fnotice (stderr, "Assuming that all execution counts are zero.\n");
528 /* Check for empty .bbg file. This indicates that there is no executable
529 code in this source file. */
530 /* Set the EOF condition if at the end of file. */
531 ungetc (getc (bbg_file), bbg_file);
532 if (feof (bbg_file))
534 fnotice (stderr, "No executable code associated with file %s.\n",
535 input_file_name);
536 exit (FATAL_EXIT_CODE);
540 /* Initialize a new arc. */
542 static void
543 init_arc (arcptr, source, target, bb_graph)
544 struct adj_list *arcptr;
545 int source, target;
546 struct bb_info *bb_graph;
548 arcptr->target = target;
549 arcptr->source = source;
551 arcptr->arc_count = 0;
552 arcptr->count_valid = 0;
553 arcptr->on_tree = 0;
554 arcptr->fake = 0;
555 arcptr->fall_through = 0;
557 arcptr->succ_next = bb_graph[source].succ;
558 bb_graph[source].succ = arcptr;
559 bb_graph[source].succ_count++;
561 arcptr->pred_next = bb_graph[target].pred;
562 bb_graph[target].pred = arcptr;
563 bb_graph[target].pred_count++;
566 /* Reverse the arcs on an arc list. */
568 static struct adj_list *
569 reverse_arcs (arcptr)
570 struct adj_list *arcptr;
572 struct adj_list *prev = 0;
573 struct adj_list *next;
575 for ( ; arcptr; arcptr = next)
577 next = arcptr->succ_next;
578 arcptr->succ_next = prev;
579 prev = arcptr;
582 return prev;
585 /* Reads profiles from the .da file and compute a hybrid profile. */
587 static gcov_type *
588 read_profile (function_name, cfg_checksum, instr_arcs)
589 char *function_name;
590 long cfg_checksum;
591 int instr_arcs;
593 int i;
594 int okay = 1;
595 gcov_type *profile;
596 char *function_name_buffer;
597 int function_name_buffer_len;
599 profile = xmalloc (sizeof (gcov_type) * instr_arcs);
600 function_name_buffer_len = strlen (function_name) + 1;
601 function_name_buffer = xmalloc (function_name_buffer_len + 1);
603 for (i = 0; i < instr_arcs; i++)
604 profile[i] = 0;
606 if (!da_file)
607 return profile;
609 rewind (da_file);
610 while (1)
612 long magic, extra_bytes;
613 long func_count;
614 int i;
616 if (__read_long (&magic, da_file, 4) != 0)
617 break;
619 if (magic != -123)
621 okay = 0;
622 break;
625 if (__read_long (&func_count, da_file, 4) != 0)
627 okay = 0;
628 break;
631 if (__read_long (&extra_bytes, da_file, 4) != 0)
633 okay = 0;
634 break;
637 /* skip extra data emited by __bb_exit_func. */
638 fseek (da_file, extra_bytes, SEEK_CUR);
640 for (i = 0; i < func_count; i++)
642 long arc_count;
643 long chksum;
644 int j;
646 if (__read_gcov_string
647 (function_name_buffer, function_name_buffer_len, da_file,
648 -1) != 0)
650 okay = 0;
651 break;
654 if (__read_long (&chksum, da_file, 4) != 0)
656 okay = 0;
657 break;
660 if (__read_long (&arc_count, da_file, 4) != 0)
662 okay = 0;
663 break;
666 if (strcmp (function_name_buffer, function_name) != 0
667 || arc_count != instr_arcs || chksum != cfg_checksum)
669 /* skip */
670 if (fseek (da_file, arc_count * 8, SEEK_CUR) < 0)
672 okay = 0;
673 break;
676 else
678 gcov_type tmp;
680 for (j = 0; j < arc_count; j++)
681 if (__read_gcov_type (&tmp, da_file, 8) != 0)
683 okay = 0;
684 break;
686 else
688 profile[j] += tmp;
693 if (!okay)
694 break;
698 free (function_name_buffer);
700 if (!okay)
702 fprintf (stderr, ".da file corrupted!\n");
703 free (profile);
704 abort ();
707 return profile;
710 /* Construct the program flow graph from the .bbg file, and read in the data
711 in the .da file. */
713 static void
714 create_program_flow_graph (bptr)
715 struct bb_info_list *bptr;
717 long num_blocks, number_arcs, src, dest, flag_bits, num_arcs_per_block;
718 int i;
719 struct adj_list *arcptr;
720 struct bb_info *bb_graph;
721 long cfg_checksum;
722 long instr_arcs = 0;
723 gcov_type *profile;
724 int profile_pos = 0;
725 char *function_name;
726 long function_name_len, tmp;
728 /* Read function name. */
729 __read_long (&tmp, bbg_file, 4); /* ignore -1. */
730 __read_long (&function_name_len, bbg_file, 4);
731 function_name = xmalloc (function_name_len + 1);
732 fread (function_name, 1, function_name_len + 1, bbg_file);
734 /* Skip padding. */
735 tmp = (function_name_len + 1) % 4;
737 if (tmp)
738 fseek (bbg_file, 4 - tmp, SEEK_CUR);
740 __read_long (&tmp, bbg_file, 4); /* ignore -1. */
742 /* Read the cfg checksum. */
743 __read_long (&cfg_checksum, bbg_file, 4);
745 /* Read the number of blocks. */
746 __read_long (&num_blocks, bbg_file, 4);
748 /* Create an array of size bb number of bb_info structs. */
749 bb_graph = (struct bb_info *) xcalloc (num_blocks, sizeof (struct bb_info));
751 bptr->bb_graph = bb_graph;
752 bptr->num_blocks = num_blocks;
754 /* Read and create each arc from the .bbg file. */
755 __read_long (&number_arcs, bbg_file, 4);
756 for (i = 0; i < num_blocks; i++)
758 int j;
760 __read_long (&num_arcs_per_block, bbg_file, 4);
761 for (j = 0; j < num_arcs_per_block; j++)
763 if (number_arcs-- < 0)
764 abort ();
766 src = i;
767 __read_long (&dest, bbg_file, 4);
769 arcptr = (struct adj_list *) xmalloc (sizeof (struct adj_list));
770 init_arc (arcptr, src, dest, bb_graph);
772 __read_long (&flag_bits, bbg_file, 4);
773 if (flag_bits & 0x1)
774 arcptr->on_tree++;
775 else
776 instr_arcs++;
777 arcptr->fake = !! (flag_bits & 0x2);
778 arcptr->fall_through = !! (flag_bits & 0x4);
782 if (number_arcs)
783 abort ();
785 /* Read and ignore the -1 separating the arc list from the arc list of the
786 next function. */
787 __read_long (&src, bbg_file, 4);
788 if (src != -1)
789 abort ();
791 /* Must reverse the order of all succ arcs, to ensure that they match
792 the order of the data in the .da file. */
794 for (i = 0; i < num_blocks; i++)
795 if (bb_graph[i].succ)
796 bb_graph[i].succ = reverse_arcs (bb_graph[i].succ);
798 /* Read profile from the .da file. */
800 profile = read_profile (function_name, cfg_checksum, instr_arcs);
802 /* For each arc not on the spanning tree, set its execution count from
803 the .da file. */
805 /* The first count in the .da file is the number of times that the function
806 was entered. This is the exec_count for block zero. */
808 /* This duplicates code in branch_prob in profile.c. */
810 for (i = 0; i < num_blocks; i++)
811 for (arcptr = bb_graph[i].succ; arcptr; arcptr = arcptr->succ_next)
812 if (! arcptr->on_tree)
814 arcptr->arc_count = profile[profile_pos++];
815 arcptr->count_valid = 1;
816 bb_graph[i].succ_count--;
817 bb_graph[arcptr->target].pred_count--;
819 free (profile);
820 free (function_name);
823 static void
824 solve_program_flow_graph (bptr)
825 struct bb_info_list *bptr;
827 int passes, changes;
828 gcov_type total;
829 int i;
830 struct adj_list *arcptr;
831 struct bb_info *bb_graph;
832 int num_blocks;
834 num_blocks = bptr->num_blocks;
835 bb_graph = bptr->bb_graph;
837 /* For every block in the file,
838 - if every exit/entrance arc has a known count, then set the block count
839 - if the block count is known, and every exit/entrance arc but one has
840 a known execution count, then set the count of the remaining arc
842 As arc counts are set, decrement the succ/pred count, but don't delete
843 the arc, that way we can easily tell when all arcs are known, or only
844 one arc is unknown. */
846 /* The order that the basic blocks are iterated through is important.
847 Since the code that finds spanning trees starts with block 0, low numbered
848 arcs are put on the spanning tree in preference to high numbered arcs.
849 Hence, most instrumented arcs are at the end. Graph solving works much
850 faster if we propagate numbers from the end to the start.
852 This takes an average of slightly more than 3 passes. */
854 changes = 1;
855 passes = 0;
856 while (changes)
858 passes++;
859 changes = 0;
861 for (i = num_blocks - 1; i >= 0; i--)
863 if (! bb_graph[i].count_valid)
865 if (bb_graph[i].succ_count == 0)
867 total = 0;
868 for (arcptr = bb_graph[i].succ; arcptr;
869 arcptr = arcptr->succ_next)
870 total += arcptr->arc_count;
871 bb_graph[i].exec_count = total;
872 bb_graph[i].count_valid = 1;
873 changes = 1;
875 else if (bb_graph[i].pred_count == 0)
877 total = 0;
878 for (arcptr = bb_graph[i].pred; arcptr;
879 arcptr = arcptr->pred_next)
880 total += arcptr->arc_count;
881 bb_graph[i].exec_count = total;
882 bb_graph[i].count_valid = 1;
883 changes = 1;
886 if (bb_graph[i].count_valid)
888 if (bb_graph[i].succ_count == 1)
890 total = 0;
891 /* One of the counts will be invalid, but it is zero,
892 so adding it in also doesn't hurt. */
893 for (arcptr = bb_graph[i].succ; arcptr;
894 arcptr = arcptr->succ_next)
895 total += arcptr->arc_count;
896 /* Calculate count for remaining arc by conservation. */
897 total = bb_graph[i].exec_count - total;
898 /* Search for the invalid arc, and set its count. */
899 for (arcptr = bb_graph[i].succ; arcptr;
900 arcptr = arcptr->succ_next)
901 if (! arcptr->count_valid)
902 break;
903 if (! arcptr)
904 abort ();
905 arcptr->count_valid = 1;
906 arcptr->arc_count = total;
907 bb_graph[i].succ_count--;
909 bb_graph[arcptr->target].pred_count--;
910 changes = 1;
912 if (bb_graph[i].pred_count == 1)
914 total = 0;
915 /* One of the counts will be invalid, but it is zero,
916 so adding it in also doesn't hurt. */
917 for (arcptr = bb_graph[i].pred; arcptr;
918 arcptr = arcptr->pred_next)
919 total += arcptr->arc_count;
920 /* Calculate count for remaining arc by conservation. */
921 total = bb_graph[i].exec_count - total;
922 /* Search for the invalid arc, and set its count. */
923 for (arcptr = bb_graph[i].pred; arcptr;
924 arcptr = arcptr->pred_next)
925 if (! arcptr->count_valid)
926 break;
927 if (! arcptr)
928 abort ();
929 arcptr->count_valid = 1;
930 arcptr->arc_count = total;
931 bb_graph[i].pred_count--;
933 bb_graph[arcptr->source].succ_count--;
934 changes = 1;
940 /* If the graph has been correctly solved, every block will have a
941 succ and pred count of zero. */
942 for (i = 0; i < num_blocks; i++)
943 if (bb_graph[i].succ_count || bb_graph[i].pred_count)
944 abort ();
948 static void
949 read_files ()
951 struct stat buf;
952 struct bb_info_list *list_end = 0;
953 struct bb_info_list *b_ptr;
955 while (! feof (bbg_file))
957 b_ptr = (struct bb_info_list *) xmalloc (sizeof (struct bb_info_list));
959 b_ptr->next = 0;
960 if (list_end)
961 list_end->next = b_ptr;
962 else
963 bb_graph_list = b_ptr;
964 list_end = b_ptr;
966 /* Read in the data in the .bbg file and reconstruct the program flow
967 graph for one function. */
968 create_program_flow_graph (b_ptr);
970 /* Set the EOF condition if at the end of file. */
971 ungetc (getc (bbg_file), bbg_file);
974 /* Calculate all of the basic block execution counts and branch
975 taken probabilities. */
977 for (b_ptr = bb_graph_list; b_ptr; b_ptr = b_ptr->next)
978 solve_program_flow_graph (b_ptr);
980 /* Read in all of the data from the .bb file. This info will be accessed
981 sequentially twice. */
982 stat (bb_file_name, &buf);
983 bb_data_size = buf.st_size / 4;
985 bb_data = (char *) xmalloc ((unsigned) buf.st_size);
986 fread (bb_data, sizeof (char), buf.st_size, bb_file);
988 fclose (bb_file);
989 if (da_file)
990 fclose (da_file);
991 fclose (bbg_file);
995 /* Scan the data in the .bb file to find all source files referenced,
996 and the largest line number mentioned in each one. */
998 static void
999 scan_for_source_files ()
1001 struct sourcefile *s_ptr = NULL;
1002 char *ptr;
1003 long count;
1004 long line_num;
1006 /* Search the bb_data to find:
1007 1) The number of sources files contained herein, and
1008 2) The largest line number for each source file. */
1010 ptr = bb_data;
1011 sources = 0;
1012 for (count = 0; count < bb_data_size; count++)
1014 __fetch_long (&line_num, ptr, 4);
1015 ptr += 4;
1016 if (line_num == -1)
1018 /* A source file name follows. Check to see if we already have
1019 a sourcefile structure for this file. */
1020 s_ptr = sources;
1021 while (s_ptr && strcmp (s_ptr->name, ptr))
1022 s_ptr = s_ptr->next;
1024 if (s_ptr == 0)
1026 /* No sourcefile structure for this file name exists, create
1027 a new one, and append it to the front of the sources list. */
1028 s_ptr = (struct sourcefile *) xmalloc (sizeof(struct sourcefile));
1029 s_ptr->name = xstrdup (ptr);
1030 s_ptr->maxlineno = 0;
1031 s_ptr->next = sources;
1032 sources = s_ptr;
1035 /* Scan past the file name. */
1037 long delim;
1038 do {
1039 count++;
1040 __fetch_long (&delim, ptr, 4);
1041 ptr += 4;
1042 } while (delim != line_num);
1045 else if (line_num == -2)
1047 long delim;
1049 /* A function name follows. Ignore it. */
1050 do {
1051 count++;
1052 __fetch_long (&delim, ptr, 4);
1053 ptr += 4;
1054 } while (delim != line_num);
1056 /* There will be a zero before the first file name, in which case s_ptr
1057 will still be uninitialized. So, only try to set the maxlineno
1058 field if line_num is nonzero. */
1059 else if (line_num > 0)
1061 if (s_ptr->maxlineno <= line_num)
1062 s_ptr->maxlineno = line_num + 1;
1064 else if (line_num < 0)
1066 /* Don't know what this is, but it's garbage. */
1067 abort ();
1073 /* Increment totals in FUNCTION according to arc A_PTR. */
1075 static void
1076 accumulate_branch_counts (function, a_ptr)
1077 struct coverage *function;
1078 struct arcdata *a_ptr;
1080 if (a_ptr->call_insn)
1082 function->calls++;
1083 if (a_ptr->total)
1084 function->calls_executed++;
1086 else
1088 function->branches++;
1089 if (a_ptr->total)
1090 function->branches_executed++;
1091 if (a_ptr->hits)
1092 function->branches_taken++;
1096 /* Calculate the branch taken probabilities for all arcs branches at the
1097 end of this block. */
1099 static void
1100 calculate_branch_probs (block_ptr, line_info, function)
1101 struct bb_info *block_ptr;
1102 struct line_info *line_info;
1103 struct coverage *function;
1105 gcov_type total;
1106 struct adj_list *arcptr;
1108 total = block_ptr->exec_count;
1109 for (arcptr = block_ptr->succ; arcptr; arcptr = arcptr->succ_next)
1111 struct arcdata *a_ptr;
1113 /* Ignore fall through arcs as they aren't really branches. */
1114 if (arcptr->fall_through)
1115 continue;
1117 a_ptr = (struct arcdata *) xmalloc (sizeof (struct arcdata));
1118 a_ptr->total = total;
1119 a_ptr->hits = total ? arcptr->arc_count : 0;
1120 a_ptr->call_insn = arcptr->fake;
1122 if (function)
1123 accumulate_branch_counts (function, a_ptr);
1124 /* Prepend the new branch to the list. */
1125 a_ptr->next = line_info->branches;
1126 line_info->branches = a_ptr;
1130 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1131 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1132 If DP is zero, no decimal point is printed. Only print 100% when
1133 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1134 format TOP. Return pointer to a static string. */
1136 static char const *
1137 format_hwint (top, bottom, dp)
1138 HOST_WIDEST_INT top, bottom;
1139 int dp;
1141 static char buffer[20];
1143 if (dp >= 0)
1145 float ratio = bottom ? (float)top / bottom : 0;
1146 int ix;
1147 unsigned limit = 100;
1148 unsigned percent;
1150 for (ix = dp; ix--; )
1151 limit *= 10;
1153 percent = (unsigned) (ratio * limit + (float)0.5);
1154 if (percent <= 0 && top)
1155 percent = 1;
1156 else if (percent >= limit && top != bottom)
1157 percent = limit - 1;
1158 ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1159 if (dp)
1161 dp++;
1164 buffer[ix+1] = buffer[ix];
1165 ix--;
1167 while (dp--);
1168 buffer[ix + 1] = '.';
1171 else
1172 sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, top);
1174 return buffer;
1178 /* Output summary info for a function. */
1180 static void
1181 function_summary (function, title)
1182 struct coverage *function;
1183 const char *title;
1185 if (function->lines)
1186 fnotice (stdout, "%s of %d lines executed in %s %s\n",
1187 format_hwint (function->lines_executed,
1188 function->lines, 2),
1189 function->lines, title, function->name);
1190 else
1191 fnotice (stdout, "No executable lines in %s %s\n",
1192 title, function->name);
1194 if (output_branch_probs)
1196 if (function->branches)
1198 fnotice (stdout, "%s of %d branches executed in %s %s\n",
1199 format_hwint (function->branches_executed,
1200 function->branches, 2),
1201 function->branches, title, function->name);
1202 fnotice (stdout,
1203 "%s of %d branches taken at least once in %s %s\n",
1204 format_hwint (function->branches_taken,
1205 function->branches, 2),
1206 function->branches, title, function->name);
1208 else
1209 fnotice (stdout, "No branches in %s %s\n", title, function->name);
1210 if (function->calls)
1211 fnotice (stdout, "%s of %d calls executed in %s %s\n",
1212 format_hwint (function->calls_executed,
1213 function->calls, 2),
1214 function->calls, title, function->name);
1215 else
1216 fnotice (stdout, "No calls in %s %s\n", title, function->name);
1220 /* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
1221 affect name generation. With preserve_paths we create a filename
1222 from all path components of the source file, replacing '/' with
1223 '#', without it we simply take the basename component. With
1224 long_output_names we prepend the processed name of the input file
1225 to each output name (except when the current source file is the
1226 input file, so you don't get a double concatenation). The two
1227 components are separated by '##'. Also '.' filename components are
1228 removed and '..' components are renamed to '^'. */
1230 static char *
1231 make_gcov_file_name (src_name)
1232 char *src_name;
1234 char *cptr;
1235 char *name = xmalloc (strlen (src_name) + strlen (input_file_name) + 10);
1237 name[0] = 0;
1238 if (output_long_names && strcmp (src_name, input_file_name))
1240 /* Generate the input filename part. */
1241 cptr = preserve_paths ? NULL : strrchr (input_file_name, '/');
1242 cptr = cptr ? cptr + 1 : input_file_name;
1243 strcat (name, cptr);
1244 strcat (name, "##");
1247 /* Generate the source filename part. */
1248 cptr = preserve_paths ? NULL : strrchr (src_name, '/');
1249 cptr = cptr ? cptr + 1 : src_name;
1250 strcat (name, cptr);
1252 if (preserve_paths)
1254 /* Convert '/' to '#', remove '/./', convert '/../' to '/^/' */
1255 char *prev;
1257 for (cptr = name; (cptr = strchr ((prev = cptr), '/'));)
1259 unsigned shift = 0;
1261 if (prev + 1 == cptr && prev[0] == '.')
1263 /* Remove '.' */
1264 shift = 2;
1266 else if (prev + 2 == cptr && prev[0] == '.' && prev[1] == '.')
1268 /* Convert '..' */
1269 shift = 1;
1270 prev[1] = '^';
1272 else
1273 *cptr++ = '#';
1274 if (shift)
1276 cptr = prev;
1278 prev[0] = prev[shift];
1279 while (*prev++);
1284 /* Don't strip off the ending for compatibility with tcov, since
1285 this results in confusion if there is more than one file with the
1286 same basename, e.g. tmp.c and tmp.h. */
1287 strcat (name, ".gcov");
1288 return name;
1291 /* Scan through the bb_data, and when the file name matches the
1292 source file name, then for each following line number, increment
1293 the line number execution count indicated by the execution count of
1294 the appropriate basic block. */
1296 static void
1297 init_line_info (line_info, total, maxlineno)
1298 struct line_info *line_info;
1299 struct coverage *total;
1300 long maxlineno;
1302 long block_num = 0; /* current block number */
1303 struct bb_info *block_ptr = NULL; /* current block ptr */
1304 struct coverage function;
1305 struct coverage *func_ptr = NULL;
1306 struct bb_info_list *current_graph = NULL; /* Graph for current function. */
1307 int is_this_file = 0; /* We're scanning a block from the desired file. */
1308 char *ptr = bb_data;
1309 long count;
1310 long line_num;
1311 struct line_info *line_ptr = 0; /* line info ptr. */
1313 memset (&function, 0, sizeof (function));
1314 if (output_function_summary)
1315 func_ptr = &function;
1317 for (count = 0; count < bb_data_size; count++)
1319 __fetch_long (&line_num, ptr, 4);
1320 ptr += 4;
1321 if (line_num < 0)
1323 long delim;
1325 if (line_num == -1)
1327 /* Marks the beginning of a file name. Check to see
1328 whether this is the filename we are currently
1329 collecting data for. */
1330 is_this_file = !strcmp (total->name, ptr);
1332 else if (line_num == -2)
1334 /* Marks the start of a new function. Advance to the
1335 next program flow graph. */
1336 if (!current_graph)
1337 current_graph = bb_graph_list;
1338 else
1340 if (block_num == current_graph->num_blocks - 1)
1341 /* Last block falls through to exit. */
1343 else if (block_num == current_graph->num_blocks - 2)
1345 if (output_branch_probs && is_this_file)
1346 calculate_branch_probs (block_ptr, line_ptr, func_ptr);
1348 else
1350 fnotice (stderr,
1351 "didn't use all bb entries of graph, function %s\n",
1352 function.name);
1353 fnotice (stderr, "block_num = %ld, num_blocks = %d\n",
1354 block_num, current_graph->num_blocks);
1356 if (func_ptr && is_this_file)
1357 function_summary (func_ptr, "function");
1358 current_graph = current_graph->next;
1360 block_num = 0;
1361 block_ptr = current_graph->bb_graph;
1362 memset (&function, 0, sizeof (function));
1363 function.name = ptr;
1365 else
1367 fnotice (stderr, "ERROR: unexpected line number %ld\n", line_num);
1368 abort ();
1371 /* Scan past the string. */
1372 for (delim = 0; delim != line_num; count++)
1374 __fetch_long (&delim, ptr, 4);
1375 ptr += 4;
1378 else if (!line_num)
1380 /* Marks the end of a block. */
1381 if (block_num >= current_graph->num_blocks)
1383 fnotice (stderr, "ERROR: too many basic blocks in function %s\n",
1384 function.name);
1385 abort ();
1388 if (output_branch_probs && is_this_file)
1389 calculate_branch_probs (block_ptr, line_ptr, func_ptr);
1391 block_num++;
1392 block_ptr++;
1394 else if (is_this_file)
1396 if (line_num >= maxlineno)
1398 fnotice (stderr, "ERROR: out of range line number in function %s\n",
1399 function.name);
1400 abort ();
1403 line_ptr = &line_info[line_num];
1404 if (func_ptr)
1406 if (!line_ptr->exists)
1407 func_ptr->lines++;
1408 if (!line_ptr->count && block_ptr->exec_count)
1409 func_ptr->lines_executed++;
1412 /* Accumulate execution data for this line number. */
1413 line_ptr->count += block_ptr->exec_count;
1414 line_ptr->exists = 1;
1418 if (func_ptr && is_this_file)
1419 function_summary (func_ptr, "function");
1421 /* Calculate summary test coverage statistics. */
1422 for (line_num = 1, line_ptr = &line_info[line_num];
1423 line_num < maxlineno; line_num++, line_ptr++)
1425 struct arcdata *a_ptr, *prev, *next;
1427 if (line_ptr->exists)
1429 total->lines++;
1430 if (line_ptr->count)
1431 total->lines_executed++;
1434 /* Total and reverse the branch information. */
1435 for (a_ptr = line_ptr->branches, prev = NULL; a_ptr; a_ptr = next)
1437 next = a_ptr->next;
1438 a_ptr->next = prev;
1439 prev = a_ptr;
1441 accumulate_branch_counts (total, a_ptr);
1443 line_ptr->branches = prev;
1447 /* Read in the source file one line at a time, and output that line to
1448 the gcov file preceded by its execution count and other
1449 information. */
1451 static void
1452 output_line_info (gcov_file, line_info, total, maxlineno)
1453 FILE *gcov_file;
1454 const struct line_info *line_info;
1455 const struct coverage *total;
1456 long maxlineno;
1458 FILE *source_file;
1459 long line_num; /* current line number */
1460 const struct line_info *line_ptr; /* current line info ptr. */
1461 char string[STRING_SIZE]; /* line buffer. */
1462 char const *retval = ""; /* status of source file reading. */
1464 fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, total->name);
1465 fprintf (gcov_file, "%9s:%5d:Object:%s\n", "-", 0, bb_file_name);
1467 source_file = fopen (total->name, "r");
1468 if (!source_file)
1470 fnotice (stderr, "Could not open source file %s.\n", total->name);
1471 retval = NULL;
1473 else
1475 struct stat status;
1477 if (!fstat (fileno (source_file), &status)
1478 && status.st_mtime > bb_file_time)
1480 fnotice (stderr, "Warning: source file %s is newer than %s\n",
1481 total->name, bb_file_name);
1482 fprintf (gcov_file, "%9s:%5d:Source is newer than compiler output\n",
1483 "-", 0);
1487 for (line_num = 1, line_ptr = &line_info[line_num];
1488 line_num < maxlineno; line_num++, line_ptr++)
1490 /* For lines which don't exist in the .bb file, print '-' before
1491 the source line. For lines which exist but were never
1492 executed, print '#####' before the source line. Otherwise,
1493 print the execution count before the source line. There are
1494 16 spaces of indentation added before the source line so that
1495 tabs won't be messed up. */
1496 fprintf (gcov_file, "%9s:%5ld:",
1497 !line_ptr->exists ? "-"
1498 : !line_ptr->count ? "#####"
1499 : format_hwint (line_ptr->count, 0, -1), line_num);
1501 if (retval)
1503 /* Copy source line. */
1506 retval = fgets (string, STRING_SIZE, source_file);
1507 if (!retval)
1509 fnotice (stderr,
1510 "Unexpected EOF while reading source file %s.\n",
1511 total->name);
1512 break;
1514 fputs (retval, gcov_file);
1516 while (!retval[0] || retval[strlen (retval) - 1] != '\n');
1518 if (!retval)
1519 fputs ("??\n", gcov_file);
1521 if (output_branch_probs)
1523 int i;
1524 struct arcdata *a_ptr;
1526 for (i = 0, a_ptr = line_ptr->branches; a_ptr;
1527 a_ptr = a_ptr->next, i++)
1529 if (a_ptr->call_insn)
1531 if (a_ptr->total == 0)
1532 fnotice (gcov_file, "call %2d never executed\n", i);
1533 else
1534 fnotice
1535 (gcov_file, "call %2d returns %s\n", i,
1536 format_hwint (a_ptr->total - a_ptr->hits,
1537 a_ptr->total,
1538 -output_branch_counts));
1540 else
1542 if (a_ptr->total == 0)
1543 fnotice (gcov_file, "branch %2d never executed\n", i);
1544 else
1545 fnotice
1546 (gcov_file, "branch %2d taken %s\n", i,
1547 format_hwint (a_ptr->hits, a_ptr->total,
1548 -output_branch_counts));
1554 /* Handle all remaining source lines. There may be lines after the
1555 last line of code. */
1556 if (retval)
1558 for (; (retval = fgets (string, STRING_SIZE, source_file)); line_num++)
1560 fprintf (gcov_file, "%9s:%5ld:%s", "-", line_num, retval);
1562 while (!retval[0] || retval[strlen (retval) - 1] != '\n')
1564 retval = fgets (string, STRING_SIZE, source_file);
1565 if (!retval)
1566 break;
1567 fputs (retval, gcov_file);
1572 if (source_file)
1573 fclose (source_file);
1576 /* Calculate line execution counts, and output a .gcov file for source
1577 file S_PTR. Allocate an array big enough to hold a count for each
1578 line. Scan through the bb_data, and when the file name matches the
1579 current file name, then for each following line number, increment
1580 the line number execution count indicated by the execution count of
1581 the appropriate basic block. */
1583 static void
1584 output_data (s_ptr)
1585 struct sourcefile *s_ptr;
1587 struct line_info *line_info /* line info data */
1588 = (struct line_info *) xcalloc (s_ptr->maxlineno,
1589 sizeof (struct line_info));
1590 long line_num;
1591 struct coverage total;
1593 memset (&total, 0, sizeof (total));
1594 total.name = s_ptr->name;
1596 init_line_info (line_info, &total, s_ptr->maxlineno);
1597 function_summary (&total, "file");
1599 if (output_gcov_file)
1601 /* Now the statistics are ready. Read in the source file one
1602 line at a time, and output that line to the gcov file
1603 preceded by its execution information. */
1605 char *gcov_file_name = make_gcov_file_name (total.name);
1606 FILE *gcov_file = fopen (gcov_file_name, "w");
1608 if (gcov_file)
1610 fnotice (stdout, "Creating %s.\n", gcov_file_name);
1611 output_line_info (gcov_file, line_info, &total, s_ptr->maxlineno);
1612 if (ferror (gcov_file))
1613 fnotice (stderr, "Error writing output file %s.\n",
1614 gcov_file_name);
1615 fclose (gcov_file);
1617 else
1618 fnotice (stderr, "Could not open output file %s.\n", gcov_file_name);
1619 free (gcov_file_name);
1622 /* Free data. */
1623 for (line_num = 1; line_num != s_ptr->maxlineno; line_num++)
1625 struct arcdata *branch, *next;
1627 for (branch = line_info[line_num].branches; branch; branch = next)
1629 next = branch->next;
1630 free (branch);
1633 free (line_info);