* gbl-ctors.h: Fix formatting.
[official-gcc.git] / gcc / gcov.c
blob01e1a1dd77e93763713f256094a3eb3d09b5fadf
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 /* Name and file pointer of the input file for the basic block graph. */
165 static char *bbg_file_name;
166 static FILE *bbg_file;
168 /* Name and file pointer of the input file for the arc count data. */
170 static char *da_file_name;
171 static FILE *da_file;
173 /* Name and file pointer of the input file for the basic block line counts. */
175 static char *bb_file_name;
176 static FILE *bb_file;
178 /* Holds the entire contents of the bb_file read into memory. */
180 static char *bb_data;
182 /* Size of bb_data array in longs. */
184 static long bb_data_size;
186 /* Name and file pointer of the output file. */
188 static char *gcov_file_name;
189 static FILE *gcov_file;
191 /* Name of the file mentioned on the command line. */
193 static char *input_file_name = 0;
195 /* Output branch probabilities if true. */
197 static int output_branch_probs = 0;
199 /* Output a gcov file if this is true. This is on by default, and can
200 be turned off by the -n option. */
202 static int output_gcov_file = 1;
204 /* For included files, make the gcov output file name include the name of
205 the input source file. For example, if x.h is included in a.c, then the
206 output file name is a.c.x.h.gcov instead of x.h.gcov. This works only
207 when a single source file is specified. */
209 static int output_long_names = 0;
211 /* Output summary info for each function. */
213 static int output_function_summary = 0;
215 /* Object directory file prefix. This is the directory where .bb and .bbg
216 files are looked for, if non-zero. */
218 static char *object_directory = 0;
220 /* Output the number of times a branch was taken as opposed to the percentage
221 of times it was taken. Turned on by the -c option */
223 static int output_branch_counts = 0;
225 /* Forward declarations. */
226 static void process_args PARAMS ((int, char **));
227 static void open_files PARAMS ((void));
228 static void read_files PARAMS ((void));
229 static void scan_for_source_files PARAMS ((void));
230 static void output_data PARAMS ((void));
231 static void print_usage PARAMS ((int)) ATTRIBUTE_NORETURN;
232 static void print_version PARAMS ((void)) ATTRIBUTE_NORETURN;
233 static void init_arc PARAMS ((struct adj_list *, int, int, struct bb_info *));
234 static struct adj_list *reverse_arcs PARAMS ((struct adj_list *));
235 static gcov_type *read_profile PARAMS ((char *, long, int));
236 static void create_program_flow_graph PARAMS ((struct bb_info_list *));
237 static void solve_program_flow_graph PARAMS ((struct bb_info_list *));
238 static void calculate_branch_probs PARAMS ((struct bb_info_list *, int,
239 struct arcdata **, int));
240 static void function_summary PARAMS ((void));
242 extern int main PARAMS ((int, char **));
245 main (argc, argv)
246 int argc;
247 char **argv;
249 gcc_init_libintl ();
251 process_args (argc, argv);
253 open_files ();
255 read_files ();
257 scan_for_source_files ();
259 output_data ();
261 return 0;
264 static void fnotice PARAMS ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2;
265 static void
266 fnotice VPARAMS ((FILE *file, const char *msgid, ...))
268 VA_OPEN (ap, msgid);
269 VA_FIXEDARG (ap, FILE *, file);
270 VA_FIXEDARG (ap, const char *, msgid);
272 vfprintf (file, _(msgid), ap);
273 VA_CLOSE (ap);
276 /* More 'friendly' abort that prints the line and file.
277 config.h can #define abort fancy_abort if you like that sort of thing. */
278 extern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN;
280 void
281 fancy_abort ()
283 fnotice (stderr, "Internal gcov abort.\n");
284 exit (FATAL_EXIT_CODE);
287 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
288 otherwise the output of --help. */
290 static void
291 print_usage (error_p)
292 int error_p;
294 FILE *file = error_p ? stderr : stdout;
295 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
296 fnotice (file, "Usage: gcov [OPTION]... SOURCEFILE\n\n");
297 fnotice (file, "Print code coverage information.\n\n");
298 fnotice (file, " -h, --help Print this help, then exit\n");
299 fnotice (file, " -v, --version Print version number, then exit\n");
300 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
301 fnotice (file, " -c, --branch-counts Given counts of branches taken\n\
302 rather than percentages\n");
303 fnotice (file, " -n, --no-output Do not create an output file\n");
304 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
305 source files\n");
306 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
307 fnotice (file, " -o, --object-directory OBJDIR Search for object files in OBJDIR\n");
308 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
309 GCCBUGURL);
310 exit (status);
313 /* Print version information and exit. */
315 static void
316 print_version ()
318 fnotice (stdout, "gcov (GCC) %s\n", version_string);
319 fnotice (stdout, "Copyright (C) 2001 Free Software Foundation, Inc.\n");
320 fnotice (stdout,
321 "This is free software; see the source for copying conditions. There is NO\n\
322 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
323 exit (SUCCESS_EXIT_CODE);
326 static const struct option options[] =
328 { "help", no_argument, NULL, 'h' },
329 { "version", no_argument, NULL, 'v' },
330 { "branch-probabilities", no_argument, NULL, 'b' },
331 { "branch-counts", no_argument, NULL, 'c' },
332 { "no-output", no_argument, NULL, 'n' },
333 { "long-file-names", no_argument, NULL, 'l' },
334 { "function-summaries", no_argument, NULL, 'f' },
335 { "object-directory", required_argument, NULL, 'o' }
338 /* Parse the command line. */
340 static void
341 process_args (argc, argv)
342 int argc;
343 char **argv;
345 int opt;
347 while ((opt = getopt_long (argc, argv, "hvbclnfo:", options, NULL)) != -1)
349 switch (opt)
351 case 'h':
352 print_usage (false);
353 /* print_usage will exit. */
354 case 'v':
355 print_version ();
356 /* print_version will exit. */
357 case 'b':
358 output_branch_probs = 1;
359 break;
360 case 'c':
361 output_branch_counts = 1;
362 break;
363 case 'n':
364 output_gcov_file = 0;
365 break;
366 case 'l':
367 output_long_names = 1;
368 break;
369 case 'f':
370 output_function_summary = 1;
371 break;
372 case 'o':
373 object_directory = optarg;
374 break;
375 default:
376 print_usage (true);
377 /* print_usage will exit. */
381 if (optind != argc - 1)
382 print_usage (true);
384 input_file_name = argv[optind];
388 /* Find and open the .bb, .da, and .bbg files. */
390 static void
391 open_files ()
393 int count, objdir_count;
394 char *cptr;
396 /* Determine the names of the .bb, .bbg, and .da files. Strip off the
397 extension, if any, and append the new extensions. */
398 count = strlen (input_file_name);
399 if (object_directory)
400 objdir_count = strlen (object_directory);
401 else
402 objdir_count = 0;
404 da_file_name = xmalloc (count + objdir_count + 4);
405 bb_file_name = xmalloc (count + objdir_count + 4);
406 bbg_file_name = xmalloc (count + objdir_count + 5);
408 if (object_directory)
410 strcpy (da_file_name, object_directory);
411 strcpy (bb_file_name, object_directory);
412 strcpy (bbg_file_name, object_directory);
414 if (object_directory[objdir_count - 1] != '/')
416 strcat (da_file_name, "/");
417 strcat (bb_file_name, "/");
418 strcat (bbg_file_name, "/");
421 cptr = strrchr (input_file_name, '/');
422 if (cptr)
424 strcat (da_file_name, cptr + 1);
425 strcat (bb_file_name, cptr + 1);
426 strcat (bbg_file_name, cptr + 1);
428 else
430 strcat (da_file_name, input_file_name);
431 strcat (bb_file_name, input_file_name);
432 strcat (bbg_file_name, input_file_name);
435 else
437 strcpy (da_file_name, input_file_name);
438 strcpy (bb_file_name, input_file_name);
439 strcpy (bbg_file_name, input_file_name);
442 cptr = strrchr (bb_file_name, '.');
443 if (cptr)
444 strcpy (cptr, ".bb");
445 else
446 strcat (bb_file_name, ".bb");
448 cptr = strrchr (da_file_name, '.');
449 if (cptr)
450 strcpy (cptr, ".da");
451 else
452 strcat (da_file_name, ".da");
454 cptr = strrchr (bbg_file_name, '.');
455 if (cptr)
456 strcpy (cptr, ".bbg");
457 else
458 strcat (bbg_file_name, ".bbg");
460 bb_file = fopen (bb_file_name, "rb");
461 if (bb_file == NULL)
463 fnotice (stderr, "Could not open basic block file %s.\n", bb_file_name);
464 exit (FATAL_EXIT_CODE);
467 /* If none of the functions in the file were executed, then there won't
468 be a .da file. Just assume that all counts are zero in this case. */
469 da_file = fopen (da_file_name, "rb");
470 if (da_file == NULL)
472 fnotice (stderr, "Could not open data file %s.\n", da_file_name);
473 fnotice (stderr, "Assuming that all execution counts are zero.\n");
476 bbg_file = fopen (bbg_file_name, "rb");
477 if (bbg_file == NULL)
479 fnotice (stderr, "Could not open program flow graph file %s.\n",
480 bbg_file_name);
481 exit (FATAL_EXIT_CODE);
484 /* Check for empty .bbg file. This indicates that there is no executable
485 code in this source file. */
486 /* Set the EOF condition if at the end of file. */
487 ungetc (getc (bbg_file), bbg_file);
488 if (feof (bbg_file))
490 fnotice (stderr, "No executable code associated with file %s.\n",
491 input_file_name);
492 exit (FATAL_EXIT_CODE);
496 /* Initialize a new arc. */
498 static void
499 init_arc (arcptr, source, target, bb_graph)
500 struct adj_list *arcptr;
501 int source, target;
502 struct bb_info *bb_graph;
504 arcptr->target = target;
505 arcptr->source = source;
507 arcptr->arc_count = 0;
508 arcptr->count_valid = 0;
509 arcptr->on_tree = 0;
510 arcptr->fake = 0;
511 arcptr->fall_through = 0;
513 arcptr->succ_next = bb_graph[source].succ;
514 bb_graph[source].succ = arcptr;
515 bb_graph[source].succ_count++;
517 arcptr->pred_next = bb_graph[target].pred;
518 bb_graph[target].pred = arcptr;
519 bb_graph[target].pred_count++;
523 /* Reverse the arcs on an arc list. */
525 static struct adj_list *
526 reverse_arcs (arcptr)
527 struct adj_list *arcptr;
529 struct adj_list *prev = 0;
530 struct adj_list *next;
532 for ( ; arcptr; arcptr = next)
534 next = arcptr->succ_next;
535 arcptr->succ_next = prev;
536 prev = arcptr;
539 return prev;
542 /* Reads profiles from the .da file and compute a hybrid profile. */
544 static gcov_type *
545 read_profile (function_name, cfg_checksum, instr_arcs)
546 char *function_name;
547 long cfg_checksum;
548 int instr_arcs;
550 int i;
551 int okay = 1;
552 gcov_type *profile;
553 char *function_name_buffer;
554 int function_name_buffer_len;
556 profile = xmalloc (sizeof (gcov_type) * instr_arcs);
557 rewind (da_file);
558 function_name_buffer_len = strlen (function_name) + 1;
559 function_name_buffer = xmalloc (function_name_buffer_len + 1);
561 for (i = 0; i < instr_arcs; i++)
562 profile[i] = 0;
564 if (!da_file)
565 return profile;
567 while (1)
569 long magic, extra_bytes;
570 long func_count;
571 int i;
573 if (__read_long (&magic, da_file, 4) != 0)
574 break;
576 if (magic != -123)
578 okay = 0;
579 break;
582 if (__read_long (&func_count, da_file, 4) != 0)
584 okay = 0;
585 break;
588 if (__read_long (&extra_bytes, da_file, 4) != 0)
590 okay = 0;
591 break;
594 /* skip extra data emited by __bb_exit_func. */
595 fseek (da_file, extra_bytes, SEEK_CUR);
597 for (i = 0; i < func_count; i++)
599 long arc_count;
600 long chksum;
601 int j;
603 if (__read_gcov_string
604 (function_name_buffer, function_name_buffer_len, da_file,
605 -1) != 0)
607 okay = 0;
608 break;
611 if (__read_long (&chksum, da_file, 4) != 0)
613 okay = 0;
614 break;
617 if (__read_long (&arc_count, da_file, 4) != 0)
619 okay = 0;
620 break;
623 if (strcmp (function_name_buffer, function_name) != 0
624 || arc_count != instr_arcs || chksum != cfg_checksum)
626 /* skip */
627 if (fseek (da_file, arc_count * 8, SEEK_CUR) < 0)
629 okay = 0;
630 break;
633 else
635 gcov_type tmp;
637 for (j = 0; j < arc_count; j++)
638 if (__read_gcov_type (&tmp, da_file, 8) != 0)
640 okay = 0;
641 break;
643 else
645 profile[j] += tmp;
650 if (!okay)
651 break;
655 free (function_name_buffer);
657 if (!okay)
659 fprintf (stderr, ".da file corrupted!\n");
660 free (profile);
661 abort ();
664 return profile;
667 /* Construct the program flow graph from the .bbg file, and read in the data
668 in the .da file. */
670 static void
671 create_program_flow_graph (bptr)
672 struct bb_info_list *bptr;
674 long num_blocks, number_arcs, src, dest, flag_bits, num_arcs_per_block;
675 int i;
676 struct adj_list *arcptr;
677 struct bb_info *bb_graph;
678 long cfg_checksum;
679 long instr_arcs = 0;
680 gcov_type *profile;
681 int profile_pos = 0;
682 char *function_name;
683 long function_name_len, tmp;
685 /* Read function name. */
686 __read_long (&tmp, bbg_file, 4); /* ignore -1. */
687 __read_long (&function_name_len, bbg_file, 4);
688 function_name = xmalloc (function_name_len + 1);
689 fread (function_name, 1, function_name_len + 1, bbg_file);
691 /* Skip padding. */
692 tmp = (function_name_len + 1) % 4;
694 if (tmp)
695 fseek (bbg_file, 4 - tmp, SEEK_CUR);
697 __read_long (&tmp, bbg_file, 4); /* ignore -1. */
699 /* Read the cfg checksum. */
700 __read_long (&cfg_checksum, bbg_file, 4);
702 /* Read the number of blocks. */
703 __read_long (&num_blocks, bbg_file, 4);
705 /* Create an array of size bb number of bb_info structs. */
706 bb_graph = (struct bb_info *) xcalloc (num_blocks, sizeof (struct bb_info));
708 bptr->bb_graph = bb_graph;
709 bptr->num_blocks = num_blocks;
711 /* Read and create each arc from the .bbg file. */
712 __read_long (&number_arcs, bbg_file, 4);
713 for (i = 0; i < num_blocks; i++)
715 int j;
717 __read_long (&num_arcs_per_block, bbg_file, 4);
718 for (j = 0; j < num_arcs_per_block; j++)
720 if (number_arcs-- < 0)
721 abort ();
723 src = i;
724 __read_long (&dest, bbg_file, 4);
726 arcptr = (struct adj_list *) xmalloc (sizeof (struct adj_list));
727 init_arc (arcptr, src, dest, bb_graph);
729 __read_long (&flag_bits, bbg_file, 4);
730 if (flag_bits & 0x1)
731 arcptr->on_tree++;
732 else
733 instr_arcs++;
734 arcptr->fake = !! (flag_bits & 0x2);
735 arcptr->fall_through = !! (flag_bits & 0x4);
739 if (number_arcs)
740 abort ();
742 /* Read and ignore the -1 separating the arc list from the arc list of the
743 next function. */
744 __read_long (&src, bbg_file, 4);
745 if (src != -1)
746 abort ();
748 /* Must reverse the order of all succ arcs, to ensure that they match
749 the order of the data in the .da file. */
751 for (i = 0; i < num_blocks; i++)
752 if (bb_graph[i].succ)
753 bb_graph[i].succ = reverse_arcs (bb_graph[i].succ);
755 /* Read profile from the .da file. */
757 profile = read_profile (function_name, cfg_checksum, instr_arcs);
759 /* For each arc not on the spanning tree, set its execution count from
760 the .da file. */
762 /* The first count in the .da file is the number of times that the function
763 was entered. This is the exec_count for block zero. */
765 /* This duplicates code in branch_prob in profile.c. */
767 for (i = 0; i < num_blocks; i++)
768 for (arcptr = bb_graph[i].succ; arcptr; arcptr = arcptr->succ_next)
769 if (! arcptr->on_tree)
771 arcptr->arc_count = profile[profile_pos++];
772 arcptr->count_valid = 1;
773 bb_graph[i].succ_count--;
774 bb_graph[arcptr->target].pred_count--;
776 free (profile);
777 free (function_name);
780 static void
781 solve_program_flow_graph (bptr)
782 struct bb_info_list *bptr;
784 int passes, changes;
785 gcov_type total;
786 int i;
787 struct adj_list *arcptr;
788 struct bb_info *bb_graph;
789 int num_blocks;
791 num_blocks = bptr->num_blocks;
792 bb_graph = bptr->bb_graph;
794 /* For every block in the file,
795 - if every exit/entrance arc has a known count, then set the block count
796 - if the block count is known, and every exit/entrance arc but one has
797 a known execution count, then set the count of the remaining arc
799 As arc counts are set, decrement the succ/pred count, but don't delete
800 the arc, that way we can easily tell when all arcs are known, or only
801 one arc is unknown. */
803 /* The order that the basic blocks are iterated through is important.
804 Since the code that finds spanning trees starts with block 0, low numbered
805 arcs are put on the spanning tree in preference to high numbered arcs.
806 Hence, most instrumented arcs are at the end. Graph solving works much
807 faster if we propagate numbers from the end to the start.
809 This takes an average of slightly more than 3 passes. */
811 changes = 1;
812 passes = 0;
813 while (changes)
815 passes++;
816 changes = 0;
818 for (i = num_blocks - 1; i >= 0; i--)
820 if (! bb_graph[i].count_valid)
822 if (bb_graph[i].succ_count == 0)
824 total = 0;
825 for (arcptr = bb_graph[i].succ; arcptr;
826 arcptr = arcptr->succ_next)
827 total += arcptr->arc_count;
828 bb_graph[i].exec_count = total;
829 bb_graph[i].count_valid = 1;
830 changes = 1;
832 else if (bb_graph[i].pred_count == 0)
834 total = 0;
835 for (arcptr = bb_graph[i].pred; arcptr;
836 arcptr = arcptr->pred_next)
837 total += arcptr->arc_count;
838 bb_graph[i].exec_count = total;
839 bb_graph[i].count_valid = 1;
840 changes = 1;
843 if (bb_graph[i].count_valid)
845 if (bb_graph[i].succ_count == 1)
847 total = 0;
848 /* One of the counts will be invalid, but it is zero,
849 so adding it in also doesn't hurt. */
850 for (arcptr = bb_graph[i].succ; arcptr;
851 arcptr = arcptr->succ_next)
852 total += arcptr->arc_count;
853 /* Calculate count for remaining arc by conservation. */
854 total = bb_graph[i].exec_count - total;
855 /* Search for the invalid arc, and set its count. */
856 for (arcptr = bb_graph[i].succ; arcptr;
857 arcptr = arcptr->succ_next)
858 if (! arcptr->count_valid)
859 break;
860 if (! arcptr)
861 abort ();
862 arcptr->count_valid = 1;
863 arcptr->arc_count = total;
864 bb_graph[i].succ_count--;
866 bb_graph[arcptr->target].pred_count--;
867 changes = 1;
869 if (bb_graph[i].pred_count == 1)
871 total = 0;
872 /* One of the counts will be invalid, but it is zero,
873 so adding it in also doesn't hurt. */
874 for (arcptr = bb_graph[i].pred; arcptr;
875 arcptr = arcptr->pred_next)
876 total += arcptr->arc_count;
877 /* Calculate count for remaining arc by conservation. */
878 total = bb_graph[i].exec_count - total;
879 /* Search for the invalid arc, and set its count. */
880 for (arcptr = bb_graph[i].pred; arcptr;
881 arcptr = arcptr->pred_next)
882 if (! arcptr->count_valid)
883 break;
884 if (! arcptr)
885 abort ();
886 arcptr->count_valid = 1;
887 arcptr->arc_count = total;
888 bb_graph[i].pred_count--;
890 bb_graph[arcptr->source].succ_count--;
891 changes = 1;
897 /* If the graph has been correctly solved, every block will have a
898 succ and pred count of zero. */
899 for (i = 0; i < num_blocks; i++)
900 if (bb_graph[i].succ_count || bb_graph[i].pred_count)
901 abort ();
905 static void
906 read_files ()
908 struct stat buf;
909 struct bb_info_list *list_end = 0;
910 struct bb_info_list *b_ptr;
912 while (! feof (bbg_file))
914 b_ptr = (struct bb_info_list *) xmalloc (sizeof (struct bb_info_list));
916 b_ptr->next = 0;
917 if (list_end)
918 list_end->next = b_ptr;
919 else
920 bb_graph_list = b_ptr;
921 list_end = b_ptr;
923 /* Read in the data in the .bbg file and reconstruct the program flow
924 graph for one function. */
925 create_program_flow_graph (b_ptr);
927 /* Set the EOF condition if at the end of file. */
928 ungetc (getc (bbg_file), bbg_file);
931 /* Calculate all of the basic block execution counts and branch
932 taken probabilities. */
934 for (b_ptr = bb_graph_list; b_ptr; b_ptr = b_ptr->next)
935 solve_program_flow_graph (b_ptr);
937 /* Read in all of the data from the .bb file. This info will be accessed
938 sequentially twice. */
939 stat (bb_file_name, &buf);
940 bb_data_size = buf.st_size / 4;
942 bb_data = (char *) xmalloc ((unsigned) buf.st_size);
943 fread (bb_data, sizeof (char), buf.st_size, bb_file);
945 fclose (bb_file);
946 if (da_file)
947 fclose (da_file);
948 fclose (bbg_file);
952 /* Scan the data in the .bb file to find all source files referenced,
953 and the largest line number mentioned in each one. */
955 static void
956 scan_for_source_files ()
958 struct sourcefile *s_ptr = NULL;
959 char *ptr;
960 long count;
961 long line_num;
963 /* Search the bb_data to find:
964 1) The number of sources files contained herein, and
965 2) The largest line number for each source file. */
967 ptr = bb_data;
968 sources = 0;
969 for (count = 0; count < bb_data_size; count++)
971 __fetch_long (&line_num, ptr, 4);
972 ptr += 4;
973 if (line_num == -1)
975 /* A source file name follows. Check to see if we already have
976 a sourcefile structure for this file. */
977 s_ptr = sources;
978 while (s_ptr && strcmp (s_ptr->name, ptr))
979 s_ptr = s_ptr->next;
981 if (s_ptr == 0)
983 /* No sourcefile structure for this file name exists, create
984 a new one, and append it to the front of the sources list. */
985 s_ptr = (struct sourcefile *) xmalloc (sizeof(struct sourcefile));
986 s_ptr->name = xstrdup (ptr);
987 s_ptr->maxlineno = 0;
988 s_ptr->next = sources;
989 sources = s_ptr;
992 /* Scan past the file name. */
994 long delim;
995 do {
996 count++;
997 __fetch_long (&delim, ptr, 4);
998 ptr += 4;
999 } while (delim != line_num);
1002 else if (line_num == -2)
1004 long delim;
1006 /* A function name follows. Ignore it. */
1007 do {
1008 count++;
1009 __fetch_long (&delim, ptr, 4);
1010 ptr += 4;
1011 } while (delim != line_num);
1013 /* There will be a zero before the first file name, in which case s_ptr
1014 will still be uninitialized. So, only try to set the maxlineno
1015 field if line_num is non-zero. */
1016 else if (line_num > 0)
1018 if (s_ptr->maxlineno <= line_num)
1019 s_ptr->maxlineno = line_num + 1;
1021 else if (line_num < 0)
1023 /* Don't know what this is, but it's garbage. */
1024 abort ();
1029 /* For calculating coverage at the function level. */
1031 static int function_source_lines;
1032 static int function_source_lines_executed;
1033 static int function_branches;
1034 static int function_branches_executed;
1035 static int function_branches_taken;
1036 static int function_calls;
1037 static int function_calls_executed;
1038 static char *function_name;
1040 /* Calculate the branch taken probabilities for all arcs branches at the
1041 end of this block. */
1043 static void
1044 calculate_branch_probs (current_graph, block_num, branch_probs, last_line_num)
1045 struct bb_info_list *current_graph;
1046 int block_num;
1047 struct arcdata **branch_probs;
1048 int last_line_num;
1050 gcov_type total;
1051 struct adj_list *arcptr;
1052 struct arcdata *end_ptr, *a_ptr;
1054 total = current_graph->bb_graph[block_num].exec_count;
1055 for (arcptr = current_graph->bb_graph[block_num].succ; arcptr;
1056 arcptr = arcptr->succ_next)
1058 /* Ignore fall through arcs as they aren't really branches. */
1060 if (arcptr->fall_through)
1061 continue;
1063 a_ptr = (struct arcdata *) xmalloc (sizeof (struct arcdata));
1064 a_ptr->total = total;
1065 if (total == 0)
1066 a_ptr->hits = 0;
1067 else
1068 a_ptr->hits = arcptr->arc_count;
1069 a_ptr->call_insn = arcptr->fake;
1071 if (output_function_summary)
1073 if (a_ptr->call_insn)
1075 function_calls++;
1076 if (a_ptr->total != 0)
1077 function_calls_executed++;
1079 else
1081 function_branches++;
1082 if (a_ptr->total != 0)
1083 function_branches_executed++;
1084 if (a_ptr->hits > 0)
1085 function_branches_taken++;
1089 /* Append the new branch to the end of the list. */
1090 a_ptr->next = 0;
1091 if (! branch_probs[last_line_num])
1092 branch_probs[last_line_num] = a_ptr;
1093 else
1095 end_ptr = branch_probs[last_line_num];
1096 while (end_ptr->next != 0)
1097 end_ptr = end_ptr->next;
1098 end_ptr->next = a_ptr;
1103 /* Output summary info for a function. */
1105 static void
1106 function_summary ()
1108 if (function_source_lines)
1109 fnotice (stdout, "%6.2f%% of %d source lines executed in function %s\n",
1110 (((double) function_source_lines_executed / function_source_lines)
1111 * 100), function_source_lines, function_name);
1112 else
1113 fnotice (stdout, "No executable source lines in function %s\n",
1114 function_name);
1116 if (output_branch_probs)
1118 if (function_branches)
1120 fnotice (stdout, "%6.2f%% of %d branches executed in function %s\n",
1121 (((double) function_branches_executed / function_branches)
1122 * 100), function_branches, function_name);
1123 fnotice (stdout,
1124 "%6.2f%% of %d branches taken at least once in function %s\n",
1125 (((double) function_branches_taken / function_branches)
1126 * 100), function_branches, function_name);
1128 else
1129 fnotice (stdout, "No branches in function %s\n", function_name);
1130 if (function_calls)
1131 fnotice (stdout, "%6.2f%% of %d calls executed in function %s\n",
1132 (((double) function_calls_executed / function_calls)
1133 * 100), function_calls, function_name);
1134 else
1135 fnotice (stdout, "No calls in function %s\n", function_name);
1139 /* Calculate line execution counts, and output the data to a .tcov file. */
1141 static void
1142 output_data ()
1144 /* When scanning data, this is true only if the data applies to the
1145 current source file. */
1146 int this_file;
1147 /* An array indexed by line number which indicates how many times that line
1148 was executed. */
1149 gcov_type *line_counts;
1150 /* An array indexed by line number which indicates whether the line was
1151 present in the bb file (i.e. whether it had code associate with it).
1152 Lines never executed are those which both exist, and have zero execution
1153 counts. */
1154 char *line_exists;
1155 /* An array indexed by line number, which contains a list of branch
1156 probabilities, one for each branch on that line. */
1157 struct arcdata **branch_probs = NULL;
1158 struct sourcefile *s_ptr;
1159 char *source_file_name;
1160 FILE *source_file;
1161 struct bb_info_list *current_graph;
1162 long count;
1163 char *cptr;
1164 long block_num;
1165 long line_num;
1166 long last_line_num = 0;
1167 int i;
1168 struct arcdata *a_ptr;
1169 /* Buffer used for reading in lines from the source file. */
1170 char string[STRING_SIZE];
1171 /* For calculating coverage at the file level. */
1172 int total_source_lines;
1173 int total_source_lines_executed;
1174 int total_branches;
1175 int total_branches_executed;
1176 int total_branches_taken;
1177 int total_calls;
1178 int total_calls_executed;
1180 /* Now, for each source file, allocate an array big enough to hold a count
1181 for each line. Scan through the bb_data, and when the file name matches
1182 the current file name, then for each following line number, increment
1183 the line number execution count indicated by the execution count of
1184 the appropriate basic block. */
1186 for (s_ptr = sources; s_ptr; s_ptr = s_ptr->next)
1188 /* If this is a relative file name, and an object directory has been
1189 specified, then make it relative to the object directory name. */
1190 if (! IS_ABSOLUTE_PATHNAME (s_ptr->name)
1191 && object_directory != 0
1192 && *object_directory != '\0')
1194 int objdir_count = strlen (object_directory);
1195 source_file_name = xmalloc (objdir_count + strlen (s_ptr->name) + 2);
1196 strcpy (source_file_name, object_directory);
1197 if (object_directory[objdir_count - 1] != '/')
1198 source_file_name[objdir_count++] = '/';
1199 strcpy (source_file_name + objdir_count, s_ptr->name);
1201 else
1202 source_file_name = s_ptr->name;
1204 line_counts = (gcov_type *) xcalloc (sizeof (gcov_type), s_ptr->maxlineno);
1205 line_exists = xcalloc (1, s_ptr->maxlineno);
1206 if (output_branch_probs)
1207 branch_probs = (struct arcdata **)
1208 xcalloc (sizeof (struct arcdata *), s_ptr->maxlineno);
1210 /* There will be a zero at the beginning of the bb info, before the
1211 first list of line numbers, so must initialize block_num to 0. */
1212 block_num = 0;
1213 this_file = 0;
1214 current_graph = 0;
1216 /* Pointer into the bb_data, incremented while scanning the data. */
1217 char *ptr = bb_data;
1218 for (count = 0; count < bb_data_size; count++)
1220 long delim;
1222 __fetch_long (&line_num, ptr, 4);
1223 ptr += 4;
1224 if (line_num == -1)
1226 /* Marks the beginning of a file name. Check to see whether
1227 this is the filename we are currently collecting data for. */
1229 if (strcmp (s_ptr->name, ptr))
1230 this_file = 0;
1231 else
1232 this_file = 1;
1234 /* Scan past the file name. */
1235 do {
1236 count++;
1237 __fetch_long (&delim, ptr, 4);
1238 ptr += 4;
1239 } while (delim != line_num);
1241 else if (line_num == -2)
1243 /* Marks the start of a new function. Advance to the next
1244 program flow graph. */
1246 if (! current_graph)
1247 current_graph = bb_graph_list;
1248 else
1250 if (block_num == current_graph->num_blocks - 1)
1251 /* Last block falls through to exit. */
1253 else if (block_num == current_graph->num_blocks - 2)
1255 if (output_branch_probs && this_file)
1256 calculate_branch_probs (current_graph, block_num,
1257 branch_probs, last_line_num);
1259 else
1261 fnotice (stderr,
1262 "didn't use all bb entries of graph, function %s\n",
1263 function_name);
1264 fnotice (stderr, "block_num = %ld, num_blocks = %d\n",
1265 block_num, current_graph->num_blocks);
1268 current_graph = current_graph->next;
1269 block_num = 0;
1271 if (output_function_summary && this_file)
1272 function_summary ();
1275 if (output_function_summary)
1277 function_source_lines = 0;
1278 function_source_lines_executed = 0;
1279 function_branches = 0;
1280 function_branches_executed = 0;
1281 function_branches_taken = 0;
1282 function_calls = 0;
1283 function_calls_executed = 0;
1286 /* Save the function name for later use. */
1287 function_name = ptr;
1289 /* Scan past the file name. */
1290 do {
1291 count++;
1292 __fetch_long (&delim, ptr, 4);
1293 ptr += 4;
1294 } while (delim != line_num);
1296 else if (line_num == 0)
1298 /* Marks the end of a block. */
1300 if (block_num >= current_graph->num_blocks)
1302 fnotice (stderr, "ERROR: too many basic blocks in .bb file %s\n",
1303 function_name);
1304 abort ();
1307 if (output_branch_probs && this_file)
1308 calculate_branch_probs (current_graph, block_num,
1309 branch_probs, last_line_num);
1311 block_num++;
1313 else if (this_file)
1315 if (output_function_summary)
1317 if (line_exists[line_num] == 0)
1318 function_source_lines++;
1319 if (line_counts[line_num] == 0
1320 && current_graph->bb_graph[block_num].exec_count != 0)
1321 function_source_lines_executed++;
1324 /* Accumulate execution data for this line number. */
1326 line_counts[line_num]
1327 += current_graph->bb_graph[block_num].exec_count;
1328 line_exists[line_num] = 1;
1329 last_line_num = line_num;
1334 if (output_function_summary && this_file)
1335 function_summary ();
1337 /* Calculate summary test coverage statistics. */
1339 total_source_lines = 0;
1340 total_source_lines_executed = 0;
1341 total_branches = 0;
1342 total_branches_executed = 0;
1343 total_branches_taken = 0;
1344 total_calls = 0;
1345 total_calls_executed = 0;
1347 for (count = 1; count < s_ptr->maxlineno; count++)
1349 if (line_exists[count])
1351 total_source_lines++;
1352 if (line_counts[count])
1353 total_source_lines_executed++;
1355 if (output_branch_probs)
1357 for (a_ptr = branch_probs[count]; a_ptr; a_ptr = a_ptr->next)
1359 if (a_ptr->call_insn)
1361 total_calls++;
1362 if (a_ptr->total != 0)
1363 total_calls_executed++;
1365 else
1367 total_branches++;
1368 if (a_ptr->total != 0)
1369 total_branches_executed++;
1370 if (a_ptr->hits > 0)
1371 total_branches_taken++;
1377 if (total_source_lines)
1378 fnotice (stdout,
1379 "%6.2f%% of %d source lines executed in file %s\n",
1380 (((double) total_source_lines_executed / total_source_lines)
1381 * 100), total_source_lines, source_file_name);
1382 else
1383 fnotice (stdout, "No executable source lines in file %s\n",
1384 source_file_name);
1386 if (output_branch_probs)
1388 if (total_branches)
1390 fnotice (stdout, "%6.2f%% of %d branches executed in file %s\n",
1391 (((double) total_branches_executed / total_branches)
1392 * 100), total_branches, source_file_name);
1393 fnotice (stdout,
1394 "%6.2f%% of %d branches taken at least once in file %s\n",
1395 (((double) total_branches_taken / total_branches)
1396 * 100), total_branches, source_file_name);
1398 else
1399 fnotice (stdout, "No branches in file %s\n", source_file_name);
1400 if (total_calls)
1401 fnotice (stdout, "%6.2f%% of %d calls executed in file %s\n",
1402 (((double) total_calls_executed / total_calls)
1403 * 100), total_calls, source_file_name);
1404 else
1405 fnotice (stdout, "No calls in file %s\n", source_file_name);
1408 if (output_gcov_file)
1410 /* Now the statistics are ready. Read in the source file one line
1411 at a time, and output that line to the gcov file preceded by
1412 its execution count if non zero. */
1414 source_file = fopen (source_file_name, "r");
1415 if (source_file == NULL)
1417 fnotice (stderr, "Could not open source file %s.\n",
1418 source_file_name);
1419 free (line_counts);
1420 free (line_exists);
1421 continue;
1424 count = strlen (source_file_name);
1425 cptr = strrchr (s_ptr->name, '/');
1426 if (cptr)
1427 cptr = cptr + 1;
1428 else
1429 cptr = s_ptr->name;
1430 if (output_long_names && strcmp (cptr, input_file_name))
1432 gcov_file_name = xmalloc (count + 7 + strlen (input_file_name));
1434 cptr = strrchr (input_file_name, '/');
1435 if (cptr)
1436 strcpy (gcov_file_name, cptr + 1);
1437 else
1438 strcpy (gcov_file_name, input_file_name);
1440 strcat (gcov_file_name, ".");
1442 cptr = strrchr (source_file_name, '/');
1443 if (cptr)
1444 strcat (gcov_file_name, cptr + 1);
1445 else
1446 strcat (gcov_file_name, source_file_name);
1448 else
1450 gcov_file_name = xmalloc (count + 6);
1451 cptr = strrchr (source_file_name, '/');
1452 if (cptr)
1453 strcpy (gcov_file_name, cptr + 1);
1454 else
1455 strcpy (gcov_file_name, source_file_name);
1458 /* Don't strip off the ending for compatibility with tcov, since
1459 this results in confusion if there is more than one file with
1460 the same basename, e.g. tmp.c and tmp.h. */
1461 strcat (gcov_file_name, ".gcov");
1463 gcov_file = fopen (gcov_file_name, "w");
1465 if (gcov_file == NULL)
1467 fnotice (stderr, "Could not open output file %s.\n",
1468 gcov_file_name);
1469 fclose (source_file);
1470 free (line_counts);
1471 free (line_exists);
1472 continue;
1475 fnotice (stdout, "Creating %s.\n", gcov_file_name);
1477 for (count = 1; count < s_ptr->maxlineno; count++)
1479 char *retval;
1480 int len;
1482 retval = fgets (string, STRING_SIZE, source_file);
1484 /* For lines which don't exist in the .bb file, print nothing
1485 before the source line. For lines which exist but were never
1486 executed, print ###### before the source line. Otherwise,
1487 print the execution count before the source line. */
1488 /* There are 16 spaces of indentation added before the source
1489 line so that tabs won't be messed up. */
1490 if (line_exists[count])
1492 if (line_counts[count])
1494 char c[20];
1495 sprintf (c, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)line_counts[count]);
1496 fprintf (gcov_file, "%12s %s", c,
1497 string);
1499 else
1500 fprintf (gcov_file, " ###### %s", string);
1502 else
1503 fprintf (gcov_file, "\t\t%s", string);
1505 /* In case the source file line is larger than our buffer, keep
1506 reading and outputting lines until we get a newline. */
1507 len = strlen (string);
1508 while ((len == 0 || string[strlen (string) - 1] != '\n')
1509 && retval != NULL)
1511 retval = fgets (string, STRING_SIZE, source_file);
1512 fputs (string, gcov_file);
1515 if (output_branch_probs)
1517 for (i = 0, a_ptr = branch_probs[count]; a_ptr;
1518 a_ptr = a_ptr->next, i++)
1520 if (a_ptr->call_insn)
1522 if (a_ptr->total == 0)
1523 fnotice (gcov_file, "call %d never executed\n", i);
1524 else
1526 if (output_branch_counts)
1528 char c[20];
1529 sprintf (c, HOST_WIDEST_INT_PRINT_DEC,
1530 a_ptr->total - a_ptr->hits);
1531 fnotice (gcov_file,
1532 "call %d returns = %s\n", i, c);
1534 else
1536 char c[20];
1537 sprintf (c, HOST_WIDEST_INT_PRINT_DEC,
1538 100 - ((a_ptr->hits * 100)
1539 + (a_ptr->total >> 1))
1540 / a_ptr->total);
1541 fnotice (gcov_file,
1542 "call %d returns = %s%%\n", i, c);
1546 else
1548 if (a_ptr->total == 0)
1549 fnotice (gcov_file, "branch %d never executed\n",
1551 else
1553 if (output_branch_counts)
1555 char c[20];
1556 sprintf (c, HOST_WIDEST_INT_PRINT_DEC,
1557 a_ptr->hits);
1558 fnotice (gcov_file,
1559 "branch %d taken = %s\n", i, c);
1561 else
1563 char c[20];
1564 sprintf (c, HOST_WIDEST_INT_PRINT_DEC,
1565 ((a_ptr->hits * 100)
1566 + (a_ptr->total >> 1))
1567 / a_ptr->total);
1568 fnotice (gcov_file,
1569 "branch %d taken = %s%%\n", i, c);
1576 /* Gracefully handle errors while reading the source file. */
1577 if (retval == NULL)
1579 fnotice (stderr,
1580 "Unexpected EOF while reading source file %s.\n",
1581 source_file_name);
1582 break;
1586 /* Handle all remaining source lines. There may be lines
1587 after the last line of code. */
1590 char *retval = fgets (string, STRING_SIZE, source_file);
1591 while (retval != NULL)
1593 int len;
1595 fprintf (gcov_file, "\t\t%s", string);
1597 /* In case the source file line is larger than our buffer, keep
1598 reading and outputting lines until we get a newline. */
1599 len = strlen (string);
1600 while ((len == 0 || string[strlen (string) - 1] != '\n')
1601 && retval != NULL)
1603 retval = fgets (string, STRING_SIZE, source_file);
1604 fputs (string, gcov_file);
1607 retval = fgets (string, STRING_SIZE, source_file);
1611 fclose (source_file);
1612 fclose (gcov_file);
1615 free (line_counts);
1616 free (line_exists);