tree.h (build_int_cst): New.
[gcc.git] / gcc / coverage.c
1 /* Read and write coverage files, and associated functionality.
2 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
3 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
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
9 This file is part of GCC.
10
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 2, or (at your option) any later
14 version.
15
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING. If not, write to the Free
23 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
24 02111-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"
42 #include "coverage.h"
43 #include "langhooks.h"
44 #include "hashtab.h"
45 #include "tree-iterator.h"
46 #include "cgraph.h"
47
48 #include "gcov-io.c"
49
50 struct function_list
51 {
52 struct function_list *next; /* next function */
53 unsigned ident; /* function ident */
54 unsigned checksum; /* function checksum */
55 unsigned n_ctrs[GCOV_COUNTERS];/* number of counters. */
56 };
57
58 /* Counts information for a function. */
59 typedef struct counts_entry
60 {
61 /* We hash by */
62 unsigned ident;
63 unsigned ctr;
64
65 /* Store */
66 unsigned checksum;
67 gcov_type *counts;
68 struct gcov_ctr_summary summary;
69
70 /* Workspace */
71 struct counts_entry *chain;
72
73 } counts_entry_t;
74
75 static struct function_list *functions_head = 0;
76 static struct function_list **functions_tail = &functions_head;
77 static unsigned no_coverage = 0;
78
79 /* Cumulative counter information for whole program. */
80 static unsigned prg_ctr_mask; /* Mask of counter types generated. */
81 static unsigned prg_n_ctrs[GCOV_COUNTERS]; /* Total counters allocated. */
82
83 /* Counter information for current function. */
84 static unsigned fn_ctr_mask; /* Mask of counters used. */
85 static unsigned fn_n_ctrs[GCOV_COUNTERS]; /* Counters allocated. */
86 static unsigned fn_b_ctrs[GCOV_COUNTERS]; /* Allocation base. */
87
88 /* Name of the output file for coverage output file. */
89 static char *bbg_file_name;
90 static unsigned bbg_file_opened;
91 static int bbg_function_announced;
92
93 /* Name of the count data file. */
94 static char *da_file_name;
95
96 /* Hash table of count data. */
97 static htab_t counts_hash = NULL;
98
99 /* Trees representing the counter table arrays. */
100 static 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. */
104 static GTY(()) rtx ctr_labels[GCOV_COUNTERS];
105
106 /* The names of merge functions for counters. */
107 static const char *const ctr_merge_functions[GCOV_COUNTERS] = GCOV_MERGE_FUNCTIONS;
108 static const char *const ctr_names[GCOV_COUNTERS] = GCOV_COUNTER_NAMES;
109
110 /* Forward declarations. */
111 static hashval_t htab_counts_entry_hash (const void *);
112 static int htab_counts_entry_eq (const void *, const void *);
113 static void htab_counts_entry_del (void *);
114 static void read_counts_file (void);
115 static unsigned compute_checksum (void);
116 static unsigned coverage_checksum_string (unsigned, const char *);
117 static tree build_fn_info_type (unsigned);
118 static tree build_fn_info_value (const struct function_list *, tree);
119 static tree build_ctr_info_type (void);
120 static tree build_ctr_info_value (unsigned, tree);
121 static tree build_gcov_info (void);
122 static void create_coverage (void);
123
124 \f
125 static hashval_t
126 htab_counts_entry_hash (const void *of)
127 {
128 const counts_entry_t *entry = of;
129
130 return entry->ident * GCOV_COUNTERS + entry->ctr;
131 }
132
133 static int
134 htab_counts_entry_eq (const void *of1, const void *of2)
135 {
136 const counts_entry_t *entry1 = of1;
137 const counts_entry_t *entry2 = of2;
138
139 return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
140 }
141
142 static void
143 htab_counts_entry_del (void *of)
144 {
145 counts_entry_t *entry = of;
146
147 free (entry->counts);
148 free (entry);
149 }
150
151 /* Read in the counts file, if available. */
152
153 static void
154 read_counts_file (void)
155 {
156 gcov_unsigned_t fn_ident = 0;
157 gcov_unsigned_t checksum = -1;
158 counts_entry_t *summaried = NULL;
159 unsigned seen_summary = 0;
160 gcov_unsigned_t tag;
161 int is_error = 0;
162
163 if (!gcov_open (da_file_name, 1))
164 return;
165
166 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
167 {
168 warning ("`%s' is not a gcov data file", da_file_name);
169 gcov_close ();
170 return;
171 }
172 else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
173 {
174 char v[4], e[4];
175
176 GCOV_UNSIGNED2STRING (v, tag);
177 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
178
179 warning ("`%s' is version `%.*s', expected version `%.*s'",
180 da_file_name, 4, v, 4, e);
181 gcov_close ();
182 return;
183 }
184
185 /* Read and discard the stamp. */
186 gcov_read_unsigned ();
187
188 counts_hash = htab_create (10,
189 htab_counts_entry_hash, htab_counts_entry_eq,
190 htab_counts_entry_del);
191 while ((tag = gcov_read_unsigned ()))
192 {
193 gcov_unsigned_t length;
194 gcov_position_t offset;
195
196 length = gcov_read_unsigned ();
197 offset = gcov_position ();
198 if (tag == GCOV_TAG_FUNCTION)
199 {
200 fn_ident = gcov_read_unsigned ();
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;
208
209 for (entry = summaried; entry; entry = chain)
210 {
211 chain = entry->chain;
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;
222
223 gcov_read_summary (&summary);
224 seen_summary = 1;
225 for (entry = summaried; entry; entry = entry->chain)
226 {
227 struct gcov_ctr_summary *csum = &summary.ctrs[entry->ctr];
228
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;
234 }
235 }
236 else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
237 {
238 counts_entry_t **slot, *entry, elt;
239 unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
240 unsigned ix;
241
242 elt.ident = fn_ident;
243 elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
244
245 slot = (counts_entry_t **) htab_find_slot
246 (counts_hash, &elt, INSERT);
247 entry = *slot;
248 if (!entry)
249 {
250 *slot = entry = xcalloc (1, sizeof (counts_entry_t));
251 entry->ident = elt.ident;
252 entry->ctr = elt.ctr;
253 entry->checksum = checksum;
254 entry->summary.num = n_counts;
255 entry->counts = xcalloc (n_counts, sizeof (gcov_type));
256 }
257 else if (entry->checksum != checksum)
258 {
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);
270 htab_delete (counts_hash);
271 break;
272 }
273 else if (elt.ctr >= GCOV_COUNTERS_SUMMABLE)
274 {
275 error ("cannot merge separate %s counters for function %u",
276 ctr_names[elt.ctr], fn_ident);
277 goto skip_merge;
278 }
279
280 if (elt.ctr < GCOV_COUNTERS_SUMMABLE
281 /* This should always be true for a just allocated entry,
282 and always false for an existing one. Check this way, in
283 case the gcov file is corrupt. */
284 && (!entry->chain || summaried != entry))
285 {
286 entry->chain = summaried;
287 summaried = entry;
288 }
289 for (ix = 0; ix != n_counts; ix++)
290 entry->counts[ix] += gcov_read_counter ();
291 skip_merge:;
292 }
293 gcov_sync (offset, length);
294 if ((is_error = gcov_is_error ()))
295 {
296 error (is_error < 0 ? "`%s' has overflowed" : "`%s' is corrupted",
297 da_file_name);
298 htab_delete (counts_hash);
299 break;
300 }
301 }
302
303 gcov_close ();
304 }
305
306 /* Returns the counters for a particular tag. */
307
308 gcov_type *
309 get_coverage_counts (unsigned counter, unsigned expected,
310 const struct gcov_ctr_summary **summary)
311 {
312 counts_entry_t *entry, elt;
313 gcov_unsigned_t checksum = -1;
314
315 /* No hash table, no counts. */
316 if (!counts_hash)
317 {
318 static int warned = 0;
319
320 if (!warned++)
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"),
324 da_file_name);
325 return NULL;
326 }
327
328 elt.ident = current_function_funcdef_no + 1;
329 elt.ctr = counter;
330 entry = htab_find (counts_hash, &elt);
331 if (!entry)
332 {
333 warning ("no coverage for function '%s' found.", IDENTIFIER_POINTER
334 (DECL_ASSEMBLER_NAME (current_function_decl)));
335 return 0;
336 }
337
338 checksum = compute_checksum ();
339 if (entry->checksum != checksum)
340 {
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;
354 }
355
356 if (summary)
357 *summary = &entry->summary;
358
359 return entry->counts;
360 }
361
362 /* Allocate NUM counters of type COUNTER. Returns nonzero if the
363 allocation succeeded. */
364
365 int
366 coverage_counter_alloc (unsigned counter, unsigned num)
367 {
368 if (no_coverage)
369 return 0;
370
371 if (!num)
372 return 1;
373
374 if (!tree_ctr_tables[counter])
375 {
376 /* Generate and save a copy of this so it can be shared. */
377 /* We don't know the size yet; make it big enough that nobody
378 will make any clever transformation on it. */
379 char buf[20];
380 tree domain_tree
381 = build_index_type (build_int_cst (NULL_TREE, 1000, 0)); /* replaced later */
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;
387 ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
388 DECL_NAME (tree_ctr_tables[counter]) = get_identifier (buf);
389 DECL_ALIGN (tree_ctr_tables[counter]) = TYPE_ALIGN (GCOV_TYPE_NODE);
390 }
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 }
396
397 /* Generate a MEM rtl to access COUNTER NO. */
398
399 rtx
400 rtl_coverage_counter_ref (unsigned counter, unsigned no)
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];
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 }
416 ref = plus_constant (ctr_labels[counter], gcov_size / BITS_PER_UNIT * no);
417 ref = gen_rtx_MEM (mode, ref);
418 set_mem_alias_set (ref, new_alias_set ());
419 MEM_NOTRAP_P (ref) = 1;
420
421 return ref;
422 }
423
424 /* Generate a tree to access COUNTER NO. */
425
426 tree
427 tree_coverage_counter_ref (unsigned counter, unsigned no)
428 {
429 tree domain_type = TYPE_DOMAIN (TREE_TYPE (tree_ctr_tables[counter]));
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. */
436 return build4 (ARRAY_REF, GCOV_TYPE_NODE, tree_ctr_tables[counter],
437 fold_convert (domain_type,
438 build_int_cst (NULL_TREE, no, 0)),
439 TYPE_MIN_VALUE (domain_type),
440 size_binop (EXACT_DIV_EXPR, TYPE_SIZE_UNIT (GCOV_TYPE_NODE),
441 size_int (TYPE_ALIGN_UNIT (GCOV_TYPE_NODE))));
442 }
443 \f
444 /* Generate a checksum for a string. CHKSUM is the current
445 checksum. */
446
447 static unsigned
448 coverage_checksum_string (unsigned chksum, const char *string)
449 {
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++)
458 {
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;
488 }
489
490 chksum = crc32_string (chksum, string);
491 if (dup)
492 free (dup);
493
494 return chksum;
495 }
496
497 /* Compute checksum for the current function. We generate a CRC32. */
498
499 static unsigned
500 compute_checksum (void)
501 {
502 expanded_location xloc
503 = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
504 unsigned chksum = xloc.line;
505
506 chksum = coverage_checksum_string (chksum, xloc.file);
507 chksum = coverage_checksum_string
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
515 function header, if not already done. Returns nonzero if data
516 should be output. */
517
518 int
519 coverage_begin_output (void)
520 {
521 if (no_coverage)
522 return 0;
523
524 if (!bbg_function_announced)
525 {
526 expanded_location xloc
527 = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
528 unsigned long offset;
529
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 {
536 gcov_write_unsigned (GCOV_NOTE_MAGIC);
537 gcov_write_unsigned (GCOV_VERSION);
538 gcov_write_unsigned (local_tick);
539 }
540 bbg_file_opened = 1;
541 }
542
543 /* Announce function */
544 offset = gcov_write_tag (GCOV_TAG_FUNCTION);
545 gcov_write_unsigned (current_function_funcdef_no + 1);
546 gcov_write_unsigned (compute_checksum ());
547 gcov_write_string (IDENTIFIER_POINTER
548 (DECL_ASSEMBLER_NAME (current_function_decl)));
549 gcov_write_string (xloc.file);
550 gcov_write_unsigned (xloc.line);
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
561 void
562 coverage_end_function (void)
563 {
564 unsigned i;
565
566 if (bbg_file_opened > 1 && gcov_is_error ())
567 {
568 warning ("error writing `%s'", bbg_file_name);
569 bbg_file_opened = -1;
570 }
571
572 if (fn_ctr_mask)
573 {
574 struct function_list *item;
575
576 item = xmalloc (sizeof (struct function_list));
577
578 *functions_tail = item;
579 functions_tail = &item->next;
580
581 item->next = 0;
582 item->ident = current_function_funcdef_no + 1;
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];
588 fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
589 }
590 prg_ctr_mask |= fn_ctr_mask;
591 fn_ctr_mask = 0;
592 }
593 bbg_function_announced = 0;
594 }
595
596 /* Creates the gcov_fn_info RECORD_TYPE. */
597
598 static tree
599 build_fn_info_type (unsigned int counters)
600 {
601 tree type = lang_hooks.types.make_type (RECORD_TYPE);
602 tree field, fields;
603 tree array_type;
604
605 /* ident */
606 fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
607
608 /* checksum */
609 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
610 TREE_CHAIN (field) = fields;
611 fields = field;
612
613 array_type = build_int_cst (NULL_TREE, counters - 1, 0);
614 array_type = build_index_type (array_type);
615 array_type = build_array_type (unsigned_type_node, array_type);
616
617 /* counters */
618 field = build_decl (FIELD_DECL, NULL_TREE, array_type);
619 TREE_CHAIN (field) = fields;
620 fields = field;
621
622 finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
623
624 return type;
625 }
626
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
631 static tree
632 build_fn_info_value (const struct function_list *function, tree type)
633 {
634 tree value = NULL_TREE;
635 tree fields = TYPE_FIELDS (type);
636 unsigned ix;
637 tree array_value = NULL_TREE;
638
639 /* ident */
640 value = tree_cons (fields, build_int_cst (unsigned_intSI_type_node,
641 function->ident, 0), value);
642 fields = TREE_CHAIN (fields);
643
644 /* checksum */
645 value = tree_cons (fields, build_int_cst (unsigned_intSI_type_node,
646 function->checksum, 0), value);
647 fields = TREE_CHAIN (fields);
648
649 /* counters */
650 for (ix = 0; ix != GCOV_COUNTERS; ix++)
651 if (prg_ctr_mask & (1 << ix))
652 {
653 tree counters = build_int_cst (unsigned_type_node,
654 function->n_ctrs[ix], 0);
655
656 array_value = tree_cons (NULL_TREE, counters, array_value);
657 }
658
659 array_value = build_constructor (TREE_TYPE (fields), nreverse (array_value));
660 value = tree_cons (fields, array_value, value);
661
662 value = build_constructor (type, nreverse (value));
663
664 return value;
665 }
666
667 /* Creates the gcov_ctr_info RECORD_TYPE. */
668
669 static tree
670 build_ctr_info_type (void)
671 {
672 tree type = lang_hooks.types.make_type (RECORD_TYPE);
673 tree field, fields = NULL_TREE;
674 tree gcov_ptr_type = build_pointer_type (GCOV_TYPE_NODE);
675 tree gcov_merge_fn_type;
676
677 /* counters */
678 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
679 TREE_CHAIN (field) = fields;
680 fields = field;
681
682 /* values */
683 field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
684 TREE_CHAIN (field) = fields;
685 fields = field;
686
687 /* merge */
688 gcov_merge_fn_type =
689 build_function_type_list (void_type_node,
690 gcov_ptr_type, unsigned_type_node,
691 NULL_TREE);
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
697 finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
698
699 return type;
700 }
701
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
706 static tree
707 build_ctr_info_value (unsigned int counter, tree type)
708 {
709 tree value = NULL_TREE;
710 tree fields = TYPE_FIELDS (type);
711 tree fn;
712
713 /* counters */
714 value = tree_cons (fields,
715 build_int_cst (unsigned_intSI_type_node,
716 prg_n_ctrs[counter], 0),
717 value);
718 fields = TREE_CHAIN (fields);
719
720 if (prg_n_ctrs[counter])
721 {
722 tree array_type;
723
724 array_type = build_int_cst (unsigned_type_node,
725 prg_n_ctrs[counter] - 1, 0);
726 array_type = build_index_type (array_type);
727 array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
728 array_type);
729
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);
734
735 value = tree_cons (fields,
736 build1 (ADDR_EXPR, TREE_TYPE (fields),
737 tree_ctr_tables[counter]),
738 value);
739 }
740 else
741 value = tree_cons (fields, null_pointer_node, value);
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,
752 build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
753 value);
754
755 value = build_constructor (type, nreverse (value));
756
757 return value;
758 }
759
760 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
761 CONSTRUCTOR. */
762
763 static tree
764 build_gcov_info (void)
765 {
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;
774 char *filename;
775 int filename_len;
776 unsigned n_fns;
777 const struct function_list *fn;
778 tree string_type;
779
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++;
784
785 type = lang_hooks.types.make_type (RECORD_TYPE);
786 const_type = build_qualified_type (type, TYPE_QUAL_CONST);
787
788 /* Version ident */
789 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
790 TREE_CHAIN (field) = fields;
791 fields = field;
792 value = tree_cons (field, build_int_cst (unsigned_intSI_type_node,
793 GCOV_VERSION, 0), value);
794
795 /* next -- NULL */
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);
800
801 /* stamp */
802 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
803 TREE_CHAIN (field) = fields;
804 fields = field;
805 value = tree_cons (field, build_int_cst (unsigned_intSI_type_node,
806 local_tick, 0), value);
807
808 /* Filename */
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;
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);
822 TREE_TYPE (filename_string) = build_array_type
823 (char_type_node, build_index_type
824 (build_int_cst (NULL_TREE, filename_len, 0)));
825 value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
826 value);
827
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)
837 {
838 tree array_type;
839
840 array_type = build_index_type (build_int_cst (NULL_TREE,
841 n_fns - 1, 0));
842 array_type = build_array_type (fn_info_type, array_type);
843
844 fn_info_value = build_constructor (array_type, nreverse (fn_info_value));
845 fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
846 }
847 else
848 fn_info_value = null_pointer_node;
849
850 /* number of functions */
851 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
852 TREE_CHAIN (field) = fields;
853 fields = field;
854 value = tree_cons (field,
855 build_int_cst (unsigned_type_node, n_fns, 0),
856 value);
857
858 /* fn_info table */
859 field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type);
860 TREE_CHAIN (field) = fields;
861 fields = field;
862 value = tree_cons (field, fn_info_value, value);
863
864 /* counter_mask */
865 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
866 TREE_CHAIN (field) = fields;
867 fields = field;
868 value = tree_cons (field,
869 build_int_cst (unsigned_type_node, prg_ctr_mask, 0),
870 value);
871
872 /* counters */
873 ctr_info_type = build_ctr_info_type ();
874 ctr_info_ary_type = build_index_type (build_int_cst (NULL_TREE,
875 n_ctr_types, 0));
876 ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
877 for (ix = 0; ix != GCOV_COUNTERS; ix++)
878 if (prg_ctr_mask & (1 << ix))
879 ctr_info_value = tree_cons (NULL_TREE,
880 build_ctr_info_value (ix, ctr_info_type),
881 ctr_info_value);
882 ctr_info_value = build_constructor (ctr_info_ary_type,
883 nreverse (ctr_info_value));
884
885 field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
886 TREE_CHAIN (field) = fields;
887 fields = field;
888 value = tree_cons (field, ctr_info_value, value);
889
890 finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
891
892 value = build_constructor (type, nreverse (value));
893
894 return value;
895 }
896
897 /* Write out the structure which libgcov uses to locate all the
898 counters. The structures used here must match those defined in
899 gcov-io.h. Write out the constructor to call __gcov_init. */
900
901 static void
902 create_coverage (void)
903 {
904 tree gcov_info, gcov_init, body, t;
905 char name_buf[32];
906
907 no_coverage = 1; /* Disable any further coverage. */
908
909 if (!prg_ctr_mask)
910 return;
911
912 t = build_gcov_info ();
913
914 gcov_info = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (t));
915 TREE_STATIC (gcov_info) = 1;
916 ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
917 DECL_NAME (gcov_info) = get_identifier (name_buf);
918 DECL_INITIAL (gcov_info) = t;
919
920 /* Build structure. */
921 assemble_variable (gcov_info, 0, 0, 0);
922
923 /* Build a decl for __gcov_init. */
924 t = build_pointer_type (TREE_TYPE (gcov_info));
925 t = build_function_type_list (void_type_node, t, NULL);
926 t = build_decl (FUNCTION_DECL, get_identifier ("__gcov_init"), t);
927 TREE_PUBLIC (t) = 1;
928 DECL_EXTERNAL (t) = 1;
929 gcov_init = t;
930
931 /* Generate a call to __gcov_init(&gcov_info). */
932 body = NULL;
933 t = build_fold_addr_expr (gcov_info);
934 t = tree_cons (NULL, t, NULL);
935 t = build_function_call_expr (gcov_init, t);
936 append_to_statement_list (t, &body);
937
938 /* Generate a constructor to run it. */
939 cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
940 }
941 \f
942 /* Perform file-level initialization. Read in data file, generate name
943 of graph file. */
944
945 void
946 coverage_init (const char *filename)
947 {
948 int len = strlen (filename);
949
950 /* Name of da file. */
951 da_file_name = xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1);
952 strcpy (da_file_name, filename);
953 strcat (da_file_name, GCOV_DATA_SUFFIX);
954
955 /* Name of bbg file. */
956 bbg_file_name = xmalloc (len + strlen (GCOV_NOTE_SUFFIX) + 1);
957 strcpy (bbg_file_name, filename);
958 strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
959
960 read_counts_file ();
961 }
962
963 /* Performs file-level cleanup. Close graph file, generate coverage
964 variables and constructor. */
965
966 void
967 coverage_finish (void)
968 {
969 create_coverage ();
970 if (bbg_file_opened)
971 {
972 int error = gcov_close ();
973
974 if (error)
975 unlink (bbg_file_name);
976 if (!local_tick)
977 /* Only remove the da file, if we cannot stamp it. If we can
978 stamp it, libgcov will DTRT. */
979 unlink (da_file_name);
980 }
981 }
982
983 #include "gt-coverage.h"