* cp-tree.h (DECL_LOCAL_FUCNTION_P): New macro.
[official-gcc.git] / gcc / gcov.c
blob46e0c435c33bb9111aadb60ae53003642856d12e
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"
48 #undef abort
50 #include "gcov-io.h"
52 /* The .bb file format consists of several lists of 4-byte integers
53 which are the line numbers of each basic block in the file. Each
54 list is terminated by a zero. These lists correspond to the basic
55 blocks in the reconstructed program flow graph.
57 A line number of -1 indicates that a source file name (padded to a
58 long boundary) follows. The padded file name is followed by
59 another -1 to make it easy to scan past file names. A -2 indicates
60 that a function name (padded to a long boundary) follows; the name
61 is followed by another -2 to make it easy to scan past the function
62 name.
64 The .bbg file contains enough info to enable gcov to reconstruct the
65 program flow graph. The first word is the number of basic blocks,
66 the second word is the number of arcs, followed by the list of arcs
67 (source bb, dest bb pairs), then a -1, then the number of instrumented
68 arcs followed by the instrumented arcs, followed by another -1. This
69 is repeated for each function.
71 The .da file contains the execution count for each instrumented branch.
73 The .bb and .bbg files are created by giving GCC the -ftest-coverage option,
74 and the .da files are created when an executable compiled with
75 -fprofile-arcs is run. */
77 /* The functions in this file for creating and solution program flow graphs
78 are very similar to functions in the gcc source file profile.c. */
80 char gcov_version_string[] = "GNU gcov version 1.5\n";
82 /* This is the size of the buffer used to read in source file lines. */
84 #define STRING_SIZE 200
86 /* One copy of this structure is created for each source file mentioned in the
87 .bb file. */
89 struct sourcefile
91 char *name;
92 int maxlineno;
93 struct sourcefile *next;
96 /* This points to the head of the sourcefile structure list. */
98 struct sourcefile *sources;
100 /* One of these is dynamically created whenever we identify an arc in the
101 function. */
103 struct adj_list {
104 int source;
105 int target;
106 int arc_count;
107 unsigned int count_valid : 1;
108 unsigned int on_tree : 1;
109 unsigned int fake : 1;
110 unsigned int fall_through : 1;
111 #if 0
112 /* Not needed for gcov, but defined in profile.c. */
113 rtx branch_insn;
114 #endif
115 struct adj_list *pred_next;
116 struct adj_list *succ_next;
119 /* Count the number of basic blocks, and create an array of these structures,
120 one for each bb in the function. */
122 struct bb_info {
123 struct adj_list *succ;
124 struct adj_list *pred;
125 int succ_count;
126 int pred_count;
127 int exec_count;
128 unsigned int count_valid : 1;
129 unsigned int on_tree : 1;
130 #if 0
131 /* Not needed for gcov, but defined in profile.c. */
132 rtx first_insn;
133 #endif
136 /* When outputting branch probabilities, one of these structures is created
137 for each branch/call. */
139 struct arcdata
141 int hits;
142 int total;
143 int call_insn;
144 struct arcdata *next;
147 /* Used to save the list of bb_graphs, one per function. */
149 struct bb_info_list {
150 /* Indexed by block number, holds the basic block graph for one function. */
151 struct bb_info *bb_graph;
152 int num_blocks;
153 struct bb_info_list *next;
156 /* Holds a list of function basic block graphs. */
158 static struct bb_info_list *bb_graph_list = 0;
160 /* Name and file pointer of the input file for the basic block graph. */
162 static char *bbg_file_name;
163 static FILE *bbg_file;
165 /* Name and file pointer of the input file for the arc count data. */
167 static char *da_file_name;
168 static FILE *da_file;
170 /* Name and file pointer of the input file for the basic block line counts. */
172 static char *bb_file_name;
173 static FILE *bb_file;
175 /* Holds the entire contents of the bb_file read into memory. */
177 static char *bb_data;
179 /* Size of bb_data array in longs. */
181 static long bb_data_size;
183 /* Name and file pointer of the output file. */
185 static char *gcov_file_name;
186 static FILE *gcov_file;
188 /* Name of the file mentioned on the command line. */
190 static char *input_file_name = 0;
192 /* Output branch probabilities if true. */
194 static int output_branch_probs = 0;
196 /* Output a gcov file if this is true. This is on by default, and can
197 be turned off by the -n option. */
199 static int output_gcov_file = 1;
201 /* For included files, make the gcov output file name include the name of
202 the input source file. For example, if x.h is included in a.c, then the
203 output file name is a.c.x.h.gcov instead of x.h.gcov. This works only
204 when a single source file is specified. */
206 static int output_long_names = 0;
208 /* Output summary info for each function. */
210 static int output_function_summary = 0;
212 /* Object directory file prefix. This is the directory where .bb and .bbg
213 files are looked for, if non-zero. */
215 static char *object_directory = 0;
217 /* Output the number of times a branch was taken as opposed to the percentage
218 of times it was taken. Turned on by the -c option */
220 static int output_branch_counts = 0;
222 /* Forward declarations. */
223 static void process_args PROTO ((int, char **));
224 static void open_files PROTO ((void));
225 static void read_files PROTO ((void));
226 static void scan_for_source_files PROTO ((void));
227 static void output_data PROTO ((void));
228 static void print_usage PROTO ((void)) ATTRIBUTE_NORETURN;
229 static void init_arc PROTO ((struct adj_list *, int, int, struct bb_info *));
230 static struct adj_list *reverse_arcs PROTO ((struct adj_list *));
231 static void create_program_flow_graph PROTO ((struct bb_info_list *));
232 static void solve_program_flow_graph PROTO ((struct bb_info_list *));
233 static void calculate_branch_probs PROTO ((struct bb_info_list *, int,
234 struct arcdata **, int));
235 static void function_summary PROTO ((void));
237 extern int main PROTO ((int, char **));
240 main (argc, argv)
241 int argc;
242 char **argv;
244 #ifdef HAVE_LC_MESSAGES
245 setlocale (LC_MESSAGES, "");
246 #endif
247 (void) bindtextdomain (PACKAGE, localedir);
248 (void) textdomain (PACKAGE);
250 process_args (argc, argv);
252 open_files ();
254 read_files ();
256 scan_for_source_files ();
258 output_data ();
260 return 0;
263 static void fnotice PVPROTO ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2;
264 static void
265 fnotice VPROTO ((FILE *file, const char *msgid, ...))
267 #ifndef ANSI_PROTOTYPES
268 FILE *file;
269 const char *msgid;
270 #endif
271 va_list ap;
273 VA_START (ap, msgid);
275 #ifndef ANSI_PROTOTYPES
276 file = va_arg (ap, FILE *);
277 msgid = va_arg (ap, const char *);
278 #endif
280 vfprintf (file, _(msgid), ap);
281 va_end (ap);
284 #ifndef DIR_SEPARATOR
285 #define DIR_SEPARATOR '/'
286 #endif
288 /* More 'friendly' abort that prints the line and file.
289 config.h can #define abort fancy_abort if you like that sort of thing. */
290 extern void fancy_abort PROTO ((void)) ATTRIBUTE_NORETURN;
292 void
293 fancy_abort ()
295 fnotice (stderr, "Internal gcov abort.\n");
296 exit (FATAL_EXIT_CODE);
299 /* Print a usage message and exit. */
301 static void
302 print_usage ()
304 fnotice (stderr, "gcov [-b] [-v] [-n] [-l] [-f] [-o OBJDIR] file\n");
305 exit (FATAL_EXIT_CODE);
308 /* Parse the command line. */
310 static void
311 process_args (argc, argv)
312 int argc;
313 char **argv;
315 int i;
317 for (i = 1; i < argc; i++)
319 if (argv[i][0] == '-')
321 if (argv[i][1] == 'b')
322 output_branch_probs = 1;
323 else if (argv[i][1] == 'c')
324 output_branch_counts = 1;
325 else if (argv[i][1] == 'v')
326 fputs (gcov_version_string, stderr);
327 else if (argv[i][1] == 'n')
328 output_gcov_file = 0;
329 else if (argv[i][1] == 'l')
330 output_long_names = 1;
331 else if (argv[i][1] == 'f')
332 output_function_summary = 1;
333 else if (argv[i][1] == 'o' && argv[i][2] == '\0')
334 object_directory = argv[++i];
335 else
336 print_usage ();
338 else if (! input_file_name)
339 input_file_name = argv[i];
340 else
341 print_usage ();
344 if (! input_file_name)
345 print_usage ();
349 /* Find and open the .bb, .da, and .bbg files. */
351 static void
352 open_files ()
354 int count, objdir_count;
355 char *cptr;
357 /* Determine the names of the .bb, .bbg, and .da files. Strip off the
358 extension, if any, and append the new extensions. */
359 count = strlen (input_file_name);
360 if (object_directory)
361 objdir_count = strlen (object_directory);
362 else
363 objdir_count = 0;
365 da_file_name = xmalloc (count + objdir_count + 4);
366 bb_file_name = xmalloc (count + objdir_count + 4);
367 bbg_file_name = xmalloc (count + objdir_count + 5);
369 if (object_directory)
371 strcpy (da_file_name, object_directory);
372 strcpy (bb_file_name, object_directory);
373 strcpy (bbg_file_name, object_directory);
375 if (object_directory[objdir_count - 1] != '/')
377 strcat (da_file_name, "/");
378 strcat (bb_file_name, "/");
379 strcat (bbg_file_name, "/");
382 cptr = rindex (input_file_name, '/');
383 if (cptr)
385 strcat (da_file_name, cptr + 1);
386 strcat (bb_file_name, cptr + 1);
387 strcat (bbg_file_name, cptr + 1);
389 else
391 strcat (da_file_name, input_file_name);
392 strcat (bb_file_name, input_file_name);
393 strcat (bbg_file_name, input_file_name);
396 else
398 strcpy (da_file_name, input_file_name);
399 strcpy (bb_file_name, input_file_name);
400 strcpy (bbg_file_name, input_file_name);
403 cptr = rindex (bb_file_name, '.');
404 if (cptr)
405 strcpy (cptr, ".bb");
406 else
407 strcat (bb_file_name, ".bb");
409 cptr = rindex (da_file_name, '.');
410 if (cptr)
411 strcpy (cptr, ".da");
412 else
413 strcat (da_file_name, ".da");
415 cptr = rindex (bbg_file_name, '.');
416 if (cptr)
417 strcpy (cptr, ".bbg");
418 else
419 strcat (bbg_file_name, ".bbg");
421 bb_file = fopen (bb_file_name, "rb");
422 if (bb_file == NULL)
424 fnotice (stderr, "Could not open basic block file %s.\n", bb_file_name);
425 exit (FATAL_EXIT_CODE);
428 /* If none of the functions in the file were executed, then there won't
429 be a .da file. Just assume that all counts are zero in this case. */
430 da_file = fopen (da_file_name, "rb");
431 if (da_file == NULL)
433 fnotice (stderr, "Could not open data file %s.\n", da_file_name);
434 fnotice (stderr, "Assuming that all execution counts are zero.\n");
437 bbg_file = fopen (bbg_file_name, "rb");
438 if (bbg_file == NULL)
440 fnotice (stderr, "Could not open program flow graph file %s.\n",
441 bbg_file_name);
442 exit (FATAL_EXIT_CODE);
445 /* Check for empty .bbg file. This indicates that there is no executable
446 code in this source file. */
447 /* Set the EOF condition if at the end of file. */
448 ungetc (getc (bbg_file), bbg_file);
449 if (feof (bbg_file))
451 fnotice (stderr, "No executable code associated with file %s.\n",
452 input_file_name);
453 exit (FATAL_EXIT_CODE);
457 /* Initialize a new arc. */
459 static void
460 init_arc (arcptr, source, target, bb_graph)
461 struct adj_list *arcptr;
462 int source, target;
463 struct bb_info *bb_graph;
465 arcptr->target = target;
466 arcptr->source = source;
468 arcptr->arc_count = 0;
469 arcptr->count_valid = 0;
470 arcptr->on_tree = 0;
471 arcptr->fake = 0;
472 arcptr->fall_through = 0;
474 arcptr->succ_next = bb_graph[source].succ;
475 bb_graph[source].succ = arcptr;
476 bb_graph[source].succ_count++;
478 arcptr->pred_next = bb_graph[target].pred;
479 bb_graph[target].pred = arcptr;
480 bb_graph[target].pred_count++;
484 /* Reverse the arcs on a arc list. */
486 static struct adj_list *
487 reverse_arcs (arcptr)
488 struct adj_list *arcptr;
490 struct adj_list *prev = 0;
491 struct adj_list *next;
493 for ( ; arcptr; arcptr = next)
495 next = arcptr->succ_next;
496 arcptr->succ_next = prev;
497 prev = arcptr;
500 return prev;
504 /* Construct the program flow graph from the .bbg file, and read in the data
505 in the .da file. */
507 static void
508 create_program_flow_graph (bptr)
509 struct bb_info_list *bptr;
511 long num_blocks, number_arcs, src, dest, flag_bits, num_arcs_per_block;
512 int i;
513 struct adj_list *arcptr;
514 struct bb_info *bb_graph;
516 /* Read the number of blocks. */
517 __read_long (&num_blocks, bbg_file, 4);
519 /* Create an array of size bb number of bb_info structs. */
520 bb_graph = (struct bb_info *) xcalloc (num_blocks, sizeof (struct bb_info));
522 bptr->bb_graph = bb_graph;
523 bptr->num_blocks = num_blocks;
525 /* Read and create each arc from the .bbg file. */
526 __read_long (&number_arcs, bbg_file, 4);
527 for (i = 0; i < num_blocks; i++)
529 int j;
531 __read_long (&num_arcs_per_block, bbg_file, 4);
532 for (j = 0; j < num_arcs_per_block; j++)
534 if (number_arcs-- < 0)
535 abort ();
537 src = i;
538 __read_long (&dest, bbg_file, 4);
540 arcptr = (struct adj_list *) xmalloc (sizeof (struct adj_list));
541 init_arc (arcptr, src, dest, bb_graph);
543 __read_long (&flag_bits, bbg_file, 4);
544 arcptr->on_tree = flag_bits & 0x1;
545 arcptr->fake = !! (flag_bits & 0x2);
546 arcptr->fall_through = !! (flag_bits & 0x4);
550 if (number_arcs)
551 abort ();
553 /* Read and ignore the -1 separating the arc list from the arc list of the
554 next function. */
555 __read_long (&src, bbg_file, 4);
556 if (src != -1)
557 abort ();
559 /* Must reverse the order of all succ arcs, to ensure that they match
560 the order of the data in the .da file. */
562 for (i = 0; i < num_blocks; i++)
563 if (bb_graph[i].succ)
564 bb_graph[i].succ = reverse_arcs (bb_graph[i].succ);
566 /* For each arc not on the spanning tree, set its execution count from
567 the .da file. */
569 /* The first count in the .da file is the number of times that the function
570 was entered. This is the exec_count for block zero. */
572 /* This duplicates code in branch_prob in profile.c. */
574 for (i = 0; i < num_blocks; i++)
575 for (arcptr = bb_graph[i].succ; arcptr; arcptr = arcptr->succ_next)
576 if (! arcptr->on_tree)
578 long tmp_count = 0;
579 if (da_file && __read_long (&tmp_count, da_file, 8))
580 abort();
582 arcptr->arc_count = tmp_count;
583 arcptr->count_valid = 1;
584 bb_graph[i].succ_count--;
585 bb_graph[arcptr->target].pred_count--;
589 static void
590 solve_program_flow_graph (bptr)
591 struct bb_info_list *bptr;
593 int passes, changes, total;
594 int i;
595 struct adj_list *arcptr;
596 struct bb_info *bb_graph;
597 int num_blocks;
599 num_blocks = bptr->num_blocks;
600 bb_graph = bptr->bb_graph;
602 /* For every block in the file,
603 - if every exit/entrance arc has a known count, then set the block count
604 - if the block count is known, and every exit/entrance arc but one has
605 a known execution count, then set the count of the remaining arc
607 As arc counts are set, decrement the succ/pred count, but don't delete
608 the arc, that way we can easily tell when all arcs are known, or only
609 one arc is unknown. */
611 /* The order that the basic blocks are iterated through is important.
612 Since the code that finds spanning trees starts with block 0, low numbered
613 arcs are put on the spanning tree in preference to high numbered arcs.
614 Hence, most instrumented arcs are at the end. Graph solving works much
615 faster if we propagate numbers from the end to the start.
617 This takes an average of slightly more than 3 passes. */
619 changes = 1;
620 passes = 0;
621 while (changes)
623 passes++;
624 changes = 0;
626 for (i = num_blocks - 1; i >= 0; i--)
628 if (! bb_graph[i].count_valid)
630 if (bb_graph[i].succ_count == 0)
632 total = 0;
633 for (arcptr = bb_graph[i].succ; arcptr;
634 arcptr = arcptr->succ_next)
635 total += arcptr->arc_count;
636 bb_graph[i].exec_count = total;
637 bb_graph[i].count_valid = 1;
638 changes = 1;
640 else if (bb_graph[i].pred_count == 0)
642 total = 0;
643 for (arcptr = bb_graph[i].pred; arcptr;
644 arcptr = arcptr->pred_next)
645 total += arcptr->arc_count;
646 bb_graph[i].exec_count = total;
647 bb_graph[i].count_valid = 1;
648 changes = 1;
651 if (bb_graph[i].count_valid)
653 if (bb_graph[i].succ_count == 1)
655 total = 0;
656 /* One of the counts will be invalid, but it is zero,
657 so adding it in also doesn't hurt. */
658 for (arcptr = bb_graph[i].succ; arcptr;
659 arcptr = arcptr->succ_next)
660 total += arcptr->arc_count;
661 /* Calculate count for remaining arc by conservation. */
662 total = bb_graph[i].exec_count - total;
663 /* Search for the invalid arc, and set its count. */
664 for (arcptr = bb_graph[i].succ; arcptr;
665 arcptr = arcptr->succ_next)
666 if (! arcptr->count_valid)
667 break;
668 if (! arcptr)
669 abort ();
670 arcptr->count_valid = 1;
671 arcptr->arc_count = total;
672 bb_graph[i].succ_count--;
674 bb_graph[arcptr->target].pred_count--;
675 changes = 1;
677 if (bb_graph[i].pred_count == 1)
679 total = 0;
680 /* One of the counts will be invalid, but it is zero,
681 so adding it in also doesn't hurt. */
682 for (arcptr = bb_graph[i].pred; arcptr;
683 arcptr = arcptr->pred_next)
684 total += arcptr->arc_count;
685 /* Calculate count for remaining arc by conservation. */
686 total = bb_graph[i].exec_count - total;
687 /* Search for the invalid arc, and set its count. */
688 for (arcptr = bb_graph[i].pred; arcptr;
689 arcptr = arcptr->pred_next)
690 if (! arcptr->count_valid)
691 break;
692 if (! arcptr)
693 abort ();
694 arcptr->count_valid = 1;
695 arcptr->arc_count = total;
696 bb_graph[i].pred_count--;
698 bb_graph[arcptr->source].succ_count--;
699 changes = 1;
705 /* If the graph has been correctly solved, every block will have a
706 succ and pred count of zero. */
707 for (i = 0; i < num_blocks; i++)
708 if (bb_graph[i].succ_count || bb_graph[i].pred_count)
709 abort ();
713 static void
714 read_files ()
716 struct stat buf;
717 struct bb_info_list *list_end = 0;
718 struct bb_info_list *b_ptr;
719 long total;
721 /* Read and ignore the first word of the .da file, which is the count of
722 how many numbers follow. */
723 if (da_file && __read_long (&total, da_file, 8))
724 abort();
726 while (! feof (bbg_file))
728 b_ptr = (struct bb_info_list *) xmalloc (sizeof (struct bb_info_list));
730 b_ptr->next = 0;
731 if (list_end)
732 list_end->next = b_ptr;
733 else
734 bb_graph_list = b_ptr;
735 list_end = b_ptr;
737 /* Read in the data in the .bbg file and reconstruct the program flow
738 graph for one function. */
739 create_program_flow_graph (b_ptr);
741 /* Set the EOF condition if at the end of file. */
742 ungetc (getc (bbg_file), bbg_file);
745 /* Check to make sure the .da file data is valid. */
747 if (da_file)
749 if (feof (da_file))
750 fnotice (stderr, ".da file contents exhausted too early\n");
751 /* Should be at end of file now. */
752 if (__read_long (&total, da_file, 8) == 0)
753 fnotice (stderr, ".da file contents not exhausted\n");
756 /* Calculate all of the basic block execution counts and branch
757 taken probabilities. */
759 for (b_ptr = bb_graph_list; b_ptr; b_ptr = b_ptr->next)
760 solve_program_flow_graph (b_ptr);
762 /* Read in all of the data from the .bb file. This info will be accessed
763 sequentially twice. */
764 stat (bb_file_name, &buf);
765 bb_data_size = buf.st_size / 4;
767 bb_data = (char *) xmalloc ((unsigned) buf.st_size);
768 fread (bb_data, sizeof (char), buf.st_size, bb_file);
770 fclose (bb_file);
771 if (da_file)
772 fclose (da_file);
773 fclose (bbg_file);
777 /* Scan the data in the .bb file to find all source files referenced,
778 and the largest line number mentioned in each one. */
780 static void
781 scan_for_source_files ()
783 struct sourcefile *s_ptr = NULL;
784 char *ptr;
785 int count;
786 long line_num;
788 /* Search the bb_data to find:
789 1) The number of sources files contained herein, and
790 2) The largest line number for each source file. */
792 ptr = bb_data;
793 sources = 0;
794 for (count = 0; count < bb_data_size; count++)
796 __fetch_long (&line_num, ptr, 4);
797 ptr += 4;
798 if (line_num == -1)
800 /* A source file name follows. Check to see if we already have
801 a sourcefile structure for this file. */
802 s_ptr = sources;
803 while (s_ptr && strcmp (s_ptr->name, ptr))
804 s_ptr = s_ptr->next;
806 if (s_ptr == 0)
808 /* No sourcefile structure for this file name exists, create
809 a new one, and append it to the front of the sources list. */
810 s_ptr = (struct sourcefile *) xmalloc (sizeof(struct sourcefile));
811 s_ptr->name = xstrdup (ptr);
812 s_ptr->maxlineno = 0;
813 s_ptr->next = sources;
814 sources = s_ptr;
817 /* Scan past the file name. */
819 long delim;
820 do {
821 count++;
822 __fetch_long (&delim, ptr, 4);
823 ptr += 4;
824 } while (delim != line_num);
827 else if (line_num == -2)
829 long delim;
831 /* A function name follows. Ignore it. */
832 do {
833 count++;
834 __fetch_long (&delim, ptr, 4);
835 ptr += 4;
836 } while (delim != line_num);
838 /* There will be a zero before the first file name, in which case s_ptr
839 will still be uninitialized. So, only try to set the maxlineno
840 field if line_num is non-zero. */
841 else if (line_num > 0)
843 if (s_ptr->maxlineno <= line_num)
844 s_ptr->maxlineno = line_num + 1;
846 else if (line_num < 0)
848 /* Don't know what this is, but it's garbage. */
849 abort();
854 /* For calculating coverage at the function level. */
856 static int function_source_lines;
857 static int function_source_lines_executed;
858 static int function_branches;
859 static int function_branches_executed;
860 static int function_branches_taken;
861 static int function_calls;
862 static int function_calls_executed;
863 static char *function_name;
865 /* Calculate the branch taken probabilities for all arcs branches at the
866 end of this block. */
868 static void
869 calculate_branch_probs (current_graph, block_num, branch_probs, last_line_num)
870 struct bb_info_list *current_graph;
871 int block_num;
872 struct arcdata **branch_probs;
873 int last_line_num;
875 int total;
876 struct adj_list *arcptr;
877 struct arcdata *end_ptr, *a_ptr;
879 total = current_graph->bb_graph[block_num].exec_count;
880 for (arcptr = current_graph->bb_graph[block_num].succ; arcptr;
881 arcptr = arcptr->succ_next)
883 /* Ignore fall through arcs as they aren't really branches. */
885 if (arcptr->fall_through)
886 continue;
888 a_ptr = (struct arcdata *) xmalloc (sizeof (struct arcdata));
889 a_ptr->total = total;
890 if (total == 0)
891 a_ptr->hits = 0;
892 else
893 a_ptr->hits = arcptr->arc_count;
894 a_ptr->call_insn = arcptr->fake;
896 if (output_function_summary)
898 if (a_ptr->call_insn)
900 function_calls++;
901 if (a_ptr->total != 0)
902 function_calls_executed++;
904 else
906 function_branches++;
907 if (a_ptr->total != 0)
908 function_branches_executed++;
909 if (a_ptr->hits > 0)
910 function_branches_taken++;
914 /* Append the new branch to the end of the list. */
915 a_ptr->next = 0;
916 if (! branch_probs[last_line_num])
917 branch_probs[last_line_num] = a_ptr;
918 else
920 end_ptr = branch_probs[last_line_num];
921 while (end_ptr->next != 0)
922 end_ptr = end_ptr->next;
923 end_ptr->next = a_ptr;
928 /* Output summary info for a function. */
930 static void
931 function_summary ()
933 if (function_source_lines)
934 fnotice (stdout, "%6.2f%% of %d source lines executed in function %s\n",
935 (((double) function_source_lines_executed / function_source_lines)
936 * 100), function_source_lines, function_name);
937 else
938 fnotice (stdout, "No executable source lines in function %s\n",
939 function_name);
941 if (output_branch_probs)
943 if (function_branches)
945 fnotice (stdout, "%6.2f%% of %d branches executed in function %s\n",
946 (((double) function_branches_executed / function_branches)
947 * 100), function_branches, function_name);
948 fnotice (stdout,
949 "%6.2f%% of %d branches taken at least once in function %s\n",
950 (((double) function_branches_taken / function_branches)
951 * 100), function_branches, function_name);
953 else
954 fnotice (stdout, "No branches in function %s\n", function_name);
955 if (function_calls)
956 fnotice (stdout, "%6.2f%% of %d calls executed in function %s\n",
957 (((double) function_calls_executed / function_calls)
958 * 100), function_calls, function_name);
959 else
960 fnotice (stdout, "No calls in function %s\n", function_name);
964 /* Calculate line execution counts, and output the data to a .tcov file. */
966 static void
967 output_data ()
969 /* When scanning data, this is true only if the data applies to the
970 current source file. */
971 int this_file;
972 /* An array indexed by line number which indicates how many times that line
973 was executed. */
974 long *line_counts;
975 /* An array indexed by line number which indicates whether the line was
976 present in the bb file (i.e. whether it had code associate with it).
977 Lines never executed are those which both exist, and have zero execution
978 counts. */
979 char *line_exists;
980 /* An array indexed by line number, which contains a list of branch
981 probabilities, one for each branch on that line. */
982 struct arcdata **branch_probs = NULL;
983 struct sourcefile *s_ptr;
984 char *source_file_name;
985 FILE *source_file;
986 struct bb_info_list *current_graph;
987 int count;
988 char *cptr;
989 long block_num;
990 long line_num;
991 long last_line_num = 0;
992 int i;
993 struct arcdata *a_ptr;
994 /* Buffer used for reading in lines from the source file. */
995 char string[STRING_SIZE];
996 /* For calculating coverage at the file level. */
997 int total_source_lines;
998 int total_source_lines_executed;
999 int total_branches;
1000 int total_branches_executed;
1001 int total_branches_taken;
1002 int total_calls;
1003 int total_calls_executed;
1005 /* Now, for each source file, allocate an array big enough to hold a count
1006 for each line. Scan through the bb_data, and when the file name matches
1007 the current file name, then for each following line number, increment
1008 the line number execution count indicated by the execution count of
1009 the appropriate basic block. */
1011 for (s_ptr = sources; s_ptr; s_ptr = s_ptr->next)
1013 /* If this is a relative file name, and an object directory has been
1014 specified, then make it relative to the object directory name. */
1015 if (! (*s_ptr->name == '/' || *s_ptr->name == DIR_SEPARATOR
1016 /* Check for disk name on MS-DOS-based systems. */
1017 || (DIR_SEPARATOR == '\\'
1018 && s_ptr->name[1] == ':'
1019 && (s_ptr->name[2] == DIR_SEPARATOR
1020 || s_ptr->name[2] == '/')))
1021 && object_directory != 0
1022 && *object_directory != '\0')
1024 int objdir_count = strlen (object_directory);
1025 source_file_name = xmalloc (objdir_count + strlen (s_ptr->name) + 2);
1026 strcpy (source_file_name, object_directory);
1027 if (object_directory[objdir_count - 1] != '/')
1028 source_file_name[objdir_count++] = '/';
1029 strcpy (source_file_name + objdir_count, s_ptr->name);
1031 else
1032 source_file_name = s_ptr->name;
1034 line_counts = (long *) xcalloc (sizeof (long), s_ptr->maxlineno);
1035 line_exists = xcalloc (1, s_ptr->maxlineno);
1036 if (output_branch_probs)
1037 branch_probs = (struct arcdata **)
1038 xcalloc (sizeof (struct arcdata *), s_ptr->maxlineno);
1040 /* There will be a zero at the beginning of the bb info, before the
1041 first list of line numbers, so must initialize block_num to 0. */
1042 block_num = 0;
1043 this_file = 0;
1044 current_graph = 0;
1046 /* Pointer into the bb_data, incremented while scanning the data. */
1047 char *ptr = bb_data;
1048 for (count = 0; count < bb_data_size; count++)
1050 long delim;
1052 __fetch_long (&line_num, ptr, 4);
1053 ptr += 4;
1054 if (line_num == -1)
1056 /* Marks the beginning of a file name. Check to see whether
1057 this is the filename we are currently collecting data for. */
1059 if (strcmp (s_ptr->name, ptr))
1060 this_file = 0;
1061 else
1062 this_file = 1;
1064 /* Scan past the file name. */
1065 do {
1066 count++;
1067 __fetch_long (&delim, ptr, 4);
1068 ptr += 4;
1069 } while (delim != line_num);
1071 else if (line_num == -2)
1073 /* Marks the start of a new function. Advance to the next
1074 program flow graph. */
1076 if (! current_graph)
1077 current_graph = bb_graph_list;
1078 else
1080 if (block_num == current_graph->num_blocks - 1)
1081 /* Last block falls through to exit. */
1083 else if (block_num == current_graph->num_blocks - 2)
1085 if (output_branch_probs && this_file)
1086 calculate_branch_probs (current_graph, block_num,
1087 branch_probs, last_line_num);
1089 else
1091 fnotice (stderr,
1092 "didn't use all bb entries of graph, function %s\n",
1093 function_name);
1094 fnotice (stderr, "block_num = %ld, num_blocks = %d\n",
1095 block_num, current_graph->num_blocks);
1098 current_graph = current_graph->next;
1099 block_num = 0;
1101 if (output_function_summary && this_file)
1102 function_summary ();
1105 if (output_function_summary)
1107 function_source_lines = 0;
1108 function_source_lines_executed = 0;
1109 function_branches = 0;
1110 function_branches_executed = 0;
1111 function_branches_taken = 0;
1112 function_calls = 0;
1113 function_calls_executed = 0;
1116 /* Save the function name for later use. */
1117 function_name = ptr;
1119 /* Scan past the file name. */
1120 do {
1121 count++;
1122 __fetch_long (&delim, ptr, 4);
1123 ptr += 4;
1124 } while (delim != line_num);
1126 else if (line_num == 0)
1128 /* Marks the end of a block. */
1130 if (block_num >= current_graph->num_blocks)
1132 fnotice (stderr, "ERROR: too many basic blocks in .bb file %s\n",
1133 function_name);
1134 abort ();
1137 if (output_branch_probs && this_file)
1138 calculate_branch_probs (current_graph, block_num,
1139 branch_probs, last_line_num);
1141 block_num++;
1143 else if (this_file)
1145 if (output_function_summary)
1147 if (line_exists[line_num] == 0)
1148 function_source_lines++;
1149 if (line_counts[line_num] == 0
1150 && current_graph->bb_graph[block_num].exec_count != 0)
1151 function_source_lines_executed++;
1154 /* Accumulate execution data for this line number. */
1156 line_counts[line_num]
1157 += current_graph->bb_graph[block_num].exec_count;
1158 line_exists[line_num] = 1;
1159 last_line_num = line_num;
1164 if (output_function_summary && this_file)
1165 function_summary ();
1167 /* Calculate summary test coverage statistics. */
1169 total_source_lines = 0;
1170 total_source_lines_executed = 0;
1171 total_branches = 0;
1172 total_branches_executed = 0;
1173 total_branches_taken = 0;
1174 total_calls = 0;
1175 total_calls_executed = 0;
1177 for (count = 1; count < s_ptr->maxlineno; count++)
1179 if (line_exists[count])
1181 total_source_lines++;
1182 if (line_counts[count])
1183 total_source_lines_executed++;
1185 if (output_branch_probs)
1187 for (a_ptr = branch_probs[count]; a_ptr; a_ptr = a_ptr->next)
1189 if (a_ptr->call_insn)
1191 total_calls++;
1192 if (a_ptr->total != 0)
1193 total_calls_executed++;
1195 else
1197 total_branches++;
1198 if (a_ptr->total != 0)
1199 total_branches_executed++;
1200 if (a_ptr->hits > 0)
1201 total_branches_taken++;
1207 if (total_source_lines)
1208 fnotice (stdout,
1209 "%6.2f%% of %d source lines executed in file %s\n",
1210 (((double) total_source_lines_executed / total_source_lines)
1211 * 100), total_source_lines, source_file_name);
1212 else
1213 fnotice (stdout, "No executable source lines in file %s\n",
1214 source_file_name);
1216 if (output_branch_probs)
1218 if (total_branches)
1220 fnotice (stdout, "%6.2f%% of %d branches executed in file %s\n",
1221 (((double) total_branches_executed / total_branches)
1222 * 100), total_branches, source_file_name);
1223 fnotice (stdout,
1224 "%6.2f%% of %d branches taken at least once in file %s\n",
1225 (((double) total_branches_taken / total_branches)
1226 * 100), total_branches, source_file_name);
1228 else
1229 fnotice (stdout, "No branches in file %s\n", source_file_name);
1230 if (total_calls)
1231 fnotice (stdout, "%6.2f%% of %d calls executed in file %s\n",
1232 (((double) total_calls_executed / total_calls)
1233 * 100), total_calls, source_file_name);
1234 else
1235 fnotice (stdout, "No calls in file %s\n", source_file_name);
1238 if (output_gcov_file)
1240 /* Now the statistics are ready. Read in the source file one line
1241 at a time, and output that line to the gcov file preceded by
1242 its execution count if non zero. */
1244 source_file = fopen (source_file_name, "r");
1245 if (source_file == NULL)
1247 fnotice (stderr, "Could not open source file %s.\n",
1248 source_file_name);
1249 free (line_counts);
1250 free (line_exists);
1251 continue;
1254 count = strlen (source_file_name);
1255 cptr = rindex (s_ptr->name, '/');
1256 if (cptr)
1257 cptr = cptr + 1;
1258 else
1259 cptr = s_ptr->name;
1260 if (output_long_names && strcmp (cptr, input_file_name))
1262 gcov_file_name = xmalloc (count + 7 + strlen (input_file_name));
1264 cptr = rindex (input_file_name, '/');
1265 if (cptr)
1266 strcpy (gcov_file_name, cptr + 1);
1267 else
1268 strcpy (gcov_file_name, input_file_name);
1270 strcat (gcov_file_name, ".");
1272 cptr = rindex (source_file_name, '/');
1273 if (cptr)
1274 strcat (gcov_file_name, cptr + 1);
1275 else
1276 strcat (gcov_file_name, source_file_name);
1278 else
1280 gcov_file_name = xmalloc (count + 6);
1281 cptr = rindex (source_file_name, '/');
1282 if (cptr)
1283 strcpy (gcov_file_name, cptr + 1);
1284 else
1285 strcpy (gcov_file_name, source_file_name);
1288 /* Don't strip off the ending for compatibility with tcov, since
1289 this results in confusion if there is more than one file with
1290 the same basename, e.g. tmp.c and tmp.h. */
1291 strcat (gcov_file_name, ".gcov");
1293 gcov_file = fopen (gcov_file_name, "w");
1295 if (gcov_file == NULL)
1297 fnotice (stderr, "Could not open output file %s.\n",
1298 gcov_file_name);
1299 fclose (source_file);
1300 free (line_counts);
1301 free (line_exists);
1302 continue;
1305 fnotice (stdout, "Creating %s.\n", gcov_file_name);
1307 for (count = 1; count < s_ptr->maxlineno; count++)
1309 char *retval;
1310 int len;
1312 retval = fgets (string, STRING_SIZE, source_file);
1314 /* For lines which don't exist in the .bb file, print nothing
1315 before the source line. For lines which exist but were never
1316 executed, print ###### before the source line. Otherwise,
1317 print the execution count before the source line. */
1318 /* There are 16 spaces of indentation added before the source
1319 line so that tabs won't be messed up. */
1320 if (line_exists[count])
1322 if (line_counts[count])
1323 fprintf (gcov_file, "%12ld %s", line_counts[count],
1324 string);
1325 else
1326 fprintf (gcov_file, " ###### %s", string);
1328 else
1329 fprintf (gcov_file, "\t\t%s", string);
1331 /* In case the source file line is larger than our buffer, keep
1332 reading and outputting lines until we get a newline. */
1333 len = strlen (string);
1334 while ((len == 0 || string[strlen (string) - 1] != '\n')
1335 && retval != NULL)
1337 retval = fgets (string, STRING_SIZE, source_file);
1338 fputs (string, gcov_file);
1341 if (output_branch_probs)
1343 for (i = 0, a_ptr = branch_probs[count]; a_ptr;
1344 a_ptr = a_ptr->next, i++)
1346 if (a_ptr->call_insn)
1348 if (a_ptr->total == 0)
1349 fnotice (gcov_file, "call %d never executed\n", i);
1350 else
1352 if (output_branch_counts)
1353 fnotice (gcov_file,
1354 "call %d returns = %d\n",
1355 i, a_ptr->total - a_ptr->hits);
1356 else
1357 fnotice (gcov_file,
1358 "call %d returns = %d%%\n",
1359 i, 100 - ((a_ptr->hits * 100) +
1360 (a_ptr->total >> 1))/a_ptr->total);
1363 else
1365 if (a_ptr->total == 0)
1366 fnotice (gcov_file, "branch %d never executed\n",
1368 else
1370 if (output_branch_counts)
1371 fnotice (gcov_file,
1372 "branch %d taken = %d\n",
1373 i, a_ptr->hits);
1374 else
1375 fnotice (gcov_file,
1376 "branch %d taken = %d%%\n", i,
1377 ((a_ptr->hits * 100) +
1378 (a_ptr->total >> 1))/
1379 a_ptr->total);
1386 /* Gracefully handle errors while reading the source file. */
1387 if (retval == NULL)
1389 fnotice (stderr,
1390 "Unexpected EOF while reading source file %s.\n",
1391 source_file_name);
1392 break;
1396 /* Handle all remaining source lines. There may be lines
1397 after the last line of code. */
1400 char *retval = fgets (string, STRING_SIZE, source_file);
1401 while (retval != NULL)
1403 int len;
1405 fprintf (gcov_file, "\t\t%s", string);
1407 /* In case the source file line is larger than our buffer, keep
1408 reading and outputting lines until we get a newline. */
1409 len = strlen (string);
1410 while ((len == 0 || string[strlen (string) - 1] != '\n')
1411 && retval != NULL)
1413 retval = fgets (string, STRING_SIZE, source_file);
1414 fputs (string, gcov_file);
1417 retval = fgets (string, STRING_SIZE, source_file);
1421 fclose (source_file);
1422 fclose (gcov_file);
1425 free (line_counts);
1426 free (line_exists);