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