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