/* Read and write coverage files, and associated functionality.
Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
- 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
+ 2000, 2001, 2003, 2004, 2005 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.
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, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#define GCOV_LINKAGE
static tree build_ctr_info_value (unsigned, tree);
static tree build_gcov_info (void);
static void create_coverage (void);
+\f
+/* Return the type node for gcov_type. */
+
+tree
+get_gcov_type (void)
+{
+ return lang_hooks.types.type_for_size (GCOV_TYPE_SIZE, false);
+}
+
+/* Return the type node for gcov_unsigned_t. */
+static tree
+get_gcov_unsigned_t (void)
+{
+ return lang_hooks.types.type_for_size (32, true);
+}
\f
static hashval_t
htab_counts_entry_hash (const void *of)
if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
{
- warning ("`%s' is not a gcov data file", da_file_name);
+ warning (0, "%qs is not a gcov data file", da_file_name);
gcov_close ();
return;
}
GCOV_UNSIGNED2STRING (v, tag);
GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
- warning ("`%s' is version `%.*s', expected version `%.*s'",
+ warning (0, "%qs is version %q.*s, expected version %q.*s",
da_file_name, 4, v, 4, e);
gcov_close ();
return;
entry = *slot;
if (!entry)
{
- *slot = entry = xcalloc (1, sizeof (counts_entry_t));
+ *slot = entry = XCNEW (counts_entry_t);
entry->ident = elt.ident;
entry->ctr = elt.ctr;
entry->checksum = checksum;
entry->summary.num = n_counts;
- entry->counts = xcalloc (n_counts, sizeof (gcov_type));
+ entry->counts = XCNEWVEC (gcov_type, n_counts);
}
else if (entry->checksum != checksum)
{
- error ("coverage mismatch for function %u while reading execution counters.",
+ error ("coverage mismatch for function %u while reading execution counters",
fn_ident);
error ("checksum is %x instead of %x", entry->checksum, checksum);
htab_delete (counts_hash);
}
else if (entry->summary.num != n_counts)
{
- error ("coverage mismatch for function %u while reading execution counters.",
+ error ("coverage mismatch for function %u while reading execution counters",
fn_ident);
error ("number of counters is %d instead of %d", entry->summary.num, n_counts);
htab_delete (counts_hash);
gcov_sync (offset, length);
if ((is_error = gcov_is_error ()))
{
- error (is_error < 0 ? "`%s' has overflowed" : "`%s' is corrupted",
+ error (is_error < 0 ? "%qs has overflowed" : "%qs is corrupted",
da_file_name);
htab_delete (counts_hash);
break;
entry = htab_find (counts_hash, &elt);
if (!entry)
{
- warning ("no coverage for function '%s' found.", IDENTIFIER_POINTER
+ warning (0, "no coverage for function %qs found", IDENTIFIER_POINTER
(DECL_ASSEMBLER_NAME (current_function_decl)));
return 0;
}
checksum = compute_checksum ();
if (entry->checksum != checksum)
{
- error ("coverage mismatch for function '%s' while reading counter '%s'.",
+ 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);
}
else if (entry->summary.num != expected)
{
- error ("coverage mismatch for function '%s' while reading counter '%s'.",
+ 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);
/* We don't know the size yet; make it big enough that nobody
will make any clever transformation on it. */
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, domain_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);
+ DECL_ALIGN (tree_ctr_tables[counter]) = TYPE_ALIGN (gcov_type_node);
}
fn_b_ctrs[counter] = fn_n_ctrs[counter];
fn_n_ctrs[counter] += num;
return 1;
}
-/* Generate a MEM rtl to access COUNTER NO. */
-
-rtx
-rtl_coverage_counter_ref (unsigned counter, unsigned no)
-{
- unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
- enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
- rtx ref;
-
- gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
- no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
- if (!ctr_labels[counter])
- {
- ctr_labels[counter] = gen_rtx_SYMBOL_REF (Pmode,
- ggc_strdup (IDENTIFIER_POINTER (DECL_NAME
- (tree_ctr_tables[counter]))));
- SYMBOL_REF_FLAGS (ctr_labels[counter]) = SYMBOL_FLAG_LOCAL;
- }
- ref = plus_constant (ctr_labels[counter], gcov_size / BITS_PER_UNIT * no);
- ref = gen_rtx_MEM (mode, ref);
- set_mem_alias_set (ref, new_alias_set ());
- MEM_NOTRAP_P (ref) = 1;
-
- return ref;
-}
-
/* Generate a tree to access COUNTER NO. */
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],
+ 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))));
+ size_binop (EXACT_DIV_EXPR, TYPE_SIZE_UNIT (gcov_type_node),
+ size_int (TYPE_ALIGN_UNIT (gcov_type_node))));
}
\f
/* Generate a checksum for a string. CHKSUM is the current
as the checksums are used only for sanity checking. */
for (i = 0; string[i]; i++)
{
+ int offset = 0;
+ if (!strncmp (string + i, "_GLOBAL__N_", 11))
+ offset = 11;
if (!strncmp (string + i, "_GLOBAL__", 9))
- for (i = i + 9; string[i]; i++)
- if (string[i]=='_')
- {
- int y;
- unsigned seed;
- int scan;
-
- 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;
- scan = sscanf (string + i + 10, "%X", &seed);
- gcc_assert (scan);
- if (seed != crc32_string (0, flag_random_seed))
- continue;
- string = dup = xstrdup (string);
- for (y = 10; y < 18; y++)
- dup[i + y] = '0';
- break;
- }
- break;
+ offset = 9;
+
+ /* C++ namespaces do have scheme:
+ _GLOBAL__N_<filename>_<wrongmagicnumber>_<magicnumber>functionname
+ since filename might contain extra underscores there seems
+ to be no better chance then walk all possible offsets looking
+ for magicnuber. */
+ 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;
}
chksum = crc32_string (chksum, string);
if (bbg_file_opened > 1 && gcov_is_error ())
{
- warning ("error writing `%s'", bbg_file_name);
+ warning (0, "error writing %qs", bbg_file_name);
bbg_file_opened = -1;
}
{
struct function_list *item;
- item = xmalloc (sizeof (struct function_list));
+ item = XNEW (struct function_list);
*functions_tail = item;
functions_tail = &item->next;
tree array_type;
/* ident */
- fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
+ fields = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
/* checksum */
- field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
+ field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
TREE_CHAIN (field) = fields;
fields = field;
tree array_value = NULL_TREE;
/* ident */
- value = tree_cons (fields, build_int_cstu (unsigned_intSI_type_node,
+ value = tree_cons (fields, build_int_cstu (get_gcov_unsigned_t (),
function->ident), value);
fields = TREE_CHAIN (fields);
/* checksum */
- value = tree_cons (fields, build_int_cstu (unsigned_intSI_type_node,
+ value = tree_cons (fields, build_int_cstu (get_gcov_unsigned_t (),
function->checksum), value);
fields = TREE_CHAIN (fields);
array_value = tree_cons (NULL_TREE, counters, array_value);
}
- array_value = build_constructor (TREE_TYPE (fields), nreverse (array_value));
+ /* FIXME: use build_constructor directly. */
+ array_value = build_constructor_from_list (TREE_TYPE (fields),
+ nreverse (array_value));
value = tree_cons (fields, array_value, value);
- value = build_constructor (type, nreverse (value));
+ /* FIXME: use build_constructor directly. */
+ value = build_constructor_from_list (type, nreverse (value));
return value;
}
{
tree type = lang_hooks.types.make_type (RECORD_TYPE);
tree field, fields = NULL_TREE;
- tree gcov_ptr_type = build_pointer_type (GCOV_TYPE_NODE);
+ tree gcov_ptr_type = build_pointer_type (get_gcov_type ());
tree gcov_merge_fn_type;
/* counters */
- field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
+ field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
TREE_CHAIN (field) = fields;
fields = field;
/* counters */
value = tree_cons (fields,
- build_int_cstu (unsigned_intSI_type_node,
+ build_int_cstu (get_gcov_unsigned_t (),
prg_n_ctrs[counter]),
value);
fields = TREE_CHAIN (fields);
build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
value);
- value = build_constructor (type, nreverse (value));
+ /* FIXME: use build_constructor directly. */
+ value = build_constructor_from_list (type, nreverse (value));
return value;
}
const_type = build_qualified_type (type, TYPE_QUAL_CONST);
/* Version ident */
- field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_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_intSI_type_node,
- GCOV_VERSION), value);
+ value = tree_cons (field, build_int_cstu (TREE_TYPE (field), GCOV_VERSION),
+ value);
/* next -- NULL */
field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
value = tree_cons (field, null_pointer_node, value);
/* stamp */
- field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_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_intSI_type_node,
- local_tick), value);
+ value = tree_cons (field, build_int_cstu (TREE_TYPE (field), local_tick),
+ value);
/* Filename */
string_type = build_pointer_type (build_qualified_type (char_type_node,
array_type = build_index_type (build_int_cst (NULL_TREE, n_fns - 1));
array_type = build_array_type (fn_info_type, array_type);
- fn_info_value = build_constructor (array_type, nreverse (fn_info_value));
+ /* FIXME: use build_constructor directly. */
+ fn_info_value = build_constructor_from_list (array_type,
+ nreverse (fn_info_value));
fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
}
else
ctr_info_value = tree_cons (NULL_TREE,
build_ctr_info_value (ix, ctr_info_type),
ctr_info_value);
- ctr_info_value = build_constructor (ctr_info_ary_type,
- nreverse (ctr_info_value));
+ /* FIXME: use build_constructor directly. */
+ ctr_info_value = build_constructor_from_list (ctr_info_ary_type,
+ nreverse (ctr_info_value));
field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
TREE_CHAIN (field) = fields;
finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
- value = build_constructor (type, nreverse (value));
+ /* FIXME: use build_constructor directly. */
+ value = build_constructor_from_list (type, nreverse (value));
return value;
}
int len = strlen (filename);
/* Name of da file. */
- da_file_name = xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1);
+ da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX) + 1);
strcpy (da_file_name, filename);
strcat (da_file_name, GCOV_DATA_SUFFIX);
/* Name of bbg file. */
- bbg_file_name = xmalloc (len + strlen (GCOV_NOTE_SUFFIX) + 1);
+ bbg_file_name = XNEWVEC (char, len + strlen (GCOV_NOTE_SUFFIX) + 1);
strcpy (bbg_file_name, filename);
strcat (bbg_file_name, GCOV_NOTE_SUFFIX);