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