YA spurious-uninitialized-variable-warning test
[official-gcc.git] / gcc / gcov.c
blob46df6ede862a5d9e6aea38e4e4a41890f7c0ec5a
1 /* Gcov.c: prepend line execution counts and branch probabilities to a
2 source file.
3 Copyright (C) 1990, 91-94, 96, 97, 98, 1999 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"
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)) ATTRIBUTE_NORETURN;
224 main (argc, argv)
225 int argc;
226 char **argv;
228 #ifdef HAVE_LC_MESSAGES
229 setlocale (LC_MESSAGES, "");
230 #endif
231 (void) bindtextdomain (PACKAGE, localedir);
232 (void) textdomain (PACKAGE);
234 process_args (argc, argv);
236 open_files ();
238 read_files ();
240 scan_for_source_files ();
242 output_data ();
244 return 0;
247 static void fnotice PVPROTO ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2;
248 static void
249 fnotice VPROTO ((FILE *file, const char *msgid, ...))
251 #ifndef ANSI_PROTOTYPES
252 FILE *file;
253 const char *msgid;
254 #endif
255 va_list ap;
257 VA_START (ap, msgid);
259 #ifndef ANSI_PROTOTYPES
260 file = va_arg (ap, FILE *);
261 msgid = va_arg (ap, const char *);
262 #endif
264 vfprintf (file, _(msgid), ap);
265 va_end (ap);
270 xmalloc (size)
271 size_t size;
273 register PTR value = (PTR) malloc (size);
274 if (value == 0)
276 fnotice (stderr, "error: virtual memory exhausted");
277 exit (FATAL_EXIT_CODE);
279 return value;
282 /* More 'friendly' abort that prints the line and file.
283 config.h can #define abort fancy_abort if you like that sort of thing. */
285 void
286 fancy_abort ()
288 fnotice (stderr, "Internal gcc abort.\n");
289 exit (FATAL_EXIT_CODE);
292 /* Print a usage message and exit. */
294 static void
295 print_usage ()
297 fnotice (stderr, "gcov [-b] [-v] [-n] [-l] [-f] [-o OBJDIR] file\n");
298 exit (FATAL_EXIT_CODE);
301 /* Parse the command line. */
303 static void
304 process_args (argc, argv)
305 int argc;
306 char **argv;
308 int i;
310 for (i = 1; i < argc; i++)
312 if (argv[i][0] == '-')
314 if (argv[i][1] == 'b')
315 output_branch_probs = 1;
316 else if (argv[i][1] == 'v')
317 fputs (gcov_version_string, stderr);
318 else if (argv[i][1] == 'n')
319 output_gcov_file = 0;
320 else if (argv[i][1] == 'l')
321 output_long_names = 1;
322 else if (argv[i][1] == 'f')
323 output_function_summary = 1;
324 else if (argv[i][1] == 'o' && argv[i][2] == '\0')
325 object_directory = argv[++i];
326 else
327 print_usage ();
329 else if (! input_file_name)
330 input_file_name = argv[i];
331 else
332 print_usage ();
335 if (! input_file_name)
336 print_usage ();
340 /* Find and open the .bb, .da, and .bbg files. */
342 static void
343 open_files ()
345 int count, objdir_count;
346 char *cptr;
348 /* Determine the names of the .bb, .bbg, and .da files. Strip off the
349 extension, if any, and append the new extensions. */
350 count = strlen (input_file_name);
351 if (object_directory)
352 objdir_count = strlen (object_directory);
353 else
354 objdir_count = 0;
356 da_file_name = xmalloc (count + objdir_count + 4);
357 bb_file_name = xmalloc (count + objdir_count + 4);
358 bbg_file_name = xmalloc (count + objdir_count + 5);
360 if (object_directory)
362 strcpy (da_file_name, object_directory);
363 strcpy (bb_file_name, object_directory);
364 strcpy (bbg_file_name, object_directory);
366 if (object_directory[objdir_count - 1] != '/')
368 strcat (da_file_name, "/");
369 strcat (bb_file_name, "/");
370 strcat (bbg_file_name, "/");
373 cptr = rindex (input_file_name, '/');
374 if (cptr)
376 strcat (da_file_name, cptr + 1);
377 strcat (bb_file_name, cptr + 1);
378 strcat (bbg_file_name, cptr + 1);
380 else
382 strcat (da_file_name, input_file_name);
383 strcat (bb_file_name, input_file_name);
384 strcat (bbg_file_name, input_file_name);
387 else
389 strcpy (da_file_name, input_file_name);
390 strcpy (bb_file_name, input_file_name);
391 strcpy (bbg_file_name, input_file_name);
394 cptr = rindex (bb_file_name, '.');
395 if (cptr)
396 strcpy (cptr, ".bb");
397 else
398 strcat (bb_file_name, ".bb");
400 cptr = rindex (da_file_name, '.');
401 if (cptr)
402 strcpy (cptr, ".da");
403 else
404 strcat (da_file_name, ".da");
406 cptr = rindex (bbg_file_name, '.');
407 if (cptr)
408 strcpy (cptr, ".bbg");
409 else
410 strcat (bbg_file_name, ".bbg");
412 bb_file = fopen (bb_file_name, "r");
413 if (bb_file == NULL)
415 fnotice (stderr, "Could not open basic block file %s.\n", bb_file_name);
416 exit (FATAL_EXIT_CODE);
419 /* If none of the functions in the file were executed, then there won't
420 be a .da file. Just assume that all counts are zero in this case. */
421 da_file = fopen (da_file_name, "r");
422 if (da_file == NULL)
424 fnotice (stderr, "Could not open data file %s.\n", da_file_name);
425 fnotice (stderr, "Assuming that all execution counts are zero.\n");
428 bbg_file = fopen (bbg_file_name, "r");
429 if (bbg_file == NULL)
431 fnotice (stderr, "Could not open program flow graph file %s.\n",
432 bbg_file_name);
433 exit (FATAL_EXIT_CODE);
436 /* Check for empty .bbg file. This indicates that there is no executable
437 code in this source file. */
438 /* Set the EOF condition if at the end of file. */
439 ungetc (getc (bbg_file), bbg_file);
440 if (feof (bbg_file))
442 fnotice (stderr, "No executable code associated with file %s.\n",
443 input_file_name);
444 exit (FATAL_EXIT_CODE);
448 /* Initialize a new arc. */
450 static void
451 init_arc (arcptr, source, target, bb_graph)
452 struct adj_list *arcptr;
453 int source, target;
454 struct bb_info *bb_graph;
456 arcptr->target = target;
457 arcptr->source = source;
459 arcptr->arc_count = 0;
460 arcptr->count_valid = 0;
461 arcptr->on_tree = 0;
462 arcptr->fake = 0;
463 arcptr->fall_through = 0;
465 arcptr->succ_next = bb_graph[source].succ;
466 bb_graph[source].succ = arcptr;
467 bb_graph[source].succ_count++;
469 arcptr->pred_next = bb_graph[target].pred;
470 bb_graph[target].pred = arcptr;
471 bb_graph[target].pred_count++;
475 /* Reverse the arcs on a arc list. */
477 static struct adj_list *
478 reverse_arcs (arcptr)
479 struct adj_list *arcptr;
481 struct adj_list *prev = 0;
482 struct adj_list *next;
484 for ( ; arcptr; arcptr = next)
486 next = arcptr->succ_next;
487 arcptr->succ_next = prev;
488 prev = arcptr;
491 return prev;
495 /* Construct the program flow graph from the .bbg file, and read in the data
496 in the .da file. */
498 static void
499 create_program_flow_graph (bptr)
500 struct bb_info_list *bptr;
502 long num_blocks, number_arcs, src, dest, flag_bits, num_arcs_per_block;
503 int i;
504 struct adj_list *arcptr;
505 struct bb_info *bb_graph;
507 /* Read the number of blocks. */
508 __read_long (&num_blocks, bbg_file, 4);
510 /* Create an array of size bb number of bb_info structs. Bzero it. */
511 bb_graph = (struct bb_info *) xmalloc (num_blocks
512 * sizeof (struct bb_info));
513 bzero ((char *) bb_graph, sizeof (struct bb_info) * num_blocks);
515 bptr->bb_graph = bb_graph;
516 bptr->num_blocks = num_blocks;
518 /* Read and create each arc from the .bbg file. */
519 __read_long (&number_arcs, bbg_file, 4);
520 for (i = 0; i < num_blocks; i++)
522 int j;
524 __read_long (&num_arcs_per_block, bbg_file, 4);
525 for (j = 0; j < num_arcs_per_block; j++)
527 if (number_arcs-- < 0)
528 abort ();
530 src = i;
531 __read_long (&dest, bbg_file, 4);
533 arcptr = (struct adj_list *) xmalloc (sizeof (struct adj_list));
534 init_arc (arcptr, src, dest, bb_graph);
536 __read_long (&flag_bits, bbg_file, 4);
537 arcptr->on_tree = flag_bits & 0x1;
538 arcptr->fake = !! (flag_bits & 0x2);
539 arcptr->fall_through = !! (flag_bits & 0x4);
543 if (number_arcs)
544 abort ();
546 /* Read and ignore the -1 separating the arc list from the arc list of the
547 next function. */
548 __read_long (&src, bbg_file, 4);
549 if (src != -1)
550 abort ();
552 /* Must reverse the order of all succ arcs, to ensure that they match
553 the order of the data in the .da file. */
555 for (i = 0; i < num_blocks; i++)
556 if (bb_graph[i].succ)
557 bb_graph[i].succ = reverse_arcs (bb_graph[i].succ);
559 /* For each arc not on the spanning tree, set its execution count from
560 the .da file. */
562 /* The first count in the .da file is the number of times that the function
563 was entered. This is the exec_count for block zero. */
565 /* This duplicates code in branch_prob in profile.c. */
567 for (i = 0; i < num_blocks; i++)
568 for (arcptr = bb_graph[i].succ; arcptr; arcptr = arcptr->succ_next)
569 if (! arcptr->on_tree)
571 long tmp_count = 0;;
572 if (da_file && __read_long (&tmp_count, da_file, 8))
573 abort();
575 arcptr->arc_count = tmp_count;
576 arcptr->count_valid = 1;
577 bb_graph[i].succ_count--;
578 bb_graph[arcptr->target].pred_count--;
582 static void
583 solve_program_flow_graph (bptr)
584 struct bb_info_list *bptr;
586 int passes, changes, total;
587 int i;
588 struct adj_list *arcptr;
589 struct bb_info *bb_graph;
590 int num_blocks;
592 num_blocks = bptr->num_blocks;
593 bb_graph = bptr->bb_graph;
595 /* For every block in the file,
596 - if every exit/entrance arc has a known count, then set the block count
597 - if the block count is known, and every exit/entrance arc but one has
598 a known execution count, then set the count of the remaining arc
600 As arc counts are set, decrement the succ/pred count, but don't delete
601 the arc, that way we can easily tell when all arcs are known, or only
602 one arc is unknown. */
604 /* The order that the basic blocks are iterated through is important.
605 Since the code that finds spanning trees starts with block 0, low numbered
606 arcs are put on the spanning tree in preference to high numbered arcs.
607 Hence, most instrumented arcs are at the end. Graph solving works much
608 faster if we propagate numbers from the end to the start.
610 This takes an average of slightly more than 3 passes. */
612 changes = 1;
613 passes = 0;
614 while (changes)
616 passes++;
617 changes = 0;
619 for (i = num_blocks - 1; i >= 0; i--)
621 if (! bb_graph[i].count_valid)
623 if (bb_graph[i].succ_count == 0)
625 total = 0;
626 for (arcptr = bb_graph[i].succ; arcptr;
627 arcptr = arcptr->succ_next)
628 total += arcptr->arc_count;
629 bb_graph[i].exec_count = total;
630 bb_graph[i].count_valid = 1;
631 changes = 1;
633 else if (bb_graph[i].pred_count == 0)
635 total = 0;
636 for (arcptr = bb_graph[i].pred; arcptr;
637 arcptr = arcptr->pred_next)
638 total += arcptr->arc_count;
639 bb_graph[i].exec_count = total;
640 bb_graph[i].count_valid = 1;
641 changes = 1;
644 if (bb_graph[i].count_valid)
646 if (bb_graph[i].succ_count == 1)
648 total = 0;
649 /* One of the counts will be invalid, but it is zero,
650 so adding it in also doesn't hurt. */
651 for (arcptr = bb_graph[i].succ; arcptr;
652 arcptr = arcptr->succ_next)
653 total += arcptr->arc_count;
654 /* Calculate count for remaining arc by conservation. */
655 total = bb_graph[i].exec_count - total;
656 /* Search for the invalid arc, and set its count. */
657 for (arcptr = bb_graph[i].succ; arcptr;
658 arcptr = arcptr->succ_next)
659 if (! arcptr->count_valid)
660 break;
661 if (! arcptr)
662 abort ();
663 arcptr->count_valid = 1;
664 arcptr->arc_count = total;
665 bb_graph[i].succ_count--;
667 bb_graph[arcptr->target].pred_count--;
668 changes = 1;
670 if (bb_graph[i].pred_count == 1)
672 total = 0;
673 /* One of the counts will be invalid, but it is zero,
674 so adding it in also doesn't hurt. */
675 for (arcptr = bb_graph[i].pred; arcptr;
676 arcptr = arcptr->pred_next)
677 total += arcptr->arc_count;
678 /* Calculate count for remaining arc by conservation. */
679 total = bb_graph[i].exec_count - total;
680 /* Search for the invalid arc, and set its count. */
681 for (arcptr = bb_graph[i].pred; arcptr;
682 arcptr = arcptr->pred_next)
683 if (! arcptr->count_valid)
684 break;
685 if (! arcptr)
686 abort ();
687 arcptr->count_valid = 1;
688 arcptr->arc_count = total;
689 bb_graph[i].pred_count--;
691 bb_graph[arcptr->source].succ_count--;
692 changes = 1;
698 /* If the graph has been correctly solved, every block will have a
699 succ and pred count of zero. */
700 for (i = 0; i < num_blocks; i++)
701 if (bb_graph[i].succ_count || bb_graph[i].pred_count)
702 abort ();
706 static void
707 read_files ()
709 struct stat buf;
710 struct bb_info_list *list_end = 0;
711 struct bb_info_list *b_ptr;
712 long total;
714 /* Read and ignore the first word of the .da file, which is the count of
715 how many numbers follow. */
716 if (da_file && __read_long (&total, da_file, 8))
717 abort();
719 while (! feof (bbg_file))
721 b_ptr = (struct bb_info_list *) xmalloc (sizeof (struct bb_info_list));
723 b_ptr->next = 0;
724 if (list_end)
725 list_end->next = b_ptr;
726 else
727 bb_graph_list = b_ptr;
728 list_end = b_ptr;
730 /* Read in the data in the .bbg file and reconstruct the program flow
731 graph for one function. */
732 create_program_flow_graph (b_ptr);
734 /* Set the EOF condition if at the end of file. */
735 ungetc (getc (bbg_file), bbg_file);
738 /* Check to make sure the .da file data is valid. */
740 if (da_file)
742 if (feof (da_file))
743 fnotice (stderr, ".da file contents exhausted too early\n");
744 /* Should be at end of file now. */
745 if (__read_long (&total, da_file, 8) == 0)
746 fnotice (stderr, ".da file contents not exhausted\n");
749 /* Calculate all of the basic block execution counts and branch
750 taken probabilities. */
752 for (b_ptr = bb_graph_list; b_ptr; b_ptr = b_ptr->next)
753 solve_program_flow_graph (b_ptr);
755 /* Read in all of the data from the .bb file. This info will be accessed
756 sequentially twice. */
757 stat (bb_file_name, &buf);
758 bb_data_size = buf.st_size / 4;
760 bb_data = (char *) xmalloc ((unsigned) buf.st_size);
761 fread (bb_data, sizeof (char), buf.st_size, bb_file);
763 fclose (bb_file);
764 if (da_file)
765 fclose (da_file);
766 fclose (bbg_file);
770 /* Scan the data in the .bb file to find all source files referenced,
771 and the largest line number mentioned in each one. */
773 static void
774 scan_for_source_files ()
776 struct sourcefile *s_ptr = NULL;
777 char *ptr;
778 int count;
779 long line_num;
781 /* Search the bb_data to find:
782 1) The number of sources files contained herein, and
783 2) The largest line number for each source file. */
785 ptr = bb_data;
786 sources = 0;
787 for (count = 0; count < bb_data_size; count++)
789 __fetch_long (&line_num, ptr, 4);
790 ptr += 4;
791 if (line_num == -1)
793 /* A source file name follows. Check to see if we already have
794 a sourcefile structure for this file. */
795 s_ptr = sources;
796 while (s_ptr && strcmp (s_ptr->name, ptr))
797 s_ptr = s_ptr->next;
799 if (s_ptr == 0)
801 /* No sourcefile structure for this file name exists, create
802 a new one, and append it to the front of the sources list. */
803 s_ptr = (struct sourcefile *) xmalloc (sizeof(struct sourcefile));
804 s_ptr->name = xmalloc (strlen ((char *) ptr) + 1);
805 strcpy (s_ptr->name, (char *) ptr);
806 s_ptr->maxlineno = 0;
807 s_ptr->next = sources;
808 sources = s_ptr;
811 /* Scan past the file name. */
813 long delim;
814 do {
815 count++;
816 __fetch_long (&delim, ptr, 4);
817 ptr += 4;
818 } while (delim != line_num);
821 else if (line_num == -2)
823 long delim;
825 /* A function name follows. Ignore it. */
826 do {
827 count++;
828 __fetch_long (&delim, ptr, 4);
829 ptr += 4;
830 } while (delim != line_num);
832 /* There will be a zero before the first file name, in which case s_ptr
833 will still be uninitialized. So, only try to set the maxlineno
834 field if line_num is non-zero. */
835 else if (line_num > 0)
837 if (s_ptr->maxlineno <= line_num)
838 s_ptr->maxlineno = line_num + 1;
840 else if (line_num < 0)
842 /* Don't know what this is, but it's garbage. */
843 abort();
848 /* For calculating coverage at the function level. */
850 static int function_source_lines;
851 static int function_source_lines_executed;
852 static int function_branches;
853 static int function_branches_executed;
854 static int function_branches_taken;
855 static int function_calls;
856 static int function_calls_executed;
857 static char *function_name;
859 /* Calculate the branch taken probabilities for all arcs branches at the
860 end of this block. */
862 static void
863 calculate_branch_probs (current_graph, block_num, branch_probs, last_line_num)
864 struct bb_info_list *current_graph;
865 int block_num;
866 struct arcdata **branch_probs;
867 int last_line_num;
869 int total;
870 struct adj_list *arcptr;
871 struct arcdata *end_ptr, *a_ptr;
873 total = current_graph->bb_graph[block_num].exec_count;
874 for (arcptr = current_graph->bb_graph[block_num].succ; arcptr;
875 arcptr = arcptr->succ_next)
877 /* Ignore fall through arcs as they aren't really branches. */
879 if (arcptr->fall_through)
880 continue;
882 a_ptr = (struct arcdata *) xmalloc (sizeof (struct arcdata));
883 if (total == 0)
884 a_ptr->prob = -1;
885 else
886 a_ptr->prob = ((arcptr->arc_count * 100) + (total >> 1)) / total;
887 a_ptr->call_insn = arcptr->fake;
889 if (output_function_summary)
891 if (a_ptr->call_insn)
893 function_calls++;
894 if (a_ptr->prob != -1)
895 function_calls_executed++;
897 else
899 function_branches++;
900 if (a_ptr->prob != -1)
901 function_branches_executed++;
902 if (a_ptr->prob > 0)
903 function_branches_taken++;
907 /* Append the new branch to the end of the list. */
908 a_ptr->next = 0;
909 if (! branch_probs[last_line_num])
910 branch_probs[last_line_num] = a_ptr;
911 else
913 end_ptr = branch_probs[last_line_num];
914 while (end_ptr->next != 0)
915 end_ptr = end_ptr->next;
916 end_ptr->next = a_ptr;
921 /* Output summary info for a function. */
923 static void
924 function_summary ()
926 if (function_source_lines)
927 fnotice (stdout, "%6.2f%% of %d source lines executed in function %s\n",
928 (((double) function_source_lines_executed / function_source_lines)
929 * 100), function_source_lines, function_name);
930 else
931 fnotice (stdout, "No executable source lines in function %s\n",
932 function_name);
934 if (output_branch_probs)
936 if (function_branches)
938 fnotice (stdout, "%6.2f%% of %d branches executed in function %s\n",
939 (((double) function_branches_executed / function_branches)
940 * 100), function_branches, function_name);
941 fnotice (stdout,
942 "%6.2f%% of %d branches taken at least once in function %s\n",
943 (((double) function_branches_taken / function_branches)
944 * 100), function_branches, function_name);
946 else
947 fnotice (stdout, "No branches in function %s\n", function_name);
948 if (function_calls)
949 fnotice (stdout, "%6.2f%% of %d calls executed in function %s\n",
950 (((double) function_calls_executed / function_calls)
951 * 100), function_calls, function_name);
952 else
953 fnotice (stdout, "No calls in function %s\n", function_name);
957 /* Calculate line execution counts, and output the data to a .tcov file. */
959 static void
960 output_data ()
962 /* When scanning data, this is true only if the data applies to the
963 current source file. */
964 int this_file;
965 /* An array indexed by line number which indicates how many times that line
966 was executed. */
967 long *line_counts;
968 /* An array indexed by line number which indicates whether the line was
969 present in the bb file (i.e. whether it had code associate with it).
970 Lines never executed are those which both exist, and have zero execution
971 counts. */
972 char *line_exists;
973 /* An array indexed by line number, which contains a list of branch
974 probabilities, one for each branch on that line. */
975 struct arcdata **branch_probs = NULL;
976 struct sourcefile *s_ptr;
977 char *source_file_name;
978 FILE *source_file;
979 struct bb_info_list *current_graph;
980 int count;
981 char *cptr;
982 long block_num;
983 long line_num;
984 long last_line_num = 0;
985 int i;
986 struct arcdata *a_ptr;
987 /* Buffer used for reading in lines from the source file. */
988 char string[STRING_SIZE];
989 /* For calculating coverage at the file level. */
990 int total_source_lines;
991 int total_source_lines_executed;
992 int total_branches;
993 int total_branches_executed;
994 int total_branches_taken;
995 int total_calls;
996 int total_calls_executed;
998 /* Now, for each source file, allocate an array big enough to hold a count
999 for each line. Scan through the bb_data, and when the file name matches
1000 the current file name, then for each following line number, increment
1001 the line number execution count indicated by the execution count of
1002 the appropriate basic block. */
1004 for (s_ptr = sources; s_ptr; s_ptr = s_ptr->next)
1006 /* If this is a relative file name, and an object directory has been
1007 specified, then make it relative to the object directory name. */
1008 if (*s_ptr->name != '/' && object_directory != 0
1009 && *object_directory != '\0')
1011 int objdir_count = strlen (object_directory);
1012 source_file_name = xmalloc (objdir_count + strlen (s_ptr->name) + 2);
1013 strcpy (source_file_name, object_directory);
1014 if (object_directory[objdir_count - 1] != '/')
1015 source_file_name[objdir_count++] = '/';
1016 strcpy (source_file_name + objdir_count, s_ptr->name);
1018 else
1019 source_file_name = s_ptr->name;
1021 line_counts = (long *) xmalloc (sizeof (long) * s_ptr->maxlineno);
1022 bzero ((char *) line_counts, sizeof (long) * s_ptr->maxlineno);
1023 line_exists = xmalloc (s_ptr->maxlineno);
1024 bzero (line_exists, s_ptr->maxlineno);
1025 if (output_branch_probs)
1027 branch_probs = (struct arcdata **) xmalloc (sizeof (struct arcdata *)
1028 * s_ptr->maxlineno);
1029 bzero ((char *) branch_probs,
1030 sizeof (struct arcdata *) * s_ptr->maxlineno);
1033 /* There will be a zero at the beginning of the bb info, before the
1034 first list of line numbers, so must initialize block_num to 0. */
1035 block_num = 0;
1036 this_file = 0;
1037 current_graph = 0;
1039 /* Pointer into the bb_data, incremented while scanning the data. */
1040 char *ptr = bb_data;
1041 for (count = 0; count < bb_data_size; count++)
1043 long delim;
1045 __fetch_long (&line_num, ptr, 4);
1046 ptr += 4;
1047 if (line_num == -1)
1049 /* Marks the beginning of a file name. Check to see whether
1050 this is the filename we are currently collecting data for. */
1052 if (strcmp (s_ptr->name, ptr))
1053 this_file = 0;
1054 else
1055 this_file = 1;
1057 /* Scan past the file name. */
1058 do {
1059 count++;
1060 __fetch_long (&delim, ptr, 4);
1061 ptr += 4;
1062 } while (delim != line_num);
1064 else if (line_num == -2)
1066 /* Marks the start of a new function. Advance to the next
1067 program flow graph. */
1069 if (! current_graph)
1070 current_graph = bb_graph_list;
1071 else
1073 if (block_num == current_graph->num_blocks - 1)
1074 /* Last block falls through to exit. */
1076 else if (block_num == current_graph->num_blocks - 2)
1078 if (output_branch_probs && this_file)
1079 calculate_branch_probs (current_graph, block_num,
1080 branch_probs, last_line_num);
1082 else
1084 fnotice (stderr,
1085 "didn't use all bb entries of graph, function %s\n",
1086 function_name);
1087 fnotice (stderr, "block_num = %ld, num_blocks = %d\n",
1088 block_num, current_graph->num_blocks);
1091 current_graph = current_graph->next;
1092 block_num = 0;
1094 if (output_function_summary && this_file)
1095 function_summary ();
1098 if (output_function_summary)
1100 function_source_lines = 0;
1101 function_source_lines_executed = 0;
1102 function_branches = 0;
1103 function_branches_executed = 0;
1104 function_branches_taken = 0;
1105 function_calls = 0;
1106 function_calls_executed = 0;
1109 /* Save the function name for later use. */
1110 function_name = ptr;
1112 /* Scan past the file name. */
1113 do {
1114 count++;
1115 __fetch_long (&delim, ptr, 4);
1116 ptr += 4;
1117 } while (delim != line_num);
1119 else if (line_num == 0)
1121 /* Marks the end of a block. */
1123 if (block_num >= current_graph->num_blocks)
1125 fnotice (stderr, "ERROR: too many basic blocks in .bb file %s\n",
1126 function_name);
1127 abort ();
1130 if (output_branch_probs && this_file)
1131 calculate_branch_probs (current_graph, block_num,
1132 branch_probs, last_line_num);
1134 block_num++;
1136 else if (this_file)
1138 if (output_function_summary)
1140 if (line_exists[line_num] == 0)
1141 function_source_lines++;
1142 if (line_counts[line_num] == 0
1143 && current_graph->bb_graph[block_num].exec_count != 0)
1144 function_source_lines_executed++;
1147 /* Accumulate execution data for this line number. */
1149 line_counts[line_num]
1150 += current_graph->bb_graph[block_num].exec_count;
1151 line_exists[line_num] = 1;
1152 last_line_num = line_num;
1157 if (output_function_summary && this_file)
1158 function_summary ();
1160 /* Calculate summary test coverage statistics. */
1162 total_source_lines = 0;
1163 total_source_lines_executed = 0;
1164 total_branches = 0;
1165 total_branches_executed = 0;
1166 total_branches_taken = 0;
1167 total_calls = 0;
1168 total_calls_executed = 0;
1170 for (count = 1; count < s_ptr->maxlineno; count++)
1172 if (line_exists[count])
1174 total_source_lines++;
1175 if (line_counts[count])
1176 total_source_lines_executed++;
1178 if (output_branch_probs)
1180 for (a_ptr = branch_probs[count]; a_ptr; a_ptr = a_ptr->next)
1182 if (a_ptr->call_insn)
1184 total_calls++;
1185 if (a_ptr->prob != -1)
1186 total_calls_executed++;
1188 else
1190 total_branches++;
1191 if (a_ptr->prob != -1)
1192 total_branches_executed++;
1193 if (a_ptr->prob > 0)
1194 total_branches_taken++;
1200 if (total_source_lines)
1201 fnotice (stdout,
1202 "%6.2f%% of %d source lines executed in file %s\n",
1203 (((double) total_source_lines_executed / total_source_lines)
1204 * 100), total_source_lines, source_file_name);
1205 else
1206 fnotice (stdout, "No executable source lines in file %s\n",
1207 source_file_name);
1209 if (output_branch_probs)
1211 if (total_branches)
1213 fnotice (stdout, "%6.2f%% of %d branches executed in file %s\n",
1214 (((double) total_branches_executed / total_branches)
1215 * 100), total_branches, source_file_name);
1216 fnotice (stdout,
1217 "%6.2f%% of %d branches taken at least once in file %s\n",
1218 (((double) total_branches_taken / total_branches)
1219 * 100), total_branches, source_file_name);
1221 else
1222 fnotice (stdout, "No branches in file %s\n", source_file_name);
1223 if (total_calls)
1224 fnotice (stdout, "%6.2f%% of %d calls executed in file %s\n",
1225 (((double) total_calls_executed / total_calls)
1226 * 100), total_calls, source_file_name);
1227 else
1228 fnotice (stdout, "No calls in file %s\n", source_file_name);
1231 if (output_gcov_file)
1233 /* Now the statistics are ready. Read in the source file one line
1234 at a time, and output that line to the gcov file preceded by
1235 its execution count if non zero. */
1237 source_file = fopen (source_file_name, "r");
1238 if (source_file == NULL)
1240 fnotice (stderr, "Could not open source file %s.\n",
1241 source_file_name);
1242 free (line_counts);
1243 free (line_exists);
1244 continue;
1247 count = strlen (source_file_name);
1248 cptr = rindex (s_ptr->name, '/');
1249 if (cptr)
1250 cptr = cptr + 1;
1251 else
1252 cptr = s_ptr->name;
1253 if (output_long_names && strcmp (cptr, input_file_name))
1255 gcov_file_name = xmalloc (count + 7 + strlen (input_file_name));
1257 cptr = rindex (input_file_name, '/');
1258 if (cptr)
1259 strcpy (gcov_file_name, cptr + 1);
1260 else
1261 strcpy (gcov_file_name, input_file_name);
1263 strcat (gcov_file_name, ".");
1265 cptr = rindex (source_file_name, '/');
1266 if (cptr)
1267 strcat (gcov_file_name, cptr + 1);
1268 else
1269 strcat (gcov_file_name, source_file_name);
1271 else
1273 gcov_file_name = xmalloc (count + 6);
1274 cptr = rindex (source_file_name, '/');
1275 if (cptr)
1276 strcpy (gcov_file_name, cptr + 1);
1277 else
1278 strcpy (gcov_file_name, source_file_name);
1281 /* Don't strip off the ending for compatibility with tcov, since
1282 this results in confusion if there is more than one file with
1283 the same basename, e.g. tmp.c and tmp.h. */
1284 strcat (gcov_file_name, ".gcov");
1286 gcov_file = fopen (gcov_file_name, "w");
1288 if (gcov_file == NULL)
1290 fnotice (stderr, "Could not open output file %s.\n",
1291 gcov_file_name);
1292 fclose (source_file);
1293 free (line_counts);
1294 free (line_exists);
1295 continue;
1298 fnotice (stdout, "Creating %s.\n", gcov_file_name);
1300 for (count = 1; count < s_ptr->maxlineno; count++)
1302 char *retval;
1303 int len;
1305 retval = fgets (string, STRING_SIZE, source_file);
1307 /* For lines which don't exist in the .bb file, print nothing
1308 before the source line. For lines which exist but were never
1309 executed, print ###### before the source line. Otherwise,
1310 print the execution count before the source line. */
1311 /* There are 16 spaces of indentation added before the source
1312 line so that tabs won't be messed up. */
1313 if (line_exists[count])
1315 if (line_counts[count])
1316 fprintf (gcov_file, "%12ld %s", line_counts[count],
1317 string);
1318 else
1319 fprintf (gcov_file, " ###### %s", string);
1321 else
1322 fprintf (gcov_file, "\t\t%s", string);
1324 /* In case the source file line is larger than our buffer, keep
1325 reading and outputting lines until we get a newline. */
1326 len = strlen (string);
1327 while ((len == 0 || string[strlen (string) - 1] != '\n')
1328 && retval != NULL)
1330 retval = fgets (string, STRING_SIZE, source_file);
1331 fputs (string, gcov_file);
1334 if (output_branch_probs)
1336 for (i = 0, a_ptr = branch_probs[count]; a_ptr;
1337 a_ptr = a_ptr->next, i++)
1339 if (a_ptr->call_insn)
1341 if (a_ptr->prob == -1)
1342 fnotice (gcov_file, "call %d never executed\n", i);
1343 else
1344 fnotice (gcov_file,
1345 "call %d returns = %d%%\n",
1346 i, 100 - a_ptr->prob);
1348 else
1350 if (a_ptr->prob == -1)
1351 fnotice (gcov_file, "branch %d never executed\n",
1353 else
1354 fnotice (gcov_file, "branch %d taken = %d%%\n", i,
1355 a_ptr->prob);
1360 /* Gracefully handle errors while reading the source file. */
1361 if (retval == NULL)
1363 fnotice (stderr,
1364 "Unexpected EOF while reading source file %s.\n",
1365 source_file_name);
1366 break;
1370 /* Handle all remaining source lines. There may be lines
1371 after the last line of code. */
1374 char *retval = fgets (string, STRING_SIZE, source_file);
1375 while (retval != NULL)
1377 int len;
1379 fprintf (gcov_file, "\t\t%s", string);
1381 /* In case the source file line is larger than our buffer, keep
1382 reading and outputting lines until we get a newline. */
1383 len = strlen (string);
1384 while ((len == 0 || string[strlen (string) - 1] != '\n')
1385 && retval != NULL)
1387 retval = fgets (string, STRING_SIZE, source_file);
1388 fputs (string, gcov_file);
1391 retval = fgets (string, STRING_SIZE, source_file);
1395 fclose (source_file);
1396 fclose (gcov_file);
1399 free (line_counts);
1400 free (line_exists);