aboutsummaryrefslogtreecommitdiff
path: root/gcc/java
diff options
context:
space:
mode:
authorRichard Henderson <rth@gcc.gnu.org>2005-05-25 15:08:31 -0700
committerRichard Henderson <rth@gcc.gnu.org>2005-05-25 15:08:31 -0700
commit6de33afa78e19bee96963ec3771c352a488287e1 (patch)
tree047bbcbef9a1b2d83cf20f62170c7df12ca50eff /gcc/java
parent81fc305201e8913727cb61303c4812730a95c59c (diff)
downloadgcc-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/ChangeLog30
-rw-r--r--gcc/java/Make-lang.in2
-rw-r--r--gcc/java/class.c39
-rw-r--r--gcc/java/decl.c33
-rw-r--r--gcc/java/java-tree.h16
-rw-r--r--gcc/java/lang.c3
-rw-r--r--gcc/java/mangle.c124
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;
}