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