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