OSDN Git Service

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