/* Read and write coverage files, and associated functionality.
- Copyright (C) 1990-2014 Free Software Foundation, Inc.
+ Copyright (C) 1990-2015 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.
#include "coretypes.h"
#include "tm.h"
#include "rtl.h"
+#include "alias.h"
+#include "symtab.h"
#include "tree.h"
+#include "fold-const.h"
#include "stringpool.h"
#include "stor-layout.h"
#include "flags.h"
#include "output.h"
#include "regs.h"
-#include "expr.h"
+#include "hard-reg-set.h"
#include "function.h"
+#include "insn-config.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "varasm.h"
+#include "stmt.h"
+#include "expr.h"
+#include "predict.h"
+#include "dominance.h"
+#include "cfg.h"
#include "basic-block.h"
#include "toplev.h"
#include "tm_p.h"
-#include "ggc.h"
#include "coverage.h"
#include "langhooks.h"
-#include "hash-table.h"
#include "tree-iterator.h"
#include "context.h"
#include "pass_manager.h"
#include "intl.h"
#include "filenames.h"
#include "target.h"
+#include "params.h"
+#include "auto-profile.h"
#include "gcov-io.h"
#include "gcov-io.c"
};
/* Counts information for a function. */
-typedef struct counts_entry
+typedef struct counts_entry : pointer_hash <counts_entry>
{
/* We hash by */
unsigned ident;
struct gcov_ctr_summary summary;
/* hash_table support. */
- typedef counts_entry value_type;
- typedef counts_entry compare_type;
- static inline hashval_t hash (const value_type *);
- static int equal (const value_type *, const compare_type *);
- static void remove (value_type *);
+ static inline hashval_t hash (const counts_entry *);
+ static int equal (const counts_entry *, const counts_entry *);
+ static void remove (counts_entry *);
} counts_entry_t;
static GTY(()) struct coverage_data *functions_head = 0;
tree
get_gcov_type (void)
{
- enum machine_mode mode = smallest_mode_for_size (GCOV_TYPE_SIZE, MODE_INT);
+ machine_mode mode = smallest_mode_for_size (GCOV_TYPE_SIZE, MODE_INT);
return lang_hooks.types.type_for_mode (mode, false);
}
static tree
get_gcov_unsigned_t (void)
{
- enum machine_mode mode = smallest_mode_for_size (32, MODE_INT);
+ machine_mode mode = smallest_mode_for_size (32, MODE_INT);
return lang_hooks.types.type_for_mode (mode, true);
}
\f
inline hashval_t
-counts_entry::hash (const value_type *entry)
+counts_entry::hash (const counts_entry *entry)
{
return entry->ident * GCOV_COUNTERS + entry->ctr;
}
inline int
-counts_entry::equal (const value_type *entry1,
- const compare_type *entry2)
+counts_entry::equal (const counts_entry *entry1, const counts_entry *entry2)
{
return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
}
inline void
-counts_entry::remove (value_type *entry)
+counts_entry::remove (counts_entry *entry)
{
free (entry->counts);
free (entry);
da_file_name);
return NULL;
}
-
- elt.ident = current_function_funcdef_no + 1;
+ if (PARAM_VALUE (PARAM_PROFILE_FUNC_INTERNAL_ID))
+ elt.ident = current_function_funcdef_no + 1;
+ else
+ {
+ gcc_assert (coverage_node_map_initialized_p ());
+ elt.ident = cgraph_node::get (cfun->decl)->profile_id;
+ }
elt.ctr = counter;
entry = counts_hash->find (&elt);
if (!entry || !entry->summary.num)
}
else if (entry->lineno_checksum != lineno_checksum)
{
- warning (0, "source locations for function %qE have changed,"
+ warning (OPT_Wcoverage_mismatch,
+ "source locations for function %qE have changed,"
" the profile data may be out of date",
DECL_ASSEMBLER_NAME (current_function_decl));
}
unsigned chksum;
/* Externally visible symbols have unique name. */
- if (TREE_PUBLIC (n->decl) || DECL_EXTERNAL (n->decl))
+ if (TREE_PUBLIC (n->decl) || DECL_EXTERNAL (n->decl) || n->unique_name)
{
chksum = coverage_checksum_string
(0, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (n->decl)));
{
expanded_location xloc
= expand_location (DECL_SOURCE_LOCATION (n->decl));
+ bool use_name_only = (PARAM_VALUE (PARAM_PROFILE_FUNC_INTERNAL_ID) == 0);
- chksum = xloc.line;
+ chksum = (use_name_only ? 0 : xloc.line);
chksum = coverage_checksum_string (chksum, xloc.file);
chksum = coverage_checksum_string
(chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (n->decl)));
- if (first_global_object_name)
+ if (!use_name_only && first_global_object_name)
chksum = coverage_checksum_string
(chksum, first_global_object_name);
chksum = coverage_checksum_string
(chksum, aux_base_name);
}
- /* Non-negative integers are hopefully small enough to fit in all targets. */
- return chksum & 0x7fffffff;
+ /* Non-negative integers are hopefully small enough to fit in all targets.
+ Gcov file formats wants non-zero function IDs. */
+ chksum = chksum & 0x7fffffff;
+ return chksum + (!chksum);
}
/* Compute cfg checksum for the function FN given as argument.
/* Announce function */
offset = gcov_write_tag (GCOV_TAG_FUNCTION);
- gcov_write_unsigned (current_function_funcdef_no + 1);
+ if (PARAM_VALUE (PARAM_PROFILE_FUNC_INTERNAL_ID))
+ gcov_write_unsigned (current_function_funcdef_no + 1);
+ else
+ {
+ gcc_assert (coverage_node_map_initialized_p ());
+ gcov_write_unsigned (
+ cgraph_node::get (current_function_decl)->profile_id);
+ }
+
gcov_write_unsigned (lineno_checksum);
gcov_write_unsigned (cfg_checksum);
gcov_write_string (IDENTIFIER_POINTER
{
struct coverage_data *item = 0;
- /* If the function is extern (i.e. extern inline), then we won't
- be outputting it, so don't chain it onto the function
- list. */
- if (!DECL_EXTERNAL (current_function_decl))
+ item = ggc_alloc<coverage_data> ();
+
+ if (PARAM_VALUE (PARAM_PROFILE_FUNC_INTERNAL_ID))
+ item->ident = current_function_funcdef_no + 1;
+ else
{
- item = ggc_alloc<coverage_data> ();
-
- item->ident = current_function_funcdef_no + 1;
- item->lineno_checksum = lineno_checksum;
- item->cfg_checksum = cfg_checksum;
-
- item->fn_decl = current_function_decl;
- item->next = 0;
- *functions_tail = item;
- functions_tail = &item->next;
+ gcc_assert (coverage_node_map_initialized_p ());
+ item->ident = cgraph_node::get (cfun->decl)->profile_id;
}
+ item->lineno_checksum = lineno_checksum;
+ item->cfg_checksum = cfg_checksum;
+
+ item->fn_decl = current_function_decl;
+ item->next = 0;
+ *functions_tail = item;
+ functions_tail = &item->next;
+
for (i = 0; i != GCOV_COUNTERS; i++)
{
tree var = fn_v_ctrs[i];
if (!prg_ctr_mask)
return false;
- if (cgraph_dump_file)
- fprintf (cgraph_dump_file, "Using data file %s\n", da_file_name);
+ if (symtab->dump_file)
+ fprintf (symtab->dump_file, "Using data file %s\n", da_file_name);
/* Prune functions. */
for (fn_prev = &functions_head; (fn = *fn_prev);)
/* Build the info and fn_info types. These are mutually recursive. */
gcov_info_type = lang_hooks.types.make_type (RECORD_TYPE);
gcov_fn_info_type = lang_hooks.types.make_type (RECORD_TYPE);
+ build_fn_info_type (gcov_fn_info_type, n_counters, gcov_info_type);
+ gcov_info_type = lang_hooks.types.make_type (RECORD_TYPE);
gcov_fn_info_ptr_type = build_pointer_type
(build_qualified_type (gcov_fn_info_type, TYPE_QUAL_CONST));
- build_fn_info_type (gcov_fn_info_type, n_counters, gcov_info_type);
build_info_type (gcov_info_type, gcov_fn_info_ptr_type);
/* Build the gcov info var, this is referred to in its own
bbg_file_stamp = local_tick;
- if (flag_branch_probabilities)
+ if (flag_auto_profile)
+ read_autofdo_file ();
+ else if (flag_branch_probabilities)
read_counts_file ();
/* Name of bbg file. */