X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcoverage.c;h=b2ac87651d30f28fc0899aa58d5737da97a32620;hb=c2c8f6ebb22e3eec21751544b92b4cad8a4d6c4c;hp=0ba0c110cbb3abc3ee0c83f1e2f722ee3d7679db;hpb=4c36ffe68d981c213d168cf07f42dcc558bc7f1b;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/coverage.c b/gcc/coverage.c index 0ba0c110cbb..b2ac87651d3 100644 --- a/gcc/coverage.c +++ b/gcc/coverage.c @@ -1,6 +1,7 @@ /* Read and write coverage files, and associated functionality. Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999, - 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc. + 2000, 2001, 2003, 2004, 2005, 2007, 2008 Free Software Foundation, + Inc. Contributed by James E. Wilson, UC Berkeley/Cygnus Support; based on some ideas from Dain Samples of UC Berkeley. Further mangling by Bob Manson, Cygnus Support. @@ -10,7 +11,7 @@ This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2, or (at your option) any later +Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY @@ -19,9 +20,8 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301, USA. */ +along with GCC; see the file COPYING3. If not see +. */ #define GCOV_LINKAGE @@ -38,12 +38,14 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "expr.h" #include "function.h" #include "toplev.h" +#include "tm_p.h" #include "ggc.h" #include "coverage.h" #include "langhooks.h" #include "hashtab.h" #include "tree-iterator.h" #include "cgraph.h" +#include "tree-pass.h" #include "gcov-io.c" @@ -140,7 +142,7 @@ get_gcov_unsigned_t (void) static hashval_t htab_counts_entry_hash (const void *of) { - const counts_entry_t *entry = of; + const counts_entry_t *const entry = (const counts_entry_t *) of; return entry->ident * GCOV_COUNTERS + entry->ctr; } @@ -148,8 +150,8 @@ htab_counts_entry_hash (const void *of) static int htab_counts_entry_eq (const void *of1, const void *of2) { - const counts_entry_t *entry1 = of1; - const counts_entry_t *entry2 = of2; + const counts_entry_t *const entry1 = (const counts_entry_t *) of1; + const counts_entry_t *const entry2 = (const counts_entry_t *) of2; return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr; } @@ -157,7 +159,7 @@ htab_counts_entry_eq (const void *of1, const void *of2) static void htab_counts_entry_del (void *of) { - counts_entry_t *entry = of; + counts_entry_t *const entry = (counts_entry_t *) of; free (entry->counts); free (entry); @@ -333,7 +335,7 @@ get_coverage_counts (unsigned counter, unsigned expected, static int warned = 0; if (!warned++) - inform ((flag_guess_branch_prob + inform (input_location, (flag_guess_branch_prob ? "file %s not found, execution counts estimated" : "file %s not found, execution counts assumed to be zero"), da_file_name); @@ -342,30 +344,51 @@ get_coverage_counts (unsigned counter, unsigned expected, elt.ident = current_function_funcdef_no + 1; elt.ctr = counter; - entry = htab_find (counts_hash, &elt); + entry = (counts_entry_t *) htab_find (counts_hash, &elt); if (!entry) { warning (0, "no coverage for function %qs found", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl))); - return 0; + return NULL; } checksum = compute_checksum (); - if (entry->checksum != checksum) - { - error ("coverage mismatch for function %qs while reading counter %qs", - IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)), - ctr_names[counter]); - error ("checksum is %x instead of %x", entry->checksum, checksum); - return 0; - } - else if (entry->summary.num != expected) + if (entry->checksum != checksum + || entry->summary.num != expected) { - error ("coverage mismatch for function %qs while reading counter %qs", - IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)), - ctr_names[counter]); - error ("number of counters is %d instead of %d", entry->summary.num, expected); - return 0; + static int warned = 0; + const char *id = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME + (current_function_decl)); + + if (warn_coverage_mismatch) + warning (OPT_Wcoverage_mismatch, "coverage mismatch for function " + "%qs while reading counter %qs", id, ctr_names[counter]); + else + error ("coverage mismatch for function %qs while reading counter %qs", + id, ctr_names[counter]); + + if (!inhibit_warnings) + { + if (entry->checksum != checksum) + inform (input_location, "checksum is %x instead of %x", entry->checksum, checksum); + else + inform (input_location, "number of counters is %d instead of %d", + entry->summary.num, expected); + } + + if (warn_coverage_mismatch + && !inhibit_warnings + && !warned++) + { + inform (input_location, "coverage mismatch ignored due to -Wcoverage-mismatch"); + inform (input_location, flag_guess_branch_prob + ? "execution counts estimated" + : "execution counts assumed to be zero"); + if (!flag_guess_branch_prob) + inform (input_location, "this can result in poorly optimized code"); + } + + return NULL; } if (summary) @@ -388,21 +411,22 @@ coverage_counter_alloc (unsigned counter, unsigned num) if (!tree_ctr_tables[counter]) { - /* Generate and save a copy of this so it can be shared. */ - /* We don't know the size yet; make it big enough that nobody - will make any clever transformation on it. */ + /* Generate and save a copy of this so it can be shared. Leave + the index type unspecified for now; it will be set after all + functions have been compiled. */ char buf[20]; tree gcov_type_node = get_gcov_type (); - tree domain_tree - = build_index_type (build_int_cst (NULL_TREE, 1000)); /* replaced later */ tree gcov_type_array_type - = build_array_type (gcov_type_node, domain_tree); + = build_array_type (gcov_type_node, NULL_TREE); tree_ctr_tables[counter] = build_decl (VAR_DECL, NULL_TREE, gcov_type_array_type); TREE_STATIC (tree_ctr_tables[counter]) = 1; ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1); DECL_NAME (tree_ctr_tables[counter]) = get_identifier (buf); DECL_ALIGN (tree_ctr_tables[counter]) = TYPE_ALIGN (gcov_type_node); + + if (dump_file) + fprintf (dump_file, "Using data file %s\n", da_file_name); } fn_b_ctrs[counter] = fn_n_ctrs[counter]; fn_n_ctrs[counter] += num; @@ -416,18 +440,30 @@ tree tree_coverage_counter_ref (unsigned counter, unsigned no) { tree gcov_type_node = get_gcov_type (); - tree domain_type = TYPE_DOMAIN (TREE_TYPE (tree_ctr_tables[counter])); gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]); no += prg_n_ctrs[counter] + fn_b_ctrs[counter]; /* "no" here is an array index, scaled to bytes later. */ return build4 (ARRAY_REF, gcov_type_node, tree_ctr_tables[counter], - fold_convert (domain_type, - build_int_cst (NULL_TREE, no)), - TYPE_MIN_VALUE (domain_type), - size_binop (EXACT_DIV_EXPR, TYPE_SIZE_UNIT (gcov_type_node), - size_int (TYPE_ALIGN_UNIT (gcov_type_node)))); + build_int_cst (NULL_TREE, no), NULL, NULL); +} + +/* Generate a tree to access the address of COUNTER NO. */ + +tree +tree_coverage_counter_addr (unsigned counter, unsigned no) +{ + tree gcov_type_node = get_gcov_type (); + + gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]); + no += prg_n_ctrs[counter] + fn_b_ctrs[counter]; + + /* "no" here is an array index, scaled to bytes later. */ + return build_fold_addr_expr (build4 (ARRAY_REF, gcov_type_node, + tree_ctr_tables[counter], + build_int_cst (NULL_TREE, no), + NULL, NULL)); } /* Generate a checksum for a string. CHKSUM is the current @@ -440,7 +476,7 @@ coverage_checksum_string (unsigned chksum, const char *string) char *dup = NULL; /* Look for everything that looks if it were produced by - get_file_function_name_long and zero out the second part + get_file_function_name and zero out the second part that may result from flag_random_seed. This is not critical as the checksums are used only for sanity checking. */ for (i = 0; string[i]; i++) @@ -455,32 +491,33 @@ coverage_checksum_string (unsigned chksum, const char *string) _GLOBAL__N___functionname since filename might contain extra underscores there seems to be no better chance then walk all possible offsets looking - for magicnuber. */ + for magicnumber. */ if (offset) - for (;string[offset]; offset++) - for (i = i + offset; string[i]; i++) - if (string[i]=='_') - { - int y; - - for (y = 1; y < 9; y++) - if (!(string[i + y] >= '0' && string[i + y] <= '9') - && !(string[i + y] >= 'A' && string[i + y] <= 'F')) - break; - if (y != 9 || string[i + 9] != '_') - continue; - for (y = 10; y < 18; y++) - if (!(string[i + y] >= '0' && string[i + y] <= '9') - && !(string[i + y] >= 'A' && string[i + y] <= 'F')) - break; - if (y != 18) - continue; - if (!dup) - string = dup = xstrdup (string); - for (y = 10; y < 18; y++) - dup[i + y] = '0'; - } - break; + { + for (i = i + offset; string[i]; i++) + if (string[i]=='_') + { + int y; + + for (y = 1; y < 9; y++) + if (!(string[i + y] >= '0' && string[i + y] <= '9') + && !(string[i + y] >= 'A' && string[i + y] <= 'F')) + break; + if (y != 9 || string[i + 9] != '_') + continue; + for (y = 10; y < 18; y++) + if (!(string[i + y] >= '0' && string[i + y] <= '9') + && !(string[i + y] >= 'A' && string[i + y] <= 'F')) + break; + if (y != 18) + continue; + if (!dup) + string = dup = xstrdup (string); + for (y = 10; y < 18; y++) + dup[i + y] = '0'; + } + break; + } } chksum = crc32_string (chksum, string); @@ -514,7 +551,9 @@ compute_checksum (void) int coverage_begin_output (void) { - if (no_coverage) + /* We don't need to output .gcno file unless we're under -ftest-coverage + (e.g. -fprofile-arcs/generate/use don't need .gcno to work). */ + if (no_coverage || !flag_test_coverage) return 0; if (!bbg_function_announced) @@ -608,7 +647,7 @@ build_fn_info_type (unsigned int counters) array_type = build_int_cst (NULL_TREE, counters - 1); array_type = build_index_type (array_type); - array_type = build_array_type (unsigned_type_node, array_type); + array_type = build_array_type (get_gcov_unsigned_t (), array_type); /* counters */ field = build_decl (FIELD_DECL, NULL_TREE, array_type); @@ -646,7 +685,7 @@ build_fn_info_value (const struct function_list *function, tree type) for (ix = 0; ix != GCOV_COUNTERS; ix++) if (prg_ctr_mask & (1 << ix)) { - tree counters = build_int_cstu (unsigned_type_node, + tree counters = build_int_cstu (get_gcov_unsigned_t (), function->n_ctrs[ix]); array_value = tree_cons (NULL_TREE, counters, array_value); @@ -686,7 +725,7 @@ build_ctr_info_type (void) /* merge */ gcov_merge_fn_type = build_function_type_list (void_type_node, - gcov_ptr_type, unsigned_type_node, + gcov_ptr_type, get_gcov_unsigned_t (), NULL_TREE); field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type (gcov_merge_fn_type)); @@ -720,7 +759,7 @@ build_ctr_info_value (unsigned int counter, tree type) { tree array_type; - array_type = build_int_cstu (unsigned_type_node, + array_type = build_int_cstu (get_gcov_unsigned_t (), prg_n_ctrs[counter] - 1); array_type = build_index_type (array_type); array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)), @@ -771,8 +810,7 @@ build_gcov_info (void) tree field, fields = NULL_TREE; tree value = NULL_TREE; tree filename_string; - char *filename; - int filename_len; + int da_file_name_len; unsigned n_fns; const struct function_list *fn; tree string_type; @@ -811,17 +849,11 @@ build_gcov_info (void) field = build_decl (FIELD_DECL, NULL_TREE, string_type); TREE_CHAIN (field) = fields; fields = field; - filename = getpwd (); - filename = (filename && da_file_name[0] != '/' - ? concat (filename, "/", da_file_name, NULL) - : da_file_name); - filename_len = strlen (filename); - filename_string = build_string (filename_len + 1, filename); - if (filename != da_file_name) - free (filename); + da_file_name_len = strlen (da_file_name); + filename_string = build_string (da_file_name_len + 1, da_file_name); TREE_TYPE (filename_string) = build_array_type (char_type_node, build_index_type - (build_int_cst (NULL_TREE, filename_len))); + (build_int_cst (NULL_TREE, da_file_name_len))); value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string), value); @@ -849,11 +881,11 @@ build_gcov_info (void) fn_info_value = null_pointer_node; /* number of functions */ - field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node); + field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ()); TREE_CHAIN (field) = fields; fields = field; value = tree_cons (field, - build_int_cstu (unsigned_type_node, n_fns), + build_int_cstu (get_gcov_unsigned_t (), n_fns), value); /* fn_info table */ @@ -863,11 +895,11 @@ build_gcov_info (void) value = tree_cons (field, fn_info_value, value); /* counter_mask */ - field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node); + field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ()); TREE_CHAIN (field) = fields; fields = field; value = tree_cons (field, - build_int_cstu (unsigned_type_node, prg_ctr_mask), + build_int_cstu (get_gcov_unsigned_t (), prg_ctr_mask), value); /* counters */ @@ -934,8 +966,7 @@ create_coverage (void) /* Generate a call to __gcov_init(&gcov_info). */ body = NULL; t = build_fold_addr_expr (gcov_info); - t = tree_cons (NULL, t, NULL); - t = build_function_call_expr (gcov_init, t); + t = build_call_expr (gcov_init, 1, t); append_to_statement_list (t, &body); /* Generate a constructor to run it. */ @@ -949,10 +980,27 @@ void coverage_init (const char *filename) { int len = strlen (filename); + /* + 1 for extra '/', in case prefix doesn't end with /. */ + int prefix_len; + + if (profile_data_prefix == 0 && filename[0] != '/') + profile_data_prefix = getpwd (); + + prefix_len = (profile_data_prefix) ? strlen (profile_data_prefix) + 1 : 0; /* Name of da file. */ - da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX) + 1); - strcpy (da_file_name, filename); + da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX) + + prefix_len + 1); + + if (profile_data_prefix) + { + strcpy (da_file_name, profile_data_prefix); + da_file_name[prefix_len - 1] = '/'; + da_file_name[prefix_len] = 0; + } + else + da_file_name[0] = 0; + strcat (da_file_name, filename); strcat (da_file_name, GCOV_DATA_SUFFIX); /* Name of bbg file. */ @@ -960,7 +1008,8 @@ coverage_init (const char *filename) strcpy (bbg_file_name, filename); strcat (bbg_file_name, GCOV_NOTE_SUFFIX); - read_counts_file (); + if (flag_profile_use) + read_counts_file (); } /* Performs file-level cleanup. Close graph file, generate coverage