Sun Sep 13 08:13:39 1998 Ben Elliston <bje@cygnus.com>
[official-gcc.git] / gcc / gcov.c
blobeff68f1608a3a2ab31044dc6aa5840cfb209b426
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 "system.h"
46 #include <sys/stat.h>
47 #include "gansidecl.h"
49 #include "gcov-io.h"
51 /* The .bb file format consists of several lists of 4-byte integers
52 which are the line numbers of each basic block in the file. Each
53 list is terminated by a zero. These lists correspond to the basic
54 blocks in the reconstructed program flow graph.
56 A line number of -1 indicates that a source file name (padded to a
57 long boundary) follows. The padded file name is followed by
58 another -1 to make it easy to scan past file names. A -2 indicates
59 that a function name (padded to a long boundary) follows; the name
60 is followed by another -2 to make it easy to scan past the function
61 name.
63 The .bbg file contains enough info to enable gcov to reconstruct the
64 program flow graph. The first word is the number of basic blocks,
65 the second word is the number of arcs, followed by the list of arcs
66 (source bb, dest bb pairs), then a -1, then the number of instrumented
67 arcs followed by the instrumented arcs, followed by another -1. This
68 is repeated for each function.
70 The .da file contains the execution count for each instrumented branch.
72 The .bb and .bbg files are created by giving GCC the -ftest-coverage option,
73 and the .da files are created when an executable compiled with
74 -fprofile-arcs is run. */
76 /* The functions in this file for creating and solution program flow graphs
77 are very similar to functions in the gcc source file profile.c. */
79 char gcov_version_string[] = "GNU gcov version 1.5\n";
81 /* This is the size of the buffer used to read in source file lines. */
83 #define STRING_SIZE 200
85 /* One copy of this structure is created for each source file mentioned in the
86 .bb file. */
88 struct sourcefile
90 char *name;
91 int maxlineno;
92 struct sourcefile *next;
95 /* This points to the head of the sourcefile structure list. */
97 struct sourcefile *sources;
99 /* One of these is dynamically created whenever we identify an arc in the
100 function. */
102 struct adj_list {
103 int source;
104 int target;
105 int arc_count;
106 unsigned int count_valid : 1;
107 unsigned int on_tree : 1;
108 unsigned int fake : 1;
109 unsigned int fall_through : 1;
110 #if 0
111 /* Not needed for gcov, but defined in profile.c. */
112 rtx branch_insn;
113 #endif
114 struct adj_list *pred_next;
115 struct adj_list *succ_next;
118 /* Count the number of basic blocks, and create an array of these structures,
119 one for each bb in the function. */
121 struct bb_info {
122 struct adj_list *succ;
123 struct adj_list *pred;
124 int succ_count;
125 int pred_count;
126 int exec_count;
127 unsigned int count_valid : 1;
128 unsigned int on_tree : 1;
129 #if 0
130 /* Not needed for gcov, but defined in profile.c. */
131 rtx first_insn;
132 #endif
135 /* When outputting branch probabilities, one of these structures is created
136 for each branch/call. */
138 struct arcdata
140 int prob;
141 int call_insn;
142 struct arcdata *next;
145 /* Used to save the list of bb_graphs, one per function. */
147 struct bb_info_list {
148 /* Indexed by block number, holds the basic block graph for one function. */
149 struct bb_info *bb_graph;
150 int num_blocks;
151 struct bb_info_list *next;
154 /* Holds a list of function basic block graphs. */
156 static struct bb_info_list *bb_graph_list = 0;
158 /* Name and file pointer of the input file for the basic block graph. */
160 static char *bbg_file_name;
161 static FILE *bbg_file;
163 /* Name and file pointer of the input file for the arc count data. */
165 static char *da_file_name;
166 static FILE *da_file;
168 /* Name and file pointer of the input file for the basic block line counts. */
170 static char *bb_file_name;
171 static FILE *bb_file;
173 /* Holds the entire contents of the bb_file read into memory. */
175 static char *bb_data;
177 /* Size of bb_data array in longs. */
179 static long bb_data_size;
181 /* Name and file pointer of the output file. */
183 static char *gcov_file_name;
184 static FILE *gcov_file;
186 /* Name of the file mentioned on the command line. */
188 static char *input_file_name = 0;
190 /* Output branch probabilities if true. */
192 static int output_branch_probs = 0;
194 /* Output a gcov file if this is true. This is on by default, and can
195 be turned off by the -n option. */
197 static int output_gcov_file = 1;
199 /* For included files, make the gcov output file name include the name of
200 the input source file. For example, if x.h is included in a.c, then the
201 output file name is a.c.x.h.gcov instead of x.h.gcov. This works only
202 when a single source file is specified. */
204 static int output_long_names = 0;
206 /* Output summary info for each function. */
208 static int output_function_summary = 0;
210 /* Object directory file prefix. This is the directory where .bb and .bbg
211 files are looked for, if non-zero. */
213 static char *object_directory = 0;
215 /* Forward declarations. */
216 static void process_args PROTO ((int, char **));
217 static void open_files PROTO ((void));
218 static void read_files PROTO ((void));
219 static void scan_for_source_files PROTO ((void));
220 static void output_data PROTO ((void));
221 static void print_usage PROTO ((void));
222 char * xmalloc ();
225 main (argc, argv)
226 int argc;
227 char **argv;
229 process_args (argc, argv);
231 open_files ();
233 read_files ();
235 scan_for_source_files ();
237 output_data ();
239 return 0;
242 char *
243 xmalloc (size)
244 unsigned size;
246 register char *value = (char *) malloc (size);
247 if (value == 0)
249 fprintf (stderr, "error: virtual memory exhausted");
250 exit (FATAL_EXIT_CODE);
252 return value;
255 /* More 'friendly' abort that prints the line and file.
256 config.h can #define abort fancy_abort if you like that sort of thing. */
258 void
259 fancy_abort ()
261 fprintf (stderr, "Internal gcc abort.\n");
262 exit (FATAL_EXIT_CODE);
265 /* Print a usage message and exit. */
267 static void
268 print_usage ()
270 fprintf (stderr, "gcov [-b] [-v] [-n] [-l] [-f] [-o OBJDIR] file\n");
271 exit (FATAL_EXIT_CODE);
274 /* Parse the command line. */
276 static void
277 process_args (argc, argv)
278 int argc;
279 char **argv;
281 int i;
283 for (i = 1; i < argc; i++)
285 if (argv[i][0] == '-')
287 if (argv[i][1] == 'b')
288 output_branch_probs = 1;
289 else if (argv[i][1] == 'v')
290 fputs (gcov_version_string, stderr);
291 else if (argv[i][1] == 'n')
292 output_gcov_file = 0;
293 else if (argv[i][1] == 'l')
294 output_long_names = 1;
295 else if (argv[i][1] == 'f')
296 output_function_summary = 1;
297 else if (argv[i][1] == 'o' && argv[i][2] == '\0')
298 object_directory = argv[++i];
299 else
300 print_usage ();
302 else if (! input_file_name)
303 input_file_name = argv[i];
304 else
305 print_usage ();
308 if (! input_file_name)
309 print_usage ();
313 /* Find and open the .bb, .da, and .bbg files. */
315 static void
316 open_files ()
318 int count, objdir_count;
319 char *cptr;
321 /* Determine the names of the .bb, .bbg, and .da files. Strip off the
322 extension, if any, and append the new extensions. */
323 count = strlen (input_file_name);
324 if (object_directory)
325 objdir_count = strlen (object_directory);
326 else
327 objdir_count = 0;
329 da_file_name = xmalloc (count + objdir_count + 4);
330 bb_file_name = xmalloc (count + objdir_count + 4);
331 bbg_file_name = xmalloc (count + objdir_count + 5);
333 if (object_directory)
335 strcpy (da_file_name, object_directory);
336 strcpy (bb_file_name, object_directory);
337 strcpy (bbg_file_name, object_directory);
339 if (object_directory[objdir_count - 1] != '/')
341 strcat (da_file_name, "/");
342 strcat (bb_file_name, "/");
343 strcat (bbg_file_name, "/");
346 cptr = rindex (input_file_name, '/');
347 if (cptr)
349 strcat (da_file_name, cptr + 1);
350 strcat (bb_file_name, cptr + 1);
351 strcat (bbg_file_name, cptr + 1);
353 else
355 strcat (da_file_name, input_file_name);
356 strcat (bb_file_name, input_file_name);
357 strcat (bbg_file_name, input_file_name);
360 else
362 strcpy (da_file_name, input_file_name);
363 strcpy (bb_file_name, input_file_name);
364 strcpy (bbg_file_name, input_file_name);
367 cptr = rindex (bb_file_name, '.');
368 if (cptr)
369 strcpy (cptr, ".bb");
370 else
371 strcat (bb_file_name, ".bb");
373 cptr = rindex (da_file_name, '.');
374 if (cptr)
375 strcpy (cptr, ".da");
376 else
377 strcat (da_file_name, ".da");
379 cptr = rindex (bbg_file_name, '.');
380 if (cptr)
381 strcpy (cptr, ".bbg");
382 else
383 strcat (bbg_file_name, ".bbg");
385 bb_file = fopen (bb_file_name, "r");
386 if (bb_file == NULL)
388 fprintf (stderr, "Could not open basic block file %s.\n", bb_file_name);
389 exit (FATAL_EXIT_CODE);
392 /* If none of the functions in the file were executed, then there won't
393 be a .da file. Just assume that all counts are zero in this case. */
394 da_file = fopen (da_file_name, "r");
395 if (da_file == NULL)
397 fprintf (stderr, "Could not open data file %s.\n", da_file_name);
398 fprintf (stderr, "Assuming that all execution counts are zero.\n");
401 bbg_file = fopen (bbg_file_name, "r");
402 if (bbg_file == NULL)
404 fprintf (stderr, "Could not open program flow graph file %s.\n",
405 bbg_file_name);
406 exit (FATAL_EXIT_CODE);
409 /* Check for empty .bbg file. This indicates that there is no executable
410 code in this source file. */
411 /* Set the EOF condition if at the end of file. */
412 ungetc (getc (bbg_file), bbg_file);
413 if (feof (bbg_file))
415 fprintf (stderr, "No executable code associated with file %s.\n",
416 input_file_name);
417 exit (FATAL_EXIT_CODE);
421 /* Initialize a new arc. */
423 static void
424 init_arc (arcptr, source, target, bb_graph)
425 struct adj_list *arcptr;
426 int source, target;
427 struct bb_info *bb_graph;
429 arcptr->target = target;
430 arcptr->source = source;
432 arcptr->arc_count = 0;
433 arcptr->count_valid = 0;
434 arcptr->on_tree = 0;
435 arcptr->fake = 0;
436 arcptr->fall_through = 0;
438 arcptr->succ_next = bb_graph[source].succ;
439 bb_graph[source].succ = arcptr;
440 bb_graph[source].succ_count++;
442 arcptr->pred_next = bb_graph[target].pred;
443 bb_graph[target].pred = arcptr;
444 bb_graph[target].pred_count++;
448 /* Reverse the arcs on a arc list. */
450 static struct adj_list *
451 reverse_arcs (arcptr)
452 struct adj_list *arcptr;
454 struct adj_list *prev = 0;
455 struct adj_list *next;
457 for ( ; arcptr; arcptr = next)
459 next = arcptr->succ_next;
460 arcptr->succ_next = prev;
461 prev = arcptr;
464 return prev;
468 /* Construct the program flow graph from the .bbg file, and read in the data
469 in the .da file. */
471 static void
472 create_program_flow_graph (bptr)
473 struct bb_info_list *bptr;
475 long num_blocks, number_arcs, src, dest, flag_bits, num_arcs_per_block;
476 int i;
477 struct adj_list *arcptr;
478 struct bb_info *bb_graph;
480 /* Read the number of blocks. */
481 __read_long (&num_blocks, bbg_file, 4);
483 /* Create an array of size bb number of bb_info structs. Bzero it. */
484 bb_graph = (struct bb_info *) xmalloc (num_blocks
485 * sizeof (struct bb_info));
486 bzero ((char *) bb_graph, sizeof (struct bb_info) * num_blocks);
488 bptr->bb_graph = bb_graph;
489 bptr->num_blocks = num_blocks;
491 /* Read and create each arc from the .bbg file. */
492 __read_long (&number_arcs, bbg_file, 4);
493 for (i = 0; i < num_blocks; i++)
495 int j;
497 __read_long (&num_arcs_per_block, bbg_file, 4);
498 for (j = 0; j < num_arcs_per_block; j++)
500 if (number_arcs-- < 0)
501 abort ();
503 src = i;
504 __read_long (&dest, bbg_file, 4);
506 arcptr = (struct adj_list *) xmalloc (sizeof (struct adj_list));
507 init_arc (arcptr, src, dest, bb_graph);
509 __read_long (&flag_bits, bbg_file, 4);
510 arcptr->on_tree = flag_bits & 0x1;
511 arcptr->fake = !! (flag_bits & 0x2);
512 arcptr->fall_through = !! (flag_bits & 0x4);
516 if (number_arcs)
517 abort ();
519 /* Read and ignore the -1 separating the arc list from the arc list of the
520 next function. */
521 __read_long (&src, bbg_file, 4);
522 if (src != -1)
523 abort ();
525 /* Must reverse the order of all succ arcs, to ensure that they match
526 the order of the data in the .da file. */
528 for (i = 0; i < num_blocks; i++)
529 if (bb_graph[i].succ)
530 bb_graph[i].succ = reverse_arcs (bb_graph[i].succ);
532 /* For each arc not on the spanning tree, set its execution count from
533 the .da file. */
535 /* The first count in the .da file is the number of times that the function
536 was entered. This is the exec_count for block zero. */
538 /* This duplicates code in branch_prob in profile.c. */
540 for (i = 0; i < num_blocks; i++)
541 for (arcptr = bb_graph[i].succ; arcptr; arcptr = arcptr->succ_next)
542 if (! arcptr->on_tree)
544 long tmp_count = 0;;
545 if (da_file && __read_long (&tmp_count, da_file, 8))
546 abort();
548 arcptr->arc_count = tmp_count;
549 arcptr->count_valid = 1;
550 bb_graph[i].succ_count--;
551 bb_graph[arcptr->target].pred_count--;
555 static void
556 solve_program_flow_graph (bptr)
557 struct bb_info_list *bptr;
559 int passes, changes, total;
560 int i;
561 struct adj_list *arcptr;
562 struct bb_info *bb_graph;
563 int num_blocks;
565 num_blocks = bptr->num_blocks;
566 bb_graph = bptr->bb_graph;
568 /* For every block in the file,
569 - if every exit/entrance arc has a known count, then set the block count
570 - if the block count is known, and every exit/entrance arc but one has
571 a known execution count, then set the count of the remaining arc
573 As arc counts are set, decrement the succ/pred count, but don't delete
574 the arc, that way we can easily tell when all arcs are known, or only
575 one arc is unknown. */
577 /* The order that the basic blocks are iterated through is important.
578 Since the code that finds spanning trees starts with block 0, low numbered
579 arcs are put on the spanning tree in preference to high numbered arcs.
580 Hence, most instrumented arcs are at the end. Graph solving works much
581 faster if we propagate numbers from the end to the start.
583 This takes an average of slightly more than 3 passes. */
585 changes = 1;
586 passes = 0;
587 while (changes)
589 passes++;
590 changes = 0;
592 for (i = num_blocks - 1; i >= 0; i--)
594 if (! bb_graph[i].count_valid)
596 if (bb_graph[i].succ_count == 0)
598 total = 0;
599 for (arcptr = bb_graph[i].succ; arcptr;
600 arcptr = arcptr->succ_next)
601 total += arcptr->arc_count;
602 bb_graph[i].exec_count = total;
603 bb_graph[i].count_valid = 1;
604 changes = 1;
606 else if (bb_graph[i].pred_count == 0)
608 total = 0;
609 for (arcptr = bb_graph[i].pred; arcptr;
610 arcptr = arcptr->pred_next)
611 total += arcptr->arc_count;
612 bb_graph[i].exec_count = total;
613 bb_graph[i].count_valid = 1;
614 changes = 1;
617 if (bb_graph[i].count_valid)
619 if (bb_graph[i].succ_count == 1)
621 total = 0;
622 /* One of the counts will be invalid, but it is zero,
623 so adding it in also doesn't hurt. */
624 for (arcptr = bb_graph[i].succ; arcptr;
625 arcptr = arcptr->succ_next)
626 total += arcptr->arc_count;
627 /* Calculate count for remaining arc by conservation. */
628 total = bb_graph[i].exec_count - total;
629 /* Search for the invalid arc, and set its count. */
630 for (arcptr = bb_graph[i].succ; arcptr;
631 arcptr = arcptr->succ_next)
632 if (! arcptr->count_valid)
633 break;
634 if (! arcptr)
635 abort ();
636 arcptr->count_valid = 1;
637 arcptr->arc_count = total;
638 bb_graph[i].succ_count--;
640 bb_graph[arcptr->target].pred_count--;
641 changes = 1;
643 if (bb_graph[i].pred_count == 1)
645 total = 0;
646 /* One of the counts will be invalid, but it is zero,
647 so adding it in also doesn't hurt. */
648 for (arcptr = bb_graph[i].pred; arcptr;
649 arcptr = arcptr->pred_next)
650 total += arcptr->arc_count;
651 /* Calculate count for remaining arc by conservation. */
652 total = bb_graph[i].exec_count - total;
653 /* Search for the invalid arc, and set its count. */
654 for (arcptr = bb_graph[i].pred; arcptr;
655 arcptr = arcptr->pred_next)
656 if (! arcptr->count_valid)
657 break;
658 if (! arcptr)
659 abort ();
660 arcptr->count_valid = 1;
661 arcptr->arc_count = total;
662 bb_graph[i].pred_count--;
664 bb_graph[arcptr->source].succ_count--;
665 changes = 1;
671 /* If the graph has been correctly solved, every block will have a
672 succ and pred count of zero. */
673 for (i = 0; i < num_blocks; i++)
674 if (bb_graph[i].succ_count || bb_graph[i].pred_count)
675 abort ();
679 static void
680 read_files ()
682 struct stat buf;
683 struct bb_info_list *list_end = 0;
684 struct bb_info_list *b_ptr;
685 long total;
687 /* Read and ignore the first word of the .da file, which is the count of
688 how many numbers follow. */
689 if (da_file && __read_long (&total, da_file, 8))
690 abort();
692 while (! feof (bbg_file))
694 b_ptr = (struct bb_info_list *) xmalloc (sizeof (struct bb_info_list));
696 b_ptr->next = 0;
697 if (list_end)
698 list_end->next = b_ptr;
699 else
700 bb_graph_list = b_ptr;
701 list_end = b_ptr;
703 /* Read in the data in the .bbg file and reconstruct the program flow
704 graph for one function. */
705 create_program_flow_graph (b_ptr);
707 /* Set the EOF condition if at the end of file. */
708 ungetc (getc (bbg_file), bbg_file);
711 /* Check to make sure the .da file data is valid. */
713 if (da_file)
715 if (feof (da_file))
716 fprintf (stderr, ".da file contents exhausted too early\n");
717 /* Should be at end of file now. */
718 if (__read_long (&total, da_file, 8) == 0)
719 fprintf (stderr, ".da file contents not exhausted\n");
722 /* Calculate all of the basic block execution counts and branch
723 taken probabilities. */
725 for (b_ptr = bb_graph_list; b_ptr; b_ptr = b_ptr->next)
726 solve_program_flow_graph (b_ptr);
728 /* Read in all of the data from the .bb file. This info will be accessed
729 sequentially twice. */
730 stat (bb_file_name, &buf);
731 bb_data_size = buf.st_size / 4;
733 bb_data = (char *) xmalloc ((unsigned) buf.st_size);
734 fread (bb_data, sizeof (char), buf.st_size, bb_file);
736 fclose (bb_file);
737 if (da_file)
738 fclose (da_file);
739 fclose (bbg_file);
743 /* Scan the data in the .bb file to find all source files referenced,
744 and the largest line number mentioned in each one. */
746 static void
747 scan_for_source_files ()
749 struct sourcefile *s_ptr = NULL;
750 char *ptr;
751 int count;
752 long line_num;
754 /* Search the bb_data to find:
755 1) The number of sources files contained herein, and
756 2) The largest line number for each source file. */
758 ptr = bb_data;
759 sources = 0;
760 for (count = 0; count < bb_data_size; count++)
762 __fetch_long (&line_num, ptr, 4);
763 ptr += 4;
764 if (line_num == -1)
766 /* A source file name follows. Check to see if we already have
767 a sourcefile structure for this file. */
768 s_ptr = sources;
769 while (s_ptr && strcmp (s_ptr->name, ptr))
770 s_ptr = s_ptr->next;
772 if (s_ptr == 0)
774 /* No sourcefile structure for this file name exists, create
775 a new one, and append it to the front of the sources list. */
776 s_ptr = (struct sourcefile *) xmalloc (sizeof(struct sourcefile));
777 s_ptr->name = xmalloc (strlen ((char *) ptr) + 1);
778 strcpy (s_ptr->name, (char *) ptr);
779 s_ptr->maxlineno = 0;
780 s_ptr->next = sources;
781 sources = s_ptr;
784 /* Scan past the file name. */
786 long delim;
787 do {
788 count++;
789 __fetch_long (&delim, ptr, 4);
790 ptr += 4;
791 } while (delim != line_num);
794 else if (line_num == -2)
796 long delim;
798 /* A function name follows. Ignore it. */
799 do {
800 count++;
801 __fetch_long (&delim, ptr, 4);
802 ptr += 4;
803 } while (delim != line_num);
805 /* There will be a zero before the first file name, in which case s_ptr
806 will still be uninitialized. So, only try to set the maxlineno
807 field if line_num is non-zero. */
808 else if (line_num > 0)
810 if (s_ptr->maxlineno <= line_num)
811 s_ptr->maxlineno = line_num + 1;
813 else if (line_num < 0)
815 /* Don't know what this is, but it's garbage. */
816 abort();
821 /* For calculating coverage at the function level. */
823 static int function_source_lines;
824 static int function_source_lines_executed;
825 static int function_branches;
826 static int function_branches_executed;
827 static int function_branches_taken;
828 static int function_calls;
829 static int function_calls_executed;
830 static char *function_name;
832 /* Calculate the branch taken probabilities for all arcs branches at the
833 end of this block. */
835 static void
836 calculate_branch_probs (current_graph, block_num, branch_probs, last_line_num)
837 struct bb_info_list *current_graph;
838 int block_num;
839 struct arcdata **branch_probs;
840 int last_line_num;
842 int total;
843 struct adj_list *arcptr;
844 struct arcdata *end_ptr, *a_ptr;
846 total = current_graph->bb_graph[block_num].exec_count;
847 for (arcptr = current_graph->bb_graph[block_num].succ; arcptr;
848 arcptr = arcptr->succ_next)
850 /* Ignore fall through arcs as they aren't really branches. */
852 if (arcptr->fall_through)
853 continue;
855 a_ptr = (struct arcdata *) xmalloc (sizeof (struct arcdata));
856 if (total == 0)
857 a_ptr->prob = -1;
858 else
859 a_ptr->prob = ((arcptr->arc_count * 100) + (total >> 1)) / total;
860 a_ptr->call_insn = arcptr->fake;
862 if (output_function_summary)
864 if (a_ptr->call_insn)
866 function_calls++;
867 if (a_ptr->prob != -1)
868 function_calls_executed++;
870 else
872 function_branches++;
873 if (a_ptr->prob != -1)
874 function_branches_executed++;
875 if (a_ptr->prob > 0)
876 function_branches_taken++;
880 /* Append the new branch to the end of the list. */
881 a_ptr->next = 0;
882 if (! branch_probs[last_line_num])
883 branch_probs[last_line_num] = a_ptr;
884 else
886 end_ptr = branch_probs[last_line_num];
887 while (end_ptr->next != 0)
888 end_ptr = end_ptr->next;
889 end_ptr->next = a_ptr;
894 /* Output summary info for a function. */
896 static void
897 function_summary ()
899 if (function_source_lines)
900 fprintf (stdout, "%6.2f%% of %d source lines executed in function %s\n",
901 (((double) function_source_lines_executed / function_source_lines)
902 * 100), function_source_lines, function_name);
903 else
904 fprintf (stdout, "No executable source lines in function %s\n",
905 function_name);
907 if (output_branch_probs)
909 if (function_branches)
911 fprintf (stdout, "%6.2f%% of %d branches executed in function %s\n",
912 (((double) function_branches_executed / function_branches)
913 * 100), function_branches, function_name);
914 fprintf (stdout,
915 "%6.2f%% of %d branches taken at least once in function %s\n",
916 (((double) function_branches_taken / function_branches)
917 * 100), function_branches, function_name);
919 else
920 fprintf (stdout, "No branches in function %s\n", function_name);
921 if (function_calls)
922 fprintf (stdout, "%6.2f%% of %d calls executed in function %s\n",
923 (((double) function_calls_executed / function_calls)
924 * 100), function_calls, function_name);
925 else
926 fprintf (stdout, "No calls in function %s\n", function_name);
930 /* Calculate line execution counts, and output the data to a .tcov file. */
932 static void
933 output_data ()
935 /* When scanning data, this is true only if the data applies to the
936 current source file. */
937 int this_file;
938 /* An array indexed by line number which indicates how many times that line
939 was executed. */
940 long *line_counts;
941 /* An array indexed by line number which indicates whether the line was
942 present in the bb file (i.e. whether it had code associate with it).
943 Lines never executed are those which both exist, and have zero execution
944 counts. */
945 char *line_exists;
946 /* An array indexed by line number, which contains a list of branch
947 probabilities, one for each branch on that line. */
948 struct arcdata **branch_probs = NULL;
949 struct sourcefile *s_ptr;
950 char *source_file_name;
951 FILE *source_file;
952 struct bb_info_list *current_graph;
953 int count;
954 char *cptr;
955 long block_num;
956 long line_num;
957 long last_line_num = 0;
958 int i;
959 struct arcdata *a_ptr;
960 /* Buffer used for reading in lines from the source file. */
961 char string[STRING_SIZE];
962 /* For calculating coverage at the file level. */
963 int total_source_lines;
964 int total_source_lines_executed;
965 int total_branches;
966 int total_branches_executed;
967 int total_branches_taken;
968 int total_calls;
969 int total_calls_executed;
971 /* Now, for each source file, allocate an array big enough to hold a count
972 for each line. Scan through the bb_data, and when the file name matches
973 the current file name, then for each following line number, increment
974 the line number execution count indicated by the execution count of
975 the appropriate basic block. */
977 for (s_ptr = sources; s_ptr; s_ptr = s_ptr->next)
979 /* If this is a relative file name, and an object directory has been
980 specified, then make it relative to the object directory name. */
981 if (*s_ptr->name != '/' && object_directory != 0
982 && *object_directory != '\0')
984 int objdir_count = strlen (object_directory);
985 source_file_name = xmalloc (objdir_count + strlen (s_ptr->name) + 2);
986 strcpy (source_file_name, object_directory);
987 if (object_directory[objdir_count - 1] != '/')
988 source_file_name[objdir_count++] = '/';
989 strcpy (source_file_name + objdir_count, s_ptr->name);
991 else
992 source_file_name = s_ptr->name;
994 line_counts = (long *) xmalloc (sizeof (long) * s_ptr->maxlineno);
995 bzero ((char *) line_counts, sizeof (long) * s_ptr->maxlineno);
996 line_exists = xmalloc (s_ptr->maxlineno);
997 bzero (line_exists, s_ptr->maxlineno);
998 if (output_branch_probs)
1000 branch_probs = (struct arcdata **) xmalloc (sizeof (struct arcdata **)
1001 * s_ptr->maxlineno);
1002 bzero ((char *) branch_probs,
1003 sizeof (struct arcdata **) * s_ptr->maxlineno);
1006 /* There will be a zero at the beginning of the bb info, before the
1007 first list of line numbers, so must initialize block_num to 0. */
1008 block_num = 0;
1009 this_file = 0;
1010 current_graph = 0;
1012 /* Pointer into the bb_data, incremented while scanning the data. */
1013 char *ptr = bb_data;
1014 for (count = 0; count < bb_data_size; count++)
1016 long delim;
1018 __fetch_long (&line_num, ptr, 4);
1019 ptr += 4;
1020 if (line_num == -1)
1022 /* Marks the beginning of a file name. Check to see whether
1023 this is the filename we are currently collecting data for. */
1025 if (strcmp (s_ptr->name, ptr))
1026 this_file = 0;
1027 else
1028 this_file = 1;
1030 /* Scan past the file name. */
1031 do {
1032 count++;
1033 __fetch_long (&delim, ptr, 4);
1034 ptr += 4;
1035 } while (delim != line_num);
1037 else if (line_num == -2)
1039 /* Marks the start of a new function. Advance to the next
1040 program flow graph. */
1042 if (! current_graph)
1043 current_graph = bb_graph_list;
1044 else
1046 if (block_num == current_graph->num_blocks - 1)
1047 /* Last block falls through to exit. */
1049 else if (block_num == current_graph->num_blocks - 2)
1051 if (output_branch_probs && this_file)
1052 calculate_branch_probs (current_graph, block_num,
1053 branch_probs, last_line_num);
1055 else
1057 fprintf (stderr,
1058 "didn't use all bb entries of graph, function %s\n",
1059 function_name);
1060 fprintf (stderr, "block_num = %ld, num_blocks = %d\n",
1061 block_num, current_graph->num_blocks);
1064 current_graph = current_graph->next;
1065 block_num = 0;
1067 if (output_function_summary && this_file)
1068 function_summary ();
1071 if (output_function_summary)
1073 function_source_lines = 0;
1074 function_source_lines_executed = 0;
1075 function_branches = 0;
1076 function_branches_executed = 0;
1077 function_branches_taken = 0;
1078 function_calls = 0;
1079 function_calls_executed = 0;
1082 /* Save the function name for later use. */
1083 function_name = ptr;
1085 /* Scan past the file name. */
1086 do {
1087 count++;
1088 __fetch_long (&delim, ptr, 4);
1089 ptr += 4;
1090 } while (delim != line_num);
1092 else if (line_num == 0)
1094 /* Marks the end of a block. */
1096 if (block_num >= current_graph->num_blocks)
1098 fprintf (stderr, "ERROR: too many basic blocks in .bb file %s\n",
1099 function_name);
1100 abort ();
1103 if (output_branch_probs && this_file)
1104 calculate_branch_probs (current_graph, block_num,
1105 branch_probs, last_line_num);
1107 block_num++;
1109 else if (this_file)
1111 if (output_function_summary)
1113 if (line_exists[line_num] == 0)
1114 function_source_lines++;
1115 if (line_counts[line_num] == 0
1116 && current_graph->bb_graph[block_num].exec_count != 0)
1117 function_source_lines_executed++;
1120 /* Accumulate execution data for this line number. */
1122 line_counts[line_num]
1123 += current_graph->bb_graph[block_num].exec_count;
1124 line_exists[line_num] = 1;
1125 last_line_num = line_num;
1130 if (output_function_summary && this_file)
1131 function_summary ();
1133 /* Calculate summary test coverage statistics. */
1135 total_source_lines = 0;
1136 total_source_lines_executed = 0;
1137 total_branches = 0;
1138 total_branches_executed = 0;
1139 total_branches_taken = 0;
1140 total_calls = 0;
1141 total_calls_executed = 0;
1143 for (count = 1; count < s_ptr->maxlineno; count++)
1145 if (line_exists[count])
1147 total_source_lines++;
1148 if (line_counts[count])
1149 total_source_lines_executed++;
1151 if (output_branch_probs)
1153 for (a_ptr = branch_probs[count]; a_ptr; a_ptr = a_ptr->next)
1155 if (a_ptr->call_insn)
1157 total_calls++;
1158 if (a_ptr->prob != -1)
1159 total_calls_executed++;
1161 else
1163 total_branches++;
1164 if (a_ptr->prob != -1)
1165 total_branches_executed++;
1166 if (a_ptr->prob > 0)
1167 total_branches_taken++;
1173 if (total_source_lines)
1174 fprintf (stdout,
1175 "%6.2f%% of %d source lines executed in file %s\n",
1176 (((double) total_source_lines_executed / total_source_lines)
1177 * 100), total_source_lines, source_file_name);
1178 else
1179 fprintf (stdout, "No executable source lines in file %s\n",
1180 source_file_name);
1182 if (output_branch_probs)
1184 if (total_branches)
1186 fprintf (stdout, "%6.2f%% of %d branches executed in file %s\n",
1187 (((double) total_branches_executed / total_branches)
1188 * 100), total_branches, source_file_name);
1189 fprintf (stdout,
1190 "%6.2f%% of %d branches taken at least once in file %s\n",
1191 (((double) total_branches_taken / total_branches)
1192 * 100), total_branches, source_file_name);
1194 else
1195 fprintf (stdout, "No branches in file %s\n", source_file_name);
1196 if (total_calls)
1197 fprintf (stdout, "%6.2f%% of %d calls executed in file %s\n",
1198 (((double) total_calls_executed / total_calls)
1199 * 100), total_calls, source_file_name);
1200 else
1201 fprintf (stdout, "No calls in file %s\n", source_file_name);
1204 if (output_gcov_file)
1206 /* Now the statistics are ready. Read in the source file one line
1207 at a time, and output that line to the gcov file preceded by
1208 its execution count if non zero. */
1210 source_file = fopen (source_file_name, "r");
1211 if (source_file == NULL)
1213 fprintf (stderr, "Could not open source file %s.\n",
1214 source_file_name);
1215 free (line_counts);
1216 free (line_exists);
1217 continue;
1220 count = strlen (source_file_name);
1221 cptr = rindex (s_ptr->name, '/');
1222 if (cptr)
1223 cptr = cptr + 1;
1224 else
1225 cptr = s_ptr->name;
1226 if (output_long_names && strcmp (cptr, input_file_name))
1228 gcov_file_name = xmalloc (count + 7 + strlen (input_file_name));
1230 cptr = rindex (input_file_name, '/');
1231 if (cptr)
1232 strcpy (gcov_file_name, cptr + 1);
1233 else
1234 strcpy (gcov_file_name, input_file_name);
1236 strcat (gcov_file_name, ".");
1238 cptr = rindex (source_file_name, '/');
1239 if (cptr)
1240 strcat (gcov_file_name, cptr + 1);
1241 else
1242 strcat (gcov_file_name, source_file_name);
1244 else
1246 gcov_file_name = xmalloc (count + 6);
1247 cptr = rindex (source_file_name, '/');
1248 if (cptr)
1249 strcpy (gcov_file_name, cptr + 1);
1250 else
1251 strcpy (gcov_file_name, source_file_name);
1254 /* Don't strip off the ending for compatibility with tcov, since
1255 this results in confusion if there is more than one file with
1256 the same basename, e.g. tmp.c and tmp.h. */
1257 strcat (gcov_file_name, ".gcov");
1259 gcov_file = fopen (gcov_file_name, "w");
1261 if (gcov_file == NULL)
1263 fprintf (stderr, "Could not open output file %s.\n",
1264 gcov_file_name);
1265 fclose (source_file);
1266 free (line_counts);
1267 free (line_exists);
1268 continue;
1271 fprintf (stdout, "Creating %s.\n", gcov_file_name);
1273 for (count = 1; count < s_ptr->maxlineno; count++)
1275 char *retval;
1276 int len;
1278 retval = fgets (string, STRING_SIZE, source_file);
1280 /* For lines which don't exist in the .bb file, print nothing
1281 before the source line. For lines which exist but were never
1282 executed, print ###### before the source line. Otherwise,
1283 print the execution count before the source line. */
1284 /* There are 16 spaces of indentation added before the source
1285 line so that tabs won't be messed up. */
1286 if (line_exists[count])
1288 if (line_counts[count])
1289 fprintf (gcov_file, "%12ld %s", line_counts[count],
1290 string);
1291 else
1292 fprintf (gcov_file, " ###### %s", string);
1294 else
1295 fprintf (gcov_file, "\t\t%s", string);
1297 /* In case the source file line is larger than our buffer, keep
1298 reading and outputting lines until we get a newline. */
1299 len = strlen (string);
1300 while ((len == 0 || string[strlen (string) - 1] != '\n')
1301 && retval != NULL)
1303 retval = fgets (string, STRING_SIZE, source_file);
1304 fputs (string, gcov_file);
1307 if (output_branch_probs)
1309 for (i = 0, a_ptr = branch_probs[count]; a_ptr;
1310 a_ptr = a_ptr->next, i++)
1312 if (a_ptr->call_insn)
1314 if (a_ptr->prob == -1)
1315 fprintf (gcov_file, "call %d never executed\n", i);
1316 else
1317 fprintf (gcov_file,
1318 "call %d returns = %d%%\n",
1319 i, 100 - a_ptr->prob);
1321 else
1323 if (a_ptr->prob == -1)
1324 fprintf (gcov_file, "branch %d never executed\n",
1326 else
1327 fprintf (gcov_file, "branch %d taken = %d%%\n", i,
1328 a_ptr->prob);
1333 /* Gracefully handle errors while reading the source file. */
1334 if (retval == NULL)
1336 fprintf (stderr,
1337 "Unexpected EOF while reading source file %s.\n",
1338 source_file_name);
1339 break;
1343 /* Handle all remaining source lines. There may be lines
1344 after the last line of code. */
1347 char *retval = fgets (string, STRING_SIZE, source_file);
1348 while (retval != NULL)
1350 int len;
1352 fprintf (gcov_file, "\t\t%s", string);
1354 /* In case the source file line is larger than our buffer, keep
1355 reading and outputting lines until we get a newline. */
1356 len = strlen (string);
1357 while ((len == 0 || string[strlen (string) - 1] != '\n')
1358 && retval != NULL)
1360 retval = fgets (string, STRING_SIZE, source_file);
1361 fputs (string, gcov_file);
1364 retval = fgets (string, STRING_SIZE, source_file);
1368 fclose (source_file);
1369 fclose (gcov_file);
1372 free (line_counts);
1373 free (line_exists);