diff options
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 29 | ||||
-rw-r--r-- | gcc/cp/Make-lang.in | 2 | ||||
-rw-r--r-- | gcc/cp/cp-lang.c | 2 | ||||
-rw-r--r-- | gcc/cp/cp-objcp-common.h | 2 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 56 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 4 | ||||
-rw-r--r-- | gcc/cp/tree.c | 47 |
8 files changed, 133 insertions, 10 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0a351b2..bac7098 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,32 @@ +2009-09-03 Doug Kwan <dougkwan@google.com> + + * tree.c (cp_fix_function_decl_p): New. + (cp_free_lang_data): New. + +2009-09-03 Diego Novillo <dnovillo@google.com> + + * Make-lang.in (decl2.o): Add dependency on $(POINTER_SET_H). + * decl2.c: Include pointer-set.h. + (collect_candidates_for_java_method_aliases): New. + (cp_write_global_declarations): Call it. + Add local variable CANDIDATES. If set, call + build_java_method_aliases. + (build_java_method_aliases): Add argument CANDIDATES. + Use it to determine if FNDECL should get a hidden alias. + * cp-objcp-common.h (LANG_HOOKS_FREE_LANG_DATA): Define. + * cp-tree.h (cp_free_lang_data): Declare. + +2009-09-03 Richard Guenther <rguenther@suse.de> + + * method.c (use_thunk): Use cgraph_finalize_function to hand + off thunks to the cgraph. + * semantics.c (emit_associated_thunks): Do not emit thunks + for really extern functions. + +2009-09-03 Diego Novillo <dnovillo@google.com> + + * cp-lang.c (lang_hooks): Remove const qualifier. + 2009-09-02 Jason Merrill <jason@redhat.com> * semantics.c (describable_type): Don't pretend to be in a template. diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index a3190f4..356565f 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -257,7 +257,7 @@ cp/decl.o: cp/decl.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) cp/decl.h \ debug.h gt-cp-decl.h $(TIMEVAR_H) $(TREE_FLOW_H) $(TARGET_H) $(PLUGIN_H) cp/decl2.o: cp/decl2.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) cp/decl.h $(EXPR_H) \ output.h except.h toplev.h $(RTL_H) $(C_COMMON_H) gt-cp-decl2.h $(CGRAPH_H) \ - $(C_PRAGMA_H) $(TREE_DUMP_H) intl.h $(TARGET_H) $(GIMPLE_H) + $(C_PRAGMA_H) $(TREE_DUMP_H) intl.h $(TARGET_H) $(GIMPLE_H) $(POINTER_SET_H) cp/cp-objcp-common.o : cp/cp-objcp-common.c $(CONFIG_H) $(SYSTEM_H) \ coretypes.h $(TM_H) $(TREE_H) $(CXX_TREE_H) $(C_COMMON_H) toplev.h \ langhooks.h $(LANGHOOKS_DEF_H) $(DIAGNOSTIC_H) debug.h \ diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c index 0278028..f818e5b 100644 --- a/gcc/cp/cp-lang.c +++ b/gcc/cp/cp-lang.c @@ -73,7 +73,7 @@ static enum classify_record cp_classify_record (tree type); #define LANG_HOOKS_INIT_TS cp_init_ts /* Each front end provides its own lang hook initializer. */ -const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; +struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; /* Lang hook routines common to C++ and ObjC++ appear in cp/cp-objcp-common.c; there should be very few routines below. */ diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h index 19fce29..818540c 100644 --- a/gcc/cp/cp-objcp-common.h +++ b/gcc/cp/cp-objcp-common.h @@ -32,6 +32,8 @@ extern bool cp_function_decl_explicit_p (tree decl); specific to C++ or ObjC++ go in cp/cp-lang.c and objcp/objcp-lang.c, respectively. */ +#undef LANG_HOOKS_FREE_LANG_DATA +#define LANG_HOOKS_FREE_LANG_DATA cp_free_lang_data #undef LANG_HOOKS_TREE_SIZE #define LANG_HOOKS_TREE_SIZE cp_tree_size #undef LANG_HOOKS_FINISH diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index a76b2d2..23b41d3 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4891,6 +4891,7 @@ extern tree finish_decltype_type (tree, bool); extern tree finish_trait_expr (enum cp_trait_kind, tree, tree); /* in tree.c */ +void cp_free_lang_data (tree t); extern tree force_target_expr (tree, tree); extern tree build_target_expr_with_type (tree, tree); extern void lang_check_failed (const char *, int, diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index da9c2b7..cc4317a 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -52,6 +52,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-dump.h" #include "intl.h" #include "gimple.h" +#include "pointer-set.h" extern cpp_reader *parse_in; @@ -3288,27 +3289,60 @@ cxx_callgraph_analyze_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED) /* Java requires that we be able to reference a local address for a method, and not be confused by PLT entries. If hidden aliases are - supported, emit one for each java function that we've emitted. */ + supported, collect and return all the functions for which we should + emit a hidden alias. */ -static void -build_java_method_aliases (void) +static struct pointer_set_t * +collect_candidates_for_java_method_aliases (void) { struct cgraph_node *node; + struct pointer_set_t *candidates = NULL; #ifndef HAVE_GAS_HIDDEN - return; + return candidates; #endif for (node = cgraph_nodes; node ; node = node->next) { tree fndecl = node->decl; - if (TREE_ASM_WRITTEN (fndecl) - && DECL_CONTEXT (fndecl) + if (DECL_CONTEXT (fndecl) && TYPE_P (DECL_CONTEXT (fndecl)) && TYPE_FOR_JAVA (DECL_CONTEXT (fndecl)) && TARGET_USE_LOCAL_THUNK_ALIAS_P (fndecl)) { + if (candidates == NULL) + candidates = pointer_set_create (); + pointer_set_insert (candidates, fndecl); + } + } + + return candidates; +} + + +/* Java requires that we be able to reference a local address for a + method, and not be confused by PLT entries. If hidden aliases are + supported, emit one for each java function that we've emitted. + CANDIDATES is the set of FUNCTION_DECLs that were gathered + by collect_candidates_for_java_method_aliases. */ + +static void +build_java_method_aliases (struct pointer_set_t *candidates) +{ + struct cgraph_node *node; + +#ifndef HAVE_GAS_HIDDEN + return; +#endif + + for (node = cgraph_nodes; node ; node = node->next) + { + tree fndecl = node->decl; + + if (TREE_ASM_WRITTEN (fndecl) + && pointer_set_contains (candidates, fndecl)) + { /* Mangle the name in a predictable way; we need to reference this from a java compiled object file. */ tree oid, nid, alias; @@ -3379,6 +3413,7 @@ cp_write_global_declarations (void) unsigned ssdf_count = 0; int retries = 0; tree decl; + struct pointer_set_t *candidates; locus = input_location; at_eof = 1; @@ -3676,6 +3711,9 @@ cp_write_global_declarations (void) linkage now. */ pop_lang_context (); + /* Collect candidates for Java hidden aliases. */ + candidates = collect_candidates_for_java_method_aliases (); + cgraph_finalize_compilation_unit (); /* Now, issue warnings about static, but not defined, functions, @@ -3690,7 +3728,11 @@ cp_write_global_declarations (void) } /* Generate hidden aliases for Java. */ - build_java_method_aliases (); + if (candidates) + { + build_java_method_aliases (candidates); + pointer_set_destroy (candidates); + } finish_repo (); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 1e5255e8..477140c 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -3186,7 +3186,9 @@ emit_associated_thunks (tree fn) is so that you can know statically the entire set of thunks that will ever be needed for a given virtual function, thereby enabling you to output all the thunks with the function itself. */ - if (DECL_VIRTUAL_P (fn)) + if (DECL_VIRTUAL_P (fn) + /* Do not emit thunks for extern template instantiations. */ + && ! DECL_REALLY_EXTERN (fn)) { tree thunk; diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index f09b036..808a18a 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -3030,6 +3030,53 @@ cast_valid_in_integral_constant_expression_p (tree type) || type == error_mark_node); } +/* Return true if we need to fix linkage information of DECL. */ + +static bool +cp_fix_function_decl_p (tree decl) +{ + /* Skip if DECL is not externally visible. */ + if (!TREE_PUBLIC (decl)) + return false; + + /* We need to fix DECL if it a appears to be exported but with no + function body. Thunks do not have CFGs and we may need to + handle them specially later. */ + if (!gimple_has_body_p (decl) + && !DECL_THUNK_P (decl) + && !DECL_EXTERNAL (decl)) + return true; + + return false; +} + +/* Clean the C++ specific parts of the tree T. */ + +void +cp_free_lang_data (tree t) +{ + if (TREE_CODE (t) == METHOD_TYPE + || TREE_CODE (t) == FUNCTION_TYPE) + { + /* Default args are not interesting anymore. */ + tree argtypes = TYPE_ARG_TYPES (t); + while (argtypes) + { + TREE_PURPOSE (argtypes) = 0; + argtypes = TREE_CHAIN (argtypes); + } + } + else if (TREE_CODE (t) == FUNCTION_DECL + && cp_fix_function_decl_p (t)) + { + /* If T is used in this translation unit at all, the definition + must exist somewhere else since we have decided to not emit it + in this TU. So make it an external reference. */ + DECL_EXTERNAL (t) = 1; + TREE_STATIC (t) = 0; + } +} + #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007) /* Complain that some language-specific thing hanging off a tree |