]> gcc.gnu.org Git - gcc.git/blame - gcc/coverage.c
re PR c++/20679 (Parse error when accessing attributes of an inner class. Enclosing...
[gcc.git] / gcc / coverage.c
CommitLineData
ca29da43
NS
1/* Read and write coverage files, and associated functionality.
2 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
7da1799a 3 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
ca29da43
NS
4 Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
5 based on some ideas from Dain Samples of UC Berkeley.
6 Further mangling by Bob Manson, Cygnus Support.
7 Further mangled by Nathan Sidwell, CodeSourcery
8
9This file is part of GCC.
10
11GCC is free software; you can redistribute it and/or modify it under
12the terms of the GNU General Public License as published by the Free
13Software Foundation; either version 2, or (at your option) any later
14version.
15
16GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17WARRANTY; without even the implied warranty of MERCHANTABILITY or
18FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19for more details.
20
21You should have received a copy of the GNU General Public License
22along with GCC; see the file COPYING. If not, write to the Free
23Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2402111-1307, USA. */
25
26
27#define GCOV_LINKAGE
28
29#include "config.h"
30#include "system.h"
31#include "coretypes.h"
32#include "tm.h"
33#include "rtl.h"
34#include "tree.h"
35#include "flags.h"
36#include "output.h"
37#include "regs.h"
38#include "expr.h"
39#include "function.h"
40#include "toplev.h"
41#include "ggc.h"
ca29da43 42#include "coverage.h"
ca29da43
NS
43#include "langhooks.h"
44#include "hashtab.h"
c9b9aa64
RH
45#include "tree-iterator.h"
46#include "cgraph.h"
ca29da43
NS
47
48#include "gcov-io.c"
49
50struct function_list
51{
159b3be1
AJ
52 struct function_list *next; /* next function */
53 unsigned ident; /* function ident */
cdb23767
NS
54 unsigned checksum; /* function checksum */
55 unsigned n_ctrs[GCOV_COUNTERS];/* number of counters. */
ca29da43
NS
56};
57
58/* Counts information for a function. */
59typedef struct counts_entry
60{
61 /* We hash by */
796621e8 62 unsigned ident;
cdb23767 63 unsigned ctr;
159b3be1 64
ca29da43
NS
65 /* Store */
66 unsigned checksum;
ca29da43 67 gcov_type *counts;
cdb23767 68 struct gcov_ctr_summary summary;
ca29da43
NS
69
70 /* Workspace */
71 struct counts_entry *chain;
159b3be1 72
ca29da43
NS
73} counts_entry_t;
74
75static struct function_list *functions_head = 0;
76static struct function_list **functions_tail = &functions_head;
6d70e6be 77static unsigned no_coverage = 0;
ca29da43 78
cdb23767
NS
79/* Cumulative counter information for whole program. */
80static unsigned prg_ctr_mask; /* Mask of counter types generated. */
6d70e6be 81static unsigned prg_n_ctrs[GCOV_COUNTERS]; /* Total counters allocated. */
ca29da43 82
cdb23767 83/* Counter information for current function. */
71c0e7fc 84static unsigned fn_ctr_mask; /* Mask of counters used. */
6d70e6be
NS
85static unsigned fn_n_ctrs[GCOV_COUNTERS]; /* Counters allocated. */
86static unsigned fn_b_ctrs[GCOV_COUNTERS]; /* Allocation base. */
ca29da43
NS
87
88/* Name of the output file for coverage output file. */
89static char *bbg_file_name;
90static unsigned bbg_file_opened;
91static int bbg_function_announced;
92
93/* Name of the count data file. */
94static char *da_file_name;
95
96/* Hash table of count data. */
97static htab_t counts_hash = NULL;
98
6de9cd9a
DN
99/* Trees representing the counter table arrays. */
100static GTY(()) tree tree_ctr_tables[GCOV_COUNTERS];
101
102/* The names of the counter tables. Not used if we're
103 generating counters at tree level. */
cdb23767 104static GTY(()) rtx ctr_labels[GCOV_COUNTERS];
ca29da43 105
09780dfb 106/* The names of merge functions for counters. */
9b514d25
NS
107static const char *const ctr_merge_functions[GCOV_COUNTERS] = GCOV_MERGE_FUNCTIONS;
108static const char *const ctr_names[GCOV_COUNTERS] = GCOV_COUNTER_NAMES;
09780dfb 109
ca29da43 110/* Forward declarations. */
159b3be1
AJ
111static hashval_t htab_counts_entry_hash (const void *);
112static int htab_counts_entry_eq (const void *, const void *);
113static void htab_counts_entry_del (void *);
114static void read_counts_file (void);
115static unsigned compute_checksum (void);
20c361f3 116static unsigned coverage_checksum_string (unsigned, const char *);
159b3be1
AJ
117static tree build_fn_info_type (unsigned);
118static tree build_fn_info_value (const struct function_list *, tree);
119static tree build_ctr_info_type (void);
120static tree build_ctr_info_value (unsigned, tree);
121static tree build_gcov_info (void);
122static void create_coverage (void);
ca29da43
NS
123
124\f
125static hashval_t
159b3be1 126htab_counts_entry_hash (const void *of)
ca29da43
NS
127{
128 const counts_entry_t *entry = of;
129
796621e8 130 return entry->ident * GCOV_COUNTERS + entry->ctr;
ca29da43
NS
131}
132
133static int
159b3be1 134htab_counts_entry_eq (const void *of1, const void *of2)
ca29da43
NS
135{
136 const counts_entry_t *entry1 = of1;
137 const counts_entry_t *entry2 = of2;
138
796621e8 139 return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
ca29da43
NS
140}
141
142static void
159b3be1 143htab_counts_entry_del (void *of)
ca29da43
NS
144{
145 counts_entry_t *entry = of;
146
ca29da43
NS
147 free (entry->counts);
148 free (entry);
149}
150
151/* Read in the counts file, if available. */
152
153static void
159b3be1 154read_counts_file (void)
ca29da43 155{
9b514d25 156 gcov_unsigned_t fn_ident = 0;
160e2e4f 157 gcov_unsigned_t checksum = -1;
ca29da43
NS
158 counts_entry_t *summaried = NULL;
159 unsigned seen_summary = 0;
7d63a2fa 160 gcov_unsigned_t tag;
24a4a033 161 int is_error = 0;
7d63a2fa 162
ca29da43
NS
163 if (!gcov_open (da_file_name, 1))
164 return;
159b3be1 165
160e2e4f 166 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
ca29da43 167 {
971801ff 168 warning ("%qs is not a gcov data file", da_file_name);
ca29da43
NS
169 gcov_close ();
170 return;
171 }
160e2e4f 172 else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
ca29da43 173 {
330d2e2a
NS
174 char v[4], e[4];
175
176 GCOV_UNSIGNED2STRING (v, tag);
177 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
159b3be1 178
971801ff 179 warning ("%qs is version %q.*s, expected version %q.*s",
cb83302c 180 da_file_name, 4, v, 4, e);
ca29da43
NS
181 gcov_close ();
182 return;
183 }
159b3be1 184
4ed43216 185 /* Read and discard the stamp. */
dd486eb2
NS
186 gcov_read_unsigned ();
187
ca29da43
NS
188 counts_hash = htab_create (10,
189 htab_counts_entry_hash, htab_counts_entry_eq,
190 htab_counts_entry_del);
7d63a2fa 191 while ((tag = gcov_read_unsigned ()))
ca29da43 192 {
7d63a2fa 193 gcov_unsigned_t length;
9b514d25 194 gcov_position_t offset;
159b3be1 195
ca29da43
NS
196 length = gcov_read_unsigned ();
197 offset = gcov_position ();
198 if (tag == GCOV_TAG_FUNCTION)
199 {
796621e8 200 fn_ident = gcov_read_unsigned ();
ca29da43
NS
201 checksum = gcov_read_unsigned ();
202 if (seen_summary)
203 {
204 /* We have already seen a summary, this means that this
205 new function begins a new set of program runs. We
206 must unlink the summaried chain. */
207 counts_entry_t *entry, *chain;
159b3be1 208
ca29da43
NS
209 for (entry = summaried; entry; entry = chain)
210 {
211 chain = entry->chain;
ca29da43
NS
212 entry->chain = NULL;
213 }
214 summaried = NULL;
215 seen_summary = 0;
216 }
217 }
218 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
219 {
220 counts_entry_t *entry;
221 struct gcov_summary summary;
159b3be1 222
ca29da43
NS
223 gcov_read_summary (&summary);
224 seen_summary = 1;
225 for (entry = summaried; entry; entry = entry->chain)
226 {
cdb23767 227 struct gcov_ctr_summary *csum = &summary.ctrs[entry->ctr];
159b3be1 228
cdb23767
NS
229 entry->summary.runs += csum->runs;
230 entry->summary.sum_all += csum->sum_all;
231 if (entry->summary.run_max < csum->run_max)
232 entry->summary.run_max = csum->run_max;
233 entry->summary.sum_max += csum->sum_max;
ca29da43
NS
234 }
235 }
796621e8 236 else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
ca29da43
NS
237 {
238 counts_entry_t **slot, *entry, elt;
330d2e2a 239 unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
ca29da43
NS
240 unsigned ix;
241
796621e8 242 elt.ident = fn_ident;
cdb23767 243 elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
ca29da43
NS
244
245 slot = (counts_entry_t **) htab_find_slot
246 (counts_hash, &elt, INSERT);
247 entry = *slot;
248 if (!entry)
249 {
cdb23767 250 *slot = entry = xcalloc (1, sizeof (counts_entry_t));
796621e8 251 entry->ident = elt.ident;
cdb23767 252 entry->ctr = elt.ctr;
ca29da43 253 entry->checksum = checksum;
cdb23767 254 entry->summary.num = n_counts;
ca29da43
NS
255 entry->counts = xcalloc (n_counts, sizeof (gcov_type));
256 }
24a4a033 257 else if (entry->checksum != checksum)
ca29da43 258 {
24a4a033
JH
259 error ("coverage mismatch for function %u while reading execution counters.",
260 fn_ident);
261 error ("checksum is %x instead of %x", entry->checksum, checksum);
262 htab_delete (counts_hash);
263 break;
264 }
265 else if (entry->summary.num != n_counts)
266 {
267 error ("coverage mismatch for function %u while reading execution counters.",
268 fn_ident);
269 error ("number of counters is %d instead of %d", entry->summary.num, n_counts);
ca29da43
NS
270 htab_delete (counts_hash);
271 break;
272 }
9b514d25
NS
273 else if (elt.ctr >= GCOV_COUNTERS_SUMMABLE)
274 {
24a4a033
JH
275 error ("cannot merge separate %s counters for function %u",
276 ctr_names[elt.ctr], fn_ident);
9b514d25
NS
277 goto skip_merge;
278 }
279
280 if (elt.ctr < GCOV_COUNTERS_SUMMABLE
281 /* This should always be true for a just allocated entry,
159b3be1
AJ
282 and always false for an existing one. Check this way, in
283 case the gcov file is corrupt. */
9b514d25 284 && (!entry->chain || summaried != entry))
ca29da43
NS
285 {
286 entry->chain = summaried;
287 summaried = entry;
288 }
289 for (ix = 0; ix != n_counts; ix++)
290 entry->counts[ix] += gcov_read_counter ();
9b514d25 291 skip_merge:;
ca29da43 292 }
474f141e 293 gcov_sync (offset, length);
24a4a033 294 if ((is_error = gcov_is_error ()))
00cf2913 295 {
971801ff 296 error (is_error < 0 ? "%qs has overflowed" : "%qs is corrupted",
00cf2913
NS
297 da_file_name);
298 htab_delete (counts_hash);
299 break;
300 }
7d63a2fa 301 }
159b3be1 302
ca29da43
NS
303 gcov_close ();
304}
305
306/* Returns the counters for a particular tag. */
307
308gcov_type *
cdb23767
NS
309get_coverage_counts (unsigned counter, unsigned expected,
310 const struct gcov_ctr_summary **summary)
ca29da43
NS
311{
312 counts_entry_t *entry, elt;
24a4a033 313 gcov_unsigned_t checksum = -1;
ca29da43 314
71c0e7fc 315 /* No hash table, no counts. */
ca29da43
NS
316 if (!counts_hash)
317 {
318 static int warned = 0;
319
320 if (!warned++)
02307675
R
321 inform ((flag_guess_branch_prob
322 ? "file %s not found, execution counts estimated"
323 : "file %s not found, execution counts assumed to be zero"),
bbfff586 324 da_file_name);
ca29da43
NS
325 return NULL;
326 }
327
6d70e6be 328 elt.ident = current_function_funcdef_no + 1;
cdb23767 329 elt.ctr = counter;
ca29da43
NS
330 entry = htab_find (counts_hash, &elt);
331 if (!entry)
332 {
971801ff 333 warning ("no coverage for function %qs found.", IDENTIFIER_POINTER
796621e8 334 (DECL_ASSEMBLER_NAME (current_function_decl)));
ca29da43
NS
335 return 0;
336 }
159b3be1 337
24a4a033
JH
338 checksum = compute_checksum ();
339 if (entry->checksum != checksum)
ca29da43 340 {
971801ff 341 error ("coverage mismatch for function %qs while reading counter %qs.",
24a4a033
JH
342 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
343 ctr_names[counter]);
344 error ("checksum is %x instead of %x", entry->checksum, checksum);
345 return 0;
346 }
347 else if (entry->summary.num != expected)
348 {
971801ff 349 error ("coverage mismatch for function %qs while reading counter %qs.",
24a4a033
JH
350 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
351 ctr_names[counter]);
352 error ("number of counters is %d instead of %d", entry->summary.num, expected);
353 return 0;
ca29da43 354 }
159b3be1 355
cdb23767
NS
356 if (summary)
357 *summary = &entry->summary;
ca29da43
NS
358
359 return entry->counts;
360}
cdb23767 361
6356f892 362/* Allocate NUM counters of type COUNTER. Returns nonzero if the
6d70e6be 363 allocation succeeded. */
cdb23767 364
6d70e6be
NS
365int
366coverage_counter_alloc (unsigned counter, unsigned num)
cdb23767 367{
6d70e6be
NS
368 if (no_coverage)
369 return 0;
159b3be1 370
6d70e6be
NS
371 if (!num)
372 return 1;
159b3be1 373
6de9cd9a 374 if (!tree_ctr_tables[counter])
cdb23767
NS
375 {
376 /* Generate and save a copy of this so it can be shared. */
6de9cd9a
DN
377 /* We don't know the size yet; make it big enough that nobody
378 will make any clever transformation on it. */
cdb23767 379 char buf[20];
6de9cd9a 380 tree domain_tree
7d60be94 381 = build_index_type (build_int_cst (NULL_TREE, 1000)); /* replaced later */
6de9cd9a
DN
382 tree gcov_type_array_type
383 = build_array_type (GCOV_TYPE_NODE, domain_tree);
384 tree_ctr_tables[counter]
385 = build_decl (VAR_DECL, NULL_TREE, gcov_type_array_type);
386 TREE_STATIC (tree_ctr_tables[counter]) = 1;
cdb23767 387 ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
6de9cd9a
DN
388 DECL_NAME (tree_ctr_tables[counter]) = get_identifier (buf);
389 DECL_ALIGN (tree_ctr_tables[counter]) = TYPE_ALIGN (GCOV_TYPE_NODE);
cdb23767 390 }
6d70e6be
NS
391 fn_b_ctrs[counter] = fn_n_ctrs[counter];
392 fn_n_ctrs[counter] += num;
393 fn_ctr_mask |= 1 << counter;
394 return 1;
395}
cdb23767 396
6d70e6be
NS
397/* Generate a MEM rtl to access COUNTER NO. */
398
399rtx
6de9cd9a 400rtl_coverage_counter_ref (unsigned counter, unsigned no)
6d70e6be
NS
401{
402 unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
403 enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
404 rtx ref;
405
341c100f 406 gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
6d70e6be 407 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
6de9cd9a
DN
408 if (!ctr_labels[counter])
409 {
410 ctr_labels[counter] = gen_rtx_SYMBOL_REF (Pmode,
411 ggc_strdup (IDENTIFIER_POINTER (DECL_NAME
412 (tree_ctr_tables[counter]))));
413 SYMBOL_REF_FLAGS (ctr_labels[counter]) = SYMBOL_FLAG_LOCAL;
414 }
9b514d25 415 ref = plus_constant (ctr_labels[counter], gcov_size / BITS_PER_UNIT * no);
cdb23767
NS
416 ref = gen_rtx_MEM (mode, ref);
417 set_mem_alias_set (ref, new_alias_set ());
27ab3e91 418 MEM_NOTRAP_P (ref) = 1;
cdb23767
NS
419
420 return ref;
421}
6de9cd9a
DN
422
423/* Generate a tree to access COUNTER NO. */
424
425tree
426tree_coverage_counter_ref (unsigned counter, unsigned no)
427{
44de5aeb 428 tree domain_type = TYPE_DOMAIN (TREE_TYPE (tree_ctr_tables[counter]));
6de9cd9a 429
341c100f 430 gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
6de9cd9a
DN
431 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
432
433 /* "no" here is an array index, scaled to bytes later. */
3244e67d 434 return build4 (ARRAY_REF, GCOV_TYPE_NODE, tree_ctr_tables[counter],
4a90aeeb 435 fold_convert (domain_type,
7d60be94 436 build_int_cst (NULL_TREE, no)),
3244e67d
RS
437 TYPE_MIN_VALUE (domain_type),
438 size_binop (EXACT_DIV_EXPR, TYPE_SIZE_UNIT (GCOV_TYPE_NODE),
d836edf8 439 size_int (TYPE_ALIGN_UNIT (GCOV_TYPE_NODE))));
6de9cd9a 440}
ca29da43
NS
441\f
442/* Generate a checksum for a string. CHKSUM is the current
71c0e7fc 443 checksum. */
ca29da43
NS
444
445static unsigned
20c361f3 446coverage_checksum_string (unsigned chksum, const char *string)
ca29da43 447{
20c361f3
JH
448 int i;
449 char *dup = NULL;
450
451 /* Look for everything that looks if it were produced by
452 get_file_function_name_long and zero out the second part
453 that may result from flag_random_seed. This is not critical
454 as the checksums are used only for sanity checking. */
455 for (i = 0; string[i]; i++)
ca29da43 456 {
20c361f3
JH
457 if (!strncmp (string + i, "_GLOBAL__", 9))
458 for (i = i + 9; string[i]; i++)
459 if (string[i]=='_')
460 {
461 int y;
462 unsigned seed;
341c100f 463 int scan;
20c361f3
JH
464
465 for (y = 1; y < 9; y++)
466 if (!(string[i + y] >= '0' && string[i + y] <= '9')
467 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
468 break;
469 if (y != 9 || string[i + 9] != '_')
470 continue;
471 for (y = 10; y < 18; y++)
472 if (!(string[i + y] >= '0' && string[i + y] <= '9')
473 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
474 break;
475 if (y != 18)
476 continue;
341c100f
NS
477 scan = sscanf (string + i + 10, "%X", &seed);
478 gcc_assert (scan);
20c361f3
JH
479 if (seed != crc32_string (0, flag_random_seed))
480 continue;
481 string = dup = xstrdup (string);
482 for (y = 10; y < 18; y++)
483 dup[i + y] = '0';
484 break;
485 }
486 break;
ca29da43 487 }
20c361f3
JH
488
489 chksum = crc32_string (chksum, string);
490 if (dup)
491 free (dup);
159b3be1 492
ca29da43
NS
493 return chksum;
494}
495
496/* Compute checksum for the current function. We generate a CRC32. */
497
498static unsigned
159b3be1 499compute_checksum (void)
ca29da43 500{
a281759f
PB
501 expanded_location xloc
502 = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
503 unsigned chksum = xloc.line;
ca29da43 504
a281759f 505 chksum = coverage_checksum_string (chksum, xloc.file);
20c361f3 506 chksum = coverage_checksum_string
ca29da43
NS
507 (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
508
509 return chksum;
510}
511\f
512/* Begin output to the graph file for the current function.
513 Opens the output file, if not already done. Writes the
6356f892 514 function header, if not already done. Returns nonzero if data
ca29da43
NS
515 should be output. */
516
517int
159b3be1 518coverage_begin_output (void)
ca29da43 519{
6d70e6be
NS
520 if (no_coverage)
521 return 0;
159b3be1 522
ca29da43
NS
523 if (!bbg_function_announced)
524 {
a281759f
PB
525 expanded_location xloc
526 = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
ca29da43 527 unsigned long offset;
159b3be1 528
ca29da43
NS
529 if (!bbg_file_opened)
530 {
531 if (!gcov_open (bbg_file_name, -1))
532 error ("cannot open %s", bbg_file_name);
533 else
534 {
160e2e4f 535 gcov_write_unsigned (GCOV_NOTE_MAGIC);
ca29da43 536 gcov_write_unsigned (GCOV_VERSION);
dd486eb2 537 gcov_write_unsigned (local_tick);
ca29da43
NS
538 }
539 bbg_file_opened = 1;
540 }
159b3be1 541
ca29da43
NS
542 /* Announce function */
543 offset = gcov_write_tag (GCOV_TAG_FUNCTION);
6d70e6be 544 gcov_write_unsigned (current_function_funcdef_no + 1);
796621e8 545 gcov_write_unsigned (compute_checksum ());
ca29da43
NS
546 gcov_write_string (IDENTIFIER_POINTER
547 (DECL_ASSEMBLER_NAME (current_function_decl)));
a281759f
PB
548 gcov_write_string (xloc.file);
549 gcov_write_unsigned (xloc.line);
ca29da43
NS
550 gcov_write_length (offset);
551
552 bbg_function_announced = 1;
553 }
554 return !gcov_is_error ();
555}
556
557/* Finish coverage data for the current function. Verify no output
558 error has occurred. Save function coverage counts. */
559
560void
159b3be1 561coverage_end_function (void)
ca29da43
NS
562{
563 unsigned i;
159b3be1 564
ca29da43 565 if (bbg_file_opened > 1 && gcov_is_error ())
159b3be1 566 {
971801ff 567 warning ("error writing %qs", bbg_file_name);
ca29da43
NS
568 bbg_file_opened = -1;
569 }
cdb23767
NS
570
571 if (fn_ctr_mask)
572 {
573 struct function_list *item;
159b3be1 574
cdb23767 575 item = xmalloc (sizeof (struct function_list));
159b3be1 576
cdb23767
NS
577 *functions_tail = item;
578 functions_tail = &item->next;
159b3be1 579
cdb23767 580 item->next = 0;
6d70e6be 581 item->ident = current_function_funcdef_no + 1;
cdb23767
NS
582 item->checksum = compute_checksum ();
583 for (i = 0; i != GCOV_COUNTERS; i++)
584 {
585 item->n_ctrs[i] = fn_n_ctrs[i];
586 prg_n_ctrs[i] += fn_n_ctrs[i];
6d70e6be 587 fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
cdb23767
NS
588 }
589 prg_ctr_mask |= fn_ctr_mask;
590 fn_ctr_mask = 0;
591 }
ca29da43
NS
592 bbg_function_announced = 0;
593}
594
cdb23767 595/* Creates the gcov_fn_info RECORD_TYPE. */
ca29da43 596
ca29da43 597static tree
159b3be1 598build_fn_info_type (unsigned int counters)
ca29da43 599{
ae2bcd98 600 tree type = lang_hooks.types.make_type (RECORD_TYPE);
ca29da43 601 tree field, fields;
cdb23767 602 tree array_type;
159b3be1 603
796621e8 604 /* ident */
9b514d25 605 fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
ca29da43 606
cdb23767 607 /* checksum */
9b514d25 608 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
ca29da43
NS
609 TREE_CHAIN (field) = fields;
610 fields = field;
611
7d60be94 612 array_type = build_int_cst (NULL_TREE, counters - 1);
4a90aeeb 613 array_type = build_index_type (array_type);
cdb23767 614 array_type = build_array_type (unsigned_type_node, array_type);
159b3be1 615
ca29da43 616 /* counters */
cdb23767 617 field = build_decl (FIELD_DECL, NULL_TREE, array_type);
ca29da43
NS
618 TREE_CHAIN (field) = fields;
619 fields = field;
620
cdb23767
NS
621 finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
622
623 return type;
ca29da43
NS
624}
625
cdb23767
NS
626/* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
627 the function being processed and TYPE is the gcov_fn_info
628 RECORD_TYPE. */
629
ca29da43 630static tree
159b3be1 631build_fn_info_value (const struct function_list *function, tree type)
ca29da43 632{
cdb23767
NS
633 tree value = NULL_TREE;
634 tree fields = TYPE_FIELDS (type);
cdb23767
NS
635 unsigned ix;
636 tree array_value = NULL_TREE;
159b3be1 637
796621e8 638 /* ident */
7d60be94
NS
639 value = tree_cons (fields, build_int_cstu (unsigned_intSI_type_node,
640 function->ident), value);
cdb23767 641 fields = TREE_CHAIN (fields);
159b3be1 642
cdb23767 643 /* checksum */
7d60be94
NS
644 value = tree_cons (fields, build_int_cstu (unsigned_intSI_type_node,
645 function->checksum), value);
cdb23767 646 fields = TREE_CHAIN (fields);
159b3be1 647
ca29da43 648 /* counters */
cdb23767
NS
649 for (ix = 0; ix != GCOV_COUNTERS; ix++)
650 if (prg_ctr_mask & (1 << ix))
651 {
7d60be94
NS
652 tree counters = build_int_cstu (unsigned_type_node,
653 function->n_ctrs[ix]);
159b3be1 654
cdb23767
NS
655 array_value = tree_cons (NULL_TREE, counters, array_value);
656 }
159b3be1 657
cdb23767
NS
658 array_value = build_constructor (TREE_TYPE (fields), nreverse (array_value));
659 value = tree_cons (fields, array_value, value);
ca29da43 660
cdb23767 661 value = build_constructor (type, nreverse (value));
159b3be1 662
ca29da43
NS
663 return value;
664}
665
cdb23767
NS
666/* Creates the gcov_ctr_info RECORD_TYPE. */
667
ca29da43 668static tree
159b3be1 669build_ctr_info_type (void)
ca29da43 670{
ae2bcd98 671 tree type = lang_hooks.types.make_type (RECORD_TYPE);
cdb23767 672 tree field, fields = NULL_TREE;
9b514d25 673 tree gcov_ptr_type = build_pointer_type (GCOV_TYPE_NODE);
09780dfb 674 tree gcov_merge_fn_type;
9b514d25 675
cdb23767 676 /* counters */
9b514d25 677 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
ca29da43
NS
678 TREE_CHAIN (field) = fields;
679 fields = field;
680
cdb23767 681 /* values */
9b514d25 682 field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
ca29da43
NS
683 TREE_CHAIN (field) = fields;
684 fields = field;
685
09780dfb
ZD
686 /* merge */
687 gcov_merge_fn_type =
9b514d25
NS
688 build_function_type_list (void_type_node,
689 gcov_ptr_type, unsigned_type_node,
690 NULL_TREE);
09780dfb
ZD
691 field = build_decl (FIELD_DECL, NULL_TREE,
692 build_pointer_type (gcov_merge_fn_type));
693 TREE_CHAIN (field) = fields;
694 fields = field;
695
cdb23767 696 finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
ca29da43 697
cdb23767 698 return type;
ca29da43
NS
699}
700
cdb23767
NS
701/* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
702 the counter being processed and TYPE is the gcov_ctr_info
703 RECORD_TYPE. */
704
ca29da43 705static tree
159b3be1 706build_ctr_info_value (unsigned int counter, tree type)
ca29da43
NS
707{
708 tree value = NULL_TREE;
cdb23767 709 tree fields = TYPE_FIELDS (type);
09780dfb 710 tree fn;
ca29da43 711
cdb23767
NS
712 /* counters */
713 value = tree_cons (fields,
7d60be94
NS
714 build_int_cstu (unsigned_intSI_type_node,
715 prg_n_ctrs[counter]),
ca29da43 716 value);
cdb23767 717 fields = TREE_CHAIN (fields);
ca29da43 718
cdb23767 719 if (prg_n_ctrs[counter])
ca29da43 720 {
6de9cd9a 721 tree array_type;
159b3be1 722
7d60be94
NS
723 array_type = build_int_cstu (unsigned_type_node,
724 prg_n_ctrs[counter] - 1);
4a90aeeb 725 array_type = build_index_type (array_type);
cdb23767
NS
726 array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
727 array_type);
159b3be1 728
6de9cd9a
DN
729 TREE_TYPE (tree_ctr_tables[counter]) = array_type;
730 DECL_SIZE (tree_ctr_tables[counter]) = TYPE_SIZE (array_type);
731 DECL_SIZE_UNIT (tree_ctr_tables[counter]) = TYPE_SIZE_UNIT (array_type);
732 assemble_variable (tree_ctr_tables[counter], 0, 0, 0);
159b3be1 733
cdb23767 734 value = tree_cons (fields,
6de9cd9a
DN
735 build1 (ADDR_EXPR, TREE_TYPE (fields),
736 tree_ctr_tables[counter]),
cdb23767 737 value);
ca29da43
NS
738 }
739 else
cdb23767 740 value = tree_cons (fields, null_pointer_node, value);
09780dfb
ZD
741 fields = TREE_CHAIN (fields);
742
743 fn = build_decl (FUNCTION_DECL,
744 get_identifier (ctr_merge_functions[counter]),
745 TREE_TYPE (TREE_TYPE (fields)));
746 DECL_EXTERNAL (fn) = 1;
747 TREE_PUBLIC (fn) = 1;
748 DECL_ARTIFICIAL (fn) = 1;
749 TREE_NOTHROW (fn) = 1;
750 value = tree_cons (fields,
9b514d25 751 build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
09780dfb 752 value);
ca29da43 753
cdb23767 754 value = build_constructor (type, nreverse (value));
159b3be1 755
ca29da43
NS
756 return value;
757}
758
cdb23767
NS
759/* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
760 CONSTRUCTOR. */
761
ca29da43 762static tree
159b3be1 763build_gcov_info (void)
ca29da43 764{
cdb23767
NS
765 unsigned n_ctr_types, ix;
766 tree type, const_type;
767 tree fn_info_type, fn_info_value = NULL_TREE;
768 tree fn_info_ptr_type;
769 tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
770 tree field, fields = NULL_TREE;
771 tree value = NULL_TREE;
772 tree filename_string;
ca29da43
NS
773 char *filename;
774 int filename_len;
cdb23767
NS
775 unsigned n_fns;
776 const struct function_list *fn;
777 tree string_type;
159b3be1 778
cdb23767
NS
779 /* Count the number of active counters. */
780 for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
781 if (prg_ctr_mask & (1 << ix))
782 n_ctr_types++;
159b3be1 783
ae2bcd98 784 type = lang_hooks.types.make_type (RECORD_TYPE);
cdb23767 785 const_type = build_qualified_type (type, TYPE_QUAL_CONST);
159b3be1 786
cdb23767 787 /* Version ident */
9b514d25 788 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
ca29da43
NS
789 TREE_CHAIN (field) = fields;
790 fields = field;
7d60be94
NS
791 value = tree_cons (field, build_int_cstu (unsigned_intSI_type_node,
792 GCOV_VERSION), value);
159b3be1 793
ca29da43 794 /* next -- NULL */
cdb23767
NS
795 field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
796 TREE_CHAIN (field) = fields;
797 fields = field;
798 value = tree_cons (field, null_pointer_node, value);
159b3be1 799
dd486eb2
NS
800 /* stamp */
801 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
802 TREE_CHAIN (field) = fields;
803 fields = field;
7d60be94
NS
804 value = tree_cons (field, build_int_cstu (unsigned_intSI_type_node,
805 local_tick), value);
dd486eb2 806
ca29da43 807 /* Filename */
cdb23767
NS
808 string_type = build_pointer_type (build_qualified_type (char_type_node,
809 TYPE_QUAL_CONST));
810 field = build_decl (FIELD_DECL, NULL_TREE, string_type);
811 TREE_CHAIN (field) = fields;
812 fields = field;
ca29da43
NS
813 filename = getpwd ();
814 filename = (filename && da_file_name[0] != '/'
815 ? concat (filename, "/", da_file_name, NULL)
816 : da_file_name);
817 filename_len = strlen (filename);
818 filename_string = build_string (filename_len + 1, filename);
819 if (filename != da_file_name)
820 free (filename);
4a90aeeb
NS
821 TREE_TYPE (filename_string) = build_array_type
822 (char_type_node, build_index_type
7d60be94 823 (build_int_cst (NULL_TREE, filename_len)));
cdb23767 824 value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
ca29da43 825 value);
159b3be1 826
cdb23767
NS
827 /* Build the fn_info type and initializer. */
828 fn_info_type = build_fn_info_type (n_ctr_types);
829 fn_info_ptr_type = build_pointer_type (build_qualified_type
830 (fn_info_type, TYPE_QUAL_CONST));
831 for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
832 fn_info_value = tree_cons (NULL_TREE,
833 build_fn_info_value (fn, fn_info_type),
834 fn_info_value);
835 if (n_fns)
ca29da43
NS
836 {
837 tree array_type;
838
7d60be94 839 array_type = build_index_type (build_int_cst (NULL_TREE, n_fns - 1));
cdb23767 840 array_type = build_array_type (fn_info_type, array_type);
159b3be1 841
cdb23767
NS
842 fn_info_value = build_constructor (array_type, nreverse (fn_info_value));
843 fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
ca29da43
NS
844 }
845 else
cdb23767 846 fn_info_value = null_pointer_node;
159b3be1 847
cdb23767
NS
848 /* number of functions */
849 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
850 TREE_CHAIN (field) = fields;
851 fields = field;
852 value = tree_cons (field,
7d60be94 853 build_int_cstu (unsigned_type_node, n_fns),
cdb23767 854 value);
159b3be1 855
cdb23767
NS
856 /* fn_info table */
857 field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type);
858 TREE_CHAIN (field) = fields;
859 fields = field;
860 value = tree_cons (field, fn_info_value, value);
ca29da43 861
cdb23767
NS
862 /* counter_mask */
863 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
864 TREE_CHAIN (field) = fields;
865 fields = field;
866 value = tree_cons (field,
7d60be94 867 build_int_cstu (unsigned_type_node, prg_ctr_mask),
ca29da43 868 value);
159b3be1 869
cdb23767
NS
870 /* counters */
871 ctr_info_type = build_ctr_info_type ();
4a90aeeb 872 ctr_info_ary_type = build_index_type (build_int_cst (NULL_TREE,
7d60be94 873 n_ctr_types));
cdb23767
NS
874 ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
875 for (ix = 0; ix != GCOV_COUNTERS; ix++)
876 if (prg_ctr_mask & (1 << ix))
877 ctr_info_value = tree_cons (NULL_TREE,
878 build_ctr_info_value (ix, ctr_info_type),
879 ctr_info_value);
880 ctr_info_value = build_constructor (ctr_info_ary_type,
881 nreverse (ctr_info_value));
882
883 field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
884 TREE_CHAIN (field) = fields;
885 fields = field;
886 value = tree_cons (field, ctr_info_value, value);
159b3be1 887
cdb23767 888 finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
ca29da43 889
cdb23767 890 value = build_constructor (type, nreverse (value));
159b3be1 891
ca29da43
NS
892 return value;
893}
894
cdb23767 895/* Write out the structure which libgcov uses to locate all the
ca29da43
NS
896 counters. The structures used here must match those defined in
897 gcov-io.h. Write out the constructor to call __gcov_init. */
898
899static void
159b3be1 900create_coverage (void)
ca29da43 901{
c9b9aa64
RH
902 tree gcov_info, gcov_init, body, t;
903 char name_buf[32];
ca29da43 904
6d70e6be 905 no_coverage = 1; /* Disable any further coverage. */
159b3be1 906
cdb23767 907 if (!prg_ctr_mask)
ca29da43 908 return;
159b3be1 909
c9b9aa64 910 t = build_gcov_info ();
ca29da43 911
c9b9aa64 912 gcov_info = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (t));
ca29da43 913 TREE_STATIC (gcov_info) = 1;
c9b9aa64
RH
914 ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
915 DECL_NAME (gcov_info) = get_identifier (name_buf);
916 DECL_INITIAL (gcov_info) = t;
159b3be1 917
ca29da43
NS
918 /* Build structure. */
919 assemble_variable (gcov_info, 0, 0, 0);
920
c9b9aa64
RH
921 /* Build a decl for __gcov_init. */
922 t = build_pointer_type (TREE_TYPE (gcov_info));
923 t = build_function_type_list (void_type_node, t, NULL);
924 t = build_decl (FUNCTION_DECL, get_identifier ("__gcov_init"), t);
925 TREE_PUBLIC (t) = 1;
926 DECL_EXTERNAL (t) = 1;
927 gcov_init = t;
928
929 /* Generate a call to __gcov_init(&gcov_info). */
930 body = NULL;
931 t = build_fold_addr_expr (gcov_info);
932 t = tree_cons (NULL, t, NULL);
933 t = build_function_call_expr (gcov_init, t);
934 append_to_statement_list (t, &body);
935
936 /* Generate a constructor to run it. */
35b6fdcf 937 cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
ca29da43 938}
ca29da43
NS
939\f
940/* Perform file-level initialization. Read in data file, generate name
71c0e7fc 941 of graph file. */
ca29da43
NS
942
943void
159b3be1 944coverage_init (const char *filename)
ca29da43
NS
945{
946 int len = strlen (filename);
947
796621e8 948 /* Name of da file. */
703ad42b 949 da_file_name = xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1);
ca29da43
NS
950 strcpy (da_file_name, filename);
951 strcat (da_file_name, GCOV_DATA_SUFFIX);
159b3be1 952
796621e8 953 /* Name of bbg file. */
703ad42b 954 bbg_file_name = xmalloc (len + strlen (GCOV_NOTE_SUFFIX) + 1);
ca29da43 955 strcpy (bbg_file_name, filename);
160e2e4f 956 strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
796621e8
NS
957
958 read_counts_file ();
ca29da43
NS
959}
960
961/* Performs file-level cleanup. Close graph file, generate coverage
962 variables and constructor. */
963
964void
159b3be1 965coverage_finish (void)
ca29da43
NS
966{
967 create_coverage ();
968 if (bbg_file_opened)
969 {
970 int error = gcov_close ();
159b3be1 971
ca29da43
NS
972 if (error)
973 unlink (bbg_file_name);
dd486eb2
NS
974 if (!local_tick)
975 /* Only remove the da file, if we cannot stamp it. If we can
976 stamp it, libgcov will DTRT. */
ca29da43
NS
977 unlink (da_file_name);
978 }
979}
980
ca29da43 981#include "gt-coverage.h"
This page took 0.719676 seconds and 5 git commands to generate.