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