diff options
author | Dodji Seketeli <dodji@seketeli.org> | 2013-05-24 05:52:47 +0200 |
---|---|---|
committer | Dodji Seketeli <dodji@seketeli.org> | 2013-05-24 22:41:06 +0200 |
commit | 40b181f8e08678387d067f7692fe2d5f63ffaa45 (patch) | |
tree | c30aa2813e229b17b06f36793bbea31350c06961 | |
parent | 431b8fa5b0870562e91170b96430312d37ec0a96 (diff) | |
download | gcc-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.opt | 4 | ||||
-rw-r--r-- | gcc/cp/Make-lang.in | 6 | ||||
-rw-r--r-- | gcc/cp/abi-instr.cc | 300 | ||||
-rw-r--r-- | gcc/cp/abi-instr.h | 30 | ||||
-rw-r--r-- | gcc/cp/decl.c | 3 | ||||
-rw-r--r-- | gcc/cp/lex.c | 5 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 9 |
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 |