Commit 6de33afa by Richard Henderson

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
parent 81fc3052
2005-05-25 Richard Henderson <rth@redhat.com>
PR libgcj/21692
* 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.
2005-05-25 Volker Reichelt <reichelt@igpm.rwth-aachen.de> 2005-05-25 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
PR c++/21686 PR c++/21686
...@@ -248,8 +257,8 @@ ...@@ -248,8 +257,8 @@
2005-05-02 Paolo Bonzini <bonzini@gnu.org> 2005-05-02 Paolo Bonzini <bonzini@gnu.org>
* semantics.c (finish_call_expr): Call resolve_overloaded_builtin * semantics.c (finish_call_expr): Call resolve_overloaded_builtin
for BUILT_IN_MD built-ins. for BUILT_IN_MD built-ins.
2005-05-02 Michael Matz <matz@suse.de> 2005-05-02 Michael Matz <matz@suse.de>
...@@ -310,7 +319,7 @@ ...@@ -310,7 +319,7 @@
2005-04-22 Per Bothner <per@bothner.com> 2005-04-22 Per Bothner <per@bothner.com>
* decl.c (make_rtl_for_nonlocal_decl): Don't try get_fileinfo if * decl.c (make_rtl_for_nonlocal_decl): Don't try get_fileinfo if
input_filename is NULL, as it is for (say) __PRETTY_FUNCTION__. input_filename is NULL, as it is for (say) __PRETTY_FUNCTION__.
2005-04-22 Alexandre Oliva <aoliva@redhat.com> 2005-04-22 Alexandre Oliva <aoliva@redhat.com>
......
...@@ -3923,6 +3923,7 @@ extern void synthesize_method (tree); ...@@ -3923,6 +3923,7 @@ extern void synthesize_method (tree);
extern tree implicitly_declare_fn (special_function_kind, tree, bool); extern tree implicitly_declare_fn (special_function_kind, tree, bool);
extern tree lazily_declare_fn (special_function_kind, tree); extern tree lazily_declare_fn (special_function_kind, tree);
extern tree skip_artificial_parms_for (tree, tree); extern tree skip_artificial_parms_for (tree, tree);
extern tree make_alias_for (tree, tree);
/* In optimize.c */ /* In optimize.c */
extern bool maybe_clone_body (tree); extern bool maybe_clone_body (tree);
......
...@@ -2731,6 +2731,50 @@ cxx_callgraph_analyze_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, ...@@ -2731,6 +2731,50 @@ cxx_callgraph_analyze_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
return NULL; return NULL;
} }
/* 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. */
static void
build_java_method_aliases (void)
{
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)
&& DECL_CONTEXT (fndecl)
&& TYPE_P (DECL_CONTEXT (fndecl))
&& TYPE_FOR_JAVA (DECL_CONTEXT (fndecl))
&& TARGET_USE_LOCAL_THUNK_ALIAS_P (fndecl))
{
/* Mangle the name in a predictable way; we need to reference
this from a java compiled object file. */
tree oid, nid, alias;
const char *oname;
char *nname;
oid = DECL_ASSEMBLER_NAME (fndecl);
oname = IDENTIFIER_POINTER (oid);
gcc_assert (oname[0] == '_' && oname[1] == 'Z');
nname = ACONCAT (("_ZGA", oname+2, NULL));
nid = get_identifier (nname);
alias = make_alias_for (fndecl, nid);
TREE_PUBLIC (alias) = 1;
DECL_VISIBILITY (alias) = VISIBILITY_HIDDEN;
assemble_alias (alias, oid);
}
}
}
/* This routine is called from the last rule in yyparse (). /* This routine is called from the last rule in yyparse ().
Its job is to create all the code needed to initialize and Its job is to create all the code needed to initialize and
destroy the global aggregates. We do the destruction destroy the global aggregates. We do the destruction
...@@ -3062,6 +3106,9 @@ cp_finish_file (void) ...@@ -3062,6 +3106,9 @@ cp_finish_file (void)
check_global_declarations (VEC_address (tree, pending_statics), check_global_declarations (VEC_address (tree, pending_statics),
VEC_length (tree, pending_statics)); VEC_length (tree, pending_statics));
/* Generate hidden aliases for Java. */
build_java_method_aliases ();
finish_repo (); finish_repo ();
/* The entire file is now complete. If requested, dump everything /* The entire file is now complete. If requested, dump everything
......
...@@ -258,16 +258,10 @@ static GTY (()) int thunk_labelno; ...@@ -258,16 +258,10 @@ static GTY (()) int thunk_labelno;
/* Create a static alias to function. */ /* Create a static alias to function. */
static tree tree
make_alias_for_thunk (tree function) make_alias_for (tree function, tree newid)
{ {
tree alias; tree alias = build_decl (FUNCTION_DECL, newid, TREE_TYPE (function));
char buf[256];
ASM_GENERATE_INTERNAL_LABEL (buf, "LTHUNK", thunk_labelno);
thunk_labelno++;
alias = build_decl (FUNCTION_DECL, get_identifier (buf),
TREE_TYPE (function));
DECL_LANG_SPECIFIC (alias) = DECL_LANG_SPECIFIC (function); DECL_LANG_SPECIFIC (alias) = DECL_LANG_SPECIFIC (function);
cxx_dup_lang_specific_decl (alias); cxx_dup_lang_specific_decl (alias);
DECL_CONTEXT (alias) = NULL; DECL_CONTEXT (alias) = NULL;
...@@ -296,8 +290,23 @@ make_alias_for_thunk (tree function) ...@@ -296,8 +290,23 @@ make_alias_for_thunk (tree function)
TREE_USED (alias) = 1; TREE_USED (alias) = 1;
SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias)); SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias));
TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1; TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1;
return alias;
}
static tree
make_alias_for_thunk (tree function)
{
tree alias;
char buf[256];
ASM_GENERATE_INTERNAL_LABEL (buf, "LTHUNK", thunk_labelno);
thunk_labelno++;
alias = make_alias_for (function, get_identifier (buf));
if (!flag_syntax_only) if (!flag_syntax_only)
assemble_alias (alias, DECL_ASSEMBLER_NAME (function)); assemble_alias (alias, DECL_ASSEMBLER_NAME (function));
return alias; return alias;
} }
......
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> 2005-05-25 DJ Delorie <dj@redhat.com>
* class.c (set_constant_value): Move warning control from if() to * class.c (set_constant_value): Move warning control from if() to
......
...@@ -340,7 +340,7 @@ java/lang.o: java/lang.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h input.h \ ...@@ -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 \ 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 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) \ 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) \ 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) $(SYSTEM_H) coretypes.h $(TM_H) toplev.h $(GGC_H)
java/resource.o: java/resource.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ java/resource.o: java/resource.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
......
...@@ -970,10 +970,13 @@ build_class_ref (tree type) ...@@ -970,10 +970,13 @@ build_class_ref (tree type)
DECL_ARTIFICIAL (decl) = 1; DECL_ARTIFICIAL (decl) = 1;
if (is_compiled == 1) if (is_compiled == 1)
DECL_EXTERNAL (decl) = 1; DECL_EXTERNAL (decl) = 1;
SET_DECL_ASSEMBLER_NAME (decl, MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
java_mangle_class_field DECL_CLASS_FIELD_P (decl) = 1;
(&temporary_obstack, type)); DECL_CONTEXT (decl) = type;
pushdecl_top_level (decl);
/* ??? 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 else
...@@ -1969,7 +1972,7 @@ is_compiled_class (tree class) ...@@ -1969,7 +1972,7 @@ is_compiled_class (tree class)
tree tree
build_dtable_decl (tree type) build_dtable_decl (tree type)
{ {
tree dtype; tree dtype, decl;
/* We need to build a new dtable type so that its size is uniquely /* 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 computed when we're dealing with the class for real and not just
...@@ -2017,8 +2020,12 @@ build_dtable_decl (tree type) ...@@ -2017,8 +2020,12 @@ build_dtable_decl (tree type)
else else
dtype = dtable_type; dtype = dtable_type;
return build_decl (VAR_DECL, decl = build_decl (VAR_DECL, get_identifier ("vt$"), dtype);
java_mangle_vtable (&temporary_obstack, type), 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 /* Pre-pend the TYPE_FIELDS of THIS_CLASS with a dummy FIELD_DECL for the
...@@ -2092,7 +2099,6 @@ void ...@@ -2092,7 +2099,6 @@ void
layout_class (tree this_class) layout_class (tree this_class)
{ {
tree super_class = CLASSTYPE_SUPER (this_class); tree super_class = CLASSTYPE_SUPER (this_class);
tree field;
class_list = tree_cons (this_class, NULL_TREE, class_list); class_list = tree_cons (this_class, NULL_TREE, class_list);
if (CLASS_BEING_LAIDOUT (this_class)) if (CLASS_BEING_LAIDOUT (this_class))
...@@ -2140,18 +2146,6 @@ layout_class (tree this_class) ...@@ -2140,18 +2146,6 @@ layout_class (tree this_class)
push_super_field (this_class, maybe_super_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); layout_type (this_class);
/* Also recursively load/layout any superinterfaces, but only if /* Also recursively load/layout any superinterfaces, but only if
...@@ -2319,11 +2313,6 @@ layout_class_method (tree this_class, tree super_class, ...@@ -2319,11 +2313,6 @@ layout_class_method (tree this_class, tree super_class,
compiled into this object file. */ compiled into this object file. */
DECL_EXTERNAL (method_decl) = 1; 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)) if (ID_INIT_P (method_name))
{ {
const char *p = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class))); const char *p = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class)));
......
...@@ -2133,6 +2133,30 @@ java_mark_decl_local (tree decl) ...@@ -2133,6 +2133,30 @@ java_mark_decl_local (tree decl)
make_decl_rtl (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 void
java_mark_class_local (tree class) java_mark_class_local (tree class)
{ {
...@@ -2143,8 +2167,13 @@ java_mark_class_local (tree class) ...@@ -2143,8 +2167,13 @@ java_mark_class_local (tree class)
java_mark_decl_local (t); java_mark_decl_local (t);
for (t = TYPE_METHODS (class); t ; t = TREE_CHAIN (t)) for (t = TYPE_METHODS (class); t ; t = TREE_CHAIN (t))
if (!METHOD_ABSTRACT (t) && (!METHOD_NATIVE (t) || flag_jni)) if (!METHOD_ABSTRACT (t))
java_mark_decl_local (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. */ /* Add a statement to a compound_expr. */
......
...@@ -818,6 +818,9 @@ union lang_tree_node ...@@ -818,6 +818,9 @@ union lang_tree_node
#define DECL_FIXED_CONSTRUCTOR_P(DECL) \ #define DECL_FIXED_CONSTRUCTOR_P(DECL) \
(DECL_LANG_SPECIFIC(DECL)->u.f.fixed_ctor) (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. */ /* A constructor that calls this. */
#define DECL_INIT_CALLS_THIS(DECL) \ #define DECL_INIT_CALLS_THIS(DECL) \
(DECL_LANG_SPECIFIC(DECL)->u.f.init_calls_this) (DECL_LANG_SPECIFIC(DECL)->u.f.init_calls_this)
...@@ -931,6 +934,12 @@ union lang_tree_node ...@@ -931,6 +934,12 @@ union lang_tree_node
(DECL_LANG_SPECIFIC (NODE)->u.v.freed) (DECL_LANG_SPECIFIC (NODE)->u.v.freed)
#define LOCAL_SLOT_P(NODE) \ #define LOCAL_SLOT_P(NODE) \
(DECL_LANG_SPECIFIC (NODE)->u.v.local_slot) (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. */ /* Create a DECL_LANG_SPECIFIC if necessary. */
#define MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC(T) \ #define MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC(T) \
if (DECL_LANG_SPECIFIC (T) == NULL) \ if (DECL_LANG_SPECIFIC (T) == NULL) \
...@@ -993,7 +1002,8 @@ struct lang_decl_func GTY(()) ...@@ -993,7 +1002,8 @@ struct lang_decl_func GTY(())
unsigned int invisible : 1; /* Set for methods we generate unsigned int invisible : 1; /* Set for methods we generate
internally but which shouldn't be internally but which shouldn't be
written to the .class file. */ 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(()) struct treetreehash_entry GTY(())
...@@ -1037,6 +1047,8 @@ struct lang_decl_var GTY(()) ...@@ -1037,6 +1047,8 @@ struct lang_decl_var GTY(())
unsigned int cif : 1; /* True: decl is a class initialization flag */ unsigned int cif : 1; /* True: decl is a class initialization flag */
unsigned int freed : 1; /* Decl is no longer in scope. */ 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 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. */ /* This is what 'lang_decl' really points to. */
...@@ -1367,7 +1379,7 @@ extern void init_jcf_parse (void); ...@@ -1367,7 +1379,7 @@ extern void init_jcf_parse (void);
extern void init_src_parse (void); extern void init_src_parse (void);
extern int cxx_keyword_p (const char *, int); 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_class_field (struct obstack *, tree);
extern tree java_mangle_vtable (struct obstack *, tree); extern tree java_mangle_vtable (struct obstack *, tree);
extern void append_gpp_mangled_name (const char *, int); extern void append_gpp_mangled_name (const char *, int);
......
...@@ -213,6 +213,9 @@ struct language_function GTY(()) ...@@ -213,6 +213,9 @@ struct language_function GTY(())
#undef LANG_HOOKS_CLEAR_BINDING_STACK #undef LANG_HOOKS_CLEAR_BINDING_STACK
#define LANG_HOOKS_CLEAR_BINDING_STACK java_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. */ /* Each front end provides its own. */
const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
......
...@@ -35,11 +35,14 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ ...@@ -35,11 +35,14 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
#include "java-tree.h" #include "java-tree.h"
#include "obstack.h" #include "obstack.h"
#include "toplev.h" #include "toplev.h"
#include "obstack.h"
#include "ggc.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_field_decl (tree);
static void mangle_method_decl (tree); static void mangle_method_decl (tree);
static void mangle_local_cni_method_decl (tree);
static void mangle_type (tree); static void mangle_type (tree);
static void mangle_pointer_type (tree); static void mangle_pointer_type (tree);
...@@ -55,15 +58,15 @@ static void set_type_package_list (tree); ...@@ -55,15 +58,15 @@ static void set_type_package_list (tree);
static int entry_match_pointer_p (tree, int); static int entry_match_pointer_p (tree, int);
static void emit_compression_string (int); static void emit_compression_string (int);
static void init_mangling (struct obstack *); static void init_mangling (void);
static tree finish_mangling (void); static tree finish_mangling (void);
static void compression_table_add (tree); static void compression_table_add (tree);
static void mangle_member_name (tree); static void mangle_member_name (tree);
/* We use an incoming obstack, always to be provided to the interface static struct obstack mangle_obstack_1;
functions. */
struct obstack *mangle_obstack; struct obstack *mangle_obstack;
#define MANGLE_RAW_STRING(S) \ #define MANGLE_RAW_STRING(S) \
obstack_grow (mangle_obstack, (S), sizeof (S)-1) obstack_grow (mangle_obstack, (S), sizeof (S)-1)
...@@ -73,46 +76,75 @@ static GTY(()) tree atms; ...@@ -73,46 +76,75 @@ static GTY(()) tree atms;
/* This is the mangling interface: a decl, a class field (.class) and /* This is the mangling interface: a decl, a class field (.class) and
the vtable. */ the vtable. */
tree void
java_mangle_decl (struct obstack *obstack, tree decl) java_mangle_decl (tree decl)
{ {
init_mangling (obstack); /* A copy of the check from the beginning of lhd_set_decl_assembler_name.
switch (TREE_CODE (decl)) 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: init_mangling ();
mangle_field_decl (decl); switch (TREE_CODE (decl))
break; {
case FUNCTION_DECL: case VAR_DECL:
mangle_method_decl (decl); if (DECL_LANG_SPECIFIC (decl))
break; {
default: if (DECL_CLASS_FIELD_P (decl))
internal_error ("can't mangle %s", tree_code_name [TREE_CODE (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 /* Beginning of the helper functions */
java_mangle_class_field (struct obstack *obstack, tree type)
static void
mangle_class_field (tree type)
{ {
init_mangling (obstack);
mangle_record_type (type, /* for_pointer = */ 0); mangle_record_type (type, /* for_pointer = */ 0);
MANGLE_RAW_STRING ("6class$"); MANGLE_RAW_STRING ("6class$");
obstack_1grow (mangle_obstack, 'E'); obstack_1grow (mangle_obstack, 'E');
return finish_mangling ();
} }
tree static void
java_mangle_vtable (struct obstack *obstack, tree type) mangle_vtable (tree type)
{ {
init_mangling (obstack);
MANGLE_RAW_STRING ("TV"); MANGLE_RAW_STRING ("TV");
mangle_record_type (type, /* for_pointer = */ 0); mangle_record_type (type, /* for_pointer = */ 0);
obstack_1grow (mangle_obstack, 'E'); obstack_1grow (mangle_obstack, 'E');
return finish_mangling ();
} }
/* Beginning of the helper functions */
/* This mangles a field decl */ /* This mangles a field decl */
static void static void
...@@ -167,6 +199,18 @@ mangle_method_decl (tree mdecl) ...@@ -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 /* This mangles a member name, like a function name or a field
name. Handle cases were `name' is a C++ keyword. Return a nonzero name. Handle cases were `name' is a C++ keyword. Return a nonzero
value if unicode encoding was required. */ value if unicode encoding was required. */
...@@ -585,17 +629,19 @@ compression_table_add (tree type) ...@@ -585,17 +629,19 @@ compression_table_add (tree type)
/* Mangling initialization routine. */ /* Mangling initialization routine. */
static void static void
init_mangling (struct obstack *obstack) init_mangling (void)
{ {
mangle_obstack = obstack; if (!mangle_obstack)
if (!compression_table) {
compression_table = make_tree_vec (10); mangle_obstack = &mangle_obstack_1;
else gcc_obstack_init (mangle_obstack);
/* Mangling already in progress. */ }
abort ();
gcc_assert (compression_table == NULL);
compression_table = make_tree_vec (10);
/* Mangled name are to be suffixed */ /* 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 /* Mangling finalization routine. The mangled name is returned as a
...@@ -606,18 +652,14 @@ finish_mangling (void) ...@@ -606,18 +652,14 @@ finish_mangling (void)
{ {
tree result; tree result;
if (!compression_table) gcc_assert (compression_table);
/* Mangling already finished. */
abort ();
compression_table = NULL_TREE; compression_table = NULL_TREE;
compression_next = 0; compression_next = 0;
obstack_1grow (mangle_obstack, '\0'); obstack_1grow (mangle_obstack, '\0');
result = get_identifier (obstack_base (mangle_obstack)); result = get_identifier (obstack_base (mangle_obstack));
obstack_free (mangle_obstack, obstack_base (mangle_obstack)); obstack_free (mangle_obstack, obstack_base (mangle_obstack));
#if 0
printf ("// %s\n", IDENTIFIER_POINTER (result));
#endif
return result; return result;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment