OSDN Git Service

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