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