usage.adb: Change "pragma inline" to "pragma Inline" in information and error messages
[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 ("%qs 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 ("%qs is version %q.*s, expected version %q.*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 ? "%qs has overflowed" : "%qs 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 %qs 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 %qs while reading counter %qs.",
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 %qs while reading counter %qs.",
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)); /* 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 gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
407 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
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 }
415 ref = plus_constant (ctr_labels[counter], gcov_size / BITS_PER_UNIT * no);
416 ref = gen_rtx_MEM (mode, ref);
417 set_mem_alias_set (ref, new_alias_set ());
418 MEM_NOTRAP_P (ref) = 1;
419
420 return ref;
421 }
422
423 /* Generate a tree to access COUNTER NO. */
424
425 tree
426 tree_coverage_counter_ref (unsigned counter, unsigned no)
427 {
428 tree domain_type = TYPE_DOMAIN (TREE_TYPE (tree_ctr_tables[counter]));
429
430 gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
431 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
432
433 /* "no" here is an array index, scaled to bytes later. */
434 return build4 (ARRAY_REF, GCOV_TYPE_NODE, tree_ctr_tables[counter],
435 fold_convert (domain_type,
436 build_int_cst (NULL_TREE, no)),
437 TYPE_MIN_VALUE (domain_type),
438 size_binop (EXACT_DIV_EXPR, TYPE_SIZE_UNIT (GCOV_TYPE_NODE),
439 size_int (TYPE_ALIGN_UNIT (GCOV_TYPE_NODE))));
440 }
441 \f
442 /* Generate a checksum for a string. CHKSUM is the current
443 checksum. */
444
445 static unsigned
446 coverage_checksum_string (unsigned chksum, const char *string)
447 {
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++)
456 {
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;
463 int scan;
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;
477 scan = sscanf (string + i + 10, "%X", &seed);
478 gcc_assert (scan);
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;
487 }
488
489 chksum = crc32_string (chksum, string);
490 if (dup)
491 free (dup);
492
493 return chksum;
494 }
495
496 /* Compute checksum for the current function. We generate a CRC32. */
497
498 static unsigned
499 compute_checksum (void)
500 {
501 expanded_location xloc
502 = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
503 unsigned chksum = xloc.line;
504
505 chksum = coverage_checksum_string (chksum, xloc.file);
506 chksum = coverage_checksum_string
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
514 function header, if not already done. Returns nonzero if data
515 should be output. */
516
517 int
518 coverage_begin_output (void)
519 {
520 if (no_coverage)
521 return 0;
522
523 if (!bbg_function_announced)
524 {
525 expanded_location xloc
526 = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
527 unsigned long offset;
528
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 {
535 gcov_write_unsigned (GCOV_NOTE_MAGIC);
536 gcov_write_unsigned (GCOV_VERSION);
537 gcov_write_unsigned (local_tick);
538 }
539 bbg_file_opened = 1;
540 }
541
542 /* Announce function */
543 offset = gcov_write_tag (GCOV_TAG_FUNCTION);
544 gcov_write_unsigned (current_function_funcdef_no + 1);
545 gcov_write_unsigned (compute_checksum ());
546 gcov_write_string (IDENTIFIER_POINTER
547 (DECL_ASSEMBLER_NAME (current_function_decl)));
548 gcov_write_string (xloc.file);
549 gcov_write_unsigned (xloc.line);
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
560 void
561 coverage_end_function (void)
562 {
563 unsigned i;
564
565 if (bbg_file_opened > 1 && gcov_is_error ())
566 {
567 warning ("error writing %qs", bbg_file_name);
568 bbg_file_opened = -1;
569 }
570
571 if (fn_ctr_mask)
572 {
573 struct function_list *item;
574
575 item = xmalloc (sizeof (struct function_list));
576
577 *functions_tail = item;
578 functions_tail = &item->next;
579
580 item->next = 0;
581 item->ident = current_function_funcdef_no + 1;
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];
587 fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
588 }
589 prg_ctr_mask |= fn_ctr_mask;
590 fn_ctr_mask = 0;
591 }
592 bbg_function_announced = 0;
593 }
594
595 /* Creates the gcov_fn_info RECORD_TYPE. */
596
597 static tree
598 build_fn_info_type (unsigned int counters)
599 {
600 tree type = lang_hooks.types.make_type (RECORD_TYPE);
601 tree field, fields;
602 tree array_type;
603
604 /* ident */
605 fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
606
607 /* checksum */
608 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
609 TREE_CHAIN (field) = fields;
610 fields = field;
611
612 array_type = build_int_cst (NULL_TREE, counters - 1);
613 array_type = build_index_type (array_type);
614 array_type = build_array_type (unsigned_type_node, array_type);
615
616 /* counters */
617 field = build_decl (FIELD_DECL, NULL_TREE, array_type);
618 TREE_CHAIN (field) = fields;
619 fields = field;
620
621 finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
622
623 return type;
624 }
625
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
630 static tree
631 build_fn_info_value (const struct function_list *function, tree type)
632 {
633 tree value = NULL_TREE;
634 tree fields = TYPE_FIELDS (type);
635 unsigned ix;
636 tree array_value = NULL_TREE;
637
638 /* ident */
639 value = tree_cons (fields, build_int_cstu (unsigned_intSI_type_node,
640 function->ident), value);
641 fields = TREE_CHAIN (fields);
642
643 /* checksum */
644 value = tree_cons (fields, build_int_cstu (unsigned_intSI_type_node,
645 function->checksum), value);
646 fields = TREE_CHAIN (fields);
647
648 /* counters */
649 for (ix = 0; ix != GCOV_COUNTERS; ix++)
650 if (prg_ctr_mask & (1 << ix))
651 {
652 tree counters = build_int_cstu (unsigned_type_node,
653 function->n_ctrs[ix]);
654
655 array_value = tree_cons (NULL_TREE, counters, array_value);
656 }
657
658 array_value = build_constructor (TREE_TYPE (fields), nreverse (array_value));
659 value = tree_cons (fields, array_value, value);
660
661 value = build_constructor (type, nreverse (value));
662
663 return value;
664 }
665
666 /* Creates the gcov_ctr_info RECORD_TYPE. */
667
668 static tree
669 build_ctr_info_type (void)
670 {
671 tree type = lang_hooks.types.make_type (RECORD_TYPE);
672 tree field, fields = NULL_TREE;
673 tree gcov_ptr_type = build_pointer_type (GCOV_TYPE_NODE);
674 tree gcov_merge_fn_type;
675
676 /* counters */
677 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
678 TREE_CHAIN (field) = fields;
679 fields = field;
680
681 /* values */
682 field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
683 TREE_CHAIN (field) = fields;
684 fields = field;
685
686 /* merge */
687 gcov_merge_fn_type =
688 build_function_type_list (void_type_node,
689 gcov_ptr_type, unsigned_type_node,
690 NULL_TREE);
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
696 finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
697
698 return type;
699 }
700
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
705 static tree
706 build_ctr_info_value (unsigned int counter, tree type)
707 {
708 tree value = NULL_TREE;
709 tree fields = TYPE_FIELDS (type);
710 tree fn;
711
712 /* counters */
713 value = tree_cons (fields,
714 build_int_cstu (unsigned_intSI_type_node,
715 prg_n_ctrs[counter]),
716 value);
717 fields = TREE_CHAIN (fields);
718
719 if (prg_n_ctrs[counter])
720 {
721 tree array_type;
722
723 array_type = build_int_cstu (unsigned_type_node,
724 prg_n_ctrs[counter] - 1);
725 array_type = build_index_type (array_type);
726 array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
727 array_type);
728
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);
733
734 value = tree_cons (fields,
735 build1 (ADDR_EXPR, TREE_TYPE (fields),
736 tree_ctr_tables[counter]),
737 value);
738 }
739 else
740 value = tree_cons (fields, null_pointer_node, value);
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,
751 build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
752 value);
753
754 value = build_constructor (type, nreverse (value));
755
756 return value;
757 }
758
759 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
760 CONSTRUCTOR. */
761
762 static tree
763 build_gcov_info (void)
764 {
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;
773 char *filename;
774 int filename_len;
775 unsigned n_fns;
776 const struct function_list *fn;
777 tree string_type;
778
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++;
783
784 type = lang_hooks.types.make_type (RECORD_TYPE);
785 const_type = build_qualified_type (type, TYPE_QUAL_CONST);
786
787 /* Version ident */
788 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
789 TREE_CHAIN (field) = fields;
790 fields = field;
791 value = tree_cons (field, build_int_cstu (unsigned_intSI_type_node,
792 GCOV_VERSION), value);
793
794 /* next -- NULL */
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);
799
800 /* stamp */
801 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
802 TREE_CHAIN (field) = fields;
803 fields = field;
804 value = tree_cons (field, build_int_cstu (unsigned_intSI_type_node,
805 local_tick), value);
806
807 /* Filename */
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;
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);
821 TREE_TYPE (filename_string) = build_array_type
822 (char_type_node, build_index_type
823 (build_int_cst (NULL_TREE, filename_len)));
824 value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
825 value);
826
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)
836 {
837 tree array_type;
838
839 array_type = build_index_type (build_int_cst (NULL_TREE, n_fns - 1));
840 array_type = build_array_type (fn_info_type, array_type);
841
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);
844 }
845 else
846 fn_info_value = null_pointer_node;
847
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,
853 build_int_cstu (unsigned_type_node, n_fns),
854 value);
855
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);
861
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,
867 build_int_cstu (unsigned_type_node, prg_ctr_mask),
868 value);
869
870 /* counters */
871 ctr_info_type = build_ctr_info_type ();
872 ctr_info_ary_type = build_index_type (build_int_cst (NULL_TREE,
873 n_ctr_types));
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);
887
888 finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
889
890 value = build_constructor (type, nreverse (value));
891
892 return value;
893 }
894
895 /* Write out the structure which libgcov uses to locate all the
896 counters. The structures used here must match those defined in
897 gcov-io.h. Write out the constructor to call __gcov_init. */
898
899 static void
900 create_coverage (void)
901 {
902 tree gcov_info, gcov_init, body, t;
903 char name_buf[32];
904
905 no_coverage = 1; /* Disable any further coverage. */
906
907 if (!prg_ctr_mask)
908 return;
909
910 t = build_gcov_info ();
911
912 gcov_info = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (t));
913 TREE_STATIC (gcov_info) = 1;
914 ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
915 DECL_NAME (gcov_info) = get_identifier (name_buf);
916 DECL_INITIAL (gcov_info) = t;
917
918 /* Build structure. */
919 assemble_variable (gcov_info, 0, 0, 0);
920
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. */
937 cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
938 }
939 \f
940 /* Perform file-level initialization. Read in data file, generate name
941 of graph file. */
942
943 void
944 coverage_init (const char *filename)
945 {
946 int len = strlen (filename);
947
948 /* Name of da file. */
949 da_file_name = xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1);
950 strcpy (da_file_name, filename);
951 strcat (da_file_name, GCOV_DATA_SUFFIX);
952
953 /* Name of bbg file. */
954 bbg_file_name = xmalloc (len + strlen (GCOV_NOTE_SUFFIX) + 1);
955 strcpy (bbg_file_name, filename);
956 strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
957
958 read_counts_file ();
959 }
960
961 /* Performs file-level cleanup. Close graph file, generate coverage
962 variables and constructor. */
963
964 void
965 coverage_finish (void)
966 {
967 create_coverage ();
968 if (bbg_file_opened)
969 {
970 int error = gcov_close ();
971
972 if (error)
973 unlink (bbg_file_name);
974 if (!local_tick)
975 /* Only remove the da file, if we cannot stamp it. If we can
976 stamp it, libgcov will DTRT. */
977 unlink (da_file_name);
978 }
979 }
980
981 #include "gt-coverage.h"