re PR c++/13407 (Confusing error message from extraneous typename)
[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 "target.h"
43 #include "coverage.h"
44 #include "libfuncs.h"
45 #include "langhooks.h"
46 #include "hashtab.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 /* The names of the counter tables. */
100 static GTY(()) rtx ctr_labels[GCOV_COUNTERS];
101
102 /* The names of merge functions for counters. */
103 static const char *const ctr_merge_functions[GCOV_COUNTERS] = GCOV_MERGE_FUNCTIONS;
104 static const char *const ctr_names[GCOV_COUNTERS] = GCOV_COUNTER_NAMES;
105
106 /* Forward declarations. */
107 static hashval_t htab_counts_entry_hash (const void *);
108 static int htab_counts_entry_eq (const void *, const void *);
109 static void htab_counts_entry_del (void *);
110 static void read_counts_file (void);
111 static unsigned compute_checksum (void);
112 static unsigned checksum_string (unsigned, const char *);
113 static tree build_fn_info_type (unsigned);
114 static tree build_fn_info_value (const struct function_list *, tree);
115 static tree build_ctr_info_type (void);
116 static tree build_ctr_info_value (unsigned, tree);
117 static tree build_gcov_info (void);
118 static void create_coverage (void);
119
120 \f
121 static hashval_t
122 htab_counts_entry_hash (const void *of)
123 {
124 const counts_entry_t *entry = of;
125
126 return entry->ident * GCOV_COUNTERS + entry->ctr;
127 }
128
129 static int
130 htab_counts_entry_eq (const void *of1, const void *of2)
131 {
132 const counts_entry_t *entry1 = of1;
133 const counts_entry_t *entry2 = of2;
134
135 return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
136 }
137
138 static void
139 htab_counts_entry_del (void *of)
140 {
141 counts_entry_t *entry = of;
142
143 free (entry->counts);
144 free (entry);
145 }
146
147 /* Read in the counts file, if available. */
148
149 static void
150 read_counts_file (void)
151 {
152 gcov_unsigned_t fn_ident = 0;
153 gcov_unsigned_t checksum = -1;
154 counts_entry_t *summaried = NULL;
155 unsigned seen_summary = 0;
156 gcov_unsigned_t tag;
157 int is_error = 0;
158
159 if (!gcov_open (da_file_name, 1))
160 return;
161
162 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
163 {
164 warning ("`%s' is not a gcov data file", da_file_name);
165 gcov_close ();
166 return;
167 }
168 else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
169 {
170 char v[4], e[4];
171
172 GCOV_UNSIGNED2STRING (v, tag);
173 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
174
175 warning ("`%s' is version `%.4s', expected version `%.4s'",
176 da_file_name, v, e);
177 gcov_close ();
178 return;
179 }
180
181 /* Read and discard the stamp. */
182 gcov_read_unsigned ();
183
184 counts_hash = htab_create (10,
185 htab_counts_entry_hash, htab_counts_entry_eq,
186 htab_counts_entry_del);
187 while ((tag = gcov_read_unsigned ()))
188 {
189 gcov_unsigned_t length;
190 gcov_position_t offset;
191
192 length = gcov_read_unsigned ();
193 offset = gcov_position ();
194 if (tag == GCOV_TAG_FUNCTION)
195 {
196 fn_ident = gcov_read_unsigned ();
197 checksum = gcov_read_unsigned ();
198 if (seen_summary)
199 {
200 /* We have already seen a summary, this means that this
201 new function begins a new set of program runs. We
202 must unlink the summaried chain. */
203 counts_entry_t *entry, *chain;
204
205 for (entry = summaried; entry; entry = chain)
206 {
207 chain = entry->chain;
208 entry->chain = NULL;
209 }
210 summaried = NULL;
211 seen_summary = 0;
212 }
213 }
214 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
215 {
216 counts_entry_t *entry;
217 struct gcov_summary summary;
218
219 gcov_read_summary (&summary);
220 seen_summary = 1;
221 for (entry = summaried; entry; entry = entry->chain)
222 {
223 struct gcov_ctr_summary *csum = &summary.ctrs[entry->ctr];
224
225 entry->summary.runs += csum->runs;
226 entry->summary.sum_all += csum->sum_all;
227 if (entry->summary.run_max < csum->run_max)
228 entry->summary.run_max = csum->run_max;
229 entry->summary.sum_max += csum->sum_max;
230 }
231 }
232 else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
233 {
234 counts_entry_t **slot, *entry, elt;
235 unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
236 unsigned ix;
237
238 elt.ident = fn_ident;
239 elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
240
241 slot = (counts_entry_t **) htab_find_slot
242 (counts_hash, &elt, INSERT);
243 entry = *slot;
244 if (!entry)
245 {
246 *slot = entry = xcalloc (1, sizeof (counts_entry_t));
247 entry->ident = elt.ident;
248 entry->ctr = elt.ctr;
249 entry->checksum = checksum;
250 entry->summary.num = n_counts;
251 entry->counts = xcalloc (n_counts, sizeof (gcov_type));
252 }
253 else if (entry->checksum != checksum)
254 {
255 error ("coverage mismatch for function %u while reading execution counters.",
256 fn_ident);
257 error ("checksum is %x instead of %x", entry->checksum, checksum);
258 htab_delete (counts_hash);
259 break;
260 }
261 else if (entry->summary.num != n_counts)
262 {
263 error ("coverage mismatch for function %u while reading execution counters.",
264 fn_ident);
265 error ("number of counters is %d instead of %d", entry->summary.num, n_counts);
266 htab_delete (counts_hash);
267 break;
268 }
269 else if (elt.ctr >= GCOV_COUNTERS_SUMMABLE)
270 {
271 error ("cannot merge separate %s counters for function %u",
272 ctr_names[elt.ctr], fn_ident);
273 goto skip_merge;
274 }
275
276 if (elt.ctr < GCOV_COUNTERS_SUMMABLE
277 /* This should always be true for a just allocated entry,
278 and always false for an existing one. Check this way, in
279 case the gcov file is corrupt. */
280 && (!entry->chain || summaried != entry))
281 {
282 entry->chain = summaried;
283 summaried = entry;
284 }
285 for (ix = 0; ix != n_counts; ix++)
286 entry->counts[ix] += gcov_read_counter ();
287 skip_merge:;
288 }
289 gcov_sync (offset, length);
290 if ((is_error = gcov_is_error ()))
291 break;
292 }
293
294 if (!gcov_is_eof ())
295 {
296 error (is_error < 0 ? "`%s' has overflowed" : "`%s' is corrupted",
297 da_file_name);
298 htab_delete (counts_hash);
299 }
300
301 gcov_close ();
302 }
303
304 /* Returns the counters for a particular tag. */
305
306 gcov_type *
307 get_coverage_counts (unsigned counter, unsigned expected,
308 const struct gcov_ctr_summary **summary)
309 {
310 counts_entry_t *entry, elt;
311 gcov_unsigned_t checksum = -1;
312
313 /* No hash table, no counts. */
314 if (!counts_hash)
315 {
316 static int warned = 0;
317
318 if (!warned++)
319 inform ("file %s not found, execution counts assumed to be zero",
320 da_file_name);
321 return NULL;
322 }
323
324 elt.ident = current_function_funcdef_no + 1;
325 elt.ctr = counter;
326 entry = htab_find (counts_hash, &elt);
327 if (!entry)
328 {
329 warning ("no coverage for function '%s' found.", IDENTIFIER_POINTER
330 (DECL_ASSEMBLER_NAME (current_function_decl)));
331 return 0;
332 }
333
334 checksum = compute_checksum ();
335 if (entry->checksum != checksum)
336 {
337 error ("coverage mismatch for function '%s' while reading counter '%s'.",
338 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
339 ctr_names[counter]);
340 error ("checksum is %x instead of %x", entry->checksum, checksum);
341 return 0;
342 }
343 else if (entry->summary.num != expected)
344 {
345 error ("coverage mismatch for function '%s' while reading counter '%s'.",
346 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
347 ctr_names[counter]);
348 error ("number of counters is %d instead of %d", entry->summary.num, expected);
349 return 0;
350 }
351
352 if (summary)
353 *summary = &entry->summary;
354
355 return entry->counts;
356 }
357
358 /* Allocate NUM counters of type COUNTER. Returns nonzero if the
359 allocation succeeded. */
360
361 int
362 coverage_counter_alloc (unsigned counter, unsigned num)
363 {
364 if (no_coverage)
365 return 0;
366
367 if (!num)
368 return 1;
369
370 if (!ctr_labels[counter])
371 {
372 /* Generate and save a copy of this so it can be shared. */
373 char buf[20];
374
375 ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
376 ctr_labels[counter] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
377 SYMBOL_REF_FLAGS (ctr_labels[counter]) = SYMBOL_FLAG_LOCAL;
378 }
379 fn_b_ctrs[counter] = fn_n_ctrs[counter];
380 fn_n_ctrs[counter] += num;
381 fn_ctr_mask |= 1 << counter;
382 return 1;
383 }
384
385 /* Generate a MEM rtl to access COUNTER NO. */
386
387 rtx
388 coverage_counter_ref (unsigned counter, unsigned no)
389 {
390 unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
391 enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
392 rtx ref;
393
394 if (no >= fn_n_ctrs[counter] - fn_b_ctrs[counter])
395 abort ();
396 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
397 ref = plus_constant (ctr_labels[counter], gcov_size / BITS_PER_UNIT * no);
398 ref = gen_rtx_MEM (mode, ref);
399 set_mem_alias_set (ref, new_alias_set ());
400
401 return ref;
402 }
403 \f
404 /* Generate a checksum for a string. CHKSUM is the current
405 checksum. */
406
407 static unsigned
408 checksum_string (unsigned chksum, const char *string)
409 {
410 do
411 {
412 unsigned value = *string << 24;
413 unsigned ix;
414
415 for (ix = 8; ix--; value <<= 1)
416 {
417 unsigned feedback;
418
419 feedback = (value ^ chksum) & 0x80000000 ? 0x04c11db7 : 0;
420 chksum <<= 1;
421 chksum ^= feedback;
422 }
423 }
424 while (*string++);
425
426 return chksum;
427 }
428
429 /* Compute checksum for the current function. We generate a CRC32. */
430
431 static unsigned
432 compute_checksum (void)
433 {
434 unsigned chksum = DECL_SOURCE_LINE (current_function_decl);
435
436 chksum = checksum_string (chksum, DECL_SOURCE_FILE (current_function_decl));
437 chksum = checksum_string
438 (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
439
440 return chksum;
441 }
442 \f
443 /* Begin output to the graph file for the current function.
444 Opens the output file, if not already done. Writes the
445 function header, if not already done. Returns nonzero if data
446 should be output. */
447
448 int
449 coverage_begin_output (void)
450 {
451 if (no_coverage)
452 return 0;
453
454 if (!bbg_function_announced)
455 {
456 const char *file = DECL_SOURCE_FILE (current_function_decl);
457 unsigned line = DECL_SOURCE_LINE (current_function_decl);
458 unsigned long offset;
459
460 if (!bbg_file_opened)
461 {
462 if (!gcov_open (bbg_file_name, -1))
463 error ("cannot open %s", bbg_file_name);
464 else
465 {
466 gcov_write_unsigned (GCOV_NOTE_MAGIC);
467 gcov_write_unsigned (GCOV_VERSION);
468 gcov_write_unsigned (local_tick);
469 }
470 bbg_file_opened = 1;
471 }
472
473 /* Announce function */
474 offset = gcov_write_tag (GCOV_TAG_FUNCTION);
475 gcov_write_unsigned (current_function_funcdef_no + 1);
476 gcov_write_unsigned (compute_checksum ());
477 gcov_write_string (IDENTIFIER_POINTER
478 (DECL_ASSEMBLER_NAME (current_function_decl)));
479 gcov_write_string (file);
480 gcov_write_unsigned (line);
481 gcov_write_length (offset);
482
483 bbg_function_announced = 1;
484 }
485 return !gcov_is_error ();
486 }
487
488 /* Finish coverage data for the current function. Verify no output
489 error has occurred. Save function coverage counts. */
490
491 void
492 coverage_end_function (void)
493 {
494 unsigned i;
495
496 if (bbg_file_opened > 1 && gcov_is_error ())
497 {
498 warning ("error writing `%s'", bbg_file_name);
499 bbg_file_opened = -1;
500 }
501
502 if (fn_ctr_mask)
503 {
504 struct function_list *item;
505
506 item = xmalloc (sizeof (struct function_list));
507
508 *functions_tail = item;
509 functions_tail = &item->next;
510
511 item->next = 0;
512 item->ident = current_function_funcdef_no + 1;
513 item->checksum = compute_checksum ();
514 for (i = 0; i != GCOV_COUNTERS; i++)
515 {
516 item->n_ctrs[i] = fn_n_ctrs[i];
517 prg_n_ctrs[i] += fn_n_ctrs[i];
518 fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
519 }
520 prg_ctr_mask |= fn_ctr_mask;
521 fn_ctr_mask = 0;
522 }
523 bbg_function_announced = 0;
524 }
525
526 /* Creates the gcov_fn_info RECORD_TYPE. */
527
528 static tree
529 build_fn_info_type (unsigned int counters)
530 {
531 tree type = (*lang_hooks.types.make_type) (RECORD_TYPE);
532 tree field, fields;
533 tree array_type;
534
535 /* ident */
536 fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
537
538 /* checksum */
539 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
540 TREE_CHAIN (field) = fields;
541 fields = field;
542
543 array_type = build_index_type (build_int_2 (counters - 1, 0));
544 array_type = build_array_type (unsigned_type_node, array_type);
545
546 /* counters */
547 field = build_decl (FIELD_DECL, NULL_TREE, array_type);
548 TREE_CHAIN (field) = fields;
549 fields = field;
550
551 finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
552
553 return type;
554 }
555
556 /* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
557 the function being processed and TYPE is the gcov_fn_info
558 RECORD_TYPE. */
559
560 static tree
561 build_fn_info_value (const struct function_list *function, tree type)
562 {
563 tree value = NULL_TREE;
564 tree fields = TYPE_FIELDS (type);
565 unsigned ix;
566 tree array_value = NULL_TREE;
567
568 /* ident */
569 value = tree_cons (fields,
570 convert (unsigned_intSI_type_node,
571 build_int_2 (function->ident, 0)),
572 value);
573 fields = TREE_CHAIN (fields);
574
575 /* checksum */
576 value = tree_cons (fields,
577 convert (unsigned_intSI_type_node,
578 build_int_2 (function->checksum, 0)),
579 value);
580 fields = TREE_CHAIN (fields);
581
582 /* counters */
583 for (ix = 0; ix != GCOV_COUNTERS; ix++)
584 if (prg_ctr_mask & (1 << ix))
585 {
586 tree counters = convert (unsigned_type_node,
587 build_int_2 (function->n_ctrs[ix], 0));
588
589 array_value = tree_cons (NULL_TREE, counters, array_value);
590 }
591
592 array_value = build_constructor (TREE_TYPE (fields), nreverse (array_value));
593 value = tree_cons (fields, array_value, value);
594
595 value = build_constructor (type, nreverse (value));
596
597 return value;
598 }
599
600 /* Creates the gcov_ctr_info RECORD_TYPE. */
601
602 static tree
603 build_ctr_info_type (void)
604 {
605 tree type = (*lang_hooks.types.make_type) (RECORD_TYPE);
606 tree field, fields = NULL_TREE;
607 tree gcov_ptr_type = build_pointer_type (GCOV_TYPE_NODE);
608 tree gcov_merge_fn_type;
609
610 /* counters */
611 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
612 TREE_CHAIN (field) = fields;
613 fields = field;
614
615 /* values */
616 field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
617 TREE_CHAIN (field) = fields;
618 fields = field;
619
620 /* merge */
621 gcov_merge_fn_type =
622 build_function_type_list (void_type_node,
623 gcov_ptr_type, unsigned_type_node,
624 NULL_TREE);
625 field = build_decl (FIELD_DECL, NULL_TREE,
626 build_pointer_type (gcov_merge_fn_type));
627 TREE_CHAIN (field) = fields;
628 fields = field;
629
630 finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
631
632 return type;
633 }
634
635 /* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
636 the counter being processed and TYPE is the gcov_ctr_info
637 RECORD_TYPE. */
638
639 static tree
640 build_ctr_info_value (unsigned int counter, tree type)
641 {
642 tree value = NULL_TREE;
643 tree fields = TYPE_FIELDS (type);
644 tree fn;
645
646 /* counters */
647 value = tree_cons (fields,
648 convert (unsigned_intSI_type_node,
649 build_int_2 (prg_n_ctrs[counter], 0)),
650 value);
651 fields = TREE_CHAIN (fields);
652
653 if (prg_n_ctrs[counter])
654 {
655 tree array_type, array;
656
657 array_type = build_index_type (build_int_2 (prg_n_ctrs[counter] - 1, 0));
658 array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
659 array_type);
660
661 array = build_decl (VAR_DECL, NULL_TREE, array_type);
662 TREE_STATIC (array) = 1;
663 DECL_NAME (array) = get_identifier (XSTR (ctr_labels[counter], 0));
664 assemble_variable (array, 0, 0, 0);
665
666 value = tree_cons (fields,
667 build1 (ADDR_EXPR, TREE_TYPE (fields), array),
668 value);
669 }
670 else
671 value = tree_cons (fields, null_pointer_node, value);
672 fields = TREE_CHAIN (fields);
673
674 fn = build_decl (FUNCTION_DECL,
675 get_identifier (ctr_merge_functions[counter]),
676 TREE_TYPE (TREE_TYPE (fields)));
677 DECL_EXTERNAL (fn) = 1;
678 TREE_PUBLIC (fn) = 1;
679 DECL_ARTIFICIAL (fn) = 1;
680 TREE_NOTHROW (fn) = 1;
681 value = tree_cons (fields,
682 build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
683 value);
684
685 value = build_constructor (type, nreverse (value));
686
687 return value;
688 }
689
690 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
691 CONSTRUCTOR. */
692
693 static tree
694 build_gcov_info (void)
695 {
696 unsigned n_ctr_types, ix;
697 tree type, const_type;
698 tree fn_info_type, fn_info_value = NULL_TREE;
699 tree fn_info_ptr_type;
700 tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
701 tree field, fields = NULL_TREE;
702 tree value = NULL_TREE;
703 tree filename_string;
704 char *filename;
705 int filename_len;
706 unsigned n_fns;
707 const struct function_list *fn;
708 tree string_type;
709
710 /* Count the number of active counters. */
711 for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
712 if (prg_ctr_mask & (1 << ix))
713 n_ctr_types++;
714
715 type = (*lang_hooks.types.make_type) (RECORD_TYPE);
716 const_type = build_qualified_type (type, TYPE_QUAL_CONST);
717
718 /* Version ident */
719 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
720 TREE_CHAIN (field) = fields;
721 fields = field;
722 value = tree_cons (field, convert (unsigned_intSI_type_node,
723 build_int_2 (GCOV_VERSION, 0)),
724 value);
725
726 /* next -- NULL */
727 field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
728 TREE_CHAIN (field) = fields;
729 fields = field;
730 value = tree_cons (field, null_pointer_node, value);
731
732 /* stamp */
733 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
734 TREE_CHAIN (field) = fields;
735 fields = field;
736 value = tree_cons (field, convert (unsigned_intSI_type_node,
737 build_int_2 (local_tick, 0)),
738 value);
739
740 /* Filename */
741 string_type = build_pointer_type (build_qualified_type (char_type_node,
742 TYPE_QUAL_CONST));
743 field = build_decl (FIELD_DECL, NULL_TREE, string_type);
744 TREE_CHAIN (field) = fields;
745 fields = field;
746 filename = getpwd ();
747 filename = (filename && da_file_name[0] != '/'
748 ? concat (filename, "/", da_file_name, NULL)
749 : da_file_name);
750 filename_len = strlen (filename);
751 filename_string = build_string (filename_len + 1, filename);
752 if (filename != da_file_name)
753 free (filename);
754 TREE_TYPE (filename_string) =
755 build_array_type (char_type_node,
756 build_index_type (build_int_2 (filename_len, 0)));
757 value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
758 value);
759
760 /* Build the fn_info type and initializer. */
761 fn_info_type = build_fn_info_type (n_ctr_types);
762 fn_info_ptr_type = build_pointer_type (build_qualified_type
763 (fn_info_type, TYPE_QUAL_CONST));
764 for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
765 fn_info_value = tree_cons (NULL_TREE,
766 build_fn_info_value (fn, fn_info_type),
767 fn_info_value);
768 if (n_fns)
769 {
770 tree array_type;
771
772 array_type = build_index_type (build_int_2 (n_fns - 1, 0));
773 array_type = build_array_type (fn_info_type, array_type);
774
775 fn_info_value = build_constructor (array_type, nreverse (fn_info_value));
776 fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
777 }
778 else
779 fn_info_value = null_pointer_node;
780
781 /* number of functions */
782 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
783 TREE_CHAIN (field) = fields;
784 fields = field;
785 value = tree_cons (field,
786 convert (unsigned_type_node, build_int_2 (n_fns, 0)),
787 value);
788
789 /* fn_info table */
790 field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type);
791 TREE_CHAIN (field) = fields;
792 fields = field;
793 value = tree_cons (field, fn_info_value, value);
794
795 /* counter_mask */
796 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
797 TREE_CHAIN (field) = fields;
798 fields = field;
799 value = tree_cons (field,
800 convert (unsigned_type_node,
801 build_int_2 (prg_ctr_mask, 0)),
802 value);
803
804 /* counters */
805 ctr_info_type = build_ctr_info_type ();
806 ctr_info_ary_type = build_index_type (build_int_2 (n_ctr_types, 0));
807 ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
808 for (ix = 0; ix != GCOV_COUNTERS; ix++)
809 if (prg_ctr_mask & (1 << ix))
810 ctr_info_value = tree_cons (NULL_TREE,
811 build_ctr_info_value (ix, ctr_info_type),
812 ctr_info_value);
813 ctr_info_value = build_constructor (ctr_info_ary_type,
814 nreverse (ctr_info_value));
815
816 field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
817 TREE_CHAIN (field) = fields;
818 fields = field;
819 value = tree_cons (field, ctr_info_value, value);
820
821 finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
822
823 value = build_constructor (type, nreverse (value));
824
825 return value;
826 }
827
828 /* Write out the structure which libgcov uses to locate all the
829 counters. The structures used here must match those defined in
830 gcov-io.h. Write out the constructor to call __gcov_init. */
831
832 static void
833 create_coverage (void)
834 {
835 tree gcov_info, gcov_info_value;
836 char name[20];
837 char *ctor_name;
838 tree ctor;
839 rtx gcov_info_address;
840
841 no_coverage = 1; /* Disable any further coverage. */
842
843 if (!prg_ctr_mask)
844 return;
845
846 gcov_info_value = build_gcov_info ();
847
848 gcov_info = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (gcov_info_value));
849 DECL_INITIAL (gcov_info) = gcov_info_value;
850
851 TREE_STATIC (gcov_info) = 1;
852 ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 0);
853 DECL_NAME (gcov_info) = get_identifier (name);
854
855 /* Build structure. */
856 assemble_variable (gcov_info, 0, 0, 0);
857
858 /* Build the constructor function to invoke __gcov_init. */
859 ctor_name = concat (IDENTIFIER_POINTER (get_file_function_name ('I')),
860 "_GCOV", NULL);
861 ctor = build_decl (FUNCTION_DECL, get_identifier (ctor_name),
862 build_function_type (void_type_node, NULL_TREE));
863 free (ctor_name);
864 DECL_EXTERNAL (ctor) = 0;
865
866 /* It can be a static function as long as collect2 does not have
867 to scan the object file to find its ctor/dtor routine. */
868 TREE_PUBLIC (ctor) = ! targetm.have_ctors_dtors;
869 TREE_USED (ctor) = 1;
870 DECL_RESULT (ctor) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
871 DECL_UNINLINABLE (ctor) = 1;
872
873 ctor = (*lang_hooks.decls.pushdecl) (ctor);
874 rest_of_decl_compilation (ctor, 0, 1, 0);
875 announce_function (ctor);
876 current_function_decl = ctor;
877 make_decl_rtl (ctor, NULL);
878 init_function_start (ctor);
879 expand_function_start (ctor, 0);
880 /* Actually generate the code to call __gcov_init. */
881 gcov_info_address = force_reg (Pmode, XEXP (DECL_RTL (gcov_info), 0));
882 emit_library_call (gcov_init_libfunc, LCT_NORMAL, VOIDmode, 1,
883 gcov_info_address, Pmode);
884
885 expand_function_end ();
886 /* Create a dummy BLOCK. */
887 DECL_INITIAL (ctor) = make_node (BLOCK);
888 TREE_USED (DECL_INITIAL (ctor)) = 1;
889
890 rest_of_compilation (ctor);
891
892 if (! quiet_flag)
893 fflush (asm_out_file);
894 current_function_decl = NULL_TREE;
895
896 if (targetm.have_ctors_dtors)
897 (* targetm.asm_out.constructor) (XEXP (DECL_RTL (ctor), 0),
898 DEFAULT_INIT_PRIORITY);
899 }
900 \f
901 /* Perform file-level initialization. Read in data file, generate name
902 of graph file. */
903
904 void
905 coverage_init (const char *filename)
906 {
907 int len = strlen (filename);
908
909 /* Name of da file. */
910 da_file_name = xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1);
911 strcpy (da_file_name, filename);
912 strcat (da_file_name, GCOV_DATA_SUFFIX);
913
914 /* Name of bbg file. */
915 bbg_file_name = xmalloc (len + strlen (GCOV_NOTE_SUFFIX) + 1);
916 strcpy (bbg_file_name, filename);
917 strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
918
919 read_counts_file ();
920 }
921
922 /* Performs file-level cleanup. Close graph file, generate coverage
923 variables and constructor. */
924
925 void
926 coverage_finish (void)
927 {
928 create_coverage ();
929 if (bbg_file_opened)
930 {
931 int error = gcov_close ();
932
933 if (error)
934 unlink (bbg_file_name);
935 if (!local_tick)
936 /* Only remove the da file, if we cannot stamp it. If we can
937 stamp it, libgcov will DTRT. */
938 unlink (da_file_name);
939 }
940 }
941
942 #include "gt-coverage.h"