]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/coverage.c
* doc/install.texi (Specific, alpha): Remove note to use
[thirdparty/gcc.git] / gcc / coverage.c
CommitLineData
44359ced 1/* Read and write coverage files, and associated functionality.
fbd26352 2 Copyright (C) 1990-2019 Free Software Foundation, Inc.
44359ced 3 Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
4 based on some ideas from Dain Samples of UC Berkeley.
5 Further mangling by Bob Manson, Cygnus Support.
6 Further mangled by Nathan Sidwell, CodeSourcery
7
8This file is part of GCC.
9
10GCC is free software; you can redistribute it and/or modify it under
11the terms of the GNU General Public License as published by the Free
8c4c00c1 12Software Foundation; either version 3, or (at your option) any later
44359ced 13version.
14
15GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16WARRANTY; without even the implied warranty of MERCHANTABILITY or
17FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18for more details.
19
20You should have received a copy of the GNU General Public License
8c4c00c1 21along with GCC; see the file COPYING3. If not see
22<http://www.gnu.org/licenses/>. */
44359ced 23
24
25#define GCOV_LINKAGE
26
27#include "config.h"
28#include "system.h"
29#include "coretypes.h"
9ef16211 30#include "backend.h"
7c29e30e 31#include "target.h"
44359ced 32#include "rtl.h"
33#include "tree.h"
7c29e30e 34#include "tree-pass.h"
ad7b10a2 35#include "memmodel.h"
7c29e30e 36#include "tm_p.h"
9ed99284 37#include "stringpool.h"
7c29e30e 38#include "cgraph.h"
39#include "coverage.h"
40#include "diagnostic-core.h"
7c29e30e 41#include "fold-const.h"
9ed99284 42#include "stor-layout.h"
44359ced 43#include "output.h"
44359ced 44#include "toplev.h"
44359ced 45#include "langhooks.h"
b5530559 46#include "tree-iterator.h"
202c2bd9 47#include "context.h"
48#include "pass_manager.h"
21cd990d 49#include "intl.h"
d9e50003 50#include "params.h"
94bed7c3 51#include "auto-profile.h"
56621355 52#include "profile.h"
44359ced 53
54#include "gcov-io.c"
55
6c56d3c9 56struct GTY((chain_next ("%h.next"))) coverage_data
44359ced 57{
6c56d3c9 58 struct coverage_data *next; /* next function */
89a1f620 59 unsigned ident; /* function ident */
06306fd3 60 unsigned lineno_checksum; /* function lineno checksum */
61 unsigned cfg_checksum; /* function cfg checksum */
5014df5d 62 tree fn_decl; /* the function decl */
63 tree ctr_vars[GCOV_COUNTERS]; /* counter variables. */
44359ced 64};
65
66/* Counts information for a function. */
04009ada 67struct counts_entry : pointer_hash <counts_entry>
44359ced 68{
69 /* We hash by */
3f2c2dd8 70 unsigned ident;
ab6a34f2 71 unsigned ctr;
89a1f620 72
44359ced 73 /* Store */
06306fd3 74 unsigned lineno_checksum;
75 unsigned cfg_checksum;
44359ced 76 gcov_type *counts;
bed69f86 77 unsigned n_counts;
494bbaae 78
79 /* hash_table support. */
9969c043 80 static inline hashval_t hash (const counts_entry *);
81 static int equal (const counts_entry *, const counts_entry *);
82 static void remove (counts_entry *);
04009ada 83};
44359ced 84
6c56d3c9 85static GTY(()) struct coverage_data *functions_head = 0;
86static struct coverage_data **functions_tail = &functions_head;
015af757 87static unsigned no_coverage = 0;
44359ced 88
ab6a34f2 89/* Cumulative counter information for whole program. */
90static unsigned prg_ctr_mask; /* Mask of counter types generated. */
44359ced 91
ab6a34f2 92/* Counter information for current function. */
6473f3f4 93static unsigned fn_ctr_mask; /* Mask of counters used. */
5014df5d 94static GTY(()) tree fn_v_ctrs[GCOV_COUNTERS]; /* counter variables. */
015af757 95static unsigned fn_n_ctrs[GCOV_COUNTERS]; /* Counters allocated. */
96static unsigned fn_b_ctrs[GCOV_COUNTERS]; /* Allocation base. */
44359ced 97
6c56d3c9 98/* Coverage info VAR_DECL and function info type nodes. */
99static GTY(()) tree gcov_info_var;
100static GTY(()) tree gcov_fn_info_type;
101static GTY(()) tree gcov_fn_info_ptr_type;
102
56b17dd7 103/* Name of the notes (gcno) output file. The "bbg" prefix is for
104 historical reasons, when the notes file contained only the
105 basic block graph notes.
106 If this is NULL we're not writing to the notes file. */
44359ced 107static char *bbg_file_name;
44359ced 108
56b17dd7 109/* File stamp for notes file. */
267dc7fa 110static unsigned bbg_file_stamp;
111
56b17dd7 112/* Name of the count data (gcda) file. */
44359ced 113static char *da_file_name;
114
35cb45c4 115/* The names of merge functions for counters. */
e76f6040 116#define STR(str) #str
117#define DEF_GCOV_COUNTER(COUNTER, NAME, FN_TYPE) STR(__gcov_merge ## FN_TYPE),
118static const char *const ctr_merge_functions[GCOV_COUNTERS] = {
119#include "gcov-counter.def"
120};
121#undef DEF_GCOV_COUNTER
122#undef STR
123
124#define DEF_GCOV_COUNTER(COUNTER, NAME, FN_TYPE) NAME,
125static const char *const ctr_names[GCOV_COUNTERS] = {
126#include "gcov-counter.def"
127};
128#undef DEF_GCOV_COUNTER
35cb45c4 129
44359ced 130/* Forward declarations. */
89a1f620 131static void read_counts_file (void);
5014df5d 132static tree build_var (tree, tree, int);
133static void build_fn_info_type (tree, unsigned, tree);
6c56d3c9 134static void build_info_type (tree, tree);
135static tree build_fn_info (const struct coverage_data *, tree, tree);
136static tree build_info (tree, tree);
137static bool coverage_obj_init (void);
f1f41a6c 138static vec<constructor_elt, va_gc> *coverage_obj_fn
139(vec<constructor_elt, va_gc> *, tree, struct coverage_data const *);
140static void coverage_obj_finish (vec<constructor_elt, va_gc> *);
b1b07349 141\f
142/* Return the type node for gcov_type. */
143
144tree
145get_gcov_type (void)
146{
1a5d4b27 147 scalar_int_mode mode
148 = smallest_int_mode_for_size (LONG_LONG_TYPE_SIZE > 32 ? 64 : 32);
1b3c3119 149 return lang_hooks.types.type_for_mode (mode, false);
b1b07349 150}
151
152/* Return the type node for gcov_unsigned_t. */
44359ced 153
b1b07349 154static tree
155get_gcov_unsigned_t (void)
156{
1a5d4b27 157 scalar_int_mode mode = smallest_int_mode_for_size (32);
1b3c3119 158 return lang_hooks.types.type_for_mode (mode, true);
b1b07349 159}
44359ced 160\f
2b15d2ba 161inline hashval_t
9969c043 162counts_entry::hash (const counts_entry *entry)
44359ced 163{
3f2c2dd8 164 return entry->ident * GCOV_COUNTERS + entry->ctr;
44359ced 165}
166
2b15d2ba 167inline int
9969c043 168counts_entry::equal (const counts_entry *entry1, const counts_entry *entry2)
44359ced 169{
3f2c2dd8 170 return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
44359ced 171}
172
2b15d2ba 173inline void
9969c043 174counts_entry::remove (counts_entry *entry)
44359ced 175{
44359ced 176 free (entry->counts);
177 free (entry);
178}
179
2b15d2ba 180/* Hash table of count data. */
c1f445d2 181static hash_table<counts_entry> *counts_hash;
2b15d2ba 182
44359ced 183/* Read in the counts file, if available. */
184
185static void
89a1f620 186read_counts_file (void)
44359ced 187{
834f169c 188 gcov_unsigned_t fn_ident = 0;
80abd9e4 189 gcov_unsigned_t tag;
6e4c20c9 190 int is_error = 0;
06306fd3 191 unsigned lineno_checksum = 0;
192 unsigned cfg_checksum = 0;
80abd9e4 193
44359ced 194 if (!gcov_open (da_file_name, 1))
195 return;
89a1f620 196
b4d48d67 197 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
44359ced 198 {
c3ceba8e 199 warning (0, "%qs is not a gcov data file", da_file_name);
44359ced 200 gcov_close ();
201 return;
202 }
b4d48d67 203 else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
44359ced 204 {
9e0943d4 205 char v[4], e[4];
206
207 GCOV_UNSIGNED2STRING (v, tag);
208 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
89a1f620 209
c3ceba8e 210 warning (0, "%qs is version %q.*s, expected version %q.*s",
841b0dee 211 da_file_name, 4, v, 4, e);
44359ced 212 gcov_close ();
213 return;
214 }
89a1f620 215
267dc7fa 216 /* Read the stamp, used for creating a generation count. */
217 tag = gcov_read_unsigned ();
218 bbg_file_stamp = crc32_unsigned (bbg_file_stamp, tag);
48e1416a 219
c1f445d2 220 counts_hash = new hash_table<counts_entry> (10);
80abd9e4 221 while ((tag = gcov_read_unsigned ()))
44359ced 222 {
80abd9e4 223 gcov_unsigned_t length;
834f169c 224 gcov_position_t offset;
89a1f620 225
44359ced 226 length = gcov_read_unsigned ();
227 offset = gcov_position ();
228 if (tag == GCOV_TAG_FUNCTION)
229 {
5014df5d 230 if (length)
44359ced 231 {
5014df5d 232 fn_ident = gcov_read_unsigned ();
233 lineno_checksum = gcov_read_unsigned ();
234 cfg_checksum = gcov_read_unsigned ();
44359ced 235 }
5014df5d 236 else
237 fn_ident = lineno_checksum = cfg_checksum = 0;
44359ced 238 }
56621355 239 else if (tag == GCOV_TAG_OBJECT_SUMMARY)
44359ced 240 {
56621355 241 profile_info = XCNEW (gcov_summary);
242 profile_info->runs = gcov_read_unsigned ();
243 profile_info->sum_max = gcov_read_unsigned ();
44359ced 244 }
3f2c2dd8 245 else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
44359ced 246 {
04009ada 247 counts_entry **slot, *entry, elt;
9e0943d4 248 unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
44359ced 249 unsigned ix;
250
3f2c2dd8 251 elt.ident = fn_ident;
ab6a34f2 252 elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
44359ced 253
c1f445d2 254 slot = counts_hash->find_slot (&elt, INSERT);
44359ced 255 entry = *slot;
256 if (!entry)
257 {
04009ada 258 *slot = entry = XCNEW (counts_entry);
06306fd3 259 entry->ident = fn_ident;
ab6a34f2 260 entry->ctr = elt.ctr;
06306fd3 261 entry->lineno_checksum = lineno_checksum;
262 entry->cfg_checksum = cfg_checksum;
4c36ffe6 263 entry->counts = XCNEWVEC (gcov_type, n_counts);
bed69f86 264 entry->n_counts = n_counts;
44359ced 265 }
06306fd3 266 else if (entry->lineno_checksum != lineno_checksum
267 || entry->cfg_checksum != cfg_checksum)
44359ced 268 {
06306fd3 269 error ("Profile data for function %u is corrupted", fn_ident);
270 error ("checksum is (%x,%x) instead of (%x,%x)",
271 entry->lineno_checksum, entry->cfg_checksum,
272 lineno_checksum, cfg_checksum);
c1f445d2 273 delete counts_hash;
274 counts_hash = NULL;
6e4c20c9 275 break;
276 }
44359ced 277 for (ix = 0; ix != n_counts; ix++)
278 entry->counts[ix] += gcov_read_counter ();
279 }
3ddf7676 280 gcov_sync (offset, length);
6e4c20c9 281 if ((is_error = gcov_is_error ()))
421055ca 282 {
1caf9cb4 283 error (is_error < 0
284 ? G_("%qs has overflowed")
285 : G_("%qs is corrupted"),
421055ca 286 da_file_name);
c1f445d2 287 delete counts_hash;
288 counts_hash = NULL;
421055ca 289 break;
290 }
80abd9e4 291 }
89a1f620 292
44359ced 293 gcov_close ();
294}
295
296/* Returns the counters for a particular tag. */
297
298gcov_type *
56621355 299get_coverage_counts (unsigned counter, unsigned cfg_checksum,
bed69f86 300 unsigned lineno_checksum, unsigned int n_counts)
44359ced 301{
04009ada 302 counts_entry *entry, elt;
44359ced 303
6473f3f4 304 /* No hash table, no counts. */
c1f445d2 305 if (!counts_hash)
44359ced 306 {
307 static int warned = 0;
308
c5fdd880 309 if (!warned++)
c309657f 310 {
c5fdd880 311 warning (OPT_Wmissing_profile,
312 "%qs profile count data file not found",
313 da_file_name);
314 if (dump_enabled_p ())
315 {
316 dump_user_location_t loc
317 = dump_user_location_t::from_location_t (input_location);
a333f643 318 dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
298331ea 319 "file %s not found, %s\n", da_file_name,
320 (flag_guess_branch_prob
321 ? "execution counts estimated"
322 : "execution counts assumed to be zero"));
c5fdd880 323 }
c309657f 324 }
44359ced 325 return NULL;
326 }
d9e50003 327 if (PARAM_VALUE (PARAM_PROFILE_FUNC_INTERNAL_ID))
328 elt.ident = current_function_funcdef_no + 1;
329 else
330 {
331 gcc_assert (coverage_node_map_initialized_p ());
e9780462 332 elt.ident = cgraph_node::get (current_function_decl)->profile_id;
d9e50003 333 }
ab6a34f2 334 elt.ctr = counter;
c1f445d2 335 entry = counts_hash->find (&elt);
56621355 336 if (!entry)
c5fdd880 337 {
338 if (counter == GCOV_COUNTER_ARCS)
339 warning_at (DECL_SOURCE_LOCATION (current_function_decl),
340 OPT_Wmissing_profile,
341 "profile for function %qD not found in profile data",
342 current_function_decl);
343 /* The function was not emitted, or is weak and not chosen in the
344 final executable. Silently fail, because there's nothing we
345 can do about it. */
346 return NULL;
347 }
5014df5d 348
bed69f86 349 if (entry->cfg_checksum != cfg_checksum || entry->n_counts != n_counts)
6e4c20c9 350 {
c81ed7c1 351 static int warned = 0;
21cd990d 352 bool warning_printed = false;
c81ed7c1 353
bed69f86 354 if (entry->n_counts != n_counts)
355 warning_printed =
356 warning_at (DECL_SOURCE_LOCATION (current_function_decl),
357 OPT_Wcoverage_mismatch,
358 "number of counters in profile data for function %qD "
359 "does not match "
360 "its profile data (counter %qs, expected %i and have %i)",
361 current_function_decl,
362 ctr_names[counter], entry->n_counts, n_counts);
363 else
364 warning_printed =
365 warning_at (DECL_SOURCE_LOCATION (current_function_decl),
366 OPT_Wcoverage_mismatch,
367 "the control flow of function %qD does not match "
368 "its profile data (counter %qs)", current_function_decl,
369 ctr_names[counter]);
202c2bd9 370 if (warning_printed && dump_enabled_p ())
c81ed7c1 371 {
c309657f 372 dump_user_location_t loc
295b9056 373 = dump_user_location_t::from_function_decl (current_function_decl);
a333f643 374 dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
202c2bd9 375 "use -Wno-error=coverage-mismatch to tolerate "
376 "the mismatch but performance may drop if the "
78bb46f5 377 "function is hot\n");
21cd990d 378
852f689e 379 if (!seen_error ()
21cd990d 380 && !warned++)
381 {
a333f643 382 dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
78bb46f5 383 "coverage mismatch ignored\n");
a333f643 384 dump_printf (MSG_MISSED_OPTIMIZATION,
78bb46f5 385 flag_guess_branch_prob
386 ? G_("execution counts estimated\n")
387 : G_("execution counts assumed to be zero\n"));
21cd990d 388 if (!flag_guess_branch_prob)
a333f643 389 dump_printf (MSG_MISSED_OPTIMIZATION,
78bb46f5 390 "this can result in poorly optimized code\n");
21cd990d 391 }
c81ed7c1 392 }
393
394 return NULL;
44359ced 395 }
5014df5d 396 else if (entry->lineno_checksum != lineno_checksum)
397 {
1ace3cd9 398 warning_at (DECL_SOURCE_LOCATION (current_function_decl),
399 OPT_Wcoverage_mismatch,
400 "source locations for function %qD have changed,"
401 " the profile data may be out of date",
402 current_function_decl);
5014df5d 403 }
89a1f620 404
44359ced 405 return entry->counts;
406}
ab6a34f2 407
7ef5b942 408/* Allocate NUM counters of type COUNTER. Returns nonzero if the
015af757 409 allocation succeeded. */
ab6a34f2 410
015af757 411int
412coverage_counter_alloc (unsigned counter, unsigned num)
ab6a34f2 413{
015af757 414 if (no_coverage)
415 return 0;
89a1f620 416
015af757 417 if (!num)
418 return 1;
89a1f620 419
5014df5d 420 if (!fn_v_ctrs[counter])
ab6a34f2 421 {
5014df5d 422 tree array_type = build_array_type (get_gcov_type (), NULL_TREE);
423
424 fn_v_ctrs[counter]
425 = build_var (current_function_decl, array_type, counter);
ab6a34f2 426 }
5014df5d 427
015af757 428 fn_b_ctrs[counter] = fn_n_ctrs[counter];
429 fn_n_ctrs[counter] += num;
5014df5d 430
015af757 431 fn_ctr_mask |= 1 << counter;
432 return 1;
433}
ab6a34f2 434
4ee9c684 435/* Generate a tree to access COUNTER NO. */
436
437tree
438tree_coverage_counter_ref (unsigned counter, unsigned no)
439{
8aa35772 440 tree gcov_type_node = get_gcov_type ();
4ee9c684 441
cc636d56 442 gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
4ee9c684 443
5014df5d 444 no += fn_b_ctrs[counter];
445
4ee9c684 446 /* "no" here is an array index, scaled to bytes later. */
5014df5d 447 return build4 (ARRAY_REF, gcov_type_node, fn_v_ctrs[counter],
2c46738d 448 build_int_cst (integer_type_node, no), NULL, NULL);
4ee9c684 449}
a961cdc2 450
451/* Generate a tree to access the address of COUNTER NO. */
452
453tree
454tree_coverage_counter_addr (unsigned counter, unsigned no)
455{
456 tree gcov_type_node = get_gcov_type ();
457
458 gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
5014df5d 459 no += fn_b_ctrs[counter];
86f2ad37 460
a961cdc2 461 /* "no" here is an array index, scaled to bytes later. */
462 return build_fold_addr_expr (build4 (ARRAY_REF, gcov_type_node,
5014df5d 463 fn_v_ctrs[counter],
2c46738d 464 build_int_cst (integer_type_node, no),
a961cdc2 465 NULL, NULL));
466}
44359ced 467\f
06306fd3 468
44359ced 469/* Generate a checksum for a string. CHKSUM is the current
6473f3f4 470 checksum. */
44359ced 471
472static unsigned
39eca7a3 473coverage_checksum_string (unsigned chksum, const char *string)
44359ced 474{
39eca7a3 475 int i;
476 char *dup = NULL;
477
478 /* Look for everything that looks if it were produced by
db85cc4f 479 get_file_function_name and zero out the second part
39eca7a3 480 that may result from flag_random_seed. This is not critical
481 as the checksums are used only for sanity checking. */
482 for (i = 0; string[i]; i++)
44359ced 483 {
a8ccb8fe 484 int offset = 0;
485 if (!strncmp (string + i, "_GLOBAL__N_", 11))
486 offset = 11;
39eca7a3 487 if (!strncmp (string + i, "_GLOBAL__", 9))
a8ccb8fe 488 offset = 9;
489
490 /* C++ namespaces do have scheme:
491 _GLOBAL__N_<filename>_<wrongmagicnumber>_<magicnumber>functionname
492 since filename might contain extra underscores there seems
493 to be no better chance then walk all possible offsets looking
f0b5f617 494 for magicnumber. */
a8ccb8fe 495 if (offset)
0146470a 496 {
497 for (i = i + offset; string[i]; i++)
498 if (string[i]=='_')
499 {
500 int y;
501
502 for (y = 1; y < 9; y++)
503 if (!(string[i + y] >= '0' && string[i + y] <= '9')
504 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
505 break;
506 if (y != 9 || string[i + 9] != '_')
507 continue;
508 for (y = 10; y < 18; y++)
509 if (!(string[i + y] >= '0' && string[i + y] <= '9')
510 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
511 break;
512 if (y != 18)
513 continue;
514 if (!dup)
515 string = dup = xstrdup (string);
516 for (y = 10; y < 18; y++)
517 dup[i + y] = '0';
518 }
519 break;
520 }
44359ced 521 }
39eca7a3 522
523 chksum = crc32_string (chksum, string);
dd045aee 524 free (dup);
89a1f620 525
44359ced 526 return chksum;
527}
528
529/* Compute checksum for the current function. We generate a CRC32. */
530
06306fd3 531unsigned
532coverage_compute_lineno_checksum (void)
44359ced 533{
2ed8b5d0 534 expanded_location xloc
535 = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
536 unsigned chksum = xloc.line;
44359ced 537
45648efe 538 if (xloc.file)
539 chksum = coverage_checksum_string (chksum, xloc.file);
39eca7a3 540 chksum = coverage_checksum_string
44359ced 541 (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
542
543 return chksum;
544}
06306fd3 545
fe37be54 546/* Compute profile ID. This is better to be unique in whole program. */
547
548unsigned
549coverage_compute_profile_id (struct cgraph_node *n)
550{
df565eb6 551 unsigned chksum;
fe37be54 552
df565eb6 553 /* Externally visible symbols have unique name. */
64f3d828 554 if (TREE_PUBLIC (n->decl) || DECL_EXTERNAL (n->decl) || n->unique_name)
df565eb6 555 {
556 chksum = coverage_checksum_string
557 (0, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (n->decl)));
558 }
559 else
560 {
561 expanded_location xloc
562 = expand_location (DECL_SOURCE_LOCATION (n->decl));
d9e50003 563 bool use_name_only = (PARAM_VALUE (PARAM_PROFILE_FUNC_INTERNAL_ID) == 0);
df565eb6 564
d9e50003 565 chksum = (use_name_only ? 0 : xloc.line);
45648efe 566 if (xloc.file)
567 chksum = coverage_checksum_string (chksum, xloc.file);
df565eb6 568 chksum = coverage_checksum_string
569 (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (n->decl)));
d9e50003 570 if (!use_name_only && first_global_object_name)
df565eb6 571 chksum = coverage_checksum_string
572 (chksum, first_global_object_name);
573 chksum = coverage_checksum_string
574 (chksum, aux_base_name);
575 }
fe37be54 576
64f3d828 577 /* Non-negative integers are hopefully small enough to fit in all targets.
578 Gcov file formats wants non-zero function IDs. */
579 chksum = chksum & 0x7fffffff;
580 return chksum + (!chksum);
fe37be54 581}
582
a06672d4 583/* Compute cfg checksum for the function FN given as argument.
06306fd3 584 The checksum is calculated carefully so that
585 source code changes that doesn't affect the control flow graph
586 won't change the checksum.
587 This is to make the profile data useable across source code change.
588 The downside of this is that the compiler may use potentially
589 wrong profile data - that the source code change has non-trivial impact
590 on the validity of profile data (e.g. the reversed condition)
591 but the compiler won't detect the change and use the wrong profile data. */
592
593unsigned
a06672d4 594coverage_compute_cfg_checksum (struct function *fn)
06306fd3 595{
596 basic_block bb;
a06672d4 597 unsigned chksum = n_basic_blocks_for_fn (fn);
06306fd3 598
a06672d4 599 FOR_EACH_BB_FN (bb, fn)
06306fd3 600 {
601 edge e;
602 edge_iterator ei;
603 chksum = crc32_byte (chksum, bb->index);
604 FOR_EACH_EDGE (e, ei, bb->succs)
605 {
606 chksum = crc32_byte (chksum, e->dest->index);
607 }
608 }
609
610 return chksum;
611}
44359ced 612\f
56b17dd7 613/* Begin output to the notes file for the current function.
6c56d3c9 614 Writes the function header. Returns nonzero if data should be output. */
44359ced 615
616int
6c56d3c9 617coverage_begin_function (unsigned lineno_checksum, unsigned cfg_checksum)
44359ced 618{
6c56d3c9 619 expanded_location xloc;
620 unsigned long offset;
621
3e3a0e9c 622 /* We don't need to output .gcno file unless we're under -ftest-coverage
623 (e.g. -fprofile-arcs/generate/use don't need .gcno to work). */
6c56d3c9 624 if (no_coverage || !bbg_file_name)
015af757 625 return 0;
89a1f620 626
6c56d3c9 627 xloc = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
06306fd3 628
6c56d3c9 629 /* Announce function */
630 offset = gcov_write_tag (GCOV_TAG_FUNCTION);
d9e50003 631 if (PARAM_VALUE (PARAM_PROFILE_FUNC_INTERNAL_ID))
632 gcov_write_unsigned (current_function_funcdef_no + 1);
633 else
634 {
635 gcc_assert (coverage_node_map_initialized_p ());
636 gcov_write_unsigned (
637 cgraph_node::get (current_function_decl)->profile_id);
638 }
639
6c56d3c9 640 gcov_write_unsigned (lineno_checksum);
641 gcov_write_unsigned (cfg_checksum);
642 gcov_write_string (IDENTIFIER_POINTER
643 (DECL_ASSEMBLER_NAME (current_function_decl)));
9d27748d 644 gcov_write_unsigned (DECL_ARTIFICIAL (current_function_decl)
7de708f8 645 && !DECL_FUNCTION_VERSIONED (current_function_decl)
92e4277c 646 && !DECL_LAMBDA_FUNCTION_P (current_function_decl));
9bdf2425 647 gcov_write_filename (xloc.file);
6c56d3c9 648 gcov_write_unsigned (xloc.line);
a82502dd 649 gcov_write_unsigned (xloc.column);
650
651 expanded_location endloc = expand_location (cfun->function_end_locus);
652
653 /* Function can start in a single file and end in another one. */
7aaa2cc6 654 int end_line = endloc.file == xloc.file ? endloc.line : xloc.line;
4e9fa49b 655 int end_column = endloc.file == xloc.file ? endloc.column: xloc.column;
7aaa2cc6 656 gcc_assert (xloc.line <= end_line);
657 gcov_write_unsigned (end_line);
4e9fa49b 658 gcov_write_unsigned (end_column);
6c56d3c9 659 gcov_write_length (offset);
44359ced 660
44359ced 661 return !gcov_is_error ();
662}
663
664/* Finish coverage data for the current function. Verify no output
665 error has occurred. Save function coverage counts. */
666
667void
06306fd3 668coverage_end_function (unsigned lineno_checksum, unsigned cfg_checksum)
44359ced 669{
670 unsigned i;
89a1f620 671
6c56d3c9 672 if (bbg_file_name && gcov_is_error ())
89a1f620 673 {
c3ceba8e 674 warning (0, "error writing %qs", bbg_file_name);
6c56d3c9 675 unlink (bbg_file_name);
676 bbg_file_name = NULL;
44359ced 677 }
ab6a34f2 678
5b0e70ee 679 if (fn_ctr_mask)
ab6a34f2 680 {
5b0e70ee 681 struct coverage_data *item = 0;
682
64f3d828 683 item = ggc_alloc<coverage_data> ();
d9e50003 684
64f3d828 685 if (PARAM_VALUE (PARAM_PROFILE_FUNC_INTERNAL_ID))
686 item->ident = current_function_funcdef_no + 1;
687 else
688 {
689 gcc_assert (coverage_node_map_initialized_p ());
690 item->ident = cgraph_node::get (cfun->decl)->profile_id;
5b0e70ee 691 }
06306fd3 692
64f3d828 693 item->lineno_checksum = lineno_checksum;
694 item->cfg_checksum = cfg_checksum;
695
696 item->fn_decl = current_function_decl;
697 item->next = 0;
698 *functions_tail = item;
699 functions_tail = &item->next;
700
ab6a34f2 701 for (i = 0; i != GCOV_COUNTERS; i++)
702 {
5014df5d 703 tree var = fn_v_ctrs[i];
5b0e70ee 704
705 if (item)
706 item->ctr_vars[i] = var;
5014df5d 707 if (var)
708 {
709 tree array_type = build_index_type (size_int (fn_n_ctrs[i] - 1));
710 array_type = build_array_type (get_gcov_type (), array_type);
711 TREE_TYPE (var) = array_type;
712 DECL_SIZE (var) = TYPE_SIZE (array_type);
713 DECL_SIZE_UNIT (var) = TYPE_SIZE_UNIT (array_type);
97221fd7 714 varpool_node::finalize_decl (var);
5014df5d 715 }
5b0e70ee 716
5014df5d 717 fn_b_ctrs[i] = fn_n_ctrs[i] = 0;
718 fn_v_ctrs[i] = NULL_TREE;
ab6a34f2 719 }
720 prg_ctr_mask |= fn_ctr_mask;
721 fn_ctr_mask = 0;
722 }
44359ced 723}
724
cc563837 725/* Remove coverage file if opened. */
726
727void
728coverage_remove_note_file (void)
729{
730 if (bbg_file_name)
731 {
732 gcov_close ();
733 unlink (bbg_file_name);
734 }
735}
736
5014df5d 737/* Build a coverage variable of TYPE for function FN_DECL. If COUNTER
e3c1d6a7 738 >= 0 it is a counter array, otherwise it is the function structure. */
44359ced 739
44359ced 740static tree
5014df5d 741build_var (tree fn_decl, tree type, int counter)
742{
743 tree var = build_decl (BUILTINS_LOCATION, VAR_DECL, NULL_TREE, type);
8d354582 744 const char *fn_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fn_decl));
745 char *buf;
746 size_t fn_name_len, len;
747
748 fn_name = targetm.strip_name_encoding (fn_name);
749 fn_name_len = strlen (fn_name);
750 buf = XALLOCAVEC (char, fn_name_len + 8 + sizeof (int) * 3);
5014df5d 751
5014df5d 752 if (counter < 0)
8d354582 753 strcpy (buf, "__gcov__");
5014df5d 754 else
8d354582 755 sprintf (buf, "__gcov%u_", counter);
756 len = strlen (buf);
11075c28 757 buf[len - 1] = symbol_table::symbol_suffix_separator ();
8d354582 758 memcpy (buf + len, fn_name, fn_name_len + 1);
5014df5d 759 DECL_NAME (var) = get_identifier (buf);
33087d4d 760 TREE_STATIC (var) = 1;
761 TREE_ADDRESSABLE (var) = 1;
e7e44439 762 DECL_NONALIASED (var) = 1;
5d4b30ea 763 SET_DECL_ALIGN (var, TYPE_ALIGN (type));
5014df5d 764
765 return var;
766}
767
768/* Creates the gcov_fn_info RECORD_TYPE. */
769
770static void
771build_fn_info_type (tree type, unsigned counters, tree gcov_info_type)
44359ced 772{
5014df5d 773 tree ctr_info = lang_hooks.types.make_type (RECORD_TYPE);
44359ced 774 tree field, fields;
ab6a34f2 775 tree array_type;
89a1f620 776
5014df5d 777 gcc_assert (counters);
778
779 /* ctr_info::num */
780 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
781 get_gcov_unsigned_t ());
782 fields = field;
783
784 /* ctr_info::values */
785 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
786 build_pointer_type (get_gcov_type ()));
787 DECL_CHAIN (field) = fields;
788 fields = field;
789
790 finish_builtin_struct (ctr_info, "__gcov_ctr_info", fields, NULL_TREE);
791
792 /* key */
793 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
794 build_pointer_type (build_qualified_type
795 (gcov_info_type, TYPE_QUAL_CONST)));
796 fields = field;
797
3f2c2dd8 798 /* ident */
5014df5d 799 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
800 get_gcov_unsigned_t ());
801 DECL_CHAIN (field) = fields;
802 fields = field;
803
06306fd3 804 /* lineno_checksum */
5014df5d 805 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
806 get_gcov_unsigned_t ());
1767a056 807 DECL_CHAIN (field) = fields;
44359ced 808 fields = field;
809
06306fd3 810 /* cfg checksum */
5014df5d 811 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
812 get_gcov_unsigned_t ());
06306fd3 813 DECL_CHAIN (field) = fields;
814 fields = field;
815
2c46738d 816 array_type = build_index_type (size_int (counters - 1));
5014df5d 817 array_type = build_array_type (ctr_info, array_type);
89a1f620 818
44359ced 819 /* counters */
5014df5d 820 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, array_type);
1767a056 821 DECL_CHAIN (field) = fields;
44359ced 822 fields = field;
823
ab6a34f2 824 finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
44359ced 825}
826
6c56d3c9 827/* Returns a CONSTRUCTOR for a gcov_fn_info. DATA is
828 the coverage data for the function and TYPE is the gcov_fn_info
829 RECORD_TYPE. KEY is the object file key. */
ab6a34f2 830
44359ced 831static tree
6c56d3c9 832build_fn_info (const struct coverage_data *data, tree type, tree key)
44359ced 833{
ab6a34f2 834 tree fields = TYPE_FIELDS (type);
5014df5d 835 tree ctr_type;
ab6a34f2 836 unsigned ix;
f1f41a6c 837 vec<constructor_elt, va_gc> *v1 = NULL;
838 vec<constructor_elt, va_gc> *v2 = NULL;
89a1f620 839
5014df5d 840 /* key */
841 CONSTRUCTOR_APPEND_ELT (v1, fields,
842 build1 (ADDR_EXPR, TREE_TYPE (fields), key));
843 fields = DECL_CHAIN (fields);
844
3f2c2dd8 845 /* ident */
2100aa42 846 CONSTRUCTOR_APPEND_ELT (v1, fields,
847 build_int_cstu (get_gcov_unsigned_t (),
6c56d3c9 848 data->ident));
1767a056 849 fields = DECL_CHAIN (fields);
89a1f620 850
06306fd3 851 /* lineno_checksum */
852 CONSTRUCTOR_APPEND_ELT (v1, fields,
853 build_int_cstu (get_gcov_unsigned_t (),
6c56d3c9 854 data->lineno_checksum));
06306fd3 855 fields = DECL_CHAIN (fields);
856
857 /* cfg_checksum */
2100aa42 858 CONSTRUCTOR_APPEND_ELT (v1, fields,
859 build_int_cstu (get_gcov_unsigned_t (),
6c56d3c9 860 data->cfg_checksum));
1767a056 861 fields = DECL_CHAIN (fields);
89a1f620 862
44359ced 863 /* counters */
5014df5d 864 ctr_type = TREE_TYPE (TREE_TYPE (fields));
ab6a34f2 865 for (ix = 0; ix != GCOV_COUNTERS; ix++)
866 if (prg_ctr_mask & (1 << ix))
5014df5d 867 {
f1f41a6c 868 vec<constructor_elt, va_gc> *ctr = NULL;
6c56d3c9 869 tree var = data->ctr_vars[ix];
5014df5d 870 unsigned count = 0;
871
872 if (var)
873 count
fcb97e84 874 = tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (var))))
5014df5d 875 + 1;
876
877 CONSTRUCTOR_APPEND_ELT (ctr, TYPE_FIELDS (ctr_type),
878 build_int_cstu (get_gcov_unsigned_t (),
879 count));
880
881 if (var)
882 CONSTRUCTOR_APPEND_ELT (ctr, DECL_CHAIN (TYPE_FIELDS (ctr_type)),
883 build_fold_addr_expr (var));
884
885 CONSTRUCTOR_APPEND_ELT (v2, NULL, build_constructor (ctr_type, ctr));
886 }
887
2100aa42 888 CONSTRUCTOR_APPEND_ELT (v1, fields,
889 build_constructor (TREE_TYPE (fields), v2));
89a1f620 890
2100aa42 891 return build_constructor (type, v1);
44359ced 892}
893
6c56d3c9 894/* Create gcov_info struct. TYPE is the incomplete RECORD_TYPE to be
895 completed, and FN_INFO_PTR_TYPE is a pointer to the function info type. */
ab6a34f2 896
5014df5d 897static void
6c56d3c9 898build_info_type (tree type, tree fn_info_ptr_type)
44359ced 899{
ab6a34f2 900 tree field, fields = NULL_TREE;
6c56d3c9 901 tree merge_fn_type;
834f169c 902
5014df5d 903 /* Version ident */
904 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
905 get_gcov_unsigned_t ());
1767a056 906 DECL_CHAIN (field) = fields;
44359ced 907 fields = field;
908
5014df5d 909 /* next pointer */
910 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
911 build_pointer_type (build_qualified_type
912 (type, TYPE_QUAL_CONST)));
1767a056 913 DECL_CHAIN (field) = fields;
44359ced 914 fields = field;
915
5014df5d 916 /* stamp */
917 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
918 get_gcov_unsigned_t ());
1767a056 919 DECL_CHAIN (field) = fields;
35cb45c4 920 fields = field;
921
5014df5d 922 /* Filename */
923 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
924 build_pointer_type (build_qualified_type
925 (char_type_node, TYPE_QUAL_CONST)));
926 DECL_CHAIN (field) = fields;
927 fields = field;
44359ced 928
5014df5d 929 /* merge fn array */
930 merge_fn_type
931 = build_function_type_list (void_type_node,
932 build_pointer_type (get_gcov_type ()),
933 get_gcov_unsigned_t (), NULL_TREE);
934 merge_fn_type
935 = build_array_type (build_pointer_type (merge_fn_type),
936 build_index_type (size_int (GCOV_COUNTERS - 1)));
937 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
938 merge_fn_type);
939 DECL_CHAIN (field) = fields;
940 fields = field;
941
942 /* n_functions */
943 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
944 get_gcov_unsigned_t ());
945 DECL_CHAIN (field) = fields;
946 fields = field;
947
6c56d3c9 948 /* function_info pointer pointer */
949 fn_info_ptr_type = build_pointer_type
950 (build_qualified_type (fn_info_ptr_type, TYPE_QUAL_CONST));
5014df5d 951 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
6c56d3c9 952 fn_info_ptr_type);
5014df5d 953 DECL_CHAIN (field) = fields;
954 fields = field;
35cb45c4 955
5014df5d 956 finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
44359ced 957}
958
6c56d3c9 959/* Returns a CONSTRUCTOR for the gcov_info object. INFO_TYPE is the
960 gcov_info structure type, FN_ARY is the array of pointers to
961 function info objects. */
ab6a34f2 962
44359ced 963static tree
6c56d3c9 964build_info (tree info_type, tree fn_ary)
44359ced 965{
5014df5d 966 tree info_fields = TYPE_FIELDS (info_type);
6c56d3c9 967 tree merge_fn_type, n_funcs;
5014df5d 968 unsigned ix;
ab6a34f2 969 tree filename_string;
3e3a0e9c 970 int da_file_name_len;
f1f41a6c 971 vec<constructor_elt, va_gc> *v1 = NULL;
972 vec<constructor_elt, va_gc> *v2 = NULL;
89a1f620 973
ab6a34f2 974 /* Version ident */
5014df5d 975 CONSTRUCTOR_APPEND_ELT (v1, info_fields,
976 build_int_cstu (TREE_TYPE (info_fields),
977 GCOV_VERSION));
978 info_fields = DECL_CHAIN (info_fields);
89a1f620 979
44359ced 980 /* next -- NULL */
5014df5d 981 CONSTRUCTOR_APPEND_ELT (v1, info_fields, null_pointer_node);
982 info_fields = DECL_CHAIN (info_fields);
983
42fa384f 984 /* stamp */
5014df5d 985 CONSTRUCTOR_APPEND_ELT (v1, info_fields,
986 build_int_cstu (TREE_TYPE (info_fields),
267dc7fa 987 bbg_file_stamp));
5014df5d 988 info_fields = DECL_CHAIN (info_fields);
42fa384f 989
44359ced 990 /* Filename */
3e3a0e9c 991 da_file_name_len = strlen (da_file_name);
992 filename_string = build_string (da_file_name_len + 1, da_file_name);
7c446c95 993 TREE_TYPE (filename_string) = build_array_type
2c46738d 994 (char_type_node, build_index_type (size_int (da_file_name_len)));
5014df5d 995 CONSTRUCTOR_APPEND_ELT (v1, info_fields,
996 build1 (ADDR_EXPR, TREE_TYPE (info_fields),
997 filename_string));
998 info_fields = DECL_CHAIN (info_fields);
89a1f620 999
5014df5d 1000 /* merge fn array -- NULL slots indicate unmeasured counters */
1001 merge_fn_type = TREE_TYPE (TREE_TYPE (info_fields));
1002 for (ix = 0; ix != GCOV_COUNTERS; ix++)
44359ced 1003 {
5014df5d 1004 tree ptr = null_pointer_node;
89a1f620 1005
5014df5d 1006 if ((1u << ix) & prg_ctr_mask)
1007 {
1008 tree merge_fn = build_decl (BUILTINS_LOCATION,
1009 FUNCTION_DECL,
1010 get_identifier (ctr_merge_functions[ix]),
1011 TREE_TYPE (merge_fn_type));
1012 DECL_EXTERNAL (merge_fn) = 1;
1013 TREE_PUBLIC (merge_fn) = 1;
1014 DECL_ARTIFICIAL (merge_fn) = 1;
1015 TREE_NOTHROW (merge_fn) = 1;
1016 /* Initialize assembler name so we can stream out. */
1017 DECL_ASSEMBLER_NAME (merge_fn);
1018 ptr = build1 (ADDR_EXPR, merge_fn_type, merge_fn);
1019 }
1020 CONSTRUCTOR_APPEND_ELT (v2, NULL, ptr);
44359ced 1021 }
5014df5d 1022 CONSTRUCTOR_APPEND_ELT (v1, info_fields,
1023 build_constructor (TREE_TYPE (info_fields), v2));
1024 info_fields = DECL_CHAIN (info_fields);
1025
1026 /* n_functions */
6c56d3c9 1027 n_funcs = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (fn_ary)));
1028 n_funcs = fold_build2 (PLUS_EXPR, TREE_TYPE (info_fields),
1029 n_funcs, size_one_node);
1030 CONSTRUCTOR_APPEND_ELT (v1, info_fields, n_funcs);
5014df5d 1031 info_fields = DECL_CHAIN (info_fields);
5014df5d 1032
6c56d3c9 1033 /* functions */
5014df5d 1034 CONSTRUCTOR_APPEND_ELT (v1, info_fields,
6c56d3c9 1035 build1 (ADDR_EXPR, TREE_TYPE (info_fields), fn_ary));
1036 info_fields = DECL_CHAIN (info_fields);
1037
1038 gcc_assert (!info_fields);
5014df5d 1039 return build_constructor (info_type, v1);
44359ced 1040}
1041
bd13f5e8 1042/* Generate the constructor function to call __gcov_init. */
1043
1044static void
1045build_init_ctor (tree gcov_info_type)
1046{
1047 tree ctor, stmt, init_fn;
1048
1049 /* Build a decl for __gcov_init. */
1050 init_fn = build_pointer_type (gcov_info_type);
1051 init_fn = build_function_type_list (void_type_node, init_fn, NULL);
1052 init_fn = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
1053 get_identifier ("__gcov_init"), init_fn);
1054 TREE_PUBLIC (init_fn) = 1;
1055 DECL_EXTERNAL (init_fn) = 1;
1056 DECL_ASSEMBLER_NAME (init_fn);
1057
1058 /* Generate a call to __gcov_init(&gcov_info). */
1059 ctor = NULL;
1060 stmt = build_fold_addr_expr (gcov_info_var);
1061 stmt = build_call_expr (init_fn, 1, stmt);
1062 append_to_statement_list (stmt, &ctor);
1063
2d799bac 1064 /* Generate a constructor to run it. */
1065 int priority = SUPPORTS_INIT_PRIORITY
1066 ? MAX_RESERVED_INIT_PRIORITY: DEFAULT_INIT_PRIORITY;
1067 cgraph_build_static_cdtor ('I', ctor, priority);
db46bcd3 1068}
1069
1070/* Generate the destructor function to call __gcov_exit. */
1071
1072static void
1073build_gcov_exit_decl (void)
1074{
1075 tree init_fn = build_function_type_list (void_type_node, void_type_node,
1076 NULL);
1077 init_fn = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
1078 get_identifier ("__gcov_exit"), init_fn);
1079 TREE_PUBLIC (init_fn) = 1;
1080 DECL_EXTERNAL (init_fn) = 1;
1081 DECL_ASSEMBLER_NAME (init_fn);
1082
1083 /* Generate a call to __gcov_exit (). */
1084 tree dtor = NULL;
1085 tree stmt = build_call_expr (init_fn, 0);
1086 append_to_statement_list (stmt, &dtor);
1087
2d799bac 1088 /* Generate a destructor to run it. */
1089 int priority = SUPPORTS_INIT_PRIORITY
1090 ? MAX_RESERVED_INIT_PRIORITY: DEFAULT_INIT_PRIORITY;
1091
1092 cgraph_build_static_cdtor ('D', dtor, priority);
bd13f5e8 1093}
1094
6c56d3c9 1095/* Create the gcov_info types and object. Generate the constructor
1096 function to call __gcov_init. Does not generate the initializer
1097 for the object. Returns TRUE if coverage data is being emitted. */
44359ced 1098
6c56d3c9 1099static bool
1100coverage_obj_init (void)
44359ced 1101{
bd13f5e8 1102 tree gcov_info_type;
6c56d3c9 1103 unsigned n_counters = 0;
5014df5d 1104 unsigned ix;
6c56d3c9 1105 struct coverage_data *fn;
1106 struct coverage_data **fn_prev;
b5530559 1107 char name_buf[32];
44359ced 1108
015af757 1109 no_coverage = 1; /* Disable any further coverage. */
89a1f620 1110
ab6a34f2 1111 if (!prg_ctr_mask)
6c56d3c9 1112 return false;
89a1f620 1113
35ee1c66 1114 if (symtab->dump_file)
1115 fprintf (symtab->dump_file, "Using data file %s\n", da_file_name);
44359ced 1116
6c56d3c9 1117 /* Prune functions. */
5014df5d 1118 for (fn_prev = &functions_head; (fn = *fn_prev);)
1119 if (DECL_STRUCT_FUNCTION (fn->fn_decl))
6c56d3c9 1120 fn_prev = &fn->next;
5014df5d 1121 else
1122 /* The function is not being emitted, remove from list. */
1123 *fn_prev = fn->next;
6c56d3c9 1124
f1d3fe3f 1125 if (functions_head == NULL)
1126 return false;
1127
6c56d3c9 1128 for (ix = 0; ix != GCOV_COUNTERS; ix++)
1129 if ((1u << ix) & prg_ctr_mask)
1130 n_counters++;
5014df5d 1131
1132 /* Build the info and fn_info types. These are mutually recursive. */
1133 gcov_info_type = lang_hooks.types.make_type (RECORD_TYPE);
6c56d3c9 1134 gcov_fn_info_type = lang_hooks.types.make_type (RECORD_TYPE);
3e301e70 1135 build_fn_info_type (gcov_fn_info_type, n_counters, gcov_info_type);
1136 gcov_info_type = lang_hooks.types.make_type (RECORD_TYPE);
6c56d3c9 1137 gcov_fn_info_ptr_type = build_pointer_type
1138 (build_qualified_type (gcov_fn_info_type, TYPE_QUAL_CONST));
6c56d3c9 1139 build_info_type (gcov_info_type, gcov_fn_info_ptr_type);
5014df5d 1140
1141 /* Build the gcov info var, this is referred to in its own
1142 initializer. */
6c56d3c9 1143 gcov_info_var = build_decl (BUILTINS_LOCATION,
1144 VAR_DECL, NULL_TREE, gcov_info_type);
1145 TREE_STATIC (gcov_info_var) = 1;
b5530559 1146 ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
6c56d3c9 1147 DECL_NAME (gcov_info_var) = get_identifier (name_buf);
44359ced 1148
bd13f5e8 1149 build_init_ctor (gcov_info_type);
db46bcd3 1150 build_gcov_exit_decl ();
6c56d3c9 1151
1152 return true;
44359ced 1153}
6c56d3c9 1154
1155/* Generate the coverage function info for FN and DATA. Append a
1156 pointer to that object to CTOR and return the appended CTOR. */
1157
f1f41a6c 1158static vec<constructor_elt, va_gc> *
1159coverage_obj_fn (vec<constructor_elt, va_gc> *ctor, tree fn,
6c56d3c9 1160 struct coverage_data const *data)
1161{
1162 tree init = build_fn_info (data, gcov_fn_info_type, gcov_info_var);
1163 tree var = build_var (fn, gcov_fn_info_type, -1);
1164
1165 DECL_INITIAL (var) = init;
97221fd7 1166 varpool_node::finalize_decl (var);
6c56d3c9 1167
1168 CONSTRUCTOR_APPEND_ELT (ctor, NULL,
1169 build1 (ADDR_EXPR, gcov_fn_info_ptr_type, var));
1170 return ctor;
1171}
1172
1173/* Finalize the coverage data. Generates the array of pointers to
1174 function objects from CTOR. Generate the gcov_info initializer. */
1175
1176static void
f1f41a6c 1177coverage_obj_finish (vec<constructor_elt, va_gc> *ctor)
6c56d3c9 1178{
f1f41a6c 1179 unsigned n_functions = vec_safe_length (ctor);
6c56d3c9 1180 tree fn_info_ary_type = build_array_type
1181 (build_qualified_type (gcov_fn_info_ptr_type, TYPE_QUAL_CONST),
1182 build_index_type (size_int (n_functions - 1)));
1183 tree fn_info_ary = build_decl (BUILTINS_LOCATION, VAR_DECL, NULL_TREE,
1184 fn_info_ary_type);
1185 char name_buf[32];
1186
1187 TREE_STATIC (fn_info_ary) = 1;
1188 ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 1);
1189 DECL_NAME (fn_info_ary) = get_identifier (name_buf);
1190 DECL_INITIAL (fn_info_ary) = build_constructor (fn_info_ary_type, ctor);
97221fd7 1191 varpool_node::finalize_decl (fn_info_ary);
6c56d3c9 1192
1193 DECL_INITIAL (gcov_info_var)
1194 = build_info (TREE_TYPE (gcov_info_var), fn_info_ary);
97221fd7 1195 varpool_node::finalize_decl (gcov_info_var);
6c56d3c9 1196}
1197
44359ced 1198/* Perform file-level initialization. Read in data file, generate name
56b17dd7 1199 of notes file. */
44359ced 1200
1201void
89a1f620 1202coverage_init (const char *filename)
44359ced 1203{
1204 int len = strlen (filename);
6c56d3c9 1205 int prefix_len = 0;
48e1416a 1206
202c2bd9 1207 /* Since coverage_init is invoked very early, before the pass
1208 manager, we need to set up the dumping explicitly. This is
1209 similar to the handling in finish_optimization_passes. */
41142c53 1210 int profile_pass_num =
1211 g->get_passes ()->get_pass_profile ()->static_pass_number;
1212 g->get_dumps ()->dump_start (profile_pass_num, NULL);
202c2bd9 1213
59048041 1214 if (!IS_ABSOLUTE_PATH (filename))
1215 {
1216 /* When a profile_data_prefix is provided, then mangle full path
1217 of filename in order to prevent file path clashing. */
1218 if (profile_data_prefix)
1219 {
1220#if HAVE_DOS_BASED_FILE_SYSTEM
07b96644 1221 const char *separator = "\\";
59048041 1222#else
1223 const char *separator = "/";
1224#endif
1225 filename = concat (getpwd (), separator, filename, NULL);
1226 filename = mangle_path (filename);
1227 len = strlen (filename);
1228 }
1229 else
1230 profile_data_prefix = getpwd ();
1231 }
3e3a0e9c 1232
6c56d3c9 1233 if (profile_data_prefix)
1234 prefix_len = strlen (profile_data_prefix);
44359ced 1235
3f2c2dd8 1236 /* Name of da file. */
48e1416a 1237 da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX)
6c56d3c9 1238 + prefix_len + 2);
3e3a0e9c 1239
1240 if (profile_data_prefix)
1241 {
6c56d3c9 1242 memcpy (da_file_name, profile_data_prefix, prefix_len);
1243 da_file_name[prefix_len++] = '/';
3e3a0e9c 1244 }
6c56d3c9 1245 memcpy (da_file_name + prefix_len, filename, len);
1246 strcpy (da_file_name + prefix_len + len, GCOV_DATA_SUFFIX);
89a1f620 1247
267dc7fa 1248 bbg_file_stamp = local_tick;
1249
94bed7c3 1250 if (flag_auto_profile)
1251 read_autofdo_file ();
1252 else if (flag_branch_probabilities)
267dc7fa 1253 read_counts_file ();
1254
3f2c2dd8 1255 /* Name of bbg file. */
6c56d3c9 1256 if (flag_test_coverage && !flag_compare_debug)
1257 {
4048b1f0 1258 if (profile_note_location)
1259 bbg_file_name = xstrdup (profile_note_location);
1260 else
1261 {
1262 bbg_file_name = XNEWVEC (char, len + strlen (GCOV_NOTE_SUFFIX) + 1);
1263 memcpy (bbg_file_name, filename, len);
1264 strcpy (bbg_file_name + len, GCOV_NOTE_SUFFIX);
1265 }
6c56d3c9 1266
1267 if (!gcov_open (bbg_file_name, -1))
1268 {
1269 error ("cannot open %s", bbg_file_name);
1270 bbg_file_name = NULL;
1271 }
1272 else
1273 {
1274 gcov_write_unsigned (GCOV_NOTE_MAGIC);
1275 gcov_write_unsigned (GCOV_VERSION);
267dc7fa 1276 gcov_write_unsigned (bbg_file_stamp);
47e77da0 1277 gcov_write_string (getpwd ());
fa6f8ae7 1278
1279 /* Do not support has_unexecuted_blocks for Ada. */
1280 gcov_write_unsigned (strcmp (lang_hooks.name, "GNU Ada") != 0);
6c56d3c9 1281 }
1282 }
202c2bd9 1283
41142c53 1284 g->get_dumps ()->dump_finish (profile_pass_num);
44359ced 1285}
1286
56b17dd7 1287/* Performs file-level cleanup. Close notes file, generate coverage
44359ced 1288 variables and constructor. */
1289
1290void
89a1f620 1291coverage_finish (void)
44359ced 1292{
6c56d3c9 1293 if (bbg_file_name && gcov_close ())
1294 unlink (bbg_file_name);
267dc7fa 1295
1296 if (!flag_branch_probabilities && flag_test_coverage
1297 && (!local_tick || local_tick == (unsigned)-1))
1298 /* Only remove the da file, if we're emitting coverage code and
1299 cannot uniquely stamp it. If we can stamp it, libgcov will DTRT. */
6c56d3c9 1300 unlink (da_file_name);
1301
1302 if (coverage_obj_init ())
44359ced 1303 {
f1f41a6c 1304 vec<constructor_elt, va_gc> *fn_ctor = NULL;
6c56d3c9 1305 struct coverage_data *fn;
1306
1307 for (fn = functions_head; fn; fn = fn->next)
1308 fn_ctor = coverage_obj_fn (fn_ctor, fn->fn_decl, fn);
1309 coverage_obj_finish (fn_ctor);
44359ced 1310 }
073ce4ec 1311
1312 XDELETEVEC (da_file_name);
1313 da_file_name = NULL;
44359ced 1314}
1315
44359ced 1316#include "gt-coverage.h"