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