00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #define GCOV_LINKAGE
00028
00029 #include "config.h"
00030 #include "system.h"
00031 #include "coretypes.h"
00032 #include "tm.h"
00033 #include "rtl.h"
00034 #include "tree.h"
00035 #include "flags.h"
00036 #include "output.h"
00037 #include "regs.h"
00038 #include "expr.h"
00039 #include "function.h"
00040 #include "toplev.h"
00041 #include "ggc.h"
00042 #include "coverage.h"
00043 #include "langhooks.h"
00044 #include "hashtab.h"
00045 #include "tree-iterator.h"
00046 #include "cgraph.h"
00047
00048 #include "gcov-io.c"
00049
00050 struct function_list
00051 {
00052 struct function_list *next;
00053 unsigned ident;
00054 unsigned checksum;
00055 unsigned n_ctrs[GCOV_COUNTERS];
00056 };
00057
00058
00059 typedef struct counts_entry
00060 {
00061
00062 unsigned ident;
00063 unsigned ctr;
00064
00065
00066 unsigned checksum;
00067 gcov_type *counts;
00068 struct gcov_ctr_summary summary;
00069
00070
00071 struct counts_entry *chain;
00072
00073 } counts_entry_t;
00074
00075 static struct function_list *functions_head = 0;
00076 static struct function_list **functions_tail = &functions_head;
00077 static unsigned no_coverage = 0;
00078
00079
00080 static unsigned prg_ctr_mask;
00081 static unsigned prg_n_ctrs[GCOV_COUNTERS];
00082
00083
00084 static unsigned fn_ctr_mask;
00085 static unsigned fn_n_ctrs[GCOV_COUNTERS];
00086 static unsigned fn_b_ctrs[GCOV_COUNTERS];
00087
00088
00089 static char *bbg_file_name;
00090 static unsigned bbg_file_opened;
00091 static int bbg_function_announced;
00092
00093
00094 static char *da_file_name;
00095
00096
00097 static htab_t counts_hash = NULL;
00098
00099
00100 static GTY(()) tree tree_ctr_tables[GCOV_COUNTERS];
00101
00102
00103
00104 static GTY(()) rtx ctr_labels[GCOV_COUNTERS];
00105
00106
00107 static const char *const ctr_merge_functions[GCOV_COUNTERS] = GCOV_MERGE_FUNCTIONS;
00108 static const char *const ctr_names[GCOV_COUNTERS] = GCOV_COUNTER_NAMES;
00109
00110
00111 static hashval_t htab_counts_entry_hash (const void *);
00112 static int htab_counts_entry_eq (const void *, const void *);
00113 static void htab_counts_entry_del (void *);
00114 static void read_counts_file (void);
00115 static unsigned compute_checksum (void);
00116 static unsigned coverage_checksum_string (unsigned, const char *);
00117 static tree build_fn_info_type (unsigned);
00118 static tree build_fn_info_value (const struct function_list *, tree);
00119 static tree build_ctr_info_type (void);
00120 static tree build_ctr_info_value (unsigned, tree);
00121 static tree build_gcov_info (void);
00122 static void create_coverage (void);
00123
00124
00125 static hashval_t
00126 htab_counts_entry_hash (const void *of)
00127 {
00128 const counts_entry_t *entry = of;
00129
00130 return entry->ident * GCOV_COUNTERS + entry->ctr;
00131 }
00132
00133 static int
00134 htab_counts_entry_eq (const void *of1, const void *of2)
00135 {
00136 const counts_entry_t *entry1 = of1;
00137 const counts_entry_t *entry2 = of2;
00138
00139 return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
00140 }
00141
00142 static void
00143 htab_counts_entry_del (void *of)
00144 {
00145 counts_entry_t *entry = of;
00146
00147 free (entry->counts);
00148 free (entry);
00149 }
00150
00151
00152
00153 static void
00154 read_counts_file (void)
00155 {
00156 gcov_unsigned_t fn_ident = 0;
00157 gcov_unsigned_t checksum = -1;
00158 counts_entry_t *summaried = NULL;
00159 unsigned seen_summary = 0;
00160 gcov_unsigned_t tag;
00161 int is_error = 0;
00162
00163 if (!gcov_open (da_file_name, 1))
00164 return;
00165
00166 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
00167 {
00168 warning ("%qs is not a gcov data file", da_file_name);
00169 gcov_close ();
00170 return;
00171 }
00172 else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
00173 {
00174 char v[4], e[4];
00175
00176 GCOV_UNSIGNED2STRING (v, tag);
00177 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
00178
00179 warning ("%qs is version %q.*s, expected version %q.*s",
00180 da_file_name, 4, v, 4, e);
00181 gcov_close ();
00182 return;
00183 }
00184
00185
00186 gcov_read_unsigned ();
00187
00188 counts_hash = htab_create (10,
00189 htab_counts_entry_hash, htab_counts_entry_eq,
00190 htab_counts_entry_del);
00191 while ((tag = gcov_read_unsigned ()))
00192 {
00193 gcov_unsigned_t length;
00194 gcov_position_t offset;
00195
00196 length = gcov_read_unsigned ();
00197 offset = gcov_position ();
00198 if (tag == GCOV_TAG_FUNCTION)
00199 {
00200 fn_ident = gcov_read_unsigned ();
00201 checksum = gcov_read_unsigned ();
00202 if (seen_summary)
00203 {
00204
00205
00206
00207 counts_entry_t *entry, *chain;
00208
00209 for (entry = summaried; entry; entry = chain)
00210 {
00211 chain = entry->chain;
00212 entry->chain = NULL;
00213 }
00214 summaried = NULL;
00215 seen_summary = 0;
00216 }
00217 }
00218 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
00219 {
00220 counts_entry_t *entry;
00221 struct gcov_summary summary;
00222
00223 gcov_read_summary (&summary);
00224 seen_summary = 1;
00225 for (entry = summaried; entry; entry = entry->chain)
00226 {
00227 struct gcov_ctr_summary *csum = &summary.ctrs[entry->ctr];
00228
00229 entry->summary.runs += csum->runs;
00230 entry->summary.sum_all += csum->sum_all;
00231 if (entry->summary.run_max < csum->run_max)
00232 entry->summary.run_max = csum->run_max;
00233 entry->summary.sum_max += csum->sum_max;
00234 }
00235 }
00236 else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
00237 {
00238 counts_entry_t **slot, *entry, elt;
00239 unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
00240 unsigned ix;
00241
00242 elt.ident = fn_ident;
00243 elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
00244
00245 slot = (counts_entry_t **) htab_find_slot
00246 (counts_hash, &elt, INSERT);
00247 entry = *slot;
00248 if (!entry)
00249 {
00250 *slot = entry = xcalloc (1, sizeof (counts_entry_t));
00251 entry->ident = elt.ident;
00252 entry->ctr = elt.ctr;
00253 entry->checksum = checksum;
00254 entry->summary.num = n_counts;
00255 entry->counts = xcalloc (n_counts, sizeof (gcov_type));
00256 }
00257 else if (entry->checksum != checksum)
00258 {
00259 error ("coverage mismatch for function %u while reading execution counters.",
00260 fn_ident);
00261 error ("checksum is %x instead of %x", entry->checksum, checksum);
00262 htab_delete (counts_hash);
00263 break;
00264 }
00265 else if (entry->summary.num != n_counts)
00266 {
00267 error ("coverage mismatch for function %u while reading execution counters.",
00268 fn_ident);
00269 error ("number of counters is %d instead of %d", entry->summary.num, n_counts);
00270 htab_delete (counts_hash);
00271 break;
00272 }
00273 else if (elt.ctr >= GCOV_COUNTERS_SUMMABLE)
00274 {
00275 error ("cannot merge separate %s counters for function %u",
00276 ctr_names[elt.ctr], fn_ident);
00277 goto skip_merge;
00278 }
00279
00280 if (elt.ctr < GCOV_COUNTERS_SUMMABLE
00281
00282
00283
00284 && (!entry->chain || summaried != entry))
00285 {
00286 entry->chain = summaried;
00287 summaried = entry;
00288 }
00289 for (ix = 0; ix != n_counts; ix++)
00290 entry->counts[ix] += gcov_read_counter ();
00291 skip_merge:;
00292 }
00293 gcov_sync (offset, length);
00294 if ((is_error = gcov_is_error ()))
00295 {
00296 error (is_error < 0 ? "%qs has overflowed" : "%qs is corrupted",
00297 da_file_name);
00298 htab_delete (counts_hash);
00299 break;
00300 }
00301 }
00302
00303 gcov_close ();
00304 }
00305
00306
00307
00308 gcov_type *
00309 get_coverage_counts (unsigned counter, unsigned expected,
00310 const struct gcov_ctr_summary **summary)
00311 {
00312 counts_entry_t *entry, elt;
00313 gcov_unsigned_t checksum = -1;
00314
00315
00316 if (!counts_hash)
00317 {
00318 static int warned = 0;
00319
00320 if (!warned++)
00321 inform ((flag_guess_branch_prob
00322 ? "file %s not found, execution counts estimated"
00323 : "file %s not found, execution counts assumed to be zero"),
00324 da_file_name);
00325 return NULL;
00326 }
00327
00328 elt.ident = current_function_funcdef_no + 1;
00329 elt.ctr = counter;
00330 entry = htab_find (counts_hash, &elt);
00331 if (!entry)
00332 {
00333 warning ("no coverage for function %qs found.", IDENTIFIER_POINTER
00334 (DECL_ASSEMBLER_NAME (current_function_decl)));
00335 return 0;
00336 }
00337
00338 checksum = compute_checksum ();
00339 if (entry->checksum != checksum)
00340 {
00341 error ("coverage mismatch for function %qs while reading counter %qs.",
00342 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
00343 ctr_names[counter]);
00344 error ("checksum is %x instead of %x", entry->checksum, checksum);
00345 return 0;
00346 }
00347 else if (entry->summary.num != expected)
00348 {
00349 error ("coverage mismatch for function %qs while reading counter %qs.",
00350 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
00351 ctr_names[counter]);
00352 error ("number of counters is %d instead of %d", entry->summary.num, expected);
00353 return 0;
00354 }
00355
00356 if (summary)
00357 *summary = &entry->summary;
00358
00359 return entry->counts;
00360 }
00361
00362
00363
00364
00365 int
00366 coverage_counter_alloc (unsigned counter, unsigned num)
00367 {
00368 if (no_coverage)
00369 return 0;
00370
00371 if (!num)
00372 return 1;
00373
00374 if (!tree_ctr_tables[counter])
00375 {
00376
00377
00378
00379 char buf[20];
00380 tree domain_tree
00381 = build_index_type (build_int_cst (NULL_TREE, 1000));
00382 tree gcov_type_array_type
00383 = build_array_type (GCOV_TYPE_NODE, domain_tree);
00384 tree_ctr_tables[counter]
00385 = build_decl (VAR_DECL, NULL_TREE, gcov_type_array_type);
00386 TREE_STATIC (tree_ctr_tables[counter]) = 1;
00387 ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
00388 DECL_NAME (tree_ctr_tables[counter]) = get_identifier (buf);
00389 DECL_ALIGN (tree_ctr_tables[counter]) = TYPE_ALIGN (GCOV_TYPE_NODE);
00390 }
00391 fn_b_ctrs[counter] = fn_n_ctrs[counter];
00392 fn_n_ctrs[counter] += num;
00393 fn_ctr_mask |= 1 << counter;
00394 return 1;
00395 }
00396
00397
00398
00399 rtx
00400 rtl_coverage_counter_ref (unsigned counter, unsigned no)
00401 {
00402 unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
00403 enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
00404 rtx ref;
00405
00406 gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
00407 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
00408 if (!ctr_labels[counter])
00409 {
00410 ctr_labels[counter] = gen_rtx_SYMBOL_REF (Pmode,
00411 ggc_strdup (IDENTIFIER_POINTER (DECL_NAME
00412 (tree_ctr_tables[counter]))));
00413 SYMBOL_REF_FLAGS (ctr_labels[counter]) = SYMBOL_FLAG_LOCAL;
00414 }
00415 ref = plus_constant (ctr_labels[counter], gcov_size / BITS_PER_UNIT * no);
00416 ref = gen_rtx_MEM (mode, ref);
00417 set_mem_alias_set (ref, new_alias_set ());
00418 MEM_NOTRAP_P (ref) = 1;
00419
00420 return ref;
00421 }
00422
00423
00424
00425 tree
00426 tree_coverage_counter_ref (unsigned counter, unsigned no)
00427 {
00428 tree domain_type = TYPE_DOMAIN (TREE_TYPE (tree_ctr_tables[counter]));
00429
00430 gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
00431 no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
00432
00433
00434 return build4 (ARRAY_REF, GCOV_TYPE_NODE, tree_ctr_tables[counter],
00435 fold_convert (domain_type,
00436 build_int_cst (NULL_TREE, no)),
00437 TYPE_MIN_VALUE (domain_type),
00438 size_binop (EXACT_DIV_EXPR, TYPE_SIZE_UNIT (GCOV_TYPE_NODE),
00439 size_int (TYPE_ALIGN_UNIT (GCOV_TYPE_NODE))));
00440 }
00441
00442
00443
00444
00445 static unsigned
00446 coverage_checksum_string (unsigned chksum, const char *string)
00447 {
00448 int i;
00449 char *dup = NULL;
00450
00451
00452
00453
00454
00455 for (i = 0; string[i]; i++)
00456 {
00457 if (!strncmp (string + i, "_GLOBAL__", 9))
00458 for (i = i + 9; string[i]; i++)
00459 if (string[i]=='_')
00460 {
00461 int y;
00462 unsigned seed;
00463 int scan;
00464
00465 for (y = 1; y < 9; y++)
00466 if (!(string[i + y] >= '0' && string[i + y] <= '9')
00467 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
00468 break;
00469 if (y != 9 || string[i + 9] != '_')
00470 continue;
00471 for (y = 10; y < 18; y++)
00472 if (!(string[i + y] >= '0' && string[i + y] <= '9')
00473 && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
00474 break;
00475 if (y != 18)
00476 continue;
00477 scan = sscanf (string + i + 10, "%X", &seed);
00478 gcc_assert (scan);
00479 if (seed != crc32_string (0, flag_random_seed))
00480 continue;
00481 string = dup = xstrdup (string);
00482 for (y = 10; y < 18; y++)
00483 dup[i + y] = '0';
00484 break;
00485 }
00486 break;
00487 }
00488
00489 chksum = crc32_string (chksum, string);
00490 if (dup)
00491 free (dup);
00492
00493 return chksum;
00494 }
00495
00496
00497
00498 static unsigned
00499 compute_checksum (void)
00500 {
00501 expanded_location xloc
00502 = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
00503 unsigned chksum = xloc.line;
00504
00505 chksum = coverage_checksum_string (chksum, xloc.file);
00506 chksum = coverage_checksum_string
00507 (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
00508
00509 return chksum;
00510 }
00511
00512
00513
00514
00515
00516
00517 int
00518 coverage_begin_output (void)
00519 {
00520 if (no_coverage)
00521 return 0;
00522
00523 if (!bbg_function_announced)
00524 {
00525 expanded_location xloc
00526 = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
00527 unsigned long offset;
00528
00529 if (!bbg_file_opened)
00530 {
00531 if (!gcov_open (bbg_file_name, -1))
00532 error ("cannot open %s", bbg_file_name);
00533 else
00534 {
00535 gcov_write_unsigned (GCOV_NOTE_MAGIC);
00536 gcov_write_unsigned (GCOV_VERSION);
00537 gcov_write_unsigned (local_tick);
00538 }
00539 bbg_file_opened = 1;
00540 }
00541
00542
00543 offset = gcov_write_tag (GCOV_TAG_FUNCTION);
00544 gcov_write_unsigned (current_function_funcdef_no + 1);
00545 gcov_write_unsigned (compute_checksum ());
00546 gcov_write_string (IDENTIFIER_POINTER
00547 (DECL_ASSEMBLER_NAME (current_function_decl)));
00548 gcov_write_string (xloc.file);
00549 gcov_write_unsigned (xloc.line);
00550 gcov_write_length (offset);
00551
00552 bbg_function_announced = 1;
00553 }
00554 return !gcov_is_error ();
00555 }
00556
00557
00558
00559
00560 void
00561 coverage_end_function (void)
00562 {
00563 unsigned i;
00564
00565 if (bbg_file_opened > 1 && gcov_is_error ())
00566 {
00567 warning ("error writing %qs", bbg_file_name);
00568 bbg_file_opened = -1;
00569 }
00570
00571 if (fn_ctr_mask)
00572 {
00573 struct function_list *item;
00574
00575 item = xmalloc (sizeof (struct function_list));
00576
00577 *functions_tail = item;
00578 functions_tail = &item->next;
00579
00580 item->next = 0;
00581 item->ident = current_function_funcdef_no + 1;
00582 item->checksum = compute_checksum ();
00583 for (i = 0; i != GCOV_COUNTERS; i++)
00584 {
00585 item->n_ctrs[i] = fn_n_ctrs[i];
00586 prg_n_ctrs[i] += fn_n_ctrs[i];
00587 fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
00588 }
00589 prg_ctr_mask |= fn_ctr_mask;
00590 fn_ctr_mask = 0;
00591 }
00592 bbg_function_announced = 0;
00593 }
00594
00595
00596
00597 static tree
00598 build_fn_info_type (unsigned int counters)
00599 {
00600 tree type = lang_hooks.types.make_type (RECORD_TYPE);
00601 tree field, fields;
00602 tree array_type;
00603
00604
00605 fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
00606
00607
00608 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
00609 TREE_CHAIN (field) = fields;
00610 fields = field;
00611
00612 array_type = build_int_cst (NULL_TREE, counters - 1);
00613 array_type = build_index_type (array_type);
00614 array_type = build_array_type (unsigned_type_node, array_type);
00615
00616
00617 field = build_decl (FIELD_DECL, NULL_TREE, array_type);
00618 TREE_CHAIN (field) = fields;
00619 fields = field;
00620
00621 finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
00622
00623 return type;
00624 }
00625
00626
00627
00628
00629
00630 static tree
00631 build_fn_info_value (const struct function_list *function, tree type)
00632 {
00633 tree value = NULL_TREE;
00634 tree fields = TYPE_FIELDS (type);
00635 unsigned ix;
00636 tree array_value = NULL_TREE;
00637
00638
00639 value = tree_cons (fields, build_int_cstu (unsigned_intSI_type_node,
00640 function->ident), value);
00641 fields = TREE_CHAIN (fields);
00642
00643
00644 value = tree_cons (fields, build_int_cstu (unsigned_intSI_type_node,
00645 function->checksum), value);
00646 fields = TREE_CHAIN (fields);
00647
00648
00649 for (ix = 0; ix != GCOV_COUNTERS; ix++)
00650 if (prg_ctr_mask & (1 << ix))
00651 {
00652 tree counters = build_int_cstu (unsigned_type_node,
00653 function->n_ctrs[ix]);
00654
00655 array_value = tree_cons (NULL_TREE, counters, array_value);
00656 }
00657
00658 array_value = build_constructor (TREE_TYPE (fields), nreverse (array_value));
00659 value = tree_cons (fields, array_value, value);
00660
00661 value = build_constructor (type, nreverse (value));
00662
00663 return value;
00664 }
00665
00666
00667
00668 static tree
00669 build_ctr_info_type (void)
00670 {
00671 tree type = lang_hooks.types.make_type (RECORD_TYPE);
00672 tree field, fields = NULL_TREE;
00673 tree gcov_ptr_type = build_pointer_type (GCOV_TYPE_NODE);
00674 tree gcov_merge_fn_type;
00675
00676
00677 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
00678 TREE_CHAIN (field) = fields;
00679 fields = field;
00680
00681
00682 field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
00683 TREE_CHAIN (field) = fields;
00684 fields = field;
00685
00686
00687 gcov_merge_fn_type =
00688 build_function_type_list (void_type_node,
00689 gcov_ptr_type, unsigned_type_node,
00690 NULL_TREE);
00691 field = build_decl (FIELD_DECL, NULL_TREE,
00692 build_pointer_type (gcov_merge_fn_type));
00693 TREE_CHAIN (field) = fields;
00694 fields = field;
00695
00696 finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
00697
00698 return type;
00699 }
00700
00701
00702
00703
00704
00705 static tree
00706 build_ctr_info_value (unsigned int counter, tree type)
00707 {
00708 tree value = NULL_TREE;
00709 tree fields = TYPE_FIELDS (type);
00710 tree fn;
00711
00712
00713 value = tree_cons (fields,
00714 build_int_cstu (unsigned_intSI_type_node,
00715 prg_n_ctrs[counter]),
00716 value);
00717 fields = TREE_CHAIN (fields);
00718
00719 if (prg_n_ctrs[counter])
00720 {
00721 tree array_type;
00722
00723 array_type = build_int_cstu (unsigned_type_node,
00724 prg_n_ctrs[counter] - 1);
00725 array_type = build_index_type (array_type);
00726 array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
00727 array_type);
00728
00729 TREE_TYPE (tree_ctr_tables[counter]) = array_type;
00730 DECL_SIZE (tree_ctr_tables[counter]) = TYPE_SIZE (array_type);
00731 DECL_SIZE_UNIT (tree_ctr_tables[counter]) = TYPE_SIZE_UNIT (array_type);
00732 assemble_variable (tree_ctr_tables[counter], 0, 0, 0);
00733
00734 value = tree_cons (fields,
00735 build1 (ADDR_EXPR, TREE_TYPE (fields),
00736 tree_ctr_tables[counter]),
00737 value);
00738 }
00739 else
00740 value = tree_cons (fields, null_pointer_node, value);
00741 fields = TREE_CHAIN (fields);
00742
00743 fn = build_decl (FUNCTION_DECL,
00744 get_identifier (ctr_merge_functions[counter]),
00745 TREE_TYPE (TREE_TYPE (fields)));
00746 DECL_EXTERNAL (fn) = 1;
00747 TREE_PUBLIC (fn) = 1;
00748 DECL_ARTIFICIAL (fn) = 1;
00749 TREE_NOTHROW (fn) = 1;
00750 value = tree_cons (fields,
00751 build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
00752 value);
00753
00754 value = build_constructor (type, nreverse (value));
00755
00756 return value;
00757 }
00758
00759
00760
00761
00762 static tree
00763 build_gcov_info (void)
00764 {
00765 unsigned n_ctr_types, ix;
00766 tree type, const_type;
00767 tree fn_info_type, fn_info_value = NULL_TREE;
00768 tree fn_info_ptr_type;
00769 tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
00770 tree field, fields = NULL_TREE;
00771 tree value = NULL_TREE;
00772 tree filename_string;
00773 char *filename;
00774 int filename_len;
00775 unsigned n_fns;
00776 const struct function_list *fn;
00777 tree string_type;
00778
00779
00780 for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
00781 if (prg_ctr_mask & (1 << ix))
00782 n_ctr_types++;
00783
00784 type = lang_hooks.types.make_type (RECORD_TYPE);
00785 const_type = build_qualified_type (type, TYPE_QUAL_CONST);
00786
00787
00788 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
00789 TREE_CHAIN (field) = fields;
00790 fields = field;
00791 value = tree_cons (field, build_int_cstu (unsigned_intSI_type_node,
00792 GCOV_VERSION), value);
00793
00794
00795 field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
00796 TREE_CHAIN (field) = fields;
00797 fields = field;
00798 value = tree_cons (field, null_pointer_node, value);
00799
00800
00801 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
00802 TREE_CHAIN (field) = fields;
00803 fields = field;
00804 value = tree_cons (field, build_int_cstu (unsigned_intSI_type_node,
00805 local_tick), value);
00806
00807
00808 string_type = build_pointer_type (build_qualified_type (char_type_node,
00809 TYPE_QUAL_CONST));
00810 field = build_decl (FIELD_DECL, NULL_TREE, string_type);
00811 TREE_CHAIN (field) = fields;
00812 fields = field;
00813 filename = getpwd ();
00814 filename = (filename && da_file_name[0] != '/'
00815 ? concat (filename, "/", da_file_name, NULL)
00816 : da_file_name);
00817 filename_len = strlen (filename);
00818 filename_string = build_string (filename_len + 1, filename);
00819 if (filename != da_file_name)
00820 free (filename);
00821 TREE_TYPE (filename_string) = build_array_type
00822 (char_type_node, build_index_type
00823 (build_int_cst (NULL_TREE, filename_len)));
00824 value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
00825 value);
00826
00827
00828 fn_info_type = build_fn_info_type (n_ctr_types);
00829 fn_info_ptr_type = build_pointer_type (build_qualified_type
00830 (fn_info_type, TYPE_QUAL_CONST));
00831 for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
00832 fn_info_value = tree_cons (NULL_TREE,
00833 build_fn_info_value (fn, fn_info_type),
00834 fn_info_value);
00835 if (n_fns)
00836 {
00837 tree array_type;
00838
00839 array_type = build_index_type (build_int_cst (NULL_TREE, n_fns - 1));
00840 array_type = build_array_type (fn_info_type, array_type);
00841
00842 fn_info_value = build_constructor (array_type, nreverse (fn_info_value));
00843 fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
00844 }
00845 else
00846 fn_info_value = null_pointer_node;
00847
00848
00849 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
00850 TREE_CHAIN (field) = fields;
00851 fields = field;
00852 value = tree_cons (field,
00853 build_int_cstu (unsigned_type_node, n_fns),
00854 value);
00855
00856
00857 field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type);
00858 TREE_CHAIN (field) = fields;
00859 fields = field;
00860 value = tree_cons (field, fn_info_value, value);
00861
00862
00863 field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
00864 TREE_CHAIN (field) = fields;
00865 fields = field;
00866 value = tree_cons (field,
00867 build_int_cstu (unsigned_type_node, prg_ctr_mask),
00868 value);
00869
00870
00871 ctr_info_type = build_ctr_info_type ();
00872 ctr_info_ary_type = build_index_type (build_int_cst (NULL_TREE,
00873 n_ctr_types));
00874 ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
00875 for (ix = 0; ix != GCOV_COUNTERS; ix++)
00876 if (prg_ctr_mask & (1 << ix))
00877 ctr_info_value = tree_cons (NULL_TREE,
00878 build_ctr_info_value (ix, ctr_info_type),
00879 ctr_info_value);
00880 ctr_info_value = build_constructor (ctr_info_ary_type,
00881 nreverse (ctr_info_value));
00882
00883 field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
00884 TREE_CHAIN (field) = fields;
00885 fields = field;
00886 value = tree_cons (field, ctr_info_value, value);
00887
00888 finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
00889
00890 value = build_constructor (type, nreverse (value));
00891
00892 return value;
00893 }
00894
00895
00896
00897
00898
00899 static void
00900 create_coverage (void)
00901 {
00902 tree gcov_info, gcov_init, body, t;
00903 char name_buf[32];
00904
00905 no_coverage = 1;
00906
00907 if (!prg_ctr_mask)
00908 return;
00909
00910 t = build_gcov_info ();
00911
00912 gcov_info = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (t));
00913 TREE_STATIC (gcov_info) = 1;
00914 ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
00915 DECL_NAME (gcov_info) = get_identifier (name_buf);
00916 DECL_INITIAL (gcov_info) = t;
00917
00918
00919 assemble_variable (gcov_info, 0, 0, 0);
00920
00921
00922 t = build_pointer_type (TREE_TYPE (gcov_info));
00923 t = build_function_type_list (void_type_node, t, NULL);
00924 t = build_decl (FUNCTION_DECL, get_identifier ("__gcov_init"), t);
00925 TREE_PUBLIC (t) = 1;
00926 DECL_EXTERNAL (t) = 1;
00927 gcov_init = t;
00928
00929
00930 body = NULL;
00931 t = build_fold_addr_expr (gcov_info);
00932 t = tree_cons (NULL, t, NULL);
00933 t = build_function_call_expr (gcov_init, t);
00934 append_to_statement_list (t, &body);
00935
00936
00937 cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
00938 }
00939
00940
00941
00942
00943 void
00944 coverage_init (const char *filename)
00945 {
00946 int len = strlen (filename);
00947
00948
00949 da_file_name = xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1);
00950 strcpy (da_file_name, filename);
00951 strcat (da_file_name, GCOV_DATA_SUFFIX);
00952
00953
00954 bbg_file_name = xmalloc (len + strlen (GCOV_NOTE_SUFFIX) + 1);
00955 strcpy (bbg_file_name, filename);
00956 strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
00957
00958 read_counts_file ();
00959 }
00960
00961
00962
00963
00964 void
00965 coverage_finish (void)
00966 {
00967 create_coverage ();
00968 if (bbg_file_opened)
00969 {
00970 int error = gcov_close ();
00971
00972 if (error)
00973 unlink (bbg_file_name);
00974 if (!local_tick)
00975
00976
00977 unlink (da_file_name);
00978 }
00979 }
00980
00981 #include "gt-coverage.h"