]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/coverage.c
re PR rtl-optimization/52139 (ICE: in remove_insn, at emit-rtl.c:3960 with -O -fPIC...
[thirdparty/gcc.git] / gcc / coverage.c
CommitLineData
ca29da43
NS
1/* Read and write coverage files, and associated functionality.
2 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
5366b186 3 2000, 2001, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
1da2ed5f 4 Free Software Foundation, Inc.
ca29da43
NS
5 Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
6 based on some ideas from Dain Samples of UC Berkeley.
7 Further mangling by Bob Manson, Cygnus Support.
8 Further mangled by Nathan Sidwell, CodeSourcery
9
10This file is part of GCC.
11
12GCC is free software; you can redistribute it and/or modify it under
13the terms of the GNU General Public License as published by the Free
9dcd6f09 14Software Foundation; either version 3, or (at your option) any later
ca29da43
NS
15version.
16
17GCC is distributed in the hope that it will be useful, but WITHOUT ANY
18WARRANTY; without even the implied warranty of MERCHANTABILITY or
19FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20for more details.
21
22You should have received a copy of the GNU General Public License
9dcd6f09
NC
23along with GCC; see the file COPYING3. If not see
24<http://www.gnu.org/licenses/>. */
ca29da43
NS
25
26
27#define GCOV_LINKAGE
28
29#include "config.h"
30#include "system.h"
31#include "coretypes.h"
32#include "tm.h"
33#include "rtl.h"
34#include "tree.h"
35#include "flags.h"
36#include "output.h"
37#include "regs.h"
38#include "expr.h"
39#include "function.h"
2d1a4cc1 40#include "basic-block.h"
ca29da43 41#include "toplev.h"
5773a50f 42#include "tm_p.h"
ca29da43 43#include "ggc.h"
ca29da43 44#include "coverage.h"
ca29da43
NS
45#include "langhooks.h"
46#include "hashtab.h"
c9b9aa64
RH
47#include "tree-iterator.h"
48#include "cgraph.h"
27624b9e 49#include "tree-pass.h"
1da2ed5f 50#include "diagnostic-core.h"
650cfcab 51#include "intl.h"
ba78087b 52#include "filenames.h"
ca29da43 53
10adac51 54#include "gcov-io.h"
ca29da43
NS
55#include "gcov-io.c"
56
b724567e 57struct GTY((chain_next ("%h.next"))) coverage_data
ca29da43 58{
b724567e 59 struct coverage_data *next; /* next function */
159b3be1 60 unsigned ident; /* function ident */
10adac51
XDL
61 unsigned lineno_checksum; /* function lineno checksum */
62 unsigned cfg_checksum; /* function cfg checksum */
5366b186
NS
63 tree fn_decl; /* the function decl */
64 tree ctr_vars[GCOV_COUNTERS]; /* counter variables. */
ca29da43
NS
65};
66
67/* Counts information for a function. */
68typedef struct counts_entry
69{
70 /* We hash by */
796621e8 71 unsigned ident;
cdb23767 72 unsigned ctr;
159b3be1 73
ca29da43 74 /* Store */
10adac51
XDL
75 unsigned lineno_checksum;
76 unsigned cfg_checksum;
ca29da43 77 gcov_type *counts;
cdb23767 78 struct gcov_ctr_summary summary;
ca29da43
NS
79} counts_entry_t;
80
b724567e
NS
81static GTY(()) struct coverage_data *functions_head = 0;
82static struct coverage_data **functions_tail = &functions_head;
6d70e6be 83static unsigned no_coverage = 0;
ca29da43 84
cdb23767
NS
85/* Cumulative counter information for whole program. */
86static unsigned prg_ctr_mask; /* Mask of counter types generated. */
ca29da43 87
cdb23767 88/* Counter information for current function. */
71c0e7fc 89static unsigned fn_ctr_mask; /* Mask of counters used. */
5366b186 90static GTY(()) tree fn_v_ctrs[GCOV_COUNTERS]; /* counter variables. */
6d70e6be
NS
91static unsigned fn_n_ctrs[GCOV_COUNTERS]; /* Counters allocated. */
92static unsigned fn_b_ctrs[GCOV_COUNTERS]; /* Allocation base. */
ca29da43 93
b724567e
NS
94/* Coverage info VAR_DECL and function info type nodes. */
95static GTY(()) tree gcov_info_var;
96static GTY(()) tree gcov_fn_info_type;
97static GTY(()) tree gcov_fn_info_ptr_type;
98
99/* Name of the output file for coverage output file. If this is NULL
100 we're not writing to the notes file. */
ca29da43 101static char *bbg_file_name;
ca29da43
NS
102
103/* Name of the count data file. */
104static char *da_file_name;
105
106/* Hash table of count data. */
107static htab_t counts_hash = NULL;
108
09780dfb 109/* The names of merge functions for counters. */
9b514d25
NS
110static const char *const ctr_merge_functions[GCOV_COUNTERS] = GCOV_MERGE_FUNCTIONS;
111static const char *const ctr_names[GCOV_COUNTERS] = GCOV_COUNTER_NAMES;
09780dfb 112
ca29da43 113/* Forward declarations. */
159b3be1
AJ
114static hashval_t htab_counts_entry_hash (const void *);
115static int htab_counts_entry_eq (const void *, const void *);
116static void htab_counts_entry_del (void *);
117static void read_counts_file (void);
5366b186
NS
118static tree build_var (tree, tree, int);
119static void build_fn_info_type (tree, unsigned, tree);
b724567e
NS
120static void build_info_type (tree, tree);
121static tree build_fn_info (const struct coverage_data *, tree, tree);
122static tree build_info (tree, tree);
123static bool coverage_obj_init (void);
124static VEC(constructor_elt,gc) *coverage_obj_fn
125(VEC(constructor_elt,gc) *, tree, struct coverage_data const *);
126static void coverage_obj_finish (VEC(constructor_elt,gc) *);
251e2ff2
RS
127\f
128/* Return the type node for gcov_type. */
129
130tree
131get_gcov_type (void)
132{
133 return lang_hooks.types.type_for_size (GCOV_TYPE_SIZE, false);
134}
135
136/* Return the type node for gcov_unsigned_t. */
ca29da43 137
251e2ff2
RS
138static tree
139get_gcov_unsigned_t (void)
140{
141 return lang_hooks.types.type_for_size (32, true);
142}
ca29da43
NS
143\f
144static hashval_t
159b3be1 145htab_counts_entry_hash (const void *of)
ca29da43 146{
f883e0a7 147 const counts_entry_t *const entry = (const counts_entry_t *) of;
ca29da43 148
796621e8 149 return entry->ident * GCOV_COUNTERS + entry->ctr;
ca29da43
NS
150}
151
152static int
159b3be1 153htab_counts_entry_eq (const void *of1, const void *of2)
ca29da43 154{
f883e0a7
KG
155 const counts_entry_t *const entry1 = (const counts_entry_t *) of1;
156 const counts_entry_t *const entry2 = (const counts_entry_t *) of2;
ca29da43 157
796621e8 158 return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
ca29da43
NS
159}
160
161static void
159b3be1 162htab_counts_entry_del (void *of)
ca29da43 163{
f883e0a7 164 counts_entry_t *const entry = (counts_entry_t *) of;
ca29da43 165
ca29da43
NS
166 free (entry->counts);
167 free (entry);
168}
169
170/* Read in the counts file, if available. */
171
172static void
159b3be1 173read_counts_file (void)
ca29da43 174{
9b514d25 175 gcov_unsigned_t fn_ident = 0;
5366b186
NS
176 struct gcov_summary summary;
177 unsigned new_summary = 1;
7d63a2fa 178 gcov_unsigned_t tag;
24a4a033 179 int is_error = 0;
10adac51
XDL
180 unsigned lineno_checksum = 0;
181 unsigned cfg_checksum = 0;
7d63a2fa 182
ca29da43
NS
183 if (!gcov_open (da_file_name, 1))
184 return;
159b3be1 185
160e2e4f 186 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
ca29da43 187 {
d4ee4d25 188 warning (0, "%qs is not a gcov data file", da_file_name);
ca29da43
NS
189 gcov_close ();
190 return;
191 }
160e2e4f 192 else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
ca29da43 193 {
330d2e2a
NS
194 char v[4], e[4];
195
196 GCOV_UNSIGNED2STRING (v, tag);
197 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
159b3be1 198
d4ee4d25 199 warning (0, "%qs is version %q.*s, expected version %q.*s",
cb83302c 200 da_file_name, 4, v, 4, e);
ca29da43
NS
201 gcov_close ();
202 return;
203 }
159b3be1 204
4ed43216 205 /* Read and discard the stamp. */
dd486eb2 206 gcov_read_unsigned ();
b8698a0f 207
ca29da43
NS
208 counts_hash = htab_create (10,
209 htab_counts_entry_hash, htab_counts_entry_eq,
210 htab_counts_entry_del);
7d63a2fa 211 while ((tag = gcov_read_unsigned ()))
ca29da43 212 {
7d63a2fa 213 gcov_unsigned_t length;
9b514d25 214 gcov_position_t offset;
159b3be1 215
ca29da43
NS
216 length = gcov_read_unsigned ();
217 offset = gcov_position ();
218 if (tag == GCOV_TAG_FUNCTION)
219 {
5366b186 220 if (length)
ca29da43 221 {
5366b186
NS
222 fn_ident = gcov_read_unsigned ();
223 lineno_checksum = gcov_read_unsigned ();
224 cfg_checksum = gcov_read_unsigned ();
ca29da43 225 }
5366b186
NS
226 else
227 fn_ident = lineno_checksum = cfg_checksum = 0;
228 new_summary = 1;
ca29da43
NS
229 }
230 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
231 {
5366b186
NS
232 struct gcov_summary sum;
233 unsigned ix;
159b3be1 234
5366b186
NS
235 if (new_summary)
236 memset (&summary, 0, sizeof (summary));
159b3be1 237
5366b186
NS
238 gcov_read_summary (&sum);
239 for (ix = 0; ix != GCOV_COUNTERS_SUMMABLE; ix++)
240 {
241 summary.ctrs[ix].runs += sum.ctrs[ix].runs;
242 summary.ctrs[ix].sum_all += sum.ctrs[ix].sum_all;
243 if (summary.ctrs[ix].run_max < sum.ctrs[ix].run_max)
244 summary.ctrs[ix].run_max = sum.ctrs[ix].run_max;
245 summary.ctrs[ix].sum_max += sum.ctrs[ix].sum_max;
ca29da43 246 }
5366b186 247 new_summary = 0;
ca29da43 248 }
796621e8 249 else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
ca29da43
NS
250 {
251 counts_entry_t **slot, *entry, elt;
330d2e2a 252 unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
ca29da43
NS
253 unsigned ix;
254
796621e8 255 elt.ident = fn_ident;
cdb23767 256 elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
ca29da43
NS
257
258 slot = (counts_entry_t **) htab_find_slot
259 (counts_hash, &elt, INSERT);
260 entry = *slot;
261 if (!entry)
262 {
5ed6ace5 263 *slot = entry = XCNEW (counts_entry_t);
10adac51 264 entry->ident = fn_ident;
cdb23767 265 entry->ctr = elt.ctr;
10adac51
XDL
266 entry->lineno_checksum = lineno_checksum;
267 entry->cfg_checksum = cfg_checksum;
5366b186 268 entry->summary = summary.ctrs[elt.ctr];
cdb23767 269 entry->summary.num = n_counts;
5ed6ace5 270 entry->counts = XCNEWVEC (gcov_type, n_counts);
ca29da43 271 }
10adac51
XDL
272 else if (entry->lineno_checksum != lineno_checksum
273 || entry->cfg_checksum != cfg_checksum)
ca29da43 274 {
10adac51
XDL
275 error ("Profile data for function %u is corrupted", fn_ident);
276 error ("checksum is (%x,%x) instead of (%x,%x)",
277 entry->lineno_checksum, entry->cfg_checksum,
278 lineno_checksum, cfg_checksum);
24a4a033
JH
279 htab_delete (counts_hash);
280 break;
281 }
282 else if (entry->summary.num != n_counts)
283 {
10adac51 284 error ("Profile data for function %u is corrupted", fn_ident);
24a4a033 285 error ("number of counters is %d instead of %d", entry->summary.num, n_counts);
ca29da43
NS
286 htab_delete (counts_hash);
287 break;
288 }
9b514d25
NS
289 else if (elt.ctr >= GCOV_COUNTERS_SUMMABLE)
290 {
24a4a033
JH
291 error ("cannot merge separate %s counters for function %u",
292 ctr_names[elt.ctr], fn_ident);
9b514d25
NS
293 goto skip_merge;
294 }
5366b186 295 else
ca29da43 296 {
5366b186
NS
297 entry->summary.runs += summary.ctrs[elt.ctr].runs;
298 entry->summary.sum_all += summary.ctrs[elt.ctr].sum_all;
299 if (entry->summary.run_max < summary.ctrs[elt.ctr].run_max)
300 entry->summary.run_max = summary.ctrs[elt.ctr].run_max;
301 entry->summary.sum_max += summary.ctrs[elt.ctr].sum_max;
ca29da43
NS
302 }
303 for (ix = 0; ix != n_counts; ix++)
304 entry->counts[ix] += gcov_read_counter ();
9b514d25 305 skip_merge:;
ca29da43 306 }
474f141e 307 gcov_sync (offset, length);
24a4a033 308 if ((is_error = gcov_is_error ()))
00cf2913 309 {
971801ff 310 error (is_error < 0 ? "%qs has overflowed" : "%qs is corrupted",
00cf2913
NS
311 da_file_name);
312 htab_delete (counts_hash);
313 break;
314 }
7d63a2fa 315 }
159b3be1 316
ca29da43
NS
317 gcov_close ();
318}
319
320/* Returns the counters for a particular tag. */
321
322gcov_type *
cdb23767 323get_coverage_counts (unsigned counter, unsigned expected,
10adac51 324 unsigned cfg_checksum, unsigned lineno_checksum,
cdb23767 325 const struct gcov_ctr_summary **summary)
ca29da43
NS
326{
327 counts_entry_t *entry, elt;
328
71c0e7fc 329 /* No hash table, no counts. */
ca29da43
NS
330 if (!counts_hash)
331 {
332 static int warned = 0;
333
334 if (!warned++)
1f5b3869 335 inform (input_location, (flag_guess_branch_prob
02307675
R
336 ? "file %s not found, execution counts estimated"
337 : "file %s not found, execution counts assumed to be zero"),
bbfff586 338 da_file_name);
ca29da43
NS
339 return NULL;
340 }
341
6d70e6be 342 elt.ident = current_function_funcdef_no + 1;
cdb23767 343 elt.ctr = counter;
f883e0a7 344 entry = (counts_entry_t *) htab_find (counts_hash, &elt);
5366b186
NS
345 if (!entry || !entry->summary.num)
346 /* The function was not emitted, or is weak and not chosen in the
347 final executable. Silently fail, because there's nothing we
348 can do about it. */
349 return NULL;
350
10adac51 351 if (entry->cfg_checksum != cfg_checksum
16c1c158 352 || entry->summary.num != expected)
24a4a033 353 {
16c1c158 354 static int warned = 0;
650cfcab 355 bool warning_printed = false;
4f1e4960 356 tree id = DECL_ASSEMBLER_NAME (current_function_decl);
16c1c158 357
10adac51
XDL
358 warning_printed =
359 warning_at (input_location, OPT_Wcoverage_mismatch,
5366b186 360 "the control flow of function %qE does not match "
10adac51 361 "its profile data (counter %qs)", id, ctr_names[counter]);
650cfcab 362 if (warning_printed)
16c1c158 363 {
5366b186 364 inform (input_location, "use -Wno-error=coverage-mismatch to tolerate "
10adac51 365 "the mismatch but performance may drop if the function is hot");
650cfcab 366
1da2ed5f 367 if (!seen_error ()
650cfcab
NV
368 && !warned++)
369 {
370 inform (input_location, "coverage mismatch ignored");
371 inform (input_location, flag_guess_branch_prob
372 ? G_("execution counts estimated")
373 : G_("execution counts assumed to be zero"));
374 if (!flag_guess_branch_prob)
375 inform (input_location,
376 "this can result in poorly optimized code");
377 }
16c1c158
RG
378 }
379
380 return NULL;
ca29da43 381 }
5366b186
NS
382 else if (entry->lineno_checksum != lineno_checksum)
383 {
b724567e 384 warning (0, "source locations for function %qE have changed,"
5366b186
NS
385 " the profile data may be out of date",
386 DECL_ASSEMBLER_NAME (current_function_decl));
387 }
159b3be1 388
cdb23767
NS
389 if (summary)
390 *summary = &entry->summary;
ca29da43
NS
391
392 return entry->counts;
393}
cdb23767 394
6356f892 395/* Allocate NUM counters of type COUNTER. Returns nonzero if the
6d70e6be 396 allocation succeeded. */
cdb23767 397
6d70e6be
NS
398int
399coverage_counter_alloc (unsigned counter, unsigned num)
cdb23767 400{
6d70e6be
NS
401 if (no_coverage)
402 return 0;
159b3be1 403
6d70e6be
NS
404 if (!num)
405 return 1;
159b3be1 406
5366b186 407 if (!fn_v_ctrs[counter])
cdb23767 408 {
5366b186
NS
409 tree array_type = build_array_type (get_gcov_type (), NULL_TREE);
410
411 fn_v_ctrs[counter]
412 = build_var (current_function_decl, array_type, counter);
cdb23767 413 }
5366b186 414
6d70e6be
NS
415 fn_b_ctrs[counter] = fn_n_ctrs[counter];
416 fn_n_ctrs[counter] += num;
5366b186 417
6d70e6be
NS
418 fn_ctr_mask |= 1 << counter;
419 return 1;
420}
cdb23767 421
6de9cd9a
DN
422/* Generate a tree to access COUNTER NO. */
423
424tree
425tree_coverage_counter_ref (unsigned counter, unsigned no)
426{
070e3969 427 tree gcov_type_node = get_gcov_type ();
6de9cd9a 428
341c100f 429 gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
6de9cd9a 430
5366b186
NS
431 no += fn_b_ctrs[counter];
432
6de9cd9a 433 /* "no" here is an array index, scaled to bytes later. */
5366b186 434 return build4 (ARRAY_REF, gcov_type_node, fn_v_ctrs[counter],
f81b1a3d 435 build_int_cst (integer_type_node, no), NULL, NULL);
6de9cd9a 436}
fc9161c1
RG
437
438/* Generate a tree to access the address of COUNTER NO. */
439
440tree
441tree_coverage_counter_addr (unsigned counter, unsigned no)
442{
443 tree gcov_type_node = get_gcov_type ();
444
445 gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
5366b186 446 no += fn_b_ctrs[counter];
628c189e 447
fc9161c1
RG
448 /* "no" here is an array index, scaled to bytes later. */
449 return build_fold_addr_expr (build4 (ARRAY_REF, gcov_type_node,
5366b186 450 fn_v_ctrs[counter],
f81b1a3d 451 build_int_cst (integer_type_node, no),
fc9161c1
RG
452 NULL, NULL));
453}
ca29da43 454\f
10adac51 455
ca29da43 456/* Generate a checksum for a string. CHKSUM is the current
71c0e7fc 457 checksum. */
ca29da43
NS
458
459static unsigned
20c361f3 460coverage_checksum_string (unsigned chksum, const char *string)
ca29da43 461{
20c361f3
JH
462 int i;
463 char *dup = NULL;
464
465 /* Look for everything that looks if it were produced by
5880f14f 466 get_file_function_name and zero out the second part
20c361f3
JH
467 that may result from flag_random_seed. This is not critical
468 as the checksums are used only for sanity checking. */
469 for (i = 0; string[i]; i++)
ca29da43 470 {
2b557972
JH
471 int offset = 0;
472 if (!strncmp (string + i, "_GLOBAL__N_", 11))
473 offset = 11;
20c361f3 474 if (!strncmp (string + i, "_GLOBAL__", 9))
2b557972
JH
475 offset = 9;
476
477 /* C++ namespaces do have scheme:
478 _GLOBAL__N_<filename>_<wrongmagicnumber>_<magicnumber>functionname
479 since filename might contain extra underscores there seems
480 to be no better chance then walk all possible offsets looking
fa10beec 481 for magicnumber. */
2b557972 482 if (offset)
1f651229
JH
483 {
484 for (i = i + offset; string[i]; i++)
485 if (string[i]=='_')
486 {
487 int y;
488
489 for (y = 1; y < 9; y++)
490 if (!(string[i + y] >= '0' && string[i + y] <= '9')
491 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
492 break;
493 if (y != 9 || string[i + 9] != '_')
494 continue;
495 for (y = 10; y < 18; y++)
496 if (!(string[i + y] >= '0' && string[i + y] <= '9')
497 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
498 break;
499 if (y != 18)
500 continue;
501 if (!dup)
502 string = dup = xstrdup (string);
503 for (y = 10; y < 18; y++)
504 dup[i + y] = '0';
505 }
506 break;
507 }
ca29da43 508 }
20c361f3
JH
509
510 chksum = crc32_string (chksum, string);
04695783 511 free (dup);
159b3be1 512
ca29da43
NS
513 return chksum;
514}
515
516/* Compute checksum for the current function. We generate a CRC32. */
517
10adac51
XDL
518unsigned
519coverage_compute_lineno_checksum (void)
ca29da43 520{
a281759f
PB
521 expanded_location xloc
522 = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
523 unsigned chksum = xloc.line;
ca29da43 524
a281759f 525 chksum = coverage_checksum_string (chksum, xloc.file);
20c361f3 526 chksum = coverage_checksum_string
ca29da43
NS
527 (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
528
529 return chksum;
530}
10adac51
XDL
531
532/* Compute cfg checksum for the current function.
533 The checksum is calculated carefully so that
534 source code changes that doesn't affect the control flow graph
535 won't change the checksum.
536 This is to make the profile data useable across source code change.
537 The downside of this is that the compiler may use potentially
538 wrong profile data - that the source code change has non-trivial impact
539 on the validity of profile data (e.g. the reversed condition)
540 but the compiler won't detect the change and use the wrong profile data. */
541
542unsigned
543coverage_compute_cfg_checksum (void)
544{
545 basic_block bb;
546 unsigned chksum = n_basic_blocks;
547
548 FOR_EACH_BB (bb)
549 {
550 edge e;
551 edge_iterator ei;
552 chksum = crc32_byte (chksum, bb->index);
553 FOR_EACH_EDGE (e, ei, bb->succs)
554 {
555 chksum = crc32_byte (chksum, e->dest->index);
556 }
557 }
558
559 return chksum;
560}
ca29da43
NS
561\f
562/* Begin output to the graph file for the current function.
b724567e 563 Writes the function header. Returns nonzero if data should be output. */
ca29da43
NS
564
565int
b724567e 566coverage_begin_function (unsigned lineno_checksum, unsigned cfg_checksum)
ca29da43 567{
b724567e
NS
568 expanded_location xloc;
569 unsigned long offset;
570
2f908293
SP
571 /* We don't need to output .gcno file unless we're under -ftest-coverage
572 (e.g. -fprofile-arcs/generate/use don't need .gcno to work). */
b724567e 573 if (no_coverage || !bbg_file_name)
6d70e6be 574 return 0;
159b3be1 575
b724567e 576 xloc = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
10adac51 577
b724567e
NS
578 /* Announce function */
579 offset = gcov_write_tag (GCOV_TAG_FUNCTION);
580 gcov_write_unsigned (current_function_funcdef_no + 1);
581 gcov_write_unsigned (lineno_checksum);
582 gcov_write_unsigned (cfg_checksum);
583 gcov_write_string (IDENTIFIER_POINTER
584 (DECL_ASSEMBLER_NAME (current_function_decl)));
585 gcov_write_string (xloc.file);
586 gcov_write_unsigned (xloc.line);
587 gcov_write_length (offset);
ca29da43 588
ca29da43
NS
589 return !gcov_is_error ();
590}
591
592/* Finish coverage data for the current function. Verify no output
593 error has occurred. Save function coverage counts. */
594
595void
10adac51 596coverage_end_function (unsigned lineno_checksum, unsigned cfg_checksum)
ca29da43
NS
597{
598 unsigned i;
159b3be1 599
b724567e 600 if (bbg_file_name && gcov_is_error ())
159b3be1 601 {
d4ee4d25 602 warning (0, "error writing %qs", bbg_file_name);
b724567e
NS
603 unlink (bbg_file_name);
604 bbg_file_name = NULL;
ca29da43 605 }
cdb23767 606
2ac69a0c 607 if (fn_ctr_mask)
cdb23767 608 {
2ac69a0c
NS
609 struct coverage_data *item = 0;
610
611 /* If the function is extern (i.e. extern inline), then we won't
612 be outputting it, so don't chain it onto the function
613 list. */
614 if (!DECL_EXTERNAL (current_function_decl))
615 {
616 item = ggc_alloc_coverage_data ();
617
618 item->ident = current_function_funcdef_no + 1;
619 item->lineno_checksum = lineno_checksum;
620 item->cfg_checksum = cfg_checksum;
621
622 item->fn_decl = current_function_decl;
623 item->next = 0;
624 *functions_tail = item;
625 functions_tail = &item->next;
626 }
10adac51 627
cdb23767
NS
628 for (i = 0; i != GCOV_COUNTERS; i++)
629 {
5366b186 630 tree var = fn_v_ctrs[i];
2ac69a0c
NS
631
632 if (item)
633 item->ctr_vars[i] = var;
5366b186
NS
634 if (var)
635 {
636 tree array_type = build_index_type (size_int (fn_n_ctrs[i] - 1));
637 array_type = build_array_type (get_gcov_type (), array_type);
638 TREE_TYPE (var) = array_type;
639 DECL_SIZE (var) = TYPE_SIZE (array_type);
640 DECL_SIZE_UNIT (var) = TYPE_SIZE_UNIT (array_type);
641 varpool_finalize_decl (var);
642 }
2ac69a0c 643
5366b186
NS
644 fn_b_ctrs[i] = fn_n_ctrs[i] = 0;
645 fn_v_ctrs[i] = NULL_TREE;
cdb23767
NS
646 }
647 prg_ctr_mask |= fn_ctr_mask;
648 fn_ctr_mask = 0;
649 }
ca29da43
NS
650}
651
5366b186 652/* Build a coverage variable of TYPE for function FN_DECL. If COUNTER
0e485da0 653 >= 0 it is a counter array, otherwise it is the function structure. */
ca29da43 654
ca29da43 655static tree
5366b186
NS
656build_var (tree fn_decl, tree type, int counter)
657{
658 tree var = build_decl (BUILTINS_LOCATION, VAR_DECL, NULL_TREE, type);
659 tree fn_name = DECL_ASSEMBLER_NAME (fn_decl);
660 char *buf = (char *)alloca (IDENTIFIER_LENGTH (fn_name) + 10);
661
5366b186
NS
662 if (counter < 0)
663 sprintf (buf, "__gcov__%s", IDENTIFIER_POINTER (fn_name));
664 else
665 sprintf (buf, "__gcov%u_%s", counter, IDENTIFIER_POINTER (fn_name));
666 DECL_NAME (var) = get_identifier (buf);
89b0c303
NS
667 TREE_STATIC (var) = 1;
668 TREE_ADDRESSABLE (var) = 1;
669 DECL_ALIGN (var) = TYPE_ALIGN (type);
5366b186
NS
670
671 return var;
672}
673
674/* Creates the gcov_fn_info RECORD_TYPE. */
675
676static void
677build_fn_info_type (tree type, unsigned counters, tree gcov_info_type)
ca29da43 678{
5366b186 679 tree ctr_info = lang_hooks.types.make_type (RECORD_TYPE);
ca29da43 680 tree field, fields;
cdb23767 681 tree array_type;
159b3be1 682
5366b186
NS
683 gcc_assert (counters);
684
685 /* ctr_info::num */
686 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
687 get_gcov_unsigned_t ());
688 fields = field;
689
690 /* ctr_info::values */
691 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
692 build_pointer_type (get_gcov_type ()));
693 DECL_CHAIN (field) = fields;
694 fields = field;
695
696 finish_builtin_struct (ctr_info, "__gcov_ctr_info", fields, NULL_TREE);
697
698 /* key */
699 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
700 build_pointer_type (build_qualified_type
701 (gcov_info_type, TYPE_QUAL_CONST)));
702 fields = field;
703
796621e8 704 /* ident */
5366b186
NS
705 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
706 get_gcov_unsigned_t ());
707 DECL_CHAIN (field) = fields;
708 fields = field;
709
10adac51 710 /* lineno_checksum */
5366b186
NS
711 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
712 get_gcov_unsigned_t ());
910ad8de 713 DECL_CHAIN (field) = fields;
ca29da43
NS
714 fields = field;
715
10adac51 716 /* cfg checksum */
5366b186
NS
717 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
718 get_gcov_unsigned_t ());
10adac51
XDL
719 DECL_CHAIN (field) = fields;
720 fields = field;
721
f81b1a3d 722 array_type = build_index_type (size_int (counters - 1));
5366b186 723 array_type = build_array_type (ctr_info, array_type);
159b3be1 724
ca29da43 725 /* counters */
5366b186 726 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, array_type);
910ad8de 727 DECL_CHAIN (field) = fields;
ca29da43
NS
728 fields = field;
729
cdb23767 730 finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
ca29da43
NS
731}
732
b724567e
NS
733/* Returns a CONSTRUCTOR for a gcov_fn_info. DATA is
734 the coverage data for the function and TYPE is the gcov_fn_info
735 RECORD_TYPE. KEY is the object file key. */
cdb23767 736
ca29da43 737static tree
b724567e 738build_fn_info (const struct coverage_data *data, tree type, tree key)
ca29da43 739{
cdb23767 740 tree fields = TYPE_FIELDS (type);
5366b186 741 tree ctr_type;
cdb23767 742 unsigned ix;
f9b36bb3
KH
743 VEC(constructor_elt,gc) *v1 = NULL;
744 VEC(constructor_elt,gc) *v2 = NULL;
159b3be1 745
5366b186
NS
746 /* key */
747 CONSTRUCTOR_APPEND_ELT (v1, fields,
748 build1 (ADDR_EXPR, TREE_TYPE (fields), key));
749 fields = DECL_CHAIN (fields);
750
796621e8 751 /* ident */
f9b36bb3
KH
752 CONSTRUCTOR_APPEND_ELT (v1, fields,
753 build_int_cstu (get_gcov_unsigned_t (),
b724567e 754 data->ident));
910ad8de 755 fields = DECL_CHAIN (fields);
159b3be1 756
10adac51
XDL
757 /* lineno_checksum */
758 CONSTRUCTOR_APPEND_ELT (v1, fields,
759 build_int_cstu (get_gcov_unsigned_t (),
b724567e 760 data->lineno_checksum));
10adac51
XDL
761 fields = DECL_CHAIN (fields);
762
763 /* cfg_checksum */
f9b36bb3
KH
764 CONSTRUCTOR_APPEND_ELT (v1, fields,
765 build_int_cstu (get_gcov_unsigned_t (),
b724567e 766 data->cfg_checksum));
910ad8de 767 fields = DECL_CHAIN (fields);
159b3be1 768
ca29da43 769 /* counters */
5366b186 770 ctr_type = TREE_TYPE (TREE_TYPE (fields));
cdb23767
NS
771 for (ix = 0; ix != GCOV_COUNTERS; ix++)
772 if (prg_ctr_mask & (1 << ix))
5366b186
NS
773 {
774 VEC(constructor_elt,gc) *ctr = NULL;
b724567e 775 tree var = data->ctr_vars[ix];
5366b186
NS
776 unsigned count = 0;
777
778 if (var)
779 count
780 = tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (var))), 0)
781 + 1;
782
783 CONSTRUCTOR_APPEND_ELT (ctr, TYPE_FIELDS (ctr_type),
784 build_int_cstu (get_gcov_unsigned_t (),
785 count));
786
787 if (var)
788 CONSTRUCTOR_APPEND_ELT (ctr, DECL_CHAIN (TYPE_FIELDS (ctr_type)),
789 build_fold_addr_expr (var));
790
791 CONSTRUCTOR_APPEND_ELT (v2, NULL, build_constructor (ctr_type, ctr));
792 }
793
f9b36bb3
KH
794 CONSTRUCTOR_APPEND_ELT (v1, fields,
795 build_constructor (TREE_TYPE (fields), v2));
159b3be1 796
f9b36bb3 797 return build_constructor (type, v1);
ca29da43
NS
798}
799
b724567e
NS
800/* Create gcov_info struct. TYPE is the incomplete RECORD_TYPE to be
801 completed, and FN_INFO_PTR_TYPE is a pointer to the function info type. */
cdb23767 802
5366b186 803static void
b724567e 804build_info_type (tree type, tree fn_info_ptr_type)
ca29da43 805{
cdb23767 806 tree field, fields = NULL_TREE;
b724567e 807 tree merge_fn_type;
9b514d25 808
5366b186
NS
809 /* Version ident */
810 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
811 get_gcov_unsigned_t ());
910ad8de 812 DECL_CHAIN (field) = fields;
ca29da43
NS
813 fields = field;
814
5366b186
NS
815 /* next pointer */
816 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
817 build_pointer_type (build_qualified_type
818 (type, TYPE_QUAL_CONST)));
910ad8de 819 DECL_CHAIN (field) = fields;
ca29da43
NS
820 fields = field;
821
5366b186
NS
822 /* stamp */
823 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
824 get_gcov_unsigned_t ());
910ad8de 825 DECL_CHAIN (field) = fields;
09780dfb
ZD
826 fields = field;
827
5366b186
NS
828 /* Filename */
829 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
830 build_pointer_type (build_qualified_type
831 (char_type_node, TYPE_QUAL_CONST)));
832 DECL_CHAIN (field) = fields;
833 fields = field;
ca29da43 834
5366b186
NS
835 /* merge fn array */
836 merge_fn_type
837 = build_function_type_list (void_type_node,
838 build_pointer_type (get_gcov_type ()),
839 get_gcov_unsigned_t (), NULL_TREE);
840 merge_fn_type
841 = build_array_type (build_pointer_type (merge_fn_type),
842 build_index_type (size_int (GCOV_COUNTERS - 1)));
843 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
844 merge_fn_type);
845 DECL_CHAIN (field) = fields;
846 fields = field;
847
848 /* n_functions */
849 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
850 get_gcov_unsigned_t ());
851 DECL_CHAIN (field) = fields;
852 fields = field;
853
b724567e
NS
854 /* function_info pointer pointer */
855 fn_info_ptr_type = build_pointer_type
856 (build_qualified_type (fn_info_ptr_type, TYPE_QUAL_CONST));
5366b186 857 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
b724567e 858 fn_info_ptr_type);
5366b186
NS
859 DECL_CHAIN (field) = fields;
860 fields = field;
09780dfb 861
5366b186 862 finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
ca29da43
NS
863}
864
b724567e
NS
865/* Returns a CONSTRUCTOR for the gcov_info object. INFO_TYPE is the
866 gcov_info structure type, FN_ARY is the array of pointers to
867 function info objects. */
cdb23767 868
ca29da43 869static tree
b724567e 870build_info (tree info_type, tree fn_ary)
ca29da43 871{
5366b186 872 tree info_fields = TYPE_FIELDS (info_type);
b724567e 873 tree merge_fn_type, n_funcs;
5366b186 874 unsigned ix;
cdb23767 875 tree filename_string;
2f908293 876 int da_file_name_len;
f9b36bb3
KH
877 VEC(constructor_elt,gc) *v1 = NULL;
878 VEC(constructor_elt,gc) *v2 = NULL;
159b3be1 879
cdb23767 880 /* Version ident */
5366b186
NS
881 CONSTRUCTOR_APPEND_ELT (v1, info_fields,
882 build_int_cstu (TREE_TYPE (info_fields),
883 GCOV_VERSION));
884 info_fields = DECL_CHAIN (info_fields);
159b3be1 885
ca29da43 886 /* next -- NULL */
5366b186
NS
887 CONSTRUCTOR_APPEND_ELT (v1, info_fields, null_pointer_node);
888 info_fields = DECL_CHAIN (info_fields);
889
dd486eb2 890 /* stamp */
5366b186
NS
891 CONSTRUCTOR_APPEND_ELT (v1, info_fields,
892 build_int_cstu (TREE_TYPE (info_fields),
893 local_tick));
894 info_fields = DECL_CHAIN (info_fields);
dd486eb2 895
ca29da43 896 /* Filename */
2f908293
SP
897 da_file_name_len = strlen (da_file_name);
898 filename_string = build_string (da_file_name_len + 1, da_file_name);
4a90aeeb 899 TREE_TYPE (filename_string) = build_array_type
f81b1a3d 900 (char_type_node, build_index_type (size_int (da_file_name_len)));
5366b186
NS
901 CONSTRUCTOR_APPEND_ELT (v1, info_fields,
902 build1 (ADDR_EXPR, TREE_TYPE (info_fields),
903 filename_string));
904 info_fields = DECL_CHAIN (info_fields);
159b3be1 905
5366b186
NS
906 /* merge fn array -- NULL slots indicate unmeasured counters */
907 merge_fn_type = TREE_TYPE (TREE_TYPE (info_fields));
908 for (ix = 0; ix != GCOV_COUNTERS; ix++)
ca29da43 909 {
5366b186 910 tree ptr = null_pointer_node;
159b3be1 911
5366b186
NS
912 if ((1u << ix) & prg_ctr_mask)
913 {
914 tree merge_fn = build_decl (BUILTINS_LOCATION,
915 FUNCTION_DECL,
916 get_identifier (ctr_merge_functions[ix]),
917 TREE_TYPE (merge_fn_type));
918 DECL_EXTERNAL (merge_fn) = 1;
919 TREE_PUBLIC (merge_fn) = 1;
920 DECL_ARTIFICIAL (merge_fn) = 1;
921 TREE_NOTHROW (merge_fn) = 1;
922 /* Initialize assembler name so we can stream out. */
923 DECL_ASSEMBLER_NAME (merge_fn);
924 ptr = build1 (ADDR_EXPR, merge_fn_type, merge_fn);
925 }
926 CONSTRUCTOR_APPEND_ELT (v2, NULL, ptr);
ca29da43 927 }
5366b186
NS
928 CONSTRUCTOR_APPEND_ELT (v1, info_fields,
929 build_constructor (TREE_TYPE (info_fields), v2));
930 info_fields = DECL_CHAIN (info_fields);
931
932 /* n_functions */
b724567e
NS
933 n_funcs = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (fn_ary)));
934 n_funcs = fold_build2 (PLUS_EXPR, TREE_TYPE (info_fields),
935 n_funcs, size_one_node);
936 CONSTRUCTOR_APPEND_ELT (v1, info_fields, n_funcs);
5366b186 937 info_fields = DECL_CHAIN (info_fields);
5366b186 938
b724567e 939 /* functions */
5366b186 940 CONSTRUCTOR_APPEND_ELT (v1, info_fields,
b724567e
NS
941 build1 (ADDR_EXPR, TREE_TYPE (info_fields), fn_ary));
942 info_fields = DECL_CHAIN (info_fields);
943
944 gcc_assert (!info_fields);
5366b186 945 return build_constructor (info_type, v1);
ca29da43
NS
946}
947
b724567e
NS
948/* Create the gcov_info types and object. Generate the constructor
949 function to call __gcov_init. Does not generate the initializer
950 for the object. Returns TRUE if coverage data is being emitted. */
ca29da43 951
b724567e
NS
952static bool
953coverage_obj_init (void)
ca29da43 954{
b724567e
NS
955 tree gcov_info_type, ctor, stmt, init_fn;
956 unsigned n_counters = 0;
5366b186 957 unsigned ix;
b724567e
NS
958 struct coverage_data *fn;
959 struct coverage_data **fn_prev;
c9b9aa64 960 char name_buf[32];
ca29da43 961
6d70e6be 962 no_coverage = 1; /* Disable any further coverage. */
159b3be1 963
cdb23767 964 if (!prg_ctr_mask)
b724567e 965 return false;
159b3be1 966
5366b186
NS
967 if (cgraph_dump_file)
968 fprintf (cgraph_dump_file, "Using data file %s\n", da_file_name);
ca29da43 969
b724567e 970 /* Prune functions. */
5366b186
NS
971 for (fn_prev = &functions_head; (fn = *fn_prev);)
972 if (DECL_STRUCT_FUNCTION (fn->fn_decl))
b724567e 973 fn_prev = &fn->next;
5366b186
NS
974 else
975 /* The function is not being emitted, remove from list. */
976 *fn_prev = fn->next;
b724567e
NS
977
978 for (ix = 0; ix != GCOV_COUNTERS; ix++)
979 if ((1u << ix) & prg_ctr_mask)
980 n_counters++;
5366b186
NS
981
982 /* Build the info and fn_info types. These are mutually recursive. */
983 gcov_info_type = lang_hooks.types.make_type (RECORD_TYPE);
b724567e
NS
984 gcov_fn_info_type = lang_hooks.types.make_type (RECORD_TYPE);
985 gcov_fn_info_ptr_type = build_pointer_type
986 (build_qualified_type (gcov_fn_info_type, TYPE_QUAL_CONST));
987 build_fn_info_type (gcov_fn_info_type, n_counters, gcov_info_type);
988 build_info_type (gcov_info_type, gcov_fn_info_ptr_type);
5366b186
NS
989
990 /* Build the gcov info var, this is referred to in its own
991 initializer. */
b724567e
NS
992 gcov_info_var = build_decl (BUILTINS_LOCATION,
993 VAR_DECL, NULL_TREE, gcov_info_type);
994 TREE_STATIC (gcov_info_var) = 1;
c9b9aa64 995 ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
b724567e 996 DECL_NAME (gcov_info_var) = get_identifier (name_buf);
ca29da43 997
c9b9aa64 998 /* Build a decl for __gcov_init. */
b724567e
NS
999 init_fn = build_pointer_type (gcov_info_type);
1000 init_fn = build_function_type_list (void_type_node, init_fn, NULL);
1001 init_fn = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
1002 get_identifier ("__gcov_init"), init_fn);
1003 TREE_PUBLIC (init_fn) = 1;
1004 DECL_EXTERNAL (init_fn) = 1;
1005 DECL_ASSEMBLER_NAME (init_fn);
c9b9aa64
RH
1006
1007 /* Generate a call to __gcov_init(&gcov_info). */
b724567e
NS
1008 ctor = NULL;
1009 stmt = build_fold_addr_expr (gcov_info_var);
1010 stmt = build_call_expr (init_fn, 1, stmt);
1011 append_to_statement_list (stmt, &ctor);
c9b9aa64
RH
1012
1013 /* Generate a constructor to run it. */
b724567e
NS
1014 cgraph_build_static_cdtor ('I', ctor, DEFAULT_INIT_PRIORITY);
1015
1016 return true;
ca29da43 1017}
b724567e
NS
1018
1019/* Generate the coverage function info for FN and DATA. Append a
1020 pointer to that object to CTOR and return the appended CTOR. */
1021
1022static VEC(constructor_elt,gc) *
1023coverage_obj_fn (VEC(constructor_elt,gc) *ctor, tree fn,
1024 struct coverage_data const *data)
1025{
1026 tree init = build_fn_info (data, gcov_fn_info_type, gcov_info_var);
1027 tree var = build_var (fn, gcov_fn_info_type, -1);
1028
1029 DECL_INITIAL (var) = init;
1030 varpool_finalize_decl (var);
1031
1032 CONSTRUCTOR_APPEND_ELT (ctor, NULL,
1033 build1 (ADDR_EXPR, gcov_fn_info_ptr_type, var));
1034 return ctor;
1035}
1036
1037/* Finalize the coverage data. Generates the array of pointers to
1038 function objects from CTOR. Generate the gcov_info initializer. */
1039
1040static void
1041coverage_obj_finish (VEC(constructor_elt,gc) *ctor)
1042{
1043 unsigned n_functions = VEC_length(constructor_elt, ctor);
1044 tree fn_info_ary_type = build_array_type
1045 (build_qualified_type (gcov_fn_info_ptr_type, TYPE_QUAL_CONST),
1046 build_index_type (size_int (n_functions - 1)));
1047 tree fn_info_ary = build_decl (BUILTINS_LOCATION, VAR_DECL, NULL_TREE,
1048 fn_info_ary_type);
1049 char name_buf[32];
1050
1051 TREE_STATIC (fn_info_ary) = 1;
1052 ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 1);
1053 DECL_NAME (fn_info_ary) = get_identifier (name_buf);
1054 DECL_INITIAL (fn_info_ary) = build_constructor (fn_info_ary_type, ctor);
1055 varpool_finalize_decl (fn_info_ary);
1056
1057 DECL_INITIAL (gcov_info_var)
1058 = build_info (TREE_TYPE (gcov_info_var), fn_info_ary);
1059 varpool_finalize_decl (gcov_info_var);
1060}
1061
ca29da43 1062/* Perform file-level initialization. Read in data file, generate name
71c0e7fc 1063 of graph file. */
ca29da43
NS
1064
1065void
159b3be1 1066coverage_init (const char *filename)
ca29da43
NS
1067{
1068 int len = strlen (filename);
b724567e 1069 int prefix_len = 0;
b8698a0f 1070
b724567e 1071 if (!profile_data_prefix && !IS_ABSOLUTE_PATH (filename))
2f908293
SP
1072 profile_data_prefix = getpwd ();
1073
b724567e
NS
1074 if (profile_data_prefix)
1075 prefix_len = strlen (profile_data_prefix);
ca29da43 1076
796621e8 1077 /* Name of da file. */
b8698a0f 1078 da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX)
b724567e 1079 + prefix_len + 2);
2f908293
SP
1080
1081 if (profile_data_prefix)
1082 {
b724567e
NS
1083 memcpy (da_file_name, profile_data_prefix, prefix_len);
1084 da_file_name[prefix_len++] = '/';
2f908293 1085 }
b724567e
NS
1086 memcpy (da_file_name + prefix_len, filename, len);
1087 strcpy (da_file_name + prefix_len + len, GCOV_DATA_SUFFIX);
159b3be1 1088
796621e8 1089 /* Name of bbg file. */
b724567e
NS
1090 if (flag_test_coverage && !flag_compare_debug)
1091 {
1092 bbg_file_name = XNEWVEC (char, len + strlen (GCOV_NOTE_SUFFIX) + 1);
1093 memcpy (bbg_file_name, filename, len);
1094 strcpy (bbg_file_name + len, GCOV_NOTE_SUFFIX);
1095
1096 if (!gcov_open (bbg_file_name, -1))
1097 {
1098 error ("cannot open %s", bbg_file_name);
1099 bbg_file_name = NULL;
1100 }
1101 else
1102 {
1103 gcov_write_unsigned (GCOV_NOTE_MAGIC);
1104 gcov_write_unsigned (GCOV_VERSION);
1105 gcov_write_unsigned (local_tick);
1106 }
1107 }
796621e8 1108
cb89a171 1109 if (flag_branch_probabilities)
2f908293 1110 read_counts_file ();
ca29da43
NS
1111}
1112
1113/* Performs file-level cleanup. Close graph file, generate coverage
1114 variables and constructor. */
1115
1116void
159b3be1 1117coverage_finish (void)
ca29da43 1118{
b724567e
NS
1119 if (bbg_file_name && gcov_close ())
1120 unlink (bbg_file_name);
1121
bdbdc4e1 1122 if (!local_tick || local_tick == (unsigned)-1)
b724567e
NS
1123 /* Only remove the da file, if we cannot stamp it. If we can
1124 stamp it, libgcov will DTRT. */
1125 unlink (da_file_name);
1126
1127 if (coverage_obj_init ())
ca29da43 1128 {
b724567e
NS
1129 VEC(constructor_elt,gc) *fn_ctor = NULL;
1130 struct coverage_data *fn;
1131
1132 for (fn = functions_head; fn; fn = fn->next)
1133 fn_ctor = coverage_obj_fn (fn_ctor, fn->fn_decl, fn);
1134 coverage_obj_finish (fn_ctor);
ca29da43
NS
1135 }
1136}
1137
ca29da43 1138#include "gt-coverage.h"