New test from PR #3242
[official-gcc.git] / gcc / gcov.c
blobab218206f2363670477448fb643724d4682c610f
1 /* Gcov.c: prepend line execution counts and branch probabilities to a
2 source file.
3 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998,
4 1999, 2000, 2001 Free Software Foundation, Inc.
5 Contributed by James E. Wilson of Cygnus Support.
6 Mangled by Bob Manson of Cygnus Support.
8 Gcov is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
13 Gcov is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Gcov; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
23 /* ??? The code in final.c that produces the struct bb assumes that there is
24 no padding between the fields. This is not necessary true. The current
25 code can only be trusted if longs and pointers are the same size. */
27 /* ??? No need to print an execution count on every line, could just print
28 it on the first line of each block, and only print it on a subsequent
29 line in the same block if the count changes. */
31 /* ??? Print a list of the ten blocks with the highest execution counts,
32 and list the line numbers corresponding to those blocks. Also, perhaps
33 list the line numbers with the highest execution counts, only printing
34 the first if there are several which are all listed in the same block. */
36 /* ??? Should have an option to print the number of basic blocks, and the
37 percent of them that are covered. */
39 /* ??? Does not correctly handle the case where two .bb files refer to the
40 same included source file. For example, if one has a short file containing
41 only inline functions, which is then included in two other files, then
42 there will be two .bb files which refer to the include file, but there
43 is no way to get the total execution counts for the included file, can
44 only get execution counts for one or the other of the including files. */
46 #include "config.h"
47 #include "system.h"
48 #include "intl.h"
49 #undef abort
51 typedef HOST_WIDEST_INT gcov_type;
52 #include "gcov-io.h"
54 /* The .bb file format consists of several lists of 4-byte integers
55 which are the line numbers of each basic block in the file. Each
56 list is terminated by a zero. These lists correspond to the basic
57 blocks in the reconstructed program flow graph.
59 A line number of -1 indicates that a source file name (padded to a
60 long boundary) follows. The padded file name is followed by
61 another -1 to make it easy to scan past file names. A -2 indicates
62 that a function name (padded to a long boundary) follows; the name
63 is followed by another -2 to make it easy to scan past the function
64 name.
66 The .bbg file contains enough info to enable gcov to reconstruct the
67 program flow graph. The first word is the number of basic blocks,
68 the second word is the number of arcs, followed by the list of arcs
69 (source bb, dest bb pairs), then a -1, then the number of instrumented
70 arcs followed by the instrumented arcs, followed by another -1. This
71 is repeated for each function.
73 The .da file contains the execution count for each instrumented branch.
75 The .bb and .bbg files are created by giving GCC the -ftest-coverage option,
76 and the .da files are created when an executable compiled with
77 -fprofile-arcs is run. */
79 /* The functions in this file for creating and solution program flow graphs
80 are very similar to functions in the gcc source file profile.c. */
82 char gcov_version_string[] = "GNU gcov version 1.5\n";
84 /* This is the size of the buffer used to read in source file lines. */
86 #define STRING_SIZE 200
88 /* One copy of this structure is created for each source file mentioned in the
89 .bb file. */
91 struct sourcefile
93 char *name;
94 int maxlineno;
95 struct sourcefile *next;
98 /* This points to the head of the sourcefile structure list. */
100 struct sourcefile *sources;
102 /* One of these is dynamically created whenever we identify an arc in the
103 function. */
105 struct adj_list {
106 int source;
107 int target;
108 gcov_type arc_count;
109 unsigned int count_valid : 1;
110 unsigned int on_tree : 1;
111 unsigned int fake : 1;
112 unsigned int fall_through : 1;
113 #if 0
114 /* Not needed for gcov, but defined in profile.c. */
115 rtx branch_insn;
116 #endif
117 struct adj_list *pred_next;
118 struct adj_list *succ_next;
121 /* Count the number of basic blocks, and create an array of these structures,
122 one for each bb in the function. */
124 struct bb_info {
125 struct adj_list *succ;
126 struct adj_list *pred;
127 gcov_type succ_count;
128 gcov_type pred_count;
129 gcov_type exec_count;
130 unsigned int count_valid : 1;
131 unsigned int on_tree : 1;
132 #if 0
133 /* Not needed for gcov, but defined in profile.c. */
134 rtx first_insn;
135 #endif
138 /* When outputting branch probabilities, one of these structures is created
139 for each branch/call. */
141 struct arcdata
143 gcov_type hits;
144 gcov_type total;
145 int call_insn;
146 struct arcdata *next;
149 /* Used to save the list of bb_graphs, one per function. */
151 struct bb_info_list {
152 /* Indexed by block number, holds the basic block graph for one function. */
153 struct bb_info *bb_graph;
154 int num_blocks;
155 struct bb_info_list *next;
158 /* Holds a list of function basic block graphs. */
160 static struct bb_info_list *bb_graph_list = 0;
162 /* Name and file pointer of the input file for the basic block graph. */
164 static char *bbg_file_name;
165 static FILE *bbg_file;
167 /* Name and file pointer of the input file for the arc count data. */
169 static char *da_file_name;
170 static FILE *da_file;
172 /* Name and file pointer of the input file for the basic block line counts. */
174 static char *bb_file_name;
175 static FILE *bb_file;
177 /* Holds the entire contents of the bb_file read into memory. */
179 static char *bb_data;
181 /* Size of bb_data array in longs. */
183 static long bb_data_size;
185 /* Name and file pointer of the output file. */
187 static char *gcov_file_name;
188 static FILE *gcov_file;
190 /* Name of the file mentioned on the command line. */
192 static char *input_file_name = 0;
194 /* Output branch probabilities if true. */
196 static int output_branch_probs = 0;
198 /* Output a gcov file if this is true. This is on by default, and can
199 be turned off by the -n option. */
201 static int output_gcov_file = 1;
203 /* For included files, make the gcov output file name include the name of
204 the input source file. For example, if x.h is included in a.c, then the
205 output file name is a.c.x.h.gcov instead of x.h.gcov. This works only
206 when a single source file is specified. */
208 static int output_long_names = 0;
210 /* Output summary info for each function. */
212 static int output_function_summary = 0;
214 /* Object directory file prefix. This is the directory where .bb and .bbg
215 files are looked for, if non-zero. */
217 static char *object_directory = 0;
219 /* Output the number of times a branch was taken as opposed to the percentage
220 of times it was taken. Turned on by the -c option */
222 static int output_branch_counts = 0;
224 /* Forward declarations. */
225 static void process_args PARAMS ((int, char **));
226 static void open_files PARAMS ((void));
227 static void read_files PARAMS ((void));
228 static void scan_for_source_files PARAMS ((void));
229 static void output_data PARAMS ((void));
230 static void print_usage PARAMS ((void)) ATTRIBUTE_NORETURN;
231 static void init_arc PARAMS ((struct adj_list *, int, int, struct bb_info *));
232 static struct adj_list *reverse_arcs PARAMS ((struct adj_list *));
233 static void create_program_flow_graph PARAMS ((struct bb_info_list *));
234 static void solve_program_flow_graph PARAMS ((struct bb_info_list *));
235 static void calculate_branch_probs PARAMS ((struct bb_info_list *, int,
236 struct arcdata **, int));
237 static void function_summary PARAMS ((void));
239 extern int main PARAMS ((int, char **));
242 main (argc, argv)
243 int argc;
244 char **argv;
246 /* LC_CTYPE determines the character set used by the terminal so it has be set
247 to output messages correctly. */
249 #ifdef HAVE_LC_MESSAGES
250 setlocale (LC_CTYPE, "");
251 setlocale (LC_MESSAGES, "");
252 #else
253 setlocale (LC_ALL, "");
254 #endif
256 (void) bindtextdomain (PACKAGE, localedir);
257 (void) textdomain (PACKAGE);
259 process_args (argc, argv);
261 open_files ();
263 read_files ();
265 scan_for_source_files ();
267 output_data ();
269 return 0;
272 static void fnotice PARAMS ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2;
273 static void
274 fnotice VPARAMS ((FILE *file, const char *msgid, ...))
276 #ifndef ANSI_PROTOTYPES
277 FILE *file;
278 const char *msgid;
279 #endif
280 va_list ap;
282 VA_START (ap, msgid);
284 #ifndef ANSI_PROTOTYPES
285 file = va_arg (ap, FILE *);
286 msgid = va_arg (ap, const char *);
287 #endif
289 vfprintf (file, _(msgid), ap);
290 va_end (ap);
293 /* More 'friendly' abort that prints the line and file.
294 config.h can #define abort fancy_abort if you like that sort of thing. */
295 extern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN;
297 void
298 fancy_abort ()
300 fnotice (stderr, "Internal gcov abort.\n");
301 exit (FATAL_EXIT_CODE);
304 /* Print a usage message and exit. */
306 static void
307 print_usage ()
309 fnotice (stderr, "gcov [-b] [-v] [-n] [-l] [-f] [-o OBJDIR] file\n");
310 exit (FATAL_EXIT_CODE);
313 /* Parse the command line. */
315 static void
316 process_args (argc, argv)
317 int argc;
318 char **argv;
320 int i;
322 for (i = 1; i < argc; i++)
324 if (argv[i][0] == '-')
326 if (argv[i][1] == 'b')
327 output_branch_probs = 1;
328 else if (argv[i][1] == 'c')
329 output_branch_counts = 1;
330 else if (argv[i][1] == 'v')
331 fputs (gcov_version_string, stderr);
332 else if (argv[i][1] == 'n')
333 output_gcov_file = 0;
334 else if (argv[i][1] == 'l')
335 output_long_names = 1;
336 else if (argv[i][1] == 'f')
337 output_function_summary = 1;
338 else if (argv[i][1] == 'o' && argv[i][2] == '\0')
339 object_directory = argv[++i];
340 else
341 print_usage ();
343 else if (! input_file_name)
344 input_file_name = argv[i];
345 else
346 print_usage ();
349 if (! input_file_name)
350 print_usage ();
354 /* Find and open the .bb, .da, and .bbg files. */
356 static void
357 open_files ()
359 int count, objdir_count;
360 char *cptr;
362 /* Determine the names of the .bb, .bbg, and .da files. Strip off the
363 extension, if any, and append the new extensions. */
364 count = strlen (input_file_name);
365 if (object_directory)
366 objdir_count = strlen (object_directory);
367 else
368 objdir_count = 0;
370 da_file_name = xmalloc (count + objdir_count + 4);
371 bb_file_name = xmalloc (count + objdir_count + 4);
372 bbg_file_name = xmalloc (count + objdir_count + 5);
374 if (object_directory)
376 strcpy (da_file_name, object_directory);
377 strcpy (bb_file_name, object_directory);
378 strcpy (bbg_file_name, object_directory);
380 if (object_directory[objdir_count - 1] != '/')
382 strcat (da_file_name, "/");
383 strcat (bb_file_name, "/");
384 strcat (bbg_file_name, "/");
387 cptr = strrchr (input_file_name, '/');
388 if (cptr)
390 strcat (da_file_name, cptr + 1);
391 strcat (bb_file_name, cptr + 1);
392 strcat (bbg_file_name, cptr + 1);
394 else
396 strcat (da_file_name, input_file_name);
397 strcat (bb_file_name, input_file_name);
398 strcat (bbg_file_name, input_file_name);
401 else
403 strcpy (da_file_name, input_file_name);
404 strcpy (bb_file_name, input_file_name);
405 strcpy (bbg_file_name, input_file_name);
408 cptr = strrchr (bb_file_name, '.');
409 if (cptr)
410 strcpy (cptr, ".bb");
411 else
412 strcat (bb_file_name, ".bb");
414 cptr = strrchr (da_file_name, '.');
415 if (cptr)
416 strcpy (cptr, ".da");
417 else
418 strcat (da_file_name, ".da");
420 cptr = strrchr (bbg_file_name, '.');
421 if (cptr)
422 strcpy (cptr, ".bbg");
423 else
424 strcat (bbg_file_name, ".bbg");
426 bb_file = fopen (bb_file_name, "rb");
427 if (bb_file == NULL)
429 fnotice (stderr, "Could not open basic block file %s.\n", bb_file_name);
430 exit (FATAL_EXIT_CODE);
433 /* If none of the functions in the file were executed, then there won't
434 be a .da file. Just assume that all counts are zero in this case. */
435 da_file = fopen (da_file_name, "rb");
436 if (da_file == NULL)
438 fnotice (stderr, "Could not open data file %s.\n", da_file_name);
439 fnotice (stderr, "Assuming that all execution counts are zero.\n");
442 bbg_file = fopen (bbg_file_name, "rb");
443 if (bbg_file == NULL)
445 fnotice (stderr, "Could not open program flow graph file %s.\n",
446 bbg_file_name);
447 exit (FATAL_EXIT_CODE);
450 /* Check for empty .bbg file. This indicates that there is no executable
451 code in this source file. */
452 /* Set the EOF condition if at the end of file. */
453 ungetc (getc (bbg_file), bbg_file);
454 if (feof (bbg_file))
456 fnotice (stderr, "No executable code associated with file %s.\n",
457 input_file_name);
458 exit (FATAL_EXIT_CODE);
462 /* Initialize a new arc. */
464 static void
465 init_arc (arcptr, source, target, bb_graph)
466 struct adj_list *arcptr;
467 int source, target;
468 struct bb_info *bb_graph;
470 arcptr->target = target;
471 arcptr->source = source;
473 arcptr->arc_count = 0;
474 arcptr->count_valid = 0;
475 arcptr->on_tree = 0;
476 arcptr->fake = 0;
477 arcptr->fall_through = 0;
479 arcptr->succ_next = bb_graph[source].succ;
480 bb_graph[source].succ = arcptr;
481 bb_graph[source].succ_count++;
483 arcptr->pred_next = bb_graph[target].pred;
484 bb_graph[target].pred = arcptr;
485 bb_graph[target].pred_count++;
489 /* Reverse the arcs on a arc list. */
491 static struct adj_list *
492 reverse_arcs (arcptr)
493 struct adj_list *arcptr;
495 struct adj_list *prev = 0;
496 struct adj_list *next;
498 for ( ; arcptr; arcptr = next)
500 next = arcptr->succ_next;
501 arcptr->succ_next = prev;
502 prev = arcptr;
505 return prev;
509 /* Construct the program flow graph from the .bbg file, and read in the data
510 in the .da file. */
512 static void
513 create_program_flow_graph (bptr)
514 struct bb_info_list *bptr;
516 long num_blocks, number_arcs, src, dest, flag_bits, num_arcs_per_block;
517 int i;
518 struct adj_list *arcptr;
519 struct bb_info *bb_graph;
521 /* Read the number of blocks. */
522 __read_long (&num_blocks, bbg_file, 4);
524 /* Create an array of size bb number of bb_info structs. */
525 bb_graph = (struct bb_info *) xcalloc (num_blocks, sizeof (struct bb_info));
527 bptr->bb_graph = bb_graph;
528 bptr->num_blocks = num_blocks;
530 /* Read and create each arc from the .bbg file. */
531 __read_long (&number_arcs, bbg_file, 4);
532 for (i = 0; i < num_blocks; i++)
534 int j;
536 __read_long (&num_arcs_per_block, bbg_file, 4);
537 for (j = 0; j < num_arcs_per_block; j++)
539 if (number_arcs-- < 0)
540 abort ();
542 src = i;
543 __read_long (&dest, bbg_file, 4);
545 arcptr = (struct adj_list *) xmalloc (sizeof (struct adj_list));
546 init_arc (arcptr, src, dest, bb_graph);
548 __read_long (&flag_bits, bbg_file, 4);
549 arcptr->on_tree = flag_bits & 0x1;
550 arcptr->fake = !! (flag_bits & 0x2);
551 arcptr->fall_through = !! (flag_bits & 0x4);
555 if (number_arcs)
556 abort ();
558 /* Read and ignore the -1 separating the arc list from the arc list of the
559 next function. */
560 __read_long (&src, bbg_file, 4);
561 if (src != -1)
562 abort ();
564 /* Must reverse the order of all succ arcs, to ensure that they match
565 the order of the data in the .da file. */
567 for (i = 0; i < num_blocks; i++)
568 if (bb_graph[i].succ)
569 bb_graph[i].succ = reverse_arcs (bb_graph[i].succ);
571 /* For each arc not on the spanning tree, set its execution count from
572 the .da file. */
574 /* The first count in the .da file is the number of times that the function
575 was entered. This is the exec_count for block zero. */
577 /* This duplicates code in branch_prob in profile.c. */
579 for (i = 0; i < num_blocks; i++)
580 for (arcptr = bb_graph[i].succ; arcptr; arcptr = arcptr->succ_next)
581 if (! arcptr->on_tree)
583 gcov_type tmp_count = 0;
584 if (da_file && __read_gcov_type (&tmp_count, da_file, 8))
585 abort();
587 arcptr->arc_count = tmp_count;
588 arcptr->count_valid = 1;
589 bb_graph[i].succ_count--;
590 bb_graph[arcptr->target].pred_count--;
594 static void
595 solve_program_flow_graph (bptr)
596 struct bb_info_list *bptr;
598 int passes, changes;
599 gcov_type total;
600 int i;
601 struct adj_list *arcptr;
602 struct bb_info *bb_graph;
603 int num_blocks;
605 num_blocks = bptr->num_blocks;
606 bb_graph = bptr->bb_graph;
608 /* For every block in the file,
609 - if every exit/entrance arc has a known count, then set the block count
610 - if the block count is known, and every exit/entrance arc but one has
611 a known execution count, then set the count of the remaining arc
613 As arc counts are set, decrement the succ/pred count, but don't delete
614 the arc, that way we can easily tell when all arcs are known, or only
615 one arc is unknown. */
617 /* The order that the basic blocks are iterated through is important.
618 Since the code that finds spanning trees starts with block 0, low numbered
619 arcs are put on the spanning tree in preference to high numbered arcs.
620 Hence, most instrumented arcs are at the end. Graph solving works much
621 faster if we propagate numbers from the end to the start.
623 This takes an average of slightly more than 3 passes. */
625 changes = 1;
626 passes = 0;
627 while (changes)
629 passes++;
630 changes = 0;
632 for (i = num_blocks - 1; i >= 0; i--)
634 if (! bb_graph[i].count_valid)
636 if (bb_graph[i].succ_count == 0)
638 total = 0;
639 for (arcptr = bb_graph[i].succ; arcptr;
640 arcptr = arcptr->succ_next)
641 total += arcptr->arc_count;
642 bb_graph[i].exec_count = total;
643 bb_graph[i].count_valid = 1;
644 changes = 1;
646 else if (bb_graph[i].pred_count == 0)
648 total = 0;
649 for (arcptr = bb_graph[i].pred; arcptr;
650 arcptr = arcptr->pred_next)
651 total += arcptr->arc_count;
652 bb_graph[i].exec_count = total;
653 bb_graph[i].count_valid = 1;
654 changes = 1;
657 if (bb_graph[i].count_valid)
659 if (bb_graph[i].succ_count == 1)
661 total = 0;
662 /* One of the counts will be invalid, but it is zero,
663 so adding it in also doesn't hurt. */
664 for (arcptr = bb_graph[i].succ; arcptr;
665 arcptr = arcptr->succ_next)
666 total += arcptr->arc_count;
667 /* Calculate count for remaining arc by conservation. */
668 total = bb_graph[i].exec_count - total;
669 /* Search for the invalid arc, and set its count. */
670 for (arcptr = bb_graph[i].succ; arcptr;
671 arcptr = arcptr->succ_next)
672 if (! arcptr->count_valid)
673 break;
674 if (! arcptr)
675 abort ();
676 arcptr->count_valid = 1;
677 arcptr->arc_count = total;
678 bb_graph[i].succ_count--;
680 bb_graph[arcptr->target].pred_count--;
681 changes = 1;
683 if (bb_graph[i].pred_count == 1)
685 total = 0;
686 /* One of the counts will be invalid, but it is zero,
687 so adding it in also doesn't hurt. */
688 for (arcptr = bb_graph[i].pred; arcptr;
689 arcptr = arcptr->pred_next)
690 total += arcptr->arc_count;
691 /* Calculate count for remaining arc by conservation. */
692 total = bb_graph[i].exec_count - total;
693 /* Search for the invalid arc, and set its count. */
694 for (arcptr = bb_graph[i].pred; arcptr;
695 arcptr = arcptr->pred_next)
696 if (! arcptr->count_valid)
697 break;
698 if (! arcptr)
699 abort ();
700 arcptr->count_valid = 1;
701 arcptr->arc_count = total;
702 bb_graph[i].pred_count--;
704 bb_graph[arcptr->source].succ_count--;
705 changes = 1;
711 /* If the graph has been correctly solved, every block will have a
712 succ and pred count of zero. */
713 for (i = 0; i < num_blocks; i++)
714 if (bb_graph[i].succ_count || bb_graph[i].pred_count)
715 abort ();
719 static void
720 read_files ()
722 struct stat buf;
723 struct bb_info_list *list_end = 0;
724 struct bb_info_list *b_ptr;
725 long total;
727 /* Read and ignore the first word of the .da file, which is the count of
728 how many numbers follow. */
729 if (da_file && __read_long (&total, da_file, 8))
730 abort();
732 while (! feof (bbg_file))
734 b_ptr = (struct bb_info_list *) xmalloc (sizeof (struct bb_info_list));
736 b_ptr->next = 0;
737 if (list_end)
738 list_end->next = b_ptr;
739 else
740 bb_graph_list = b_ptr;
741 list_end = b_ptr;
743 /* Read in the data in the .bbg file and reconstruct the program flow
744 graph for one function. */
745 create_program_flow_graph (b_ptr);
747 /* Set the EOF condition if at the end of file. */
748 ungetc (getc (bbg_file), bbg_file);
751 /* Check to make sure the .da file data is valid. */
753 if (da_file)
755 if (feof (da_file))
756 fnotice (stderr, ".da file contents exhausted too early\n");
757 /* Should be at end of file now. */
758 if (__read_long (&total, da_file, 8) == 0)
759 fnotice (stderr, ".da file contents not exhausted\n");
762 /* Calculate all of the basic block execution counts and branch
763 taken probabilities. */
765 for (b_ptr = bb_graph_list; b_ptr; b_ptr = b_ptr->next)
766 solve_program_flow_graph (b_ptr);
768 /* Read in all of the data from the .bb file. This info will be accessed
769 sequentially twice. */
770 stat (bb_file_name, &buf);
771 bb_data_size = buf.st_size / 4;
773 bb_data = (char *) xmalloc ((unsigned) buf.st_size);
774 fread (bb_data, sizeof (char), buf.st_size, bb_file);
776 fclose (bb_file);
777 if (da_file)
778 fclose (da_file);
779 fclose (bbg_file);
783 /* Scan the data in the .bb file to find all source files referenced,
784 and the largest line number mentioned in each one. */
786 static void
787 scan_for_source_files ()
789 struct sourcefile *s_ptr = NULL;
790 char *ptr;
791 long count;
792 long line_num;
794 /* Search the bb_data to find:
795 1) The number of sources files contained herein, and
796 2) The largest line number for each source file. */
798 ptr = bb_data;
799 sources = 0;
800 for (count = 0; count < bb_data_size; count++)
802 __fetch_long (&line_num, ptr, 4);
803 ptr += 4;
804 if (line_num == -1)
806 /* A source file name follows. Check to see if we already have
807 a sourcefile structure for this file. */
808 s_ptr = sources;
809 while (s_ptr && strcmp (s_ptr->name, ptr))
810 s_ptr = s_ptr->next;
812 if (s_ptr == 0)
814 /* No sourcefile structure for this file name exists, create
815 a new one, and append it to the front of the sources list. */
816 s_ptr = (struct sourcefile *) xmalloc (sizeof(struct sourcefile));
817 s_ptr->name = xstrdup (ptr);
818 s_ptr->maxlineno = 0;
819 s_ptr->next = sources;
820 sources = s_ptr;
823 /* Scan past the file name. */
825 long delim;
826 do {
827 count++;
828 __fetch_long (&delim, ptr, 4);
829 ptr += 4;
830 } while (delim != line_num);
833 else if (line_num == -2)
835 long delim;
837 /* A function name follows. Ignore it. */
838 do {
839 count++;
840 __fetch_long (&delim, ptr, 4);
841 ptr += 4;
842 } while (delim != line_num);
844 /* There will be a zero before the first file name, in which case s_ptr
845 will still be uninitialized. So, only try to set the maxlineno
846 field if line_num is non-zero. */
847 else if (line_num > 0)
849 if (s_ptr->maxlineno <= line_num)
850 s_ptr->maxlineno = line_num + 1;
852 else if (line_num < 0)
854 /* Don't know what this is, but it's garbage. */
855 abort();
860 /* For calculating coverage at the function level. */
862 static int function_source_lines;
863 static int function_source_lines_executed;
864 static int function_branches;
865 static int function_branches_executed;
866 static int function_branches_taken;
867 static int function_calls;
868 static int function_calls_executed;
869 static char *function_name;
871 /* Calculate the branch taken probabilities for all arcs branches at the
872 end of this block. */
874 static void
875 calculate_branch_probs (current_graph, block_num, branch_probs, last_line_num)
876 struct bb_info_list *current_graph;
877 int block_num;
878 struct arcdata **branch_probs;
879 int last_line_num;
881 gcov_type total;
882 struct adj_list *arcptr;
883 struct arcdata *end_ptr, *a_ptr;
885 total = current_graph->bb_graph[block_num].exec_count;
886 for (arcptr = current_graph->bb_graph[block_num].succ; arcptr;
887 arcptr = arcptr->succ_next)
889 /* Ignore fall through arcs as they aren't really branches. */
891 if (arcptr->fall_through)
892 continue;
894 a_ptr = (struct arcdata *) xmalloc (sizeof (struct arcdata));
895 a_ptr->total = total;
896 if (total == 0)
897 a_ptr->hits = 0;
898 else
899 a_ptr->hits = arcptr->arc_count;
900 a_ptr->call_insn = arcptr->fake;
902 if (output_function_summary)
904 if (a_ptr->call_insn)
906 function_calls++;
907 if (a_ptr->total != 0)
908 function_calls_executed++;
910 else
912 function_branches++;
913 if (a_ptr->total != 0)
914 function_branches_executed++;
915 if (a_ptr->hits > 0)
916 function_branches_taken++;
920 /* Append the new branch to the end of the list. */
921 a_ptr->next = 0;
922 if (! branch_probs[last_line_num])
923 branch_probs[last_line_num] = a_ptr;
924 else
926 end_ptr = branch_probs[last_line_num];
927 while (end_ptr->next != 0)
928 end_ptr = end_ptr->next;
929 end_ptr->next = a_ptr;
934 /* Output summary info for a function. */
936 static void
937 function_summary ()
939 if (function_source_lines)
940 fnotice (stdout, "%6.2f%% of %d source lines executed in function %s\n",
941 (((double) function_source_lines_executed / function_source_lines)
942 * 100), function_source_lines, function_name);
943 else
944 fnotice (stdout, "No executable source lines in function %s\n",
945 function_name);
947 if (output_branch_probs)
949 if (function_branches)
951 fnotice (stdout, "%6.2f%% of %d branches executed in function %s\n",
952 (((double) function_branches_executed / function_branches)
953 * 100), function_branches, function_name);
954 fnotice (stdout,
955 "%6.2f%% of %d branches taken at least once in function %s\n",
956 (((double) function_branches_taken / function_branches)
957 * 100), function_branches, function_name);
959 else
960 fnotice (stdout, "No branches in function %s\n", function_name);
961 if (function_calls)
962 fnotice (stdout, "%6.2f%% of %d calls executed in function %s\n",
963 (((double) function_calls_executed / function_calls)
964 * 100), function_calls, function_name);
965 else
966 fnotice (stdout, "No calls in function %s\n", function_name);
970 /* Calculate line execution counts, and output the data to a .tcov file. */
972 static void
973 output_data ()
975 /* When scanning data, this is true only if the data applies to the
976 current source file. */
977 int this_file;
978 /* An array indexed by line number which indicates how many times that line
979 was executed. */
980 gcov_type *line_counts;
981 /* An array indexed by line number which indicates whether the line was
982 present in the bb file (i.e. whether it had code associate with it).
983 Lines never executed are those which both exist, and have zero execution
984 counts. */
985 char *line_exists;
986 /* An array indexed by line number, which contains a list of branch
987 probabilities, one for each branch on that line. */
988 struct arcdata **branch_probs = NULL;
989 struct sourcefile *s_ptr;
990 char *source_file_name;
991 FILE *source_file;
992 struct bb_info_list *current_graph;
993 long count;
994 char *cptr;
995 long block_num;
996 long line_num;
997 long last_line_num = 0;
998 int i;
999 struct arcdata *a_ptr;
1000 /* Buffer used for reading in lines from the source file. */
1001 char string[STRING_SIZE];
1002 /* For calculating coverage at the file level. */
1003 int total_source_lines;
1004 int total_source_lines_executed;
1005 int total_branches;
1006 int total_branches_executed;
1007 int total_branches_taken;
1008 int total_calls;
1009 int total_calls_executed;
1011 /* Now, for each source file, allocate an array big enough to hold a count
1012 for each line. Scan through the bb_data, and when the file name matches
1013 the current file name, then for each following line number, increment
1014 the line number execution count indicated by the execution count of
1015 the appropriate basic block. */
1017 for (s_ptr = sources; s_ptr; s_ptr = s_ptr->next)
1019 /* If this is a relative file name, and an object directory has been
1020 specified, then make it relative to the object directory name. */
1021 if (! (*s_ptr->name == '/' || *s_ptr->name == DIR_SEPARATOR
1022 /* Check for disk name on MS-DOS-based systems. */
1023 || (DIR_SEPARATOR == '\\'
1024 && s_ptr->name[1] == ':'
1025 && (s_ptr->name[2] == DIR_SEPARATOR
1026 || s_ptr->name[2] == '/')))
1027 && object_directory != 0
1028 && *object_directory != '\0')
1030 int objdir_count = strlen (object_directory);
1031 source_file_name = xmalloc (objdir_count + strlen (s_ptr->name) + 2);
1032 strcpy (source_file_name, object_directory);
1033 if (object_directory[objdir_count - 1] != '/')
1034 source_file_name[objdir_count++] = '/';
1035 strcpy (source_file_name + objdir_count, s_ptr->name);
1037 else
1038 source_file_name = s_ptr->name;
1040 line_counts = (gcov_type *) xcalloc (sizeof (gcov_type), s_ptr->maxlineno);
1041 line_exists = xcalloc (1, s_ptr->maxlineno);
1042 if (output_branch_probs)
1043 branch_probs = (struct arcdata **)
1044 xcalloc (sizeof (struct arcdata *), s_ptr->maxlineno);
1046 /* There will be a zero at the beginning of the bb info, before the
1047 first list of line numbers, so must initialize block_num to 0. */
1048 block_num = 0;
1049 this_file = 0;
1050 current_graph = 0;
1052 /* Pointer into the bb_data, incremented while scanning the data. */
1053 char *ptr = bb_data;
1054 for (count = 0; count < bb_data_size; count++)
1056 long delim;
1058 __fetch_long (&line_num, ptr, 4);
1059 ptr += 4;
1060 if (line_num == -1)
1062 /* Marks the beginning of a file name. Check to see whether
1063 this is the filename we are currently collecting data for. */
1065 if (strcmp (s_ptr->name, ptr))
1066 this_file = 0;
1067 else
1068 this_file = 1;
1070 /* Scan past the file name. */
1071 do {
1072 count++;
1073 __fetch_long (&delim, ptr, 4);
1074 ptr += 4;
1075 } while (delim != line_num);
1077 else if (line_num == -2)
1079 /* Marks the start of a new function. Advance to the next
1080 program flow graph. */
1082 if (! current_graph)
1083 current_graph = bb_graph_list;
1084 else
1086 if (block_num == current_graph->num_blocks - 1)
1087 /* Last block falls through to exit. */
1089 else if (block_num == current_graph->num_blocks - 2)
1091 if (output_branch_probs && this_file)
1092 calculate_branch_probs (current_graph, block_num,
1093 branch_probs, last_line_num);
1095 else
1097 fnotice (stderr,
1098 "didn't use all bb entries of graph, function %s\n",
1099 function_name);
1100 fnotice (stderr, "block_num = %ld, num_blocks = %d\n",
1101 block_num, current_graph->num_blocks);
1104 current_graph = current_graph->next;
1105 block_num = 0;
1107 if (output_function_summary && this_file)
1108 function_summary ();
1111 if (output_function_summary)
1113 function_source_lines = 0;
1114 function_source_lines_executed = 0;
1115 function_branches = 0;
1116 function_branches_executed = 0;
1117 function_branches_taken = 0;
1118 function_calls = 0;
1119 function_calls_executed = 0;
1122 /* Save the function name for later use. */
1123 function_name = ptr;
1125 /* Scan past the file name. */
1126 do {
1127 count++;
1128 __fetch_long (&delim, ptr, 4);
1129 ptr += 4;
1130 } while (delim != line_num);
1132 else if (line_num == 0)
1134 /* Marks the end of a block. */
1136 if (block_num >= current_graph->num_blocks)
1138 fnotice (stderr, "ERROR: too many basic blocks in .bb file %s\n",
1139 function_name);
1140 abort ();
1143 if (output_branch_probs && this_file)
1144 calculate_branch_probs (current_graph, block_num,
1145 branch_probs, last_line_num);
1147 block_num++;
1149 else if (this_file)
1151 if (output_function_summary)
1153 if (line_exists[line_num] == 0)
1154 function_source_lines++;
1155 if (line_counts[line_num] == 0
1156 && current_graph->bb_graph[block_num].exec_count != 0)
1157 function_source_lines_executed++;
1160 /* Accumulate execution data for this line number. */
1162 line_counts[line_num]
1163 += current_graph->bb_graph[block_num].exec_count;
1164 line_exists[line_num] = 1;
1165 last_line_num = line_num;
1170 if (output_function_summary && this_file)
1171 function_summary ();
1173 /* Calculate summary test coverage statistics. */
1175 total_source_lines = 0;
1176 total_source_lines_executed = 0;
1177 total_branches = 0;
1178 total_branches_executed = 0;
1179 total_branches_taken = 0;
1180 total_calls = 0;
1181 total_calls_executed = 0;
1183 for (count = 1; count < s_ptr->maxlineno; count++)
1185 if (line_exists[count])
1187 total_source_lines++;
1188 if (line_counts[count])
1189 total_source_lines_executed++;
1191 if (output_branch_probs)
1193 for (a_ptr = branch_probs[count]; a_ptr; a_ptr = a_ptr->next)
1195 if (a_ptr->call_insn)
1197 total_calls++;
1198 if (a_ptr->total != 0)
1199 total_calls_executed++;
1201 else
1203 total_branches++;
1204 if (a_ptr->total != 0)
1205 total_branches_executed++;
1206 if (a_ptr->hits > 0)
1207 total_branches_taken++;
1213 if (total_source_lines)
1214 fnotice (stdout,
1215 "%6.2f%% of %d source lines executed in file %s\n",
1216 (((double) total_source_lines_executed / total_source_lines)
1217 * 100), total_source_lines, source_file_name);
1218 else
1219 fnotice (stdout, "No executable source lines in file %s\n",
1220 source_file_name);
1222 if (output_branch_probs)
1224 if (total_branches)
1226 fnotice (stdout, "%6.2f%% of %d branches executed in file %s\n",
1227 (((double) total_branches_executed / total_branches)
1228 * 100), total_branches, source_file_name);
1229 fnotice (stdout,
1230 "%6.2f%% of %d branches taken at least once in file %s\n",
1231 (((double) total_branches_taken / total_branches)
1232 * 100), total_branches, source_file_name);
1234 else
1235 fnotice (stdout, "No branches in file %s\n", source_file_name);
1236 if (total_calls)
1237 fnotice (stdout, "%6.2f%% of %d calls executed in file %s\n",
1238 (((double) total_calls_executed / total_calls)
1239 * 100), total_calls, source_file_name);
1240 else
1241 fnotice (stdout, "No calls in file %s\n", source_file_name);
1244 if (output_gcov_file)
1246 /* Now the statistics are ready. Read in the source file one line
1247 at a time, and output that line to the gcov file preceded by
1248 its execution count if non zero. */
1250 source_file = fopen (source_file_name, "r");
1251 if (source_file == NULL)
1253 fnotice (stderr, "Could not open source file %s.\n",
1254 source_file_name);
1255 free (line_counts);
1256 free (line_exists);
1257 continue;
1260 count = strlen (source_file_name);
1261 cptr = strrchr (s_ptr->name, '/');
1262 if (cptr)
1263 cptr = cptr + 1;
1264 else
1265 cptr = s_ptr->name;
1266 if (output_long_names && strcmp (cptr, input_file_name))
1268 gcov_file_name = xmalloc (count + 7 + strlen (input_file_name));
1270 cptr = strrchr (input_file_name, '/');
1271 if (cptr)
1272 strcpy (gcov_file_name, cptr + 1);
1273 else
1274 strcpy (gcov_file_name, input_file_name);
1276 strcat (gcov_file_name, ".");
1278 cptr = strrchr (source_file_name, '/');
1279 if (cptr)
1280 strcat (gcov_file_name, cptr + 1);
1281 else
1282 strcat (gcov_file_name, source_file_name);
1284 else
1286 gcov_file_name = xmalloc (count + 6);
1287 cptr = strrchr (source_file_name, '/');
1288 if (cptr)
1289 strcpy (gcov_file_name, cptr + 1);
1290 else
1291 strcpy (gcov_file_name, source_file_name);
1294 /* Don't strip off the ending for compatibility with tcov, since
1295 this results in confusion if there is more than one file with
1296 the same basename, e.g. tmp.c and tmp.h. */
1297 strcat (gcov_file_name, ".gcov");
1299 gcov_file = fopen (gcov_file_name, "w");
1301 if (gcov_file == NULL)
1303 fnotice (stderr, "Could not open output file %s.\n",
1304 gcov_file_name);
1305 fclose (source_file);
1306 free (line_counts);
1307 free (line_exists);
1308 continue;
1311 fnotice (stdout, "Creating %s.\n", gcov_file_name);
1313 for (count = 1; count < s_ptr->maxlineno; count++)
1315 char *retval;
1316 int len;
1318 retval = fgets (string, STRING_SIZE, source_file);
1320 /* For lines which don't exist in the .bb file, print nothing
1321 before the source line. For lines which exist but were never
1322 executed, print ###### before the source line. Otherwise,
1323 print the execution count before the source line. */
1324 /* There are 16 spaces of indentation added before the source
1325 line so that tabs won't be messed up. */
1326 if (line_exists[count])
1328 if (line_counts[count])
1330 char c[20];
1331 sprintf (c, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)line_counts[count]);
1332 fprintf (gcov_file, "%12s %s", c,
1333 string);
1335 else
1336 fprintf (gcov_file, " ###### %s", string);
1338 else
1339 fprintf (gcov_file, "\t\t%s", string);
1341 /* In case the source file line is larger than our buffer, keep
1342 reading and outputting lines until we get a newline. */
1343 len = strlen (string);
1344 while ((len == 0 || string[strlen (string) - 1] != '\n')
1345 && retval != NULL)
1347 retval = fgets (string, STRING_SIZE, source_file);
1348 fputs (string, gcov_file);
1351 if (output_branch_probs)
1353 for (i = 0, a_ptr = branch_probs[count]; a_ptr;
1354 a_ptr = a_ptr->next, i++)
1356 if (a_ptr->call_insn)
1358 if (a_ptr->total == 0)
1359 fnotice (gcov_file, "call %d never executed\n", i);
1360 else
1362 if (output_branch_counts)
1364 char c[20];
1365 sprintf (c, HOST_WIDEST_INT_PRINT_DEC,
1366 a_ptr->total - a_ptr->hits);
1367 fnotice (gcov_file,
1368 "call %d returns = %s\n", i, c);
1370 else
1372 char c[20];
1373 sprintf (c, HOST_WIDEST_INT_PRINT_DEC,
1374 100 - ((a_ptr->hits * 100)
1375 + (a_ptr->total >> 1))
1376 / a_ptr->total);
1377 fnotice (gcov_file,
1378 "call %d returns = %s%%\n", i, c);
1382 else
1384 if (a_ptr->total == 0)
1385 fnotice (gcov_file, "branch %d never executed\n",
1387 else
1389 if (output_branch_counts)
1391 char c[20];
1392 sprintf (c, HOST_WIDEST_INT_PRINT_DEC,
1393 a_ptr->hits);
1394 fnotice (gcov_file,
1395 "branch %d taken = %s\n", i, c);
1397 else
1399 char c[20];
1400 sprintf (c, HOST_WIDEST_INT_PRINT_DEC,
1401 ((a_ptr->hits * 100)
1402 + (a_ptr->total >> 1))
1403 / a_ptr->total);
1404 fnotice (gcov_file,
1405 "branch %d taken = %s%%\n", i, c);
1412 /* Gracefully handle errors while reading the source file. */
1413 if (retval == NULL)
1415 fnotice (stderr,
1416 "Unexpected EOF while reading source file %s.\n",
1417 source_file_name);
1418 break;
1422 /* Handle all remaining source lines. There may be lines
1423 after the last line of code. */
1426 char *retval = fgets (string, STRING_SIZE, source_file);
1427 while (retval != NULL)
1429 int len;
1431 fprintf (gcov_file, "\t\t%s", string);
1433 /* In case the source file line is larger than our buffer, keep
1434 reading and outputting lines until we get a newline. */
1435 len = strlen (string);
1436 while ((len == 0 || string[strlen (string) - 1] != '\n')
1437 && retval != NULL)
1439 retval = fgets (string, STRING_SIZE, source_file);
1440 fputs (string, gcov_file);
1443 retval = fgets (string, STRING_SIZE, source_file);
1447 fclose (source_file);
1448 fclose (gcov_file);
1451 free (line_counts);
1452 free (line_exists);