oops - omitted from previous delta fixing UNIQUE_SECTION
[official-gcc.git] / gcc / gcov.c
blob974c708d0705d0eb7c9bc296eb9b9c41c9865e11
1 /* Gcov.c: prepend line execution counts and branch probabilities to a
2 source file.
3 Copyright (C) 1990, 91-94, 96-99, 2000 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, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* ??? The code in final.c that produces the struct bb assumes that there is
23 no padding between the fields. This is not necessary true. The current
24 code can only be trusted if longs and pointers are the same size. */
26 /* ??? No need to print an execution count on every line, could just print
27 it on the first line of each block, and only print it on a subsequent
28 line in the same block if the count changes. */
30 /* ??? Print a list of the ten blocks with the highest execution counts,
31 and list the line numbers corresponding to those blocks. Also, perhaps
32 list the line numbers with the highest execution counts, only printing
33 the first if there are several which are all listed in the same block. */
35 /* ??? Should have an option to print the number of basic blocks, and the
36 percent of them that are covered. */
38 /* ??? Does not correctly handle the case where two .bb files refer to the
39 same included source file. For example, if one has a short file containing
40 only inline functions, which is then included in two other files, then
41 there will be two .bb files which refer to the include file, but there
42 is no way to get the total execution counts for the included file, can
43 only get execution counts for one or the other of the including files. */
45 #include "config.h"
46 #include "system.h"
47 #include "intl.h"
48 #undef abort
50 #include "gcov-io.h"
52 /* The .bb file format consists of several lists of 4-byte integers
53 which are the line numbers of each basic block in the file. Each
54 list is terminated by a zero. These lists correspond to the basic
55 blocks in the reconstructed program flow graph.
57 A line number of -1 indicates that a source file name (padded to a
58 long boundary) follows. The padded file name is followed by
59 another -1 to make it easy to scan past file names. A -2 indicates
60 that a function name (padded to a long boundary) follows; the name
61 is followed by another -2 to make it easy to scan past the function
62 name.
64 The .bbg file contains enough info to enable gcov to reconstruct the
65 program flow graph. The first word is the number of basic blocks,
66 the second word is the number of arcs, followed by the list of arcs
67 (source bb, dest bb pairs), then a -1, then the number of instrumented
68 arcs followed by the instrumented arcs, followed by another -1. This
69 is repeated for each function.
71 The .da file contains the execution count for each instrumented branch.
73 The .bb and .bbg files are created by giving GCC the -ftest-coverage option,
74 and the .da files are created when an executable compiled with
75 -fprofile-arcs is run. */
77 /* The functions in this file for creating and solution program flow graphs
78 are very similar to functions in the gcc source file profile.c. */
80 char gcov_version_string[] = "GNU gcov version 1.5\n";
82 /* This is the size of the buffer used to read in source file lines. */
84 #define STRING_SIZE 200
86 /* One copy of this structure is created for each source file mentioned in the
87 .bb file. */
89 struct sourcefile
91 char *name;
92 int maxlineno;
93 struct sourcefile *next;
96 /* This points to the head of the sourcefile structure list. */
98 struct sourcefile *sources;
100 /* One of these is dynamically created whenever we identify an arc in the
101 function. */
103 struct adj_list {
104 int source;
105 int target;
106 int arc_count;
107 unsigned int count_valid : 1;
108 unsigned int on_tree : 1;
109 unsigned int fake : 1;
110 unsigned int fall_through : 1;
111 #if 0
112 /* Not needed for gcov, but defined in profile.c. */
113 rtx branch_insn;
114 #endif
115 struct adj_list *pred_next;
116 struct adj_list *succ_next;
119 /* Count the number of basic blocks, and create an array of these structures,
120 one for each bb in the function. */
122 struct bb_info {
123 struct adj_list *succ;
124 struct adj_list *pred;
125 int succ_count;
126 int pred_count;
127 int exec_count;
128 unsigned int count_valid : 1;
129 unsigned int on_tree : 1;
130 #if 0
131 /* Not needed for gcov, but defined in profile.c. */
132 rtx first_insn;
133 #endif
136 /* When outputting branch probabilities, one of these structures is created
137 for each branch/call. */
139 struct arcdata
141 int hits;
142 int total;
143 int call_insn;
144 struct arcdata *next;
147 /* Used to save the list of bb_graphs, one per function. */
149 struct bb_info_list {
150 /* Indexed by block number, holds the basic block graph for one function. */
151 struct bb_info *bb_graph;
152 int num_blocks;
153 struct bb_info_list *next;
156 /* Holds a list of function basic block graphs. */
158 static struct bb_info_list *bb_graph_list = 0;
160 /* Name and file pointer of the input file for the basic block graph. */
162 static char *bbg_file_name;
163 static FILE *bbg_file;
165 /* Name and file pointer of the input file for the arc count data. */
167 static char *da_file_name;
168 static FILE *da_file;
170 /* Name and file pointer of the input file for the basic block line counts. */
172 static char *bb_file_name;
173 static FILE *bb_file;
175 /* Holds the entire contents of the bb_file read into memory. */
177 static char *bb_data;
179 /* Size of bb_data array in longs. */
181 static long bb_data_size;
183 /* Name and file pointer of the output file. */
185 static char *gcov_file_name;
186 static FILE *gcov_file;
188 /* Name of the file mentioned on the command line. */
190 static char *input_file_name = 0;
192 /* Output branch probabilities if true. */
194 static int output_branch_probs = 0;
196 /* Output a gcov file if this is true. This is on by default, and can
197 be turned off by the -n option. */
199 static int output_gcov_file = 1;
201 /* For included files, make the gcov output file name include the name of
202 the input source file. For example, if x.h is included in a.c, then the
203 output file name is a.c.x.h.gcov instead of x.h.gcov. This works only
204 when a single source file is specified. */
206 static int output_long_names = 0;
208 /* Output summary info for each function. */
210 static int output_function_summary = 0;
212 /* Object directory file prefix. This is the directory where .bb and .bbg
213 files are looked for, if non-zero. */
215 static char *object_directory = 0;
217 /* Output the number of times a branch was taken as opposed to the percentage
218 of times it was taken. Turned on by the -c option */
220 static int output_branch_counts = 0;
222 /* Forward declarations. */
223 static void process_args PARAMS ((int, char **));
224 static void open_files PARAMS ((void));
225 static void read_files PARAMS ((void));
226 static void scan_for_source_files PARAMS ((void));
227 static void output_data PARAMS ((void));
228 static void print_usage PARAMS ((void)) ATTRIBUTE_NORETURN;
229 static void init_arc PARAMS ((struct adj_list *, int, int, struct bb_info *));
230 static struct adj_list *reverse_arcs PARAMS ((struct adj_list *));
231 static void create_program_flow_graph PARAMS ((struct bb_info_list *));
232 static void solve_program_flow_graph PARAMS ((struct bb_info_list *));
233 static void calculate_branch_probs PARAMS ((struct bb_info_list *, int,
234 struct arcdata **, int));
235 static void function_summary PARAMS ((void));
237 extern int main PARAMS ((int, char **));
240 main (argc, argv)
241 int argc;
242 char **argv;
244 #ifdef HAVE_LC_MESSAGES
245 setlocale (LC_MESSAGES, "");
246 #endif
247 (void) bindtextdomain (PACKAGE, localedir);
248 (void) textdomain (PACKAGE);
250 process_args (argc, argv);
252 open_files ();
254 read_files ();
256 scan_for_source_files ();
258 output_data ();
260 return 0;
263 static void fnotice PARAMS ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2;
264 static void
265 fnotice VPARAMS ((FILE *file, const char *msgid, ...))
267 #ifndef ANSI_PROTOTYPES
268 FILE *file;
269 const char *msgid;
270 #endif
271 va_list ap;
273 VA_START (ap, msgid);
275 #ifndef ANSI_PROTOTYPES
276 file = va_arg (ap, FILE *);
277 msgid = va_arg (ap, const char *);
278 #endif
280 vfprintf (file, _(msgid), ap);
281 va_end (ap);
284 /* More 'friendly' abort that prints the line and file.
285 config.h can #define abort fancy_abort if you like that sort of thing. */
286 extern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN;
288 void
289 fancy_abort ()
291 fnotice (stderr, "Internal gcov abort.\n");
292 exit (FATAL_EXIT_CODE);
295 /* Print a usage message and exit. */
297 static void
298 print_usage ()
300 fnotice (stderr, "gcov [-b] [-v] [-n] [-l] [-f] [-o OBJDIR] file\n");
301 exit (FATAL_EXIT_CODE);
304 /* Parse the command line. */
306 static void
307 process_args (argc, argv)
308 int argc;
309 char **argv;
311 int i;
313 for (i = 1; i < argc; i++)
315 if (argv[i][0] == '-')
317 if (argv[i][1] == 'b')
318 output_branch_probs = 1;
319 else if (argv[i][1] == 'c')
320 output_branch_counts = 1;
321 else if (argv[i][1] == 'v')
322 fputs (gcov_version_string, stderr);
323 else if (argv[i][1] == 'n')
324 output_gcov_file = 0;
325 else if (argv[i][1] == 'l')
326 output_long_names = 1;
327 else if (argv[i][1] == 'f')
328 output_function_summary = 1;
329 else if (argv[i][1] == 'o' && argv[i][2] == '\0')
330 object_directory = argv[++i];
331 else
332 print_usage ();
334 else if (! input_file_name)
335 input_file_name = argv[i];
336 else
337 print_usage ();
340 if (! input_file_name)
341 print_usage ();
345 /* Find and open the .bb, .da, and .bbg files. */
347 static void
348 open_files ()
350 int count, objdir_count;
351 char *cptr;
353 /* Determine the names of the .bb, .bbg, and .da files. Strip off the
354 extension, if any, and append the new extensions. */
355 count = strlen (input_file_name);
356 if (object_directory)
357 objdir_count = strlen (object_directory);
358 else
359 objdir_count = 0;
361 da_file_name = xmalloc (count + objdir_count + 4);
362 bb_file_name = xmalloc (count + objdir_count + 4);
363 bbg_file_name = xmalloc (count + objdir_count + 5);
365 if (object_directory)
367 strcpy (da_file_name, object_directory);
368 strcpy (bb_file_name, object_directory);
369 strcpy (bbg_file_name, object_directory);
371 if (object_directory[objdir_count - 1] != '/')
373 strcat (da_file_name, "/");
374 strcat (bb_file_name, "/");
375 strcat (bbg_file_name, "/");
378 cptr = rindex (input_file_name, '/');
379 if (cptr)
381 strcat (da_file_name, cptr + 1);
382 strcat (bb_file_name, cptr + 1);
383 strcat (bbg_file_name, cptr + 1);
385 else
387 strcat (da_file_name, input_file_name);
388 strcat (bb_file_name, input_file_name);
389 strcat (bbg_file_name, input_file_name);
392 else
394 strcpy (da_file_name, input_file_name);
395 strcpy (bb_file_name, input_file_name);
396 strcpy (bbg_file_name, input_file_name);
399 cptr = rindex (bb_file_name, '.');
400 if (cptr)
401 strcpy (cptr, ".bb");
402 else
403 strcat (bb_file_name, ".bb");
405 cptr = rindex (da_file_name, '.');
406 if (cptr)
407 strcpy (cptr, ".da");
408 else
409 strcat (da_file_name, ".da");
411 cptr = rindex (bbg_file_name, '.');
412 if (cptr)
413 strcpy (cptr, ".bbg");
414 else
415 strcat (bbg_file_name, ".bbg");
417 bb_file = fopen (bb_file_name, "rb");
418 if (bb_file == NULL)
420 fnotice (stderr, "Could not open basic block file %s.\n", bb_file_name);
421 exit (FATAL_EXIT_CODE);
424 /* If none of the functions in the file were executed, then there won't
425 be a .da file. Just assume that all counts are zero in this case. */
426 da_file = fopen (da_file_name, "rb");
427 if (da_file == NULL)
429 fnotice (stderr, "Could not open data file %s.\n", da_file_name);
430 fnotice (stderr, "Assuming that all execution counts are zero.\n");
433 bbg_file = fopen (bbg_file_name, "rb");
434 if (bbg_file == NULL)
436 fnotice (stderr, "Could not open program flow graph file %s.\n",
437 bbg_file_name);
438 exit (FATAL_EXIT_CODE);
441 /* Check for empty .bbg file. This indicates that there is no executable
442 code in this source file. */
443 /* Set the EOF condition if at the end of file. */
444 ungetc (getc (bbg_file), bbg_file);
445 if (feof (bbg_file))
447 fnotice (stderr, "No executable code associated with file %s.\n",
448 input_file_name);
449 exit (FATAL_EXIT_CODE);
453 /* Initialize a new arc. */
455 static void
456 init_arc (arcptr, source, target, bb_graph)
457 struct adj_list *arcptr;
458 int source, target;
459 struct bb_info *bb_graph;
461 arcptr->target = target;
462 arcptr->source = source;
464 arcptr->arc_count = 0;
465 arcptr->count_valid = 0;
466 arcptr->on_tree = 0;
467 arcptr->fake = 0;
468 arcptr->fall_through = 0;
470 arcptr->succ_next = bb_graph[source].succ;
471 bb_graph[source].succ = arcptr;
472 bb_graph[source].succ_count++;
474 arcptr->pred_next = bb_graph[target].pred;
475 bb_graph[target].pred = arcptr;
476 bb_graph[target].pred_count++;
480 /* Reverse the arcs on a arc list. */
482 static struct adj_list *
483 reverse_arcs (arcptr)
484 struct adj_list *arcptr;
486 struct adj_list *prev = 0;
487 struct adj_list *next;
489 for ( ; arcptr; arcptr = next)
491 next = arcptr->succ_next;
492 arcptr->succ_next = prev;
493 prev = arcptr;
496 return prev;
500 /* Construct the program flow graph from the .bbg file, and read in the data
501 in the .da file. */
503 static void
504 create_program_flow_graph (bptr)
505 struct bb_info_list *bptr;
507 long num_blocks, number_arcs, src, dest, flag_bits, num_arcs_per_block;
508 int i;
509 struct adj_list *arcptr;
510 struct bb_info *bb_graph;
512 /* Read the number of blocks. */
513 __read_long (&num_blocks, bbg_file, 4);
515 /* Create an array of size bb number of bb_info structs. */
516 bb_graph = (struct bb_info *) xcalloc (num_blocks, sizeof (struct bb_info));
518 bptr->bb_graph = bb_graph;
519 bptr->num_blocks = num_blocks;
521 /* Read and create each arc from the .bbg file. */
522 __read_long (&number_arcs, bbg_file, 4);
523 for (i = 0; i < num_blocks; i++)
525 int j;
527 __read_long (&num_arcs_per_block, bbg_file, 4);
528 for (j = 0; j < num_arcs_per_block; j++)
530 if (number_arcs-- < 0)
531 abort ();
533 src = i;
534 __read_long (&dest, bbg_file, 4);
536 arcptr = (struct adj_list *) xmalloc (sizeof (struct adj_list));
537 init_arc (arcptr, src, dest, bb_graph);
539 __read_long (&flag_bits, bbg_file, 4);
540 arcptr->on_tree = flag_bits & 0x1;
541 arcptr->fake = !! (flag_bits & 0x2);
542 arcptr->fall_through = !! (flag_bits & 0x4);
546 if (number_arcs)
547 abort ();
549 /* Read and ignore the -1 separating the arc list from the arc list of the
550 next function. */
551 __read_long (&src, bbg_file, 4);
552 if (src != -1)
553 abort ();
555 /* Must reverse the order of all succ arcs, to ensure that they match
556 the order of the data in the .da file. */
558 for (i = 0; i < num_blocks; i++)
559 if (bb_graph[i].succ)
560 bb_graph[i].succ = reverse_arcs (bb_graph[i].succ);
562 /* For each arc not on the spanning tree, set its execution count from
563 the .da file. */
565 /* The first count in the .da file is the number of times that the function
566 was entered. This is the exec_count for block zero. */
568 /* This duplicates code in branch_prob in profile.c. */
570 for (i = 0; i < num_blocks; i++)
571 for (arcptr = bb_graph[i].succ; arcptr; arcptr = arcptr->succ_next)
572 if (! arcptr->on_tree)
574 long tmp_count = 0;
575 if (da_file && __read_long (&tmp_count, da_file, 8))
576 abort();
578 arcptr->arc_count = tmp_count;
579 arcptr->count_valid = 1;
580 bb_graph[i].succ_count--;
581 bb_graph[arcptr->target].pred_count--;
585 static void
586 solve_program_flow_graph (bptr)
587 struct bb_info_list *bptr;
589 int passes, changes, total;
590 int i;
591 struct adj_list *arcptr;
592 struct bb_info *bb_graph;
593 int num_blocks;
595 num_blocks = bptr->num_blocks;
596 bb_graph = bptr->bb_graph;
598 /* For every block in the file,
599 - if every exit/entrance arc has a known count, then set the block count
600 - if the block count is known, and every exit/entrance arc but one has
601 a known execution count, then set the count of the remaining arc
603 As arc counts are set, decrement the succ/pred count, but don't delete
604 the arc, that way we can easily tell when all arcs are known, or only
605 one arc is unknown. */
607 /* The order that the basic blocks are iterated through is important.
608 Since the code that finds spanning trees starts with block 0, low numbered
609 arcs are put on the spanning tree in preference to high numbered arcs.
610 Hence, most instrumented arcs are at the end. Graph solving works much
611 faster if we propagate numbers from the end to the start.
613 This takes an average of slightly more than 3 passes. */
615 changes = 1;
616 passes = 0;
617 while (changes)
619 passes++;
620 changes = 0;
622 for (i = num_blocks - 1; i >= 0; i--)
624 if (! bb_graph[i].count_valid)
626 if (bb_graph[i].succ_count == 0)
628 total = 0;
629 for (arcptr = bb_graph[i].succ; arcptr;
630 arcptr = arcptr->succ_next)
631 total += arcptr->arc_count;
632 bb_graph[i].exec_count = total;
633 bb_graph[i].count_valid = 1;
634 changes = 1;
636 else if (bb_graph[i].pred_count == 0)
638 total = 0;
639 for (arcptr = bb_graph[i].pred; arcptr;
640 arcptr = arcptr->pred_next)
641 total += arcptr->arc_count;
642 bb_graph[i].exec_count = total;
643 bb_graph[i].count_valid = 1;
644 changes = 1;
647 if (bb_graph[i].count_valid)
649 if (bb_graph[i].succ_count == 1)
651 total = 0;
652 /* One of the counts will be invalid, but it is zero,
653 so adding it in also doesn't hurt. */
654 for (arcptr = bb_graph[i].succ; arcptr;
655 arcptr = arcptr->succ_next)
656 total += arcptr->arc_count;
657 /* Calculate count for remaining arc by conservation. */
658 total = bb_graph[i].exec_count - total;
659 /* Search for the invalid arc, and set its count. */
660 for (arcptr = bb_graph[i].succ; arcptr;
661 arcptr = arcptr->succ_next)
662 if (! arcptr->count_valid)
663 break;
664 if (! arcptr)
665 abort ();
666 arcptr->count_valid = 1;
667 arcptr->arc_count = total;
668 bb_graph[i].succ_count--;
670 bb_graph[arcptr->target].pred_count--;
671 changes = 1;
673 if (bb_graph[i].pred_count == 1)
675 total = 0;
676 /* One of the counts will be invalid, but it is zero,
677 so adding it in also doesn't hurt. */
678 for (arcptr = bb_graph[i].pred; arcptr;
679 arcptr = arcptr->pred_next)
680 total += arcptr->arc_count;
681 /* Calculate count for remaining arc by conservation. */
682 total = bb_graph[i].exec_count - total;
683 /* Search for the invalid arc, and set its count. */
684 for (arcptr = bb_graph[i].pred; arcptr;
685 arcptr = arcptr->pred_next)
686 if (! arcptr->count_valid)
687 break;
688 if (! arcptr)
689 abort ();
690 arcptr->count_valid = 1;
691 arcptr->arc_count = total;
692 bb_graph[i].pred_count--;
694 bb_graph[arcptr->source].succ_count--;
695 changes = 1;
701 /* If the graph has been correctly solved, every block will have a
702 succ and pred count of zero. */
703 for (i = 0; i < num_blocks; i++)
704 if (bb_graph[i].succ_count || bb_graph[i].pred_count)
705 abort ();
709 static void
710 read_files ()
712 struct stat buf;
713 struct bb_info_list *list_end = 0;
714 struct bb_info_list *b_ptr;
715 long total;
717 /* Read and ignore the first word of the .da file, which is the count of
718 how many numbers follow. */
719 if (da_file && __read_long (&total, da_file, 8))
720 abort();
722 while (! feof (bbg_file))
724 b_ptr = (struct bb_info_list *) xmalloc (sizeof (struct bb_info_list));
726 b_ptr->next = 0;
727 if (list_end)
728 list_end->next = b_ptr;
729 else
730 bb_graph_list = b_ptr;
731 list_end = b_ptr;
733 /* Read in the data in the .bbg file and reconstruct the program flow
734 graph for one function. */
735 create_program_flow_graph (b_ptr);
737 /* Set the EOF condition if at the end of file. */
738 ungetc (getc (bbg_file), bbg_file);
741 /* Check to make sure the .da file data is valid. */
743 if (da_file)
745 if (feof (da_file))
746 fnotice (stderr, ".da file contents exhausted too early\n");
747 /* Should be at end of file now. */
748 if (__read_long (&total, da_file, 8) == 0)
749 fnotice (stderr, ".da file contents not exhausted\n");
752 /* Calculate all of the basic block execution counts and branch
753 taken probabilities. */
755 for (b_ptr = bb_graph_list; b_ptr; b_ptr = b_ptr->next)
756 solve_program_flow_graph (b_ptr);
758 /* Read in all of the data from the .bb file. This info will be accessed
759 sequentially twice. */
760 stat (bb_file_name, &buf);
761 bb_data_size = buf.st_size / 4;
763 bb_data = (char *) xmalloc ((unsigned) buf.st_size);
764 fread (bb_data, sizeof (char), buf.st_size, bb_file);
766 fclose (bb_file);
767 if (da_file)
768 fclose (da_file);
769 fclose (bbg_file);
773 /* Scan the data in the .bb file to find all source files referenced,
774 and the largest line number mentioned in each one. */
776 static void
777 scan_for_source_files ()
779 struct sourcefile *s_ptr = NULL;
780 char *ptr;
781 int count;
782 long line_num;
784 /* Search the bb_data to find:
785 1) The number of sources files contained herein, and
786 2) The largest line number for each source file. */
788 ptr = bb_data;
789 sources = 0;
790 for (count = 0; count < bb_data_size; count++)
792 __fetch_long (&line_num, ptr, 4);
793 ptr += 4;
794 if (line_num == -1)
796 /* A source file name follows. Check to see if we already have
797 a sourcefile structure for this file. */
798 s_ptr = sources;
799 while (s_ptr && strcmp (s_ptr->name, ptr))
800 s_ptr = s_ptr->next;
802 if (s_ptr == 0)
804 /* No sourcefile structure for this file name exists, create
805 a new one, and append it to the front of the sources list. */
806 s_ptr = (struct sourcefile *) xmalloc (sizeof(struct sourcefile));
807 s_ptr->name = xstrdup (ptr);
808 s_ptr->maxlineno = 0;
809 s_ptr->next = sources;
810 sources = s_ptr;
813 /* Scan past the file name. */
815 long delim;
816 do {
817 count++;
818 __fetch_long (&delim, ptr, 4);
819 ptr += 4;
820 } while (delim != line_num);
823 else if (line_num == -2)
825 long delim;
827 /* A function name follows. Ignore it. */
828 do {
829 count++;
830 __fetch_long (&delim, ptr, 4);
831 ptr += 4;
832 } while (delim != line_num);
834 /* There will be a zero before the first file name, in which case s_ptr
835 will still be uninitialized. So, only try to set the maxlineno
836 field if line_num is non-zero. */
837 else if (line_num > 0)
839 if (s_ptr->maxlineno <= line_num)
840 s_ptr->maxlineno = line_num + 1;
842 else if (line_num < 0)
844 /* Don't know what this is, but it's garbage. */
845 abort();
850 /* For calculating coverage at the function level. */
852 static int function_source_lines;
853 static int function_source_lines_executed;
854 static int function_branches;
855 static int function_branches_executed;
856 static int function_branches_taken;
857 static int function_calls;
858 static int function_calls_executed;
859 static char *function_name;
861 /* Calculate the branch taken probabilities for all arcs branches at the
862 end of this block. */
864 static void
865 calculate_branch_probs (current_graph, block_num, branch_probs, last_line_num)
866 struct bb_info_list *current_graph;
867 int block_num;
868 struct arcdata **branch_probs;
869 int last_line_num;
871 int total;
872 struct adj_list *arcptr;
873 struct arcdata *end_ptr, *a_ptr;
875 total = current_graph->bb_graph[block_num].exec_count;
876 for (arcptr = current_graph->bb_graph[block_num].succ; arcptr;
877 arcptr = arcptr->succ_next)
879 /* Ignore fall through arcs as they aren't really branches. */
881 if (arcptr->fall_through)
882 continue;
884 a_ptr = (struct arcdata *) xmalloc (sizeof (struct arcdata));
885 a_ptr->total = total;
886 if (total == 0)
887 a_ptr->hits = 0;
888 else
889 a_ptr->hits = arcptr->arc_count;
890 a_ptr->call_insn = arcptr->fake;
892 if (output_function_summary)
894 if (a_ptr->call_insn)
896 function_calls++;
897 if (a_ptr->total != 0)
898 function_calls_executed++;
900 else
902 function_branches++;
903 if (a_ptr->total != 0)
904 function_branches_executed++;
905 if (a_ptr->hits > 0)
906 function_branches_taken++;
910 /* Append the new branch to the end of the list. */
911 a_ptr->next = 0;
912 if (! branch_probs[last_line_num])
913 branch_probs[last_line_num] = a_ptr;
914 else
916 end_ptr = branch_probs[last_line_num];
917 while (end_ptr->next != 0)
918 end_ptr = end_ptr->next;
919 end_ptr->next = a_ptr;
924 /* Output summary info for a function. */
926 static void
927 function_summary ()
929 if (function_source_lines)
930 fnotice (stdout, "%6.2f%% of %d source lines executed in function %s\n",
931 (((double) function_source_lines_executed / function_source_lines)
932 * 100), function_source_lines, function_name);
933 else
934 fnotice (stdout, "No executable source lines in function %s\n",
935 function_name);
937 if (output_branch_probs)
939 if (function_branches)
941 fnotice (stdout, "%6.2f%% of %d branches executed in function %s\n",
942 (((double) function_branches_executed / function_branches)
943 * 100), function_branches, function_name);
944 fnotice (stdout,
945 "%6.2f%% of %d branches taken at least once in function %s\n",
946 (((double) function_branches_taken / function_branches)
947 * 100), function_branches, function_name);
949 else
950 fnotice (stdout, "No branches in function %s\n", function_name);
951 if (function_calls)
952 fnotice (stdout, "%6.2f%% of %d calls executed in function %s\n",
953 (((double) function_calls_executed / function_calls)
954 * 100), function_calls, function_name);
955 else
956 fnotice (stdout, "No calls in function %s\n", function_name);
960 /* Calculate line execution counts, and output the data to a .tcov file. */
962 static void
963 output_data ()
965 /* When scanning data, this is true only if the data applies to the
966 current source file. */
967 int this_file;
968 /* An array indexed by line number which indicates how many times that line
969 was executed. */
970 long *line_counts;
971 /* An array indexed by line number which indicates whether the line was
972 present in the bb file (i.e. whether it had code associate with it).
973 Lines never executed are those which both exist, and have zero execution
974 counts. */
975 char *line_exists;
976 /* An array indexed by line number, which contains a list of branch
977 probabilities, one for each branch on that line. */
978 struct arcdata **branch_probs = NULL;
979 struct sourcefile *s_ptr;
980 char *source_file_name;
981 FILE *source_file;
982 struct bb_info_list *current_graph;
983 int count;
984 char *cptr;
985 long block_num;
986 long line_num;
987 long last_line_num = 0;
988 int i;
989 struct arcdata *a_ptr;
990 /* Buffer used for reading in lines from the source file. */
991 char string[STRING_SIZE];
992 /* For calculating coverage at the file level. */
993 int total_source_lines;
994 int total_source_lines_executed;
995 int total_branches;
996 int total_branches_executed;
997 int total_branches_taken;
998 int total_calls;
999 int total_calls_executed;
1001 /* Now, for each source file, allocate an array big enough to hold a count
1002 for each line. Scan through the bb_data, and when the file name matches
1003 the current file name, then for each following line number, increment
1004 the line number execution count indicated by the execution count of
1005 the appropriate basic block. */
1007 for (s_ptr = sources; s_ptr; s_ptr = s_ptr->next)
1009 /* If this is a relative file name, and an object directory has been
1010 specified, then make it relative to the object directory name. */
1011 if (! (*s_ptr->name == '/' || *s_ptr->name == DIR_SEPARATOR
1012 /* Check for disk name on MS-DOS-based systems. */
1013 || (DIR_SEPARATOR == '\\'
1014 && s_ptr->name[1] == ':'
1015 && (s_ptr->name[2] == DIR_SEPARATOR
1016 || s_ptr->name[2] == '/')))
1017 && object_directory != 0
1018 && *object_directory != '\0')
1020 int objdir_count = strlen (object_directory);
1021 source_file_name = xmalloc (objdir_count + strlen (s_ptr->name) + 2);
1022 strcpy (source_file_name, object_directory);
1023 if (object_directory[objdir_count - 1] != '/')
1024 source_file_name[objdir_count++] = '/';
1025 strcpy (source_file_name + objdir_count, s_ptr->name);
1027 else
1028 source_file_name = s_ptr->name;
1030 line_counts = (long *) xcalloc (sizeof (long), s_ptr->maxlineno);
1031 line_exists = xcalloc (1, s_ptr->maxlineno);
1032 if (output_branch_probs)
1033 branch_probs = (struct arcdata **)
1034 xcalloc (sizeof (struct arcdata *), s_ptr->maxlineno);
1036 /* There will be a zero at the beginning of the bb info, before the
1037 first list of line numbers, so must initialize block_num to 0. */
1038 block_num = 0;
1039 this_file = 0;
1040 current_graph = 0;
1042 /* Pointer into the bb_data, incremented while scanning the data. */
1043 char *ptr = bb_data;
1044 for (count = 0; count < bb_data_size; count++)
1046 long delim;
1048 __fetch_long (&line_num, ptr, 4);
1049 ptr += 4;
1050 if (line_num == -1)
1052 /* Marks the beginning of a file name. Check to see whether
1053 this is the filename we are currently collecting data for. */
1055 if (strcmp (s_ptr->name, ptr))
1056 this_file = 0;
1057 else
1058 this_file = 1;
1060 /* Scan past the file name. */
1061 do {
1062 count++;
1063 __fetch_long (&delim, ptr, 4);
1064 ptr += 4;
1065 } while (delim != line_num);
1067 else if (line_num == -2)
1069 /* Marks the start of a new function. Advance to the next
1070 program flow graph. */
1072 if (! current_graph)
1073 current_graph = bb_graph_list;
1074 else
1076 if (block_num == current_graph->num_blocks - 1)
1077 /* Last block falls through to exit. */
1079 else if (block_num == current_graph->num_blocks - 2)
1081 if (output_branch_probs && this_file)
1082 calculate_branch_probs (current_graph, block_num,
1083 branch_probs, last_line_num);
1085 else
1087 fnotice (stderr,
1088 "didn't use all bb entries of graph, function %s\n",
1089 function_name);
1090 fnotice (stderr, "block_num = %ld, num_blocks = %d\n",
1091 block_num, current_graph->num_blocks);
1094 current_graph = current_graph->next;
1095 block_num = 0;
1097 if (output_function_summary && this_file)
1098 function_summary ();
1101 if (output_function_summary)
1103 function_source_lines = 0;
1104 function_source_lines_executed = 0;
1105 function_branches = 0;
1106 function_branches_executed = 0;
1107 function_branches_taken = 0;
1108 function_calls = 0;
1109 function_calls_executed = 0;
1112 /* Save the function name for later use. */
1113 function_name = ptr;
1115 /* Scan past the file name. */
1116 do {
1117 count++;
1118 __fetch_long (&delim, ptr, 4);
1119 ptr += 4;
1120 } while (delim != line_num);
1122 else if (line_num == 0)
1124 /* Marks the end of a block. */
1126 if (block_num >= current_graph->num_blocks)
1128 fnotice (stderr, "ERROR: too many basic blocks in .bb file %s\n",
1129 function_name);
1130 abort ();
1133 if (output_branch_probs && this_file)
1134 calculate_branch_probs (current_graph, block_num,
1135 branch_probs, last_line_num);
1137 block_num++;
1139 else if (this_file)
1141 if (output_function_summary)
1143 if (line_exists[line_num] == 0)
1144 function_source_lines++;
1145 if (line_counts[line_num] == 0
1146 && current_graph->bb_graph[block_num].exec_count != 0)
1147 function_source_lines_executed++;
1150 /* Accumulate execution data for this line number. */
1152 line_counts[line_num]
1153 += current_graph->bb_graph[block_num].exec_count;
1154 line_exists[line_num] = 1;
1155 last_line_num = line_num;
1160 if (output_function_summary && this_file)
1161 function_summary ();
1163 /* Calculate summary test coverage statistics. */
1165 total_source_lines = 0;
1166 total_source_lines_executed = 0;
1167 total_branches = 0;
1168 total_branches_executed = 0;
1169 total_branches_taken = 0;
1170 total_calls = 0;
1171 total_calls_executed = 0;
1173 for (count = 1; count < s_ptr->maxlineno; count++)
1175 if (line_exists[count])
1177 total_source_lines++;
1178 if (line_counts[count])
1179 total_source_lines_executed++;
1181 if (output_branch_probs)
1183 for (a_ptr = branch_probs[count]; a_ptr; a_ptr = a_ptr->next)
1185 if (a_ptr->call_insn)
1187 total_calls++;
1188 if (a_ptr->total != 0)
1189 total_calls_executed++;
1191 else
1193 total_branches++;
1194 if (a_ptr->total != 0)
1195 total_branches_executed++;
1196 if (a_ptr->hits > 0)
1197 total_branches_taken++;
1203 if (total_source_lines)
1204 fnotice (stdout,
1205 "%6.2f%% of %d source lines executed in file %s\n",
1206 (((double) total_source_lines_executed / total_source_lines)
1207 * 100), total_source_lines, source_file_name);
1208 else
1209 fnotice (stdout, "No executable source lines in file %s\n",
1210 source_file_name);
1212 if (output_branch_probs)
1214 if (total_branches)
1216 fnotice (stdout, "%6.2f%% of %d branches executed in file %s\n",
1217 (((double) total_branches_executed / total_branches)
1218 * 100), total_branches, source_file_name);
1219 fnotice (stdout,
1220 "%6.2f%% of %d branches taken at least once in file %s\n",
1221 (((double) total_branches_taken / total_branches)
1222 * 100), total_branches, source_file_name);
1224 else
1225 fnotice (stdout, "No branches in file %s\n", source_file_name);
1226 if (total_calls)
1227 fnotice (stdout, "%6.2f%% of %d calls executed in file %s\n",
1228 (((double) total_calls_executed / total_calls)
1229 * 100), total_calls, source_file_name);
1230 else
1231 fnotice (stdout, "No calls in file %s\n", source_file_name);
1234 if (output_gcov_file)
1236 /* Now the statistics are ready. Read in the source file one line
1237 at a time, and output that line to the gcov file preceded by
1238 its execution count if non zero. */
1240 source_file = fopen (source_file_name, "r");
1241 if (source_file == NULL)
1243 fnotice (stderr, "Could not open source file %s.\n",
1244 source_file_name);
1245 free (line_counts);
1246 free (line_exists);
1247 continue;
1250 count = strlen (source_file_name);
1251 cptr = rindex (s_ptr->name, '/');
1252 if (cptr)
1253 cptr = cptr + 1;
1254 else
1255 cptr = s_ptr->name;
1256 if (output_long_names && strcmp (cptr, input_file_name))
1258 gcov_file_name = xmalloc (count + 7 + strlen (input_file_name));
1260 cptr = rindex (input_file_name, '/');
1261 if (cptr)
1262 strcpy (gcov_file_name, cptr + 1);
1263 else
1264 strcpy (gcov_file_name, input_file_name);
1266 strcat (gcov_file_name, ".");
1268 cptr = rindex (source_file_name, '/');
1269 if (cptr)
1270 strcat (gcov_file_name, cptr + 1);
1271 else
1272 strcat (gcov_file_name, source_file_name);
1274 else
1276 gcov_file_name = xmalloc (count + 6);
1277 cptr = rindex (source_file_name, '/');
1278 if (cptr)
1279 strcpy (gcov_file_name, cptr + 1);
1280 else
1281 strcpy (gcov_file_name, source_file_name);
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
1286 the same basename, e.g. tmp.c and tmp.h. */
1287 strcat (gcov_file_name, ".gcov");
1289 gcov_file = fopen (gcov_file_name, "w");
1291 if (gcov_file == NULL)
1293 fnotice (stderr, "Could not open output file %s.\n",
1294 gcov_file_name);
1295 fclose (source_file);
1296 free (line_counts);
1297 free (line_exists);
1298 continue;
1301 fnotice (stdout, "Creating %s.\n", gcov_file_name);
1303 for (count = 1; count < s_ptr->maxlineno; count++)
1305 char *retval;
1306 int len;
1308 retval = fgets (string, STRING_SIZE, source_file);
1310 /* For lines which don't exist in the .bb file, print nothing
1311 before the source line. For lines which exist but were never
1312 executed, print ###### before the source line. Otherwise,
1313 print the execution count before the source line. */
1314 /* There are 16 spaces of indentation added before the source
1315 line so that tabs won't be messed up. */
1316 if (line_exists[count])
1318 if (line_counts[count])
1319 fprintf (gcov_file, "%12ld %s", line_counts[count],
1320 string);
1321 else
1322 fprintf (gcov_file, " ###### %s", string);
1324 else
1325 fprintf (gcov_file, "\t\t%s", string);
1327 /* In case the source file line is larger than our buffer, keep
1328 reading and outputting lines until we get a newline. */
1329 len = strlen (string);
1330 while ((len == 0 || string[strlen (string) - 1] != '\n')
1331 && retval != NULL)
1333 retval = fgets (string, STRING_SIZE, source_file);
1334 fputs (string, gcov_file);
1337 if (output_branch_probs)
1339 for (i = 0, a_ptr = branch_probs[count]; a_ptr;
1340 a_ptr = a_ptr->next, i++)
1342 if (a_ptr->call_insn)
1344 if (a_ptr->total == 0)
1345 fnotice (gcov_file, "call %d never executed\n", i);
1346 else
1348 if (output_branch_counts)
1349 fnotice (gcov_file,
1350 "call %d returns = %d\n",
1351 i, a_ptr->total - a_ptr->hits);
1352 else
1353 fnotice (gcov_file,
1354 "call %d returns = %d%%\n",
1355 i, 100 - ((a_ptr->hits * 100) +
1356 (a_ptr->total >> 1))/a_ptr->total);
1359 else
1361 if (a_ptr->total == 0)
1362 fnotice (gcov_file, "branch %d never executed\n",
1364 else
1366 if (output_branch_counts)
1367 fnotice (gcov_file,
1368 "branch %d taken = %d\n",
1369 i, a_ptr->hits);
1370 else
1371 fnotice (gcov_file,
1372 "branch %d taken = %d%%\n", i,
1373 ((a_ptr->hits * 100) +
1374 (a_ptr->total >> 1))/
1375 a_ptr->total);
1382 /* Gracefully handle errors while reading the source file. */
1383 if (retval == NULL)
1385 fnotice (stderr,
1386 "Unexpected EOF while reading source file %s.\n",
1387 source_file_name);
1388 break;
1392 /* Handle all remaining source lines. There may be lines
1393 after the last line of code. */
1396 char *retval = fgets (string, STRING_SIZE, source_file);
1397 while (retval != NULL)
1399 int len;
1401 fprintf (gcov_file, "\t\t%s", string);
1403 /* In case the source file line is larger than our buffer, keep
1404 reading and outputting lines until we get a newline. */
1405 len = strlen (string);
1406 while ((len == 0 || string[strlen (string) - 1] != '\n')
1407 && retval != NULL)
1409 retval = fgets (string, STRING_SIZE, source_file);
1410 fputs (string, gcov_file);
1413 retval = fgets (string, STRING_SIZE, source_file);
1417 fclose (source_file);
1418 fclose (gcov_file);
1421 free (line_counts);
1422 free (line_exists);