summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDodji Seketeli <dodji@seketeli.org>2013-05-24 21:14:09 +0200
committerDodji Seketeli <dodji@seketeli.org>2013-05-24 22:41:07 +0200
commit9eb78ffdc7d6de30304dd04dc5eb38b93e9a58a8 (patch)
tree3ad67f33927d5180d1db9d5114b73d57416b8a01
parente764edacaa0f9f33fb55609063bcfd5e25c11742 (diff)
downloadgcc-9eb78ffdc7d6de30304dd04dc5eb38b93e9a58a8.tar.gz
Namespace support and misc changes
gcc/cp * abi-instr.cc (struct type_or_decl_hash): Rename struct tree_hash into this. In the hashing function, ensure we have either types or decls. (struct type_or_decl_equal): Rename struct tree_equal into this. Use same_type_p to compare types, as operand_equal_p is not suited for them. (typedef scope_map): Rename typedef tree_scope_decl_map into this. (typedef type_map, typedef decl_map): New typedefs. (tu, conf): Make these globals be naked pointers rather than shared_ptrs. (tree_2_scope_map, tree_2_type_map, tree_2_decl_map): New global maps. (deallocate_stuff, get_cur_ty, get_conf, convert_visibility) (convert_location, get_decl_binding): Declare static functions at the beginning of the translation unit. (gen_scope_of): Rename get_scope into this. Make it really generate scopes for decls/types that have one. (get_decl_visibility): Rename decl_visibility into this. (get_location): Rename tree_location into this. (gen_type): Rename gen_type_decl into this. It's now supposed to handle all types. (get_tree_2_scope_map, get_tree_2_type_map, gen_scope_decl) (gen_type_in_scope, gen_decl_in_scope, gen_decl) (get_tree_2_type_map): New static functions. (deallocate_stuff, get_cur_tu, get_conf, get_tree_2_scope_map): Adjust as the globals are now naked pointers. (convert_location): For builtins' locations, return a zero as location number. (abi_instr_emit_vars): Use the new gen_decl on each var. (*): Add comment to all the functions so far.
-rw-r--r--gcc/cp/abi-instr.cc315
1 files changed, 245 insertions, 70 deletions
diff --git a/gcc/cp/abi-instr.cc b/gcc/cp/abi-instr.cc
index 5cbbedd351a..2ccfb76a36f 100644
--- a/gcc/cp/abi-instr.cc
+++ b/gcc/cp/abi-instr.cc
@@ -38,7 +38,7 @@ using std::tr1::shared_ptr;
using std::tr1::unordered_map;
using std::string;
-struct tree_hash
+struct type_or_decl_hash
{
size_t
operator () (const_tree t) const
@@ -47,94 +47,152 @@ struct tree_hash
return 0;
if (TYPE_P (t))
return TYPE_HASH (t);
+
+ char tclass = TREE_CODE_CLASS (TREE_CODE (t));
+ gcc_assert (tclass == tcc_declaration);
return iterative_hash_expr (t, 0);
}
};
-
-struct tree_equal
+struct type_or_decl_equal
{
bool
operator () (const_tree t0, const_tree t1) const
{
+ if (TYPE_P (t0))
+ return same_type_p (CONST_CAST_TREE (t0), CONST_CAST_TREE (t1));
return operand_equal_p (t0, t1, 0);
}
};
typedef unordered_map <const_tree,
shared_ptr <abigail::scope_decl>,
- tree_hash, tree_equal> tree_scope_decl_map;
+ type_or_decl_hash, type_or_decl_equal> scope_map;
-static shared_ptr <abigail::translation_unit> tu;
-static shared_ptr<abigail::config> conf;
-static shared_ptr <tree_scope_decl_map> tree_2_scope_map;
+typedef unordered_map <const_tree,
+ shared_ptr <abigail::type_base>,
+ type_or_decl_hash,
+ type_or_decl_equal> type_map;
+typedef unordered_map <const_tree,
+ shared_ptr <abigail::decl_base>,
+ type_or_decl_hash,
+ type_or_decl_equal> decl_map;
+
+static abigail::translation_unit *tu;
+static abigail::config *conf;
+static scope_map *tree_2_scope_map;
+static type_map *tree_2_type_map;
+static decl_map *tree_2_decl_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 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);
+static abigail::decl_base::visibility get_decl_visibility (const_tree);
+static abigail::location get_location (const_tree);
+static abigail::decl_base::binding get_decl_binding (const_tree);
+static shared_ptr <abigail::scope_decl> gen_scope_decl (const_tree,
+ shared_ptr <abigail::scope_decl>);
+static shared_ptr<abigail::type_base> gen_type_in_scope (const_tree,
+ shared_ptr <abigail::scope_decl>);
+static shared_ptr<abigail::type_base> gen_type (const_tree);
+static shared_ptr<abigail::decl_base> gen_decl_in_scope (const_tree,
+ shared_ptr <abigail::scope_decl>);
+static shared_ptr<abigail::decl_base> gen_decl(const_tree);
+
+// Deallocate the dynamic memory used by globals in this translation unit.
static void
deallocate_stuff ()
{
- tu.reset ();
- tree_2_scope_map.reset ();
- conf.reset ();
-}
-
-void
-abi_instr_init ()
-{
-}
-
-void
-abi_instr_finish ()
-{
- abi_instr_dump_file ();
- deallocate_stuff ();
+ delete tu; tu = 0;
+ delete tree_2_scope_map; tree_2_scope_map = 0;
+ delete conf; conf = 0;
+ delete tree_2_type_map; tree_2_type_map = 0;
+ delete tree_2_decl_map; tree_2_decl_map = 0;
}
+// Returns the current translation unit. This function allocates it,
+// if necessary.
static abigail::translation_unit&
get_cur_tu ()
{
if (!tu)
- tu.reset (new abigail::translation_unit (main_input_filename));
+ tu = new abigail::translation_unit (main_input_filename);
return *tu;
}
+// Returns the instance of configuration type used by the libabigail
+// library.
static const abigail::config&
get_conf ()
{
if (!conf)
- conf.reset (new abigail::config);
+ conf = new abigail::config;
return *conf;
}
-static tree_scope_decl_map&
+// Allocates (if necessary) and return the map that associates trees
+// representing a scope and their matching instance of libabigail
+// scope.
+static scope_map&
get_tree_2_scope_map ()
{
if (!tree_2_scope_map)
- tree_2_scope_map.reset (new tree_scope_decl_map);
+ tree_2_scope_map = new scope_map;
return *tree_2_scope_map;
}
+// Allocates (if necessary) and return the map that associates trees
+// representing a type and their matching instance of libabigail type.
+static type_map&
+get_tree_2_type_map ()
+{
+ if (!tree_2_type_map)
+ tree_2_type_map = new type_map;
+
+ return *tree_2_type_map;
+}
+
+// Generate (if necessary) and return an instance of libabigail scope
+// type representing the scope of T.
static shared_ptr<abigail::scope_decl>
-get_scope (const_tree t)
+gen_scope_of (const_tree t)
{
- shared_ptr<abigail::scope_decl> nil;
+ shared_ptr<abigail::scope_decl> result;
if (t == NULL_TREE)
- return nil;
+ return result;
- tree_scope_decl_map& s = get_tree_2_scope_map ();
- tree_scope_decl_map::const_iterator i = s.find (t);
- if (i == s.end ())
- {
- if ((TYPE_P (t) && TYPE_FILE_SCOPE_P (t))
- || (DECL_P (t) && DECL_FILE_SCOPE_P (t)))
- return get_cur_tu ().get_global_scope ();
- return shared_ptr<abigail::scope_decl> ();
- }
- return i->second;
+ tree context = NULL_TREE;
+ if (TYPE_P (t))
+ context = TYPE_CONTEXT (t);
+ else if (DECL_P (t))
+ context = DECL_CONTEXT (t);
+
+ if (SCOPE_FILE_SCOPE_P (context))
+ return get_cur_tu ().get_global_scope ();
+
+ gcc_assert (TREE_CODE (context) == NAMESPACE_DECL
+ || TYPE_P (context));
+
+ scope_map& m = get_tree_2_scope_map ();
+ scope_map::const_iterator i = m.find (context);
+ if (i != m.end ())
+ return i->second;
+
+ result = gen_scope_decl (context, gen_scope_of (context));
+
+ return result;
}
+// Convert a symbol_visibility into a libabigail visibility.
static abigail::decl_base::visibility
convert_visibility (symbol_visibility v)
{
@@ -152,17 +210,23 @@ convert_visibility (symbol_visibility v)
return abigail::decl_base::VISIBILITY_NONE;
}
+// Convert a GCC source location into an instance of libabigail
+// location.
static abigail::location
convert_location (source_location l)
{
+ if (l <= BUILTINS_LOCATION)
+ return abigail::location ();
+
expanded_location e = expand_location (l);
return get_cur_tu ().get_loc_mgr ().create_new_location (e.file,
e.line,
e.column);
}
+// Return a libabigail visibility of the GCC DECL.
static abigail::decl_base::visibility
-decl_visibility (const_tree decl)
+get_decl_visibility (const_tree decl)
{
if (decl == NULL_TREE)
return abigail::decl_base::VISIBILITY_NONE;
@@ -170,8 +234,9 @@ decl_visibility (const_tree decl)
return convert_visibility (DECL_VISIBILITY (decl));
}
+// Return the libabigail location of T.
static abigail::location
-tree_location (const_tree t)
+get_location (const_tree t)
{
if (t != NULL_TREE)
{
@@ -185,6 +250,7 @@ tree_location (const_tree t)
return abigail::location ();
}
+// Return the libabigail binding of DECL.
static abigail::decl_base::binding
get_decl_binding (const_tree decl)
{
@@ -202,12 +268,89 @@ get_decl_binding (const_tree decl)
return abigail::decl_base::BINDING_NONE;
}
-static shared_ptr<abigail::type_decl>
-gen_basic_type_in_scope (const_tree t,
- shared_ptr<abigail::scope_decl> scope)
+// Generate (if necessary) and return an instance of the libabigail
+// scope decl type, for T that is supposed to be a GCC scope tree;
+// that is either a namespace or a class. The resulting scope is
+// itself added to SCOPE.
+static shared_ptr <abigail::scope_decl>
+gen_scope_decl (const_tree t,
+ shared_ptr <abigail::scope_decl> scope)
+{
+ shared_ptr <abigail::scope_decl> result;
+ if (t == NULL_TREE
+ || (TREE_CODE (t) != NAMESPACE_DECL
+ && !CLASS_TYPE_P (t)))
+ return result;
+
+ if (TREE_CODE (t) == NAMESPACE_DECL)
+ {
+ result.reset
+ (new abigail::namespace_decl (IDENTIFIER_POINTER (DECL_NAME (t)),
+ get_location (t),
+ get_decl_visibility (t)));
+ add_decl_to_scope (result, scope);
+ }
+ else
+ {
+ // FIXME: Generate class declaration here.
+ }
+ return result;
+}
+
+// Generate (if necessary) and return an instance of libabigail decl
+// for T that is supposed to be a GCC decl tree. The resulting
+// instance of libabigail decl is added to the scope SCOPE.
+static shared_ptr <abigail::decl_base>
+gen_decl_in_scope (const_tree t,
+ shared_ptr <abigail::scope_decl> scope)
+{
+ if (t == NULL_TREE || !DECL_P (t))
+ return shared_ptr <abigail::decl_base> ();
+
+ switch (TREE_CODE (t))
+ {
+ case VAR_DECL:
+ {
+ shared_ptr <abigail::type_base> type = gen_type (TREE_TYPE (t));
+ shared_ptr<abigail::var_decl> v
+ (new abigail::var_decl (IDENTIFIER_POINTER (DECL_NAME (t)),
+ type, get_location (t),
+ IDENTIFIER_POINTER
+ (DECL_ASSEMBLER_NAME (CONST_CAST_TREE (t))),
+ get_decl_visibility (t),
+ get_decl_binding (t)));
+ add_decl_to_scope (v, scope);
+ return v;
+ }
+ case NAMESPACE_DECL:
+ {
+ shared_ptr<abigail::namespace_decl> n
+ (new abigail::namespace_decl (IDENTIFIER_POINTER (DECL_NAME (t)),
+ get_location (t),
+ get_decl_visibility (t)));
+ add_decl_to_scope (n, scope);
+ return n;
+ }
+ default:
+ break;
+ }
+ return shared_ptr <abigail::decl_base> ();
+}
+
+// Generate (if necessary) and return an instance of libabigail type
+// for T that is supposed to be a GCC type tree. The resulting
+// libabigail type is added to the scope SCOPE.
+static shared_ptr<abigail::type_base>
+gen_type_in_scope (const_tree t,
+ shared_ptr <abigail::scope_decl> scope)
{
if (t == NULL_TREE || !TYPE_P (t))
- return shared_ptr<abigail::type_decl> ();
+ return shared_ptr <abigail::type_decl> ();
+
+ type_map& m = get_tree_2_type_map ();
+ type_map::const_iterator i = m.find (t);
+ if (i != m.end ())
+ return i->second;
switch (TREE_CODE (t))
{
@@ -216,7 +359,7 @@ gen_basic_type_in_scope (const_tree t,
case NULLPTR_TYPE:
case VOID_TYPE:
{
- abigail::location aloc = tree_location (t);
+ abigail::location aloc = get_location (t);
shared_ptr<abigail::type_decl> type_declaration
(new abigail::type_decl (IDENTIFIER_POINTER
@@ -225,60 +368,92 @@ gen_basic_type_in_scope (const_tree t,
TYPE_ALIGN (t), aloc,
IDENTIFIER_POINTER
(DECL_ASSEMBLER_NAME (TYPE_NAME (t))),
- decl_visibility (TYPE_NAME (t))));
+ get_decl_visibility (TYPE_NAME (t))));
add_decl_to_scope (type_declaration, scope);
+ m[t] = type_declaration;
return type_declaration;
}
default:
break;
}
- return shared_ptr<abigail::type_decl> ();
+ return shared_ptr <abigail::type_decl> ();
}
-static shared_ptr<abigail::type_decl>
-gen_type_decl (const_tree t)
+// Generate (if necessary) and return an instance of libabigail decl
+// for T that is supposed to be a GCC decl tree.
+static shared_ptr<abigail::decl_base>
+gen_decl(const_tree t)
{
- shared_ptr<abigail::scope_decl> scope = get_scope (t);
+ shared_ptr <abigail::decl_base> result;
+ if (t == NULL_TREE)
+ return result;
+
+ gen_type (TREE_TYPE (t));
+ shared_ptr <abigail::scope_decl> scope = gen_scope_of (t);
if (scope)
- return gen_basic_type_in_scope (t, scope);
- /* FIXME: if scope is null, then generate abi instr for the
- scope. */
- return shared_ptr<abigail::type_decl> ();
+ result = gen_decl_in_scope (t, scope);
+
+ return result;
+}
+
+// Generate (if necessary) and return an instance of libabigail type
+// for T that is supposed to be a GCC type tree.
+static shared_ptr<abigail::type_base>
+gen_type (const_tree t)
+{
+ shared_ptr<abigail::scope_decl> scope = gen_scope_of (t);
+ if (scope)
+ return gen_type_in_scope (t, scope);
+ return shared_ptr<abigail::type_base> ();
+}
+
+// -- The public entry points of this translation unit start here.
+
+// All initialization stuff should go here.
+void
+abi_instr_init ()
+{
+}
+
+// Anything that should be done at the very end of the life time of
+// this module should go here.
+void
+abi_instr_finish ()
+{
+ abi_instr_dump_file ();
+ deallocate_stuff ();
}
-/* Build a representation of type T, in libabigail. Return true iff
- the type was emitted. */
+// Build a libabigail representation of type T and add it to the
+// libabigail representation of the current translation unit. Return
+// TRUE upon successful completion, false otherwise.
bool
abi_instr_emit_type (const_tree t)
{
gcc_assert (TYPE_P (t));
- return gen_type_decl (t);
+ return gen_type (t);
}
+// Build a libabigail representation of the variables in the VARS
+// array and add them to the libabigail representation of the current
+// translation unit. Return TRUE upon successful completion, false
+// otherwise.
bool
abi_instr_emit_vars (tree *vars, int len)
{
for (int i = 0; i < len; ++i)
{
tree var = vars[i];
- shared_ptr<abigail::type_decl> t = gen_type_decl (TREE_TYPE (var));
- abigail::location loc = tree_location (var);
-
- shared_ptr<abigail::var_decl> v
- (new abigail::var_decl (IDENTIFIER_POINTER
- (DECL_NAME (var)),
- t, loc,
- IDENTIFIER_POINTER
- (DECL_ASSEMBLER_NAME (var)),
- decl_visibility (var),
- get_decl_binding (var)));
- add_decl_to_scope (v, get_scope (var));
+ if (!gen_decl (var))
+ return false;
}
return true;
}
+// Serialize the libabigail representation of the current translation
+// unit into a file named after the name of the main input file.
void
abi_instr_dump_file ()
{