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