OSDN Git Service

2001-11-11 H.J. Lu <hjl@gnu.org>
[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 #include "version.h"
50 #undef abort
51
52 #include <getopt.h>
53
54 typedef HOST_WIDEST_INT gcov_type;
55 #include "gcov-io.h"
56
57 /* The .bb file format consists of several lists of 4-byte integers
58    which are the line numbers of each basic block in the file.  Each
59    list is terminated by a zero.  These lists correspond to the basic
60    blocks in the reconstructed program flow graph.
61
62    A line number of -1 indicates that a source file name (padded to a
63    long boundary) follows.  The padded file name is followed by
64    another -1 to make it easy to scan past file names.  A -2 indicates
65    that a function name (padded to a long boundary) follows; the name
66    is followed by another -2 to make it easy to scan past the function
67    name.
68
69    The .bbg file contains enough info to enable gcov to reconstruct the
70    program flow graph.  The first word is the number of basic blocks,
71    the second word is the number of arcs, followed by the list of arcs
72    (source bb, dest bb pairs), then a -1, then the number of instrumented
73    arcs followed by the instrumented arcs, followed by another -1.  This
74    is repeated for each function.
75
76    The .da file contains the execution count for each instrumented branch.
77
78    The .bb and .bbg files are created by giving GCC the -ftest-coverage option,
79    and the .da files are created when an executable compiled with
80    -fprofile-arcs is run.  */
81
82 /* The functions in this file for creating and solution program flow graphs
83    are very similar to functions in the gcc source file profile.c.  */
84
85 /* This is the size of the buffer used to read in source file lines.  */
86
87 #define STRING_SIZE 200
88
89 /* One copy of this structure is created for each source file mentioned in the
90    .bb file.  */
91
92 struct sourcefile
93 {
94   char *name;
95   int maxlineno;
96   struct sourcefile *next;
97 };
98
99 /* This points to the head of the sourcefile structure list.  */
100
101 struct sourcefile *sources;
102
103 /* One of these is dynamically created whenever we identify an arc in the
104    function.  */
105
106 struct adj_list {
107   int source;
108   int target;
109   gcov_type arc_count;
110   unsigned int count_valid : 1;
111   unsigned int on_tree : 1;
112   unsigned int fake : 1;
113   unsigned int fall_through : 1;
114 #if 0
115   /* Not needed for gcov, but defined in profile.c.  */
116   rtx branch_insn;
117 #endif
118   struct adj_list *pred_next;
119   struct adj_list *succ_next;
120 };
121
122 /* Count the number of basic blocks, and create an array of these structures,
123    one for each bb in the function.  */
124
125 struct bb_info {
126   struct adj_list *succ;
127   struct adj_list *pred;
128   gcov_type succ_count;
129   gcov_type pred_count;
130   gcov_type exec_count;
131   unsigned int count_valid : 1;
132   unsigned int on_tree : 1;
133 #if 0
134   /* Not needed for gcov, but defined in profile.c.  */
135   rtx first_insn;
136 #endif
137 };
138
139 /* When outputting branch probabilities, one of these structures is created
140    for each branch/call.  */
141
142 struct arcdata
143 {
144   gcov_type hits;
145   gcov_type total;
146   int call_insn;
147   struct arcdata *next;
148 };
149
150 /* Used to save the list of bb_graphs, one per function.  */
151
152 struct bb_info_list {
153   /* Indexed by block number, holds the basic block graph for one function.  */
154   struct bb_info *bb_graph;
155   int num_blocks;
156   struct bb_info_list *next;
157 };
158
159 /* Holds a list of function basic block graphs.  */
160
161 static struct bb_info_list *bb_graph_list = 0;
162
163 /* Name and file pointer of the input file for the basic block graph.  */
164
165 static char *bbg_file_name;
166 static FILE *bbg_file;
167
168 /* Name and file pointer of the input file for the arc count data.  */
169
170 static char *da_file_name;
171 static FILE *da_file;
172
173 /* Name and file pointer of the input file for the basic block line counts.  */
174
175 static char *bb_file_name;
176 static FILE *bb_file;
177
178 /* Holds the entire contents of the bb_file read into memory.  */
179
180 static char *bb_data;
181
182 /* Size of bb_data array in longs.  */
183
184 static long bb_data_size;
185
186 /* Name and file pointer of the output file.  */
187
188 static char *gcov_file_name;
189 static FILE *gcov_file;
190
191 /* Name of the file mentioned on the command line.  */
192
193 static char *input_file_name = 0;
194
195 /* Output branch probabilities if true.  */
196
197 static int output_branch_probs = 0;
198
199 /* Output a gcov file if this is true.  This is on by default, and can
200    be turned off by the -n option.  */
201
202 static int output_gcov_file = 1;
203
204 /* For included files, make the gcov output file name include the name of
205    the input source file.  For example, if x.h is included in a.c, then the
206    output file name is a.c.x.h.gcov instead of x.h.gcov.  This works only
207    when a single source file is specified.  */
208
209 static int output_long_names = 0;
210
211 /* Output summary info for each function.  */
212
213 static int output_function_summary = 0;
214
215 /* Object directory file prefix.  This is the directory where .bb and .bbg
216    files are looked for, if non-zero.  */
217
218 static char *object_directory = 0;
219
220 /* Output the number of times a branch was taken as opposed to the percentage
221    of times it was taken.  Turned on by the -c option */
222
223 static int output_branch_counts = 0;
224
225 /* Forward declarations.  */
226 static void process_args PARAMS ((int, char **));
227 static void open_files PARAMS ((void));
228 static void read_files PARAMS ((void));
229 static void scan_for_source_files PARAMS ((void));
230 static void output_data PARAMS ((void));
231 static void print_usage PARAMS ((int)) ATTRIBUTE_NORETURN;
232 static void print_version PARAMS ((void)) ATTRIBUTE_NORETURN;
233 static void init_arc PARAMS ((struct adj_list *, int, int, struct bb_info *));
234 static struct adj_list *reverse_arcs PARAMS ((struct adj_list *));
235 static void create_program_flow_graph PARAMS ((struct bb_info_list *));
236 static void solve_program_flow_graph PARAMS ((struct bb_info_list *));
237 static void calculate_branch_probs PARAMS ((struct bb_info_list *, int,
238                                             struct arcdata **, int));
239 static void function_summary PARAMS ((void));
240
241 extern int main PARAMS ((int, char **));
242
243 int
244 main (argc, argv)
245      int argc;
246      char **argv;
247 {
248   gcc_init_libintl ();
249
250   process_args (argc, argv);
251
252   open_files ();
253
254   read_files ();
255
256   scan_for_source_files ();
257
258   output_data ();
259
260   return 0;
261 }
262
263 static void fnotice PARAMS ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2;
264 static void
265 fnotice VPARAMS ((FILE *file, const char *msgid, ...))
266 {
267   VA_OPEN (ap, msgid);
268   VA_FIXEDARG (ap, FILE *, file);
269   VA_FIXEDARG (ap, const char *, msgid);
270
271   vfprintf (file, _(msgid), ap);
272   VA_CLOSE (ap);
273 }
274
275 /* More 'friendly' abort that prints the line and file.
276    config.h can #define abort fancy_abort if you like that sort of thing.  */
277 extern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN;
278
279 void
280 fancy_abort ()
281 {
282   fnotice (stderr, "Internal gcov abort.\n");
283   exit (FATAL_EXIT_CODE);
284 }
285 \f
286 /* Print a usage message and exit.  If ERROR_P is nonzero, this is an error,
287    otherwise the output of --help.  */
288
289 static void
290 print_usage (error_p)
291      int error_p;
292 {
293   FILE *file = error_p ? stderr : stdout;
294   int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
295   fnotice (file, "Usage: gcov [OPTION]... SOURCEFILE\n\n");
296   fnotice (file, "Print code coverage information.\n\n");
297   fnotice (file, "  -h, --help                      Print this help, then exit\n");
298   fnotice (file, "  -v, --version                   Print version number, then exit\n");
299   fnotice (file, "  -b, --branch-probabilities      Include branch probabilities in output\n");
300   fnotice (file, "  -c, --branch-counts             Given counts of branches taken\n\
301                                     rather than percentages\n");
302   fnotice (file, "  -n, --no-output                 Do not create an output file\n");
303   fnotice (file, "  -l, --long-file-names           Use long output file names for included\n\
304                                     source files\n");
305   fnotice (file, "  -f, --function-summaries        Output summaries for each function\n");
306   fnotice (file, "  -o, --object-directory OBJDIR   Search for object files in OBJDIR\n");
307   fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
308            GCCBUGURL);
309   exit (status);
310 }
311
312 /* Print version information and exit.  */
313
314 static void
315 print_version ()
316 {
317   fnotice (stdout, "gcov (GCC) %s\n", version_string);
318   fnotice (stdout, "Copyright (C) 2001 Free Software Foundation, Inc.\n");
319   fnotice (stdout,
320            "This is free software; see the source for copying conditions.  There is NO\n\
321 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
322   exit (SUCCESS_EXIT_CODE);
323 }
324
325 static const struct option options[] =
326 {
327   { "help",                 no_argument,       NULL, 'h' },
328   { "version",              no_argument,       NULL, 'v' },
329   { "branch-probabilities", no_argument,       NULL, 'b' },
330   { "branch-counts",        no_argument,       NULL, 'c' },
331   { "no-output",            no_argument,       NULL, 'n' },
332   { "long-file-names",      no_argument,       NULL, 'l' },
333   { "function-summaries",   no_argument,       NULL, 'f' },
334   { "object-directory",     required_argument, NULL, 'o' }
335 };
336
337 /* Parse the command line.  */
338
339 static void
340 process_args (argc, argv)
341      int argc;
342      char **argv;
343 {
344   int opt;
345
346   while ((opt = getopt_long (argc, argv, "hvbclnfo:", options, NULL)) != -1)
347     {
348       switch (opt)
349         {
350         case 'h':
351           print_usage (false);
352           /* print_usage will exit.  */
353         case 'v':
354           print_version ();
355           /* print_version will exit.  */
356         case 'b':
357           output_branch_probs = 1;
358           break;
359         case 'c':
360           output_branch_counts = 1;
361           break;
362         case 'n':
363           output_gcov_file = 0;
364           break;
365         case 'l':
366           output_long_names = 1;
367           break;
368         case 'f':
369           output_function_summary = 1;
370           break;
371         case 'o':
372           object_directory = optarg;
373           break;
374         default:
375           print_usage (true);
376           /* print_usage will exit.  */
377         }
378     }
379
380   if (optind != argc - 1)
381     print_usage (true);
382
383   input_file_name = argv[optind];
384 }
385
386
387 /* Find and open the .bb, .da, and .bbg files.  */
388
389 static void
390 open_files ()
391 {
392   int count, objdir_count;
393   char *cptr;
394
395   /* Determine the names of the .bb, .bbg, and .da files.  Strip off the
396      extension, if any, and append the new extensions.  */
397   count = strlen (input_file_name);
398   if (object_directory)
399     objdir_count = strlen (object_directory);
400   else
401     objdir_count = 0;
402
403   da_file_name = xmalloc (count + objdir_count + 4);
404   bb_file_name = xmalloc (count + objdir_count + 4);
405   bbg_file_name = xmalloc (count + objdir_count + 5);
406
407   if (object_directory)
408     {
409       strcpy (da_file_name, object_directory);
410       strcpy (bb_file_name, object_directory);
411       strcpy (bbg_file_name, object_directory);
412
413       if (object_directory[objdir_count - 1] != '/')
414         {
415           strcat (da_file_name, "/");
416           strcat (bb_file_name, "/");
417           strcat (bbg_file_name, "/");
418         }
419
420       cptr = strrchr (input_file_name, '/');
421       if (cptr)
422         {
423           strcat (da_file_name, cptr + 1);
424           strcat (bb_file_name, cptr + 1);
425           strcat (bbg_file_name, cptr + 1);
426         }
427       else
428         {
429           strcat (da_file_name, input_file_name);
430           strcat (bb_file_name, input_file_name);
431           strcat (bbg_file_name, input_file_name);
432         }
433     }
434   else
435     {
436       strcpy (da_file_name, input_file_name);
437       strcpy (bb_file_name, input_file_name);
438       strcpy (bbg_file_name, input_file_name);
439     }
440
441   cptr = strrchr (bb_file_name, '.');
442   if (cptr)
443     strcpy (cptr, ".bb");
444   else
445     strcat (bb_file_name, ".bb");
446
447   cptr = strrchr (da_file_name, '.');
448   if (cptr)
449     strcpy (cptr, ".da");
450   else
451     strcat (da_file_name, ".da");
452
453   cptr = strrchr (bbg_file_name, '.');
454   if (cptr)
455     strcpy (cptr, ".bbg");
456   else
457     strcat (bbg_file_name, ".bbg");
458
459   bb_file = fopen (bb_file_name, "rb");
460   if (bb_file == NULL)
461     {
462       fnotice (stderr, "Could not open basic block file %s.\n", bb_file_name);
463       exit (FATAL_EXIT_CODE);
464     }
465
466   /* If none of the functions in the file were executed, then there won't
467      be a .da file.  Just assume that all counts are zero in this case.  */
468   da_file = fopen (da_file_name, "rb");
469   if (da_file == NULL)
470     {
471       fnotice (stderr, "Could not open data file %s.\n", da_file_name);
472       fnotice (stderr, "Assuming that all execution counts are zero.\n");
473     }
474
475   bbg_file = fopen (bbg_file_name, "rb");
476   if (bbg_file == NULL)
477     {
478       fnotice (stderr, "Could not open program flow graph file %s.\n",
479                bbg_file_name);
480       exit (FATAL_EXIT_CODE);
481     }
482
483   /* Check for empty .bbg file.  This indicates that there is no executable
484      code in this source file.  */
485   /* Set the EOF condition if at the end of file.  */
486   ungetc (getc (bbg_file), bbg_file);
487   if (feof (bbg_file))
488     {
489       fnotice (stderr, "No executable code associated with file %s.\n",
490                input_file_name);
491       exit (FATAL_EXIT_CODE);
492     }
493 }
494 \f
495 /* Initialize a new arc.  */
496
497 static void
498 init_arc (arcptr, source, target, bb_graph)
499      struct adj_list *arcptr;
500      int source, target;
501      struct bb_info *bb_graph;
502 {
503   arcptr->target = target;
504   arcptr->source = source;
505
506   arcptr->arc_count = 0;
507   arcptr->count_valid = 0;
508   arcptr->on_tree = 0;
509   arcptr->fake = 0;
510   arcptr->fall_through = 0;
511
512   arcptr->succ_next = bb_graph[source].succ;
513   bb_graph[source].succ = arcptr;
514   bb_graph[source].succ_count++;
515
516   arcptr->pred_next = bb_graph[target].pred;
517   bb_graph[target].pred = arcptr;
518   bb_graph[target].pred_count++;
519 }
520
521
522 /* Reverse the arcs on an arc list.  */
523
524 static struct adj_list *
525 reverse_arcs (arcptr)
526      struct adj_list *arcptr;
527 {
528   struct adj_list *prev = 0;
529   struct adj_list *next;
530
531   for ( ; arcptr; arcptr = next)
532     {
533       next = arcptr->succ_next;
534       arcptr->succ_next = prev;
535       prev = arcptr;
536     }
537
538   return prev;
539 }
540
541
542 /* Construct the program flow graph from the .bbg file, and read in the data
543    in the .da file.  */
544
545 static void
546 create_program_flow_graph (bptr)
547      struct bb_info_list *bptr;
548 {
549   long num_blocks, number_arcs, src, dest, flag_bits, num_arcs_per_block;
550   int i;
551   struct adj_list *arcptr;
552   struct bb_info *bb_graph;
553
554   /* Read the number of blocks.  */
555   __read_long (&num_blocks, bbg_file, 4);
556
557   /* Create an array of size bb number of bb_info structs.  */
558   bb_graph = (struct bb_info *) xcalloc (num_blocks, sizeof (struct bb_info));
559
560   bptr->bb_graph = bb_graph;
561   bptr->num_blocks = num_blocks;
562
563   /* Read and create each arc from the .bbg file.  */
564   __read_long (&number_arcs, bbg_file, 4);
565   for (i = 0; i < num_blocks; i++)
566     {
567       int j;
568
569       __read_long (&num_arcs_per_block, bbg_file, 4);
570       for (j = 0; j < num_arcs_per_block; j++)
571         {
572           if (number_arcs-- < 0)
573             abort ();
574
575           src = i;
576           __read_long (&dest, bbg_file, 4);
577
578           arcptr = (struct adj_list *) xmalloc (sizeof (struct adj_list));
579           init_arc (arcptr, src, dest, bb_graph);
580
581           __read_long (&flag_bits, bbg_file, 4);
582           arcptr->on_tree = flag_bits & 0x1;
583           arcptr->fake = !! (flag_bits & 0x2);
584           arcptr->fall_through = !! (flag_bits & 0x4);
585         }
586     }
587
588   if (number_arcs)
589     abort ();
590
591   /* Read and ignore the -1 separating the arc list from the arc list of the
592      next function.  */
593   __read_long (&src, bbg_file, 4);
594   if (src != -1)
595     abort ();
596
597   /* Must reverse the order of all succ arcs, to ensure that they match
598      the order of the data in the .da file.  */
599
600   for (i = 0; i < num_blocks; i++)
601     if (bb_graph[i].succ)
602       bb_graph[i].succ = reverse_arcs (bb_graph[i].succ);
603
604   /* For each arc not on the spanning tree, set its execution count from
605      the .da file.  */
606
607   /* The first count in the .da file is the number of times that the function
608      was entered.  This is the exec_count for block zero.  */
609
610   /* This duplicates code in branch_prob in profile.c.  */
611
612   for (i = 0; i < num_blocks; i++)
613     for (arcptr = bb_graph[i].succ; arcptr; arcptr = arcptr->succ_next)
614       if (! arcptr->on_tree)
615         {
616           gcov_type tmp_count = 0;
617           if (da_file && __read_gcov_type (&tmp_count, da_file, 8))
618             abort();
619
620           arcptr->arc_count = tmp_count;
621           arcptr->count_valid = 1;
622           bb_graph[i].succ_count--;
623           bb_graph[arcptr->target].pred_count--;
624         }
625 }
626
627 static void
628 solve_program_flow_graph (bptr)
629      struct bb_info_list *bptr;
630 {
631   int passes, changes;
632   gcov_type total;
633   int i;
634   struct adj_list *arcptr;
635   struct bb_info *bb_graph;
636   int num_blocks;
637
638   num_blocks = bptr->num_blocks;
639   bb_graph = bptr->bb_graph;
640
641   /* For every block in the file,
642      - if every exit/entrance arc has a known count, then set the block count
643      - if the block count is known, and every exit/entrance arc but one has
644        a known execution count, then set the count of the remaining arc
645
646      As arc counts are set, decrement the succ/pred count, but don't delete
647      the arc, that way we can easily tell when all arcs are known, or only
648      one arc is unknown.  */
649
650   /* The order that the basic blocks are iterated through is important.
651      Since the code that finds spanning trees starts with block 0, low numbered
652      arcs are put on the spanning tree in preference to high numbered arcs.
653      Hence, most instrumented arcs are at the end.  Graph solving works much
654      faster if we propagate numbers from the end to the start.
655
656      This takes an average of slightly more than 3 passes.  */
657
658   changes = 1;
659   passes = 0;
660   while (changes)
661     {
662       passes++;
663       changes = 0;
664
665       for (i = num_blocks - 1; i >= 0; i--)
666         {
667           if (! bb_graph[i].count_valid)
668             {
669               if (bb_graph[i].succ_count == 0)
670                 {
671                   total = 0;
672                   for (arcptr = bb_graph[i].succ; arcptr;
673                        arcptr = arcptr->succ_next)
674                     total += arcptr->arc_count;
675                   bb_graph[i].exec_count = total;
676                   bb_graph[i].count_valid = 1;
677                   changes = 1;
678                 }
679               else if (bb_graph[i].pred_count == 0)
680                 {
681                   total = 0;
682                   for (arcptr = bb_graph[i].pred; arcptr;
683                        arcptr = arcptr->pred_next)
684                     total += arcptr->arc_count;
685                   bb_graph[i].exec_count = total;
686                   bb_graph[i].count_valid = 1;
687                   changes = 1;
688                 }
689             }
690           if (bb_graph[i].count_valid)
691             {
692               if (bb_graph[i].succ_count == 1)
693                 {
694                   total = 0;
695                   /* One of the counts will be invalid, but it is zero,
696                      so adding it in also doesn't hurt.  */
697                   for (arcptr = bb_graph[i].succ; arcptr;
698                        arcptr = arcptr->succ_next)
699                     total += arcptr->arc_count;
700                   /* Calculate count for remaining arc by conservation.  */
701                   total = bb_graph[i].exec_count - total;
702                   /* Search for the invalid arc, and set its count.  */
703                   for (arcptr = bb_graph[i].succ; arcptr;
704                        arcptr = arcptr->succ_next)
705                     if (! arcptr->count_valid)
706                       break;
707                   if (! arcptr)
708                     abort ();
709                   arcptr->count_valid = 1;
710                   arcptr->arc_count = total;
711                   bb_graph[i].succ_count--;
712
713                   bb_graph[arcptr->target].pred_count--;
714                   changes = 1;
715                 }
716               if (bb_graph[i].pred_count == 1)
717                 {
718                   total = 0;
719                   /* One of the counts will be invalid, but it is zero,
720                      so adding it in also doesn't hurt.  */
721                   for (arcptr = bb_graph[i].pred; arcptr;
722                        arcptr = arcptr->pred_next)
723                     total += arcptr->arc_count;
724                   /* Calculate count for remaining arc by conservation.  */
725                   total = bb_graph[i].exec_count - total;
726                   /* Search for the invalid arc, and set its count.  */
727                   for (arcptr = bb_graph[i].pred; arcptr;
728                        arcptr = arcptr->pred_next)
729                     if (! arcptr->count_valid)
730                       break;
731                   if (! arcptr)
732                     abort ();
733                   arcptr->count_valid = 1;
734                   arcptr->arc_count = total;
735                   bb_graph[i].pred_count--;
736
737                   bb_graph[arcptr->source].succ_count--;
738                   changes = 1;
739                 }
740             }
741         }
742     }
743
744   /* If the graph has been correctly solved, every block will have a
745      succ and pred count of zero.  */
746   for (i = 0; i < num_blocks; i++)
747     if (bb_graph[i].succ_count || bb_graph[i].pred_count)
748       abort ();
749 }
750
751
752 static void
753 read_files ()
754 {
755   struct stat buf;
756   struct bb_info_list *list_end = 0;
757   struct bb_info_list *b_ptr;
758   long total;
759
760   /* Read and ignore the first word of the .da file, which is the count of
761      how many numbers follow.  */
762   if (da_file && __read_long (&total, da_file, 8))
763     abort();
764
765   while (! feof (bbg_file))
766     {
767       b_ptr = (struct bb_info_list *) xmalloc (sizeof (struct bb_info_list));
768
769       b_ptr->next = 0;
770       if (list_end)
771         list_end->next = b_ptr;
772       else
773         bb_graph_list = b_ptr;
774       list_end = b_ptr;
775
776       /* Read in the data in the .bbg file and reconstruct the program flow
777          graph for one function.  */
778       create_program_flow_graph (b_ptr);
779
780       /* Set the EOF condition if at the end of file.  */
781       ungetc (getc (bbg_file), bbg_file);
782     }
783
784   /* Check to make sure the .da file data is valid.  */
785
786   if (da_file)
787     {
788       if (feof (da_file))
789         fnotice (stderr, ".da file contents exhausted too early\n");
790       /* Should be at end of file now.  */
791       if (__read_long (&total, da_file, 8) == 0)
792         fnotice (stderr, ".da file contents not exhausted\n");
793     }
794
795   /* Calculate all of the basic block execution counts and branch
796      taken probabilities.  */
797
798   for (b_ptr = bb_graph_list; b_ptr; b_ptr = b_ptr->next)
799     solve_program_flow_graph (b_ptr);
800
801   /* Read in all of the data from the .bb file.   This info will be accessed
802      sequentially twice.  */
803   stat (bb_file_name, &buf);
804   bb_data_size = buf.st_size / 4;
805
806   bb_data = (char *) xmalloc ((unsigned) buf.st_size);
807   fread (bb_data, sizeof (char), buf.st_size, bb_file);
808
809   fclose (bb_file);
810   if (da_file)
811     fclose (da_file);
812   fclose (bbg_file);
813 }
814
815
816 /* Scan the data in the .bb file to find all source files referenced,
817    and the largest line number mentioned in each one.  */
818
819 static void
820 scan_for_source_files ()
821 {
822   struct sourcefile *s_ptr = NULL;
823   char *ptr;
824   long count;
825   long line_num;
826
827   /* Search the bb_data to find:
828      1) The number of sources files contained herein, and
829      2) The largest line number for each source file.  */
830
831   ptr = bb_data;
832   sources = 0;
833   for (count = 0; count < bb_data_size; count++)
834     {
835       __fetch_long (&line_num, ptr, 4);
836       ptr += 4;
837       if (line_num == -1)
838         {
839           /* A source file name follows.  Check to see if we already have
840            a sourcefile structure for this file.  */
841           s_ptr = sources;
842           while (s_ptr && strcmp (s_ptr->name, ptr))
843             s_ptr = s_ptr->next;
844
845           if (s_ptr == 0)
846             {
847               /* No sourcefile structure for this file name exists, create
848                  a new one, and append it to the front of the sources list.  */
849               s_ptr = (struct sourcefile *) xmalloc (sizeof(struct sourcefile));
850               s_ptr->name = xstrdup (ptr);
851               s_ptr->maxlineno = 0;
852               s_ptr->next = sources;
853               sources = s_ptr;
854             }
855
856           /* Scan past the file name.  */
857           {
858             long delim;
859             do {
860               count++;
861               __fetch_long (&delim, ptr, 4);
862               ptr += 4;
863             } while (delim != line_num);
864           }
865         }
866       else if (line_num == -2)
867         {
868           long delim;
869
870           /* A function name follows.  Ignore it.  */
871           do {
872             count++;
873             __fetch_long (&delim, ptr, 4);
874             ptr += 4;
875           } while (delim != line_num);
876         }
877       /* There will be a zero before the first file name, in which case s_ptr
878          will still be uninitialized.  So, only try to set the maxlineno
879          field if line_num is non-zero.  */
880       else if (line_num > 0)
881         {
882           if (s_ptr->maxlineno <= line_num)
883             s_ptr->maxlineno = line_num + 1;
884         }
885       else if (line_num < 0)
886         {
887           /* Don't know what this is, but it's garbage.  */
888           abort();
889         }
890     }
891 }
892 \f
893 /* For calculating coverage at the function level.  */
894
895 static int function_source_lines;
896 static int function_source_lines_executed;
897 static int function_branches;
898 static int function_branches_executed;
899 static int function_branches_taken;
900 static int function_calls;
901 static int function_calls_executed;
902 static char *function_name;
903
904 /* Calculate the branch taken probabilities for all arcs branches at the
905    end of this block.  */
906
907 static void
908 calculate_branch_probs (current_graph, block_num, branch_probs, last_line_num)
909      struct bb_info_list *current_graph;
910      int block_num;
911      struct arcdata **branch_probs;
912      int last_line_num;
913 {
914   gcov_type total;
915   struct adj_list *arcptr;
916   struct arcdata *end_ptr, *a_ptr;
917
918   total = current_graph->bb_graph[block_num].exec_count;
919   for (arcptr = current_graph->bb_graph[block_num].succ; arcptr;
920        arcptr = arcptr->succ_next)
921     {
922       /* Ignore fall through arcs as they aren't really branches.  */
923
924       if (arcptr->fall_through)
925         continue;
926
927       a_ptr = (struct arcdata *) xmalloc (sizeof (struct arcdata));
928       a_ptr->total = total;
929       if (total == 0)
930           a_ptr->hits = 0;
931       else
932           a_ptr->hits = arcptr->arc_count;
933       a_ptr->call_insn = arcptr->fake;
934
935       if (output_function_summary)
936         {
937           if (a_ptr->call_insn)
938             {
939               function_calls++;
940               if (a_ptr->total != 0)
941                 function_calls_executed++;
942             }
943           else
944             {
945               function_branches++;
946               if (a_ptr->total != 0)
947                 function_branches_executed++;
948               if (a_ptr->hits > 0)
949                 function_branches_taken++;
950             }
951         }
952
953       /* Append the new branch to the end of the list.  */
954       a_ptr->next = 0;
955       if (! branch_probs[last_line_num])
956         branch_probs[last_line_num] = a_ptr;
957       else
958         {
959           end_ptr = branch_probs[last_line_num];
960           while (end_ptr->next != 0)
961             end_ptr = end_ptr->next;
962           end_ptr->next = a_ptr;
963         }
964     }
965 }
966
967 /* Output summary info for a function.  */
968
969 static void
970 function_summary ()
971 {
972   if (function_source_lines)
973     fnotice (stdout, "%6.2f%% of %d source lines executed in function %s\n",
974              (((double) function_source_lines_executed / function_source_lines)
975               * 100), function_source_lines, function_name);
976   else
977     fnotice (stdout, "No executable source lines in function %s\n",
978              function_name);
979
980   if (output_branch_probs)
981     {
982       if (function_branches)
983         {
984           fnotice (stdout, "%6.2f%% of %d branches executed in function %s\n",
985                    (((double) function_branches_executed / function_branches)
986                     * 100), function_branches, function_name);
987           fnotice (stdout,
988                 "%6.2f%% of %d branches taken at least once in function %s\n",
989                    (((double) function_branches_taken / function_branches)
990                     * 100), function_branches, function_name);
991         }
992       else
993         fnotice (stdout, "No branches in function %s\n", function_name);
994       if (function_calls)
995         fnotice (stdout, "%6.2f%% of %d calls executed in function %s\n",
996                  (((double) function_calls_executed / function_calls)
997                   * 100), function_calls, function_name);
998       else
999         fnotice (stdout, "No calls in function %s\n", function_name);
1000     }
1001 }
1002
1003 /* Calculate line execution counts, and output the data to a .tcov file.  */
1004
1005 static void
1006 output_data ()
1007 {
1008   /* When scanning data, this is true only if the data applies to the
1009      current source file.  */
1010   int this_file;
1011   /* An array indexed by line number which indicates how many times that line
1012      was executed.  */
1013   gcov_type *line_counts;
1014   /* An array indexed by line number which indicates whether the line was
1015      present in the bb file (i.e. whether it had code associate with it).
1016      Lines never executed are those which both exist, and have zero execution
1017      counts.  */
1018   char *line_exists;
1019   /* An array indexed by line number, which contains a list of branch
1020      probabilities, one for each branch on that line.  */
1021   struct arcdata **branch_probs = NULL;
1022   struct sourcefile *s_ptr;
1023   char *source_file_name;
1024   FILE *source_file;
1025   struct bb_info_list *current_graph;
1026   long count;
1027   char *cptr;
1028   long block_num;
1029   long line_num;
1030   long last_line_num = 0;
1031   int i;
1032   struct arcdata *a_ptr;
1033   /* Buffer used for reading in lines from the source file.  */
1034   char string[STRING_SIZE];
1035   /* For calculating coverage at the file level.  */
1036   int total_source_lines;
1037   int total_source_lines_executed;
1038   int total_branches;
1039   int total_branches_executed;
1040   int total_branches_taken;
1041   int total_calls;
1042   int total_calls_executed;
1043
1044   /* Now, for each source file, allocate an array big enough to hold a count
1045      for each line.  Scan through the bb_data, and when the file name matches
1046      the current file name, then for each following line number, increment
1047      the line number execution count indicated by the execution count of
1048      the appropriate basic block.  */
1049
1050   for (s_ptr = sources; s_ptr; s_ptr = s_ptr->next)
1051     {
1052       /* If this is a relative file name, and an object directory has been
1053          specified, then make it relative to the object directory name.  */
1054       if (! IS_ABSOLUTE_PATHNAME (s_ptr->name)
1055           && object_directory != 0
1056           && *object_directory != '\0')
1057         {
1058           int objdir_count = strlen (object_directory);
1059           source_file_name = xmalloc (objdir_count + strlen (s_ptr->name) + 2);
1060           strcpy (source_file_name, object_directory);
1061           if (object_directory[objdir_count - 1] != '/')
1062             source_file_name[objdir_count++] = '/';
1063           strcpy (source_file_name + objdir_count, s_ptr->name);
1064         }
1065       else
1066         source_file_name = s_ptr->name;
1067
1068       line_counts = (gcov_type *) xcalloc (sizeof (gcov_type), s_ptr->maxlineno);
1069       line_exists = xcalloc (1, s_ptr->maxlineno);
1070       if (output_branch_probs)
1071         branch_probs = (struct arcdata **)
1072           xcalloc (sizeof (struct arcdata *), s_ptr->maxlineno);
1073
1074       /* There will be a zero at the beginning of the bb info, before the
1075          first list of line numbers, so must initialize block_num to 0.  */
1076       block_num = 0;
1077       this_file = 0;
1078       current_graph = 0;
1079       {
1080         /* Pointer into the bb_data, incremented while scanning the data.  */
1081         char *ptr = bb_data;
1082         for (count = 0; count < bb_data_size; count++)
1083           {
1084             long delim;
1085
1086             __fetch_long (&line_num, ptr, 4);
1087             ptr += 4;
1088             if (line_num == -1)
1089               {
1090                 /* Marks the beginning of a file name.  Check to see whether
1091                    this is the filename we are currently collecting data for.  */
1092
1093                 if (strcmp (s_ptr->name, ptr))
1094                   this_file = 0;
1095                 else
1096                   this_file = 1;
1097
1098                 /* Scan past the file name.  */
1099                 do {
1100                   count++;
1101                   __fetch_long (&delim, ptr, 4);
1102                   ptr += 4;
1103                 } while (delim != line_num);
1104               }
1105             else if (line_num == -2)
1106               {
1107                 /* Marks the start of a new function.  Advance to the next
1108                    program flow graph.  */
1109
1110                 if (! current_graph)
1111                   current_graph = bb_graph_list;
1112                 else
1113                   {
1114                     if (block_num == current_graph->num_blocks - 1)
1115                       /* Last block falls through to exit.  */
1116                       ;
1117                     else if (block_num == current_graph->num_blocks - 2)
1118                       {
1119                         if (output_branch_probs && this_file)
1120                           calculate_branch_probs (current_graph, block_num,
1121                                                   branch_probs, last_line_num);
1122                       }
1123                     else
1124                       {
1125                         fnotice (stderr,
1126                                  "didn't use all bb entries of graph, function %s\n",
1127                                  function_name);
1128                         fnotice (stderr, "block_num = %ld, num_blocks = %d\n",
1129                                  block_num, current_graph->num_blocks);
1130                       }
1131
1132                     current_graph = current_graph->next;
1133                     block_num = 0;
1134
1135                     if (output_function_summary && this_file)
1136                       function_summary ();
1137                   }
1138
1139                 if (output_function_summary)
1140                   {
1141                     function_source_lines = 0;
1142                     function_source_lines_executed = 0;
1143                     function_branches = 0;
1144                     function_branches_executed = 0;
1145                     function_branches_taken = 0;
1146                     function_calls = 0;
1147                     function_calls_executed = 0;
1148                   }
1149
1150                 /* Save the function name for later use.  */
1151                 function_name = ptr;
1152
1153                 /* Scan past the file name.  */
1154                 do {
1155                   count++;
1156                   __fetch_long (&delim, ptr, 4);
1157                   ptr += 4;
1158                 } while (delim != line_num);
1159               }
1160             else if (line_num == 0)
1161               {
1162                 /* Marks the end of a block.  */
1163
1164                 if (block_num >= current_graph->num_blocks)
1165                   {
1166                     fnotice (stderr, "ERROR: too many basic blocks in .bb file %s\n",
1167                              function_name);
1168                     abort ();
1169                   }
1170
1171                 if (output_branch_probs && this_file)
1172                   calculate_branch_probs (current_graph, block_num,
1173                                           branch_probs, last_line_num);
1174
1175                 block_num++;
1176               }
1177             else if (this_file)
1178               {
1179                 if (output_function_summary)
1180                   {
1181                     if (line_exists[line_num] == 0)
1182                       function_source_lines++;
1183                     if (line_counts[line_num] == 0
1184                         && current_graph->bb_graph[block_num].exec_count != 0)
1185                       function_source_lines_executed++;
1186                   }
1187
1188                 /* Accumulate execution data for this line number.  */
1189
1190                 line_counts[line_num]
1191                   += current_graph->bb_graph[block_num].exec_count;
1192                 line_exists[line_num] = 1;
1193                 last_line_num = line_num;
1194               }
1195           }
1196       }
1197
1198       if (output_function_summary && this_file)
1199         function_summary ();
1200
1201       /* Calculate summary test coverage statistics.  */
1202
1203       total_source_lines = 0;
1204       total_source_lines_executed = 0;
1205       total_branches = 0;
1206       total_branches_executed = 0;
1207       total_branches_taken = 0;
1208       total_calls = 0;
1209       total_calls_executed = 0;
1210
1211       for (count = 1; count < s_ptr->maxlineno; count++)
1212         {
1213           if (line_exists[count])
1214             {
1215               total_source_lines++;
1216               if (line_counts[count])
1217                 total_source_lines_executed++;
1218             }
1219           if (output_branch_probs)
1220             {
1221               for (a_ptr = branch_probs[count]; a_ptr; a_ptr = a_ptr->next)
1222                 {
1223                   if (a_ptr->call_insn)
1224                     {
1225                       total_calls++;
1226                       if (a_ptr->total != 0)
1227                         total_calls_executed++;
1228                     }
1229                   else
1230                     {
1231                       total_branches++;
1232                       if (a_ptr->total != 0)
1233                         total_branches_executed++;
1234                       if (a_ptr->hits > 0)
1235                         total_branches_taken++;
1236                     }
1237                 }
1238             }
1239         }
1240
1241       if (total_source_lines)
1242         fnotice (stdout,
1243                  "%6.2f%% of %d source lines executed in file %s\n",
1244                  (((double) total_source_lines_executed / total_source_lines)
1245                   * 100), total_source_lines, source_file_name);
1246       else
1247         fnotice (stdout, "No executable source lines in file %s\n",
1248                  source_file_name);
1249
1250       if (output_branch_probs)
1251         {
1252           if (total_branches)
1253             {
1254               fnotice (stdout, "%6.2f%% of %d branches executed in file %s\n",
1255                        (((double) total_branches_executed / total_branches)
1256                         * 100), total_branches, source_file_name);
1257               fnotice (stdout,
1258                     "%6.2f%% of %d branches taken at least once in file %s\n",
1259                        (((double) total_branches_taken / total_branches)
1260                         * 100), total_branches, source_file_name);
1261             }
1262           else
1263             fnotice (stdout, "No branches in file %s\n", source_file_name);
1264           if (total_calls)
1265             fnotice (stdout, "%6.2f%% of %d calls executed in file %s\n",
1266                      (((double) total_calls_executed / total_calls)
1267                       * 100), total_calls, source_file_name);
1268           else
1269             fnotice (stdout, "No calls in file %s\n", source_file_name);
1270         }
1271
1272       if (output_gcov_file)
1273         {
1274           /* Now the statistics are ready.  Read in the source file one line
1275              at a time, and output that line to the gcov file preceded by
1276              its execution count if non zero.  */
1277
1278           source_file = fopen (source_file_name, "r");
1279           if (source_file == NULL)
1280             {
1281               fnotice (stderr, "Could not open source file %s.\n",
1282                        source_file_name);
1283               free (line_counts);
1284               free (line_exists);
1285               continue;
1286             }
1287
1288           count = strlen (source_file_name);
1289           cptr = strrchr (s_ptr->name, '/');
1290           if (cptr)
1291             cptr = cptr + 1;
1292           else
1293             cptr = s_ptr->name;
1294           if (output_long_names && strcmp (cptr, input_file_name))
1295             {
1296               gcov_file_name = xmalloc (count + 7 + strlen (input_file_name));
1297
1298               cptr = strrchr (input_file_name, '/');
1299               if (cptr)
1300                 strcpy (gcov_file_name, cptr + 1);
1301               else
1302                 strcpy (gcov_file_name, input_file_name);
1303
1304               strcat (gcov_file_name, ".");
1305
1306               cptr = strrchr (source_file_name, '/');
1307               if (cptr)
1308                 strcat (gcov_file_name, cptr + 1);
1309               else
1310                 strcat (gcov_file_name, source_file_name);
1311             }
1312           else
1313             {
1314               gcov_file_name = xmalloc (count + 6);
1315               cptr = strrchr (source_file_name, '/');
1316               if (cptr)
1317                 strcpy (gcov_file_name, cptr + 1);
1318               else
1319                 strcpy (gcov_file_name, source_file_name);
1320             }
1321
1322           /* Don't strip off the ending for compatibility with tcov, since
1323              this results in confusion if there is more than one file with
1324              the same basename, e.g. tmp.c and tmp.h.  */
1325           strcat (gcov_file_name, ".gcov");
1326
1327           gcov_file = fopen (gcov_file_name, "w");
1328
1329           if (gcov_file == NULL)
1330             {
1331               fnotice (stderr, "Could not open output file %s.\n",
1332                        gcov_file_name);
1333               fclose (source_file);
1334               free (line_counts);
1335               free (line_exists);
1336               continue;
1337             }
1338
1339           fnotice (stdout, "Creating %s.\n", gcov_file_name);
1340
1341           for (count = 1; count < s_ptr->maxlineno; count++)
1342             {
1343               char *retval;
1344               int len;
1345
1346               retval = fgets (string, STRING_SIZE, source_file);
1347
1348               /* For lines which don't exist in the .bb file, print nothing
1349                  before the source line.  For lines which exist but were never
1350                  executed, print ###### before the source line.  Otherwise,
1351                  print the execution count before the source line.  */
1352               /* There are 16 spaces of indentation added before the source
1353                  line so that tabs won't be messed up.  */
1354               if (line_exists[count])
1355                 {
1356                   if (line_counts[count])
1357                     {
1358                       char c[20];
1359                       sprintf (c, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)line_counts[count]);
1360                       fprintf (gcov_file, "%12s    %s", c,
1361                                string);
1362                     }
1363                   else
1364                     fprintf (gcov_file, "      ######    %s", string);
1365                 }
1366               else
1367                 fprintf (gcov_file, "\t\t%s", string);
1368
1369               /* In case the source file line is larger than our buffer, keep
1370                  reading and outputting lines until we get a newline.  */
1371               len = strlen (string);
1372               while ((len == 0 || string[strlen (string) - 1] != '\n')
1373                      && retval != NULL)
1374                 {
1375                   retval = fgets (string, STRING_SIZE, source_file);
1376                   fputs (string, gcov_file);
1377                 }
1378
1379               if (output_branch_probs)
1380                 {
1381                   for (i = 0, a_ptr = branch_probs[count]; a_ptr;
1382                        a_ptr = a_ptr->next, i++)
1383                     {
1384                       if (a_ptr->call_insn)
1385                         {
1386                           if (a_ptr->total == 0)
1387                             fnotice (gcov_file, "call %d never executed\n", i);
1388                             else
1389                               {
1390                                 if (output_branch_counts)
1391                                   {
1392                                     char c[20];
1393                                     sprintf (c, HOST_WIDEST_INT_PRINT_DEC,
1394                                              a_ptr->total - a_ptr->hits);
1395                                     fnotice (gcov_file,
1396                                              "call %d returns = %s\n", i, c);
1397                                   }
1398                                 else
1399                                   {
1400                                     char c[20];
1401                                     sprintf (c, HOST_WIDEST_INT_PRINT_DEC,
1402                                              100 - ((a_ptr->hits * 100)
1403                                                     + (a_ptr->total >> 1))
1404                                              / a_ptr->total);
1405                                     fnotice (gcov_file,
1406                                              "call %d returns = %s%%\n", i, c);
1407                                   }
1408                               }
1409                         }
1410                       else
1411                         {
1412                           if (a_ptr->total == 0)
1413                             fnotice (gcov_file, "branch %d never executed\n",
1414                                      i);
1415                           else
1416                             {
1417                               if (output_branch_counts)
1418                                 {
1419                                   char c[20];
1420                                   sprintf (c, HOST_WIDEST_INT_PRINT_DEC,
1421                                            a_ptr->hits);
1422                                   fnotice (gcov_file,
1423                                            "branch %d taken = %s\n", i, c);
1424                                 }
1425                               else
1426                                 {
1427                                   char c[20];
1428                                   sprintf (c, HOST_WIDEST_INT_PRINT_DEC,
1429                                            ((a_ptr->hits * 100)
1430                                             + (a_ptr->total >> 1))
1431                                            / a_ptr->total);
1432                                 fnotice (gcov_file,
1433                                          "branch %d taken = %s%%\n", i, c);
1434                                 }
1435                             }
1436                         }
1437                    }
1438               }
1439
1440               /* Gracefully handle errors while reading the source file.  */
1441               if (retval == NULL)
1442                 {
1443                   fnotice (stderr,
1444                            "Unexpected EOF while reading source file %s.\n",
1445                            source_file_name);
1446                   break;
1447                 }
1448             }
1449
1450           /* Handle all remaining source lines.  There may be lines
1451              after the last line of code.  */
1452
1453           {
1454             char *retval = fgets (string, STRING_SIZE, source_file);
1455             while (retval != NULL)
1456               {
1457                 int len;
1458
1459                 fprintf (gcov_file, "\t\t%s", string);
1460
1461                 /* In case the source file line is larger than our buffer, keep
1462                    reading and outputting lines until we get a newline.  */
1463                 len = strlen (string);
1464                 while ((len == 0 || string[strlen (string) - 1] != '\n')
1465                        && retval != NULL)
1466                   {
1467                     retval = fgets (string, STRING_SIZE, source_file);
1468                     fputs (string, gcov_file);
1469                   }
1470
1471                 retval = fgets (string, STRING_SIZE, source_file);
1472               }
1473           }
1474
1475           fclose (source_file);
1476           fclose (gcov_file);
1477         }
1478
1479       free (line_counts);
1480       free (line_exists);
1481     }
1482 }