import of gcc-2.8
[official-gcc.git] / gcc / gcov.c
blob2dda0d48ee8aebe61a80a0fab68995b3901b8bb0
1 /* Gcov.c: prepend line execution counts and branch probabilities to a
2 source file.
3 Copyright (C) 1990, 91, 92, 93, 94, 96, 1997 Free Software Foundation, Inc.
4 Contributed by James E. Wilson of Cygnus Support.
5 Mangled by Bob Manson of Cygnus Support.
7 Gcov is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 Gcov is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Gcov; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 /* ??? The code in final.c that produces the struct bb assumes that there is
22 no padding between the fields. This is not necessary true. The current
23 code can only be trusted if longs and pointers are the same size. */
25 /* ??? No need to print an execution count on every line, could just print
26 it on the first line of each block, and only print it on a subsequent
27 line in the same block if the count changes. */
29 /* ??? Print a list of the ten blocks with the highest execution counts,
30 and list the line numbers corresponding to those blocks. Also, perhaps
31 list the line numbers with the highest execution counts, only printing
32 the first if there are several which are all listed in the same block. */
34 /* ??? Should have an option to print the number of basic blocks, and the
35 percent of them that are covered. */
37 /* ??? Does not correctly handle the case where two .bb files refer to the
38 same included source file. For example, if one has a short file containing
39 only inline functions, which is then included in two other files, then
40 there will be two .bb files which refer to the include file, but there
41 is no way to get the total execution counts for the included file, can
42 only get execution counts for one or the other of the including files. */
44 #include "config.h"
45 #include <stdio.h>
46 #include "gansidecl.h"
47 #include <sys/types.h>
48 #include <sys/stat.h>
50 #ifdef HAVE_STDLIB_H
51 #include <stdlib.h>
52 #endif
54 #ifdef HAVE_STRING_H
55 #include <string.h>
56 #else
57 #ifdef HAVE_STRINGS_H
58 #include <strings.h>
59 #endif
60 #endif
62 #include "gcov-io.h"
64 #ifdef NEED_DECLARATION_RINDEX
65 extern char *rindex ();
66 #endif
68 /* The .bb file format consists of several lists of 4-byte integers
69 which are the line numbers of each basic block in the file. Each
70 list is terminated by a zero. These lists correspond to the basic
71 blocks in the reconstructed program flow graph.
73 A line number of -1 indicates that a source file name (padded to a
74 long boundary) follows. The padded file name is followed by
75 another -1 to make it easy to scan past file names. A -2 indicates
76 that a function name (padded to a long boundary) follows; the name
77 is followed by another -2 to make it easy to scan past the function
78 name.
80 The .bbg file contains enough info to enable gcov to reconstruct the
81 program flow graph. The first word is the number of basic blocks,
82 the second word is the number of arcs, followed by the list of arcs
83 (source bb, dest bb pairs), then a -1, then the number of instrumented
84 arcs followed by the instrumented arcs, followed by another -1. This
85 is repeated for each function.
87 The .da file contains the execution count for each instrumented branch.
89 The .bb and .bbg files are created by giving GCC the -ftest-coverage option,
90 and the .da files are created when an executable compiled with
91 -fprofile-arcs is run. */
93 /* The functions in this file for creating and solution program flow graphs
94 are very similar to functions in the gcc source file profile.c. */
96 char gcov_version_string[] = "GNU gcov version 1.5\n";
98 /* This is the size of the buffer used to read in source file lines. */
100 #define STRING_SIZE 200
102 /* One copy of this structure is created for each source file mentioned in the
103 .bb file. */
105 struct sourcefile
107 char *name;
108 int maxlineno;
109 struct sourcefile *next;
112 /* This points to the head of the sourcefile structure list. */
114 struct sourcefile *sources;
116 /* One of these is dynamically created whenever we identify an arc in the
117 function. */
119 struct adj_list {
120 int source;
121 int target;
122 int arc_count;
123 unsigned int count_valid : 1;
124 unsigned int on_tree : 1;
125 unsigned int fake : 1;
126 unsigned int fall_through : 1;
127 #if 0
128 /* Not needed for gcov, but defined in profile.c. */
129 rtx branch_insn;
130 #endif
131 struct adj_list *pred_next;
132 struct adj_list *succ_next;
135 /* Count the number of basic blocks, and create an array of these structures,
136 one for each bb in the function. */
138 struct bb_info {
139 struct adj_list *succ;
140 struct adj_list *pred;
141 int succ_count;
142 int pred_count;
143 int exec_count;
144 unsigned int count_valid : 1;
145 unsigned int on_tree : 1;
146 #if 0
147 /* Not needed for gcov, but defined in profile.c. */
148 rtx first_insn;
149 #endif
152 /* When outputting branch probabilities, one of these structures is created
153 for each branch/call. */
155 struct arcdata
157 int prob;
158 int call_insn;
159 struct arcdata *next;
162 /* Used to save the list of bb_graphs, one per function. */
164 struct bb_info_list {
165 /* Indexed by block number, holds the basic block graph for one function. */
166 struct bb_info *bb_graph;
167 int num_blocks;
168 struct bb_info_list *next;
171 /* Holds a list of function basic block graphs. */
173 static struct bb_info_list *bb_graph_list = 0;
175 /* Name and file pointer of the input file for the basic block graph. */
177 static char *bbg_file_name;
178 static FILE *bbg_file;
180 /* Name and file pointer of the input file for the arc count data. */
182 static char *da_file_name;
183 static FILE *da_file;
185 /* Name and file pointer of the input file for the basic block line counts. */
187 static char *bb_file_name;
188 static FILE *bb_file;
190 /* Holds the entire contents of the bb_file read into memory. */
192 static char *bb_data;
194 /* Size of bb_data array in longs. */
196 static long bb_data_size;
198 /* Name and file pointer of the output file. */
200 static char *gcov_file_name;
201 static FILE *gcov_file;
203 /* Name of the file mentioned on the command line. */
205 static char *input_file_name = 0;
207 /* Output branch probabilities if true. */
209 static int output_branch_probs = 0;
211 /* Output a gcov file if this is true. This is on by default, and can
212 be turned off by the -n option. */
214 static int output_gcov_file = 1;
216 /* For included files, make the gcov output file name include the name of
217 the input source file. For example, if x.h is included in a.c, then the
218 output file name is a.c.x.h.gcov instead of x.h.gcov. This works only
219 when a single source file is specified. */
221 static int output_long_names = 0;
223 /* Output summary info for each function. */
225 static int output_function_summary = 0;
227 /* Object directory file prefix. This is the directory where .bb and .bbg
228 files are looked for, if non-zero. */
230 static char *object_directory = 0;
232 /* Forward declarations. */
233 static void process_args ();
234 static void open_files ();
235 static void read_files ();
236 static void scan_for_source_files ();
237 static void output_data ();
238 char * xmalloc ();
241 main (argc, argv)
242 int argc;
243 char **argv;
245 process_args (argc, argv);
247 open_files ();
249 read_files ();
251 scan_for_source_files ();
253 output_data ();
255 return 0;
258 char *
259 xmalloc (size)
260 unsigned size;
262 register char *value = (char *) malloc (size);
263 if (value == 0)
265 fprintf (stderr, "error: virtual memory exhausted");
266 exit (FATAL_EXIT_CODE);
268 return value;
271 /* More 'friendly' abort that prints the line and file.
272 config.h can #define abort fancy_abort if you like that sort of thing. */
274 void
275 fancy_abort ()
277 fprintf (stderr, "Internal gcc abort.\n");
278 exit (FATAL_EXIT_CODE);
281 /* Print a usage message and exit. */
283 static void
284 print_usage ()
286 fprintf (stderr, "gcov [-b] [-v] [-n] [-l] [-f] [-o OBJDIR] file\n");
287 exit (FATAL_EXIT_CODE);
290 /* Parse the command line. */
292 static void
293 process_args (argc, argv)
294 int argc;
295 char **argv;
297 int i;
299 for (i = 1; i < argc; i++)
301 if (argv[i][0] == '-')
303 if (argv[i][1] == 'b')
304 output_branch_probs = 1;
305 else if (argv[i][1] == 'v')
306 fputs (gcov_version_string, stderr);
307 else if (argv[i][1] == 'n')
308 output_gcov_file = 0;
309 else if (argv[i][1] == 'l')
310 output_long_names = 1;
311 else if (argv[i][1] == 'f')
312 output_function_summary = 1;
313 else if (argv[i][1] == 'o' && argv[i][2] == '\0')
314 object_directory = argv[++i];
315 else
316 print_usage ();
318 else if (! input_file_name)
319 input_file_name = argv[i];
320 else
321 print_usage ();
324 if (! input_file_name)
325 print_usage ();
329 /* Find and open the .bb, .da, and .bbg files. */
331 static void
332 open_files ()
334 int count, objdir_count;
335 char *cptr;
337 /* Determine the names of the .bb, .bbg, and .da files. Strip off the
338 extension, if any, and append the new extensions. */
339 count = strlen (input_file_name);
340 if (object_directory)
341 objdir_count = strlen (object_directory);
342 else
343 objdir_count = 0;
345 da_file_name = xmalloc (count + objdir_count + 4);
346 bb_file_name = xmalloc (count + objdir_count + 4);
347 bbg_file_name = xmalloc (count + objdir_count + 5);
349 if (object_directory)
351 strcpy (da_file_name, object_directory);
352 strcpy (bb_file_name, object_directory);
353 strcpy (bbg_file_name, object_directory);
355 if (object_directory[objdir_count - 1] != '/')
357 strcat (da_file_name, "/");
358 strcat (bb_file_name, "/");
359 strcat (bbg_file_name, "/");
362 cptr = rindex (input_file_name, '/');
363 if (cptr)
365 strcat (da_file_name, cptr + 1);
366 strcat (bb_file_name, cptr + 1);
367 strcat (bbg_file_name, cptr + 1);
369 else
371 strcat (da_file_name, input_file_name);
372 strcat (bb_file_name, input_file_name);
373 strcat (bbg_file_name, input_file_name);
376 else
378 strcpy (da_file_name, input_file_name);
379 strcpy (bb_file_name, input_file_name);
380 strcpy (bbg_file_name, input_file_name);
383 cptr = rindex (bb_file_name, '.');
384 if (cptr)
385 strcpy (cptr, ".bb");
386 else
387 strcat (bb_file_name, ".bb");
389 cptr = rindex (da_file_name, '.');
390 if (cptr)
391 strcpy (cptr, ".da");
392 else
393 strcat (da_file_name, ".da");
395 cptr = rindex (bbg_file_name, '.');
396 if (cptr)
397 strcpy (cptr, ".bbg");
398 else
399 strcat (bbg_file_name, ".bbg");
401 bb_file = fopen (bb_file_name, "r");
402 if (bb_file == NULL)
404 fprintf (stderr, "Could not open basic block file %s.\n", bb_file_name);
405 exit (FATAL_EXIT_CODE);
408 /* If none of the functions in the file were executed, then there won't
409 be a .da file. Just assume that all counts are zero in this case. */
410 da_file = fopen (da_file_name, "r");
411 if (da_file == NULL)
413 fprintf (stderr, "Could not open data file %s.\n", da_file_name);
414 fprintf (stderr, "Assuming that all execution counts are zero.\n");
417 bbg_file = fopen (bbg_file_name, "r");
418 if (bbg_file == NULL)
420 fprintf (stderr, "Could not open program flow graph file %s.\n",
421 bbg_file_name);
422 exit (FATAL_EXIT_CODE);
425 /* Check for empty .bbg file. This indicates that there is no executable
426 code in this source file. */
427 /* Set the EOF condition if at the end of file. */
428 ungetc (getc (bbg_file), bbg_file);
429 if (feof (bbg_file))
431 fprintf (stderr, "No executable code associated with file %s.\n",
432 input_file_name);
433 exit (FATAL_EXIT_CODE);
437 /* Initialize a new arc. */
439 static void
440 init_arc (arcptr, source, target, bb_graph)
441 struct adj_list *arcptr;
442 int source, target;
443 struct bb_info *bb_graph;
445 arcptr->target = target;
446 arcptr->source = source;
448 arcptr->arc_count = 0;
449 arcptr->count_valid = 0;
450 arcptr->on_tree = 0;
451 arcptr->fake = 0;
452 arcptr->fall_through = 0;
454 arcptr->succ_next = bb_graph[source].succ;
455 bb_graph[source].succ = arcptr;
456 bb_graph[source].succ_count++;
458 arcptr->pred_next = bb_graph[target].pred;
459 bb_graph[target].pred = arcptr;
460 bb_graph[target].pred_count++;
464 /* Reverse the arcs on a arc list. */
466 static struct adj_list *
467 reverse_arcs (arcptr)
468 struct adj_list *arcptr;
470 struct adj_list *prev = 0;
471 struct adj_list *next;
473 for ( ; arcptr; arcptr = next)
475 next = arcptr->succ_next;
476 arcptr->succ_next = prev;
477 prev = arcptr;
480 return prev;
484 /* Construct the program flow graph from the .bbg file, and read in the data
485 in the .da file. */
487 static void
488 create_program_flow_graph (bptr)
489 struct bb_info_list *bptr;
491 long num_blocks, number_arcs, src, dest, flag_bits, num_arcs_per_block;
492 int i;
493 struct adj_list *arcptr;
494 struct bb_info *bb_graph;
496 /* Read the number of blocks. */
497 __read_long (&num_blocks, bbg_file, 4);
499 /* Create an array of size bb number of bb_info structs. Bzero it. */
500 bb_graph = (struct bb_info *) xmalloc (num_blocks
501 * sizeof (struct bb_info));
502 bzero ((char *) bb_graph, sizeof (struct bb_info) * num_blocks);
504 bptr->bb_graph = bb_graph;
505 bptr->num_blocks = num_blocks;
507 /* Read and create each arc from the .bbg file. */
508 __read_long (&number_arcs, bbg_file, 4);
509 for (i = 0; i < num_blocks; i++)
511 int j;
513 __read_long (&num_arcs_per_block, bbg_file, 4);
514 for (j = 0; j < num_arcs_per_block; j++)
516 if (number_arcs-- < 0)
517 abort ();
519 src = i;
520 __read_long (&dest, bbg_file, 4);
522 arcptr = (struct adj_list *) xmalloc (sizeof (struct adj_list));
523 init_arc (arcptr, src, dest, bb_graph);
525 __read_long (&flag_bits, bbg_file, 4);
526 arcptr->on_tree = flag_bits & 0x1;
527 arcptr->fake = !! (flag_bits & 0x2);
528 arcptr->fall_through = !! (flag_bits & 0x4);
532 if (number_arcs)
533 abort ();
535 /* Read and ignore the -1 separating the arc list from the arc list of the
536 next function. */
537 __read_long (&src, bbg_file, 4);
538 if (src != -1)
539 abort ();
541 /* Must reverse the order of all succ arcs, to ensure that they match
542 the order of the data in the .da file. */
544 for (i = 0; i < num_blocks; i++)
545 if (bb_graph[i].succ)
546 bb_graph[i].succ = reverse_arcs (bb_graph[i].succ);
548 /* For each arc not on the spanning tree, set its execution count from
549 the .da file. */
551 /* The first count in the .da file is the number of times that the function
552 was entered. This is the exec_count for block zero. */
554 /* This duplicates code in branch_prob in profile.c. */
556 for (i = 0; i < num_blocks; i++)
557 for (arcptr = bb_graph[i].succ; arcptr; arcptr = arcptr->succ_next)
558 if (! arcptr->on_tree)
560 long tmp_count = 0;;
561 if (da_file && __read_long (&tmp_count, da_file, 8))
562 abort();
564 arcptr->arc_count = tmp_count;
565 arcptr->count_valid = 1;
566 bb_graph[i].succ_count--;
567 bb_graph[arcptr->target].pred_count--;
571 static void
572 solve_program_flow_graph (bptr)
573 struct bb_info_list *bptr;
575 int passes, changes, total;
576 int i;
577 struct adj_list *arcptr;
578 struct bb_info *bb_graph;
579 int num_blocks;
581 num_blocks = bptr->num_blocks;
582 bb_graph = bptr->bb_graph;
584 /* For every block in the file,
585 - if every exit/entrance arc has a known count, then set the block count
586 - if the block count is known, and every exit/entrance arc but one has
587 a known execution count, then set the count of the remaining arc
589 As arc counts are set, decrement the succ/pred count, but don't delete
590 the arc, that way we can easily tell when all arcs are known, or only
591 one arc is unknown. */
593 /* The order that the basic blocks are iterated through is important.
594 Since the code that finds spanning trees starts with block 0, low numbered
595 arcs are put on the spanning tree in preference to high numbered arcs.
596 Hence, most instrumented arcs are at the end. Graph solving works much
597 faster if we propagate numbers from the end to the start.
599 This takes an average of slightly more than 3 passes. */
601 changes = 1;
602 passes = 0;
603 while (changes)
605 passes++;
606 changes = 0;
608 for (i = num_blocks - 1; i >= 0; i--)
610 if (! bb_graph[i].count_valid)
612 if (bb_graph[i].succ_count == 0)
614 total = 0;
615 for (arcptr = bb_graph[i].succ; arcptr;
616 arcptr = arcptr->succ_next)
617 total += arcptr->arc_count;
618 bb_graph[i].exec_count = total;
619 bb_graph[i].count_valid = 1;
620 changes = 1;
622 else if (bb_graph[i].pred_count == 0)
624 total = 0;
625 for (arcptr = bb_graph[i].pred; arcptr;
626 arcptr = arcptr->pred_next)
627 total += arcptr->arc_count;
628 bb_graph[i].exec_count = total;
629 bb_graph[i].count_valid = 1;
630 changes = 1;
633 if (bb_graph[i].count_valid)
635 if (bb_graph[i].succ_count == 1)
637 total = 0;
638 /* One of the counts will be invalid, but it is zero,
639 so adding it in also doesn't hurt. */
640 for (arcptr = bb_graph[i].succ; arcptr;
641 arcptr = arcptr->succ_next)
642 total += arcptr->arc_count;
643 /* Calculate count for remaining arc by conservation. */
644 total = bb_graph[i].exec_count - total;
645 /* Search for the invalid arc, and set its count. */
646 for (arcptr = bb_graph[i].succ; arcptr;
647 arcptr = arcptr->succ_next)
648 if (! arcptr->count_valid)
649 break;
650 if (! arcptr)
651 abort ();
652 arcptr->count_valid = 1;
653 arcptr->arc_count = total;
654 bb_graph[i].succ_count--;
656 bb_graph[arcptr->target].pred_count--;
657 changes = 1;
659 if (bb_graph[i].pred_count == 1)
661 total = 0;
662 /* One of the counts will be invalid, but it is zero,
663 so adding it in also doesn't hurt. */
664 for (arcptr = bb_graph[i].pred; arcptr;
665 arcptr = arcptr->pred_next)
666 total += arcptr->arc_count;
667 /* Calculate count for remaining arc by conservation. */
668 total = bb_graph[i].exec_count - total;
669 /* Search for the invalid arc, and set its count. */
670 for (arcptr = bb_graph[i].pred; arcptr;
671 arcptr = arcptr->pred_next)
672 if (! arcptr->count_valid)
673 break;
674 if (! arcptr)
675 abort ();
676 arcptr->count_valid = 1;
677 arcptr->arc_count = total;
678 bb_graph[i].pred_count--;
680 bb_graph[arcptr->source].succ_count--;
681 changes = 1;
687 /* If the graph has been correctly solved, every block will have a
688 succ and pred count of zero. */
689 for (i = 0; i < num_blocks; i++)
690 if (bb_graph[i].succ_count || bb_graph[i].pred_count)
691 abort ();
695 static void
696 read_files ()
698 struct stat buf;
699 struct bb_info_list *list_end = 0;
700 struct bb_info_list *b_ptr;
701 long total, first_time;
703 /* Read and ignore the first word of the .da file, which is the count of
704 how many numbers follow. */
705 if (da_file && __read_long (&total, da_file, 8))
706 abort();
708 while (! feof (bbg_file))
710 b_ptr = (struct bb_info_list *) xmalloc (sizeof (struct bb_info_list));
712 b_ptr->next = 0;
713 if (list_end)
714 list_end->next = b_ptr;
715 else
716 bb_graph_list = b_ptr;
717 list_end = b_ptr;
719 /* Read in the data in the .bbg file and reconstruct the program flow
720 graph for one function. */
721 create_program_flow_graph (b_ptr, first_time);
723 /* Set the EOF condition if at the end of file. */
724 ungetc (getc (bbg_file), bbg_file);
727 /* Check to make sure the .da file data is valid. */
729 if (da_file)
731 if (feof (da_file))
732 fprintf (stderr, ".da file contents exhausted too early\n");
733 /* Should be at end of file now. */
734 if (__read_long (&total, da_file, 8) == 0)
735 fprintf (stderr, ".da file contents not exhausted\n");
738 /* Calculate all of the basic block execution counts and branch
739 taken probabilities. */
741 for (b_ptr = bb_graph_list; b_ptr; b_ptr = b_ptr->next)
742 solve_program_flow_graph (b_ptr);
744 /* Read in all of the data from the .bb file. This info will be accessed
745 sequentially twice. */
746 stat (bb_file_name, &buf);
747 bb_data_size = buf.st_size / 4;
749 bb_data = (char *) xmalloc ((unsigned) buf.st_size);
750 fread (bb_data, sizeof (char), buf.st_size, bb_file);
752 fclose (bb_file);
753 if (da_file)
754 fclose (da_file);
755 fclose (bbg_file);
759 /* Scan the data in the .bb file to find all source files referenced,
760 and the largest line number mentioned in each one. */
762 static void
763 scan_for_source_files ()
765 struct sourcefile *s_ptr;
766 char *ptr;
767 int count;
768 long line_num;
770 /* Search the bb_data to find:
771 1) The number of sources files contained herein, and
772 2) The largest line number for each source file. */
774 ptr = bb_data;
775 sources = 0;
776 for (count = 0; count < bb_data_size; count++)
778 __fetch_long (&line_num, ptr, 4);
779 ptr += 4;
780 if (line_num == -1)
782 /* A source file name follows. Check to see if we already have
783 a sourcefile structure for this file. */
784 s_ptr = sources;
785 while (s_ptr && strcmp (s_ptr->name, ptr))
786 s_ptr = s_ptr->next;
788 if (s_ptr == 0)
790 /* No sourcefile structure for this file name exists, create
791 a new one, and append it to the front of the sources list. */
792 s_ptr = (struct sourcefile *) xmalloc (sizeof(struct sourcefile));
793 s_ptr->name = xmalloc (strlen ((char *) ptr) + 1);
794 strcpy (s_ptr->name, (char *) ptr);
795 s_ptr->maxlineno = 0;
796 s_ptr->next = sources;
797 sources = s_ptr;
800 /* Scan past the file name. */
802 long delim;
803 do {
804 count++;
805 __fetch_long (&delim, ptr, 4);
806 ptr += 4;
807 } while (delim != line_num);
810 else if (line_num == -2)
812 long delim;
814 /* A function name follows. Ignore it. */
815 do {
816 count++;
817 __fetch_long (&delim, ptr, 4);
818 ptr += 4;
819 } while (delim != line_num);
821 /* There will be a zero before the first file name, in which case s_ptr
822 will still be uninitialized. So, only try to set the maxlineno
823 field if line_num is non-zero. */
824 else if (line_num > 0)
826 if (s_ptr->maxlineno <= line_num)
827 s_ptr->maxlineno = line_num + 1;
829 else if (line_num < 0)
831 /* Don't know what this is, but it's garbage. */
832 abort();
837 /* For calculating coverage at the function level. */
839 static int function_source_lines;
840 static int function_source_lines_executed;
841 static int function_branches;
842 static int function_branches_executed;
843 static int function_branches_taken;
844 static int function_calls;
845 static int function_calls_executed;
846 static char *function_name;
848 /* Calculate the branch taken probabilities for all arcs branches at the
849 end of this block. */
851 static void
852 calculate_branch_probs (current_graph, block_num, branch_probs, last_line_num)
853 struct bb_info_list *current_graph;
854 int block_num;
855 struct arcdata **branch_probs;
856 int last_line_num;
858 int total;
859 struct adj_list *arcptr;
860 struct arcdata *end_ptr, *a_ptr;
862 total = current_graph->bb_graph[block_num].exec_count;
863 for (arcptr = current_graph->bb_graph[block_num].succ; arcptr;
864 arcptr = arcptr->succ_next)
866 /* Ignore fall through arcs as they aren't really branches. */
868 if (arcptr->fall_through)
869 continue;
871 a_ptr = (struct arcdata *) xmalloc (sizeof (struct arcdata));
872 if (total == 0)
873 a_ptr->prob = -1;
874 else
875 a_ptr->prob = ((arcptr->arc_count * 100) + (total >> 1)) / total;
876 a_ptr->call_insn = arcptr->fake;
878 if (output_function_summary)
880 if (a_ptr->call_insn)
882 function_calls++;
883 if (a_ptr->prob != -1)
884 function_calls_executed++;
886 else
888 function_branches++;
889 if (a_ptr->prob != -1)
890 function_branches_executed++;
891 if (a_ptr->prob > 0)
892 function_branches_taken++;
896 /* Append the new branch to the end of the list. */
897 a_ptr->next = 0;
898 if (! branch_probs[last_line_num])
899 branch_probs[last_line_num] = a_ptr;
900 else
902 end_ptr = branch_probs[last_line_num];
903 while (end_ptr->next != 0)
904 end_ptr = end_ptr->next;
905 end_ptr->next = a_ptr;
910 /* Output summary info for a function. */
912 static void
913 function_summary ()
915 if (function_source_lines)
916 fprintf (stdout, "%6.2lf%% of %d source lines executed in function %s\n",
917 (((double) function_source_lines_executed / function_source_lines)
918 * 100), function_source_lines, function_name);
919 else
920 fprintf (stdout, "No executable source lines in function %s\n",
921 function_name);
923 if (output_branch_probs)
925 if (function_branches)
927 fprintf (stdout, "%6.2lf%% of %d branches executed in function %s\n",
928 (((double) function_branches_executed / function_branches)
929 * 100), function_branches, function_name);
930 fprintf (stdout,
931 "%6.2lf%% of %d branches taken at least once in function %s\n",
932 (((double) function_branches_taken / function_branches)
933 * 100), function_branches, function_name);
935 else
936 fprintf (stdout, "No branches in function %s\n", function_name);
937 if (function_calls)
938 fprintf (stdout, "%6.2lf%% of %d calls executed in function %s\n",
939 (((double) function_calls_executed / function_calls)
940 * 100), function_calls, function_name);
941 else
942 fprintf (stdout, "No calls in function %s\n", function_name);
946 /* Calculate line execution counts, and output the data to a .tcov file. */
948 static void
949 output_data ()
951 /* When scanning data, this is true only if the data applies to the
952 current source file. */
953 int this_file;
954 /* An array indexed by line number which indicates how many times that line
955 was executed. */
956 long *line_counts;
957 /* An array indexed by line number which indicates whether the line was
958 present in the bb file (i.e. whether it had code associate with it).
959 Lines never executed are those which both exist, and have zero execution
960 counts. */
961 char *line_exists;
962 /* An array indexed by line number, which contains a list of branch
963 probabilities, one for each branch on that line. */
964 struct arcdata **branch_probs;
965 struct sourcefile *s_ptr;
966 char *source_file_name;
967 FILE *source_file;
968 struct bb_info_list *current_graph;
969 int count;
970 char *cptr;
971 long block_num;
972 long line_num;
973 long last_line_num;
974 int i;
975 struct arcdata *a_ptr;
976 /* Buffer used for reading in lines from the source file. */
977 char string[STRING_SIZE];
978 /* For calculating coverage at the file level. */
979 int total_source_lines;
980 int total_source_lines_executed;
981 int total_branches;
982 int total_branches_executed;
983 int total_branches_taken;
984 int total_calls;
985 int total_calls_executed;
987 /* Now, for each source file, allocate an array big enough to hold a count
988 for each line. Scan through the bb_data, and when the file name matches
989 the current file name, then for each following line number, increment
990 the line number execution count indicated by the execution count of
991 the appropriate basic block. */
993 for (s_ptr = sources; s_ptr; s_ptr = s_ptr->next)
995 /* If this is a relative file name, and an object directory has been
996 specified, then make it relative to the object directory name. */
997 if (*s_ptr->name != '/' && object_directory != 0
998 && *object_directory != '\0')
1000 int objdir_count = strlen (object_directory);
1001 source_file_name = xmalloc (objdir_count + strlen (s_ptr->name) + 2);
1002 strcpy (source_file_name, object_directory);
1003 if (object_directory[objdir_count - 1] != '/')
1004 source_file_name[objdir_count++] = '/';
1005 strcpy (source_file_name + objdir_count, s_ptr->name);
1007 else
1008 source_file_name = s_ptr->name;
1010 line_counts = (long *) xmalloc (sizeof (long) * s_ptr->maxlineno);
1011 bzero ((char *) line_counts, sizeof (long) * s_ptr->maxlineno);
1012 line_exists = xmalloc (s_ptr->maxlineno);
1013 bzero (line_exists, s_ptr->maxlineno);
1014 if (output_branch_probs)
1016 branch_probs = (struct arcdata **) xmalloc (sizeof (struct arcdata **)
1017 * s_ptr->maxlineno);
1018 bzero ((char *) branch_probs,
1019 sizeof (struct arcdata **) * s_ptr->maxlineno);
1022 /* There will be a zero at the beginning of the bb info, before the
1023 first list of line numbers, so must initialize block_num to 0. */
1024 block_num = 0;
1025 this_file = 0;
1026 current_graph = 0;
1028 /* Pointer into the bb_data, incremented while scanning the data. */
1029 char *ptr = bb_data;
1030 for (count = 0; count < bb_data_size; count++)
1032 long delim;
1034 __fetch_long (&line_num, ptr, 4);
1035 ptr += 4;
1036 if (line_num == -1)
1038 /* Marks the beginning of a file name. Check to see whether
1039 this is the filename we are currently collecting data for. */
1041 if (strcmp (s_ptr->name, ptr))
1042 this_file = 0;
1043 else
1044 this_file = 1;
1046 /* Scan past the file name. */
1047 do {
1048 count++;
1049 __fetch_long (&delim, ptr, 4);
1050 ptr += 4;
1051 } while (delim != line_num);
1053 else if (line_num == -2)
1055 /* Marks the start of a new function. Advance to the next
1056 program flow graph. */
1058 if (! current_graph)
1059 current_graph = bb_graph_list;
1060 else
1062 if (block_num == current_graph->num_blocks - 1)
1063 /* Last block falls through to exit. */
1065 else if (block_num == current_graph->num_blocks - 2)
1067 if (output_branch_probs && this_file)
1068 calculate_branch_probs (current_graph, block_num,
1069 branch_probs, last_line_num);
1071 else
1073 fprintf (stderr,
1074 "didn't use all bb entries of graph, function %s\n",
1075 function_name);
1076 fprintf (stderr, "block_num = %d, num_blocks = %d\n",
1077 block_num, current_graph->num_blocks);
1080 current_graph = current_graph->next;
1081 block_num = 0;
1083 if (output_function_summary && this_file)
1084 function_summary ();
1087 if (output_function_summary)
1089 function_source_lines = 0;
1090 function_source_lines_executed = 0;
1091 function_branches = 0;
1092 function_branches_executed = 0;
1093 function_branches_taken = 0;
1094 function_calls = 0;
1095 function_calls_executed = 0;
1098 /* Save the function name for later use. */
1099 function_name = ptr;
1101 /* Scan past the file name. */
1102 do {
1103 count++;
1104 __fetch_long (&delim, ptr, 4);
1105 ptr += 4;
1106 } while (delim != line_num);
1108 else if (line_num == 0)
1110 /* Marks the end of a block. */
1112 if (block_num >= current_graph->num_blocks)
1114 fprintf (stderr, "ERROR: too many basic blocks in .bb file %s\n",
1115 function_name);
1116 abort ();
1119 if (output_branch_probs && this_file)
1120 calculate_branch_probs (current_graph, block_num,
1121 branch_probs, last_line_num);
1123 block_num++;
1125 else if (this_file)
1127 if (output_function_summary)
1129 if (line_exists[line_num] == 0)
1130 function_source_lines++;
1131 if (line_counts[line_num] == 0
1132 && current_graph->bb_graph[block_num].exec_count != 0)
1133 function_source_lines_executed++;
1136 /* Accumulate execution data for this line number. */
1138 line_counts[line_num]
1139 += current_graph->bb_graph[block_num].exec_count;
1140 line_exists[line_num] = 1;
1141 last_line_num = line_num;
1146 if (output_function_summary && this_file)
1147 function_summary ();
1149 /* Calculate summary test coverage statistics. */
1151 total_source_lines = 0;
1152 total_source_lines_executed = 0;
1153 total_branches = 0;
1154 total_branches_executed = 0;
1155 total_branches_taken = 0;
1156 total_calls = 0;
1157 total_calls_executed = 0;
1159 for (count = 1; count < s_ptr->maxlineno; count++)
1161 if (line_exists[count])
1163 total_source_lines++;
1164 if (line_counts[count])
1165 total_source_lines_executed++;
1167 if (output_branch_probs)
1169 for (a_ptr = branch_probs[count]; a_ptr; a_ptr = a_ptr->next)
1171 if (a_ptr->call_insn)
1173 total_calls++;
1174 if (a_ptr->prob != -1)
1175 total_calls_executed++;
1177 else
1179 total_branches++;
1180 if (a_ptr->prob != -1)
1181 total_branches_executed++;
1182 if (a_ptr->prob > 0)
1183 total_branches_taken++;
1189 if (total_source_lines)
1190 fprintf (stdout,
1191 "%6.2lf%% of %d source lines executed in file %s\n",
1192 (((double) total_source_lines_executed / total_source_lines)
1193 * 100), total_source_lines, source_file_name);
1194 else
1195 fprintf (stdout, "No executable source lines in file %s\n",
1196 source_file_name);
1198 if (output_branch_probs)
1200 if (total_branches)
1202 fprintf (stdout, "%6.2lf%% of %d branches executed in file %s\n",
1203 (((double) total_branches_executed / total_branches)
1204 * 100), total_branches, source_file_name);
1205 fprintf (stdout,
1206 "%6.2lf%% of %d branches taken at least once in file %s\n",
1207 (((double) total_branches_taken / total_branches)
1208 * 100), total_branches, source_file_name);
1210 else
1211 fprintf (stdout, "No branches in file %s\n", source_file_name);
1212 if (total_calls)
1213 fprintf (stdout, "%6.2lf%% of %d calls executed in file %s\n",
1214 (((double) total_calls_executed / total_calls)
1215 * 100), total_calls, source_file_name);
1216 else
1217 fprintf (stdout, "No calls in file %s\n", source_file_name);
1220 if (output_gcov_file)
1222 /* Now the statistics are ready. Read in the source file one line
1223 at a time, and output that line to the gcov file preceded by
1224 its execution count if non zero. */
1226 source_file = fopen (source_file_name, "r");
1227 if (source_file == NULL)
1229 fprintf (stderr, "Could not open source file %s.\n",
1230 source_file_name);
1231 free (line_counts);
1232 free (line_exists);
1233 continue;
1236 count = strlen (source_file_name);
1237 cptr = rindex (s_ptr->name, '/');
1238 if (cptr)
1239 cptr = cptr + 1;
1240 else
1241 cptr = s_ptr->name;
1242 if (output_long_names && strcmp (cptr, input_file_name))
1244 gcov_file_name = xmalloc (count + 7 + strlen (input_file_name));
1246 cptr = rindex (input_file_name, '/');
1247 if (cptr)
1248 strcpy (gcov_file_name, cptr + 1);
1249 else
1250 strcpy (gcov_file_name, input_file_name);
1252 strcat (gcov_file_name, ".");
1254 cptr = rindex (source_file_name, '/');
1255 if (cptr)
1256 strcat (gcov_file_name, cptr + 1);
1257 else
1258 strcat (gcov_file_name, source_file_name);
1260 else
1262 gcov_file_name = xmalloc (count + 6);
1263 cptr = rindex (source_file_name, '/');
1264 if (cptr)
1265 strcpy (gcov_file_name, cptr + 1);
1266 else
1267 strcpy (gcov_file_name, source_file_name);
1270 /* Don't strip off the ending for compatibility with tcov, since
1271 this results in confusion if there is more than one file with
1272 the same basename, e.g. tmp.c and tmp.h. */
1273 strcat (gcov_file_name, ".gcov");
1275 gcov_file = fopen (gcov_file_name, "w");
1277 if (gcov_file == NULL)
1279 fprintf (stderr, "Could not open output file %s.\n",
1280 gcov_file_name);
1281 fclose (source_file);
1282 free (line_counts);
1283 free (line_exists);
1284 continue;
1287 fprintf (stdout, "Creating %s.\n", gcov_file_name);
1289 for (count = 1; count < s_ptr->maxlineno; count++)
1291 char *retval;
1292 int len;
1294 retval = fgets (string, STRING_SIZE, source_file);
1296 /* For lines which don't exist in the .bb file, print nothing
1297 before the source line. For lines which exist but were never
1298 executed, print ###### before the source line. Otherwise,
1299 print the execution count before the source line. */
1300 /* There are 16 spaces of indentation added before the source
1301 line so that tabs won't be messed up. */
1302 if (line_exists[count])
1304 if (line_counts[count])
1305 fprintf (gcov_file, "%12d %s", line_counts[count],
1306 string);
1307 else
1308 fprintf (gcov_file, " ###### %s", string);
1310 else
1311 fprintf (gcov_file, "\t\t%s", string);
1313 /* In case the source file line is larger than our buffer, keep
1314 reading and outputting lines until we get a newline. */
1315 len = strlen (string);
1316 while ((len == 0 || string[strlen (string) - 1] != '\n')
1317 && retval != NULL)
1319 retval = fgets (string, STRING_SIZE, source_file);
1320 fputs (string, gcov_file);
1323 if (output_branch_probs)
1325 for (i = 0, a_ptr = branch_probs[count]; a_ptr;
1326 a_ptr = a_ptr->next, i++)
1328 if (a_ptr->call_insn)
1330 if (a_ptr->prob == -1)
1331 fprintf (gcov_file, "call %d never executed\n", i);
1332 else
1333 fprintf (gcov_file,
1334 "call %d returns = %d%%\n",
1335 i, 100 - a_ptr->prob);
1337 else
1339 if (a_ptr->prob == -1)
1340 fprintf (gcov_file, "branch %d never executed\n",
1342 else
1343 fprintf (gcov_file, "branch %d taken = %d%%\n", i,
1344 a_ptr->prob);
1349 /* Gracefully handle errors while reading the source file. */
1350 if (retval == NULL)
1352 fprintf (stderr,
1353 "Unexpected EOF while reading source file %s.\n",
1354 source_file_name);
1355 break;
1359 /* Handle all remaining source lines. There may be lines
1360 after the last line of code. */
1363 char *retval = fgets (string, STRING_SIZE, source_file);
1364 while (retval != NULL)
1366 int len;
1368 fprintf (gcov_file, "\t\t%s", string);
1370 /* In case the source file line is larger than our buffer, keep
1371 reading and outputting lines until we get a newline. */
1372 len = strlen (string);
1373 while ((len == 0 || string[strlen (string) - 1] != '\n')
1374 && retval != NULL)
1376 retval = fgets (string, STRING_SIZE, source_file);
1377 fputs (string, gcov_file);
1380 retval = fgets (string, STRING_SIZE, source_file);
1384 fclose (source_file);
1385 fclose (gcov_file);
1388 free (line_counts);
1389 free (line_exists);