]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/coverage.c
PR fortran/95090 - ICE: identifier overflow
[thirdparty/gcc.git] / gcc / coverage.c
CommitLineData
ca29da43 1/* Read and write coverage files, and associated functionality.
8d9254fc 2 Copyright (C) 1990-2020 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 34#include "tree-pass.h"
4d0cdd0c 35#include "memmodel.h"
957060b5 36#include "tm_p.h"
d8a2d370 37#include "stringpool.h"
957060b5
AM
38#include "cgraph.h"
39#include "coverage.h"
40#include "diagnostic-core.h"
957060b5 41#include "fold-const.h"
d8a2d370 42#include "stor-layout.h"
ca29da43 43#include "output.h"
ca29da43 44#include "toplev.h"
ca29da43 45#include "langhooks.h"
c9b9aa64 46#include "tree-iterator.h"
103ff0d6
TJ
47#include "context.h"
48#include "pass_manager.h"
650cfcab 49#include "intl.h"
be3c16c4 50#include "auto-profile.h"
512cc015 51#include "profile.h"
44b32683 52#include "diagnostic.h"
ca29da43
NS
53
54#include "gcov-io.c"
55
b724567e 56struct GTY((chain_next ("%h.next"))) coverage_data
ca29da43 57{
b724567e 58 struct coverage_data *next; /* next function */
159b3be1 59 unsigned ident; /* function ident */
10adac51
XDL
60 unsigned lineno_checksum; /* function lineno checksum */
61 unsigned cfg_checksum; /* function cfg checksum */
5366b186
NS
62 tree fn_decl; /* the function decl */
63 tree ctr_vars[GCOV_COUNTERS]; /* counter variables. */
ca29da43
NS
64};
65
66/* Counts information for a function. */
526ceb68 67struct counts_entry : pointer_hash <counts_entry>
ca29da43
NS
68{
69 /* We hash by */
796621e8 70 unsigned ident;
cdb23767 71 unsigned ctr;
159b3be1 72
ca29da43 73 /* Store */
10adac51
XDL
74 unsigned lineno_checksum;
75 unsigned cfg_checksum;
ca29da43 76 gcov_type *counts;
0418f237 77 unsigned n_counts;
5deac340
RG
78
79 /* hash_table support. */
67f58944
TS
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 *);
526ceb68 83};
ca29da43 84
b724567e
NS
85static GTY(()) struct coverage_data *functions_head = 0;
86static struct coverage_data **functions_tail = &functions_head;
6d70e6be 87static unsigned no_coverage = 0;
ca29da43 88
cdb23767
NS
89/* Cumulative counter information for whole program. */
90static unsigned prg_ctr_mask; /* Mask of counter types generated. */
ca29da43 91
cdb23767 92/* Counter information for current function. */
71c0e7fc 93static unsigned fn_ctr_mask; /* Mask of counters used. */
5366b186 94static GTY(()) tree fn_v_ctrs[GCOV_COUNTERS]; /* counter variables. */
6d70e6be
NS
95static unsigned fn_n_ctrs[GCOV_COUNTERS]; /* Counters allocated. */
96static unsigned fn_b_ctrs[GCOV_COUNTERS]; /* Allocation base. */
ca29da43 97
b724567e
NS
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
efbb59b2
SB
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. */
ca29da43 107static char *bbg_file_name;
ca29da43 108
efbb59b2 109/* File stamp for notes file. */
cb686b99
NS
110static unsigned bbg_file_stamp;
111
efbb59b2 112/* Name of the count data (gcda) file. */
ca29da43
NS
113static char *da_file_name;
114
09780dfb 115/* The names of merge functions for counters. */
c77556a5
RX
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
09780dfb 129
ca29da43 130/* Forward declarations. */
159b3be1 131static void read_counts_file (void);
5366b186
NS
132static tree build_var (tree, tree, int);
133static void build_fn_info_type (tree, unsigned, tree);
b724567e
NS
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);
9771b263
DN
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> *);
251e2ff2
RS
141\f
142/* Return the type node for gcov_type. */
143
144tree
145get_gcov_type (void)
146{
f67f4dff
RS
147 scalar_int_mode mode
148 = smallest_int_mode_for_size (LONG_LONG_TYPE_SIZE > 32 ? 64 : 32);
0f250839 149 return lang_hooks.types.type_for_mode (mode, false);
251e2ff2
RS
150}
151
152/* Return the type node for gcov_unsigned_t. */
ca29da43 153
251e2ff2
RS
154static tree
155get_gcov_unsigned_t (void)
156{
f67f4dff 157 scalar_int_mode mode = smallest_int_mode_for_size (32);
0f250839 158 return lang_hooks.types.type_for_mode (mode, true);
251e2ff2 159}
ca29da43 160\f
0823efed 161inline hashval_t
67f58944 162counts_entry::hash (const counts_entry *entry)
ca29da43 163{
796621e8 164 return entry->ident * GCOV_COUNTERS + entry->ctr;
ca29da43
NS
165}
166
0823efed 167inline int
67f58944 168counts_entry::equal (const counts_entry *entry1, const counts_entry *entry2)
ca29da43 169{
796621e8 170 return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
ca29da43
NS
171}
172
0823efed 173inline void
67f58944 174counts_entry::remove (counts_entry *entry)
ca29da43 175{
ca29da43
NS
176 free (entry->counts);
177 free (entry);
178}
179
0823efed 180/* Hash table of count data. */
c203e8a7 181static hash_table<counts_entry> *counts_hash;
0823efed 182
ca29da43
NS
183/* Read in the counts file, if available. */
184
185static void
159b3be1 186read_counts_file (void)
ca29da43 187{
9b514d25 188 gcov_unsigned_t fn_ident = 0;
7d63a2fa 189 gcov_unsigned_t tag;
24a4a033 190 int is_error = 0;
10adac51
XDL
191 unsigned lineno_checksum = 0;
192 unsigned cfg_checksum = 0;
7d63a2fa 193
ca29da43
NS
194 if (!gcov_open (da_file_name, 1))
195 return;
159b3be1 196
160e2e4f 197 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
ca29da43 198 {
d4ee4d25 199 warning (0, "%qs is not a gcov data file", da_file_name);
ca29da43
NS
200 gcov_close ();
201 return;
202 }
160e2e4f 203 else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
ca29da43 204 {
330d2e2a
NS
205 char v[4], e[4];
206
207 GCOV_UNSIGNED2STRING (v, tag);
208 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
159b3be1 209
d4ee4d25 210 warning (0, "%qs is version %q.*s, expected version %q.*s",
cb83302c 211 da_file_name, 4, v, 4, e);
ca29da43
NS
212 gcov_close ();
213 return;
214 }
159b3be1 215
cb686b99
NS
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);
b8698a0f 219
c203e8a7 220 counts_hash = new hash_table<counts_entry> (10);
7d63a2fa 221 while ((tag = gcov_read_unsigned ()))
ca29da43 222 {
7d63a2fa 223 gcov_unsigned_t length;
9b514d25 224 gcov_position_t offset;
159b3be1 225
ca29da43
NS
226 length = gcov_read_unsigned ();
227 offset = gcov_position ();
228 if (tag == GCOV_TAG_FUNCTION)
229 {
5366b186 230 if (length)
ca29da43 231 {
5366b186
NS
232 fn_ident = gcov_read_unsigned ();
233 lineno_checksum = gcov_read_unsigned ();
234 cfg_checksum = gcov_read_unsigned ();
ca29da43 235 }
5366b186
NS
236 else
237 fn_ident = lineno_checksum = cfg_checksum = 0;
ca29da43 238 }
512cc015 239 else if (tag == GCOV_TAG_OBJECT_SUMMARY)
ca29da43 240 {
512cc015
ML
241 profile_info = XCNEW (gcov_summary);
242 profile_info->runs = gcov_read_unsigned ();
243 profile_info->sum_max = gcov_read_unsigned ();
ca29da43 244 }
796621e8 245 else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
ca29da43 246 {
526ceb68 247 counts_entry **slot, *entry, elt;
330d2e2a 248 unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
ca29da43
NS
249 unsigned ix;
250
796621e8 251 elt.ident = fn_ident;
cdb23767 252 elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
ca29da43 253
c203e8a7 254 slot = counts_hash->find_slot (&elt, INSERT);
ca29da43
NS
255 entry = *slot;
256 if (!entry)
257 {
526ceb68 258 *slot = entry = XCNEW (counts_entry);
10adac51 259 entry->ident = fn_ident;
cdb23767 260 entry->ctr = elt.ctr;
10adac51
XDL
261 entry->lineno_checksum = lineno_checksum;
262 entry->cfg_checksum = cfg_checksum;
5ed6ace5 263 entry->counts = XCNEWVEC (gcov_type, n_counts);
0418f237 264 entry->n_counts = n_counts;
ca29da43 265 }
10adac51
XDL
266 else if (entry->lineno_checksum != lineno_checksum
267 || entry->cfg_checksum != cfg_checksum)
ca29da43 268 {
32387f76 269 error ("profile data for function %u is corrupted", fn_ident);
10adac51
XDL
270 error ("checksum is (%x,%x) instead of (%x,%x)",
271 entry->lineno_checksum, entry->cfg_checksum,
272 lineno_checksum, cfg_checksum);
c203e8a7
TS
273 delete counts_hash;
274 counts_hash = NULL;
24a4a033
JH
275 break;
276 }
ca29da43
NS
277 for (ix = 0; ix != n_counts; ix++)
278 entry->counts[ix] += gcov_read_counter ();
279 }
474f141e 280 gcov_sync (offset, length);
24a4a033 281 if ((is_error = gcov_is_error ()))
00cf2913 282 {
324ff1a0
JJ
283 error (is_error < 0
284 ? G_("%qs has overflowed")
285 : G_("%qs is corrupted"),
00cf2913 286 da_file_name);
c203e8a7
TS
287 delete counts_hash;
288 counts_hash = NULL;
00cf2913
NS
289 break;
290 }
7d63a2fa 291 }
159b3be1 292
ca29da43
NS
293 gcov_close ();
294}
295
296/* Returns the counters for a particular tag. */
297
298gcov_type *
512cc015 299get_coverage_counts (unsigned counter, unsigned cfg_checksum,
0418f237 300 unsigned lineno_checksum, unsigned int n_counts)
ca29da43 301{
526ceb68 302 counts_entry *entry, elt;
ca29da43 303
71c0e7fc 304 /* No hash table, no counts. */
c203e8a7 305 if (!counts_hash)
ca29da43
NS
306 {
307 static int warned = 0;
308
bc162b0e 309 if (!warned++)
4f5b9c80 310 {
bc162b0e
IB
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);
ed2d9d37 318 dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
88307040
ML
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"));
bc162b0e 323 }
4f5b9c80 324 }
ca29da43
NS
325 return NULL;
326 }
028d4092 327 if (param_profile_func_internal_id)
2243ba51
XDL
328 elt.ident = current_function_funcdef_no + 1;
329 else
330 {
331 gcc_assert (coverage_node_map_initialized_p ());
962e88a9 332 elt.ident = cgraph_node::get (current_function_decl)->profile_id;
2243ba51 333 }
cdb23767 334 elt.ctr = counter;
c203e8a7 335 entry = counts_hash->find (&elt);
512cc015 336 if (!entry)
bc162b0e
IB
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 }
5366b186 348
0418f237 349 if (entry->cfg_checksum != cfg_checksum || entry->n_counts != n_counts)
24a4a033 350 {
16c1c158 351 static int warned = 0;
650cfcab 352 bool warning_printed = false;
16c1c158 353
0418f237
JH
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]);
103ff0d6 370 if (warning_printed && dump_enabled_p ())
16c1c158 371 {
4f5b9c80 372 dump_user_location_t loc
732779d0 373 = dump_user_location_t::from_function_decl (current_function_decl);
ed2d9d37 374 dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
103ff0d6
TJ
375 "use -Wno-error=coverage-mismatch to tolerate "
376 "the mismatch but performance may drop if the "
e645e942 377 "function is hot\n");
650cfcab 378
1da2ed5f 379 if (!seen_error ()
650cfcab
NV
380 && !warned++)
381 {
ed2d9d37 382 dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
e645e942 383 "coverage mismatch ignored\n");
ed2d9d37 384 dump_printf (MSG_MISSED_OPTIMIZATION,
e645e942
TJ
385 flag_guess_branch_prob
386 ? G_("execution counts estimated\n")
387 : G_("execution counts assumed to be zero\n"));
650cfcab 388 if (!flag_guess_branch_prob)
ed2d9d37 389 dump_printf (MSG_MISSED_OPTIMIZATION,
e645e942 390 "this can result in poorly optimized code\n");
650cfcab 391 }
16c1c158
RG
392 }
393
394 return NULL;
ca29da43 395 }
5366b186
NS
396 else if (entry->lineno_checksum != lineno_checksum)
397 {
bda815c5
ML
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);
5366b186 403 }
159b3be1 404
ca29da43
NS
405 return entry->counts;
406}
cdb23767 407
6356f892 408/* Allocate NUM counters of type COUNTER. Returns nonzero if the
6d70e6be 409 allocation succeeded. */
cdb23767 410
6d70e6be
NS
411int
412coverage_counter_alloc (unsigned counter, unsigned num)
cdb23767 413{
6d70e6be
NS
414 if (no_coverage)
415 return 0;
159b3be1 416
6d70e6be
NS
417 if (!num)
418 return 1;
159b3be1 419
5366b186 420 if (!fn_v_ctrs[counter])
cdb23767 421 {
5366b186
NS
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);
cdb23767 426 }
5366b186 427
6d70e6be
NS
428 fn_b_ctrs[counter] = fn_n_ctrs[counter];
429 fn_n_ctrs[counter] += num;
5366b186 430
6d70e6be
NS
431 fn_ctr_mask |= 1 << counter;
432 return 1;
433}
cdb23767 434
6de9cd9a
DN
435/* Generate a tree to access COUNTER NO. */
436
437tree
438tree_coverage_counter_ref (unsigned counter, unsigned no)
439{
070e3969 440 tree gcov_type_node = get_gcov_type ();
6de9cd9a 441
341c100f 442 gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
6de9cd9a 443
5366b186
NS
444 no += fn_b_ctrs[counter];
445
6de9cd9a 446 /* "no" here is an array index, scaled to bytes later. */
5366b186 447 return build4 (ARRAY_REF, gcov_type_node, fn_v_ctrs[counter],
f81b1a3d 448 build_int_cst (integer_type_node, no), NULL, NULL);
6de9cd9a 449}
fc9161c1
RG
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]);
5366b186 459 no += fn_b_ctrs[counter];
628c189e 460
fc9161c1
RG
461 /* "no" here is an array index, scaled to bytes later. */
462 return build_fold_addr_expr (build4 (ARRAY_REF, gcov_type_node,
5366b186 463 fn_v_ctrs[counter],
f81b1a3d 464 build_int_cst (integer_type_node, no),
fc9161c1
RG
465 NULL, NULL));
466}
ca29da43 467\f
10adac51 468
ca29da43 469/* Generate a checksum for a string. CHKSUM is the current
71c0e7fc 470 checksum. */
ca29da43
NS
471
472static unsigned
20c361f3 473coverage_checksum_string (unsigned chksum, const char *string)
ca29da43 474{
20c361f3
JH
475 int i;
476 char *dup = NULL;
477
478 /* Look for everything that looks if it were produced by
5880f14f 479 get_file_function_name and zero out the second part
20c361f3
JH
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++)
ca29da43 483 {
2b557972
JH
484 int offset = 0;
485 if (!strncmp (string + i, "_GLOBAL__N_", 11))
486 offset = 11;
20c361f3 487 if (!strncmp (string + i, "_GLOBAL__", 9))
2b557972
JH
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
fa10beec 494 for magicnumber. */
2b557972 495 if (offset)
1f651229
JH
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 }
ca29da43 521 }
20c361f3
JH
522
523 chksum = crc32_string (chksum, string);
04695783 524 free (dup);
159b3be1 525
ca29da43
NS
526 return chksum;
527}
528
529/* Compute checksum for the current function. We generate a CRC32. */
530
10adac51
XDL
531unsigned
532coverage_compute_lineno_checksum (void)
ca29da43 533{
a281759f
PB
534 expanded_location xloc
535 = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
536 unsigned chksum = xloc.line;
ca29da43 537
bc91c436
ML
538 if (xloc.file)
539 chksum = coverage_checksum_string (chksum, xloc.file);
20c361f3 540 chksum = coverage_checksum_string
ca29da43
NS
541 (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
542
543 return chksum;
544}
10adac51 545
2fa3d31b
JH
546/* Compute profile ID. This is better to be unique in whole program. */
547
548unsigned
549coverage_compute_profile_id (struct cgraph_node *n)
550{
cb90235d 551 unsigned chksum;
2fa3d31b 552
cb90235d 553 /* Externally visible symbols have unique name. */
7e044261 554 if (TREE_PUBLIC (n->decl) || DECL_EXTERNAL (n->decl) || n->unique_name)
cb90235d
JH
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));
028d4092 563 bool use_name_only = (param_profile_func_internal_id == 0);
cb90235d 564
2243ba51 565 chksum = (use_name_only ? 0 : xloc.line);
bc91c436
ML
566 if (xloc.file)
567 chksum = coverage_checksum_string (chksum, xloc.file);
cb90235d
JH
568 chksum = coverage_checksum_string
569 (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (n->decl)));
2243ba51 570 if (!use_name_only && first_global_object_name)
cb90235d
JH
571 chksum = coverage_checksum_string
572 (chksum, first_global_object_name);
573 chksum = coverage_checksum_string
574 (chksum, aux_base_name);
575 }
2fa3d31b 576
7e044261
JH
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);
2fa3d31b
JH
581}
582
a96bf0d3 583/* Compute cfg checksum for the function FN given as argument.
10adac51
XDL
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
a96bf0d3 594coverage_compute_cfg_checksum (struct function *fn)
10adac51
XDL
595{
596 basic_block bb;
a96bf0d3 597 unsigned chksum = n_basic_blocks_for_fn (fn);
10adac51 598
a96bf0d3 599 FOR_EACH_BB_FN (bb, fn)
10adac51
XDL
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}
ca29da43 612\f
efbb59b2 613/* Begin output to the notes file for the current function.
b724567e 614 Writes the function header. Returns nonzero if data should be output. */
ca29da43
NS
615
616int
b724567e 617coverage_begin_function (unsigned lineno_checksum, unsigned cfg_checksum)
ca29da43 618{
b724567e
NS
619 expanded_location xloc;
620 unsigned long offset;
621
2f908293
SP
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). */
b724567e 624 if (no_coverage || !bbg_file_name)
6d70e6be 625 return 0;
159b3be1 626
b724567e 627 xloc = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
10adac51 628
b724567e
NS
629 /* Announce function */
630 offset = gcov_write_tag (GCOV_TAG_FUNCTION);
028d4092 631 if (param_profile_func_internal_id)
2243ba51
XDL
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
b724567e
NS
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)));
80dde427 644 gcov_write_unsigned (DECL_ARTIFICIAL (current_function_decl)
f2db4602 645 && !DECL_FUNCTION_VERSIONED (current_function_decl)
cb50701e 646 && !DECL_LAMBDA_FUNCTION_P (current_function_decl));
676519f7 647 gcov_write_filename (xloc.file);
b724567e 648 gcov_write_unsigned (xloc.line);
136ca74e
ML
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. */
390e529e 654 int end_line = endloc.file == xloc.file ? endloc.line : xloc.line;
b8154717 655 int end_column = endloc.file == xloc.file ? endloc.column: xloc.column;
390e529e
ML
656 gcc_assert (xloc.line <= end_line);
657 gcov_write_unsigned (end_line);
b8154717 658 gcov_write_unsigned (end_column);
b724567e 659 gcov_write_length (offset);
ca29da43 660
ca29da43
NS
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
10adac51 668coverage_end_function (unsigned lineno_checksum, unsigned cfg_checksum)
ca29da43
NS
669{
670 unsigned i;
159b3be1 671
b724567e 672 if (bbg_file_name && gcov_is_error ())
159b3be1 673 {
d4ee4d25 674 warning (0, "error writing %qs", bbg_file_name);
b724567e
NS
675 unlink (bbg_file_name);
676 bbg_file_name = NULL;
ca29da43 677 }
cdb23767 678
2ac69a0c 679 if (fn_ctr_mask)
cdb23767 680 {
2ac69a0c
NS
681 struct coverage_data *item = 0;
682
7e044261 683 item = ggc_alloc<coverage_data> ();
2243ba51 684
028d4092 685 if (param_profile_func_internal_id)
7e044261
JH
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;
2ac69a0c 691 }
10adac51 692
7e044261
JH
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
cdb23767
NS
701 for (i = 0; i != GCOV_COUNTERS; i++)
702 {
5366b186 703 tree var = fn_v_ctrs[i];
2ac69a0c
NS
704
705 if (item)
706 item->ctr_vars[i] = var;
5366b186
NS
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);
9041d2e6 714 varpool_node::finalize_decl (var);
5366b186 715 }
2ac69a0c 716
5366b186
NS
717 fn_b_ctrs[i] = fn_n_ctrs[i] = 0;
718 fn_v_ctrs[i] = NULL_TREE;
cdb23767
NS
719 }
720 prg_ctr_mask |= fn_ctr_mask;
721 fn_ctr_mask = 0;
722 }
ca29da43
NS
723}
724
4ebcdc23
ML
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
5366b186 737/* Build a coverage variable of TYPE for function FN_DECL. If COUNTER
0e485da0 738 >= 0 it is a counter array, otherwise it is the function structure. */
ca29da43 739
ca29da43 740static tree
5366b186
NS
741build_var (tree fn_decl, tree type, int counter)
742{
743 tree var = build_decl (BUILTINS_LOCATION, VAR_DECL, NULL_TREE, type);
9e66e106
JJ
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);
5366b186 751
5366b186 752 if (counter < 0)
9e66e106 753 strcpy (buf, "__gcov__");
5366b186 754 else
9e66e106
JJ
755 sprintf (buf, "__gcov%u_", counter);
756 len = strlen (buf);
f8a1abf8 757 buf[len - 1] = symbol_table::symbol_suffix_separator ();
9e66e106 758 memcpy (buf + len, fn_name, fn_name_len + 1);
5366b186 759 DECL_NAME (var) = get_identifier (buf);
89b0c303
NS
760 TREE_STATIC (var) = 1;
761 TREE_ADDRESSABLE (var) = 1;
400a4f6c 762 DECL_NONALIASED (var) = 1;
fe37c7af 763 SET_DECL_ALIGN (var, TYPE_ALIGN (type));
5366b186
NS
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)
ca29da43 772{
5366b186 773 tree ctr_info = lang_hooks.types.make_type (RECORD_TYPE);
ca29da43 774 tree field, fields;
cdb23767 775 tree array_type;
159b3be1 776
5366b186
NS
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
796621e8 798 /* ident */
5366b186
NS
799 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
800 get_gcov_unsigned_t ());
801 DECL_CHAIN (field) = fields;
802 fields = field;
803
10adac51 804 /* lineno_checksum */
5366b186
NS
805 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
806 get_gcov_unsigned_t ());
910ad8de 807 DECL_CHAIN (field) = fields;
ca29da43
NS
808 fields = field;
809
10adac51 810 /* cfg checksum */
5366b186
NS
811 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
812 get_gcov_unsigned_t ());
10adac51
XDL
813 DECL_CHAIN (field) = fields;
814 fields = field;
815
f81b1a3d 816 array_type = build_index_type (size_int (counters - 1));
5366b186 817 array_type = build_array_type (ctr_info, array_type);
159b3be1 818
ca29da43 819 /* counters */
5366b186 820 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, array_type);
910ad8de 821 DECL_CHAIN (field) = fields;
ca29da43
NS
822 fields = field;
823
cdb23767 824 finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
ca29da43
NS
825}
826
b724567e
NS
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. */
cdb23767 830
ca29da43 831static tree
b724567e 832build_fn_info (const struct coverage_data *data, tree type, tree key)
ca29da43 833{
cdb23767 834 tree fields = TYPE_FIELDS (type);
5366b186 835 tree ctr_type;
cdb23767 836 unsigned ix;
9771b263
DN
837 vec<constructor_elt, va_gc> *v1 = NULL;
838 vec<constructor_elt, va_gc> *v2 = NULL;
159b3be1 839
5366b186
NS
840 /* key */
841 CONSTRUCTOR_APPEND_ELT (v1, fields,
842 build1 (ADDR_EXPR, TREE_TYPE (fields), key));
843 fields = DECL_CHAIN (fields);
844
796621e8 845 /* ident */
f9b36bb3
KH
846 CONSTRUCTOR_APPEND_ELT (v1, fields,
847 build_int_cstu (get_gcov_unsigned_t (),
b724567e 848 data->ident));
910ad8de 849 fields = DECL_CHAIN (fields);
159b3be1 850
10adac51
XDL
851 /* lineno_checksum */
852 CONSTRUCTOR_APPEND_ELT (v1, fields,
853 build_int_cstu (get_gcov_unsigned_t (),
b724567e 854 data->lineno_checksum));
10adac51
XDL
855 fields = DECL_CHAIN (fields);
856
857 /* cfg_checksum */
f9b36bb3
KH
858 CONSTRUCTOR_APPEND_ELT (v1, fields,
859 build_int_cstu (get_gcov_unsigned_t (),
b724567e 860 data->cfg_checksum));
910ad8de 861 fields = DECL_CHAIN (fields);
159b3be1 862
ca29da43 863 /* counters */
5366b186 864 ctr_type = TREE_TYPE (TREE_TYPE (fields));
cdb23767
NS
865 for (ix = 0; ix != GCOV_COUNTERS; ix++)
866 if (prg_ctr_mask & (1 << ix))
5366b186 867 {
9771b263 868 vec<constructor_elt, va_gc> *ctr = NULL;
b724567e 869 tree var = data->ctr_vars[ix];
5366b186
NS
870 unsigned count = 0;
871
872 if (var)
873 count
9439e9a1 874 = tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (var))))
5366b186
NS
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
f9b36bb3
KH
888 CONSTRUCTOR_APPEND_ELT (v1, fields,
889 build_constructor (TREE_TYPE (fields), v2));
159b3be1 890
f9b36bb3 891 return build_constructor (type, v1);
ca29da43
NS
892}
893
b724567e
NS
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. */
cdb23767 896
5366b186 897static void
b724567e 898build_info_type (tree type, tree fn_info_ptr_type)
ca29da43 899{
cdb23767 900 tree field, fields = NULL_TREE;
b724567e 901 tree merge_fn_type;
9b514d25 902
5366b186
NS
903 /* Version ident */
904 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
905 get_gcov_unsigned_t ());
910ad8de 906 DECL_CHAIN (field) = fields;
ca29da43
NS
907 fields = field;
908
5366b186
NS
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)));
910ad8de 913 DECL_CHAIN (field) = fields;
ca29da43
NS
914 fields = field;
915
5366b186
NS
916 /* stamp */
917 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
918 get_gcov_unsigned_t ());
910ad8de 919 DECL_CHAIN (field) = fields;
09780dfb
ZD
920 fields = field;
921
5366b186
NS
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;
ca29da43 928
5366b186
NS
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
b724567e
NS
948 /* function_info pointer pointer */
949 fn_info_ptr_type = build_pointer_type
950 (build_qualified_type (fn_info_ptr_type, TYPE_QUAL_CONST));
5366b186 951 field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
b724567e 952 fn_info_ptr_type);
5366b186
NS
953 DECL_CHAIN (field) = fields;
954 fields = field;
09780dfb 955
5366b186 956 finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
ca29da43
NS
957}
958
b724567e
NS
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. */
cdb23767 962
ca29da43 963static tree
b724567e 964build_info (tree info_type, tree fn_ary)
ca29da43 965{
5366b186 966 tree info_fields = TYPE_FIELDS (info_type);
b724567e 967 tree merge_fn_type, n_funcs;
5366b186 968 unsigned ix;
cdb23767 969 tree filename_string;
2f908293 970 int da_file_name_len;
9771b263
DN
971 vec<constructor_elt, va_gc> *v1 = NULL;
972 vec<constructor_elt, va_gc> *v2 = NULL;
159b3be1 973
cdb23767 974 /* Version ident */
5366b186
NS
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);
159b3be1 979
ca29da43 980 /* next -- NULL */
5366b186
NS
981 CONSTRUCTOR_APPEND_ELT (v1, info_fields, null_pointer_node);
982 info_fields = DECL_CHAIN (info_fields);
983
dd486eb2 984 /* stamp */
5366b186
NS
985 CONSTRUCTOR_APPEND_ELT (v1, info_fields,
986 build_int_cstu (TREE_TYPE (info_fields),
cb686b99 987 bbg_file_stamp));
5366b186 988 info_fields = DECL_CHAIN (info_fields);
dd486eb2 989
ca29da43 990 /* Filename */
2f908293
SP
991 da_file_name_len = strlen (da_file_name);
992 filename_string = build_string (da_file_name_len + 1, da_file_name);
4a90aeeb 993 TREE_TYPE (filename_string) = build_array_type
f81b1a3d 994 (char_type_node, build_index_type (size_int (da_file_name_len)));
5366b186
NS
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);
159b3be1 999
5366b186
NS
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++)
ca29da43 1003 {
5366b186 1004 tree ptr = null_pointer_node;
159b3be1 1005
5366b186
NS
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);
ca29da43 1021 }
5366b186
NS
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 */
b724567e
NS
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);
5366b186 1031 info_fields = DECL_CHAIN (info_fields);
5366b186 1032
b724567e 1033 /* functions */
5366b186 1034 CONSTRUCTOR_APPEND_ELT (v1, info_fields,
b724567e
NS
1035 build1 (ADDR_EXPR, TREE_TYPE (info_fields), fn_ary));
1036 info_fields = DECL_CHAIN (info_fields);
1037
1038 gcc_assert (!info_fields);
5366b186 1039 return build_constructor (info_type, v1);
ca29da43
NS
1040}
1041
d6d7eee1
GW
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
78681a7b
ML
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);
8c9434c2
ML
1068}
1069
1070/* Generate the destructor function to call __gcov_exit. */
1071
1072static void
1073build_gcov_exit_decl (void)
1074{
16e81d51 1075 tree init_fn = build_function_type_list (void_type_node, NULL);
8c9434c2
ML
1076 init_fn = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
1077 get_identifier ("__gcov_exit"), init_fn);
1078 TREE_PUBLIC (init_fn) = 1;
1079 DECL_EXTERNAL (init_fn) = 1;
1080 DECL_ASSEMBLER_NAME (init_fn);
1081
1082 /* Generate a call to __gcov_exit (). */
1083 tree dtor = NULL;
1084 tree stmt = build_call_expr (init_fn, 0);
1085 append_to_statement_list (stmt, &dtor);
1086
78681a7b
ML
1087 /* Generate a destructor to run it. */
1088 int priority = SUPPORTS_INIT_PRIORITY
1089 ? MAX_RESERVED_INIT_PRIORITY: DEFAULT_INIT_PRIORITY;
1090
1091 cgraph_build_static_cdtor ('D', dtor, priority);
d6d7eee1
GW
1092}
1093
b724567e
NS
1094/* Create the gcov_info types and object. Generate the constructor
1095 function to call __gcov_init. Does not generate the initializer
1096 for the object. Returns TRUE if coverage data is being emitted. */
ca29da43 1097
b724567e
NS
1098static bool
1099coverage_obj_init (void)
ca29da43 1100{
d6d7eee1 1101 tree gcov_info_type;
b724567e 1102 unsigned n_counters = 0;
5366b186 1103 unsigned ix;
b724567e
NS
1104 struct coverage_data *fn;
1105 struct coverage_data **fn_prev;
c9b9aa64 1106 char name_buf[32];
ca29da43 1107
6d70e6be 1108 no_coverage = 1; /* Disable any further coverage. */
159b3be1 1109
cdb23767 1110 if (!prg_ctr_mask)
b724567e 1111 return false;
159b3be1 1112
3dafb85c
ML
1113 if (symtab->dump_file)
1114 fprintf (symtab->dump_file, "Using data file %s\n", da_file_name);
ca29da43 1115
b724567e 1116 /* Prune functions. */
5366b186
NS
1117 for (fn_prev = &functions_head; (fn = *fn_prev);)
1118 if (DECL_STRUCT_FUNCTION (fn->fn_decl))
b724567e 1119 fn_prev = &fn->next;
5366b186
NS
1120 else
1121 /* The function is not being emitted, remove from list. */
1122 *fn_prev = fn->next;
b724567e 1123
0f9fb22f
JJ
1124 if (functions_head == NULL)
1125 return false;
1126
b724567e
NS
1127 for (ix = 0; ix != GCOV_COUNTERS; ix++)
1128 if ((1u << ix) & prg_ctr_mask)
1129 n_counters++;
5366b186
NS
1130
1131 /* Build the info and fn_info types. These are mutually recursive. */
1132 gcov_info_type = lang_hooks.types.make_type (RECORD_TYPE);
b724567e 1133 gcov_fn_info_type = lang_hooks.types.make_type (RECORD_TYPE);
dafb7b56
JH
1134 build_fn_info_type (gcov_fn_info_type, n_counters, gcov_info_type);
1135 gcov_info_type = lang_hooks.types.make_type (RECORD_TYPE);
b724567e
NS
1136 gcov_fn_info_ptr_type = build_pointer_type
1137 (build_qualified_type (gcov_fn_info_type, TYPE_QUAL_CONST));
b724567e 1138 build_info_type (gcov_info_type, gcov_fn_info_ptr_type);
5366b186
NS
1139
1140 /* Build the gcov info var, this is referred to in its own
1141 initializer. */
b724567e
NS
1142 gcov_info_var = build_decl (BUILTINS_LOCATION,
1143 VAR_DECL, NULL_TREE, gcov_info_type);
1144 TREE_STATIC (gcov_info_var) = 1;
c9b9aa64 1145 ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
b724567e 1146 DECL_NAME (gcov_info_var) = get_identifier (name_buf);
ca29da43 1147
d6d7eee1 1148 build_init_ctor (gcov_info_type);
8c9434c2 1149 build_gcov_exit_decl ();
b724567e
NS
1150
1151 return true;
ca29da43 1152}
b724567e
NS
1153
1154/* Generate the coverage function info for FN and DATA. Append a
1155 pointer to that object to CTOR and return the appended CTOR. */
1156
9771b263
DN
1157static vec<constructor_elt, va_gc> *
1158coverage_obj_fn (vec<constructor_elt, va_gc> *ctor, tree fn,
b724567e
NS
1159 struct coverage_data const *data)
1160{
1161 tree init = build_fn_info (data, gcov_fn_info_type, gcov_info_var);
1162 tree var = build_var (fn, gcov_fn_info_type, -1);
1163
1164 DECL_INITIAL (var) = init;
9041d2e6 1165 varpool_node::finalize_decl (var);
b724567e
NS
1166
1167 CONSTRUCTOR_APPEND_ELT (ctor, NULL,
1168 build1 (ADDR_EXPR, gcov_fn_info_ptr_type, var));
1169 return ctor;
1170}
1171
1172/* Finalize the coverage data. Generates the array of pointers to
1173 function objects from CTOR. Generate the gcov_info initializer. */
1174
1175static void
9771b263 1176coverage_obj_finish (vec<constructor_elt, va_gc> *ctor)
b724567e 1177{
9771b263 1178 unsigned n_functions = vec_safe_length (ctor);
b724567e
NS
1179 tree fn_info_ary_type = build_array_type
1180 (build_qualified_type (gcov_fn_info_ptr_type, TYPE_QUAL_CONST),
1181 build_index_type (size_int (n_functions - 1)));
1182 tree fn_info_ary = build_decl (BUILTINS_LOCATION, VAR_DECL, NULL_TREE,
1183 fn_info_ary_type);
1184 char name_buf[32];
1185
1186 TREE_STATIC (fn_info_ary) = 1;
1187 ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 1);
1188 DECL_NAME (fn_info_ary) = get_identifier (name_buf);
1189 DECL_INITIAL (fn_info_ary) = build_constructor (fn_info_ary_type, ctor);
9041d2e6 1190 varpool_node::finalize_decl (fn_info_ary);
b724567e
NS
1191
1192 DECL_INITIAL (gcov_info_var)
1193 = build_info (TREE_TYPE (gcov_info_var), fn_info_ary);
9041d2e6 1194 varpool_node::finalize_decl (gcov_info_var);
b724567e
NS
1195}
1196
ca29da43 1197/* Perform file-level initialization. Read in data file, generate name
efbb59b2 1198 of notes file. */
ca29da43
NS
1199
1200void
159b3be1 1201coverage_init (const char *filename)
ca29da43 1202{
e9f799d2
ML
1203#if HAVE_DOS_BASED_FILE_SYSTEM
1204 const char *separator = "\\";
1205#else
1206 const char *separator = "/";
1207#endif
ca29da43 1208 int len = strlen (filename);
b724567e 1209 int prefix_len = 0;
b8698a0f 1210
103ff0d6
TJ
1211 /* Since coverage_init is invoked very early, before the pass
1212 manager, we need to set up the dumping explicitly. This is
1213 similar to the handling in finish_optimization_passes. */
47e0da37
DM
1214 int profile_pass_num =
1215 g->get_passes ()->get_pass_profile ()->static_pass_number;
1216 g->get_dumps ()->dump_start (profile_pass_num, NULL);
103ff0d6 1217
1f2bb38a
ML
1218 if (!IS_ABSOLUTE_PATH (filename))
1219 {
1220 /* When a profile_data_prefix is provided, then mangle full path
1221 of filename in order to prevent file path clashing. */
1222 if (profile_data_prefix)
1223 {
1f2bb38a 1224 filename = concat (getpwd (), separator, filename, NULL);
44b32683
JH
1225 if (profile_prefix_path)
1226 {
1227 if (!strncmp (filename, profile_prefix_path,
1228 strlen (profile_prefix_path)))
1229 {
1230 filename += strlen (profile_prefix_path);
1231 while (*filename == *separator)
1232 filename++;
1233 }
1234 else
1235 warning (0, "filename %qs does not start with profile "
1236 "prefix %qs", filename, profile_prefix_path);
1237 }
1f2bb38a
ML
1238 filename = mangle_path (filename);
1239 len = strlen (filename);
1240 }
1241 else
1242 profile_data_prefix = getpwd ();
1243 }
2f908293 1244
b724567e
NS
1245 if (profile_data_prefix)
1246 prefix_len = strlen (profile_data_prefix);
ca29da43 1247
796621e8 1248 /* Name of da file. */
b8698a0f 1249 da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX)
b724567e 1250 + prefix_len + 2);
2f908293
SP
1251
1252 if (profile_data_prefix)
1253 {
b724567e 1254 memcpy (da_file_name, profile_data_prefix, prefix_len);
e9f799d2 1255 da_file_name[prefix_len++] = *separator;
2f908293 1256 }
b724567e
NS
1257 memcpy (da_file_name + prefix_len, filename, len);
1258 strcpy (da_file_name + prefix_len + len, GCOV_DATA_SUFFIX);
159b3be1 1259
cb686b99
NS
1260 bbg_file_stamp = local_tick;
1261
be3c16c4
DC
1262 if (flag_auto_profile)
1263 read_autofdo_file ();
1264 else if (flag_branch_probabilities)
cb686b99
NS
1265 read_counts_file ();
1266
796621e8 1267 /* Name of bbg file. */
b724567e
NS
1268 if (flag_test_coverage && !flag_compare_debug)
1269 {
8e37c995
ML
1270 if (profile_note_location)
1271 bbg_file_name = xstrdup (profile_note_location);
1272 else
1273 {
1274 bbg_file_name = XNEWVEC (char, len + strlen (GCOV_NOTE_SUFFIX) + 1);
1275 memcpy (bbg_file_name, filename, len);
1276 strcpy (bbg_file_name + len, GCOV_NOTE_SUFFIX);
1277 }
b724567e
NS
1278
1279 if (!gcov_open (bbg_file_name, -1))
1280 {
1281 error ("cannot open %s", bbg_file_name);
1282 bbg_file_name = NULL;
1283 }
1284 else
1285 {
1286 gcov_write_unsigned (GCOV_NOTE_MAGIC);
1287 gcov_write_unsigned (GCOV_VERSION);
cb686b99 1288 gcov_write_unsigned (bbg_file_stamp);
c74bd3fb 1289 gcov_write_string (getpwd ());
93814e2d
ML
1290
1291 /* Do not support has_unexecuted_blocks for Ada. */
1292 gcov_write_unsigned (strcmp (lang_hooks.name, "GNU Ada") != 0);
b724567e
NS
1293 }
1294 }
103ff0d6 1295
47e0da37 1296 g->get_dumps ()->dump_finish (profile_pass_num);
ca29da43
NS
1297}
1298
efbb59b2 1299/* Performs file-level cleanup. Close notes file, generate coverage
ca29da43
NS
1300 variables and constructor. */
1301
1302void
159b3be1 1303coverage_finish (void)
ca29da43 1304{
b724567e
NS
1305 if (bbg_file_name && gcov_close ())
1306 unlink (bbg_file_name);
cb686b99
NS
1307
1308 if (!flag_branch_probabilities && flag_test_coverage
1309 && (!local_tick || local_tick == (unsigned)-1))
1310 /* Only remove the da file, if we're emitting coverage code and
1311 cannot uniquely stamp it. If we can stamp it, libgcov will DTRT. */
b724567e
NS
1312 unlink (da_file_name);
1313
1314 if (coverage_obj_init ())
ca29da43 1315 {
9771b263 1316 vec<constructor_elt, va_gc> *fn_ctor = NULL;
b724567e
NS
1317 struct coverage_data *fn;
1318
1319 for (fn = functions_head; fn; fn = fn->next)
1320 fn_ctor = coverage_obj_fn (fn_ctor, fn->fn_decl, fn);
1321 coverage_obj_finish (fn_ctor);
ca29da43 1322 }
782f0db2
DM
1323
1324 XDELETEVEC (da_file_name);
1325 da_file_name = NULL;
ca29da43
NS
1326}
1327
ca29da43 1328#include "gt-coverage.h"