OSDN Git Service

* jump.c: Add prototype for mark_modified_reg.
[pf3gnuchains/gcc-fork.git] / gcc / gcov.c
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.
7
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.
12
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.
17
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.  */
22
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.  */
26
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.  */
30
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.  */
35
36 /* ??? Should have an option to print the number of basic blocks, and the
37    percent of them that are covered.  */
38
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.  */
45
46 #include "config.h"
47 #include "system.h"
48 #include "intl.h"
49 #undef abort
50
51 typedef HOST_WIDEST_INT gcov_type;
52 #include "gcov-io.h"
53
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.
58
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.
65
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.
72
73    The .da file contains the execution count for each instrumented branch.
74
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.  */
78
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.  */
81
82 char gcov_version_string[] = "GNU gcov version 1.5\n";
83
84 /* This is the size of the buffer used to read in source file lines.  */
85
86 #define STRING_SIZE 200
87
88 /* One copy of this structure is created for each source file mentioned in the
89    .bb file.  */
90
91 struct sourcefile
92 {
93   char *name;
94   int maxlineno;
95   struct sourcefile *next;
96 };
97
98 /* This points to the head of the sourcefile structure list.  */
99
100 struct sourcefile *sources;
101
102 /* One of these is dynamically created whenever we identify an arc in the
103    function.  */
104
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;
119 };
120
121 /* Count the number of basic blocks, and create an array of these structures,
122    one for each bb in the function.  */
123
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
136 };
137
138 /* When outputting branch probabilities, one of these structures is created
139    for each branch/call.  */
140
141 struct arcdata
142 {
143   gcov_type hits;
144   gcov_type total;
145   int call_insn;
146   struct arcdata *next;
147 };
148
149 /* Used to save the list of bb_graphs, one per function.  */
150
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;
156 };
157
158 /* Holds a list of function basic block graphs.  */
159
160 static struct bb_info_list *bb_graph_list = 0;
161
162 /* Name and file pointer of the input file for the basic block graph.  */
163
164 static char *bbg_file_name;
165 static FILE *bbg_file;
166
167 /* Name and file pointer of the input file for the arc count data.  */
168
169 static char *da_file_name;
170 static FILE *da_file;
171
172 /* Name and file pointer of the input file for the basic block line counts.  */
173
174 static char *bb_file_name;
175 static FILE *bb_file;
176
177 /* Holds the entire contents of the bb_file read into memory.  */
178
179 static char *bb_data;
180
181 /* Size of bb_data array in longs.  */
182
183 static long bb_data_size;
184
185 /* Name and file pointer of the output file.  */
186
187 static char *gcov_file_name;
188 static FILE *gcov_file;
189
190 /* Name of the file mentioned on the command line.  */
191
192 static char *input_file_name = 0;
193
194 /* Output branch probabilities if true.  */
195
196 static int output_branch_probs = 0;
197
198 /* Output a gcov file if this is true.  This is on by default, and can
199    be turned off by the -n option.  */
200
201 static int output_gcov_file = 1;
202
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.  */
207
208 static int output_long_names = 0;
209
210 /* Output summary info for each function.  */
211
212 static int output_function_summary = 0;
213
214 /* Object directory file prefix.  This is the directory where .bb and .bbg
215    files are looked for, if non-zero.  */
216
217 static char *object_directory = 0;
218
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 */
221
222 static int output_branch_counts = 0;
223
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));
238
239 extern int main PARAMS ((int, char **));
240
241 int
242 main (argc, argv)
243      int argc;
244      char **argv;
245 {
246 /* LC_CTYPE determines the character set used by the terminal so it has be set
247    to output messages correctly.  */
248
249 #ifdef HAVE_LC_MESSAGES
250   setlocale (LC_CTYPE, "");
251   setlocale (LC_MESSAGES, "");
252 #else
253   setlocale (LC_ALL, "");
254 #endif
255
256   (void) bindtextdomain (PACKAGE, localedir);
257   (void) textdomain (PACKAGE);
258
259   process_args (argc, argv);
260
261   open_files ();
262
263   read_files ();
264
265   scan_for_source_files ();
266
267   output_data ();
268
269   return 0;
270 }
271
272 static void fnotice PARAMS ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2;
273 static void
274 fnotice VPARAMS ((FILE *file, const char *msgid, ...))
275 {
276 #ifndef ANSI_PROTOTYPES
277   FILE *file;
278   const char *msgid;
279 #endif
280   va_list ap;
281
282   VA_START (ap, msgid);
283
284 #ifndef ANSI_PROTOTYPES
285   file = va_arg (ap, FILE *);
286   msgid = va_arg (ap, const char *);
287 #endif
288
289   vfprintf (file, _(msgid), ap);
290   va_end (ap);
291 }
292
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;
296
297 void
298 fancy_abort ()
299 {
300   fnotice (stderr, "Internal gcov abort.\n");
301   exit (FATAL_EXIT_CODE);
302 }
303 \f
304 /* Print a usage message and exit.  */
305
306 static void
307 print_usage ()
308 {
309   fnotice (stderr, "gcov [-b] [-v] [-n] [-l] [-f] [-o OBJDIR] file\n");
310   exit (FATAL_EXIT_CODE);
311 }
312
313 /* Parse the command line.  */
314
315 static void
316 process_args (argc, argv)
317      int argc;
318      char **argv;
319 {
320   int i;
321
322   for (i = 1; i < argc; i++)
323     {
324       if (argv[i][0] == '-')
325         {
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 ();
342         }
343       else if (! input_file_name)
344         input_file_name = argv[i];
345       else
346         print_usage ();
347     }
348
349   if (! input_file_name)
350     print_usage ();
351 }
352
353
354 /* Find and open the .bb, .da, and .bbg files.  */
355
356 static void
357 open_files ()
358 {
359   int count, objdir_count;
360   char *cptr;
361
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;
369
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);
373
374   if (object_directory)
375     {
376       strcpy (da_file_name, object_directory);
377       strcpy (bb_file_name, object_directory);
378       strcpy (bbg_file_name, object_directory);
379
380       if (object_directory[objdir_count - 1] != '/')
381         {
382           strcat (da_file_name, "/");
383           strcat (bb_file_name, "/");
384           strcat (bbg_file_name, "/");
385         }
386
387       cptr = strrchr (input_file_name, '/');
388       if (cptr)
389         {
390           strcat (da_file_name, cptr + 1);
391           strcat (bb_file_name, cptr + 1);
392           strcat (bbg_file_name, cptr + 1);
393         }
394       else
395         {
396           strcat (da_file_name, input_file_name);
397           strcat (bb_file_name, input_file_name);
398           strcat (bbg_file_name, input_file_name);
399         }
400     }
401   else
402     {
403       strcpy (da_file_name, input_file_name);
404       strcpy (bb_file_name, input_file_name);
405       strcpy (bbg_file_name, input_file_name);
406     }
407
408   cptr = strrchr (bb_file_name, '.');
409   if (cptr)
410     strcpy (cptr, ".bb");
411   else
412     strcat (bb_file_name, ".bb");
413
414   cptr = strrchr (da_file_name, '.');
415   if (cptr)
416     strcpy (cptr, ".da");
417   else
418     strcat (da_file_name, ".da");
419
420   cptr = strrchr (bbg_file_name, '.');
421   if (cptr)
422     strcpy (cptr, ".bbg");
423   else
424     strcat (bbg_file_name, ".bbg");
425
426   bb_file = fopen (bb_file_name, "rb");
427   if (bb_file == NULL)
428     {
429       fnotice (stderr, "Could not open basic block file %s.\n", bb_file_name);
430       exit (FATAL_EXIT_CODE);
431     }
432
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)
437     {
438       fnotice (stderr, "Could not open data file %s.\n", da_file_name);
439       fnotice (stderr, "Assuming that all execution counts are zero.\n");
440     }
441
442   bbg_file = fopen (bbg_file_name, "rb");
443   if (bbg_file == NULL)
444     {
445       fnotice (stderr, "Could not open program flow graph file %s.\n",
446                bbg_file_name);
447       exit (FATAL_EXIT_CODE);
448     }
449
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))
455     {
456       fnotice (stderr, "No executable code associated with file %s.\n",
457                input_file_name);
458       exit (FATAL_EXIT_CODE);
459     }
460 }
461 \f
462 /* Initialize a new arc.  */
463
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;
469 {
470   arcptr->target = target;
471   arcptr->source = source;
472
473   arcptr->arc_count = 0;
474   arcptr->count_valid = 0;
475   arcptr->on_tree = 0;
476   arcptr->fake = 0;
477   arcptr->fall_through = 0;
478
479   arcptr->succ_next = bb_graph[source].succ;
480   bb_graph[source].succ = arcptr;
481   bb_graph[source].succ_count++;
482
483   arcptr->pred_next = bb_graph[target].pred;
484   bb_graph[target].pred = arcptr;
485   bb_graph[target].pred_count++;
486 }
487
488
489 /* Reverse the arcs on a arc list.  */
490
491 static struct adj_list *
492 reverse_arcs (arcptr)
493      struct adj_list *arcptr;
494 {
495   struct adj_list *prev = 0;
496   struct adj_list *next;
497
498   for ( ; arcptr; arcptr = next)
499     {
500       next = arcptr->succ_next;
501       arcptr->succ_next = prev;
502       prev = arcptr;
503     }
504
505   return prev;
506 }
507
508
509 /* Construct the program flow graph from the .bbg file, and read in the data
510    in the .da file.  */
511
512 static void
513 create_program_flow_graph (bptr)
514      struct bb_info_list *bptr;
515 {
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;
520
521   /* Read the number of blocks.  */
522   __read_long (&num_blocks, bbg_file, 4);
523
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));
526
527   bptr->bb_graph = bb_graph;
528   bptr->num_blocks = num_blocks;
529
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++)
533     {
534       int j;
535
536       __read_long (&num_arcs_per_block, bbg_file, 4);
537       for (j = 0; j < num_arcs_per_block; j++)
538         {
539           if (number_arcs-- < 0)
540             abort ();
541
542           src = i;
543           __read_long (&dest, bbg_file, 4);
544
545           arcptr = (struct adj_list *) xmalloc (sizeof (struct adj_list));
546           init_arc (arcptr, src, dest, bb_graph);
547
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);
552         }
553     }
554
555   if (number_arcs)
556     abort ();
557
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 ();
563
564   /* Must reverse the order of all succ arcs, to ensure that they match
565      the order of the data in the .da file.  */
566
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);
570
571   /* For each arc not on the spanning tree, set its execution count from
572      the .da file.  */
573
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.  */
576
577   /* This duplicates code in branch_prob in profile.c.  */
578
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)
582         {
583           gcov_type tmp_count = 0;
584           if (da_file && __read_gcov_type (&tmp_count, da_file, 8))
585             abort();
586
587           arcptr->arc_count = tmp_count;
588           arcptr->count_valid = 1;
589           bb_graph[i].succ_count--;
590           bb_graph[arcptr->target].pred_count--;
591         }
592 }
593
594 static void
595 solve_program_flow_graph (bptr)
596      struct bb_info_list *bptr;
597 {
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;
604
605   num_blocks = bptr->num_blocks;
606   bb_graph = bptr->bb_graph;
607
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
612
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.  */
616
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.
622
623      This takes an average of slightly more than 3 passes.  */
624
625   changes = 1;
626   passes = 0;
627   while (changes)
628     {
629       passes++;
630       changes = 0;
631
632       for (i = num_blocks - 1; i >= 0; i--)
633         {
634           if (! bb_graph[i].count_valid)
635             {
636               if (bb_graph[i].succ_count == 0)
637                 {
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;
645                 }
646               else if (bb_graph[i].pred_count == 0)
647                 {
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;
655                 }
656             }
657           if (bb_graph[i].count_valid)
658             {
659               if (bb_graph[i].succ_count == 1)
660                 {
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--;
679
680                   bb_graph[arcptr->target].pred_count--;
681                   changes = 1;
682                 }
683               if (bb_graph[i].pred_count == 1)
684                 {
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--;
703
704                   bb_graph[arcptr->source].succ_count--;
705                   changes = 1;
706                 }
707             }
708         }
709     }
710
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 ();
716 }
717
718
719 static void
720 read_files ()
721 {
722   struct stat buf;
723   struct bb_info_list *list_end = 0;
724   struct bb_info_list *b_ptr;
725   long total;
726
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();
731
732   while (! feof (bbg_file))
733     {
734       b_ptr = (struct bb_info_list *) xmalloc (sizeof (struct bb_info_list));
735
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;
742
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);
746
747       /* Set the EOF condition if at the end of file.  */
748       ungetc (getc (bbg_file), bbg_file);
749     }
750
751   /* Check to make sure the .da file data is valid.  */
752
753   if (da_file)
754     {
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");
760     }
761
762   /* Calculate all of the basic block execution counts and branch
763      taken probabilities.  */
764
765   for (b_ptr = bb_graph_list; b_ptr; b_ptr = b_ptr->next)
766     solve_program_flow_graph (b_ptr);
767
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;
772
773   bb_data = (char *) xmalloc ((unsigned) buf.st_size);
774   fread (bb_data, sizeof (char), buf.st_size, bb_file);
775
776   fclose (bb_file);
777   if (da_file)
778     fclose (da_file);
779   fclose (bbg_file);
780 }
781
782
783 /* Scan the data in the .bb file to find all source files referenced,
784    and the largest line number mentioned in each one.  */
785
786 static void
787 scan_for_source_files ()
788 {
789   struct sourcefile *s_ptr = NULL;
790   char *ptr;
791   long count;
792   long line_num;
793
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.  */
797
798   ptr = bb_data;
799   sources = 0;
800   for (count = 0; count < bb_data_size; count++)
801     {
802       __fetch_long (&line_num, ptr, 4);
803       ptr += 4;
804       if (line_num == -1)
805         {
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;
811
812           if (s_ptr == 0)
813             {
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;
821             }
822
823           /* Scan past the file name.  */
824           {
825             long delim;
826             do {
827               count++;
828               __fetch_long (&delim, ptr, 4);
829               ptr += 4;
830             } while (delim != line_num);
831           }
832         }
833       else if (line_num == -2)
834         {
835           long delim;
836
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);
843         }
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)
848         {
849           if (s_ptr->maxlineno <= line_num)
850             s_ptr->maxlineno = line_num + 1;
851         }
852       else if (line_num < 0)
853         {
854           /* Don't know what this is, but it's garbage. */
855           abort();
856         }
857     }
858 }
859 \f
860 /* For calculating coverage at the function level.  */
861
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;
870
871 /* Calculate the branch taken probabilities for all arcs branches at the
872    end of this block.  */
873
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;
880 {
881   gcov_type total;
882   struct adj_list *arcptr;
883   struct arcdata *end_ptr, *a_ptr;
884
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)
888     {
889       /* Ignore fall through arcs as they aren't really branches.  */
890
891       if (arcptr->fall_through)
892         continue;
893
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;
901
902       if (output_function_summary)
903         {
904           if (a_ptr->call_insn)
905             {
906               function_calls++;
907               if (a_ptr->total != 0)
908                 function_calls_executed++;
909             }
910           else
911             {
912               function_branches++;
913               if (a_ptr->total != 0)
914                 function_branches_executed++;
915               if (a_ptr->hits > 0)
916                 function_branches_taken++;
917             }
918         }
919
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
925         {
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;
930         }
931     }
932 }
933
934 /* Output summary info for a function.  */
935
936 static void
937 function_summary ()
938 {
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);
946
947   if (output_branch_probs)
948     {
949       if (function_branches)
950         {
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);
958         }
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);
967     }
968 }
969
970 /* Calculate line execution counts, and output the data to a .tcov file.  */
971
972 static void
973 output_data ()
974 {
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;
1010
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.  */
1016
1017   for (s_ptr = sources; s_ptr; s_ptr = s_ptr->next)
1018     {
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')
1029         {
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);
1036         }
1037       else
1038         source_file_name = s_ptr->name;
1039
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);
1045
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;
1051       {
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++)
1055           {
1056             long delim;
1057
1058             __fetch_long (&line_num, ptr, 4);
1059             ptr += 4;
1060             if (line_num == -1)
1061               {
1062                 /* Marks the beginning of a file name.  Check to see whether
1063                    this is the filename we are currently collecting data for.  */
1064
1065                 if (strcmp (s_ptr->name, ptr))
1066                   this_file = 0;
1067                 else
1068                   this_file = 1;
1069
1070                 /* Scan past the file name.  */
1071                 do {
1072                   count++;
1073                   __fetch_long (&delim, ptr, 4);
1074                   ptr += 4;
1075                 } while (delim != line_num);
1076               }
1077             else if (line_num == -2)
1078               {
1079                 /* Marks the start of a new function.  Advance to the next
1080                    program flow graph.  */
1081
1082                 if (! current_graph)
1083                   current_graph = bb_graph_list;
1084                 else
1085                   {
1086                     if (block_num == current_graph->num_blocks - 1)
1087                       /* Last block falls through to exit.  */
1088                       ;
1089                     else if (block_num == current_graph->num_blocks - 2)
1090                       {
1091                         if (output_branch_probs && this_file)
1092                           calculate_branch_probs (current_graph, block_num,
1093                                                   branch_probs, last_line_num);
1094                       }
1095                     else
1096                       {
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);
1102                       }
1103
1104                     current_graph = current_graph->next;
1105                     block_num = 0;
1106
1107                     if (output_function_summary && this_file)
1108                       function_summary ();
1109                   }
1110
1111                 if (output_function_summary)
1112                   {
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;
1120                   }
1121
1122                 /* Save the function name for later use.  */
1123                 function_name = ptr;
1124
1125                 /* Scan past the file name.  */
1126                 do {
1127                   count++;
1128                   __fetch_long (&delim, ptr, 4);
1129                   ptr += 4;
1130                 } while (delim != line_num);
1131               }
1132             else if (line_num == 0)
1133               {
1134                 /* Marks the end of a block.  */
1135
1136                 if (block_num >= current_graph->num_blocks)
1137                   {
1138                     fnotice (stderr, "ERROR: too many basic blocks in .bb file %s\n",
1139                              function_name);
1140                     abort ();
1141                   }
1142
1143                 if (output_branch_probs && this_file)
1144                   calculate_branch_probs (current_graph, block_num,
1145                                           branch_probs, last_line_num);
1146
1147                 block_num++;
1148               }
1149             else if (this_file)
1150               {
1151                 if (output_function_summary)
1152                   {
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++;
1158                   }
1159
1160                 /* Accumulate execution data for this line number.  */
1161
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;
1166               }
1167           }
1168       }
1169
1170       if (output_function_summary && this_file)
1171         function_summary ();
1172
1173       /* Calculate summary test coverage statistics.  */
1174
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;
1182
1183       for (count = 1; count < s_ptr->maxlineno; count++)
1184         {
1185           if (line_exists[count])
1186             {
1187               total_source_lines++;
1188               if (line_counts[count])
1189                 total_source_lines_executed++;
1190             }
1191           if (output_branch_probs)
1192             {
1193               for (a_ptr = branch_probs[count]; a_ptr; a_ptr = a_ptr->next)
1194                 {
1195                   if (a_ptr->call_insn)
1196                     {
1197                       total_calls++;
1198                       if (a_ptr->total != 0)
1199                         total_calls_executed++;
1200                     }
1201                   else
1202                     {
1203                       total_branches++;
1204                       if (a_ptr->total != 0)
1205                         total_branches_executed++;
1206                       if (a_ptr->hits > 0)
1207                         total_branches_taken++;
1208                     }
1209                 }
1210             }
1211         }
1212
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);
1221
1222       if (output_branch_probs)
1223         {
1224           if (total_branches)
1225             {
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);
1233             }
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);
1242         }
1243
1244       if (output_gcov_file)
1245         {
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.  */
1249
1250           source_file = fopen (source_file_name, "r");
1251           if (source_file == NULL)
1252             {
1253               fnotice (stderr, "Could not open source file %s.\n",
1254                        source_file_name);
1255               free (line_counts);
1256               free (line_exists);
1257               continue;
1258             }
1259
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))
1267             {
1268               gcov_file_name = xmalloc (count + 7 + strlen (input_file_name));
1269
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);
1275
1276               strcat (gcov_file_name, ".");
1277
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);
1283             }
1284           else
1285             {
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);
1292             }
1293
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");
1298
1299           gcov_file = fopen (gcov_file_name, "w");
1300
1301           if (gcov_file == NULL)
1302             {
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;
1309             }
1310
1311           fnotice (stdout, "Creating %s.\n", gcov_file_name);
1312
1313           for (count = 1; count < s_ptr->maxlineno; count++)
1314             {
1315               char *retval;
1316               int len;
1317
1318               retval = fgets (string, STRING_SIZE, source_file);
1319
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])
1327                 {
1328                   if (line_counts[count])
1329                     {
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);
1334                     }
1335                   else
1336                     fprintf (gcov_file, "      ######    %s", string);
1337                 }
1338               else
1339                 fprintf (gcov_file, "\t\t%s", string);
1340
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)
1346                 {
1347                   retval = fgets (string, STRING_SIZE, source_file);
1348                   fputs (string, gcov_file);
1349                 }
1350
1351               if (output_branch_probs)
1352                 {
1353                   for (i = 0, a_ptr = branch_probs[count]; a_ptr;
1354                        a_ptr = a_ptr->next, i++)
1355                     {
1356                       if (a_ptr->call_insn)
1357                         {
1358                           if (a_ptr->total == 0)
1359                             fnotice (gcov_file, "call %d never executed\n", i);
1360                             else
1361                               {
1362                                 if (output_branch_counts)
1363                                   {
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);
1369                                   }
1370                                 else
1371                                   {
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);
1379                                   }
1380                               }
1381                         }
1382                       else
1383                         {
1384                           if (a_ptr->total == 0)
1385                             fnotice (gcov_file, "branch %d never executed\n",
1386                                      i);
1387                           else
1388                             {
1389                               if (output_branch_counts)
1390                                 {
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);
1396                                 }
1397                               else
1398                                 {
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);
1406                                 }
1407                             }
1408                         }
1409                    }
1410               }
1411
1412               /* Gracefully handle errors while reading the source file.  */
1413               if (retval == NULL)
1414                 {
1415                   fnotice (stderr,
1416                            "Unexpected EOF while reading source file %s.\n",
1417                            source_file_name);
1418                   break;
1419                 }
1420             }
1421
1422           /* Handle all remaining source lines.  There may be lines
1423              after the last line of code.  */
1424
1425           {
1426             char *retval = fgets (string, STRING_SIZE, source_file);
1427             while (retval != NULL)
1428               {
1429                 int len;
1430
1431                 fprintf (gcov_file, "\t\t%s", string);
1432
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)
1438                   {
1439                     retval = fgets (string, STRING_SIZE, source_file);
1440                     fputs (string, gcov_file);
1441                   }
1442
1443                 retval = fgets (string, STRING_SIZE, source_file);
1444               }
1445           }
1446
1447           fclose (source_file);
1448           fclose (gcov_file);
1449         }
1450
1451       free (line_counts);
1452       free (line_exists);
1453     }
1454 }