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