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