OSDN Git Service

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