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