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