summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDodji Seketeli <dodji@seketeli.org>2013-05-24 05:52:47 +0200
committerDodji Seketeli <dodji@seketeli.org>2013-05-24 22:41:06 +0200
commit40b181f8e08678387d067f7692fe2d5f63ffaa45 (patch)
treec30aa2813e229b17b06f36793bbea31350c06961
parent431b8fa5b0870562e91170b96430312d37ec0a96 (diff)
downloadgcc-40b181f8e08678387d067f7692fe2d5f63ffaa45.tar.gz
Initial support for vars with simple scalar types
gcc/ * c-family/c.opt (fdump-abi): New command line option that flips the flag_dump_abi flag. * doc/invoke.texi: Add documentation for fdump-abi gcc/cp/ * abi-instr.{h,cc}: New files. * decl.c (wrapup_globals_for_namespace): Emit abi instrumentation for the global variables that are emitted. * lex.c (cxx_finish): Call abi_instr_finish from here. (cxx_init): Call abi_instr_init from here. * Make-lang.in: Add the new files to the build system. Add abi-instr.h to the dependencies of decl.c and lex.c
-rw-r--r--gcc/c-family/c.opt4
-rw-r--r--gcc/cp/Make-lang.in6
-rw-r--r--gcc/cp/abi-instr.cc300
-rw-r--r--gcc/cp/abi-instr.h30
-rw-r--r--gcc/cp/decl.c3
-rw-r--r--gcc/cp/lex.c5
-rw-r--r--gcc/doc/invoke.texi9
7 files changed, 354 insertions, 3 deletions
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 124c13986a8..d4fc55e9ecf 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -891,6 +891,10 @@ fdump-ada-spec-slim
C ObjC C++ ObjC++ RejectNegative Var(flag_dump_ada_spec_slim)
Write all declarations as Ada code for the given file only
+fdump-abi
+C++ Var(flag_dump_abi)
+Dump the ABI of the translation unit to a file
+
felide-constructors
C++ ObjC++ Var(flag_elide_constructors) Init(1)
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index 9bd53639c89..437b9a4966a 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -265,7 +265,7 @@ CXX_PRETTY_PRINT_H = cp/cxx-pretty-print.h $(C_PRETTY_PRINT_H)
cp/lex.o: cp/lex.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) \
$(C_PRAGMA_H) input.h cp/operators.def $(TM_P_H) \
- c-family/c-objc.h
+ c-family/c-objc.h cp/abi-instr.h
cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) $(TM_H) debug.h langhooks.h \
$(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-cp.h gt-cp-cp-lang.h \
cp/cp-objcp-common.h $(EXPR_H) $(TARGET_H) $(CXX_PARSER_H)
@@ -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
+ c-family/c-objc.h cp/abi-instr.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 \
@@ -346,4 +346,4 @@ cp/name-lookup.o: cp/name-lookup.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
cp/cxx-pretty-print.o: cp/cxx-pretty-print.c $(CXX_PRETTY_PRINT_H) \
$(CONFIG_H) $(SYSTEM_H) $(TM_H) coretypes.h $(CXX_TREE_H) tree-pretty-print.h
-cp/abi-instr.o: cp/abi-instr.c $(CONFIG_H)
+cp/abi-instr.o: cp/abi-instr.cc $(CONFIG_H) cp/abi-instr.h
diff --git a/gcc/cp/abi-instr.cc b/gcc/cp/abi-instr.cc
new file mode 100644
index 00000000000..5cbbedd351a
--- /dev/null
+++ b/gcc/cp/abi-instr.cc
@@ -0,0 +1,300 @@
+/* ABI Instrumentation
+ Copyright (C) 2000-2013 Free Software Foundation, Inc.
+ Written by Dodji Seketeli <dodji@redhat.com>
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+
+#ifdef HAVE_abigail
+
+#include "system.h"
+#include "coretypes.h"
+#include <map>
+#include <tr1/unordered_map>
+#include <tr1/memory>
+#include <string>
+#include <fstream>
+#include "cp-tree.h"
+#include "abg-writer.h"
+#include "abg-config.h"
+#include "abi-instr.h"
+
+using std::tr1::shared_ptr;
+using std::tr1::unordered_map;
+using std::string;
+
+struct tree_hash
+{
+ size_t
+ operator () (const_tree t) const
+ {
+ if (t == NULL_TREE)
+ return 0;
+ if (TYPE_P (t))
+ return TYPE_HASH (t);
+ return iterative_hash_expr (t, 0);
+ }
+};
+
+
+struct tree_equal
+{
+ bool
+ operator () (const_tree t0, const_tree t1) const
+ {
+ 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;
+
+static shared_ptr <abigail::translation_unit> tu;
+static shared_ptr<abigail::config> conf;
+static shared_ptr <tree_scope_decl_map> tree_2_scope_map;
+
+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 ();
+}
+
+static abigail::translation_unit&
+get_cur_tu ()
+{
+ if (!tu)
+ tu.reset (new abigail::translation_unit (main_input_filename));
+
+ return *tu;
+}
+
+static const abigail::config&
+get_conf ()
+{
+ if (!conf)
+ conf.reset (new abigail::config);
+
+ return *conf;
+}
+
+static tree_scope_decl_map&
+get_tree_2_scope_map ()
+{
+ if (!tree_2_scope_map)
+ tree_2_scope_map.reset (new tree_scope_decl_map);
+
+ return *tree_2_scope_map;
+}
+
+static shared_ptr<abigail::scope_decl>
+get_scope (const_tree t)
+{
+ shared_ptr<abigail::scope_decl> nil;
+ if (t == NULL_TREE)
+ return nil;
+
+ 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;
+}
+
+static abigail::decl_base::visibility
+convert_visibility (symbol_visibility v)
+{
+ switch (v)
+ {
+ case VISIBILITY_DEFAULT:
+ return abigail::decl_base::VISIBILITY_DEFAULT;
+ case VISIBILITY_PROTECTED:
+ return abigail::decl_base::VISIBILITY_PROTECTED;
+ case VISIBILITY_HIDDEN:
+ return abigail::decl_base::VISIBILITY_HIDDEN;
+ case VISIBILITY_INTERNAL:
+ return abigail::decl_base::VISIBILITY_INTERNAL;
+ }
+ return abigail::decl_base::VISIBILITY_NONE;
+}
+
+static abigail::location
+convert_location (source_location l)
+{
+ expanded_location e = expand_location (l);
+ return get_cur_tu ().get_loc_mgr ().create_new_location (e.file,
+ e.line,
+ e.column);
+}
+
+static abigail::decl_base::visibility
+decl_visibility (const_tree decl)
+{
+ if (decl == NULL_TREE)
+ return abigail::decl_base::VISIBILITY_NONE;
+ gcc_assert (DECL_P (decl));
+ return convert_visibility (DECL_VISIBILITY (decl));
+}
+
+static abigail::location
+tree_location (const_tree t)
+{
+ if (t != NULL_TREE)
+ {
+ if (DECL_P (t))
+ return convert_location (DECL_SOURCE_LOCATION (t));
+ if (TYPE_P (t))
+ return convert_location (DECL_SOURCE_LOCATION (TYPE_NAME (t)));
+ if (EXPR_P (t) && EXPR_HAS_LOCATION (t))
+ return convert_location (EXPR_LOCATION (t));
+ }
+ return abigail::location ();
+}
+
+static abigail::decl_base::binding
+get_decl_binding (const_tree decl)
+{
+ if (decl != NULL)
+ {
+ gcc_assert (DECL_P (decl));
+
+ if (DECL_WEAK (decl))
+ return abigail::decl_base::BINDING_WEAK;
+ if ((!TYPE_P (CP_DECL_CONTEXT (decl)) && !DECL_NAMESPACE_SCOPE_P (decl))
+ || TREE_CODE (decl) == PARM_DECL)
+ return abigail::decl_base::BINDING_LOCAL;
+ return abigail::decl_base::BINDING_GLOBAL;
+ }
+ 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)
+{
+ if (t == NULL_TREE || !TYPE_P (t))
+ return shared_ptr<abigail::type_decl> ();
+
+ switch (TREE_CODE (t))
+ {
+ case BOOLEAN_TYPE:
+ case INTEGER_TYPE:
+ case NULLPTR_TYPE:
+ case VOID_TYPE:
+ {
+ abigail::location aloc = tree_location (t);
+
+ shared_ptr<abigail::type_decl> type_declaration
+ (new abigail::type_decl (IDENTIFIER_POINTER
+ (DECL_NAME (TYPE_NAME (t))),
+ int_cst_value (TYPE_SIZE (t)),
+ TYPE_ALIGN (t), aloc,
+ IDENTIFIER_POINTER
+ (DECL_ASSEMBLER_NAME (TYPE_NAME (t))),
+ decl_visibility (TYPE_NAME (t))));
+
+ add_decl_to_scope (type_declaration, scope);
+ return type_declaration;
+ }
+ default:
+ break;
+ }
+ return shared_ptr<abigail::type_decl> ();
+}
+
+static shared_ptr<abigail::type_decl>
+gen_type_decl (const_tree t)
+{
+ shared_ptr<abigail::scope_decl> scope = get_scope (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> ();
+}
+
+/* Build a representation of type T, in libabigail. Return true iff
+ the type was emitted. */
+bool
+abi_instr_emit_type (const_tree t)
+{
+ gcc_assert (TYPE_P (t));
+
+ return gen_type_decl (t);
+}
+
+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));
+ }
+ return true;
+}
+
+void
+abi_instr_dump_file ()
+{
+ if (!tu)
+ return;
+
+ string out_path = dump_base_name;
+ out_path += get_conf ().get_tu_instr_suffix ();
+ std::ofstream of (out_path.c_str (), std::ios_base::trunc);
+ if (!of.is_open ())
+ fatal_error ("can%'t open %s for writing: %m", out_path.c_str ());
+
+ bool is_ok = abigail::writer::write_to_ostream (get_cur_tu (), of);
+ of.close ();
+ if (!is_ok)
+ error ("could not dump abi instrumentation to file %s: %m",
+ out_path.c_str ());
+}
+#endif /* HAVE_abigail*/
diff --git a/gcc/cp/abi-instr.h b/gcc/cp/abi-instr.h
new file mode 100644
index 00000000000..29cbec723c1
--- /dev/null
+++ b/gcc/cp/abi-instr.h
@@ -0,0 +1,30 @@
+/* ABI Instrumentation
+ Copyright (C) 2000-2013 Free Software Foundation, Inc.
+ Written by Dodji Seketeli <dodji@redhat.com>
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_ABI_INSTR_H
+#define GCC_ABI_INSTR_H
+
+void abi_instr_init ();
+void abi_instr_finish ();
+bool abi_instr_emit_type (const_tree);
+bool abi_instr_emit_vars (tree *, int);
+void abi_instr_dump_file ();
+
+#endif /* ! GCC_ABI_INSTR_H */
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index c37b4fe5592..3687f425741 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -52,6 +52,7 @@ 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 {
@@ -869,6 +870,8 @@ 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 (vec, len);
return 0;
}
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index e00d25a2a85..9cc5fdae790 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see
#include "c-family/c-objc.h"
#include "tm_p.h"
#include "timevar.h"
+#include "abi-instr.h"
static int interface_strcmp (const char *);
static void init_cp_pragma (void);
@@ -85,6 +86,8 @@ void
cxx_finish (void)
{
c_common_finish ();
+ if (flag_dump_abi)
+ abi_instr_finish();
}
/* A mapping from tree codes to operator name information. */
@@ -241,6 +244,8 @@ cxx_init (void)
init_operators ();
init_method ();
init_error ();
+ if (flag_dump_abi)
+ abi_instr_init ();
current_function_decl = NULL;
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 5ca55d9e58b..c61bb12e8dc 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -296,6 +296,7 @@ Objective-C and Objective-C++ Dialects}.
-fdump-noaddr -fdump-unnumbered -fdump-unnumbered-links @gol
-fdump-translation-unit@r{[}-@var{n}@r{]} @gol
-fdump-class-hierarchy@r{[}-@var{n}@r{]} @gol
+-fdump-abi @gol
-fdump-ipa-all -fdump-ipa-cgraph -fdump-ipa-inline @gol
-fdump-passes @gol
-fdump-statistics @gol
@@ -5878,6 +5879,14 @@ same directory as the output file. If the @samp{-@var{options}} form
is used, @var{options} controls the details of the dump as described
for the @option{-fdump-tree} options.
+@item -fdump-abi @r{(C++ only)}
+@opindex fdump-abi
+Dump an XML representation of the types and declarations that are
+meaningful from an application binary interface standpoint. For
+instance, types and declarations that are local to functions are not
+emitted in the dump. The name of the dump file is made by appending
+@file{.bi} to the name of the input file.
+
@item -fdump-ipa-@var{switch}
@opindex fdump-ipa
Control the dumping at various stages of inter-procedural analysis