summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDodji Seketeli <dodji@seketeli.org>2013-06-24 23:29:15 +0200
committerDodji Seketeli <dodji@seketeli.org>2013-06-25 00:15:40 +0200
commite741b70d6317c6ca6618f251be8ce3adf093ac70 (patch)
tree5e866880ccd7978061239de8426623eb420551ad
parentcf3800e82c403b8d89d1b9d2233225f35a8313d2 (diff)
downloadgcc-e741b70d6317c6ca6618f251be8ce3adf093ac70.tar.gz
Instrument functions and vars by walking them in cgraph
gcc/cp/ * Make-lang.in (decl.o): Remove dependency on abi-instr.h * abi-instr.cc (type_or_decl_equal::operator()): Support comparison of trees of different code. (class_map): Rename class_wip_map typedef into this. (function_type_map): New typedef. (tree_2_class_map, tree_2_function_type_map): New global map pointers. (get_tree_2_decl_map, get_tree_2_class_map) (get_tree_2_function_type_map): New accessors. (gen_class_type_in_scope): Take a default argument for the scope parameter. (deallocate_stuff): Deallocate tree_2_class_map and tree_2_function_type_map. (get_wip_classes_map): Adjust for the renaming of class_wip_map into class_map. (gen_function_type): For method types, generate the representation for the base type if necessary. As the generation of the base type can indirectly generate the current method type, look for the method type in the hash map after generating the base type. Add the generated type into the function type map. (gen_class_in_scope): Add the resulting class into the class map and look it up there to avoid building the class twice. Generate the representation of the scope if necessary. (gen_decl_in_scope): Add the resulting decl into the decl map and look it up there to avoid building the decl twice. (gen_type_in_scope): Support building METHOD_TYPE from here. (abi_instr_emit_vars_or_funs): Remove this definition. * abi-instr.h (abi_instr_emit_vars_or_funs): Remove this declaration. * decl.c (wrapup_globals_for_namespace): Remove the instrumentation of vars and functions from here. * decl2.c (cp_write_global_declarations): Remove the instrumentation of vars and functions from the pending_statics vector. Walk the defined functions and globals as seen by cgraph and instrument them if they are emitted.
-rw-r--r--gcc/cp/Make-lang.in2
-rw-r--r--gcc/cp/abi-instr.cc158
-rw-r--r--gcc/cp/abi-instr.h1
-rw-r--r--gcc/cp/decl.c7
-rw-r--r--gcc/cp/decl2.c14
5 files changed, 125 insertions, 57 deletions
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index e6334db772d..2233156b8f5 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -274,7 +274,7 @@ cp/decl.o: cp/decl.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) cp/decl.h \
cp/operators.def $(TM_P_H) $(TREE_INLINE_H) $(DIAGNOSTIC_H) $(C_PRAGMA_H) \
debug.h gt-cp-decl.h $(TIMEVAR_H) $(TARGET_H) $(PLUGIN_H) \
intl.h tree-iterator.h pointer-set.h $(SPLAY_TREE_H) \
- c-family/c-objc.h cp/abi-instr.h
+ c-family/c-objc.h
cp/decl2.o: cp/decl2.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) cp/decl.h \
toplev.h $(C_COMMON_H) gt-cp-decl2.h $(CGRAPH_H) \
$(C_PRAGMA_H) dumpfile.h intl.h $(TARGET_H) $(GIMPLE_H) pointer-set.h \
diff --git a/gcc/cp/abi-instr.cc b/gcc/cp/abi-instr.cc
index 8d015bd9193..607f16bd48a 100644
--- a/gcc/cp/abi-instr.cc
+++ b/gcc/cp/abi-instr.cc
@@ -42,6 +42,7 @@ using std::string;
using std::list;
using std::vector;
+// Hashing functor for hash maps that take a type or decl as keys.
struct type_or_decl_hash
{
size_t
@@ -58,11 +59,17 @@ struct type_or_decl_hash
}
};
+// Comparison functor for hash maps that take either types or decls as
+// keys.
struct type_or_decl_equal
{
bool
operator () (const_tree t0, const_tree t1) const
{
+ if ((!!t0 != !! t1)
+ || (TREE_CODE (t0) != TREE_CODE (t1)))
+ return false;
+
if (TYPE_P (t0))
return same_type_p (CONST_CAST_TREE (t0), CONST_CAST_TREE (t1));
return operand_equal_p (t0, t1, 0);
@@ -71,7 +78,12 @@ struct type_or_decl_equal
typedef unordered_map <const_tree,
shared_ptr <abigail::class_decl>,
type_or_decl_hash,
- type_or_decl_equal> classes_wip_map;
+ type_or_decl_equal> class_map;
+
+typedef unordered_map <const_tree,
+ shared_ptr <abigail::function_type>,
+ type_or_decl_hash,
+ type_or_decl_equal> function_type_map;
typedef unordered_map <const_tree,
shared_ptr <abigail::scope_decl>,
@@ -90,15 +102,20 @@ typedef unordered_map <const_tree,
static abigail::translation_unit *tu;
static abigail::config *conf;
static scope_map *tree_2_scope_map;
-static classes_wip_map *wip_classes_map;
+static class_map *wip_classes_map;
static type_map *tree_2_type_map;
static decl_map *tree_2_decl_map;
+static class_map *tree_2_class_map;
+static function_type_map *tree_2_function_type_map;
static void deallocate_stuff ();
static abigail::translation_unit& get_cur_tu ();
static const abigail::config& get_conf ();
static scope_map& get_tree_2_scope_map ();
static type_map& get_tree_2_type_map ();
+static decl_map& get_tree_2_decl_map ();
+static class_map& get_tree_2_class_map ();
+static function_type_map& get_tree_2_function_type_map ();
static shared_ptr<abigail::scope_decl> gen_scope_of (const_tree );
static abigail::decl_base::visibility convert_visibility (symbol_visibility);
static abigail::location convert_location (source_location);
@@ -124,7 +141,8 @@ static shared_ptr <abigail::function_decl> gen_function_decl
shared_ptr <abigail::class_decl> base_type =
shared_ptr <abigail::class_decl> ());
static shared_ptr <abigail::class_decl> gen_class_type_in_scope
-(const_tree, shared_ptr <abigail::scope_decl>);
+(const_tree,
+ shared_ptr <abigail::scope_decl> scope = shared_ptr <abigail::scope_decl> ());
static shared_ptr<abigail::class_decl::data_member> gen_data_member
(const_tree);
static shared_ptr<abigail::class_decl::member_function> gen_member_function
@@ -146,6 +164,8 @@ deallocate_stuff ()
delete wip_classes_map; wip_classes_map = 0;
delete tree_2_type_map; tree_2_type_map = 0;
delete tree_2_decl_map; tree_2_decl_map = 0;
+ delete tree_2_class_map; tree_2_class_map = 0;
+ delete tree_2_function_type_map; tree_2_function_type_map = 0;
}
// Returns the current translation unit. This function allocates it,
@@ -194,13 +214,47 @@ get_tree_2_type_map ()
}
// Allocates (if necessary) and return the map that associates trees
+// representing a decl and their matching isntance of libabigail type.
+static decl_map&
+get_tree_2_decl_map ()
+{
+ if (!tree_2_decl_map)
+ tree_2_decl_map = new decl_map;
+
+ return *tree_2_decl_map;
+}
+
+// Allocates (if necessary) and return the map that associates trees
+// representing a decl and their matching isntance of libabigail type.
+static class_map&
+get_tree_2_class_map ()
+{
+ if (!tree_2_class_map)
+ tree_2_class_map = new class_map;
+
+ return *tree_2_class_map;
+}
+
+// Allocates (if necessary) and return the map that associates trees
+// representing a function type and their matching isntance of
+// libabigail type.
+static function_type_map&
+get_tree_2_function_type_map ()
+{
+ if (!tree_2_function_type_map)
+ tree_2_function_type_map = new function_type_map;
+
+ return *tree_2_function_type_map;
+}
+
+// Allocates (if necessary) and return the map that associates trees
// representing a class that is currently being instrumented, and the
// matching abigail class_decl.
-static classes_wip_map&
+static class_map&
get_wip_classes_map ()
{
if (!wip_classes_map)
- wip_classes_map = new classes_wip_map;
+ wip_classes_map = new class_map;
return *wip_classes_map;
}
@@ -576,8 +630,20 @@ gen_function_type (const_tree t,
&& TREE_CODE (t) != METHOD_TYPE))
return result;
- if (TREE_CODE (t) == METHOD_TYPE && !base_type)
- return result;
+ if (TREE_CODE (t) == METHOD_TYPE)
+ {
+ if (!base_type)
+ base_type = gen_class_type_in_scope (TYPE_METHOD_BASETYPE (t));
+ gcc_assert (base_type);
+ }
+
+ {
+ function_type_map::const_iterator i =
+ get_tree_2_function_type_map ().find (t);
+ if (i != get_tree_2_function_type_map ().end ())
+ return i->second;
+ }
+
vector<shared_ptr <abigail::function_decl::parameter> > parms;
tree parm_desc = TYPE_ARG_TYPES (t);
@@ -626,6 +692,8 @@ gen_function_type (const_tree t,
get_int_constant_value (TYPE_SIZE (t)),
TYPE_ALIGN (t)));
+ get_tree_2_function_type_map ()[t] = result;
+
return result;
}
@@ -684,19 +752,28 @@ gen_class_type_in_scope (const_tree t,
// handled by gen_type_in_scope.
gcc_assert (!TYPE_QUALS (t) && !typedef_variant_p (t));
- classes_wip_map::const_iterator c =
- get_wip_classes_map ().find(t);
- if (c != get_wip_classes_map ().end ())
- {
- // Someone is referring to this record type but the
- // type is not defined yet -- it's currently being
- // defined. So we let's forward declare it a this point.
-
- shared_ptr <abigail::class_decl> class_type
- (new abigail::class_decl (get_tree_name (t)));
- add_decl_to_scope (class_type, scope);
- return class_type;
- }
+ {
+ class_map::const_iterator i = get_tree_2_class_map ().find (t);
+ if (i != get_tree_2_class_map ().end ())
+ return i->second;
+ }
+
+ {
+ class_map::const_iterator i =
+ get_wip_classes_map ().find(t);
+ if (i != get_wip_classes_map ().end ())
+ {
+ // Someone is referring to this record type but the
+ // type is not defined yet -- it's currently being
+ // defined. So let's forward declare it a this point.
+
+ shared_ptr <abigail::class_decl> class_type
+ (new abigail::class_decl (get_tree_name (t)));
+ add_decl_to_scope (class_type, scope);
+ get_tree_2_class_map ()[t] = class_type;
+ return class_type;
+ }
+ }
shared_ptr <abigail::class_decl> class_type
(new abigail::class_decl (get_tree_name (t),
@@ -706,6 +783,9 @@ gen_class_type_in_scope (const_tree t,
get_wip_classes_map ()[t] = class_type;
+ if (!scope)
+ scope = gen_scope_of (t);
+
{
tree binfo = TYPE_BINFO (t), base_binfo;
for (int i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
@@ -746,6 +826,8 @@ gen_class_type_in_scope (const_tree t,
result = class_type;
get_wip_classes_map ().erase (t);
+ get_tree_2_class_map ()[t] = result;
+
return result;
}
@@ -760,6 +842,12 @@ gen_decl_in_scope (const_tree t,
if (t == NULL_TREE || !DECL_P (t))
return result;
+ {
+ decl_map::const_iterator i = get_tree_2_decl_map ().find (t);
+ if (i != get_tree_2_decl_map ().end ())
+ return i->second;
+ }
+
switch (TREE_CODE (t))
{
case VAR_DECL:
@@ -812,6 +900,10 @@ gen_decl_in_scope (const_tree t,
default:
break;
}
+
+ if (result)
+ get_tree_2_decl_map ()[t] = result;
+
return result;
}
@@ -963,14 +1055,10 @@ gen_type_in_scope (const_tree t,
break;
case FUNCTION_TYPE:
+ case METHOD_TYPE:
result = gen_function_type (t);
break;
- case METHOD_TYPE:
- // This must be handled by gen_function_type, called from within
- // gen_type_in_scope.
- gcc_unreachable ();
-
case RECORD_TYPE:
{
shared_ptr <abigail::class_decl> r =
@@ -1059,26 +1147,6 @@ abi_instr_emit_type (const_tree t)
return gen_type (t);
}
-// Build a libabigail representation of the variables or functions in
-// the VEC array and add them to the libabigail representation of the
-// current translation unit.
-void
-abi_instr_emit_vars_or_funs (tree *vec, int len)
-{
- for (int i = 0; i < len; ++i)
- {
- tree decl = vec[i];
- if (decl == NULL_TREE || (TREE_CODE (decl) != VAR_DECL
- && TREE_CODE (decl) != FUNCTION_DECL))
- continue;
-
- if (TREE_CODE (decl) == VAR_DECL)
- abi_instr_emit_variable (decl);
- else if (TREE_CODE (decl) == FUNCTION_DECL)
- abi_instr_emit_function (decl);
- }
-}
-
// Build a libabigail representation of the function FN and add it to
// the libabigail repesentation of the current translation unit.
// Return TRUE upon successful completion, false otherwise.
diff --git a/gcc/cp/abi-instr.h b/gcc/cp/abi-instr.h
index b8e92b1bf6b..65047842e5b 100644
--- a/gcc/cp/abi-instr.h
+++ b/gcc/cp/abi-instr.h
@@ -24,7 +24,6 @@ along with GCC; see the file COPYING3. If not see
void abi_instr_init ();
void abi_instr_finish ();
bool abi_instr_emit_type (const_tree);
-void abi_instr_emit_vars_or_funs (tree *, int);
bool abi_instr_emit_function(const_tree);
bool abi_instr_emit_variable(const_tree);
void abi_instr_dump_file ();
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index ed001c92238..c37b4fe5592 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -52,7 +52,6 @@ along with GCC; see the file COPYING3. If not see
#include "splay-tree.h"
#include "plugin.h"
#include "cgraph.h"
-#include "abi-instr.h"
/* Possible cases of bad specifiers type used by bad_specifiers. */
enum bad_spec_place {
@@ -870,12 +869,6 @@ wrapup_globals_for_namespace (tree name_space, void* data)
{
check_global_declarations (vec, len);
emit_debug_global_declarations (vec, len);
- if (flag_dump_abi)
- {
- abi_instr_emit_vars_or_funs (vec, len);
- for (tree t = level->names; t; t = TREE_CHAIN (t))
- abi_instr_emit_function (t);
- }
return 0;
}
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 1c44e63daed..4880a7d5a76 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -4339,9 +4339,6 @@ cp_write_global_declarations (void)
pending_statics->length ());
emit_debug_global_declarations (pending_statics->address (),
pending_statics->length ());
- if (flag_dump_abi)
- abi_instr_emit_vars_or_funs (pending_statics->address (),
- pending_statics->length ());
}
perform_deferred_noexcept_checks ();
@@ -4355,6 +4352,17 @@ cp_write_global_declarations (void)
finish_repo ();
+ if (flag_dump_abi)
+ {
+ cgraph_node *fun_node;
+ FOR_EACH_DEFINED_FUNCTION (fun_node)
+ abi_instr_emit_function (fun_node->symbol.decl);
+
+ varpool_node *var_node;
+ FOR_EACH_DEFINED_VARIABLE (var_node)
+ abi_instr_emit_variable (var_node->symbol.decl);
+ }
+
/* The entire file is now complete. If requested, dump everything
to a file. */
{