]> gcc.gnu.org Git - gcc.git/blame - gcc/coverage.c
* tree-ssa-loop-ivopts.c (iv_value): Avoid invalid sharing on niter.
[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
NS
167 {
168 warning ("`%s' is not a gcov data file", da_file_name);
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
cb83302c
SB
179 warning ("`%s' is version `%.*s', expected version `%.*s'",
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
NS
295 {
296 error (is_error < 0 ? "`%s' has overflowed" : "`%s' is corrupted",
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 {
796621e8
NS
333 warning ("no coverage for function '%s' found.", IDENTIFIER_POINTER
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 {
24a4a033
JH
341 error ("coverage mismatch for function '%s' while reading counter '%s'.",
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 {
349 error ("coverage mismatch for function '%s' while reading counter '%s'.",
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
406 if (no >= fn_n_ctrs[counter] - fn_b_ctrs[counter])
407 abort ();
408 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
6de9cd9a
DN
409 if (!ctr_labels[counter])
410 {
411 ctr_labels[counter] = gen_rtx_SYMBOL_REF (Pmode,
412 ggc_strdup (IDENTIFIER_POINTER (DECL_NAME
413 (tree_ctr_tables[counter]))));
414 SYMBOL_REF_FLAGS (ctr_labels[counter]) = SYMBOL_FLAG_LOCAL;
415 }
9b514d25 416 ref = plus_constant (ctr_labels[counter], gcov_size / BITS_PER_UNIT * no);
cdb23767
NS
417 ref = gen_rtx_MEM (mode, ref);
418 set_mem_alias_set (ref, new_alias_set ());
27ab3e91 419 MEM_NOTRAP_P (ref) = 1;
cdb23767
NS
420
421 return ref;
422}
6de9cd9a
DN
423
424/* Generate a tree to access COUNTER NO. */
425
426tree
427tree_coverage_counter_ref (unsigned counter, unsigned no)
428{
44de5aeb 429 tree domain_type = TYPE_DOMAIN (TREE_TYPE (tree_ctr_tables[counter]));
6de9cd9a
DN
430
431 if (no >= fn_n_ctrs[counter] - fn_b_ctrs[counter])
432 abort ();
433 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
434
435 /* "no" here is an array index, scaled to bytes later. */
3244e67d 436 return build4 (ARRAY_REF, GCOV_TYPE_NODE, tree_ctr_tables[counter],
4a90aeeb 437 fold_convert (domain_type,
7d60be94 438 build_int_cst (NULL_TREE, no)),
3244e67d
RS
439 TYPE_MIN_VALUE (domain_type),
440 size_binop (EXACT_DIV_EXPR, TYPE_SIZE_UNIT (GCOV_TYPE_NODE),
d836edf8 441 size_int (TYPE_ALIGN_UNIT (GCOV_TYPE_NODE))));
6de9cd9a 442}
ca29da43
NS
443\f
444/* Generate a checksum for a string. CHKSUM is the current
71c0e7fc 445 checksum. */
ca29da43
NS
446
447static unsigned
20c361f3 448coverage_checksum_string (unsigned chksum, const char *string)
ca29da43 449{
20c361f3
JH
450 int i;
451 char *dup = NULL;
452
453 /* Look for everything that looks if it were produced by
454 get_file_function_name_long and zero out the second part
455 that may result from flag_random_seed. This is not critical
456 as the checksums are used only for sanity checking. */
457 for (i = 0; string[i]; i++)
ca29da43 458 {
20c361f3
JH
459 if (!strncmp (string + i, "_GLOBAL__", 9))
460 for (i = i + 9; string[i]; i++)
461 if (string[i]=='_')
462 {
463 int y;
464 unsigned seed;
465
466 for (y = 1; y < 9; y++)
467 if (!(string[i + y] >= '0' && string[i + y] <= '9')
468 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
469 break;
470 if (y != 9 || string[i + 9] != '_')
471 continue;
472 for (y = 10; y < 18; y++)
473 if (!(string[i + y] >= '0' && string[i + y] <= '9')
474 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
475 break;
476 if (y != 18)
477 continue;
478 if (!sscanf (string + i + 10, "%X", &seed))
479 abort ();
480 if (seed != crc32_string (0, flag_random_seed))
481 continue;
482 string = dup = xstrdup (string);
483 for (y = 10; y < 18; y++)
484 dup[i + y] = '0';
485 break;
486 }
487 break;
ca29da43 488 }
20c361f3
JH
489
490 chksum = crc32_string (chksum, string);
491 if (dup)
492 free (dup);
159b3be1 493
ca29da43
NS
494 return chksum;
495}
496
497/* Compute checksum for the current function. We generate a CRC32. */
498
499static unsigned
159b3be1 500compute_checksum (void)
ca29da43 501{
a281759f
PB
502 expanded_location xloc
503 = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
504 unsigned chksum = xloc.line;
ca29da43 505
a281759f 506 chksum = coverage_checksum_string (chksum, xloc.file);
20c361f3 507 chksum = coverage_checksum_string
ca29da43
NS
508 (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
509
510 return chksum;
511}
512\f
513/* Begin output to the graph file for the current function.
514 Opens the output file, if not already done. Writes the
6356f892 515 function header, if not already done. Returns nonzero if data
ca29da43
NS
516 should be output. */
517
518int
159b3be1 519coverage_begin_output (void)
ca29da43 520{
6d70e6be
NS
521 if (no_coverage)
522 return 0;
159b3be1 523
ca29da43
NS
524 if (!bbg_function_announced)
525 {
a281759f
PB
526 expanded_location xloc
527 = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
ca29da43 528 unsigned long offset;
159b3be1 529
ca29da43
NS
530 if (!bbg_file_opened)
531 {
532 if (!gcov_open (bbg_file_name, -1))
533 error ("cannot open %s", bbg_file_name);
534 else
535 {
160e2e4f 536 gcov_write_unsigned (GCOV_NOTE_MAGIC);
ca29da43 537 gcov_write_unsigned (GCOV_VERSION);
dd486eb2 538 gcov_write_unsigned (local_tick);
ca29da43
NS
539 }
540 bbg_file_opened = 1;
541 }
159b3be1 542
ca29da43
NS
543 /* Announce function */
544 offset = gcov_write_tag (GCOV_TAG_FUNCTION);
6d70e6be 545 gcov_write_unsigned (current_function_funcdef_no + 1);
796621e8 546 gcov_write_unsigned (compute_checksum ());
ca29da43
NS
547 gcov_write_string (IDENTIFIER_POINTER
548 (DECL_ASSEMBLER_NAME (current_function_decl)));
a281759f
PB
549 gcov_write_string (xloc.file);
550 gcov_write_unsigned (xloc.line);
ca29da43
NS
551 gcov_write_length (offset);
552
553 bbg_function_announced = 1;
554 }
555 return !gcov_is_error ();
556}
557
558/* Finish coverage data for the current function. Verify no output
559 error has occurred. Save function coverage counts. */
560
561void
159b3be1 562coverage_end_function (void)
ca29da43
NS
563{
564 unsigned i;
159b3be1 565
ca29da43 566 if (bbg_file_opened > 1 && gcov_is_error ())
159b3be1 567 {
ca29da43
NS
568 warning ("error writing `%s'", bbg_file_name);
569 bbg_file_opened = -1;
570 }
cdb23767
NS
571
572 if (fn_ctr_mask)
573 {
574 struct function_list *item;
159b3be1 575
cdb23767 576 item = xmalloc (sizeof (struct function_list));
159b3be1 577
cdb23767
NS
578 *functions_tail = item;
579 functions_tail = &item->next;
159b3be1 580
cdb23767 581 item->next = 0;
6d70e6be 582 item->ident = current_function_funcdef_no + 1;
cdb23767
NS
583 item->checksum = compute_checksum ();
584 for (i = 0; i != GCOV_COUNTERS; i++)
585 {
586 item->n_ctrs[i] = fn_n_ctrs[i];
587 prg_n_ctrs[i] += fn_n_ctrs[i];
6d70e6be 588 fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
cdb23767
NS
589 }
590 prg_ctr_mask |= fn_ctr_mask;
591 fn_ctr_mask = 0;
592 }
ca29da43
NS
593 bbg_function_announced = 0;
594}
595
cdb23767 596/* Creates the gcov_fn_info RECORD_TYPE. */
ca29da43 597
ca29da43 598static tree
159b3be1 599build_fn_info_type (unsigned int counters)
ca29da43 600{
ae2bcd98 601 tree type = lang_hooks.types.make_type (RECORD_TYPE);
ca29da43 602 tree field, fields;
cdb23767 603 tree array_type;
159b3be1 604
796621e8 605 /* ident */
9b514d25 606 fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
ca29da43 607
cdb23767 608 /* checksum */
9b514d25 609 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
ca29da43
NS
610 TREE_CHAIN (field) = fields;
611 fields = field;
612
7d60be94 613 array_type = build_int_cst (NULL_TREE, counters - 1);
4a90aeeb 614 array_type = build_index_type (array_type);
cdb23767 615 array_type = build_array_type (unsigned_type_node, array_type);
159b3be1 616
ca29da43 617 /* counters */
cdb23767 618 field = build_decl (FIELD_DECL, NULL_TREE, array_type);
ca29da43
NS
619 TREE_CHAIN (field) = fields;
620 fields = field;
621
cdb23767
NS
622 finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
623
624 return type;
ca29da43
NS
625}
626
cdb23767
NS
627/* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
628 the function being processed and TYPE is the gcov_fn_info
629 RECORD_TYPE. */
630
ca29da43 631static tree
159b3be1 632build_fn_info_value (const struct function_list *function, tree type)
ca29da43 633{
cdb23767
NS
634 tree value = NULL_TREE;
635 tree fields = TYPE_FIELDS (type);
cdb23767
NS
636 unsigned ix;
637 tree array_value = NULL_TREE;
159b3be1 638
796621e8 639 /* ident */
7d60be94
NS
640 value = tree_cons (fields, build_int_cstu (unsigned_intSI_type_node,
641 function->ident), value);
cdb23767 642 fields = TREE_CHAIN (fields);
159b3be1 643
cdb23767 644 /* checksum */
7d60be94
NS
645 value = tree_cons (fields, build_int_cstu (unsigned_intSI_type_node,
646 function->checksum), value);
cdb23767 647 fields = TREE_CHAIN (fields);
159b3be1 648
ca29da43 649 /* counters */
cdb23767
NS
650 for (ix = 0; ix != GCOV_COUNTERS; ix++)
651 if (prg_ctr_mask & (1 << ix))
652 {
7d60be94
NS
653 tree counters = build_int_cstu (unsigned_type_node,
654 function->n_ctrs[ix]);
159b3be1 655
cdb23767
NS
656 array_value = tree_cons (NULL_TREE, counters, array_value);
657 }
159b3be1 658
cdb23767
NS
659 array_value = build_constructor (TREE_TYPE (fields), nreverse (array_value));
660 value = tree_cons (fields, array_value, value);
ca29da43 661
cdb23767 662 value = build_constructor (type, nreverse (value));
159b3be1 663
ca29da43
NS
664 return value;
665}
666
cdb23767
NS
667/* Creates the gcov_ctr_info RECORD_TYPE. */
668
ca29da43 669static tree
159b3be1 670build_ctr_info_type (void)
ca29da43 671{
ae2bcd98 672 tree type = lang_hooks.types.make_type (RECORD_TYPE);
cdb23767 673 tree field, fields = NULL_TREE;
9b514d25 674 tree gcov_ptr_type = build_pointer_type (GCOV_TYPE_NODE);
09780dfb 675 tree gcov_merge_fn_type;
9b514d25 676
cdb23767 677 /* counters */
9b514d25 678 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
ca29da43
NS
679 TREE_CHAIN (field) = fields;
680 fields = field;
681
cdb23767 682 /* values */
9b514d25 683 field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
ca29da43
NS
684 TREE_CHAIN (field) = fields;
685 fields = field;
686
09780dfb
ZD
687 /* merge */
688 gcov_merge_fn_type =
9b514d25
NS
689 build_function_type_list (void_type_node,
690 gcov_ptr_type, unsigned_type_node,
691 NULL_TREE);
09780dfb
ZD
692 field = build_decl (FIELD_DECL, NULL_TREE,
693 build_pointer_type (gcov_merge_fn_type));
694 TREE_CHAIN (field) = fields;
695 fields = field;
696
cdb23767 697 finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
ca29da43 698
cdb23767 699 return type;
ca29da43
NS
700}
701
cdb23767
NS
702/* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
703 the counter being processed and TYPE is the gcov_ctr_info
704 RECORD_TYPE. */
705
ca29da43 706static tree
159b3be1 707build_ctr_info_value (unsigned int counter, tree type)
ca29da43
NS
708{
709 tree value = NULL_TREE;
cdb23767 710 tree fields = TYPE_FIELDS (type);
09780dfb 711 tree fn;
ca29da43 712
cdb23767
NS
713 /* counters */
714 value = tree_cons (fields,
7d60be94
NS
715 build_int_cstu (unsigned_intSI_type_node,
716 prg_n_ctrs[counter]),
ca29da43 717 value);
cdb23767 718 fields = TREE_CHAIN (fields);
ca29da43 719
cdb23767 720 if (prg_n_ctrs[counter])
ca29da43 721 {
6de9cd9a 722 tree array_type;
159b3be1 723
7d60be94
NS
724 array_type = build_int_cstu (unsigned_type_node,
725 prg_n_ctrs[counter] - 1);
4a90aeeb 726 array_type = build_index_type (array_type);
cdb23767
NS
727 array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
728 array_type);
159b3be1 729
6de9cd9a
DN
730 TREE_TYPE (tree_ctr_tables[counter]) = array_type;
731 DECL_SIZE (tree_ctr_tables[counter]) = TYPE_SIZE (array_type);
732 DECL_SIZE_UNIT (tree_ctr_tables[counter]) = TYPE_SIZE_UNIT (array_type);
733 assemble_variable (tree_ctr_tables[counter], 0, 0, 0);
159b3be1 734
cdb23767 735 value = tree_cons (fields,
6de9cd9a
DN
736 build1 (ADDR_EXPR, TREE_TYPE (fields),
737 tree_ctr_tables[counter]),
cdb23767 738 value);
ca29da43
NS
739 }
740 else
cdb23767 741 value = tree_cons (fields, null_pointer_node, value);
09780dfb
ZD
742 fields = TREE_CHAIN (fields);
743
744 fn = build_decl (FUNCTION_DECL,
745 get_identifier (ctr_merge_functions[counter]),
746 TREE_TYPE (TREE_TYPE (fields)));
747 DECL_EXTERNAL (fn) = 1;
748 TREE_PUBLIC (fn) = 1;
749 DECL_ARTIFICIAL (fn) = 1;
750 TREE_NOTHROW (fn) = 1;
751 value = tree_cons (fields,
9b514d25 752 build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
09780dfb 753 value);
ca29da43 754
cdb23767 755 value = build_constructor (type, nreverse (value));
159b3be1 756
ca29da43
NS
757 return value;
758}
759
cdb23767
NS
760/* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
761 CONSTRUCTOR. */
762
ca29da43 763static tree
159b3be1 764build_gcov_info (void)
ca29da43 765{
cdb23767
NS
766 unsigned n_ctr_types, ix;
767 tree type, const_type;
768 tree fn_info_type, fn_info_value = NULL_TREE;
769 tree fn_info_ptr_type;
770 tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
771 tree field, fields = NULL_TREE;
772 tree value = NULL_TREE;
773 tree filename_string;
ca29da43
NS
774 char *filename;
775 int filename_len;
cdb23767
NS
776 unsigned n_fns;
777 const struct function_list *fn;
778 tree string_type;
159b3be1 779
cdb23767
NS
780 /* Count the number of active counters. */
781 for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
782 if (prg_ctr_mask & (1 << ix))
783 n_ctr_types++;
159b3be1 784
ae2bcd98 785 type = lang_hooks.types.make_type (RECORD_TYPE);
cdb23767 786 const_type = build_qualified_type (type, TYPE_QUAL_CONST);
159b3be1 787
cdb23767 788 /* Version ident */
9b514d25 789 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
ca29da43
NS
790 TREE_CHAIN (field) = fields;
791 fields = field;
7d60be94
NS
792 value = tree_cons (field, build_int_cstu (unsigned_intSI_type_node,
793 GCOV_VERSION), value);
159b3be1 794
ca29da43 795 /* next -- NULL */
cdb23767
NS
796 field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
797 TREE_CHAIN (field) = fields;
798 fields = field;
799 value = tree_cons (field, null_pointer_node, value);
159b3be1 800
dd486eb2
NS
801 /* stamp */
802 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
803 TREE_CHAIN (field) = fields;
804 fields = field;
7d60be94
NS
805 value = tree_cons (field, build_int_cstu (unsigned_intSI_type_node,
806 local_tick), value);
dd486eb2 807
ca29da43 808 /* Filename */
cdb23767
NS
809 string_type = build_pointer_type (build_qualified_type (char_type_node,
810 TYPE_QUAL_CONST));
811 field = build_decl (FIELD_DECL, NULL_TREE, string_type);
812 TREE_CHAIN (field) = fields;
813 fields = field;
ca29da43
NS
814 filename = getpwd ();
815 filename = (filename && da_file_name[0] != '/'
816 ? concat (filename, "/", da_file_name, NULL)
817 : da_file_name);
818 filename_len = strlen (filename);
819 filename_string = build_string (filename_len + 1, filename);
820 if (filename != da_file_name)
821 free (filename);
4a90aeeb
NS
822 TREE_TYPE (filename_string) = build_array_type
823 (char_type_node, build_index_type
7d60be94 824 (build_int_cst (NULL_TREE, filename_len)));
cdb23767 825 value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
ca29da43 826 value);
159b3be1 827
cdb23767
NS
828 /* Build the fn_info type and initializer. */
829 fn_info_type = build_fn_info_type (n_ctr_types);
830 fn_info_ptr_type = build_pointer_type (build_qualified_type
831 (fn_info_type, TYPE_QUAL_CONST));
832 for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
833 fn_info_value = tree_cons (NULL_TREE,
834 build_fn_info_value (fn, fn_info_type),
835 fn_info_value);
836 if (n_fns)
ca29da43
NS
837 {
838 tree array_type;
839
7d60be94 840 array_type = build_index_type (build_int_cst (NULL_TREE, n_fns - 1));
cdb23767 841 array_type = build_array_type (fn_info_type, array_type);
159b3be1 842
cdb23767
NS
843 fn_info_value = build_constructor (array_type, nreverse (fn_info_value));
844 fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
ca29da43
NS
845 }
846 else
cdb23767 847 fn_info_value = null_pointer_node;
159b3be1 848
cdb23767
NS
849 /* number of functions */
850 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
851 TREE_CHAIN (field) = fields;
852 fields = field;
853 value = tree_cons (field,
7d60be94 854 build_int_cstu (unsigned_type_node, n_fns),
cdb23767 855 value);
159b3be1 856
cdb23767
NS
857 /* fn_info table */
858 field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type);
859 TREE_CHAIN (field) = fields;
860 fields = field;
861 value = tree_cons (field, fn_info_value, value);
ca29da43 862
cdb23767
NS
863 /* counter_mask */
864 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
865 TREE_CHAIN (field) = fields;
866 fields = field;
867 value = tree_cons (field,
7d60be94 868 build_int_cstu (unsigned_type_node, prg_ctr_mask),
ca29da43 869 value);
159b3be1 870
cdb23767
NS
871 /* counters */
872 ctr_info_type = build_ctr_info_type ();
4a90aeeb 873 ctr_info_ary_type = build_index_type (build_int_cst (NULL_TREE,
7d60be94 874 n_ctr_types));
cdb23767
NS
875 ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
876 for (ix = 0; ix != GCOV_COUNTERS; ix++)
877 if (prg_ctr_mask & (1 << ix))
878 ctr_info_value = tree_cons (NULL_TREE,
879 build_ctr_info_value (ix, ctr_info_type),
880 ctr_info_value);
881 ctr_info_value = build_constructor (ctr_info_ary_type,
882 nreverse (ctr_info_value));
883
884 field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
885 TREE_CHAIN (field) = fields;
886 fields = field;
887 value = tree_cons (field, ctr_info_value, value);
159b3be1 888
cdb23767 889 finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
ca29da43 890
cdb23767 891 value = build_constructor (type, nreverse (value));
159b3be1 892
ca29da43
NS
893 return value;
894}
895
cdb23767 896/* Write out the structure which libgcov uses to locate all the
ca29da43
NS
897 counters. The structures used here must match those defined in
898 gcov-io.h. Write out the constructor to call __gcov_init. */
899
900static void
159b3be1 901create_coverage (void)
ca29da43 902{
c9b9aa64
RH
903 tree gcov_info, gcov_init, body, t;
904 char name_buf[32];
ca29da43 905
6d70e6be 906 no_coverage = 1; /* Disable any further coverage. */
159b3be1 907
cdb23767 908 if (!prg_ctr_mask)
ca29da43 909 return;
159b3be1 910
c9b9aa64 911 t = build_gcov_info ();
ca29da43 912
c9b9aa64 913 gcov_info = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (t));
ca29da43 914 TREE_STATIC (gcov_info) = 1;
c9b9aa64
RH
915 ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
916 DECL_NAME (gcov_info) = get_identifier (name_buf);
917 DECL_INITIAL (gcov_info) = t;
159b3be1 918
ca29da43
NS
919 /* Build structure. */
920 assemble_variable (gcov_info, 0, 0, 0);
921
c9b9aa64
RH
922 /* Build a decl for __gcov_init. */
923 t = build_pointer_type (TREE_TYPE (gcov_info));
924 t = build_function_type_list (void_type_node, t, NULL);
925 t = build_decl (FUNCTION_DECL, get_identifier ("__gcov_init"), t);
926 TREE_PUBLIC (t) = 1;
927 DECL_EXTERNAL (t) = 1;
928 gcov_init = t;
929
930 /* Generate a call to __gcov_init(&gcov_info). */
931 body = NULL;
932 t = build_fold_addr_expr (gcov_info);
933 t = tree_cons (NULL, t, NULL);
934 t = build_function_call_expr (gcov_init, t);
935 append_to_statement_list (t, &body);
936
937 /* Generate a constructor to run it. */
35b6fdcf 938 cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
ca29da43 939}
ca29da43
NS
940\f
941/* Perform file-level initialization. Read in data file, generate name
71c0e7fc 942 of graph file. */
ca29da43
NS
943
944void
159b3be1 945coverage_init (const char *filename)
ca29da43
NS
946{
947 int len = strlen (filename);
948
796621e8 949 /* Name of da file. */
703ad42b 950 da_file_name = xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1);
ca29da43
NS
951 strcpy (da_file_name, filename);
952 strcat (da_file_name, GCOV_DATA_SUFFIX);
159b3be1 953
796621e8 954 /* Name of bbg file. */
703ad42b 955 bbg_file_name = xmalloc (len + strlen (GCOV_NOTE_SUFFIX) + 1);
ca29da43 956 strcpy (bbg_file_name, filename);
160e2e4f 957 strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
796621e8
NS
958
959 read_counts_file ();
ca29da43
NS
960}
961
962/* Performs file-level cleanup. Close graph file, generate coverage
963 variables and constructor. */
964
965void
159b3be1 966coverage_finish (void)
ca29da43
NS
967{
968 create_coverage ();
969 if (bbg_file_opened)
970 {
971 int error = gcov_close ();
159b3be1 972
ca29da43
NS
973 if (error)
974 unlink (bbg_file_name);
dd486eb2
NS
975 if (!local_tick)
976 /* Only remove the da file, if we cannot stamp it. If we can
977 stamp it, libgcov will DTRT. */
ca29da43
NS
978 unlink (da_file_name);
979 }
980}
981
ca29da43 982#include "gt-coverage.h"
This page took 0.535556 seconds and 5 git commands to generate.