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