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