coverage.c (get_coverage_counts): Give a different message if flag_guess_branch_prob...
[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 coverage_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 ((flag_guess_branch_prob
320 ? "file %s not found, execution counts estimated"
321 : "file %s not found, execution counts assumed to be zero"),
322 da_file_name);
323 return NULL;
324 }
325
326 elt.ident = current_function_funcdef_no + 1;
327 elt.ctr = counter;
328 entry = htab_find (counts_hash, &elt);
329 if (!entry)
330 {
331 warning ("no coverage for function '%s' found.", IDENTIFIER_POINTER
332 (DECL_ASSEMBLER_NAME (current_function_decl)));
333 return 0;
334 }
335
336 checksum = compute_checksum ();
337 if (entry->checksum != checksum)
338 {
339 error ("coverage mismatch for function '%s' while reading counter '%s'.",
340 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
341 ctr_names[counter]);
342 error ("checksum is %x instead of %x", entry->checksum, checksum);
343 return 0;
344 }
345 else if (entry->summary.num != expected)
346 {
347 error ("coverage mismatch for function '%s' while reading counter '%s'.",
348 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
349 ctr_names[counter]);
350 error ("number of counters is %d instead of %d", entry->summary.num, expected);
351 return 0;
352 }
353
354 if (summary)
355 *summary = &entry->summary;
356
357 return entry->counts;
358 }
359
360 /* Allocate NUM counters of type COUNTER. Returns nonzero if the
361 allocation succeeded. */
362
363 int
364 coverage_counter_alloc (unsigned counter, unsigned num)
365 {
366 if (no_coverage)
367 return 0;
368
369 if (!num)
370 return 1;
371
372 if (!ctr_labels[counter])
373 {
374 /* Generate and save a copy of this so it can be shared. */
375 char buf[20];
376
377 ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
378 ctr_labels[counter] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
379 SYMBOL_REF_FLAGS (ctr_labels[counter]) = SYMBOL_FLAG_LOCAL;
380 }
381 fn_b_ctrs[counter] = fn_n_ctrs[counter];
382 fn_n_ctrs[counter] += num;
383 fn_ctr_mask |= 1 << counter;
384 return 1;
385 }
386
387 /* Generate a MEM rtl to access COUNTER NO. */
388
389 rtx
390 coverage_counter_ref (unsigned counter, unsigned no)
391 {
392 unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
393 enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
394 rtx ref;
395
396 if (no >= fn_n_ctrs[counter] - fn_b_ctrs[counter])
397 abort ();
398 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
399 ref = plus_constant (ctr_labels[counter], gcov_size / BITS_PER_UNIT * no);
400 ref = gen_rtx_MEM (mode, ref);
401 set_mem_alias_set (ref, new_alias_set ());
402
403 return ref;
404 }
405 \f
406 /* Generate a checksum for a string. CHKSUM is the current
407 checksum. */
408
409 static unsigned
410 coverage_checksum_string (unsigned chksum, const char *string)
411 {
412 int i;
413 char *dup = NULL;
414
415 /* Look for everything that looks if it were produced by
416 get_file_function_name_long and zero out the second part
417 that may result from flag_random_seed. This is not critical
418 as the checksums are used only for sanity checking. */
419 for (i = 0; string[i]; i++)
420 {
421 if (!strncmp (string + i, "_GLOBAL__", 9))
422 for (i = i + 9; string[i]; i++)
423 if (string[i]=='_')
424 {
425 int y;
426 unsigned seed;
427
428 for (y = 1; y < 9; y++)
429 if (!(string[i + y] >= '0' && string[i + y] <= '9')
430 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
431 break;
432 if (y != 9 || string[i + 9] != '_')
433 continue;
434 for (y = 10; y < 18; y++)
435 if (!(string[i + y] >= '0' && string[i + y] <= '9')
436 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
437 break;
438 if (y != 18)
439 continue;
440 if (!sscanf (string + i + 10, "%X", &seed))
441 abort ();
442 if (seed != crc32_string (0, flag_random_seed))
443 continue;
444 string = dup = xstrdup (string);
445 for (y = 10; y < 18; y++)
446 dup[i + y] = '0';
447 break;
448 }
449 break;
450 }
451
452 chksum = crc32_string (chksum, string);
453 if (dup)
454 free (dup);
455
456 return chksum;
457 }
458
459 /* Compute checksum for the current function. We generate a CRC32. */
460
461 static unsigned
462 compute_checksum (void)
463 {
464 unsigned chksum = DECL_SOURCE_LINE (current_function_decl);
465
466 chksum = coverage_checksum_string (chksum,
467 DECL_SOURCE_FILE (current_function_decl));
468 chksum = coverage_checksum_string
469 (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
470
471 return chksum;
472 }
473 \f
474 /* Begin output to the graph file for the current function.
475 Opens the output file, if not already done. Writes the
476 function header, if not already done. Returns nonzero if data
477 should be output. */
478
479 int
480 coverage_begin_output (void)
481 {
482 if (no_coverage)
483 return 0;
484
485 if (!bbg_function_announced)
486 {
487 const char *file = DECL_SOURCE_FILE (current_function_decl);
488 unsigned line = DECL_SOURCE_LINE (current_function_decl);
489 unsigned long offset;
490
491 if (!bbg_file_opened)
492 {
493 if (!gcov_open (bbg_file_name, -1))
494 error ("cannot open %s", bbg_file_name);
495 else
496 {
497 gcov_write_unsigned (GCOV_NOTE_MAGIC);
498 gcov_write_unsigned (GCOV_VERSION);
499 gcov_write_unsigned (local_tick);
500 }
501 bbg_file_opened = 1;
502 }
503
504 /* Announce function */
505 offset = gcov_write_tag (GCOV_TAG_FUNCTION);
506 gcov_write_unsigned (current_function_funcdef_no + 1);
507 gcov_write_unsigned (compute_checksum ());
508 gcov_write_string (IDENTIFIER_POINTER
509 (DECL_ASSEMBLER_NAME (current_function_decl)));
510 gcov_write_string (file);
511 gcov_write_unsigned (line);
512 gcov_write_length (offset);
513
514 bbg_function_announced = 1;
515 }
516 return !gcov_is_error ();
517 }
518
519 /* Finish coverage data for the current function. Verify no output
520 error has occurred. Save function coverage counts. */
521
522 void
523 coverage_end_function (void)
524 {
525 unsigned i;
526
527 if (bbg_file_opened > 1 && gcov_is_error ())
528 {
529 warning ("error writing `%s'", bbg_file_name);
530 bbg_file_opened = -1;
531 }
532
533 if (fn_ctr_mask)
534 {
535 struct function_list *item;
536
537 item = xmalloc (sizeof (struct function_list));
538
539 *functions_tail = item;
540 functions_tail = &item->next;
541
542 item->next = 0;
543 item->ident = current_function_funcdef_no + 1;
544 item->checksum = compute_checksum ();
545 for (i = 0; i != GCOV_COUNTERS; i++)
546 {
547 item->n_ctrs[i] = fn_n_ctrs[i];
548 prg_n_ctrs[i] += fn_n_ctrs[i];
549 fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
550 }
551 prg_ctr_mask |= fn_ctr_mask;
552 fn_ctr_mask = 0;
553 }
554 bbg_function_announced = 0;
555 }
556
557 /* Creates the gcov_fn_info RECORD_TYPE. */
558
559 static tree
560 build_fn_info_type (unsigned int counters)
561 {
562 tree type = (*lang_hooks.types.make_type) (RECORD_TYPE);
563 tree field, fields;
564 tree array_type;
565
566 /* ident */
567 fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
568
569 /* checksum */
570 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
571 TREE_CHAIN (field) = fields;
572 fields = field;
573
574 array_type = build_index_type (build_int_2 (counters - 1, 0));
575 array_type = build_array_type (unsigned_type_node, array_type);
576
577 /* counters */
578 field = build_decl (FIELD_DECL, NULL_TREE, array_type);
579 TREE_CHAIN (field) = fields;
580 fields = field;
581
582 finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
583
584 return type;
585 }
586
587 /* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
588 the function being processed and TYPE is the gcov_fn_info
589 RECORD_TYPE. */
590
591 static tree
592 build_fn_info_value (const struct function_list *function, tree type)
593 {
594 tree value = NULL_TREE;
595 tree fields = TYPE_FIELDS (type);
596 unsigned ix;
597 tree array_value = NULL_TREE;
598
599 /* ident */
600 value = tree_cons (fields,
601 convert (unsigned_intSI_type_node,
602 build_int_2 (function->ident, 0)),
603 value);
604 fields = TREE_CHAIN (fields);
605
606 /* checksum */
607 value = tree_cons (fields,
608 convert (unsigned_intSI_type_node,
609 build_int_2 (function->checksum, 0)),
610 value);
611 fields = TREE_CHAIN (fields);
612
613 /* counters */
614 for (ix = 0; ix != GCOV_COUNTERS; ix++)
615 if (prg_ctr_mask & (1 << ix))
616 {
617 tree counters = convert (unsigned_type_node,
618 build_int_2 (function->n_ctrs[ix], 0));
619
620 array_value = tree_cons (NULL_TREE, counters, array_value);
621 }
622
623 array_value = build_constructor (TREE_TYPE (fields), nreverse (array_value));
624 value = tree_cons (fields, array_value, value);
625
626 value = build_constructor (type, nreverse (value));
627
628 return value;
629 }
630
631 /* Creates the gcov_ctr_info RECORD_TYPE. */
632
633 static tree
634 build_ctr_info_type (void)
635 {
636 tree type = (*lang_hooks.types.make_type) (RECORD_TYPE);
637 tree field, fields = NULL_TREE;
638 tree gcov_ptr_type = build_pointer_type (GCOV_TYPE_NODE);
639 tree gcov_merge_fn_type;
640
641 /* counters */
642 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
643 TREE_CHAIN (field) = fields;
644 fields = field;
645
646 /* values */
647 field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
648 TREE_CHAIN (field) = fields;
649 fields = field;
650
651 /* merge */
652 gcov_merge_fn_type =
653 build_function_type_list (void_type_node,
654 gcov_ptr_type, unsigned_type_node,
655 NULL_TREE);
656 field = build_decl (FIELD_DECL, NULL_TREE,
657 build_pointer_type (gcov_merge_fn_type));
658 TREE_CHAIN (field) = fields;
659 fields = field;
660
661 finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
662
663 return type;
664 }
665
666 /* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
667 the counter being processed and TYPE is the gcov_ctr_info
668 RECORD_TYPE. */
669
670 static tree
671 build_ctr_info_value (unsigned int counter, tree type)
672 {
673 tree value = NULL_TREE;
674 tree fields = TYPE_FIELDS (type);
675 tree fn;
676
677 /* counters */
678 value = tree_cons (fields,
679 convert (unsigned_intSI_type_node,
680 build_int_2 (prg_n_ctrs[counter], 0)),
681 value);
682 fields = TREE_CHAIN (fields);
683
684 if (prg_n_ctrs[counter])
685 {
686 tree array_type, array;
687
688 array_type = build_index_type (build_int_2 (prg_n_ctrs[counter] - 1, 0));
689 array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
690 array_type);
691
692 array = build_decl (VAR_DECL, NULL_TREE, array_type);
693 TREE_STATIC (array) = 1;
694 DECL_NAME (array) = get_identifier (XSTR (ctr_labels[counter], 0));
695 assemble_variable (array, 0, 0, 0);
696
697 value = tree_cons (fields,
698 build1 (ADDR_EXPR, TREE_TYPE (fields), array),
699 value);
700 }
701 else
702 value = tree_cons (fields, null_pointer_node, value);
703 fields = TREE_CHAIN (fields);
704
705 fn = build_decl (FUNCTION_DECL,
706 get_identifier (ctr_merge_functions[counter]),
707 TREE_TYPE (TREE_TYPE (fields)));
708 DECL_EXTERNAL (fn) = 1;
709 TREE_PUBLIC (fn) = 1;
710 DECL_ARTIFICIAL (fn) = 1;
711 TREE_NOTHROW (fn) = 1;
712 value = tree_cons (fields,
713 build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
714 value);
715
716 value = build_constructor (type, nreverse (value));
717
718 return value;
719 }
720
721 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
722 CONSTRUCTOR. */
723
724 static tree
725 build_gcov_info (void)
726 {
727 unsigned n_ctr_types, ix;
728 tree type, const_type;
729 tree fn_info_type, fn_info_value = NULL_TREE;
730 tree fn_info_ptr_type;
731 tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
732 tree field, fields = NULL_TREE;
733 tree value = NULL_TREE;
734 tree filename_string;
735 char *filename;
736 int filename_len;
737 unsigned n_fns;
738 const struct function_list *fn;
739 tree string_type;
740
741 /* Count the number of active counters. */
742 for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
743 if (prg_ctr_mask & (1 << ix))
744 n_ctr_types++;
745
746 type = (*lang_hooks.types.make_type) (RECORD_TYPE);
747 const_type = build_qualified_type (type, TYPE_QUAL_CONST);
748
749 /* Version ident */
750 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
751 TREE_CHAIN (field) = fields;
752 fields = field;
753 value = tree_cons (field, convert (unsigned_intSI_type_node,
754 build_int_2 (GCOV_VERSION, 0)),
755 value);
756
757 /* next -- NULL */
758 field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
759 TREE_CHAIN (field) = fields;
760 fields = field;
761 value = tree_cons (field, null_pointer_node, value);
762
763 /* stamp */
764 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
765 TREE_CHAIN (field) = fields;
766 fields = field;
767 value = tree_cons (field, convert (unsigned_intSI_type_node,
768 build_int_2 (local_tick, 0)),
769 value);
770
771 /* Filename */
772 string_type = build_pointer_type (build_qualified_type (char_type_node,
773 TYPE_QUAL_CONST));
774 field = build_decl (FIELD_DECL, NULL_TREE, string_type);
775 TREE_CHAIN (field) = fields;
776 fields = field;
777 filename = getpwd ();
778 filename = (filename && da_file_name[0] != '/'
779 ? concat (filename, "/", da_file_name, NULL)
780 : da_file_name);
781 filename_len = strlen (filename);
782 filename_string = build_string (filename_len + 1, filename);
783 if (filename != da_file_name)
784 free (filename);
785 TREE_TYPE (filename_string) =
786 build_array_type (char_type_node,
787 build_index_type (build_int_2 (filename_len, 0)));
788 value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
789 value);
790
791 /* Build the fn_info type and initializer. */
792 fn_info_type = build_fn_info_type (n_ctr_types);
793 fn_info_ptr_type = build_pointer_type (build_qualified_type
794 (fn_info_type, TYPE_QUAL_CONST));
795 for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
796 fn_info_value = tree_cons (NULL_TREE,
797 build_fn_info_value (fn, fn_info_type),
798 fn_info_value);
799 if (n_fns)
800 {
801 tree array_type;
802
803 array_type = build_index_type (build_int_2 (n_fns - 1, 0));
804 array_type = build_array_type (fn_info_type, array_type);
805
806 fn_info_value = build_constructor (array_type, nreverse (fn_info_value));
807 fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
808 }
809 else
810 fn_info_value = null_pointer_node;
811
812 /* number of functions */
813 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
814 TREE_CHAIN (field) = fields;
815 fields = field;
816 value = tree_cons (field,
817 convert (unsigned_type_node, build_int_2 (n_fns, 0)),
818 value);
819
820 /* fn_info table */
821 field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type);
822 TREE_CHAIN (field) = fields;
823 fields = field;
824 value = tree_cons (field, fn_info_value, value);
825
826 /* counter_mask */
827 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
828 TREE_CHAIN (field) = fields;
829 fields = field;
830 value = tree_cons (field,
831 convert (unsigned_type_node,
832 build_int_2 (prg_ctr_mask, 0)),
833 value);
834
835 /* counters */
836 ctr_info_type = build_ctr_info_type ();
837 ctr_info_ary_type = build_index_type (build_int_2 (n_ctr_types, 0));
838 ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
839 for (ix = 0; ix != GCOV_COUNTERS; ix++)
840 if (prg_ctr_mask & (1 << ix))
841 ctr_info_value = tree_cons (NULL_TREE,
842 build_ctr_info_value (ix, ctr_info_type),
843 ctr_info_value);
844 ctr_info_value = build_constructor (ctr_info_ary_type,
845 nreverse (ctr_info_value));
846
847 field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
848 TREE_CHAIN (field) = fields;
849 fields = field;
850 value = tree_cons (field, ctr_info_value, value);
851
852 finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
853
854 value = build_constructor (type, nreverse (value));
855
856 return value;
857 }
858
859 /* Write out the structure which libgcov uses to locate all the
860 counters. The structures used here must match those defined in
861 gcov-io.h. Write out the constructor to call __gcov_init. */
862
863 static void
864 create_coverage (void)
865 {
866 tree gcov_info, gcov_info_value;
867 char name[20];
868 char *ctor_name;
869 tree ctor;
870 rtx gcov_info_address;
871
872 no_coverage = 1; /* Disable any further coverage. */
873
874 if (!prg_ctr_mask)
875 return;
876
877 gcov_info_value = build_gcov_info ();
878
879 gcov_info = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (gcov_info_value));
880 DECL_INITIAL (gcov_info) = gcov_info_value;
881
882 TREE_STATIC (gcov_info) = 1;
883 ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 0);
884 DECL_NAME (gcov_info) = get_identifier (name);
885
886 /* Build structure. */
887 assemble_variable (gcov_info, 0, 0, 0);
888
889 /* Build the constructor function to invoke __gcov_init. */
890 ctor_name = concat (IDENTIFIER_POINTER (get_file_function_name ('I')),
891 "_GCOV", NULL);
892 ctor = build_decl (FUNCTION_DECL, get_identifier (ctor_name),
893 build_function_type (void_type_node, NULL_TREE));
894 free (ctor_name);
895 DECL_EXTERNAL (ctor) = 0;
896
897 /* It can be a static function as long as collect2 does not have
898 to scan the object file to find its ctor/dtor routine. */
899 TREE_PUBLIC (ctor) = ! targetm.have_ctors_dtors;
900 TREE_USED (ctor) = 1;
901 DECL_RESULT (ctor) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
902 DECL_UNINLINABLE (ctor) = 1;
903
904 ctor = (*lang_hooks.decls.pushdecl) (ctor);
905 rest_of_decl_compilation (ctor, 0, 1, 0);
906 announce_function (ctor);
907 current_function_decl = ctor;
908 make_decl_rtl (ctor, NULL);
909 init_function_start (ctor);
910 expand_function_start (ctor, 0);
911 /* Actually generate the code to call __gcov_init. */
912 gcov_info_address = force_reg (Pmode, XEXP (DECL_RTL (gcov_info), 0));
913 emit_library_call (gcov_init_libfunc, LCT_NORMAL, VOIDmode, 1,
914 gcov_info_address, Pmode);
915
916 expand_function_end ();
917 /* Create a dummy BLOCK. */
918 DECL_INITIAL (ctor) = make_node (BLOCK);
919 TREE_USED (DECL_INITIAL (ctor)) = 1;
920
921 rest_of_compilation (ctor);
922
923 if (! quiet_flag)
924 fflush (asm_out_file);
925 current_function_decl = NULL_TREE;
926
927 if (targetm.have_ctors_dtors)
928 (* targetm.asm_out.constructor) (XEXP (DECL_RTL (ctor), 0),
929 DEFAULT_INIT_PRIORITY);
930 }
931 \f
932 /* Perform file-level initialization. Read in data file, generate name
933 of graph file. */
934
935 void
936 coverage_init (const char *filename)
937 {
938 int len = strlen (filename);
939
940 /* Name of da file. */
941 da_file_name = xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1);
942 strcpy (da_file_name, filename);
943 strcat (da_file_name, GCOV_DATA_SUFFIX);
944
945 /* Name of bbg file. */
946 bbg_file_name = xmalloc (len + strlen (GCOV_NOTE_SUFFIX) + 1);
947 strcpy (bbg_file_name, filename);
948 strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
949
950 read_counts_file ();
951 }
952
953 /* Performs file-level cleanup. Close graph file, generate coverage
954 variables and constructor. */
955
956 void
957 coverage_finish (void)
958 {
959 create_coverage ();
960 if (bbg_file_opened)
961 {
962 int error = gcov_close ();
963
964 if (error)
965 unlink (bbg_file_name);
966 if (!local_tick)
967 /* Only remove the da file, if we cannot stamp it. If we can
968 stamp it, libgcov will DTRT. */
969 unlink (da_file_name);
970 }
971 }
972
973 #include "gt-coverage.h"