diff options
author | Dodji Seketeli <dodji@seketeli.org> | 2013-06-24 23:29:15 +0200 |
---|---|---|
committer | Dodji Seketeli <dodji@seketeli.org> | 2013-06-25 00:15:40 +0200 |
commit | e741b70d6317c6ca6618f251be8ce3adf093ac70 (patch) | |
tree | 5e866880ccd7978061239de8426623eb420551ad | |
parent | cf3800e82c403b8d89d1b9d2233225f35a8313d2 (diff) | |
download | gcc-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.in | 2 | ||||
-rw-r--r-- | gcc/cp/abi-instr.cc | 158 | ||||
-rw-r--r-- | gcc/cp/abi-instr.h | 1 | ||||
-rw-r--r-- | gcc/cp/decl.c | 7 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 14 |
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. */ { |