]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/gcov.cc
[prange] Reword dispatch error message
[thirdparty/gcc.git] / gcc / gcov.cc
CommitLineData
86144b75
DE
1/* Gcov.c: prepend line execution counts and branch probabilities to a
2 source file.
a945c346 3 Copyright (C) 1990-2024 Free Software Foundation, Inc.
86144b75 4 Contributed by James E. Wilson of Cygnus Support.
1d300e19 5 Mangled by Bob Manson of Cygnus Support.
4977bab6 6 Mangled further by Nathan Sidwell <nathan@codesourcery.com>
86144b75
DE
7
8Gcov is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
9dcd6f09 10the Free Software Foundation; either version 3, or (at your option)
86144b75
DE
11any later version.
12
13Gcov is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
9dcd6f09
NC
19along with Gcov; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
86144b75 21
86144b75
DE
22/* ??? Print a list of the ten blocks with the highest execution counts,
23 and list the line numbers corresponding to those blocks. Also, perhaps
24 list the line numbers with the highest execution counts, only printing
25 the first if there are several which are all listed in the same block. */
26
27/* ??? Should have an option to print the number of basic blocks, and the
28 percent of them that are covered. */
29
4977bab6
ZW
30/* Need an option to show individual block counts, and show
31 probabilities of fall through arcs. */
86144b75 32
1d300e19 33#include "config.h"
6aed7ed0
DA
34#define INCLUDE_ALGORITHM
35#define INCLUDE_VECTOR
28f4a4a8 36#define INCLUDE_STRING
136ca74e
ML
37#define INCLUDE_MAP
38#define INCLUDE_SET
b04cd507 39#include "system.h"
4977bab6
ZW
40#include "coretypes.h"
41#include "tm.h"
ab87f8c8 42#include "intl.h"
2691e6d7 43#include "diagnostic.h"
5735c3ea 44#include "version.h"
fc8a650e 45#include "demangle.h"
28f4a4a8 46#include "color-macros.h"
c8fda30f
ML
47#include "pretty-print.h"
48#include "json.h"
08a52331 49#include "hwint.h"
86144b75 50
c8fda30f 51#include <zlib.h>
5735c3ea
JM
52#include <getopt.h>
53
75cc66f2 54#include "md5.h"
24bc5921
ML
55
56using namespace std;
57
546d2adb 58#define IN_GCOV 1
86144b75 59#include "gcov-io.h"
e53b6e56 60#include "gcov-io.cc"
86144b75 61
d879d68e
ML
62#define GCOV_JSON_FORMAT_VERSION "2"
63
1a9075e2 64/* The gcno file is generated by -ftest-coverage option. The gcda file is
4977bab6
ZW
65 generated by a program compiled with -fprofile-arcs. Their formats
66 are documented in gcov-io.h. */
86144b75
DE
67
68/* The functions in this file for creating and solution program flow graphs
e53b6e56
ML
69 are very similar to functions in the gcc source file profile.cc. In
70 some places we make use of the knowledge of how profile.cc works to
4977bab6 71 select particular algorithms here. */
86144b75 72
10adac51
XDL
73/* The code validates that the profile information read in corresponds
74 to the code currently being compiled. Rather than checking for
9696c529 75 identical files, the code below compares a checksum on the CFG
10adac51 76 (based on the order of basic blocks and the arcs in the CFG). If
9696c529
SB
77 the CFG checksum in the gcda file match the CFG checksum in the
78 gcno file, the profile data will be used. */
10adac51 79
86144b75
DE
80/* This is the size of the buffer used to read in source file lines. */
81
99b1c316
MS
82class function_info;
83class block_info;
84class source_info;
08a52331 85class condition_info;
86144b75 86
4977bab6 87/* Describes an arc between two basic blocks. */
86144b75 88
232c80f2 89struct arc_info
4977bab6 90{
32dd366d 91 /* source and destination blocks. */
99b1c316
MS
92 class block_info *src;
93 class block_info *dst;
86144b75 94
4977bab6
ZW
95 /* transition counts. */
96 gcov_type count;
3d7ca167
ZD
97 /* used in cycle search, so that we do not clobber original counts. */
98 gcov_type cs_count;
86144b75 99
86144b75
DE
100 unsigned int count_valid : 1;
101 unsigned int on_tree : 1;
102 unsigned int fake : 1;
103 unsigned int fall_through : 1;
86144b75 104
8919c0d9
NS
105 /* Arc to a catch handler. */
106 unsigned int is_throw : 1;
107
27283c73
NS
108 /* Arc is for a function that abnormally returns. */
109 unsigned int is_call_non_return : 1;
110
fa10beec 111 /* Arc is for catch/setjmp. */
27283c73
NS
112 unsigned int is_nonlocal_return : 1;
113
114 /* Is an unconditional branch. */
115 unsigned int is_unconditional : 1;
116
10b7602f
NS
117 /* Loop making arc. */
118 unsigned int cycle : 1;
119
4977bab6
ZW
120 /* Links to next arc on src and dst lists. */
121 struct arc_info *succ_next;
122 struct arc_info *pred_next;
232c80f2 123};
86144b75 124
0790260e
ML
125/* Describes which locations (lines and files) are associated with
126 a basic block. */
127
6c1dae73 128class block_location_info
0790260e 129{
6c1dae73 130public:
0790260e
ML
131 block_location_info (unsigned _source_file_idx):
132 source_file_idx (_source_file_idx)
133 {}
134
135 unsigned source_file_idx;
136 vector<unsigned> lines;
137};
138
08a52331
JK
139/* Describes a single conditional expression and the (recorded) conditions
140 shown to independently affect the outcome. */
141class condition_info
142{
143public:
144 condition_info ();
145
146 int popcount () const;
147
148 /* Bitsets storing the independently significant outcomes for true and false,
149 respectively. */
150 gcov_type_unsigned truev;
151 gcov_type_unsigned falsev;
152
153 /* Number of terms in the expression; if (x) -> 1, if (x && y) -> 2 etc. */
154 unsigned n_terms;
155};
156
157condition_info::condition_info (): truev (0), falsev (0), n_terms (0)
158{
159}
160
161int condition_info::popcount () const
162{
163 return popcount_hwi (truev) + popcount_hwi (falsev);
164}
165
4977bab6
ZW
166/* Describes a basic block. Contains lists of arcs to successor and
167 predecessor blocks. */
86144b75 168
6c1dae73 169class block_info
86144b75 170{
6c1dae73 171public:
a82be9d5
ML
172 /* Constructor. */
173 block_info ();
174
4977bab6 175 /* Chain of exit and entry arcs. */
232c80f2
ML
176 arc_info *succ;
177 arc_info *pred;
4977bab6 178
32dd366d 179 /* Number of unprocessed exit and entry arcs. */
4977bab6
ZW
180 gcov_type num_succ;
181 gcov_type num_pred;
182
9b9d6370
ML
183 unsigned id;
184
32dd366d 185 /* Block execution count. */
4977bab6
ZW
186 gcov_type count;
187 unsigned count_valid : 1;
188 unsigned valid_chain : 1;
189 unsigned invalid_chain : 1;
8919c0d9 190 unsigned exceptional : 1;
4977bab6 191
27283c73 192 /* Block is a call instrumenting site. */
10b7602f
NS
193 unsigned is_call_site : 1; /* Does the call. */
194 unsigned is_call_return : 1; /* Is the return. */
4977bab6 195
27283c73
NS
196 /* Block is a landing pad for longjmp or throw. */
197 unsigned is_nonlocal_return : 1;
198
08a52331
JK
199 condition_info conditions;
200
0790260e
ML
201 vector<block_location_info> locations;
202
203 struct
27283c73 204 {
0790260e
ML
205 /* Single line graph cycle workspace. Used for all-blocks
206 mode. */
232c80f2 207 arc_info *arc;
0790260e
ML
208 unsigned ident;
209 } cycle; /* Used in all-blocks mode, after blocks are linked onto
210 lines. */
27283c73
NS
211
212 /* Temporary chain for solving graph, and for chaining blocks on one
213 line. */
99b1c316 214 class block_info *chain;
f55ade6e 215
bea002e9 216};
86144b75 217
a82be9d5
ML
218block_info::block_info (): succ (NULL), pred (NULL), num_succ (0), num_pred (0),
219 id (0), count (0), count_valid (0), valid_chain (0), invalid_chain (0),
220 exceptional (0), is_call_site (0), is_call_return (0), is_nonlocal_return (0),
221 locations (), chain (NULL)
222{
223 cycle.arc = NULL;
224}
225
136ca74e
ML
226/* Describes a single line of source. Contains a chain of basic blocks
227 with code on it. */
228
6c1dae73 229class line_info
136ca74e 230{
6c1dae73 231public:
136ca74e
ML
232 /* Default constructor. */
233 line_info ();
234
235 /* Return true when NEEDLE is one of basic blocks the line belongs to. */
bea002e9 236 bool has_block (block_info *needle);
136ca74e
ML
237
238 /* Execution count. */
239 gcov_type count;
240
241 /* Branches from blocks that end on this line. */
232c80f2 242 vector<arc_info *> branches;
136ca74e
ML
243
244 /* blocks which start on this line. Used in all-blocks mode. */
bea002e9 245 vector<block_info *> blocks;
136ca74e
ML
246
247 unsigned exists : 1;
248 unsigned unexceptional : 1;
249 unsigned has_unexecuted_block : 1;
250};
251
252line_info::line_info (): count (0), branches (), blocks (), exists (false),
253 unexceptional (0), has_unexecuted_block (0)
254{
255}
256
257bool
bea002e9 258line_info::has_block (block_info *needle)
136ca74e
ML
259{
260 return std::find (blocks.begin (), blocks.end (), needle) != blocks.end ();
261}
262
c8fda30f
ML
263/* Output demangled function names. */
264
265static int flag_demangled_names = 0;
266
4977bab6 267/* Describes a single function. Contains an array of basic blocks. */
86144b75 268
6c1dae73 269class function_info
8b219a76 270{
6c1dae73 271public:
0790260e
ML
272 function_info ();
273 ~function_info ();
274
136ca74e
ML
275 /* Return true when line N belongs to the function in source file SRC_IDX.
276 The line must be defined in body of the function, can't be inlined. */
277 bool group_line_p (unsigned n, unsigned src_idx);
278
1e81a283
ML
279 /* Function filter based on function_info::artificial variable. */
280
281 static inline bool
282 is_artificial (function_info *fn)
283 {
284 return fn->artificial;
285 }
286
4977bab6 287 /* Name of function. */
c8fda30f
ML
288 char *m_name;
289 char *m_demangled_name;
796621e8 290 unsigned ident;
10adac51
XDL
291 unsigned lineno_checksum;
292 unsigned cfg_checksum;
86144b75 293
8919c0d9
NS
294 /* The graph contains at least one fake incoming edge. */
295 unsigned has_catch : 1;
296
136ca74e
ML
297 /* True when the function is artificial and does not exist
298 in a source file. */
299 unsigned artificial : 1;
300
301 /* True when multiple functions start at a line in a source file. */
302 unsigned is_group : 1;
303
9696c529
SB
304 /* Array of basic blocks. Like in GCC, the entry block is
305 at blocks[0] and the exit block is at blocks[1]. */
306#define ENTRY_BLOCK (0)
307#define EXIT_BLOCK (1)
bea002e9 308 vector<block_info> blocks;
27283c73 309 unsigned blocks_executed;
4977bab6 310
08a52331
JK
311 vector<condition_info*> conditions;
312
4977bab6 313 /* Raw arc coverage counts. */
4464b977 314 vector<gcov_type> counts;
27283c73 315
136ca74e
ML
316 /* First line number. */
317 unsigned start_line;
318
319 /* First line column. */
320 unsigned start_column;
321
322 /* Last line number. */
323 unsigned end_line;
324
b8154717
ML
325 /* Last line column. */
326 unsigned end_column;
327
136ca74e 328 /* Index of source file where the function is defined. */
1ce1b792 329 unsigned src;
27283c73 330
ca086b8b 331 /* Vector of line information (used only for group functions). */
136ca74e 332 vector<line_info> lines;
f55ade6e 333
4977bab6 334 /* Next function. */
99b1c316 335 class function_info *next;
c8fda30f
ML
336
337 /* Get demangled name of a function. The demangled name
338 is converted when it is used for the first time. */
339 char *get_demangled_name ()
340 {
341 if (m_demangled_name == NULL)
342 {
343 m_demangled_name = cplus_demangle (m_name, DMGL_PARAMS);
344 if (!m_demangled_name)
345 m_demangled_name = m_name;
346 }
347
348 return m_demangled_name;
349 }
350
351 /* Get name of the function based on flag_demangled_names. */
352 char *get_name ()
353 {
354 return flag_demangled_names ? get_demangled_name () : m_name;
355 }
356
357 /* Return number of basic blocks (without entry and exit block). */
358 unsigned get_block_count ()
359 {
360 return blocks.size () - 2;
361 }
cb8758b2 362};
4977bab6 363
136ca74e
ML
364/* Function info comparer that will sort functions according to starting
365 line. */
366
367struct function_line_start_cmp
368{
369 inline bool operator() (const function_info *lhs,
370 const function_info *rhs)
371 {
372 return (lhs->start_line == rhs->start_line
373 ? lhs->start_column < rhs->start_column
374 : lhs->start_line < rhs->start_line);
375 }
376};
377
4977bab6
ZW
378/* Describes coverage of a file or function. */
379
a1b5dd18 380struct coverage_info
8b219a76
NS
381{
382 int lines;
383 int lines_executed;
f55ade6e 384
8b219a76
NS
385 int branches;
386 int branches_executed;
387 int branches_taken;
f55ade6e 388
08a52331
JK
389 int conditions;
390 int conditions_covered;
391
8b219a76
NS
392 int calls;
393 int calls_executed;
f55ade6e 394
8b219a76 395 char *name;
a1b5dd18 396};
8b219a76 397
4977bab6
ZW
398/* Describes a file mentioned in the block graph. Contains an array
399 of line info. */
37b8715b 400
6c1dae73 401class source_info
4977bab6 402{
6c1dae73 403public:
c7432e76
ML
404 /* Default constructor. */
405 source_info ();
406
59688303
ML
407 vector<function_info *> *get_functions_at_location (unsigned line_num) const;
408
409 /* Register a new function. */
410 void add_function (function_info *fn);
136ca74e 411
b2230210
ML
412 /* Debug the source file. */
413 void debug ();
414
136ca74e
ML
415 /* Index of the source_info in sources vector. */
416 unsigned index;
417
eeabee0a 418 /* Canonical name of source file. */
4977bab6 419 char *name;
1a9075e2 420 time_t file_time;
37b8715b 421
c7432e76 422 /* Vector of line information. */
4695d816 423 vector<line_info> lines;
86144b75 424
a1b5dd18 425 coverage_info coverage;
27283c73 426
d6683f89
ML
427 /* Maximum line count in the source file. */
428 unsigned int maximum_count;
429
27283c73
NS
430 /* Functions in this source file. These are in ascending line
431 number order. */
59688303
ML
432 vector<function_info *> functions;
433
434 /* Line number to functions map. */
435 vector<vector<function_info *> *> line_to_function_map;
c7432e76
ML
436};
437
136ca74e 438source_info::source_info (): index (0), name (NULL), file_time (),
d6683f89 439 lines (), coverage (), maximum_count (0), functions ()
c7432e76
ML
440{
441}
86144b75 442
59688303
ML
443/* Register a new function. */
444void
445source_info::add_function (function_info *fn)
136ca74e 446{
59688303 447 functions.push_back (fn);
136ca74e 448
59688303
ML
449 if (fn->start_line >= line_to_function_map.size ())
450 line_to_function_map.resize (fn->start_line + 1);
451
452 vector<function_info *> **slot = &line_to_function_map[fn->start_line];
453 if (*slot == NULL)
454 *slot = new vector<function_info *> ();
136ca74e 455
59688303
ML
456 (*slot)->push_back (fn);
457}
458
459vector<function_info *> *
460source_info::get_functions_at_location (unsigned line_num) const
461{
462 if (line_num >= line_to_function_map.size ())
463 return NULL;
136ca74e 464
59688303
ML
465 vector<function_info *> *slot = line_to_function_map[line_num];
466 if (slot != NULL)
467 std::sort (slot->begin (), slot->end (), function_line_start_cmp ());
468
469 return slot;
136ca74e
ML
470}
471
b2230210
ML
472void source_info::debug ()
473{
474 fprintf (stderr, "source_info: %s\n", name);
475 for (vector<function_info *>::iterator it = functions.begin ();
476 it != functions.end (); it++)
477 {
478 function_info *fn = *it;
479 fprintf (stderr, " function_info: %s\n", fn->get_name ());
480 for (vector<block_info>::iterator bit = fn->blocks.begin ();
481 bit != fn->blocks.end (); bit++)
482 {
248feb2f 483 fprintf (stderr, " block_info id=%d, count=%" PRId64 " \n",
b2230210
ML
484 bit->id, bit->count);
485 }
486 }
487
488 for (unsigned lineno = 1; lineno < lines.size (); ++lineno)
489 {
490 line_info &line = lines[lineno];
248feb2f 491 fprintf (stderr, " line_info=%d, count=%" PRId64 "\n", lineno, line.count);
b2230210
ML
492 }
493
494 fprintf (stderr, "\n");
495}
496
8a3f457f 497class name_map
eeabee0a 498{
8a3f457f
ML
499public:
500 name_map ()
501 {
502 }
503
504 name_map (char *_name, unsigned _src): name (_name), src (_src)
505 {
506 }
507
508 bool operator== (const name_map &rhs) const
509 {
510#if HAVE_DOS_BASED_FILE_SYSTEM
511 return strcasecmp (this->name, rhs.name) == 0;
512#else
513 return strcmp (this->name, rhs.name) == 0;
514#endif
515 }
516
517 bool operator< (const name_map &rhs) const
518 {
519#if HAVE_DOS_BASED_FILE_SYSTEM
520 return strcasecmp (this->name, rhs.name) < 0;
521#else
522 return strcmp (this->name, rhs.name) < 0;
523#endif
524 }
525
526 const char *name; /* Source file name */
eeabee0a 527 unsigned src; /* Source file */
8a3f457f 528};
eeabee0a 529
211bea6b 530/* Vector of all functions. */
cb8758b2 531static vector<function_info *> functions;
86144b75 532
59688303
ML
533/* Function ident to function_info * map. */
534static map<unsigned, function_info *> ident_to_fn;
535
c7432e76
ML
536/* Vector of source files. */
537static vector<source_info> sources;
1a9075e2 538
8a3f457f
ML
539/* Mapping of file names to sources */
540static vector<name_map> names;
eeabee0a 541
7a583153
ML
542/* Record all processed files in order to warn about
543 a file being read multiple times. */
544static vector<char *> processed_files;
545
27283c73
NS
546/* This holds data summary information. */
547
5366b186 548static unsigned object_runs;
27283c73 549
bdbdc4e1
NS
550static unsigned total_lines;
551static unsigned total_executed;
552
32dd366d 553/* Modification time of graph file. */
86144b75 554
4977bab6 555static time_t bbg_file_time;
86144b75 556
efbb59b2
SB
557/* Name of the notes (gcno) output file. The "bbg" prefix is for
558 historical reasons, when the notes file contained only the
559 basic block graph notes. */
86144b75 560
4977bab6 561static char *bbg_file_name;
86144b75 562
dd486eb2
NS
563/* Stamp of the bbg file */
564static unsigned bbg_stamp;
565
93814e2d
ML
566/* Supports has_unexecuted_blocks functionality. */
567static unsigned bbg_supports_has_unexecuted_blocks;
568
c74bd3fb
ML
569/* Working directory in which a TU was compiled. */
570static const char *bbg_cwd;
571
efbb59b2 572/* Name and file pointer of the input file for the count data (gcda). */
86144b75 573
4977bab6 574static char *da_file_name;
86144b75 575
80b3502b
NS
576/* Data file is missing. */
577
578static int no_data_file;
579
1a9075e2
TG
580/* If there is several input files, compute and display results after
581 reading all data files. This way if two or more gcda file refer to
582 the same source file (eg inline subprograms in a .h file), the
583 counts are added. */
584
585static int multiple_files = 0;
586
4977bab6 587/* Output branch probabilities. */
86144b75 588
4977bab6 589static int flag_branches = 0;
86144b75 590
08a52331
JK
591/* Output conditions (modified condition/decision coverage). */
592
593static bool flag_conditions = 0;
594
f55ade6e 595/* Show unconditional branches too. */
27283c73
NS
596static int flag_unconditional = 0;
597
86144b75
DE
598/* Output a gcov file if this is true. This is on by default, and can
599 be turned off by the -n option. */
600
4977bab6 601static int flag_gcov_file = 1;
86144b75 602
feb4589d
ML
603/* Output to stdout instead to a gcov file. */
604
605static int flag_use_stdout = 0;
606
acdb4da7
NS
607/* Output progress indication if this is true. This is off by default
608 and can be turned on by the -d option. */
609
610static int flag_display_progress = 0;
611
c8fda30f 612/* Output *.gcov file in JSON intermediate format used by consumers. */
fc8a650e 613
c8fda30f 614static int flag_json_format = 0;
fc8a650e 615
4977bab6
ZW
616/* For included files, make the gcov output file name include the name
617 of the input source file. For example, if x.h is included in a.c,
618 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
86144b75 619
4977bab6 620static int flag_long_names = 0;
86144b75 621
75cc66f2
ML
622/* For situations when a long name can potentially hit filesystem path limit,
623 let's calculate md5sum of the path and append it to a file name. */
624
625static int flag_hash_filenames = 0;
626
9b9d6370
ML
627/* Print verbose informations. */
628
629static int flag_verbose = 0;
630
28f4a4a8
ML
631/* Print colored output. */
632
633static int flag_use_colors = 0;
634
d6683f89
ML
635/* Use perf-like colors to indicate hot lines. */
636
637static int flag_use_hotness_colors = 0;
638
27283c73
NS
639/* Output count information for every basic block, not merely those
640 that contain line number information. */
641
642static int flag_all_blocks = 0;
643
29a4ef18
ML
644/* Output human readable numbers. */
645
646static int flag_human_readable_numbers = 0;
647
86144b75
DE
648/* Output summary info for each function. */
649
4977bab6 650static int flag_function_summary = 0;
86144b75 651
b2230210
ML
652/* Print debugging dumps. */
653
654static int flag_debug = 0;
655
4977bab6
ZW
656/* Object directory file prefix. This is the directory/file where the
657 graph and data files are looked for, if nonzero. */
86144b75
DE
658
659static char *object_directory = 0;
660
1bec9caa
NS
661/* Source directory prefix. This is removed from source pathnames
662 that match, when generating the output file name. */
663
664static char *source_prefix = 0;
665static size_t source_length = 0;
666
667/* Only show data for sources with relative pathnames. Absolute ones
668 usually indicate a system header file, which although it may
669 contain inline functions, is usually uninteresting. */
670static int flag_relative_only = 0;
671
37b8715b 672/* Preserve all pathname components. Needed when object files and
4977bab6
ZW
673 source files are in subdirectories. '/' is mangled as '#', '.' is
674 elided and '..' mangled to '^'. */
675
676static int flag_preserve_paths = 0;
37b8715b 677
8bfa6fc5 678/* Output the number of times a branch was taken as opposed to the percentage
32dd366d 679 of times it was taken. */
23190837 680
4977bab6 681static int flag_counts = 0;
8bfa6fc5 682
815f15d3
ML
683/* Return code of the tool invocation. */
684static int return_code = 0;
685
86144b75 686/* Forward declarations. */
f55ade6e
AJ
687static int process_args (int, char **);
688static void print_usage (int) ATTRIBUTE_NORETURN;
689static void print_version (void) ATTRIBUTE_NORETURN;
690static void process_file (const char *);
ca498a11 691static void process_all_functions (void);
1a9075e2 692static void generate_results (const char *);
f55ade6e 693static void create_file_names (const char *);
eeabee0a 694static char *canonicalize_name (const char *);
1ce1b792 695static unsigned find_source (const char *);
211bea6b
ML
696static void read_graph_file (void);
697static int read_count_file (void);
cb8758b2
ML
698static void solve_flow_graph (function_info *);
699static void find_exception_blocks (function_info *);
a1b5dd18 700static void add_branch_counts (coverage_info *, const arc_info *);
08a52331 701static void add_condition_counts (coverage_info *, const block_info *);
a1b5dd18 702static void add_line_counts (coverage_info *, function_info *);
bdbdc4e1 703static void executed_summary (unsigned, unsigned);
e4b52fca
ML
704static void function_summary (const coverage_info *);
705static void file_summary (const coverage_info *);
f55ade6e 706static const char *format_gcov (gcov_type, gcov_type, int);
c7432e76
ML
707static void accumulate_line_counts (source_info *);
708static void output_gcov_file (const char *, source_info *);
232c80f2 709static int output_branch_count (FILE *, int, const arc_info *);
08a52331 710static void output_conditions (FILE *, const block_info *);
c7432e76 711static void output_lines (FILE *, const source_info *);
b777f228
ML
712static string make_gcov_file_name (const char *, const char *);
713static char *mangle_name (const char *);
f55ade6e
AJ
714static void release_structures (void);
715extern int main (int, char **);
86144b75 716
c8fda30f 717function_info::function_info (): m_name (NULL), m_demangled_name (NULL),
4e8bfd79 718 ident (0), lineno_checksum (0), cfg_checksum (0), has_catch (0),
136ca74e 719 artificial (0), is_group (0),
4464b977 720 blocks (), blocks_executed (0), counts (),
b8154717
ML
721 start_line (0), start_column (0), end_line (0), end_column (0),
722 src (0), lines (), next (NULL)
0790260e 723{
0790260e
ML
724}
725
726function_info::~function_info ()
727{
728 for (int i = blocks.size () - 1; i >= 0; i--)
729 {
232c80f2 730 arc_info *arc, *arc_n;
0790260e
ML
731
732 for (arc = blocks[i].succ; arc; arc = arc_n)
733 {
734 arc_n = arc->succ_next;
735 free (arc);
736 }
737 }
c8fda30f
ML
738 if (m_demangled_name != m_name)
739 free (m_demangled_name);
740 free (m_name);
0790260e
ML
741}
742
136ca74e
ML
743bool function_info::group_line_p (unsigned n, unsigned src_idx)
744{
745 return is_group && src == src_idx && start_line <= n && n <= end_line;
746}
747
24bc5921
ML
748/* Cycle detection!
749 There are a bajillion algorithms that do this. Boost's function is named
750 hawick_cycles, so I used the algorithm by K. A. Hawick and H. A. James in
751 "Enumerating Circuits and Loops in Graphs with Self-Arcs and Multiple-Arcs"
752 (url at <http://complexity.massey.ac.nz/cstn/013/cstn-013.pdf>).
753
754 The basic algorithm is simple: effectively, we're finding all simple paths
755 in a subgraph (that shrinks every iteration). Duplicates are filtered by
756 "blocking" a path when a node is added to the path (this also prevents non-
757 simple paths)--the node is unblocked only when it participates in a cycle.
758 */
759
232c80f2 760typedef vector<arc_info *> arc_vector_t;
bea002e9 761typedef vector<const block_info *> block_vector_t;
24bc5921 762
24bc5921
ML
763/* Handle cycle identified by EDGES, where the function finds minimum cs_count
764 and subtract the value from all counts. The subtracted value is added
765 to COUNT. Returns type of loop. */
766
4af3b0ea 767static void
24bc5921
ML
768handle_cycle (const arc_vector_t &edges, int64_t &count)
769{
770 /* Find the minimum edge of the cycle, and reduce all nodes in the cycle by
771 that amount. */
4ab65208 772 int64_t cycle_count = INTTYPE_MAXIMUM (int64_t);
24bc5921
ML
773 for (unsigned i = 0; i < edges.size (); i++)
774 {
775 int64_t ecount = edges[i]->cs_count;
776 if (cycle_count > ecount)
777 cycle_count = ecount;
778 }
779 count += cycle_count;
780 for (unsigned i = 0; i < edges.size (); i++)
781 edges[i]->cs_count -= cycle_count;
782
2e9ff3bb 783 gcc_assert (cycle_count > 0);
24bc5921
ML
784}
785
786/* Unblock a block U from BLOCKED. Apart from that, iterate all blocks
787 blocked by U in BLOCK_LISTS. */
788
789static void
bea002e9 790unblock (const block_info *u, block_vector_t &blocked,
24bc5921
ML
791 vector<block_vector_t > &block_lists)
792{
793 block_vector_t::iterator it = find (blocked.begin (), blocked.end (), u);
794 if (it == blocked.end ())
795 return;
796
797 unsigned index = it - blocked.begin ();
798 blocked.erase (it);
799
363a0690 800 block_vector_t to_unblock (block_lists[index]);
24bc5921
ML
801
802 block_lists.erase (block_lists.begin () + index);
363a0690
ML
803
804 for (block_vector_t::iterator it = to_unblock.begin ();
805 it != to_unblock.end (); it++)
806 unblock (*it, blocked, block_lists);
24bc5921
ML
807}
808
2e9ff3bb
ML
809/* Return true when PATH contains a zero cycle arc count. */
810
811static bool
9297e013 812path_contains_zero_or_negative_cycle_arc (arc_vector_t &path)
2e9ff3bb
ML
813{
814 for (unsigned i = 0; i < path.size (); i++)
9297e013 815 if (path[i]->cs_count <= 0)
2e9ff3bb
ML
816 return true;
817 return false;
818}
819
24bc5921
ML
820/* Find circuit going to block V, PATH is provisional seen cycle.
821 BLOCKED is vector of blocked vertices, BLOCK_LISTS contains vertices
822 blocked by a block. COUNT is accumulated count of the current LINE.
823 Returns what type of loop it contains. */
824
4af3b0ea 825static bool
bea002e9 826circuit (block_info *v, arc_vector_t &path, block_info *start,
24bc5921 827 block_vector_t &blocked, vector<block_vector_t> &block_lists,
4695d816 828 line_info &linfo, int64_t &count)
24bc5921 829{
4af3b0ea 830 bool loop_found = false;
24bc5921
ML
831
832 /* Add v to the block list. */
833 gcc_assert (find (blocked.begin (), blocked.end (), v) == blocked.end ());
834 blocked.push_back (v);
835 block_lists.push_back (block_vector_t ());
836
232c80f2 837 for (arc_info *arc = v->succ; arc; arc = arc->succ_next)
24bc5921 838 {
bea002e9 839 block_info *w = arc->dst;
2e9ff3bb 840 if (w < start
9297e013 841 || arc->cs_count <= 0
2e9ff3bb 842 || !linfo.has_block (w))
24bc5921
ML
843 continue;
844
845 path.push_back (arc);
846 if (w == start)
4af3b0ea
ML
847 {
848 /* Cycle has been found. */
849 handle_cycle (path, count);
850 loop_found = true;
851 }
9297e013 852 else if (!path_contains_zero_or_negative_cycle_arc (path)
2e9ff3bb 853 && find (blocked.begin (), blocked.end (), w) == blocked.end ())
4af3b0ea
ML
854 loop_found |= circuit (w, path, start, blocked, block_lists, linfo,
855 count);
24bc5921
ML
856
857 path.pop_back ();
858 }
859
4af3b0ea 860 if (loop_found)
24bc5921
ML
861 unblock (v, blocked, block_lists);
862 else
232c80f2 863 for (arc_info *arc = v->succ; arc; arc = arc->succ_next)
24bc5921 864 {
bea002e9 865 block_info *w = arc->dst;
2e9ff3bb 866 if (w < start
9297e013 867 || arc->cs_count <= 0
2e9ff3bb 868 || !linfo.has_block (w))
24bc5921
ML
869 continue;
870
871 size_t index
872 = find (blocked.begin (), blocked.end (), w) - blocked.begin ();
873 gcc_assert (index < blocked.size ());
874 block_vector_t &list = block_lists[index];
875 if (find (list.begin (), list.end (), v) == list.end ())
876 list.push_back (v);
877 }
878
4af3b0ea 879 return loop_found;
24bc5921
ML
880}
881
4af3b0ea 882/* Find cycles for a LINFO. */
24bc5921
ML
883
884static gcov_type
4af3b0ea 885get_cycles_count (line_info &linfo)
24bc5921
ML
886{
887 /* Note that this algorithm works even if blocks aren't in sorted order.
888 Each iteration of the circuit detection is completely independent
889 (except for reducing counts, but that shouldn't matter anyways).
890 Therefore, operating on a permuted order (i.e., non-sorted) only
891 has the effect of permuting the output cycles. */
892
24bc5921 893 gcov_type count = 0;
bea002e9 894 for (vector<block_info *>::iterator it = linfo.blocks.begin ();
4695d816 895 it != linfo.blocks.end (); it++)
24bc5921
ML
896 {
897 arc_vector_t path;
898 block_vector_t blocked;
899 vector<block_vector_t > block_lists;
724e2704 900 circuit (*it, path, *it, blocked, block_lists, linfo, count);
24bc5921
ML
901 }
902
24bc5921
ML
903 return count;
904}
905
86144b75 906int
f55ade6e 907main (int argc, char **argv)
86144b75 908{
4977bab6 909 int argno;
acdb4da7 910 int first_arg;
2691e6d7
JM
911 const char *p;
912
913 p = argv[0] + strlen (argv[0]);
914 while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
915 --p;
916 progname = p;
917
918 xmalloc_set_program_name (progname);
f55ade6e 919
98a3dad4 920 /* Unlock the stdio streams. */
2653bb0c 921 unlock_std_streams ();
98a3dad4 922
191bf464 923 gcc_init_libintl ();
ab87f8c8 924
2691e6d7
JM
925 diagnostic_initialize (global_dc, 0);
926
e3536b82
TG
927 /* Handle response files. */
928 expandargv (&argc, &argv);
929
4977bab6
ZW
930 argno = process_args (argc, argv);
931 if (optind == argc)
932 print_usage (true);
86144b75 933
1a9075e2
TG
934 if (argc - argno > 1)
935 multiple_files = 1;
936
acdb4da7 937 first_arg = argno;
176bf572 938
4977bab6 939 for (; argno != argc; argno++)
acdb4da7
NS
940 {
941 if (flag_display_progress)
176bf572
ML
942 printf ("Processing file %d out of %d\n", argno - first_arg + 1,
943 argc - first_arg);
acdb4da7 944 process_file (argv[argno]);
1a9075e2 945
c8fda30f 946 if (flag_json_format || argno == argc - 1)
e89ce41d 947 {
ca498a11 948 process_all_functions ();
e89ce41d
ML
949 generate_results (argv[argno]);
950 release_structures ();
951 }
952 }
f55ade6e 953
ab37baa6
ML
954 if (!flag_use_stdout)
955 executed_summary (total_lines, total_executed);
956
815f15d3 957 return return_code;
86144b75 958}
86144b75 959\f
5735c3ea
JM
960/* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
961 otherwise the output of --help. */
86144b75
DE
962
963static void
f55ade6e 964print_usage (int error_p)
86144b75 965{
5735c3ea
JM
966 FILE *file = error_p ? stderr : stdout;
967 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
f55ade6e 968
541e0d55 969 fnotice (file, "Usage: gcov [OPTION...] SOURCE|OBJ...\n\n");
5735c3ea 970 fnotice (file, "Print code coverage information.\n\n");
27283c73 971 fnotice (file, " -a, --all-blocks Show information for every basic block\n");
5735c3ea 972 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
fc8a650e 973 fnotice (file, " -c, --branch-counts Output counts of branches taken\n\
5735c3ea 974 rather than percentages\n");
08a52331
JK
975 fnotice (file, " -g, --conditions Include modified condition/decision\n\
976 coverage in output\n");
fc8a650e 977 fnotice (file, " -d, --display-progress Display progress information\n");
b2230210 978 fnotice (file, " -D, --debug Display debugging dumps\n");
fc8a650e 979 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
2f360676 980 fnotice (file, " -h, --help Print this help, then exit\n");
8439b081 981 fnotice (file, " -j, --json-format Output JSON intermediate format\n\
4222fd8e 982 into .gcov.json.gz file\n");
c4076255 983 fnotice (file, " -H, --human-readable Output human readable numbers\n");
28f4a4a8 984 fnotice (file, " -k, --use-colors Emit colored output\n");
5735c3ea
JM
985 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
986 source files\n");
fc8a650e
SS
987 fnotice (file, " -m, --demangled-names Output demangled function names\n");
988 fnotice (file, " -n, --no-output Do not create an output file\n");
37b8715b
NS
989 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
990 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
d6683f89 991 fnotice (file, " -q, --use-hotness-colors Emit perf-like colored output for hot lines\n");
fc8a650e
SS
992 fnotice (file, " -r, --relative-only Only show data for relative sources\n");
993 fnotice (file, " -s, --source-prefix DIR Source prefix to elide\n");
feb4589d 994 fnotice (file, " -t, --stdout Output to stdout instead of a file\n");
27283c73 995 fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
fc8a650e 996 fnotice (file, " -v, --version Print version number, then exit\n");
9b9d6370 997 fnotice (file, " -w, --verbose Print verbose informations\n");
75cc66f2 998 fnotice (file, " -x, --hash-filenames Hash long pathnames\n");
c4076255
ML
999 fnotice (file, "\nObsolete options:\n");
1000 fnotice (file, " -i, --json-format Replaced with -j, --json-format\n");
1001 fnotice (file, " -j, --human-readable Replaced with -H, --human-readable\n");
5735c3ea 1002 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
a976603e 1003 bug_report_url);
5735c3ea
JM
1004 exit (status);
1005}
1006
1007/* Print version information and exit. */
1008
1009static void
f55ade6e 1010print_version (void)
5735c3ea 1011{
2f41c1d6 1012 fnotice (stdout, "gcov %s%s\n", pkgversion_string, version_string);
d879d68e 1013 fnotice (stdout, "JSON format version: %s\n", GCOV_JSON_FORMAT_VERSION);
4e053a7e 1014 fprintf (stdout, "Copyright %s 2024 Free Software Foundation, Inc.\n",
9f76f909 1015 _("(C)"));
5735c3ea 1016 fnotice (stdout,
8ad4fc26
ML
1017 _("This is free software; see the source for copying conditions. There is NO\n\
1018warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
5735c3ea 1019 exit (SUCCESS_EXIT_CODE);
86144b75
DE
1020}
1021
5735c3ea
JM
1022static const struct option options[] =
1023{
1024 { "help", no_argument, NULL, 'h' },
1025 { "version", no_argument, NULL, 'v' },
9b9d6370 1026 { "verbose", no_argument, NULL, 'w' },
27283c73 1027 { "all-blocks", no_argument, NULL, 'a' },
5735c3ea
JM
1028 { "branch-probabilities", no_argument, NULL, 'b' },
1029 { "branch-counts", no_argument, NULL, 'c' },
08a52331 1030 { "conditions", no_argument, NULL, 'g' },
c4076255
ML
1031 { "json-format", no_argument, NULL, 'j' },
1032 { "human-readable", no_argument, NULL, 'H' },
5735c3ea
JM
1033 { "no-output", no_argument, NULL, 'n' },
1034 { "long-file-names", no_argument, NULL, 'l' },
1035 { "function-summaries", no_argument, NULL, 'f' },
fc8a650e 1036 { "demangled-names", no_argument, NULL, 'm' },
37b8715b 1037 { "preserve-paths", no_argument, NULL, 'p' },
1bec9caa 1038 { "relative-only", no_argument, NULL, 'r' },
37b8715b
NS
1039 { "object-directory", required_argument, NULL, 'o' },
1040 { "object-file", required_argument, NULL, 'o' },
1bec9caa 1041 { "source-prefix", required_argument, NULL, 's' },
feb4589d 1042 { "stdout", no_argument, NULL, 't' },
27283c73 1043 { "unconditional-branches", no_argument, NULL, 'u' },
acdb4da7 1044 { "display-progress", no_argument, NULL, 'd' },
75cc66f2 1045 { "hash-filenames", no_argument, NULL, 'x' },
28f4a4a8 1046 { "use-colors", no_argument, NULL, 'k' },
d6683f89 1047 { "use-hotness-colors", no_argument, NULL, 'q' },
b2230210 1048 { "debug", no_argument, NULL, 'D' },
d90f9882 1049 { 0, 0, 0, 0 }
5735c3ea
JM
1050};
1051
4977bab6 1052/* Process args, return index to first non-arg. */
86144b75 1053
4977bab6 1054static int
f55ade6e 1055process_args (int argc, char **argv)
86144b75 1056{
5735c3ea 1057 int opt;
86144b75 1058
08a52331 1059 const char *opts = "abcdDfghHijklmno:pqrs:tuvwx";
75cc66f2 1060 while ((opt = getopt_long (argc, argv, opts, options, NULL)) != -1)
86144b75 1061 {
5735c3ea 1062 switch (opt)
86144b75 1063 {
27283c73
NS
1064 case 'a':
1065 flag_all_blocks = 1;
1066 break;
5735c3ea 1067 case 'b':
4977bab6 1068 flag_branches = 1;
5735c3ea
JM
1069 break;
1070 case 'c':
4977bab6 1071 flag_counts = 1;
5735c3ea 1072 break;
27283c73
NS
1073 case 'f':
1074 flag_function_summary = 1;
5735c3ea 1075 break;
08a52331
JK
1076 case 'g':
1077 flag_conditions = 1;
1078 break;
27283c73
NS
1079 case 'h':
1080 print_usage (false);
1081 /* print_usage will exit. */
5735c3ea 1082 case 'l':
4977bab6 1083 flag_long_names = 1;
5735c3ea 1084 break;
c4076255 1085 case 'H':
29a4ef18
ML
1086 flag_human_readable_numbers = 1;
1087 break;
28f4a4a8
ML
1088 case 'k':
1089 flag_use_colors = 1;
1090 break;
d6683f89
ML
1091 case 'q':
1092 flag_use_hotness_colors = 1;
1093 break;
fc8a650e
SS
1094 case 'm':
1095 flag_demangled_names = 1;
1096 break;
27283c73
NS
1097 case 'n':
1098 flag_gcov_file = 0;
5735c3ea
JM
1099 break;
1100 case 'o':
1101 object_directory = optarg;
1102 break;
1bec9caa
NS
1103 case 's':
1104 source_prefix = optarg;
1105 source_length = strlen (source_prefix);
1106 break;
1107 case 'r':
1108 flag_relative_only = 1;
1109 break;
37b8715b 1110 case 'p':
4977bab6 1111 flag_preserve_paths = 1;
37b8715b 1112 break;
27283c73
NS
1113 case 'u':
1114 flag_unconditional = 1;
1115 break;
fc8a650e 1116 case 'i':
c4076255 1117 case 'j':
c8fda30f
ML
1118 flag_json_format = 1;
1119 flag_gcov_file = 1;
1120 break;
1121 case 'd':
1122 flag_display_progress = 1;
1123 break;
75cc66f2
ML
1124 case 'x':
1125 flag_hash_filenames = 1;
1126 break;
9b9d6370
ML
1127 case 'w':
1128 flag_verbose = 1;
1129 break;
feb4589d
ML
1130 case 't':
1131 flag_use_stdout = 1;
1132 break;
b2230210
ML
1133 case 'D':
1134 flag_debug = 1;
1135 break;
ec383304
ML
1136 case 'v':
1137 print_version ();
27283c73 1138 /* print_version will exit. */
5735c3ea
JM
1139 default:
1140 print_usage (true);
1141 /* print_usage will exit. */
86144b75 1142 }
86144b75
DE
1143 }
1144
4977bab6
ZW
1145 return optind;
1146}
1147
52eba779
ML
1148/* Output intermediate LINE sitting on LINE_NUM to JSON OBJECT.
1149 Add FUNCTION_NAME to the LINE. */
136ca74e
ML
1150
1151static void
c8fda30f 1152output_intermediate_json_line (json::array *object,
52eba779
ML
1153 line_info *line, unsigned line_num,
1154 const char *function_name)
136ca74e
ML
1155{
1156 if (!line->exists)
1157 return;
1158
c8fda30f 1159 json::object *lineo = new json::object ();
070944fd 1160 lineo->set_integer ("line_number", line_num);
52eba779 1161 if (function_name != NULL)
070944fd
DM
1162 lineo->set_string ("function_name", function_name);
1163 lineo->set_integer ("count", line->count);
1164 lineo->set_bool ("unexecuted_block", line->has_unexecuted_block);
c8fda30f 1165
171fe068
ML
1166 json::array *bb_ids = new json::array ();
1167 for (const block_info *block : line->blocks)
1168 bb_ids->append (new json::integer_number (block->id));
1169 lineo->set ("block_ids", bb_ids);
1170
c8fda30f
ML
1171 json::array *branches = new json::array ();
1172 lineo->set ("branches", branches);
136ca74e 1173
171fe068
ML
1174 json::array *calls = new json::array ();
1175 lineo->set ("calls", calls);
1176
232c80f2 1177 vector<arc_info *>::const_iterator it;
136ca74e
ML
1178 if (flag_branches)
1179 for (it = line->branches.begin (); it != line->branches.end ();
1180 it++)
1181 {
1182 if (!(*it)->is_unconditional && !(*it)->is_call_non_return)
1183 {
c8fda30f 1184 json::object *branch = new json::object ();
070944fd
DM
1185 branch->set_integer ("count", (*it)->count);
1186 branch->set_bool ("throw", (*it)->is_throw);
1187 branch->set_bool ("fallthrough", (*it)->fall_through);
1188 branch->set_integer ("source_block_id", (*it)->src->id);
1189 branch->set_integer ("destination_block_id", (*it)->dst->id);
c8fda30f 1190 branches->append (branch);
136ca74e 1191 }
171fe068
ML
1192 else if ((*it)->is_call_non_return)
1193 {
1194 json::object *call = new json::object ();
1195 gcov_type returns = (*it)->src->count - (*it)->count;
070944fd
DM
1196 call->set_integer ("source_block_id", (*it)->src->id);
1197 call->set_integer ("destination_block_id", (*it)->dst->id);
1198 call->set_integer ("returned", returns);
171fe068
ML
1199 calls->append (call);
1200 }
136ca74e 1201 }
c8fda30f 1202
08a52331
JK
1203 json::array *conditions = new json::array ();
1204 lineo->set ("conditions", conditions);
1205 if (flag_conditions)
1206 {
1207 vector<block_info *>::const_iterator it;
1208 for (it = line->blocks.begin (); it != line->blocks.end (); it++)
1209 {
1210 const condition_info& info = (*it)->conditions;
1211 if (info.n_terms == 0)
1212 continue;
1213
1214 const int count = 2 * info.n_terms;
1215 const int covered = info.popcount ();
1216
1217 json::object *cond = new json::object ();
1218 cond->set ("count", new json::integer_number (count));
1219 cond->set ("covered", new json::integer_number (covered));
1220
1221 json::array *mtrue = new json::array ();
1222 json::array *mfalse = new json::array ();
1223 cond->set ("not_covered_true", mtrue);
1224 cond->set ("not_covered_false", mfalse);
1225
1226 if (count != covered)
1227 {
1228 for (unsigned i = 0; i < info.n_terms; i++)
1229 {
1230 gcov_type_unsigned index = 1;
1231 index <<= i;
1232 if (!(index & info.truev))
1233 mtrue->append (new json::integer_number (i));
1234 if (!(index & info.falsev))
1235 mfalse->append (new json::integer_number (i));
1236 }
1237 }
1238 conditions->append (cond);
1239 }
1240 }
1241
c8fda30f 1242 object->append (lineo);
136ca74e
ML
1243}
1244
b777f228
ML
1245/* Strip filename extension in STR. */
1246
1247static string
1248strip_extention (string str)
1249{
1250 string::size_type pos = str.rfind ('.');
1251 if (pos != string::npos)
1252 str = str.substr (0, pos);
1253
1254 return str;
1255}
1256
1257/* Calcualte md5sum for INPUT string and return it in hex string format. */
1258
1259static string
1260get_md5sum (const char *input)
1261{
1262 md5_ctx ctx;
1263 char md5sum[16];
1264 string str;
1265
1266 md5_init_ctx (&ctx);
1267 md5_process_bytes (input, strlen (input), &ctx);
1268 md5_finish_ctx (&ctx, md5sum);
1269
1270 for (unsigned i = 0; i < 16; i++)
1271 {
1272 char b[3];
1273 sprintf (b, "%02x", (unsigned char)md5sum[i]);
1274 str += b;
1275 }
1276
1277 return str;
1278}
1279
e89ce41d
ML
1280/* Get the name of the gcov file. The return value must be free'd.
1281
1282 It appends the '.gcov' extension to the *basename* of the file.
1283 The resulting file name will be in PWD.
1284
1285 e.g.,
1286 input: foo.da, output: foo.da.gcov
1287 input: a/b/foo.cc, output: foo.cc.gcov */
1288
b777f228
ML
1289static string
1290get_gcov_intermediate_filename (const char *input_file_name)
e89ce41d 1291{
b777f228
ML
1292 string base = basename (input_file_name);
1293 string str = strip_extention (base);
e89ce41d 1294
b777f228
ML
1295 if (flag_hash_filenames)
1296 {
1297 str += "##";
1298 str += get_md5sum (input_file_name);
1299 }
1300 else if (flag_preserve_paths && base != input_file_name)
1301 {
1302 str += "##";
1303 str += mangle_path (input_file_name);
1304 str = strip_extention (str);
1305 }
e89ce41d 1306
b777f228
ML
1307 str += ".gcov.json.gz";
1308 return str.c_str ();
e89ce41d
ML
1309}
1310
c8fda30f
ML
1311/* Output the result in JSON intermediate format.
1312 Source info SRC is dumped into JSON_FILES which is JSON array. */
fc8a650e
SS
1313
1314static void
c8fda30f 1315output_json_intermediate_file (json::array *json_files, source_info *src)
fc8a650e 1316{
c8fda30f
ML
1317 json::object *root = new json::object ();
1318 json_files->append (root);
1319
070944fd 1320 root->set_string ("file", src->name);
c8fda30f
ML
1321
1322 json::array *functions = new json::array ();
1323 root->set ("functions", functions);
fc8a650e 1324
136ca74e
ML
1325 std::sort (src->functions.begin (), src->functions.end (),
1326 function_line_start_cmp ());
cb8758b2 1327 for (vector<function_info *>::iterator it = src->functions.begin ();
136ca74e 1328 it != src->functions.end (); it++)
fc8a650e 1329 {
c8fda30f 1330 json::object *function = new json::object ();
070944fd
DM
1331 function->set_string ("name", (*it)->m_name);
1332 function->set_string ("demangled_name", (*it)->get_demangled_name ());
1333 function->set_integer ("start_line", (*it)->start_line);
1334 function->set_integer ("start_column", (*it)->start_column);
1335 function->set_integer ("end_line", (*it)->end_line);
1336 function->set_integer ("end_column", (*it)->end_column);
1337 function->set_integer ("blocks", (*it)->get_block_count ());
1338 function->set_integer ("blocks_executed", (*it)->blocks_executed);
1339 function->set_integer ("execution_count", (*it)->blocks[0].count);
c8fda30f
ML
1340
1341 functions->append (function);
fc8a650e
SS
1342 }
1343
c8fda30f
ML
1344 json::array *lineso = new json::array ();
1345 root->set ("lines", lineso);
1346
efd08ad5 1347 vector<function_info *> last_non_group_fns;
52eba779 1348
e89ce41d 1349 for (unsigned line_num = 1; line_num <= src->lines.size (); line_num++)
fc8a650e 1350 {
59688303 1351 vector<function_info *> *fns = src->get_functions_at_location (line_num);
136ca74e 1352
59688303 1353 if (fns != NULL)
ca086b8b 1354 /* Print info for all group functions that begin on the line. */
59688303
ML
1355 for (vector<function_info *>::iterator it2 = fns->begin ();
1356 it2 != fns->end (); it2++)
1357 {
52eba779 1358 if (!(*it2)->is_group)
efd08ad5 1359 last_non_group_fns.push_back (*it2);
52eba779 1360
59688303 1361 vector<line_info> &lines = (*it2)->lines;
ca086b8b 1362 /* The LINES array is allocated only for group functions. */
59688303
ML
1363 for (unsigned i = 0; i < lines.size (); i++)
1364 {
1365 line_info *line = &lines[i];
52eba779
ML
1366 output_intermediate_json_line (lineso, line, line_num + i,
1367 (*it2)->m_name);
59688303
ML
1368 }
1369 }
136ca74e
ML
1370
1371 /* Follow with lines associated with the source file. */
dda107df 1372 if (line_num < src->lines.size ())
efd08ad5
ML
1373 {
1374 unsigned size = last_non_group_fns.size ();
1375 function_info *last_fn = size > 0 ? last_non_group_fns[size - 1] : NULL;
1376 const char *fname = last_fn ? last_fn->m_name : NULL;
1377 output_intermediate_json_line (lineso, &src->lines[line_num], line_num,
1378 fname);
1379
1380 /* Pop ending function from stack. */
1381 if (last_fn != NULL && last_fn->end_line == line_num)
1382 last_non_group_fns.pop_back ();
1383 }
fc8a650e
SS
1384 }
1385}
1386
136ca74e
ML
1387/* Function start pair. */
1388struct function_start
1389{
1390 unsigned source_file_idx;
1391 unsigned start_line;
1392};
1393
1394/* Traits class for function start hash maps below. */
1395
1396struct function_start_pair_hash : typed_noop_remove <function_start>
1397{
1398 typedef function_start value_type;
1399 typedef function_start compare_type;
1400
1401 static hashval_t
1402 hash (const function_start &ref)
1403 {
1404 inchash::hash hstate (0);
1405 hstate.add_int (ref.source_file_idx);
1406 hstate.add_int (ref.start_line);
1407 return hstate.end ();
1408 }
1409
1410 static bool
1411 equal (const function_start &ref1, const function_start &ref2)
1412 {
1413 return (ref1.source_file_idx == ref2.source_file_idx
1414 && ref1.start_line == ref2.start_line);
1415 }
1416
1417 static void
1418 mark_deleted (function_start &ref)
1419 {
1420 ref.start_line = ~1U;
1421 }
1422
7ca50de0
DM
1423 static const bool empty_zero_p = false;
1424
136ca74e
ML
1425 static void
1426 mark_empty (function_start &ref)
1427 {
1428 ref.start_line = ~2U;
1429 }
1430
1431 static bool
1432 is_deleted (const function_start &ref)
1433 {
1434 return ref.start_line == ~1U;
1435 }
1436
1437 static bool
1438 is_empty (const function_start &ref)
1439 {
1440 return ref.start_line == ~2U;
1441 }
1442};
1443
eeabee0a 1444/* Process a single input file. */
5735c3ea 1445
4977bab6 1446static void
f55ade6e 1447process_file (const char *file_name)
4977bab6 1448{
4977bab6 1449 create_file_names (file_name);
7a583153
ML
1450
1451 for (unsigned i = 0; i < processed_files.size (); i++)
1452 if (strcmp (da_file_name, processed_files[i]) == 0)
1453 {
1454 fnotice (stderr, "'%s' file is already processed\n",
1455 file_name);
1456 return;
1457 }
1458
1459 processed_files.push_back (xstrdup (da_file_name));
1460
211bea6b 1461 read_graph_file ();
211bea6b 1462 read_count_file ();
ca498a11
ML
1463}
1464
1465/* Process all functions in all files. */
136ca74e 1466
ca498a11
ML
1467static void
1468process_all_functions (void)
1469{
cb8758b2 1470 hash_map<function_start_pair_hash, function_info *> fn_map;
136ca74e
ML
1471
1472 /* Identify group functions. */
cb8758b2 1473 for (vector<function_info *>::iterator it = functions.begin ();
211bea6b
ML
1474 it != functions.end (); it++)
1475 if (!(*it)->artificial)
136ca74e
ML
1476 {
1477 function_start needle;
211bea6b
ML
1478 needle.source_file_idx = (*it)->src;
1479 needle.start_line = (*it)->start_line;
136ca74e 1480
cb8758b2 1481 function_info **slot = fn_map.get (needle);
136ca74e
ML
1482 if (slot)
1483 {
136ca74e 1484 (*slot)->is_group = 1;
211bea6b 1485 (*it)->is_group = 1;
136ca74e
ML
1486 }
1487 else
211bea6b 1488 fn_map.put (needle, *it);
136ca74e
ML
1489 }
1490
1e81a283
ML
1491 /* Remove all artificial function. */
1492 functions.erase (remove_if (functions.begin (), functions.end (),
1493 function_info::is_artificial), functions.end ());
1494
cb8758b2 1495 for (vector<function_info *>::iterator it = functions.begin ();
211bea6b 1496 it != functions.end (); it++)
4977bab6 1497 {
cb8758b2 1498 function_info *fn = *it;
1e81a283 1499 unsigned src = fn->src;
f55ade6e 1500
4464b977 1501 if (!fn->counts.empty () || no_data_file)
5366b186 1502 {
1e81a283 1503 source_info *s = &sources[src];
59688303 1504 s->add_function (fn);
1ce1b792 1505
1e81a283
ML
1506 /* Mark last line in files touched by function. */
1507 for (unsigned block_no = 0; block_no != fn->blocks.size ();
1508 block_no++)
1ce1b792 1509 {
bea002e9 1510 block_info *block = &fn->blocks[block_no];
1e81a283 1511 for (unsigned i = 0; i < block->locations.size (); i++)
136ca74e 1512 {
1e81a283
ML
1513 /* Sort lines of locations. */
1514 sort (block->locations[i].lines.begin (),
1515 block->locations[i].lines.end ());
1516
1517 if (!block->locations[i].lines.empty ())
0790260e 1518 {
1e81a283
ML
1519 s = &sources[block->locations[i].source_file_idx];
1520 unsigned last_line
1521 = block->locations[i].lines.back ();
136ca74e 1522
1e81a283
ML
1523 /* Record new lines for the function. */
1524 if (last_line >= s->lines.size ())
136ca74e
ML
1525 {
1526 s = &sources[block->locations[i].source_file_idx];
1527 unsigned last_line
1528 = block->locations[i].lines.back ();
1529
1530 /* Record new lines for the function. */
1531 if (last_line >= s->lines.size ())
1532 {
1533 /* Record new lines for a source file. */
1534 s->lines.resize (last_line + 1);
1535 }
1536 }
0790260e
ML
1537 }
1538 }
1ce1b792 1539 }
1e81a283
ML
1540
1541 /* Allocate lines for group function, following start_line
1542 and end_line information of the function. */
1543 if (fn->is_group)
1544 fn->lines.resize (fn->end_line - fn->start_line + 1);
1545
1e81a283
ML
1546 solve_flow_graph (fn);
1547 if (fn->has_catch)
1548 find_exception_blocks (fn);
5366b186
NS
1549 }
1550 else
211bea6b
ML
1551 {
1552 /* The function was not in the executable -- some other
1553 instance must have been selected. */
1554 }
5366b186 1555 }
1a9075e2
TG
1556}
1557
fc8a650e 1558static void
c7432e76 1559output_gcov_file (const char *file_name, source_info *src)
fc8a650e 1560{
b777f228
ML
1561 string gcov_file_name_str
1562 = make_gcov_file_name (file_name, src->coverage.name);
1563 const char *gcov_file_name = gcov_file_name_str.c_str ();
fc8a650e
SS
1564
1565 if (src->coverage.lines)
1566 {
1567 FILE *gcov_file = fopen (gcov_file_name, "w");
1568 if (gcov_file)
e89ce41d
ML
1569 {
1570 fnotice (stdout, "Creating '%s'\n", gcov_file_name);
1571 output_lines (gcov_file, src);
1572 if (ferror (gcov_file))
815f15d3
ML
1573 {
1574 fnotice (stderr, "Error writing output file '%s'\n",
1575 gcov_file_name);
1576 return_code = 6;
1577 }
e89ce41d
ML
1578 fclose (gcov_file);
1579 }
fc8a650e 1580 else
815f15d3
ML
1581 {
1582 fnotice (stderr, "Could not open output file '%s'\n", gcov_file_name);
1583 return_code = 6;
1584 }
fc8a650e
SS
1585 }
1586 else
1587 {
1588 unlink (gcov_file_name);
1589 fnotice (stdout, "Removing '%s'\n", gcov_file_name);
1590 }
fc8a650e
SS
1591}
1592
1a9075e2
TG
1593static void
1594generate_results (const char *file_name)
1595{
b777f228 1596 string gcov_intermediate_filename;
1a9075e2 1597
cb8758b2 1598 for (vector<function_info *>::iterator it = functions.begin ();
211bea6b 1599 it != functions.end (); it++)
4977bab6 1600 {
cb8758b2 1601 function_info *fn = *it;
a1b5dd18 1602 coverage_info coverage;
f55ade6e 1603
4977bab6 1604 memset (&coverage, 0, sizeof (coverage));
c8fda30f 1605 coverage.name = fn->get_name ();
4977bab6
ZW
1606 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
1607 if (flag_function_summary)
1608 {
e4b52fca 1609 function_summary (&coverage);
4977bab6
ZW
1610 fnotice (stdout, "\n");
1611 }
1612 }
f55ade6e 1613
8a3f457f 1614 name_map needle;
ab37baa6
ML
1615 needle.name = file_name;
1616 vector<name_map>::iterator it
1617 = std::find (names.begin (), names.end (), needle);
1618 if (it != names.end ())
1619 file_name = sources[it->src].coverage.name;
1620 else
1621 file_name = canonicalize_name (file_name);
fc8a650e 1622
c8fda30f
ML
1623 gcov_intermediate_filename = get_gcov_intermediate_filename (file_name);
1624
1625 json::object *root = new json::object ();
070944fd
DM
1626 root->set_string ("format_version", GCOV_JSON_FORMAT_VERSION);
1627 root->set_string ("gcc_version", version_string);
0ffa4bc2
ML
1628
1629 if (bbg_cwd != NULL)
070944fd
DM
1630 root->set_string ("current_working_directory", bbg_cwd);
1631 root->set_string ("data_file", file_name);
c8fda30f
ML
1632
1633 json::array *json_files = new json::array ();
1634 root->set ("files", json_files);
e89ce41d 1635
c7432e76
ML
1636 for (vector<source_info>::iterator it = sources.begin ();
1637 it != sources.end (); it++)
4977bab6 1638 {
c7432e76 1639 source_info *src = &(*it);
1bec9caa
NS
1640 if (flag_relative_only)
1641 {
1642 /* Ignore this source, if it is an absolute path (after
1643 source prefix removal). */
1644 char first = src->coverage.name[0];
176bf572 1645
1bec9caa
NS
1646#if HAVE_DOS_BASED_FILE_SYSTEM
1647 if (first && src->coverage.name[1] == ':')
fe860eb5 1648 first = src->coverage.name[2];
1bec9caa 1649#endif
fe860eb5
KT
1650 if (IS_DIR_SEPARATOR (first))
1651 continue;
1bec9caa 1652 }
176bf572 1653
4977bab6 1654 accumulate_line_counts (src);
b2230210
ML
1655 if (flag_debug)
1656 src->debug ();
feb4589d
ML
1657
1658 if (!flag_use_stdout)
e4b52fca 1659 file_summary (&src->coverage);
bdbdc4e1
NS
1660 total_lines += src->coverage.lines;
1661 total_executed += src->coverage.lines_executed;
8f961b22 1662 if (flag_gcov_file)
4977bab6 1663 {
c8fda30f 1664 if (flag_json_format)
ab37baa6
ML
1665 {
1666 output_json_intermediate_file (json_files, src);
1667 if (!flag_use_stdout)
1668 fnotice (stdout, "\n");
1669 }
e89ce41d 1670 else
feb4589d
ML
1671 {
1672 if (flag_use_stdout)
1673 {
1674 if (src->coverage.lines)
1675 output_lines (stdout, src);
1676 }
1677 else
1678 {
1679 output_gcov_file (file_name, src);
1680 fnotice (stdout, "\n");
1681 }
1682 }
e89ce41d
ML
1683 }
1684 }
1685
c8fda30f 1686 if (flag_gcov_file && flag_json_format)
e89ce41d 1687 {
c8fda30f
ML
1688 if (flag_use_stdout)
1689 {
3bd8241a 1690 root->dump (stdout, false);
c8fda30f
ML
1691 printf ("\n");
1692 }
1693 else
1694 {
1695 pretty_printer pp;
3bd8241a 1696 root->print (&pp, false);
c8fda30f
ML
1697 pp_formatted_text (&pp);
1698
b777f228
ML
1699 fnotice (stdout, "Creating '%s'\n",
1700 gcov_intermediate_filename.c_str ());
1701 gzFile output = gzopen (gcov_intermediate_filename.c_str (), "w");
c8fda30f
ML
1702 if (output == NULL)
1703 {
1704 fnotice (stderr, "Cannot open JSON output file %s\n",
b777f228 1705 gcov_intermediate_filename.c_str ());
815f15d3 1706 return_code = 6;
c8fda30f
ML
1707 return;
1708 }
1709
1710 if (gzputs (output, pp_formatted_text (&pp)) == EOF
1711 || gzclose (output))
1712 {
1713 fnotice (stderr, "Error writing JSON output file %s\n",
b777f228 1714 gcov_intermediate_filename.c_str ());
815f15d3 1715 return_code = 6;
c8fda30f
ML
1716 return;
1717 }
1718 }
fc8a650e 1719 }
86144b75
DE
1720}
1721
4977bab6 1722/* Release all memory used. */
86144b75 1723
4977bab6 1724static void
f55ade6e 1725release_structures (void)
4977bab6 1726{
cb8758b2 1727 for (vector<function_info *>::iterator it = functions.begin ();
211bea6b
ML
1728 it != functions.end (); it++)
1729 delete (*it);
f55ade6e 1730
e89ce41d
ML
1731 sources.resize (0);
1732 names.resize (0);
211bea6b 1733 functions.resize (0);
59688303 1734 ident_to_fn.clear ();
4977bab6
ZW
1735}
1736
15882fe9
TG
1737/* Generate the names of the graph and data files. If OBJECT_DIRECTORY
1738 is not specified, these are named from FILE_NAME sans extension. If
1739 OBJECT_DIRECTORY is specified and is a directory, the files are in that
1740 directory, but named from the basename of the FILE_NAME, sans extension.
1741 Otherwise OBJECT_DIRECTORY is taken to be the name of the object *file*
1742 and the data files are named from that. */
86144b75
DE
1743
1744static void
f55ade6e 1745create_file_names (const char *file_name)
86144b75 1746{
86144b75 1747 char *cptr;
37b8715b 1748 char *name;
4977bab6 1749 int length = strlen (file_name);
37b8715b 1750 int base;
f55ade6e 1751
1a9075e2 1752 /* Free previous file names. */
04695783
JM
1753 free (bbg_file_name);
1754 free (da_file_name);
1a9075e2
TG
1755 da_file_name = bbg_file_name = NULL;
1756 bbg_file_time = 0;
1757 bbg_stamp = 0;
1758
37b8715b 1759 if (object_directory && object_directory[0])
86144b75 1760 {
37b8715b
NS
1761 struct stat status;
1762
1763 length += strlen (object_directory) + 2;
5ed6ace5 1764 name = XNEWVEC (char, length);
37b8715b 1765 name[0] = 0;
f55ade6e 1766
37b8715b
NS
1767 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
1768 strcat (name, object_directory);
176bf572 1769 if (base && (!IS_DIR_SEPARATOR (name[strlen (name) - 1])))
37b8715b 1770 strcat (name, "/");
86144b75
DE
1771 }
1772 else
1773 {
5ed6ace5 1774 name = XNEWVEC (char, length + 1);
15882fe9
TG
1775 strcpy (name, file_name);
1776 base = 0;
86144b75 1777 }
f55ade6e 1778
37b8715b
NS
1779 if (base)
1780 {
f9da5064 1781 /* Append source file name. */
2f07423c
PO
1782 const char *cptr = lbasename (file_name);
1783 strcat (name, cptr ? cptr : file_name);
37b8715b 1784 }
f55ade6e 1785
4b7e68e7 1786 /* Remove the extension. */
258ef007 1787 cptr = strrchr (CONST_CAST (char *, lbasename (name)), '.');
86144b75 1788 if (cptr)
37b8715b 1789 *cptr = 0;
f55ade6e 1790
37b8715b 1791 length = strlen (name);
b8698a0f 1792
5ed6ace5 1793 bbg_file_name = XNEWVEC (char, length + strlen (GCOV_NOTE_SUFFIX) + 1);
4977bab6 1794 strcpy (bbg_file_name, name);
160e2e4f 1795 strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
37b8715b 1796
5ed6ace5 1797 da_file_name = XNEWVEC (char, length + strlen (GCOV_DATA_SUFFIX) + 1);
4977bab6
ZW
1798 strcpy (da_file_name, name);
1799 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
f55ade6e 1800
a14df7da 1801 free (name);
4977bab6 1802 return;
86144b75 1803}
86144b75 1804
94de45d9
NS
1805/* Find or create a source file structure for FILE_NAME. Copies
1806 FILE_NAME on creation */
27283c73 1807
1ce1b792 1808static unsigned
f55ade6e 1809find_source (const char *file_name)
27283c73 1810{
eeabee0a
NS
1811 char *canon;
1812 unsigned idx;
1a9075e2 1813 struct stat status;
94de45d9
NS
1814
1815 if (!file_name)
1816 file_name = "<unknown>";
f55ade6e 1817
8a3f457f
ML
1818 name_map needle;
1819 needle.name = file_name;
1820
1821 vector<name_map>::iterator it = std::find (names.begin (), names.end (),
1822 needle);
1823 if (it != names.end ())
1a9075e2 1824 {
8a3f457f
ML
1825 idx = it->src;
1826 goto check_date;
eeabee0a 1827 }
176bf572 1828
eeabee0a
NS
1829 /* Not found, try the canonical name. */
1830 canon = canonicalize_name (file_name);
8a3f457f
ML
1831 needle.name = canon;
1832 it = std::find (names.begin (), names.end (), needle);
1833 if (it == names.end ())
eeabee0a
NS
1834 {
1835 /* Not found with canonical name, create a new source. */
c7432e76 1836 source_info *src;
eeabee0a 1837
c7432e76 1838 idx = sources.size ();
8a3f457f
ML
1839 needle = name_map (canon, idx);
1840 names.push_back (needle);
eeabee0a 1841
c7432e76
ML
1842 sources.push_back (source_info ());
1843 src = &sources.back ();
eeabee0a 1844 src->name = canon;
1a9075e2 1845 src->coverage.name = src->name;
136ca74e 1846 src->index = idx;
1bec9caa
NS
1847 if (source_length
1848#if HAVE_DOS_BASED_FILE_SYSTEM
1849 /* You lose if separators don't match exactly in the
1850 prefix. */
1851 && !strncasecmp (source_prefix, src->coverage.name, source_length)
1852#else
1853 && !strncmp (source_prefix, src->coverage.name, source_length)
1854#endif
1855 && IS_DIR_SEPARATOR (src->coverage.name[source_length]))
1856 src->coverage.name += source_length + 1;
eeabee0a 1857 if (!stat (src->name, &status))
1a9075e2
TG
1858 src->file_time = status.st_mtime;
1859 }
eeabee0a 1860 else
8a3f457f 1861 idx = it->src;
eeabee0a 1862
8a3f457f
ML
1863 needle.name = file_name;
1864 if (std::find (names.begin (), names.end (), needle) == names.end ())
eeabee0a
NS
1865 {
1866 /* Append the non-canonical name. */
8a3f457f 1867 names.push_back (name_map (xstrdup (file_name), idx));
eeabee0a 1868 }
1a9075e2 1869
eeabee0a 1870 /* Resort the name map. */
8a3f457f 1871 std::sort (names.begin (), names.end ());
6e49961c 1872
eeabee0a
NS
1873 check_date:
1874 if (sources[idx].file_time > bbg_file_time)
1a9075e2
TG
1875 {
1876 static int info_emitted;
1877
efbb59b2 1878 fnotice (stderr, "%s:source file is newer than notes file '%s'\n",
eeabee0a 1879 file_name, bbg_file_name);
1a9075e2
TG
1880 if (!info_emitted)
1881 {
1882 fnotice (stderr,
7106478c 1883 "(the message is displayed only once per source file)\n");
1a9075e2
TG
1884 info_emitted = 1;
1885 }
eeabee0a 1886 sources[idx].file_time = 0;
1a9075e2 1887 }
94de45d9 1888
eeabee0a 1889 return idx;
27283c73
NS
1890}
1891
211bea6b 1892/* Read the notes file. Save functions to FUNCTIONS global vector. */
86144b75 1893
211bea6b 1894static void
f55ade6e 1895read_graph_file (void)
86144b75 1896{
94de45d9 1897 unsigned version;
4977bab6 1898 unsigned current_tag = 0;
7d63a2fa 1899 unsigned tag;
f55ade6e 1900
546d2adb 1901 if (!gcov_open (bbg_file_name, 1))
86144b75 1902 {
efbb59b2 1903 fnotice (stderr, "%s:cannot open notes file\n", bbg_file_name);
815f15d3 1904 return_code = 1;
211bea6b 1905 return;
86144b75 1906 }
546d2adb 1907 bbg_file_time = gcov_time ();
160e2e4f 1908 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
b7c9bf28 1909 {
efbb59b2 1910 fnotice (stderr, "%s:not a gcov notes file\n", bbg_file_name);
815f15d3 1911 return_code = 2;
546d2adb 1912 gcov_close ();
211bea6b 1913 return;
4977bab6 1914 }
b7c9bf28 1915
94de45d9
NS
1916 version = gcov_read_unsigned ();
1917 if (version != GCOV_VERSION)
4977bab6
ZW
1918 {
1919 char v[4], e[4];
f55ade6e 1920
330d2e2a
NS
1921 GCOV_UNSIGNED2STRING (v, version);
1922 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1923
9e637a26 1924 fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n",
4977bab6 1925 bbg_file_name, v, e);
815f15d3 1926 return_code = 3;
4977bab6 1927 }
dd486eb2 1928 bbg_stamp = gcov_read_unsigned ();
72e0c742
ML
1929 /* Read checksum. */
1930 gcov_read_unsigned ();
c74bd3fb 1931 bbg_cwd = xstrdup (gcov_read_string ());
93814e2d 1932 bbg_supports_has_unexecuted_blocks = gcov_read_unsigned ();
dd486eb2 1933
cb8758b2 1934 function_info *fn = NULL;
7d63a2fa 1935 while ((tag = gcov_read_unsigned ()))
4977bab6 1936 {
94de45d9 1937 unsigned length = gcov_read_unsigned ();
7d63a2fa 1938 gcov_position_t base = gcov_position ();
796621e8 1939
4977bab6 1940 if (tag == GCOV_TAG_FUNCTION)
b7c9bf28 1941 {
94de45d9 1942 char *function_name;
136ca74e 1943 unsigned ident;
10adac51 1944 unsigned lineno_checksum, cfg_checksum;
4977bab6 1945
796621e8 1946 ident = gcov_read_unsigned ();
10adac51
XDL
1947 lineno_checksum = gcov_read_unsigned ();
1948 cfg_checksum = gcov_read_unsigned ();
796621e8 1949 function_name = xstrdup (gcov_read_string ());
136ca74e 1950 unsigned artificial = gcov_read_unsigned ();
0790260e 1951 unsigned src_idx = find_source (gcov_read_string ());
136ca74e
ML
1952 unsigned start_line = gcov_read_unsigned ();
1953 unsigned start_column = gcov_read_unsigned ();
1954 unsigned end_line = gcov_read_unsigned ();
b8154717 1955 unsigned end_column = gcov_read_unsigned ();
f55ade6e 1956
cb8758b2 1957 fn = new function_info ();
211bea6b 1958 functions.push_back (fn);
59688303
ML
1959 ident_to_fn[ident] = fn;
1960
c8fda30f 1961 fn->m_name = function_name;
796621e8 1962 fn->ident = ident;
10adac51
XDL
1963 fn->lineno_checksum = lineno_checksum;
1964 fn->cfg_checksum = cfg_checksum;
1ce1b792 1965 fn->src = src_idx;
136ca74e
ML
1966 fn->start_line = start_line;
1967 fn->start_column = start_column;
1968 fn->end_line = end_line;
b8154717 1969 fn->end_column = end_column;
136ca74e 1970 fn->artificial = artificial;
4977bab6 1971
4977bab6 1972 current_tag = tag;
b7c9bf28 1973 }
4977bab6 1974 else if (fn && tag == GCOV_TAG_BLOCKS)
b7c9bf28 1975 {
0790260e 1976 if (!fn->blocks.empty ())
9e637a26 1977 fnotice (stderr, "%s:already seen blocks for '%s'\n",
c8fda30f 1978 bbg_file_name, fn->get_name ());
4977bab6 1979 else
0790260e 1980 fn->blocks.resize (gcov_read_unsigned ());
4977bab6
ZW
1981 }
1982 else if (fn && tag == GCOV_TAG_ARCS)
1983 {
94de45d9 1984 unsigned src = gcov_read_unsigned ();
9b9d6370 1985 fn->blocks[src].id = src;
330d2e2a 1986 unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
bea002e9 1987 block_info *src_blk = &fn->blocks[src];
8919c0d9
NS
1988 unsigned mark_catches = 0;
1989 struct arc_info *arc;
4977bab6 1990
0790260e 1991 if (src >= fn->blocks.size () || fn->blocks[src].succ)
4977bab6 1992 goto corrupt;
f55ade6e 1993
4977bab6 1994 while (num_dests--)
b7c9bf28 1995 {
94de45d9
NS
1996 unsigned dest = gcov_read_unsigned ();
1997 unsigned flags = gcov_read_unsigned ();
f55ade6e 1998
0790260e 1999 if (dest >= fn->blocks.size ())
4977bab6 2000 goto corrupt;
232c80f2 2001 arc = XCNEW (arc_info);
f55ade6e 2002
4977bab6 2003 arc->dst = &fn->blocks[dest];
b2230210
ML
2004 /* Set id in order to find EXIT_BLOCK. */
2005 arc->dst->id = dest;
8919c0d9 2006 arc->src = src_blk;
f55ade6e 2007
4977bab6
ZW
2008 arc->count = 0;
2009 arc->count_valid = 0;
2010 arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
2011 arc->fake = !!(flags & GCOV_ARC_FAKE);
2012 arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
f55ade6e 2013
8919c0d9
NS
2014 arc->succ_next = src_blk->succ;
2015 src_blk->succ = arc;
2016 src_blk->num_succ++;
f55ade6e 2017
4977bab6
ZW
2018 arc->pred_next = fn->blocks[dest].pred;
2019 fn->blocks[dest].pred = arc;
2020 fn->blocks[dest].num_pred++;
2021
27283c73
NS
2022 if (arc->fake)
2023 {
2024 if (src)
2025 {
2026 /* Exceptional exit from this function, the
2027 source block must be a call. */
2028 fn->blocks[src].is_call_site = 1;
2029 arc->is_call_non_return = 1;
8919c0d9 2030 mark_catches = 1;
27283c73
NS
2031 }
2032 else
2033 {
2034 /* Non-local return from a callee of this
176bf572 2035 function. The destination block is a setjmp. */
27283c73
NS
2036 arc->is_nonlocal_return = 1;
2037 fn->blocks[dest].is_nonlocal_return = 1;
2038 }
2039 }
f55ade6e 2040
4977bab6 2041 if (!arc->on_tree)
4464b977 2042 fn->counts.push_back (0);
b7c9bf28 2043 }
176bf572 2044
8919c0d9
NS
2045 if (mark_catches)
2046 {
2047 /* We have a fake exit from this block. The other
2048 non-fall through exits must be to catch handlers.
2049 Mark them as catch arcs. */
2050
2051 for (arc = src_blk->succ; arc; arc = arc->succ_next)
2052 if (!arc->fake && !arc->fall_through)
2053 {
2054 arc->is_throw = 1;
2055 fn->has_catch = 1;
2056 }
2057 }
4977bab6 2058 }
08a52331
JK
2059 else if (fn && tag == GCOV_TAG_CONDS)
2060 {
2061 unsigned num_dests = GCOV_TAG_CONDS_NUM (length);
2062
2063 if (!fn->conditions.empty ())
2064 fnotice (stderr, "%s:already seen conditions for '%s'\n",
2065 bbg_file_name, fn->get_name ());
2066 else
2067 fn->conditions.resize (num_dests);
2068
2069 for (unsigned i = 0; i < num_dests; ++i)
2070 {
2071 unsigned idx = gcov_read_unsigned ();
2072
2073 if (idx >= fn->blocks.size ())
2074 goto corrupt;
2075
2076 condition_info *info = &fn->blocks[idx].conditions;
2077 info->n_terms = gcov_read_unsigned ();
2078 fn->conditions[i] = info;
2079 }
2080 }
4977bab6
ZW
2081 else if (fn && tag == GCOV_TAG_LINES)
2082 {
94de45d9 2083 unsigned blockno = gcov_read_unsigned ();
bea002e9 2084 block_info *block = &fn->blocks[blockno];
4977bab6 2085
0790260e 2086 if (blockno >= fn->blocks.size ())
4977bab6 2087 goto corrupt;
f55ade6e 2088
0790260e 2089 while (true)
b7c9bf28 2090 {
94de45d9 2091 unsigned lineno = gcov_read_unsigned ();
f55ade6e 2092
4977bab6 2093 if (lineno)
0790260e 2094 block->locations.back ().lines.push_back (lineno);
4977bab6
ZW
2095 else
2096 {
94de45d9 2097 const char *file_name = gcov_read_string ();
f55ade6e 2098
4977bab6 2099 if (!file_name)
b7c9bf28 2100 break;
0790260e
ML
2101 block->locations.push_back (block_location_info
2102 (find_source (file_name)));
4977bab6 2103 }
b7c9bf28 2104 }
4977bab6
ZW
2105 }
2106 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
2107 {
2108 fn = NULL;
2109 current_tag = 0;
2110 }
474f141e 2111 gcov_sync (base, length);
94de45d9 2112 if (gcov_is_error ())
00cf2913
NS
2113 {
2114 corrupt:;
2115 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
815f15d3 2116 return_code = 4;
1ce1b792 2117 break;
00cf2913 2118 }
b7c9bf28 2119 }
546d2adb 2120 gcov_close ();
f55ade6e 2121
211bea6b 2122 if (functions.empty ())
1ce1b792 2123 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
b7c9bf28 2124}
86144b75 2125
4977bab6 2126/* Reads profiles from the count file and attach to each
272d0bee 2127 function. Return nonzero if fatal error. */
86144b75 2128
4977bab6 2129static int
211bea6b 2130read_count_file (void)
86144b75 2131{
4977bab6 2132 unsigned ix;
94de45d9 2133 unsigned version;
7d63a2fa 2134 unsigned tag;
cb8758b2 2135 function_info *fn = NULL;
7d63a2fa 2136 int error = 0;
59688303 2137 map<unsigned, function_info *>::iterator it;
4977bab6 2138
546d2adb 2139 if (!gcov_open (da_file_name, 1))
86144b75 2140 {
80b3502b
NS
2141 fnotice (stderr, "%s:cannot open data file, assuming not executed\n",
2142 da_file_name);
2143 no_data_file = 1;
2144 return 0;
4977bab6 2145 }
160e2e4f 2146 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
4977bab6
ZW
2147 {
2148 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
815f15d3 2149 return_code = 2;
4977bab6 2150 cleanup:;
546d2adb 2151 gcov_close ();
4977bab6
ZW
2152 return 1;
2153 }
94de45d9
NS
2154 version = gcov_read_unsigned ();
2155 if (version != GCOV_VERSION)
4977bab6 2156 {
330d2e2a
NS
2157 char v[4], e[4];
2158
2159 GCOV_UNSIGNED2STRING (v, version);
2160 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
b8698a0f 2161
9e637a26 2162 fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
330d2e2a 2163 da_file_name, v, e);
815f15d3 2164 return_code = 3;
86144b75 2165 }
dd486eb2
NS
2166 tag = gcov_read_unsigned ();
2167 if (tag != bbg_stamp)
2168 {
efbb59b2 2169 fnotice (stderr, "%s:stamp mismatch with notes file\n", da_file_name);
815f15d3 2170 return_code = 5;
dd486eb2
NS
2171 goto cleanup;
2172 }
f55ade6e 2173
72e0c742
ML
2174 /* Read checksum. */
2175 gcov_read_unsigned ();
2176
7d63a2fa 2177 while ((tag = gcov_read_unsigned ()))
4977bab6 2178 {
94de45d9 2179 unsigned length = gcov_read_unsigned ();
9067a154 2180 int read_length = (int)length;
94de45d9 2181 unsigned long base = gcov_position ();
94de45d9 2182
512cc015 2183 if (tag == GCOV_TAG_OBJECT_SUMMARY)
86144b75 2184 {
5366b186
NS
2185 struct gcov_summary summary;
2186 gcov_read_summary (&summary);
512cc015 2187 object_runs = summary.runs;
5366b186
NS
2188 }
2189 else if (tag == GCOV_TAG_FUNCTION && !length)
2190 ; /* placeholder */
2191 else if (tag == GCOV_TAG_FUNCTION && length == GCOV_TAG_FUNCTION_LENGTH)
2192 {
2193 unsigned ident;
5366b186 2194 ident = gcov_read_unsigned ();
211bea6b 2195 fn = NULL;
59688303
ML
2196 it = ident_to_fn.find (ident);
2197 if (it != ident_to_fn.end ())
2198 fn = it->second;
4977bab6
ZW
2199
2200 if (!fn)
2201 ;
10adac51
XDL
2202 else if (gcov_read_unsigned () != fn->lineno_checksum
2203 || gcov_read_unsigned () != fn->cfg_checksum)
86144b75 2204 {
4977bab6 2205 mismatch:;
9e637a26 2206 fnotice (stderr, "%s:profile mismatch for '%s'\n",
c8fda30f 2207 da_file_name, fn->get_name ());
4977bab6
ZW
2208 goto cleanup;
2209 }
2210 }
08a52331
JK
2211 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_CONDS) && fn)
2212 {
2213 length = abs (read_length);
2214 if (length != GCOV_TAG_COUNTER_LENGTH (2 * fn->conditions.size ()))
2215 goto mismatch;
2216
2217 if (read_length > 0)
2218 {
2219 for (ix = 0; ix != fn->conditions.size (); ix++)
2220 {
2221 fn->conditions[ix]->truev |= gcov_read_counter ();
2222 fn->conditions[ix]->falsev |= gcov_read_counter ();
2223 }
2224 }
2225 }
cdb23767 2226 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
4977bab6 2227 {
ece21ff6 2228 length = abs (read_length);
4464b977 2229 if (length != GCOV_TAG_COUNTER_LENGTH (fn->counts.size ()))
4977bab6 2230 goto mismatch;
f55ade6e 2231
ece21ff6
ML
2232 if (read_length > 0)
2233 for (ix = 0; ix != fn->counts.size (); ix++)
2234 fn->counts[ix] += gcov_read_counter ();
94de45d9 2235 }
9067a154
ML
2236 if (read_length < 0)
2237 read_length = 0;
2238 gcov_sync (base, read_length);
94de45d9 2239 if ((error = gcov_is_error ()))
00cf2913 2240 {
324ff1a0
JJ
2241 fnotice (stderr,
2242 error < 0
2243 ? N_("%s:overflowed\n")
2244 : N_("%s:corrupted\n"),
00cf2913 2245 da_file_name);
815f15d3 2246 return_code = 4;
00cf2913
NS
2247 goto cleanup;
2248 }
7d63a2fa 2249 }
f55ade6e 2250
546d2adb 2251 gcov_close ();
4977bab6 2252 return 0;
86144b75
DE
2253}
2254
4977bab6
ZW
2255/* Solve the flow graph. Propagate counts from the instrumented arcs
2256 to the blocks and the uninstrumented arcs. */
86144b75
DE
2257
2258static void
cb8758b2 2259solve_flow_graph (function_info *fn)
86144b75 2260{
4977bab6 2261 unsigned ix;
232c80f2 2262 arc_info *arc;
4464b977 2263 gcov_type *count_ptr = &fn->counts.front ();
bea002e9
ML
2264 block_info *blk;
2265 block_info *valid_blocks = NULL; /* valid, but unpropagated blocks. */
2266 block_info *invalid_blocks = NULL; /* invalid, but inferable blocks. */
f55ade6e 2267
1ce1b792 2268 /* The arcs were built in reverse order. Fix that now. */
0790260e 2269 for (ix = fn->blocks.size (); ix--;)
1ce1b792 2270 {
232c80f2 2271 arc_info *arc_p, *arc_n;
1ce1b792
NS
2272
2273 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
2274 arc_p = arc, arc = arc_n)
2275 {
2276 arc_n = arc->succ_next;
2277 arc->succ_next = arc_p;
2278 }
2279 fn->blocks[ix].succ = arc_p;
2280
2281 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
2282 arc_p = arc, arc = arc_n)
2283 {
2284 arc_n = arc->pred_next;
2285 arc->pred_next = arc_p;
2286 }
2287 fn->blocks[ix].pred = arc_p;
2288 }
2289
0790260e 2290 if (fn->blocks.size () < 2)
9e637a26 2291 fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n",
c8fda30f 2292 bbg_file_name, fn->get_name ());
4977bab6 2293 else
86144b75 2294 {
9696c529 2295 if (fn->blocks[ENTRY_BLOCK].num_pred)
9e637a26 2296 fnotice (stderr, "%s:'%s' has arcs to entry block\n",
c8fda30f 2297 bbg_file_name, fn->get_name ());
86144b75 2298 else
4977bab6
ZW
2299 /* We can't deduce the entry block counts from the lack of
2300 predecessors. */
9696c529 2301 fn->blocks[ENTRY_BLOCK].num_pred = ~(unsigned)0;
f55ade6e 2302
9696c529 2303 if (fn->blocks[EXIT_BLOCK].num_succ)
9e637a26 2304 fnotice (stderr, "%s:'%s' has arcs from exit block\n",
c8fda30f 2305 bbg_file_name, fn->get_name ());
4977bab6
ZW
2306 else
2307 /* Likewise, we can't deduce exit block counts from the lack
2308 of its successors. */
9696c529 2309 fn->blocks[EXIT_BLOCK].num_succ = ~(unsigned)0;
86144b75
DE
2310 }
2311
4977bab6 2312 /* Propagate the measured counts, this must be done in the same
e53b6e56 2313 order as the code in profile.cc */
0790260e 2314 for (unsigned i = 0; i < fn->blocks.size (); i++)
86144b75 2315 {
0790260e 2316 blk = &fn->blocks[i];
bea002e9 2317 block_info const *prev_dst = NULL;
4977bab6 2318 int out_of_order = 0;
27283c73 2319 int non_fake_succ = 0;
f55ade6e 2320
27283c73 2321 for (arc = blk->succ; arc; arc = arc->succ_next)
86144b75 2322 {
27283c73
NS
2323 if (!arc->fake)
2324 non_fake_succ++;
f55ade6e 2325
4977bab6 2326 if (!arc->on_tree)
86144b75 2327 {
4977bab6
ZW
2328 if (count_ptr)
2329 arc->count = *count_ptr++;
2330 arc->count_valid = 1;
27283c73 2331 blk->num_succ--;
4977bab6 2332 arc->dst->num_pred--;
86144b75 2333 }
4977bab6
ZW
2334 if (prev_dst && prev_dst > arc->dst)
2335 out_of_order = 1;
2336 prev_dst = arc->dst;
86144b75 2337 }
27283c73
NS
2338 if (non_fake_succ == 1)
2339 {
2340 /* If there is only one non-fake exit, it is an
2341 unconditional branch. */
2342 for (arc = blk->succ; arc; arc = arc->succ_next)
2343 if (!arc->fake)
2344 {
2345 arc->is_unconditional = 1;
2346 /* If this block is instrumenting a call, it might be
e0bb17a8 2347 an artificial block. It is not artificial if it has
10b7602f
NS
2348 a non-fallthrough exit, or the destination of this
2349 arc has more than one entry. Mark the destination
2350 block as a return site, if none of those conditions
2351 hold. */
2352 if (blk->is_call_site && arc->fall_through
2353 && arc->dst->pred == arc && !arc->pred_next)
2354 arc->dst->is_call_return = 1;
27283c73
NS
2355 }
2356 }
f55ade6e 2357
e53b6e56 2358 /* Sort the successor arcs into ascending dst order. profile.cc
4977bab6
ZW
2359 normally produces arcs in the right order, but sometimes with
2360 one or two out of order. We're not using a particularly
32dd366d 2361 smart sort. */
4977bab6 2362 if (out_of_order)
86144b75 2363 {
232c80f2 2364 arc_info *start = blk->succ;
4977bab6 2365 unsigned changes = 1;
f55ade6e 2366
4977bab6
ZW
2367 while (changes)
2368 {
232c80f2 2369 arc_info *arc, *arc_p, *arc_n;
f55ade6e 2370
4977bab6
ZW
2371 changes = 0;
2372 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
2373 {
2374 if (arc->dst > arc_n->dst)
2375 {
2376 changes = 1;
2377 if (arc_p)
2378 arc_p->succ_next = arc_n;
2379 else
2380 start = arc_n;
2381 arc->succ_next = arc_n->succ_next;
2382 arc_n->succ_next = arc;
2383 arc_p = arc_n;
2384 }
2385 else
2386 {
2387 arc_p = arc;
2388 arc = arc_n;
2389 }
2390 }
2391 }
27283c73 2392 blk->succ = start;
86144b75 2393 }
f55ade6e 2394
4977bab6
ZW
2395 /* Place it on the invalid chain, it will be ignored if that's
2396 wrong. */
27283c73
NS
2397 blk->invalid_chain = 1;
2398 blk->chain = invalid_blocks;
2399 invalid_blocks = blk;
4977bab6
ZW
2400 }
2401
2402 while (invalid_blocks || valid_blocks)
2403 {
4977bab6 2404 while ((blk = invalid_blocks))
86144b75 2405 {
4977bab6 2406 gcov_type total = 0;
232c80f2 2407 const arc_info *arc;
f55ade6e 2408
4977bab6
ZW
2409 invalid_blocks = blk->chain;
2410 blk->invalid_chain = 0;
2411 if (!blk->num_succ)
2412 for (arc = blk->succ; arc; arc = arc->succ_next)
2413 total += arc->count;
2414 else if (!blk->num_pred)
2415 for (arc = blk->pred; arc; arc = arc->pred_next)
2416 total += arc->count;
2417 else
2418 continue;
f55ade6e 2419
4977bab6
ZW
2420 blk->count = total;
2421 blk->count_valid = 1;
2422 blk->chain = valid_blocks;
2423 blk->valid_chain = 1;
2424 valid_blocks = blk;
86144b75 2425 }
4977bab6 2426 while ((blk = valid_blocks))
86144b75 2427 {
4977bab6 2428 gcov_type total;
232c80f2 2429 arc_info *arc, *inv_arc;
4977bab6
ZW
2430
2431 valid_blocks = blk->chain;
2432 blk->valid_chain = 0;
2433 if (blk->num_succ == 1)
2434 {
bea002e9 2435 block_info *dst;
f55ade6e 2436
4977bab6
ZW
2437 total = blk->count;
2438 inv_arc = NULL;
2439 for (arc = blk->succ; arc; arc = arc->succ_next)
2440 {
2441 total -= arc->count;
2442 if (!arc->count_valid)
2443 inv_arc = arc;
2444 }
2445 dst = inv_arc->dst;
2446 inv_arc->count_valid = 1;
2447 inv_arc->count = total;
2448 blk->num_succ--;
2449 dst->num_pred--;
2450 if (dst->count_valid)
2451 {
2452 if (dst->num_pred == 1 && !dst->valid_chain)
2453 {
2454 dst->chain = valid_blocks;
2455 dst->valid_chain = 1;
2456 valid_blocks = dst;
2457 }
2458 }
2459 else
2460 {
2461 if (!dst->num_pred && !dst->invalid_chain)
2462 {
2463 dst->chain = invalid_blocks;
2464 dst->invalid_chain = 1;
2465 invalid_blocks = dst;
2466 }
2467 }
2468 }
2469 if (blk->num_pred == 1)
2470 {
bea002e9 2471 block_info *src;
f55ade6e 2472
4977bab6
ZW
2473 total = blk->count;
2474 inv_arc = NULL;
2475 for (arc = blk->pred; arc; arc = arc->pred_next)
2476 {
2477 total -= arc->count;
2478 if (!arc->count_valid)
2479 inv_arc = arc;
2480 }
2481 src = inv_arc->src;
2482 inv_arc->count_valid = 1;
2483 inv_arc->count = total;
2484 blk->num_pred--;
2485 src->num_succ--;
2486 if (src->count_valid)
2487 {
2488 if (src->num_succ == 1 && !src->valid_chain)
2489 {
2490 src->chain = valid_blocks;
2491 src->valid_chain = 1;
2492 valid_blocks = src;
2493 }
2494 }
2495 else
2496 {
2497 if (!src->num_succ && !src->invalid_chain)
2498 {
2499 src->chain = invalid_blocks;
2500 src->invalid_chain = 1;
2501 invalid_blocks = src;
2502 }
2503 }
2504 }
86144b75
DE
2505 }
2506 }
f55ade6e 2507
4977bab6
ZW
2508 /* If the graph has been correctly solved, every block will have a
2509 valid count. */
0790260e
ML
2510 for (unsigned i = 0; ix < fn->blocks.size (); i++)
2511 if (!fn->blocks[i].count_valid)
4977bab6 2512 {
9e637a26 2513 fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
c8fda30f 2514 bbg_file_name, fn->get_name ());
4977bab6
ZW
2515 break;
2516 }
86144b75 2517}
4977bab6 2518
8919c0d9
NS
2519/* Mark all the blocks only reachable via an incoming catch. */
2520
2521static void
cb8758b2 2522find_exception_blocks (function_info *fn)
8919c0d9
NS
2523{
2524 unsigned ix;
bea002e9 2525 block_info **queue = XALLOCAVEC (block_info *, fn->blocks.size ());
8919c0d9
NS
2526
2527 /* First mark all blocks as exceptional. */
0790260e 2528 for (ix = fn->blocks.size (); ix--;)
8919c0d9
NS
2529 fn->blocks[ix].exceptional = 1;
2530
2531 /* Now mark all the blocks reachable via non-fake edges */
0790260e 2532 queue[0] = &fn->blocks[0];
8919c0d9
NS
2533 queue[0]->exceptional = 0;
2534 for (ix = 1; ix;)
2535 {
bea002e9 2536 block_info *block = queue[--ix];
232c80f2 2537 const arc_info *arc;
176bf572 2538
8919c0d9
NS
2539 for (arc = block->succ; arc; arc = arc->succ_next)
2540 if (!arc->fake && !arc->is_throw && arc->dst->exceptional)
2541 {
2542 arc->dst->exceptional = 0;
2543 queue[ix++] = arc->dst;
2544 }
2545 }
2546}
86144b75 2547\f
86144b75 2548
4977bab6 2549/* Increment totals in COVERAGE according to arc ARC. */
8b219a76
NS
2550
2551static void
a1b5dd18 2552add_branch_counts (coverage_info *coverage, const arc_info *arc)
8b219a76 2553{
27283c73 2554 if (arc->is_call_non_return)
8b219a76 2555 {
4977bab6
ZW
2556 coverage->calls++;
2557 if (arc->src->count)
2558 coverage->calls_executed++;
8b219a76 2559 }
27283c73 2560 else if (!arc->is_unconditional)
8b219a76 2561 {
4977bab6
ZW
2562 coverage->branches++;
2563 if (arc->src->count)
2564 coverage->branches_executed++;
2565 if (arc->count)
2566 coverage->branches_taken++;
86144b75
DE
2567 }
2568}
2569
64aa48ce 2570/* Increment totals in COVERAGE according to block BLOCK. */
08a52331
JK
2571
2572static void
2573add_condition_counts (coverage_info *coverage, const block_info *block)
2574{
2575 coverage->conditions += 2 * block->conditions.n_terms;
2576 coverage->conditions_covered += block->conditions.popcount ();
2577}
2578
29a4ef18
ML
2579/* Format COUNT, if flag_human_readable_numbers is set, return it human
2580 readable format. */
2581
2582static char const *
2583format_count (gcov_type count)
2584{
2585 static char buffer[64];
2586 const char *units = " kMGTPEZY";
2587
2588 if (count < 1000 || !flag_human_readable_numbers)
2589 {
2590 sprintf (buffer, "%" PRId64, count);
2591 return buffer;
2592 }
2593
2594 unsigned i;
2595 gcov_type divisor = 1;
2596 for (i = 0; units[i+1]; i++, divisor *= 1000)
2597 {
2598 if (count + divisor / 2 < 1000 * divisor)
2599 break;
2600 }
d1c772b9
ML
2601 float r = 1.0f * count / divisor;
2602 sprintf (buffer, "%.1f%c", r, units[i]);
29a4ef18
ML
2603 return buffer;
2604}
2605
9696c529 2606/* Format a GCOV_TYPE integer as either a percent ratio, or absolute
977667e6
ML
2607 count. If DECIMAL_PLACES >= 0, format TOP/BOTTOM * 100 to DECIMAL_PLACES.
2608 If DECIMAL_PLACES is zero, no decimal point is printed. Only print 100% when
2609 TOP==BOTTOM and only print 0% when TOP=0. If DECIMAL_PLACES < 0, then simply
37b8715b
NS
2610 format TOP. Return pointer to a static string. */
2611
2612static char const *
977667e6 2613format_gcov (gcov_type top, gcov_type bottom, int decimal_places)
37b8715b
NS
2614{
2615 static char buffer[20];
f55ade6e 2616
977667e6 2617 if (decimal_places >= 0)
07ea19a7 2618 {
977667e6 2619 float ratio = bottom ? 100.0f * top / bottom: 0;
07ea19a7 2620
977667e6
ML
2621 /* Round up to 1% if there's a small non-zero value. */
2622 if (ratio > 0.0f && ratio < 0.5f && decimal_places == 0)
2623 ratio = 1.0f;
2624 sprintf (buffer, "%.*f%%", decimal_places, ratio);
37b8715b
NS
2625 }
2626 else
29a4ef18 2627 return format_count (top);
f55ade6e 2628
37b8715b
NS
2629 return buffer;
2630}
2631
bdbdc4e1 2632/* Summary of execution */
86144b75
DE
2633
2634static void
bdbdc4e1 2635executed_summary (unsigned lines, unsigned executed)
86144b75 2636{
bdbdc4e1 2637 if (lines)
4977bab6 2638 fnotice (stdout, "Lines executed:%s of %d\n",
bdbdc4e1 2639 format_gcov (executed, lines, 2), lines);
86144b75 2640 else
1457ebf9 2641 fnotice (stdout, "No executable lines\n");
bdbdc4e1 2642}
176bf572 2643
e4b52fca 2644/* Output summary info for a function. */
bdbdc4e1
NS
2645
2646static void
e4b52fca 2647function_summary (const coverage_info *coverage)
bdbdc4e1 2648{
e4b52fca
ML
2649 fnotice (stdout, "%s '%s'\n", "Function", coverage->name);
2650 executed_summary (coverage->lines, coverage->lines_executed);
2651}
2652
2653/* Output summary info for a file. */
2654
2655static void
2656file_summary (const coverage_info *coverage)
2657{
2658 fnotice (stdout, "%s '%s'\n", "File", coverage->name);
bdbdc4e1 2659 executed_summary (coverage->lines, coverage->lines_executed);
86144b75 2660
4977bab6 2661 if (flag_branches)
86144b75 2662 {
4977bab6 2663 if (coverage->branches)
86144b75 2664 {
4977bab6
ZW
2665 fnotice (stdout, "Branches executed:%s of %d\n",
2666 format_gcov (coverage->branches_executed,
2667 coverage->branches, 2),
2668 coverage->branches);
2669 fnotice (stdout, "Taken at least once:%s of %d\n",
2670 format_gcov (coverage->branches_taken,
2671 coverage->branches, 2),
2672 coverage->branches);
86144b75
DE
2673 }
2674 else
4977bab6
ZW
2675 fnotice (stdout, "No branches\n");
2676 if (coverage->calls)
2677 fnotice (stdout, "Calls executed:%s of %d\n",
2678 format_gcov (coverage->calls_executed, coverage->calls, 2),
2679 coverage->calls);
86144b75 2680 else
4977bab6 2681 fnotice (stdout, "No calls\n");
08a52331
JK
2682
2683 }
2684
2685 if (flag_conditions)
2686 {
2687 if (coverage->conditions)
2688 fnotice (stdout, "Condition outcomes covered:%s of %d\n",
2689 format_gcov (coverage->conditions_covered,
2690 coverage->conditions, 2),
2691 coverage->conditions);
2692 else
2693 fnotice (stdout, "No conditions\n");
8b219a76
NS
2694 }
2695}
2696
eeabee0a
NS
2697/* Canonicalize the filename NAME by canonicalizing directory
2698 separators, eliding . components and resolving .. components
2699 appropriately. Always returns a unique string. */
2700
2701static char *
2702canonicalize_name (const char *name)
2703{
2704 /* The canonical name cannot be longer than the incoming name. */
2705 char *result = XNEWVEC (char, strlen (name) + 1);
2706 const char *base = name, *probe;
2707 char *ptr = result;
2708 char *dd_base;
2709 int slash = 0;
2710
2711#if HAVE_DOS_BASED_FILE_SYSTEM
2712 if (base[0] && base[1] == ':')
2713 {
2714 result[0] = base[0];
2715 result[1] = ':';
2716 base += 2;
2717 ptr += 2;
2718 }
2719#endif
2720 for (dd_base = ptr; *base; base = probe)
2721 {
2722 size_t len;
176bf572 2723
eeabee0a
NS
2724 for (probe = base; *probe; probe++)
2725 if (IS_DIR_SEPARATOR (*probe))
2726 break;
2727
2728 len = probe - base;
2729 if (len == 1 && base[0] == '.')
2730 /* Elide a '.' directory */
2731 ;
2732 else if (len == 2 && base[0] == '.' && base[1] == '.')
2733 {
2734 /* '..', we can only elide it and the previous directory, if
2735 we're not a symlink. */
8c121ccb
NS
2736 struct stat ATTRIBUTE_UNUSED buf;
2737
eeabee0a 2738 *ptr = 0;
8c121ccb
NS
2739 if (dd_base == ptr
2740#if defined (S_ISLNK)
2741 /* S_ISLNK is not POSIX.1-1996. */
2742 || stat (result, &buf) || S_ISLNK (buf.st_mode)
2743#endif
176bf572 2744 )
eeabee0a
NS
2745 {
2746 /* Cannot elide, or unreadable or a symlink. */
2747 dd_base = ptr + 2 + slash;
2748 goto regular;
2749 }
2750 while (ptr != dd_base && *ptr != '/')
2751 ptr--;
2752 slash = ptr != result;
2753 }
2754 else
2755 {
2756 regular:
2757 /* Regular pathname component. */
2758 if (slash)
2759 *ptr++ = '/';
2760 memcpy (ptr, base, len);
2761 ptr += len;
2762 slash = 1;
2763 }
2764
2765 for (; IS_DIR_SEPARATOR (*probe); probe++)
2766 continue;
2767 }
2768 *ptr = 0;
2769
2770 return result;
2771}
2772
2773/* Generate an output file name. INPUT_NAME is the canonicalized main
2774 input file and SRC_NAME is the canonicalized file name.
2775 LONG_OUTPUT_NAMES and PRESERVE_PATHS affect name generation. With
8b219a76
NS
2776 long_output_names we prepend the processed name of the input file
2777 to each output name (except when the current source file is the
2778 input file, so you don't get a double concatenation). The two
eeabee0a
NS
2779 components are separated by '##'. With preserve_paths we create a
2780 filename from all path components of the source file, replacing '/'
2781 with '#', and .. with '^', without it we simply take the basename
2782 component. (Remember, the canonicalized name will already have
2783 elided '.' components and converted \\ separators.) */
8b219a76 2784
b777f228 2785static string
f55ade6e 2786make_gcov_file_name (const char *input_name, const char *src_name)
8b219a76 2787{
b777f228 2788 string str;
176bf572 2789
75cc66f2
ML
2790 /* When hashing filenames, we shorten them by only using the filename
2791 component and appending a hash of the full (mangled) pathname. */
2792 if (flag_hash_filenames)
b777f228
ML
2793 str = (string (mangle_name (src_name)) + "##"
2794 + get_md5sum (src_name) + ".gcov");
2795 else
75cc66f2 2796 {
b777f228
ML
2797 if (flag_long_names && input_name && strcmp (src_name, input_name) != 0)
2798 {
2799 str += mangle_name (input_name);
2800 str += "##";
2801 }
2802
2803 str += mangle_name (src_name);
2804 str += ".gcov";
75cc66f2
ML
2805 }
2806
b777f228 2807 return str;
eeabee0a 2808}
f55ade6e 2809
12502bf2
ML
2810/* Mangle BASE name, copy it at the beginning of PTR buffer and
2811 return address of the \0 character of the buffer. */
2812
eeabee0a 2813static char *
b777f228 2814mangle_name (char const *base)
eeabee0a 2815{
eeabee0a
NS
2816 /* Generate the source filename part. */
2817 if (!flag_preserve_paths)
b777f228 2818 return xstrdup (lbasename (base));
eeabee0a 2819 else
b777f228 2820 return mangle_path (base);
86144b75
DE
2821}
2822
4977bab6 2823/* Scan through the bb_data for each line in the block, increment
8b219a76
NS
2824 the line number execution count indicated by the execution count of
2825 the appropriate basic block. */
86144b75
DE
2826
2827static void
a1b5dd18 2828add_line_counts (coverage_info *coverage, function_info *fn)
86144b75 2829{
6e49961c 2830 bool has_any_line = false;
32dd366d 2831 /* Scan each basic block. */
6e49961c 2832 for (unsigned ix = 0; ix != fn->blocks.size (); ix++)
86144b75 2833 {
4695d816 2834 line_info *line = NULL;
bea002e9 2835 block_info *block = &fn->blocks[ix];
0790260e 2836 if (block->count && ix && ix + 1 != fn->blocks.size ())
27283c73 2837 fn->blocks_executed++;
0790260e
ML
2838 for (unsigned i = 0; i < block->locations.size (); i++)
2839 {
136ca74e 2840 unsigned src_idx = block->locations[i].source_file_idx;
0790260e 2841 vector<unsigned> &lines = block->locations[i].lines;
136ca74e
ML
2842
2843 block->cycle.arc = NULL;
2844 block->cycle.ident = ~0U;
2845
0790260e
ML
2846 for (unsigned j = 0; j < lines.size (); j++)
2847 {
136ca74e
ML
2848 unsigned ln = lines[j];
2849
2850 /* Line belongs to a function that is in a group. */
2851 if (fn->group_line_p (ln, src_idx))
0790260e 2852 {
136ca74e
ML
2853 gcc_assert (lines[j] - fn->start_line < fn->lines.size ());
2854 line = &(fn->lines[lines[j] - fn->start_line]);
42301c02
ML
2855 if (coverage)
2856 {
2857 if (!line->exists)
2858 coverage->lines++;
2859 if (!line->count && block->count)
2860 coverage->lines_executed++;
2861 }
136ca74e
ML
2862 line->exists = 1;
2863 if (!block->exceptional)
2864 {
2865 line->unexceptional = 1;
2866 if (block->count == 0)
2867 line->has_unexecuted_block = 1;
2868 }
2869 line->count += block->count;
0790260e 2870 }
136ca74e 2871 else
cdb07de7 2872 {
136ca74e
ML
2873 gcc_assert (ln < sources[src_idx].lines.size ());
2874 line = &(sources[src_idx].lines[ln]);
2875 if (coverage)
2876 {
2877 if (!line->exists)
2878 coverage->lines++;
2879 if (!line->count && block->count)
2880 coverage->lines_executed++;
2881 }
2882 line->exists = 1;
2883 if (!block->exceptional)
2884 {
2885 line->unexceptional = 1;
2886 if (block->count == 0)
2887 line->has_unexecuted_block = 1;
2888 }
2889 line->count += block->count;
cdb07de7 2890 }
0790260e 2891 }
f55ade6e 2892
136ca74e 2893 has_any_line = true;
f55ade6e 2894
136ca74e
ML
2895 if (!ix || ix + 1 == fn->blocks.size ())
2896 /* Entry or exit block. */;
2897 else if (line != NULL)
86144b75 2898 {
136ca74e 2899 line->blocks.push_back (block);
6e49961c 2900
136ca74e 2901 if (flag_branches)
6e49961c 2902 {
232c80f2 2903 arc_info *arc;
136ca74e
ML
2904
2905 for (arc = block->succ; arc; arc = arc->succ_next)
2906 line->branches.push_back (arc);
6e49961c 2907 }
86144b75 2908 }
8b219a76
NS
2909 }
2910 }
6e49961c
ML
2911
2912 if (!has_any_line)
c8fda30f
ML
2913 fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name,
2914 fn->get_name ());
4977bab6
ZW
2915}
2916
136ca74e
ML
2917/* Accumulate info for LINE that belongs to SRC source file. If ADD_COVERAGE
2918 is set to true, update source file summary. */
2919
2920static void accumulate_line_info (line_info *line, source_info *src,
2921 bool add_coverage)
2922{
2923 if (add_coverage)
2924 for (vector<arc_info *>::iterator it = line->branches.begin ();
2925 it != line->branches.end (); it++)
2926 add_branch_counts (&src->coverage, *it);
2927
08a52331
JK
2928 if (add_coverage)
2929 for (vector<block_info *>::iterator it = line->blocks.begin ();
2930 it != line->blocks.end (); it++)
2931 add_condition_counts (&src->coverage, *it);
2932
2933
136ca74e
ML
2934 if (!line->blocks.empty ())
2935 {
2936 /* The user expects the line count to be the number of times
2937 a line has been executed. Simply summing the block count
2938 will give an artificially high number. The Right Thing
2939 is to sum the entry counts to the graph of blocks on this
2940 line, then find the elementary cycles of the local graph
2941 and add the transition counts of those cycles. */
2942 gcov_type count = 0;
2943
2944 /* Cycle detection. */
bea002e9 2945 for (vector<block_info *>::iterator it = line->blocks.begin ();
136ca74e
ML
2946 it != line->blocks.end (); it++)
2947 {
232c80f2 2948 for (arc_info *arc = (*it)->pred; arc; arc = arc->pred_next)
136ca74e
ML
2949 if (!line->has_block (arc->src))
2950 count += arc->count;
232c80f2 2951 for (arc_info *arc = (*it)->succ; arc; arc = arc->succ_next)
136ca74e
ML
2952 arc->cs_count = arc->count;
2953 }
2954
2955 /* Now, add the count of loops entirely on this line. */
2956 count += get_cycles_count (*line);
2957 line->count = count;
d6683f89
ML
2958
2959 if (line->count > src->maximum_count)
2960 src->maximum_count = line->count;
136ca74e
ML
2961 }
2962
2963 if (line->exists && add_coverage)
2964 {
2965 src->coverage.lines++;
2966 if (line->count)
2967 src->coverage.lines_executed++;
2968 }
2969}
2970
32dd366d 2971/* Accumulate the line counts of a file. */
4977bab6
ZW
2972
2973static void
c7432e76 2974accumulate_line_counts (source_info *src)
4977bab6 2975{
136ca74e 2976 /* First work on group functions. */
cb8758b2 2977 for (vector<function_info *>::iterator it = src->functions.begin ();
136ca74e 2978 it != src->functions.end (); it++)
27283c73 2979 {
136ca74e
ML
2980 function_info *fn = *it;
2981
2982 if (fn->src != src->index || !fn->is_group)
2983 continue;
2984
2985 for (vector<line_info>::iterator it2 = fn->lines.begin ();
2986 it2 != fn->lines.end (); it2++)
2987 {
2988 line_info *line = &(*it2);
42301c02 2989 accumulate_line_info (line, src, true);
136ca74e 2990 }
27283c73 2991 }
f55ade6e 2992
136ca74e
ML
2993 /* Work on global lines that line in source file SRC. */
2994 for (vector<line_info>::iterator it = src->lines.begin ();
2995 it != src->lines.end (); it++)
2996 accumulate_line_info (&(*it), src, true);
86144b75 2997
136ca74e
ML
2998 /* If not using intermediate mode, sum lines of group functions and
2999 add them to lines that live in a source file. */
c8fda30f 3000 if (!flag_json_format)
cb8758b2 3001 for (vector<function_info *>::iterator it = src->functions.begin ();
136ca74e
ML
3002 it != src->functions.end (); it++)
3003 {
3004 function_info *fn = *it;
10b7602f 3005
136ca74e
ML
3006 if (fn->src != src->index || !fn->is_group)
3007 continue;
10b7602f 3008
136ca74e
ML
3009 for (unsigned i = 0; i < fn->lines.size (); i++)
3010 {
3011 line_info *fn_line = &fn->lines[i];
3012 if (fn_line->exists)
3013 {
3014 unsigned ln = fn->start_line + i;
3015 line_info *src_line = &src->lines[ln];
f55ade6e 3016
136ca74e
ML
3017 if (!src_line->exists)
3018 src->coverage.lines++;
3019 if (!src_line->count && fn_line->count)
3020 src->coverage.lines_executed++;
c7432e76 3021
136ca74e
ML
3022 src_line->count += fn_line->count;
3023 src_line->exists = 1;
3024
3025 if (fn_line->has_unexecuted_block)
3026 src_line->has_unexecuted_block = 1;
3027
3028 if (fn_line->unexceptional)
3029 src_line->unexceptional = 1;
3030 }
3031 }
3032 }
8b219a76 3033}
86144b75 3034
08a52331
JK
3035/* Output information about the conditions in block BINFO. The output includes
3036 * a summary (n/m outcomes covered) and a list of the missing (uncovered)
3037 * outcomes. */
3038
3039static void
3040output_conditions (FILE *gcov_file, const block_info *binfo)
3041{
3042 const condition_info& info = binfo->conditions;
3043 if (info.n_terms == 0)
3044 return;
3045
3046 const int expected = 2 * info.n_terms;
3047 const int got = info.popcount ();
3048
3049 fnotice (gcov_file, "condition outcomes covered %d/%d\n", got, expected);
3050 if (expected == got)
3051 return;
3052
3053 for (unsigned i = 0; i < info.n_terms; i++)
3054 {
3055 gcov_type_unsigned index = 1;
3056 index <<= i;
3057 if ((index & info.truev & info.falsev))
3058 continue;
3059
3060 const char *t = (index & info.truev) ? "" : "true";
3061 const char *f = (index & info.falsev) ? "" : " false";
3062 fnotice (gcov_file, "condition %2u not covered (%s%s)\n", i, t, f + !t[0]);
3063 }
3064}
3065
61ada8ae 3066/* Output information about ARC number IX. Returns nonzero if
27283c73
NS
3067 anything is output. */
3068
3069static int
232c80f2 3070output_branch_count (FILE *gcov_file, int ix, const arc_info *arc)
27283c73 3071{
27283c73
NS
3072 if (arc->is_call_non_return)
3073 {
3074 if (arc->src->count)
3075 {
3076 fnotice (gcov_file, "call %2d returned %s\n", ix,
3077 format_gcov (arc->src->count - arc->count,
3078 arc->src->count, -flag_counts));
3079 }
3080 else
3081 fnotice (gcov_file, "call %2d never executed\n", ix);
3082 }
3083 else if (!arc->is_unconditional)
3084 {
3085 if (arc->src->count)
9b9d6370 3086 fnotice (gcov_file, "branch %2d taken %s%s", ix,
27283c73 3087 format_gcov (arc->count, arc->src->count, -flag_counts),
8919c0d9
NS
3088 arc->fall_through ? " (fallthrough)"
3089 : arc->is_throw ? " (throw)" : "");
27283c73 3090 else
c263c3eb
S
3091 fnotice (gcov_file, "branch %2d never executed%s", ix,
3092 (arc->fall_through ? " (fallthrough)"
3093 : arc->is_throw ? " (throw)" : ""));
9b9d6370
ML
3094
3095 if (flag_verbose)
3096 fnotice (gcov_file, " (BB %d)", arc->dst->id);
3097
3098 fnotice (gcov_file, "\n");
27283c73 3099 }
10b7602f 3100 else if (flag_unconditional && !arc->dst->is_call_return)
27283c73
NS
3101 {
3102 if (arc->src->count)
3103 fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
3104 format_gcov (arc->count, arc->src->count, -flag_counts));
3105 else
3106 fnotice (gcov_file, "unconditional %2d never executed\n", ix);
3107 }
3108 else
3109 return 0;
3110 return 1;
27283c73
NS
3111}
3112
8f961b22
NS
3113static const char *
3114read_line (FILE *file)
3115{
3116 static char *string;
3117 static size_t string_len;
3118 size_t pos = 0;
8f961b22
NS
3119
3120 if (!string_len)
3121 {
3122 string_len = 200;
3123 string = XNEWVEC (char, string_len);
3124 }
3125
4096eb50 3126 while (fgets (string + pos, string_len - pos, file))
8f961b22
NS
3127 {
3128 size_t len = strlen (string + pos);
3129
62a76702 3130 if (len && string[pos + len - 1] == '\n')
8f961b22
NS
3131 {
3132 string[pos + len - 1] = 0;
3133 return string;
3134 }
3135 pos += len;
62a76702
BE
3136 /* If the file contains NUL characters or an incomplete
3137 last line, which can happen more than once in one run,
3138 we have to avoid doubling the STRING_LEN unnecessarily. */
3139 if (pos > string_len / 2)
3140 {
3141 string_len *= 2;
3142 string = XRESIZEVEC (char, string, string_len);
3143 }
8f961b22 3144 }
176bf572 3145
8f961b22
NS
3146 return pos ? string : NULL;
3147}
3148
28f4a4a8
ML
3149/* Pad string S with spaces from left to have total width equal to 9. */
3150
3151static void
3152pad_count_string (string &s)
3153{
3154 if (s.size () < 9)
3155 s.insert (0, 9 - s.size (), ' ');
3156}
3157
3158/* Print GCOV line beginning to F stream. If EXISTS is set to true, the
3159 line exists in source file. UNEXCEPTIONAL indicated that it's not in
3160 an exceptional statement. The output is printed for LINE_NUM of given
3161 COUNT of executions. EXCEPTIONAL_STRING and UNEXCEPTIONAL_STRING are
3162 used to indicate non-executed blocks. */
3163
3164static void
3165output_line_beginning (FILE *f, bool exists, bool unexceptional,
cdb07de7 3166 bool has_unexecuted_block,
28f4a4a8
ML
3167 gcov_type count, unsigned line_num,
3168 const char *exceptional_string,
d6683f89
ML
3169 const char *unexceptional_string,
3170 unsigned int maximum_count)
28f4a4a8
ML
3171{
3172 string s;
3173 if (exists)
3174 {
3175 if (count > 0)
3176 {
3177 s = format_gcov (count, 0, -1);
93814e2d
ML
3178 if (has_unexecuted_block
3179 && bbg_supports_has_unexecuted_blocks)
cdb07de7
ML
3180 {
3181 if (flag_use_colors)
3182 {
3183 pad_count_string (s);
136ca74e
ML
3184 s.insert (0, SGR_SEQ (COLOR_BG_MAGENTA
3185 COLOR_SEPARATOR COLOR_FG_WHITE));
cdb07de7
ML
3186 s += SGR_RESET;
3187 }
3188 else
3189 s += "*";
3190 }
28f4a4a8
ML
3191 pad_count_string (s);
3192 }
3193 else
3194 {
3195 if (flag_use_colors)
3196 {
3197 s = "0";
3198 pad_count_string (s);
3199 if (unexceptional)
3200 s.insert (0, SGR_SEQ (COLOR_BG_RED
3201 COLOR_SEPARATOR COLOR_FG_WHITE));
3202 else
3203 s.insert (0, SGR_SEQ (COLOR_BG_CYAN
3204 COLOR_SEPARATOR COLOR_FG_WHITE));
3205 s += SGR_RESET;
3206 }
3207 else
3208 {
3209 s = unexceptional ? unexceptional_string : exceptional_string;
3210 pad_count_string (s);
3211 }
3212 }
3213 }
3214 else
3215 {
3216 s = "-";
3217 pad_count_string (s);
3218 }
3219
d6683f89
ML
3220 /* Format line number in output. */
3221 char buffer[16];
3222 sprintf (buffer, "%5u", line_num);
3223 string linestr (buffer);
3224
3225 if (flag_use_hotness_colors && maximum_count)
3226 {
3227 if (count * 2 > maximum_count) /* > 50%. */
3228 linestr.insert (0, SGR_SEQ (COLOR_BG_RED));
3229 else if (count * 5 > maximum_count) /* > 20%. */
3230 linestr.insert (0, SGR_SEQ (COLOR_BG_YELLOW));
3231 else if (count * 10 > maximum_count) /* > 10%. */
3232 linestr.insert (0, SGR_SEQ (COLOR_BG_GREEN));
3233 linestr += SGR_RESET;
3234 }
3235
3236 fprintf (f, "%s:%s", s.c_str (), linestr.c_str ());
28f4a4a8
ML
3237}
3238
136ca74e
ML
3239static void
3240print_source_line (FILE *f, const vector<const char *> &source_lines,
3241 unsigned line)
3242{
3243 gcc_assert (line >= 1);
3244 gcc_assert (line <= source_lines.size ());
3245
3246 fprintf (f, ":%s\n", source_lines[line - 1]);
3247}
3248
3249/* Output line details for LINE and print it to F file. LINE lives on
3250 LINE_NUM. */
3251
3252static void
3253output_line_details (FILE *f, const line_info *line, unsigned line_num)
3254{
3255 if (flag_all_blocks)
3256 {
232c80f2 3257 arc_info *arc;
171fe068 3258 int jx = 0;
bea002e9 3259 for (vector<block_info *>::const_iterator it = line->blocks.begin ();
136ca74e
ML
3260 it != line->blocks.end (); it++)
3261 {
3262 if (!(*it)->is_call_return)
3263 {
3264 output_line_beginning (f, line->exists,
3265 (*it)->exceptional, false,
3266 (*it)->count, line_num,
d6683f89 3267 "%%%%%", "$$$$$", 0);
171fe068 3268 fprintf (f, "-block %d", (*it)->id);
136ca74e
ML
3269 if (flag_verbose)
3270 fprintf (f, " (BB %u)", (*it)->id);
3271 fprintf (f, "\n");
3272 }
3273 if (flag_branches)
3274 for (arc = (*it)->succ; arc; arc = arc->succ_next)
3275 jx += output_branch_count (f, jx, arc);
08a52331
JK
3276
3277 if (flag_conditions)
3278 output_conditions (f, *it);
136ca74e
ML
3279 }
3280 }
08a52331 3281 else
136ca74e 3282 {
08a52331
JK
3283 if (flag_branches)
3284 {
3285 int ix;
3286
3287 ix = 0;
3288 for (vector<arc_info *>::const_iterator it = line->branches.begin ();
3289 it != line->branches.end (); it++)
3290 ix += output_branch_count (f, ix, (*it));
3291 }
136ca74e 3292
08a52331
JK
3293 if (flag_conditions)
3294 {
3295 for (vector<block_info *>::const_iterator it = line->blocks.begin ();
3296 it != line->blocks.end (); it++)
3297 output_conditions (f, *it);
3298 }
136ca74e
ML
3299 }
3300}
3301
3302/* Output detail statistics about function FN to file F. */
3303
3304static void
c8fda30f 3305output_function_details (FILE *f, function_info *fn)
136ca74e
ML
3306{
3307 if (!flag_branches)
3308 return;
3309
232c80f2 3310 arc_info *arc = fn->blocks[EXIT_BLOCK].pred;
136ca74e
ML
3311 gcov_type return_count = fn->blocks[EXIT_BLOCK].count;
3312 gcov_type called_count = fn->blocks[ENTRY_BLOCK].count;
3313
3314 for (; arc; arc = arc->pred_next)
3315 if (arc->fake)
3316 return_count -= arc->count;
3317
c8fda30f 3318 fprintf (f, "function %s", fn->get_name ());
136ca74e
ML
3319 fprintf (f, " called %s",
3320 format_gcov (called_count, 0, -1));
3321 fprintf (f, " returned %s",
3322 format_gcov (return_count, called_count, 0));
3323 fprintf (f, " blocks executed %s",
c8fda30f 3324 format_gcov (fn->blocks_executed, fn->get_block_count (), 0));
136ca74e
ML
3325 fprintf (f, "\n");
3326}
3327
8b219a76
NS
3328/* Read in the source file one line at a time, and output that line to
3329 the gcov file preceded by its execution count and other
3330 information. */
86144b75 3331
8b219a76 3332static void
c7432e76 3333output_lines (FILE *gcov_file, const source_info *src)
8b219a76 3334{
28f4a4a8 3335#define DEFAULT_LINE_START " -: 0:"
136ca74e 3336#define FN_SEPARATOR "------------------\n"
28f4a4a8 3337
8b219a76 3338 FILE *source_file;
136ca74e 3339 const char *retval;
4977bab6 3340
e595522a
ML
3341 /* Print colorization legend. */
3342 if (flag_use_colors)
3343 fprintf (gcov_file, "%s",
3344 DEFAULT_LINE_START "Colorization: profile count: " \
3345 SGR_SEQ (COLOR_BG_CYAN) "zero coverage (exceptional)" SGR_RESET \
3346 " " \
3347 SGR_SEQ (COLOR_BG_RED) "zero coverage (unexceptional)" SGR_RESET \
3348 " " \
3349 SGR_SEQ (COLOR_BG_MAGENTA) "unexecuted block" SGR_RESET "\n");
3350
d6683f89 3351 if (flag_use_hotness_colors)
e595522a
ML
3352 fprintf (gcov_file, "%s",
3353 DEFAULT_LINE_START "Colorization: line numbers: hotness: " \
d6683f89
ML
3354 SGR_SEQ (COLOR_BG_RED) "> 50%" SGR_RESET " " \
3355 SGR_SEQ (COLOR_BG_YELLOW) "> 20%" SGR_RESET " " \
3356 SGR_SEQ (COLOR_BG_GREEN) "> 10%" SGR_RESET "\n");
3357
28f4a4a8 3358 fprintf (gcov_file, DEFAULT_LINE_START "Source:%s\n", src->coverage.name);
1a9075e2
TG
3359 if (!multiple_files)
3360 {
28f4a4a8
ML
3361 fprintf (gcov_file, DEFAULT_LINE_START "Graph:%s\n", bbg_file_name);
3362 fprintf (gcov_file, DEFAULT_LINE_START "Data:%s\n",
1a9075e2 3363 no_data_file ? "-" : da_file_name);
28f4a4a8 3364 fprintf (gcov_file, DEFAULT_LINE_START "Runs:%u\n", object_runs);
1a9075e2 3365 }
f55ade6e 3366
4977bab6 3367 source_file = fopen (src->name, "r");
8b219a76 3368 if (!source_file)
136ca74e 3369 fnotice (stderr, "Cannot open source file %s\n", src->name);
1a9075e2 3370 else if (src->file_time == 0)
28f4a4a8 3371 fprintf (gcov_file, DEFAULT_LINE_START "Source is newer than graph\n");
8b219a76 3372
136ca74e
ML
3373 vector<const char *> source_lines;
3374 if (source_file)
3375 while ((retval = read_line (source_file)) != NULL)
3376 source_lines.push_back (xstrdup (retval));
f5d39c3d 3377
136ca74e 3378 unsigned line_start_group = 0;
59688303 3379 vector<function_info *> *fns;
136ca74e
ML
3380
3381 for (unsigned line_num = 1; line_num <= source_lines.size (); line_num++)
8b219a76 3382 {
136ca74e 3383 if (line_num >= src->lines.size ())
27283c73 3384 {
136ca74e
ML
3385 fprintf (gcov_file, "%9s:%5u", "-", line_num);
3386 print_source_line (gcov_file, source_lines, line_num);
3387 continue;
27283c73 3388 }
f55ade6e 3389
136ca74e
ML
3390 const line_info *line = &src->lines[line_num];
3391
3392 if (line_start_group == 0)
3393 {
3394 fns = src->get_functions_at_location (line_num);
59688303 3395 if (fns != NULL && fns->size () > 1)
e59b5e24
ML
3396 {
3397 /* It's possible to have functions that partially overlap,
3398 thus take the maximum end_line of functions starting
3399 at LINE_NUM. */
59688303
ML
3400 for (unsigned i = 0; i < fns->size (); i++)
3401 if ((*fns)[i]->end_line > line_start_group)
3402 line_start_group = (*fns)[i]->end_line;
e59b5e24 3403 }
59688303 3404 else if (fns != NULL && fns->size () == 1)
136ca74e 3405 {
59688303 3406 function_info *fn = (*fns)[0];
136ca74e
ML
3407 output_function_details (gcov_file, fn);
3408 }
3409 }
8f961b22 3410
8b219a76 3411 /* For lines which don't exist in the .bb file, print '-' before
f55ade6e 3412 the source line. For lines which exist but were never
8f961b22
NS
3413 executed, print '#####' or '=====' before the source line.
3414 Otherwise, print the execution count before the source line.
3415 There are 16 spaces of indentation added before the source
3416 line so that tabs won't be messed up. */
28f4a4a8 3417 output_line_beginning (gcov_file, line->exists, line->unexceptional,
136ca74e 3418 line->has_unexecuted_block, line->count,
d6683f89 3419 line_num, "=====", "#####", src->maximum_count);
27283c73 3420
136ca74e
ML
3421 print_source_line (gcov_file, source_lines, line_num);
3422 output_line_details (gcov_file, line, line_num);
f55ade6e 3423
136ca74e
ML
3424 if (line_start_group == line_num)
3425 {
59688303
ML
3426 for (vector<function_info *>::iterator it = fns->begin ();
3427 it != fns->end (); it++)
37b8715b 3428 {
136ca74e
ML
3429 function_info *fn = *it;
3430 vector<line_info> &lines = fn->lines;
3431
3432 fprintf (gcov_file, FN_SEPARATOR);
3433
c8fda30f 3434 string fn_name = fn->get_name ();
136ca74e 3435 if (flag_use_colors)
9b9d6370 3436 {
136ca74e
ML
3437 fn_name.insert (0, SGR_SEQ (COLOR_FG_CYAN));
3438 fn_name += SGR_RESET;
3439 }
3440
3441 fprintf (gcov_file, "%s:\n", fn_name.c_str ());
3442
3443 output_function_details (gcov_file, fn);
3444
3445 /* Print all lines covered by the function. */
3446 for (unsigned i = 0; i < lines.size (); i++)
3447 {
3448 line_info *line = &lines[i];
3449 unsigned l = fn->start_line + i;
3450
3451 /* For lines which don't exist in the .bb file, print '-'
3452 before the source line. For lines which exist but
3453 were never executed, print '#####' or '=====' before
3454 the source line. Otherwise, print the execution count
3455 before the source line.
3456 There are 16 spaces of indentation added before the source
3457 line so that tabs won't be messed up. */
28f4a4a8 3458 output_line_beginning (gcov_file, line->exists,
136ca74e
ML
3459 line->unexceptional,
3460 line->has_unexecuted_block,
3461 line->count,
d6683f89
ML
3462 l, "=====", "#####",
3463 src->maximum_count);
136ca74e
ML
3464
3465 print_source_line (gcov_file, source_lines, l);
3466 output_line_details (gcov_file, line, l);
9b9d6370 3467 }
86144b75 3468 }
f55ade6e 3469
136ca74e
ML
3470 fprintf (gcov_file, FN_SEPARATOR);
3471 line_start_group = 0;
27283c73 3472 }
8b219a76 3473 }
f55ade6e 3474
8b219a76
NS
3475 if (source_file)
3476 fclose (source_file);
3477}