diff options
author | Richard Henderson <rth@gcc.gnu.org> | 2005-05-25 15:08:31 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2005-05-25 15:08:31 -0700 |
commit | 6de33afa78e19bee96963ec3771c352a488287e1 (patch) | |
tree | 047bbcbef9a1b2d83cf20f62170c7df12ca50eff /gcc/java | |
parent | 81fc305201e8913727cb61303c4812730a95c59c (diff) | |
download | gcc-6de33afa78e19bee96963ec3771c352a488287e1.zip gcc-6de33afa78e19bee96963ec3771c352a488287e1.tar.gz gcc-6de33afa78e19bee96963ec3771c352a488287e1.tar.bz2 |
re PR libgcj/21692 (unexpected java.lang.NoClassDefFoundError)
PR libgcj/21692
cp/
* cp-tree.h (make_alias_for): Declare.
* decl2.c (build_java_method_aliases): New.
(cp_finish_file): Call it.
* method.c (make_alias_for): Split out from ...
(make_alias_for_thunk): ... here.
java/
* Make-lang.in (java/mangle.o): Depend on LANGHOOKS_DEF_H.
* class.c (build_class_ref): Set DECL_CLASS_FIELD_P and
DECL_CONTEXT; avoid pushdecl_top_level.
(build_dtable_decl): Set DECL_VTABLE_P and DECL_CONTEXT.
(layout_class): Don't SET_DECL_ASSEMBLER_NAME.
(layout_class_method): Likewise.
* decl.c (java_mark_cni_decl_local): New.
(java_mark_class_local): Use it.
* java-tree.h (DECL_LOCAL_CNI_METHOD_P): New.
(DECL_CLASS_FIELD_P, DECL_VTABLE_P): New.
(struct lang_decl_func): Add local_cni;
(struct lang_decl_var): Add class_field, vtable.
(java_mangle_decl): Declare.
* lang.c (LANG_HOOKS_SET_DECL_ASSEMBLER_NAME): New.
* mangle.c: Remove dup obstack.h; include langhooks-def.h.
(mangle_obstack_1): New.
(java_mangle_decl): Remove obstack argument. Call mangle_class_field,
mangle_vtable, and mangle_local_cni_method_decl. Fall back to
lhd_set_decl_assembler_name for things that don't need mangling.
(mangle_class_field): Rename from java_mangle_class_field, make
static, don't call init_mangling or finish_mangling.
(mangle_vtable): Similarly.
(mangle_local_cni_method_decl): New.
(init_mangling): Remove obstack argument. Use &mangle_obstack_1,
gcc_assert, and MANGLE_RAW_STRING.
(finish_mangling): Use gcc_assert, remove if 0 debugging code.
From-SVN: r100171
Diffstat (limited to 'gcc/java')
-rw-r--r-- | gcc/java/ChangeLog | 30 | ||||
-rw-r--r-- | gcc/java/Make-lang.in | 2 | ||||
-rw-r--r-- | gcc/java/class.c | 39 | ||||
-rw-r--r-- | gcc/java/decl.c | 33 | ||||
-rw-r--r-- | gcc/java/java-tree.h | 16 | ||||
-rw-r--r-- | gcc/java/lang.c | 3 | ||||
-rw-r--r-- | gcc/java/mangle.c | 124 |
7 files changed, 176 insertions, 71 deletions
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index a9bcf44..82a2ba8 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,33 @@ +2005-05-25 Richard Henderson <rth@redhat.com> + + PR libgcj/21692 + * Make-lang.in (java/mangle.o): Depend on LANGHOOKS_DEF_H. + * class.c (build_class_ref): Set DECL_CLASS_FIELD_P and + DECL_CONTEXT; avoid pushdecl_top_level. + (build_dtable_decl): Set DECL_VTABLE_P and DECL_CONTEXT. + (layout_class): Don't SET_DECL_ASSEMBLER_NAME. + (layout_class_method): Likewise. + * decl.c (java_mark_cni_decl_local): New. + (java_mark_class_local): Use it. + * java-tree.h (DECL_LOCAL_CNI_METHOD_P): New. + (DECL_CLASS_FIELD_P, DECL_VTABLE_P): New. + (struct lang_decl_func): Add local_cni; + (struct lang_decl_var): Add class_field, vtable. + (java_mangle_decl): Declare. + * lang.c (LANG_HOOKS_SET_DECL_ASSEMBLER_NAME): New. + * mangle.c: Remove dup obstack.h; include langhooks-def.h. + (mangle_obstack_1): New. + (java_mangle_decl): Remove obstack argument. Call mangle_class_field, + mangle_vtable, and mangle_local_cni_method_decl. Fall back to + lhd_set_decl_assembler_name for things that don't need mangling. + (mangle_class_field): Rename from java_mangle_class_field, make + static, don't call init_mangling or finish_mangling. + (mangle_vtable): Similarly. + (mangle_local_cni_method_decl): New. + (init_mangling): Remove obstack argument. Use &mangle_obstack_1, + gcc_assert, and MANGLE_RAW_STRING. + (finish_mangling): Use gcc_assert, remove if 0 debugging code. + 2005-05-25 DJ Delorie <dj@redhat.com> * class.c (set_constant_value): Move warning control from if() to diff --git a/gcc/java/Make-lang.in b/gcc/java/Make-lang.in index 17aa70a..f4831b6 100644 --- a/gcc/java/Make-lang.in +++ b/gcc/java/Make-lang.in @@ -340,7 +340,7 @@ java/lang.o: java/lang.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h input.h \ toplev.h $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(EXPR_H) diagnostic.h \ langhooks.h $(LANGHOOKS_DEF_H) gt-java-lang.h opts.h options.h java/mangle.o: java/mangle.c $(CONFIG_H) java/jcf.h $(JAVA_TREE_H) $(SYSTEM_H) \ - coretypes.h $(TM_H) toplev.h $(GGC_H) gt-java-mangle.h + coretypes.h $(TM_H) toplev.h $(GGC_H) gt-java-mangle.h $(LANGHOOKS_DEF_H) java/mangle_name.o: java/mangle_name.c $(CONFIG_H) java/jcf.h $(JAVA_TREE_H) \ $(SYSTEM_H) coretypes.h $(TM_H) toplev.h $(GGC_H) java/resource.o: java/resource.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ diff --git a/gcc/java/class.c b/gcc/java/class.c index 3e8ae26..88ca1f4 100644 --- a/gcc/java/class.c +++ b/gcc/java/class.c @@ -970,10 +970,13 @@ build_class_ref (tree type) DECL_ARTIFICIAL (decl) = 1; if (is_compiled == 1) DECL_EXTERNAL (decl) = 1; - SET_DECL_ASSEMBLER_NAME (decl, - java_mangle_class_field - (&temporary_obstack, type)); - pushdecl_top_level (decl); + MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl); + DECL_CLASS_FIELD_P (decl) = 1; + DECL_CONTEXT (decl) = type; + + /* ??? We want to preserve the DECL_CONTEXT we set just above, + that that means not calling pushdecl_top_level. */ + IDENTIFIER_GLOBAL_VALUE (decl_name) = decl; } } else @@ -1969,7 +1972,7 @@ is_compiled_class (tree class) tree build_dtable_decl (tree type) { - tree dtype; + tree dtype, decl; /* We need to build a new dtable type so that its size is uniquely computed when we're dealing with the class for real and not just @@ -2017,8 +2020,12 @@ build_dtable_decl (tree type) else dtype = dtable_type; - return build_decl (VAR_DECL, - java_mangle_vtable (&temporary_obstack, type), dtype); + decl = build_decl (VAR_DECL, get_identifier ("vt$"), dtype); + DECL_CONTEXT (decl) = type; + MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl); + DECL_VTABLE_P (decl) = 1; + + return decl; } /* Pre-pend the TYPE_FIELDS of THIS_CLASS with a dummy FIELD_DECL for the @@ -2092,7 +2099,6 @@ void layout_class (tree this_class) { tree super_class = CLASSTYPE_SUPER (this_class); - tree field; class_list = tree_cons (this_class, NULL_TREE, class_list); if (CLASS_BEING_LAIDOUT (this_class)) @@ -2140,18 +2146,6 @@ layout_class (tree this_class) push_super_field (this_class, maybe_super_class); } - for (field = TYPE_FIELDS (this_class); - field != NULL_TREE; field = TREE_CHAIN (field)) - { - if (FIELD_STATIC (field)) - { - /* Set DECL_ASSEMBLER_NAME to something suitably mangled. */ - SET_DECL_ASSEMBLER_NAME (field, - java_mangle_decl - (&temporary_obstack, field)); - } - } - layout_type (this_class); /* Also recursively load/layout any superinterfaces, but only if @@ -2319,11 +2313,6 @@ layout_class_method (tree this_class, tree super_class, compiled into this object file. */ DECL_EXTERNAL (method_decl) = 1; - /* This is a good occasion to mangle the method's name */ - SET_DECL_ASSEMBLER_NAME (method_decl, - java_mangle_decl (&temporary_obstack, - method_decl)); - if (ID_INIT_P (method_name)) { const char *p = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class))); diff --git a/gcc/java/decl.c b/gcc/java/decl.c index 5b693cb..a31b668 100644 --- a/gcc/java/decl.c +++ b/gcc/java/decl.c @@ -2133,6 +2133,30 @@ java_mark_decl_local (tree decl) make_decl_rtl (decl); } +/* Given appropriate target support, G++ will emit hidden aliases for native + methods. Using this hidden name is required for proper operation of + _Jv_Method::ncode, but it doesn't hurt to use it everywhere. Look for + proper target support, then mark the method for aliasing. */ + +static void +java_mark_cni_decl_local (tree decl) +{ + /* Setting DECL_LOCAL_CNI_METHOD_P changes the behaviour of the mangler. + We expect that we should not yet have referenced this decl in a + context that requires it. Check this invariant even if we don't have + support for hidden aliases. */ + gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl)); + +#if !defined(HAVE_GAS_HIDDEN) || !defined(ASM_OUTPUT_DEF) + return; +#endif + + DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN; + DECL_LOCAL_CNI_METHOD_P (decl) = 1; +} + +/* Use the preceeding two functions and mark all members of the class. */ + void java_mark_class_local (tree class) { @@ -2143,8 +2167,13 @@ java_mark_class_local (tree class) java_mark_decl_local (t); for (t = TYPE_METHODS (class); t ; t = TREE_CHAIN (t)) - if (!METHOD_ABSTRACT (t) && (!METHOD_NATIVE (t) || flag_jni)) - java_mark_decl_local (t); + if (!METHOD_ABSTRACT (t)) + { + if (METHOD_NATIVE (t) && !flag_jni) + java_mark_cni_decl_local (t); + else + java_mark_decl_local (t); + } } /* Add a statement to a compound_expr. */ diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h index 68eb1d6..f919741 100644 --- a/gcc/java/java-tree.h +++ b/gcc/java/java-tree.h @@ -818,6 +818,9 @@ union lang_tree_node #define DECL_FIXED_CONSTRUCTOR_P(DECL) \ (DECL_LANG_SPECIFIC(DECL)->u.f.fixed_ctor) +#define DECL_LOCAL_CNI_METHOD_P(NODE) \ + (DECL_LANG_SPECIFIC (NODE)->u.f.local_cni) + /* A constructor that calls this. */ #define DECL_INIT_CALLS_THIS(DECL) \ (DECL_LANG_SPECIFIC(DECL)->u.f.init_calls_this) @@ -931,6 +934,12 @@ union lang_tree_node (DECL_LANG_SPECIFIC (NODE)->u.v.freed) #define LOCAL_SLOT_P(NODE) \ (DECL_LANG_SPECIFIC (NODE)->u.v.local_slot) + +#define DECL_CLASS_FIELD_P(NODE) \ + (DECL_LANG_SPECIFIC (NODE)->u.v.class_field) +#define DECL_VTABLE_P(NODE) \ + (DECL_LANG_SPECIFIC (NODE)->u.v.vtable) + /* Create a DECL_LANG_SPECIFIC if necessary. */ #define MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC(T) \ if (DECL_LANG_SPECIFIC (T) == NULL) \ @@ -993,7 +1002,8 @@ struct lang_decl_func GTY(()) unsigned int invisible : 1; /* Set for methods we generate internally but which shouldn't be written to the .class file. */ - unsigned int dummy:1; + unsigned int dummy : 1; + unsigned int local_cni : 1; /* Decl needs mangle_local_cni_method. */ }; struct treetreehash_entry GTY(()) @@ -1037,6 +1047,8 @@ struct lang_decl_var GTY(()) unsigned int cif : 1; /* True: decl is a class initialization flag */ unsigned int freed : 1; /* Decl is no longer in scope. */ unsigned int local_slot : 1; /* Decl is a temporary in the stack frame. */ + unsigned int class_field : 1; /* Decl needs mangle_class_field. */ + unsigned int vtable : 1; /* Decl needs mangle_vtable. */ }; /* This is what 'lang_decl' really points to. */ @@ -1367,7 +1379,7 @@ extern void init_jcf_parse (void); extern void init_src_parse (void); extern int cxx_keyword_p (const char *, int); -extern tree java_mangle_decl (struct obstack *, tree); +extern void java_mangle_decl (tree); extern tree java_mangle_class_field (struct obstack *, tree); extern tree java_mangle_vtable (struct obstack *, tree); extern void append_gpp_mangled_name (const char *, int); diff --git a/gcc/java/lang.c b/gcc/java/lang.c index e0d2672..4ade936 100644 --- a/gcc/java/lang.c +++ b/gcc/java/lang.c @@ -213,6 +213,9 @@ struct language_function GTY(()) #undef LANG_HOOKS_CLEAR_BINDING_STACK #define LANG_HOOKS_CLEAR_BINDING_STACK java_clear_binding_stack +#undef LANG_HOOKS_SET_DECL_ASSEMBLER_NAME +#define LANG_HOOKS_SET_DECL_ASSEMBLER_NAME java_mangle_decl + /* Each front end provides its own. */ const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; diff --git a/gcc/java/mangle.c b/gcc/java/mangle.c index e0b53a1..22a3918 100644 --- a/gcc/java/mangle.c +++ b/gcc/java/mangle.c @@ -35,11 +35,14 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "java-tree.h" #include "obstack.h" #include "toplev.h" -#include "obstack.h" #include "ggc.h" +#include "langhooks-def.h" +static void mangle_class_field (tree); +static void mangle_vtable (tree); static void mangle_field_decl (tree); static void mangle_method_decl (tree); +static void mangle_local_cni_method_decl (tree); static void mangle_type (tree); static void mangle_pointer_type (tree); @@ -55,15 +58,15 @@ static void set_type_package_list (tree); static int entry_match_pointer_p (tree, int); static void emit_compression_string (int); -static void init_mangling (struct obstack *); +static void init_mangling (void); static tree finish_mangling (void); static void compression_table_add (tree); static void mangle_member_name (tree); -/* We use an incoming obstack, always to be provided to the interface - functions. */ +static struct obstack mangle_obstack_1; struct obstack *mangle_obstack; + #define MANGLE_RAW_STRING(S) \ obstack_grow (mangle_obstack, (S), sizeof (S)-1) @@ -73,46 +76,75 @@ static GTY(()) tree atms; /* This is the mangling interface: a decl, a class field (.class) and the vtable. */ -tree -java_mangle_decl (struct obstack *obstack, tree decl) +void +java_mangle_decl (tree decl) { - init_mangling (obstack); - switch (TREE_CODE (decl)) + /* A copy of the check from the beginning of lhd_set_decl_assembler_name. + Only FUNCTION_DECLs and VAR_DECLs for variables with static storage + duration need a real DECL_ASSEMBLER_NAME. */ + gcc_assert (TREE_CODE (decl) == FUNCTION_DECL + || (TREE_CODE (decl) == VAR_DECL + && (TREE_STATIC (decl) + || DECL_EXTERNAL (decl) + || TREE_PUBLIC (decl)))); + + /* Mangling only applies to class members. */ + if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl))) { - case VAR_DECL: - mangle_field_decl (decl); - break; - case FUNCTION_DECL: - mangle_method_decl (decl); - break; - default: - internal_error ("can't mangle %s", tree_code_name [TREE_CODE (decl)]); + init_mangling (); + switch (TREE_CODE (decl)) + { + case VAR_DECL: + if (DECL_LANG_SPECIFIC (decl)) + { + if (DECL_CLASS_FIELD_P (decl)) + { + mangle_class_field (DECL_CONTEXT (decl)); + break; + } + else if (DECL_VTABLE_P (decl)) + { + mangle_vtable (DECL_CONTEXT (decl)); + break; + } + } + mangle_field_decl (decl); + break; + + case FUNCTION_DECL: + if (DECL_LANG_SPECIFIC (decl) && DECL_LOCAL_CNI_METHOD_P (decl)) + mangle_local_cni_method_decl (decl); + else + mangle_method_decl (decl); + break; + + default: + gcc_unreachable (); + } + SET_DECL_ASSEMBLER_NAME (decl, finish_mangling ()); } - return finish_mangling (); + else + lhd_set_decl_assembler_name (decl); } -tree -java_mangle_class_field (struct obstack *obstack, tree type) +/* Beginning of the helper functions */ + +static void +mangle_class_field (tree type) { - init_mangling (obstack); mangle_record_type (type, /* for_pointer = */ 0); MANGLE_RAW_STRING ("6class$"); obstack_1grow (mangle_obstack, 'E'); - return finish_mangling (); } -tree -java_mangle_vtable (struct obstack *obstack, tree type) +static void +mangle_vtable (tree type) { - init_mangling (obstack); MANGLE_RAW_STRING ("TV"); mangle_record_type (type, /* for_pointer = */ 0); obstack_1grow (mangle_obstack, 'E'); - return finish_mangling (); } -/* Beginning of the helper functions */ - /* This mangles a field decl */ static void @@ -167,6 +199,18 @@ mangle_method_decl (tree mdecl) } } +/* This mangles a CNI method for a local class. If the target supports + hidden aliases, then G++ will have generated one for us. It is the + responsibility of java_mark_class_local to check target support, since + we need to set DECL_VISIBILITY (or not) much earlier. */ + +static void +mangle_local_cni_method_decl (tree decl) +{ + MANGLE_RAW_STRING ("GA"); + mangle_method_decl (decl); +} + /* This mangles a member name, like a function name or a field name. Handle cases were `name' is a C++ keyword. Return a nonzero value if unicode encoding was required. */ @@ -585,17 +629,19 @@ compression_table_add (tree type) /* Mangling initialization routine. */ static void -init_mangling (struct obstack *obstack) +init_mangling (void) { - mangle_obstack = obstack; - if (!compression_table) - compression_table = make_tree_vec (10); - else - /* Mangling already in progress. */ - abort (); + if (!mangle_obstack) + { + mangle_obstack = &mangle_obstack_1; + gcc_obstack_init (mangle_obstack); + } + + gcc_assert (compression_table == NULL); + compression_table = make_tree_vec (10); /* Mangled name are to be suffixed */ - obstack_grow (mangle_obstack, "_Z", 2); + MANGLE_RAW_STRING ("_Z"); } /* Mangling finalization routine. The mangled name is returned as a @@ -606,18 +652,14 @@ finish_mangling (void) { tree result; - if (!compression_table) - /* Mangling already finished. */ - abort (); + gcc_assert (compression_table); compression_table = NULL_TREE; compression_next = 0; obstack_1grow (mangle_obstack, '\0'); result = get_identifier (obstack_base (mangle_obstack)); obstack_free (mangle_obstack, obstack_base (mangle_obstack)); -#if 0 - printf ("// %s\n", IDENTIFIER_POINTER (result)); -#endif + return result; } |