Add powerpc embedded targets to --with-cpu=n.
[official-gcc.git] / gcc / gcov.c
blobb3ad330b42c2d38c25e63e6ec5c7ea04a7196e2f
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 Mongled 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 <stdio.h>
45 #include <sys/types.h>
46 #include <sys/stat.h>
48 /* The only need for this is so that we get macro definitions for rindex
49 if necessary. */
50 #include "config.h"
52 #include "gcov-io.h"
54 extern char * rindex ();
56 /* The .bb file format consists of several lists of 4-byte integers
57 which are the line numbers of each basic block in the file. Each
58 list is terminated by a zero. These lists correspond to the basic
59 blocks in the reconstructed program flow graph.
61 A line number of -1 indicates that a source file name (padded to a
62 long boundary) follows. The padded file name is followed by
63 another -1 to make it easy to scan past file names. A -2 indicates
64 that a function name (padded to a long boundary) follows; the name
65 is followed by another -2 to make it easy to scan past the function
66 name.
68 The .bbg file contains enough info to enable gcov to reconstruct the
69 program flow graph. The first word is the number of basic blocks,
70 the second word is the number of arcs, followed by the list of arcs
71 (source bb, dest bb pairs), then a -1, then the number of instrumented
72 arcs followed by the instrumented arcs, followed by another -1. This
73 is repeated for each function.
75 The .da file contains the execution count for each instrumented branch.
77 The .bb and .bbg files are created by giving GCC the -ftest-coverage option,
78 and the .da files are created when an executable compiled with
79 -fprofile-arcs is run. */
81 /* The functions in this file for creating and solution program flow graphs
82 are very similar to functions in the gcc source file profile.c. */
84 char gcov_version_string[] = "GNU gcov version 1.5\n";
86 /* This is the size of the buffer used to read in source file lines. */
88 #define STRING_SIZE 200
90 /* One copy of this structure is created for each source file mentioned in the
91 .bb file. */
93 struct sourcefile
95 char *name;
96 int maxlineno;
97 struct sourcefile *next;
100 /* This points to the head of the sourcefile structure list. */
102 struct sourcefile *sources;
104 /* One of these is dynamically created whenever we identify an arc in the
105 function. */
107 struct adj_list {
108 int source;
109 int target;
110 int arc_count;
111 unsigned int count_valid : 1;
112 unsigned int on_tree : 1;
113 unsigned int fake : 1;
114 unsigned int fall_through : 1;
115 #if 0
116 /* Not needed for gcov, but defined in profile.c. */
117 rtx branch_insn;
118 #endif
119 struct adj_list *pred_next;
120 struct adj_list *succ_next;
123 /* Count the number of basic blocks, and create an array of these structures,
124 one for each bb in the function. */
126 struct bb_info {
127 struct adj_list *succ;
128 struct adj_list *pred;
129 int succ_count;
130 int pred_count;
131 int exec_count;
132 unsigned int count_valid : 1;
133 unsigned int on_tree : 1;
134 #if 0
135 /* Not needed for gcov, but defined in profile.c. */
136 rtx first_insn;
137 #endif
140 /* When outputting branch probabilities, one of these structures is created
141 for each branch/call. */
143 struct arcdata
145 int prob;
146 int call_insn;
147 struct arcdata *next;
150 /* Used to save the list of bb_graphs, one per function. */
152 struct bb_info_list {
153 /* Indexed by block number, holds the basic block graph for one function. */
154 struct bb_info *bb_graph;
155 int num_blocks;
156 struct bb_info_list *next;
159 /* Holds a list of function basic block graphs. */
161 static struct bb_info_list *bb_graph_list = 0;
163 /* Name and file pointer of the input file for the basic block graph. */
165 static char *bbg_file_name;
166 static FILE *bbg_file;
168 /* Name and file pointer of the input file for the arc count data. */
170 static char *da_file_name;
171 static FILE *da_file;
173 /* Name and file pointer of the input file for the basic block line counts. */
175 static char *bb_file_name;
176 static FILE *bb_file;
178 /* Holds the entire contents of the bb_file read into memory. */
180 static char *bb_data;
182 /* Size of bb_data array in longs. */
184 static long bb_data_size;
186 /* Name and file pointer of the output file. */
188 static char *gcov_file_name;
189 static FILE *gcov_file;
191 /* Name of the file mentioned on the command line. */
193 static char *input_file_name = 0;
195 /* Output branch probabilities if true. */
197 static int output_branch_probs = 0;
199 /* Output a gcov file if this is true. This is on by default, and can
200 be turned off by the -n option. */
202 static int output_gcov_file = 1;
204 /* For included files, make the gcov output file name include the name of
205 the input source file. For example, if x.h is included in a.c, then the
206 output file name is a.c.x.h.gcov instead of x.h.gcov. This works only
207 when a single source file is specified. */
209 static int output_long_names = 0;
211 /* Output summary info for each function. */
213 static int output_function_summary = 0;
215 /* Object directory file prefix. This is the directory where .bb and .bbg
216 files are looked for, if non-zero. */
218 static char *object_directory = 0;
220 /* Forward declarations. */
221 static void process_args ();
222 static void open_files ();
223 static void read_files ();
224 static void scan_for_source_files ();
225 static void output_data ();
226 char * xmalloc ();
229 main (argc, argv)
230 int argc;
231 char **argv;
233 process_args (argc, argv);
235 open_files ();
237 read_files ();
239 scan_for_source_files ();
241 output_data ();
243 return 0;
246 char *
247 xmalloc (size)
248 unsigned size;
250 register char *value = (char *) malloc (size);
251 if (value == 0)
253 fprintf (stderr, "error: virtual memory exhausted");
254 exit (FATAL_EXIT_CODE);
256 return value;
259 /* More 'friendly' abort that prints the line and file.
260 config.h can #define abort fancy_abort if you like that sort of thing. */
262 void
263 fancy_abort ()
265 fprintf (stderr, "Internal gcc abort.\n");
266 exit (FATAL_EXIT_CODE);
269 /* Print a usage message and exit. */
271 static void
272 print_usage ()
274 fprintf (stderr, "gcov [-b] [-v] [-n] [-l] [-f] [-o OBJDIR] file\n");
275 exit (FATAL_EXIT_CODE);
278 /* Parse the command line. */
280 static void
281 process_args (argc, argv)
282 int argc;
283 char **argv;
285 int i;
287 for (i = 1; i < argc; i++)
289 if (argv[i][0] == '-')
291 if (argv[i][1] == 'b')
292 output_branch_probs = 1;
293 else if (argv[i][1] == 'v')
294 fputs (gcov_version_string, stderr);
295 else if (argv[i][1] == 'n')
296 output_gcov_file = 0;
297 else if (argv[i][1] == 'l')
298 output_long_names = 1;
299 else if (argv[i][1] == 'f')
300 output_function_summary = 1;
301 else if (argv[i][1] == 'o' && argv[i][2] == '\0')
302 object_directory = argv[++i];
303 else
304 print_usage ();
306 else if (! input_file_name)
307 input_file_name = argv[i];
308 else
309 print_usage ();
312 if (! input_file_name)
313 print_usage ();
317 /* Find and open the .bb, .da, and .bbg files. */
319 static void
320 open_files ()
322 int count, objdir_count;
323 char *cptr;
325 /* Determine the names of the .bb, .bbg, and .da files. Strip off the
326 extension, if any, and append the new extensions. */
327 count = strlen (input_file_name);
328 if (object_directory)
329 objdir_count = strlen (object_directory);
330 else
331 objdir_count = 0;
333 da_file_name = xmalloc (count + objdir_count + 4);
334 bb_file_name = xmalloc (count + objdir_count + 4);
335 bbg_file_name = xmalloc (count + objdir_count + 5);
337 if (object_directory)
339 strcpy (da_file_name, object_directory);
340 strcpy (bb_file_name, object_directory);
341 strcpy (bbg_file_name, object_directory);
343 if (object_directory[objdir_count - 1] != '/')
345 strcat (da_file_name, "/");
346 strcat (bb_file_name, "/");
347 strcat (bbg_file_name, "/");
350 cptr = rindex (input_file_name, '/');
351 if (cptr)
353 strcat (da_file_name, cptr + 1);
354 strcat (bb_file_name, cptr + 1);
355 strcat (bbg_file_name, cptr + 1);
357 else
359 strcat (da_file_name, input_file_name);
360 strcat (bb_file_name, input_file_name);
361 strcat (bbg_file_name, input_file_name);
364 else
366 strcpy (da_file_name, input_file_name);
367 strcpy (bb_file_name, input_file_name);
368 strcpy (bbg_file_name, input_file_name);
371 cptr = rindex (bb_file_name, '.');
372 if (cptr)
373 strcpy (cptr, ".bb");
374 else
375 strcat (bb_file_name, ".bb");
377 cptr = rindex (da_file_name, '.');
378 if (cptr)
379 strcpy (cptr, ".da");
380 else
381 strcat (da_file_name, ".da");
383 cptr = rindex (bbg_file_name, '.');
384 if (cptr)
385 strcpy (cptr, ".bbg");
386 else
387 strcat (bbg_file_name, ".bbg");
389 bb_file = fopen (bb_file_name, "r");
390 if (bb_file == NULL)
392 fprintf (stderr, "Could not open basic block file %s.\n", bb_file_name);
393 exit (FATAL_EXIT_CODE);
396 /* If none of the functions in the file were executed, then there won't
397 be a .da file. Just assume that all counts are zero in this case. */
398 da_file = fopen (da_file_name, "r");
399 if (da_file == NULL)
401 fprintf (stderr, "Could not open data file %s.\n", da_file_name);
402 fprintf (stderr, "Assuming that all execution counts are zero.\n");
405 bbg_file = fopen (bbg_file_name, "r");
406 if (bbg_file == NULL)
408 fprintf (stderr, "Could not open program flow graph file %s.\n",
409 bbg_file_name);
410 exit (FATAL_EXIT_CODE);
413 /* Check for empty .bbg file. This indicates that there is no executable
414 code in this source file. */
415 /* Set the EOF condition if at the end of file. */
416 ungetc (getc (bbg_file), bbg_file);
417 if (feof (bbg_file))
419 fprintf (stderr, "No executable code associated with file %s.\n",
420 input_file_name);
421 exit (FATAL_EXIT_CODE);
425 /* Initialize a new arc. */
427 static void
428 init_arc (arcptr, source, target, bb_graph)
429 struct adj_list *arcptr;
430 int source, target;
431 struct bb_info *bb_graph;
433 arcptr->target = target;
434 arcptr->source = source;
436 arcptr->arc_count = 0;
437 arcptr->count_valid = 0;
438 arcptr->on_tree = 0;
439 arcptr->fake = 0;
440 arcptr->fall_through = 0;
442 arcptr->succ_next = bb_graph[source].succ;
443 bb_graph[source].succ = arcptr;
444 bb_graph[source].succ_count++;
446 arcptr->pred_next = bb_graph[target].pred;
447 bb_graph[target].pred = arcptr;
448 bb_graph[target].pred_count++;
452 /* Reverse the arcs on a arc list. */
454 static struct adj_list *
455 reverse_arcs (arcptr)
456 struct adj_list *arcptr;
458 struct adj_list *prev = 0;
459 struct adj_list *next;
461 for ( ; arcptr; arcptr = next)
463 next = arcptr->succ_next;
464 arcptr->succ_next = prev;
465 prev = arcptr;
468 return prev;
472 /* Construct the program flow graph from the .bbg file, and read in the data
473 in the .da file. */
475 static void
476 create_program_flow_graph (bptr)
477 struct bb_info_list *bptr;
479 long num_blocks, number_arcs, src, dest, flag_bits, num_arcs_per_block;
480 int i;
481 struct adj_list *arcptr;
482 struct bb_info *bb_graph;
484 /* Read the number of blocks. */
485 __read_long (&num_blocks, bbg_file, 4);
487 /* Create an array of size bb number of bb_info structs. Bzero it. */
488 bb_graph = (struct bb_info *) xmalloc (num_blocks
489 * sizeof (struct bb_info));
490 bzero ((char *) bb_graph, sizeof (struct bb_info) * num_blocks);
492 bptr->bb_graph = bb_graph;
493 bptr->num_blocks = num_blocks;
495 /* Read and create each arc from the .bbg file. */
496 __read_long (&number_arcs, bbg_file, 4);
497 for (i = 0; i < num_blocks; i++)
499 int j;
501 __read_long (&num_arcs_per_block, bbg_file, 4);
502 for (j = 0; j < num_arcs_per_block; j++)
504 if (number_arcs-- < 0)
505 abort ();
507 src = i;
508 __read_long (&dest, bbg_file, 4);
510 arcptr = (struct adj_list *) xmalloc (sizeof (struct adj_list));
511 init_arc (arcptr, src, dest, bb_graph);
513 __read_long (&flag_bits, bbg_file, 4);
514 arcptr->on_tree = flag_bits & 0x1;
515 arcptr->fake = !! (flag_bits & 0x2);
516 arcptr->fall_through = !! (flag_bits & 0x4);
520 if (number_arcs)
521 abort ();
523 /* Read and ignore the -1 separating the arc list from the arc list of the
524 next function. */
525 __read_long (&src, bbg_file, 4);
526 if (src != -1)
527 abort ();
529 /* Must reverse the order of all succ arcs, to ensure that they match
530 the order of the data in the .da file. */
532 for (i = 0; i < num_blocks; i++)
533 if (bb_graph[i].succ)
534 bb_graph[i].succ = reverse_arcs (bb_graph[i].succ);
536 /* For each arc not on the spanning tree, set its execution count from
537 the .da file. */
539 /* The first count in the .da file is the number of times that the function
540 was entered. This is the exec_count for block zero. */
542 /* This duplicates code in branch_prob in profile.c. */
544 for (i = 0; i < num_blocks; i++)
545 for (arcptr = bb_graph[i].succ; arcptr; arcptr = arcptr->succ_next)
546 if (! arcptr->on_tree)
548 long tmp_count = 0;;
549 if (da_file && __read_long (&tmp_count, da_file, 8))
550 abort();
552 arcptr->arc_count = tmp_count;
553 arcptr->count_valid = 1;
554 bb_graph[i].succ_count--;
555 bb_graph[arcptr->target].pred_count--;
559 static void
560 solve_program_flow_graph (bptr)
561 struct bb_info_list *bptr;
563 int passes, changes, total;
564 int i;
565 struct adj_list *arcptr;
566 struct bb_info *bb_graph;
567 int num_blocks;
569 num_blocks = bptr->num_blocks;
570 bb_graph = bptr->bb_graph;
572 /* For every block in the file,
573 - if every exit/entrance arc has a known count, then set the block count
574 - if the block count is known, and every exit/entrance arc but one has
575 a known execution count, then set the count of the remaining arc
577 As arc counts are set, decrement the succ/pred count, but don't delete
578 the arc, that way we can easily tell when all arcs are known, or only
579 one arc is unknown. */
581 /* The order that the basic blocks are iterated through is important.
582 Since the code that finds spanning trees starts with block 0, low numbered
583 arcs are put on the spanning tree in preference to high numbered arcs.
584 Hence, most instrumented arcs are at the end. Graph solving works much
585 faster if we propagate numbers from the end to the start.
587 This takes an average of slightly more than 3 passes. */
589 changes = 1;
590 passes = 0;
591 while (changes)
593 passes++;
594 changes = 0;
596 for (i = num_blocks - 1; i >= 0; i--)
598 if (! bb_graph[i].count_valid)
600 if (bb_graph[i].succ_count == 0)
602 total = 0;
603 for (arcptr = bb_graph[i].succ; arcptr;
604 arcptr = arcptr->succ_next)
605 total += arcptr->arc_count;
606 bb_graph[i].exec_count = total;
607 bb_graph[i].count_valid = 1;
608 changes = 1;
610 else if (bb_graph[i].pred_count == 0)
612 total = 0;
613 for (arcptr = bb_graph[i].pred; arcptr;
614 arcptr = arcptr->pred_next)
615 total += arcptr->arc_count;
616 bb_graph[i].exec_count = total;
617 bb_graph[i].count_valid = 1;
618 changes = 1;
621 if (bb_graph[i].count_valid)
623 if (bb_graph[i].succ_count == 1)
625 total = 0;
626 /* One of the counts will be invalid, but it is zero,
627 so adding it in also doesn't hurt. */
628 for (arcptr = bb_graph[i].succ; arcptr;
629 arcptr = arcptr->succ_next)
630 total += arcptr->arc_count;
631 /* Calculate count for remaining arc by conservation. */
632 total = bb_graph[i].exec_count - total;
633 /* Search for the invalid arc, and set its count. */
634 for (arcptr = bb_graph[i].succ; arcptr;
635 arcptr = arcptr->succ_next)
636 if (! arcptr->count_valid)
637 break;
638 if (! arcptr)
639 abort ();
640 arcptr->count_valid = 1;
641 arcptr->arc_count = total;
642 bb_graph[i].succ_count--;
644 bb_graph[arcptr->target].pred_count--;
645 changes = 1;
647 if (bb_graph[i].pred_count == 1)
649 total = 0;
650 /* One of the counts will be invalid, but it is zero,
651 so adding it in also doesn't hurt. */
652 for (arcptr = bb_graph[i].pred; arcptr;
653 arcptr = arcptr->pred_next)
654 total += arcptr->arc_count;
655 /* Calculate count for remaining arc by conservation. */
656 total = bb_graph[i].exec_count - total;
657 /* Search for the invalid arc, and set its count. */
658 for (arcptr = bb_graph[i].pred; arcptr;
659 arcptr = arcptr->pred_next)
660 if (! arcptr->count_valid)
661 break;
662 if (! arcptr)
663 abort ();
664 arcptr->count_valid = 1;
665 arcptr->arc_count = total;
666 bb_graph[i].pred_count--;
668 bb_graph[arcptr->source].succ_count--;
669 changes = 1;
675 /* If the graph has been correctly solved, every block will have a
676 succ and pred count of zero. */
677 for (i = 0; i < num_blocks; i++)
678 if (bb_graph[i].succ_count || bb_graph[i].pred_count)
679 abort ();
683 static void
684 read_files ()
686 struct stat buf;
687 struct bb_info_list *list_end = 0;
688 struct bb_info_list *b_ptr;
689 long total, first_time;
691 /* Read and ignore the first word of the .da file, which is the count of
692 how many numbers follow. */
693 if (da_file && __read_long (&total, da_file, 8))
694 abort();
696 while (! feof (bbg_file))
698 b_ptr = (struct bb_info_list *) xmalloc (sizeof (struct bb_info_list));
700 b_ptr->next = 0;
701 if (list_end)
702 list_end->next = b_ptr;
703 else
704 bb_graph_list = b_ptr;
705 list_end = b_ptr;
707 /* Read in the data in the .bbg file and reconstruct the program flow
708 graph for one function. */
709 create_program_flow_graph (b_ptr, first_time);
711 /* Set the EOF condition if at the end of file. */
712 ungetc (getc (bbg_file), bbg_file);
715 /* Check to make sure the .da file data is valid. */
717 if (da_file)
719 if (feof (da_file))
720 fprintf (stderr, ".da file contents exhausted too early\n");
721 /* Should be at end of file now. */
722 if (__read_long (&total, da_file, 8) == 0)
723 fprintf (stderr, ".da file contents not exhausted\n");
726 /* Calculate all of the basic block execution counts and branch
727 taken probabilities. */
729 for (b_ptr = bb_graph_list; b_ptr; b_ptr = b_ptr->next)
730 solve_program_flow_graph (b_ptr);
732 /* Read in all of the data from the .bb file. This info will be accessed
733 sequentially twice. */
734 stat (bb_file_name, &buf);
735 bb_data_size = buf.st_size / 4;
737 bb_data = (char *) xmalloc (buf.st_size);
738 fread (bb_data, sizeof (char), buf.st_size, bb_file);
740 fclose (bb_file);
741 if (da_file)
742 fclose (da_file);
743 fclose (bbg_file);
747 /* Scan the data in the .bb file to find all source files referenced,
748 and the largest line number mentioned in each one. */
750 static void
751 scan_for_source_files ()
753 struct sourcefile *s_ptr;
754 char *ptr;
755 int count;
756 long line_num;
758 /* Search the bb_data to find:
759 1) The number of sources files contained herein, and
760 2) The largest line number for each source file. */
762 ptr = bb_data;
763 sources = 0;
764 for (count = 0; count < bb_data_size; count++)
766 __fetch_long (&line_num, ptr, 4);
767 ptr += 4;
768 if (line_num == -1)
770 /* A source file name follows. Check to see if we already have
771 a sourcefile structure for this file. */
772 s_ptr = sources;
773 while (s_ptr && strcmp (s_ptr->name, ptr))
774 s_ptr = s_ptr->next;
776 if (s_ptr == 0)
778 /* No sourcefile structure for this file name exists, create
779 a new one, and append it to the front of the sources list. */
780 s_ptr = (struct sourcefile *) xmalloc (sizeof(struct sourcefile));
781 s_ptr->name = xmalloc (strlen ((char *) ptr) + 1);
782 strcpy (s_ptr->name, (char *) ptr);
783 s_ptr->maxlineno = 0;
784 s_ptr->next = sources;
785 sources = s_ptr;
788 /* Scan past the file name. */
790 long delim;
791 do {
792 count++;
793 __fetch_long (&delim, ptr, 4);
794 ptr += 4;
795 } while (delim != line_num);
798 else if (line_num == -2)
800 long delim;
802 /* A function name follows. Ignore it. */
803 do {
804 count++;
805 __fetch_long (&delim, ptr, 4);
806 ptr += 4;
807 } while (delim != line_num);
809 /* There will be a zero before the first file name, in which case s_ptr
810 will still be uninitialized. So, only try to set the maxlineno
811 field if line_num is non-zero. */
812 else if (line_num > 0)
814 if (s_ptr->maxlineno <= line_num)
815 s_ptr->maxlineno = line_num + 1;
817 else if (line_num < 0)
819 /* Don't know what this is, but it's garbage. */
820 abort();
825 /* For calculating coverage at the function level. */
827 static int function_source_lines;
828 static int function_source_lines_executed;
829 static int function_branches;
830 static int function_branches_executed;
831 static int function_branches_taken;
832 static int function_calls;
833 static int function_calls_executed;
834 static char *function_name;
836 /* Calculate the branch taken probabilities for all arcs branches at the
837 end of this block. */
839 static void
840 calculate_branch_probs (current_graph, block_num, branch_probs, last_line_num)
841 struct bb_info_list *current_graph;
842 int block_num;
843 struct arcdata **branch_probs;
844 int last_line_num;
846 int total;
847 struct adj_list *arcptr;
848 struct arcdata *end_ptr, *a_ptr;
850 total = current_graph->bb_graph[block_num].exec_count;
851 for (arcptr = current_graph->bb_graph[block_num].succ; arcptr;
852 arcptr = arcptr->succ_next)
854 /* Ignore fall through arcs as they aren't really branches. */
856 if (arcptr->fall_through)
857 continue;
859 a_ptr = (struct arcdata *) xmalloc (sizeof (struct arcdata));
860 if (total == 0)
861 a_ptr->prob = -1;
862 else
863 a_ptr->prob = ((arcptr->arc_count * 100) + (total >> 1)) / total;
864 a_ptr->call_insn = arcptr->fake;
866 if (output_function_summary)
868 if (a_ptr->call_insn)
870 function_calls++;
871 if (a_ptr->prob != -1)
872 function_calls_executed++;
874 else
876 function_branches++;
877 if (a_ptr->prob != -1)
878 function_branches_executed++;
879 if (a_ptr->prob > 0)
880 function_branches_taken++;
884 /* Append the new branch to the end of the list. */
885 a_ptr->next = 0;
886 if (! branch_probs[last_line_num])
887 branch_probs[last_line_num] = a_ptr;
888 else
890 end_ptr = branch_probs[last_line_num];
891 while (end_ptr->next != 0)
892 end_ptr = end_ptr->next;
893 end_ptr->next = a_ptr;
898 /* Output summary info for a function. */
900 static void
901 function_summary ()
903 if (function_source_lines)
904 fprintf (stdout, "%6.2lf%% of %d source lines executed in function %s\n",
905 (((double) function_source_lines_executed / function_source_lines)
906 * 100), function_source_lines, function_name);
907 else
908 fprintf (stdout, "No executable source lines in function %s\n",
909 function_name);
911 if (output_branch_probs)
913 if (function_branches)
915 fprintf (stdout, "%6.2lf%% of %d branches executed in funcion %s\n",
916 (((double) function_branches_executed / function_branches)
917 * 100), function_branches, function_name);
918 fprintf (stdout,
919 "%6.2lf%% of %d branches taken at least once in function %s\n",
920 (((double) function_branches_taken / function_branches)
921 * 100), function_branches, function_name);
923 else
924 fprintf (stdout, "No branches in function %s\n", function_name);
925 if (function_calls)
926 fprintf (stdout, "%6.2lf%% of %d calls executed in function %s\n",
927 (((double) function_calls_executed / function_calls)
928 * 100), function_calls, function_name);
929 else
930 fprintf (stdout, "No calls in function %s\n", function_name);
934 /* Calculate line execution counts, and output the data to a .tcov file. */
936 static void
937 output_data ()
939 /* When scanning data, this is true only if the data applies to the
940 current source file. */
941 int this_file;
942 /* An array indexed by line number which indicates how many times that line
943 was executed. */
944 long *line_counts;
945 /* An array indexed by line number which indicates whether the line was
946 present in the bb file (i.e. whether it had code associate with it).
947 Lines never executed are those which both exist, and have zero execution
948 counts. */
949 char *line_exists;
950 /* An array indexed by line number, which contains a list of branch
951 probabilities, one for each branch on that line. */
952 struct arcdata **branch_probs;
953 struct sourcefile *s_ptr;
954 char *source_file_name;
955 FILE *source_file;
956 struct bb_info_list *current_graph;
957 int count;
958 char *cptr;
959 long block_num;
960 long line_num;
961 long last_line_num;
962 int i;
963 struct arcdata *a_ptr;
964 /* Buffer used for reading in lines from the source file. */
965 char string[STRING_SIZE];
966 /* For calculating coverage at the file level. */
967 int total_source_lines;
968 int total_source_lines_executed;
969 int total_branches;
970 int total_branches_executed;
971 int total_branches_taken;
972 int total_calls;
973 int total_calls_executed;
975 /* Now, for each source file, allocate an array big enough to hold a count
976 for each line. Scan through the bb_data, and when the file name matches
977 the current file name, then for each following line number, increment
978 the line number execution count indicated by the execution count of
979 the appropriate basic block. */
981 for (s_ptr = sources; s_ptr; s_ptr = s_ptr->next)
983 /* If this is a relative file name, and an object directory has been
984 specified, then make it relative to the object directory name. */
985 if (*s_ptr->name != '/' && object_directory != 0
986 && *object_directory != '\0')
988 int objdir_count = strlen (object_directory);
989 source_file_name = xmalloc (objdir_count + strlen (s_ptr->name) + 2);
990 strcpy (source_file_name, object_directory);
991 if (object_directory[objdir_count - 1] != '/')
992 source_file_name[objdir_count++] = '/';
993 strcpy (source_file_name + objdir_count, s_ptr->name);
995 else
996 source_file_name = s_ptr->name;
998 line_counts = (long *) xmalloc (sizeof (long) * s_ptr->maxlineno);
999 bzero ((char *) line_counts, sizeof (long) * s_ptr->maxlineno);
1000 line_exists = xmalloc (s_ptr->maxlineno);
1001 bzero (line_exists, s_ptr->maxlineno);
1002 if (output_branch_probs)
1004 branch_probs = (struct arcdata **) xmalloc (sizeof (struct arcdata **)
1005 * s_ptr->maxlineno);
1006 bzero ((char *) branch_probs,
1007 sizeof (struct arcdata **) * s_ptr->maxlineno);
1010 /* There will be a zero at the beginning of the bb info, before the
1011 first list of line numbers, so must initialize block_num to 0. */
1012 block_num = 0;
1013 this_file = 0;
1014 current_graph = 0;
1016 /* Pointer into the bb_data, incremented while scanning the data. */
1017 char *ptr = bb_data;
1018 for (count = 0; count < bb_data_size; count++)
1020 long delim;
1022 __fetch_long (&line_num, ptr, 4);
1023 ptr += 4;
1024 if (line_num == -1)
1026 /* Marks the beginning of a file name. Check to see whether
1027 this is the filename we are currently collecting data for. */
1029 if (strcmp (s_ptr->name, ptr))
1030 this_file = 0;
1031 else
1032 this_file = 1;
1034 /* Scan past the file name. */
1035 do {
1036 count++;
1037 __fetch_long (&delim, ptr, 4);
1038 ptr += 4;
1039 } while (delim != line_num);
1041 else if (line_num == -2)
1043 /* Marks the start of a new function. Advance to the next
1044 program flow graph. */
1046 if (! current_graph)
1047 current_graph = bb_graph_list;
1048 else
1050 if (block_num == current_graph->num_blocks - 1)
1051 /* Last block falls through to exit. */
1053 else if (block_num == current_graph->num_blocks - 2)
1055 if (output_branch_probs && this_file)
1056 calculate_branch_probs (current_graph, block_num,
1057 branch_probs, last_line_num);
1059 else
1061 fprintf (stderr,
1062 "didn't use all bb entries of graph, function %s\n",
1063 function_name);
1064 fprintf (stderr, "block_num = %d, num_blocks = %d\n",
1065 block_num, current_graph->num_blocks);
1068 current_graph = current_graph->next;
1069 block_num = 0;
1071 if (output_function_summary && this_file)
1072 function_summary ();
1075 if (output_function_summary)
1077 function_source_lines = 0;
1078 function_source_lines_executed = 0;
1079 function_branches = 0;
1080 function_branches_executed = 0;
1081 function_branches_taken = 0;
1082 function_calls = 0;
1083 function_calls_executed = 0;
1086 /* Save the function name for later use. */
1087 function_name = ptr;
1089 /* Scan past the file name. */
1090 do {
1091 count++;
1092 __fetch_long (&delim, ptr, 4);
1093 ptr += 4;
1094 } while (delim != line_num);
1096 else if (line_num == 0)
1098 /* Marks the end of a block. */
1100 if (block_num >= current_graph->num_blocks)
1102 fprintf (stderr, "ERROR: too many basic blocks in .bb file %s\n",
1103 function_name);
1104 abort ();
1107 if (output_branch_probs && this_file)
1108 calculate_branch_probs (current_graph, block_num,
1109 branch_probs, last_line_num);
1111 block_num++;
1113 else if (this_file)
1115 if (output_function_summary)
1117 if (line_exists[line_num] == 0)
1118 function_source_lines++;
1119 if (line_counts[line_num] == 0
1120 && current_graph->bb_graph[block_num].exec_count != 0)
1121 function_source_lines_executed++;
1124 /* Accumulate execution data for this line number. */
1126 line_counts[line_num]
1127 += current_graph->bb_graph[block_num].exec_count;
1128 line_exists[line_num] = 1;
1129 last_line_num = line_num;
1134 if (output_function_summary && this_file)
1135 function_summary ();
1137 /* Calculate summary test coverage statistics. */
1139 total_source_lines = 0;
1140 total_source_lines_executed = 0;
1141 total_branches = 0;
1142 total_branches_executed = 0;
1143 total_branches_taken = 0;
1144 total_calls = 0;
1145 total_calls_executed = 0;
1147 for (count = 1; count < s_ptr->maxlineno; count++)
1149 if (line_exists[count])
1151 total_source_lines++;
1152 if (line_counts[count])
1153 total_source_lines_executed++;
1155 if (output_branch_probs)
1157 for (a_ptr = branch_probs[count]; a_ptr; a_ptr = a_ptr->next)
1159 if (a_ptr->call_insn)
1161 total_calls++;
1162 if (a_ptr->prob != -1)
1163 total_calls_executed++;
1165 else
1167 total_branches++;
1168 if (a_ptr->prob != -1)
1169 total_branches_executed++;
1170 if (a_ptr->prob > 0)
1171 total_branches_taken++;
1177 if (total_source_lines)
1178 fprintf (stdout,
1179 "%6.2lf%% of %d source lines executed in file %s\n",
1180 (((double) total_source_lines_executed / total_source_lines)
1181 * 100), total_source_lines, source_file_name);
1182 else
1183 fprintf (stdout, "No executable source lines in file %s\n",
1184 source_file_name);
1186 if (output_branch_probs)
1188 if (total_branches)
1190 fprintf (stdout, "%6.2lf%% of %d branches executed in file %s\n",
1191 (((double) total_branches_executed / total_branches)
1192 * 100), total_branches, source_file_name);
1193 fprintf (stdout,
1194 "%6.2lf%% of %d branches taken at least once in file %s\n",
1195 (((double) total_branches_taken / total_branches)
1196 * 100), total_branches, source_file_name);
1198 else
1199 fprintf (stdout, "No branches in file %s\n", source_file_name);
1200 if (total_calls)
1201 fprintf (stdout, "%6.2lf%% of %d calls executed in file %s\n",
1202 (((double) total_calls_executed / total_calls)
1203 * 100), total_calls, source_file_name);
1204 else
1205 fprintf (stdout, "No calls in file %s\n", source_file_name);
1208 if (output_gcov_file)
1210 /* Now the statistics are ready. Read in the source file one line
1211 at a time, and output that line to the gcov file preceeded by
1212 its execution count if non zero. */
1214 source_file = fopen (source_file_name, "r");
1215 if (source_file == NULL)
1217 fprintf (stderr, "Could not open source file %s.\n",
1218 source_file_name);
1219 free (line_counts);
1220 free (line_exists);
1221 continue;
1224 count = strlen (source_file_name);
1225 cptr = rindex (s_ptr->name, '/');
1226 if (cptr)
1227 cptr = cptr + 1;
1228 else
1229 cptr = s_ptr->name;
1230 if (output_long_names && strcmp (cptr, input_file_name))
1232 gcov_file_name = xmalloc (count + 7 + strlen (input_file_name));
1234 cptr = rindex (input_file_name, '/');
1235 if (cptr)
1236 strcpy (gcov_file_name, cptr + 1);
1237 else
1238 strcpy (gcov_file_name, input_file_name);
1240 strcat (gcov_file_name, ".");
1242 cptr = rindex (source_file_name, '/');
1243 if (cptr)
1244 strcat (gcov_file_name, cptr + 1);
1245 else
1246 strcat (gcov_file_name, source_file_name);
1248 else
1250 gcov_file_name = xmalloc (count + 6);
1251 cptr = rindex (source_file_name, '/');
1252 if (cptr)
1253 strcpy (gcov_file_name, cptr + 1);
1254 else
1255 strcpy (gcov_file_name, source_file_name);
1258 /* Don't strip off the ending for compatibility with tcov, since
1259 this results in confusion if there is more than one file with
1260 the same basename, e.g. tmp.c and tmp.h. */
1261 strcat (gcov_file_name, ".gcov");
1263 gcov_file = fopen (gcov_file_name, "w");
1265 if (gcov_file == NULL)
1267 fprintf (stderr, "Could not open output file %s.\n",
1268 gcov_file_name);
1269 fclose (source_file);
1270 free (line_counts);
1271 free (line_exists);
1272 continue;
1275 fprintf (stdout, "Creating %s.\n", gcov_file_name);
1277 for (count = 1; count < s_ptr->maxlineno; count++)
1279 char *retval;
1280 int len;
1282 retval = fgets (string, STRING_SIZE, source_file);
1284 /* For lines which don't exist in the .bb file, print nothing
1285 before the source line. For lines which exist but were never
1286 executed, print ###### before the source line. Otherwise,
1287 print the execution count before the source line. */
1288 /* There are 16 spaces of identation added before the source line
1289 so that tabs won't be messed up. */
1290 if (line_exists[count])
1292 if (line_counts[count])
1293 fprintf (gcov_file, "%12d %s", line_counts[count],
1294 string);
1295 else
1296 fprintf (gcov_file, " ###### %s", string);
1298 else
1299 fprintf (gcov_file, "\t\t%s", string);
1301 /* In case the source file line is larger than our buffer, keep
1302 reading and outputing lines until we get a newline. */
1303 len = strlen (string);
1304 while ((len == 0 || string[strlen (string) - 1] != '\n')
1305 && retval != NULL)
1307 retval = fgets (string, STRING_SIZE, source_file);
1308 fputs (string, gcov_file);
1311 if (output_branch_probs)
1313 for (i = 0, a_ptr = branch_probs[count]; a_ptr;
1314 a_ptr = a_ptr->next, i++)
1316 if (a_ptr->call_insn)
1318 if (a_ptr->prob == -1)
1319 fprintf (gcov_file, "call %d never executed\n", i);
1320 else
1321 fprintf (gcov_file,
1322 "call %d returns = %d%%\n",
1323 i, 100 - a_ptr->prob);
1325 else
1327 if (a_ptr->prob == -1)
1328 fprintf (gcov_file, "branch %d never executed\n",
1330 else
1331 fprintf (gcov_file, "branch %d taken = %d%%\n", i,
1332 a_ptr->prob);
1337 /* Gracefully handle errors while reading the source file. */
1338 if (retval == NULL)
1340 fprintf (stderr,
1341 "Unexpected EOF while reading source file %s.\n",
1342 source_file_name);
1343 break;
1347 /* Handle all remaining source lines. There may be lines
1348 after the last line of code. */
1351 char *retval = fgets (string, STRING_SIZE, source_file);
1352 while (retval != NULL)
1354 int len;
1356 fprintf (gcov_file, "\t\t%s", string);
1358 /* In case the source file line is larger than our buffer, keep
1359 reading and outputing lines until we get a newline. */
1360 len = strlen (string);
1361 while ((len == 0 || string[strlen (string) - 1] != '\n')
1362 && retval != NULL)
1364 retval = fgets (string, STRING_SIZE, source_file);
1365 fputs (string, gcov_file);
1368 retval = fgets (string, STRING_SIZE, source_file);
1372 fclose (source_file);
1373 fclose (gcov_file);
1376 free (line_counts);
1377 free (line_exists);