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