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