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