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