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