OSDN Git Service

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