X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fjava%2Fmangle.c;h=4630f6d9da026d40fc54c313e923fbca758d6026;hb=58d82cd04d30e16e38e5fcac6d2d120fa55d64ed;hp=93d8fe7647ea0c3d2ec5e0789473990e305f248f;hpb=684359128e4da5eefe42173ee6909fcf2bca36a7;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/java/mangle.c b/gcc/java/mangle.c index 93d8fe7647e..4630f6d9da0 100644 --- a/gcc/java/mangle.c +++ b/gcc/java/mangle.c @@ -1,23 +1,23 @@ /* Functions related to mangling class names for the GNU compiler for the Java(TM) language. - Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + Copyright (C) 1998, 1999, 2001, 2002, 2003, 2006, 2007, 2008 + Free Software Foundation, Inc. -This file is part of GNU CC. +This file is part of GCC. -GNU CC is free software; you can redistribute it and/or modify +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 2, or (at your option) +the Free Software Foundation; either version 3, or (at your option) any later version. -GNU CC is distributed in the hope that it will be useful, +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 GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. +along with GCC; see the file COPYING3. If not see +. Java and all Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. @@ -27,97 +27,131 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "config.h" #include "system.h" +#include "coretypes.h" +#include "tm.h" #include "jcf.h" #include "tree.h" #include "java-tree.h" #include "obstack.h" #include "toplev.h" -#include "obstack.h" #include "ggc.h" +#include "langhooks-def.h" -static void mangle_field_decl PARAMS ((tree)); -static void mangle_method_decl PARAMS ((tree)); +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 PARAMS ((tree)); -static void mangle_pointer_type PARAMS ((tree)); -static void mangle_array_type PARAMS ((tree)); -static int mangle_record_type PARAMS ((tree, int)); +static void mangle_type (tree); +static void mangle_pointer_type (tree); +static void mangle_array_type (tree); +static int mangle_record_type (tree, int); -static int find_compression_pointer_match PARAMS ((tree)); -static int find_compression_array_match PARAMS ((tree)); -static int find_compression_record_match PARAMS ((tree, tree *)); -static int find_compression_array_template_match PARAMS ((tree)); +static int find_compression_pointer_match (tree); +static int find_compression_array_match (tree); +static int find_compression_record_match (tree, tree *); +static int find_compression_array_template_match (tree); -static void set_type_package_list PARAMS ((tree)); -static int entry_match_pointer_p PARAMS ((tree, int)); -static void emit_compression_string PARAMS ((int)); +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 PARAMS ((struct obstack *)); -static tree finish_mangling PARAMS ((void)); -static void compression_table_add PARAMS ((tree)); +static void init_mangling (void); +static tree finish_mangling (void); +static void compression_table_add (tree); -static void mangle_member_name PARAMS ((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) +/* atms: array template mangled string. */ +static GTY(()) tree atms; + /* This is the mangling interface: a decl, a class field (.class) and the vtable. */ -tree -java_mangle_decl (obstack, 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); + 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 (obstack, type) - struct obstack *obstack; - tree type; +/* Beginning of the helper functions */ + +static void +mangle_class_field (tree decl) { - init_mangling (obstack); + tree type = DECL_CONTEXT (decl); mangle_record_type (type, /* for_pointer = */ 0); - MANGLE_RAW_STRING ("6class$"); + if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE) + MANGLE_RAW_STRING ("6class$"); + else + MANGLE_RAW_STRING ("7class$$"); obstack_1grow (mangle_obstack, 'E'); - return finish_mangling (); } -tree -java_mangle_vtable (obstack, type) - 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 -mangle_field_decl (decl) - tree decl; +mangle_field_decl (tree decl) { /* Mangle the name of the this the field belongs to */ mangle_record_type (DECL_CONTEXT (decl), /* for_pointer = */ 0); @@ -133,8 +167,7 @@ mangle_field_decl (decl) its arguments. */ static void -mangle_method_decl (mdecl) - tree mdecl; +mangle_method_decl (tree mdecl) { tree method_name = DECL_NAME (mdecl); tree arglist; @@ -142,20 +175,13 @@ mangle_method_decl (mdecl) /* Mangle the name of the type that contains mdecl */ mangle_record_type (DECL_CONTEXT (mdecl), /* for_pointer = */ 0); - /* Mangle the function name. There three cases - - mdecl is java.lang.Object.Object(), use `C2' for its name - (denotes a base object constructor.) + /* Mangle the function name. There are two cases: - mdecl is a constructor, use `C1' for its name, (denotes a complete object constructor.) - mdecl is not a constructor, standard mangling is performed. We terminate the mangled function name with a `E'. */ if (ID_INIT_P (method_name)) - { - if (DECL_CONTEXT (mdecl) == object_type_node) - obstack_grow (mangle_obstack, "C2", 2); - else - obstack_grow (mangle_obstack, "C1", 2); - } + obstack_grow (mangle_obstack, "C1", 2); else mangle_member_name (method_name); obstack_1grow (mangle_obstack, 'E'); @@ -165,6 +191,14 @@ mangle_method_decl (mdecl) if (TREE_CODE (TREE_TYPE (mdecl)) == METHOD_TYPE) arglist = TREE_CHAIN (arglist); + /* Output literal 'J' and mangle the return type IF not a + constructor. */ + if (!ID_INIT_P (method_name)) + { + obstack_1grow (mangle_obstack, 'J'); + mangle_type(TREE_TYPE(TREE_TYPE(mdecl))); + } + /* No arguments is easy. We shortcut it. */ if (arglist == end_params_node) obstack_1grow (mangle_obstack, 'v'); @@ -176,45 +210,45 @@ mangle_method_decl (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 non zero + name. Handle cases were `name' is a C++ keyword. Return a nonzero value if unicode encoding was required. */ static void -mangle_member_name (name) - tree name; +mangle_member_name (tree name) { append_gpp_mangled_name (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name)); - - /* If NAME happens to be a C++ keyword, add `$' or `.' or `_'. */ - if (cxx_keyword_p (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name))) - { -#ifndef NO_DOLLAR_IN_LABEL - obstack_1grow (mangle_obstack, '$'); -#else /* NO_DOLLAR_IN_LABEL */ -#ifndef NO_DOT_IN_LABEL - obstack_1grow (mangle_obstack, '.'); -#else /* NO_DOT_IN_LABEL */ - obstack_1grow (mangle_obstack, '_'); -#endif /* NO_DOT_IN_LABEL */ -#endif /* NO_DOLLAR_IN_LABEL */ - } } /* Append the mangled name of TYPE onto OBSTACK. */ static void -mangle_type (type) - tree type; +mangle_type (tree type) { switch (TREE_CODE (type)) { char code; case BOOLEAN_TYPE: code = 'b'; goto primitive; - case CHAR_TYPE: code = 'w'; goto primitive; case VOID_TYPE: code = 'v'; goto primitive; case INTEGER_TYPE: + if (type == char_type_node || type == promoted_char_type_node) + { + code = 'w'; + goto primitive; + } /* Get the original type instead of the arguments promoted type. Avoid symbol name clashes. Should call a function to do that. FIXME. */ @@ -249,7 +283,7 @@ mangle_type (type) break; bad_type: default: - abort (); + gcc_unreachable (); } } @@ -257,20 +291,19 @@ mangle_type (type) already seen, so they can be reused. For example, java.lang.Object would generate three entries: two package names and a type. If java.lang.String is presented next, the java.lang will be matched - against the first two entries (and kept for compression as S_0), and + against the first two entries (and kept for compression as S0_), and type String would be added to the table. See mangle_record_type. COMPRESSION_NEXT is the index to the location of the next insertion of an element. */ -static tree compression_table; +static GTY(()) tree compression_table; static int compression_next; /* Find a POINTER_TYPE in the compression table. Use a special function to match pointer entries and start from the end */ static int -find_compression_pointer_match (type) - tree type; +find_compression_pointer_match (tree type) { int i; @@ -284,8 +317,7 @@ find_compression_pointer_match (type) associated with it. */ static int -find_compression_array_match (type) - tree type; +find_compression_array_match (tree type) { return find_compression_pointer_match (type); } @@ -293,8 +325,7 @@ find_compression_array_match (type) /* Match the table of type against STRING. */ static int -find_compression_array_template_match (string) - tree string; +find_compression_array_template_match (tree string) { int i; for (i = 0; i < compression_next; i++) @@ -305,42 +336,35 @@ find_compression_array_template_match (string) /* We go through the compression table and try to find a complete or partial match. The function returns the compression table entry - that (evenutally partially) matches TYPE. *NEXT_CURRENT can be set + that (eventually partially) matches TYPE. *NEXT_CURRENT can be set to the rest of TYPE to be mangled. */ static int -find_compression_record_match (type, next_current) - tree type; - tree *next_current; +find_compression_record_match (tree type, tree *next_current) { - int i, match; + int i, match = -1; tree current, saved_current = NULL_TREE; - /* Search from the beginning for something that matches TYPE, even - partially. */ - for (current = TYPE_PACKAGE_LIST (type), i = 0, match = -1; current; - current = TREE_CHAIN (current)) + current = TYPE_PACKAGE_LIST (type); + + for (i = 0; i < compression_next; i++) { - int j; - for (j = i; j < compression_next; j++) - if (TREE_VEC_ELT (compression_table, j) == TREE_PURPOSE (current)) - { - match = i = j; - saved_current = current; - i++; - break; - } - else - { - /* We don't want to match an element that appears in the middle - of a package name, so skip forward to the next complete type name. - IDENTIFIER_NODEs are partial package names while RECORD_TYPEs - represent complete type names. */ - while (j < compression_next - && TREE_CODE (TREE_VEC_ELT (compression_table, j)) == - IDENTIFIER_NODE) - j++; - } + tree compression_entry = TREE_VEC_ELT (compression_table, i); + if (current && compression_entry == TREE_PURPOSE (current)) + { + match = i; + saved_current = current; + current = TREE_CHAIN (current); + } + else + /* We don't want to match an element that appears in the middle + of a package name, so skip forward to the next complete type name. + IDENTIFIER_NODEs (except for a "6JArray") are partial package + names while RECORD_TYPEs represent complete type names. */ + while (i < compression_next + && TREE_CODE (compression_entry) == IDENTIFIER_NODE + && compression_entry != atms) + compression_entry = TREE_VEC_ELT (compression_table, ++i); } if (!next_current) @@ -357,15 +381,13 @@ find_compression_record_match (type, next_current) return match; } -/* Mangle a record type. If a non zero value is returned, it means +/* Mangle a record type. If a nonzero value is returned, it means that a 'N' was emitted (so that a matching 'E' can be emitted if necessary.) FOR_POINTER indicates that this element is for a pointer symbol, meaning it was preceded by a 'P'. */ static int -mangle_record_type (type, for_pointer) - tree type; - int for_pointer; +mangle_record_type (tree type, int for_pointer) { tree current; int match; @@ -378,8 +400,7 @@ mangle_record_type (type, for_pointer) #define ADD_N() \ do { obstack_1grow (mangle_obstack, 'N'); nadded_p = 1; } while (0) - if (TREE_CODE (type) != RECORD_TYPE) - abort (); + gcc_assert (TREE_CODE (type) == RECORD_TYPE); if (!TYPE_PACKAGE_LIST (type)) set_type_package_list (type); @@ -411,13 +432,12 @@ mangle_record_type (type, for_pointer) } /* Mangle a pointer type. There are two cases: the pointer is already - in the compression table: the compression is emited sans 'P' + in the compression table: the compression is emitted sans 'P' indicator. Otherwise, a 'P' is emitted and, depending on the type, a partial compression or/plus the rest of the mangling. */ static void -mangle_pointer_type (type) - tree type; +mangle_pointer_type (tree type) { int match; tree pointer_type; @@ -432,8 +452,7 @@ mangle_pointer_type (type) /* This didn't work. We start by mangling the pointed-to type */ pointer_type = type; type = TREE_TYPE (type); - if (TREE_CODE (type) != RECORD_TYPE) - abort (); + gcc_assert (TREE_CODE (type) == RECORD_TYPE); obstack_1grow (mangle_obstack, 'P'); if (mangle_record_type (type, /* for_pointer = */ 1)) @@ -445,21 +464,17 @@ mangle_pointer_type (type) /* Mangle an array type. Search for an easy solution first, then go through the process of finding out whether the bare array type or even - the template indicator where already used an compress appropriately. + the template indicator were already used and compressed appropriately. It handles pointers. */ static void -mangle_array_type (p_type) - tree p_type; +mangle_array_type (tree p_type) { - /* atms: array template mangled string. */ - static tree atms = NULL_TREE; tree type, elt_type; int match; type = TREE_TYPE (p_type); - if (!type) - abort (); + gcc_assert (type); elt_type = TYPE_ARRAY_ELEMENT (type); @@ -467,10 +482,9 @@ mangle_array_type (p_type) if (!atms) { atms = get_identifier ("6JArray"); - ggc_add_tree_root (&atms, 1); } - /* Maybe we have what we're looking in the compression table. */ + /* Maybe we have what we're looking for in the compression table. */ if ((match = find_compression_array_match (p_type)) >= 0) { emit_compression_string (match); @@ -508,8 +522,8 @@ mangle_array_type (p_type) compression_table_add (p_type); } -/* Write a substition string for entry I. Substitution string starts a - -1 (encoded S_.) The base is 36, and the code shamlessly taken from +/* Write a substitution string for entry I. Substitution string starts a + -1 (encoded S_.) The base is 36, and the code shamelessly taken from cp/mangle.c. */ static void @@ -541,9 +555,7 @@ emit_compression_string (int i) might all be unique, we find the same RECORD_TYPE.) */ static int -entry_match_pointer_p (type, i) - tree type; - int i; +entry_match_pointer_p (tree type, int i) { tree t = TREE_VEC_ELT (compression_table, i); @@ -564,32 +576,25 @@ entry_match_pointer_p (type, i) part. The result is stored in TYPE_PACKAGE_LIST to be reused. */ static void -set_type_package_list (type) - tree type; +set_type_package_list (tree type) { int i; const char *type_string = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))); - char *ptr; + const char *ptr; int qualifications; tree list = NULL_TREE, elt; - for (ptr = (char *)type_string, qualifications = 0; *ptr; ptr++) + for (ptr = type_string, qualifications = 0; *ptr; ptr++) if (*ptr == '.') qualifications += 1; - for (ptr = (char *)type_string, i = 0; i < qualifications; ptr++) + for (ptr = type_string, i = 0; i < qualifications; ptr++) { if (ptr [0] == '.') { - char c; - tree identifier; - - /* Can't use an obstack, we're already using it to - accumulate the mangling. */ - c = ptr [0]; - ptr [0] = '\0'; - identifier = get_identifier (type_string); - ptr [0] = c; + tree const identifier + = get_identifier_with_length (type_string, ptr - type_string); + elt = build_tree_list (identifier, identifier); TREE_CHAIN (elt) = list; list = elt; @@ -608,64 +613,109 @@ set_type_package_list (type) compression table if necessary. */ static void -compression_table_add (type) - tree type; +compression_table_add (tree type) { if (compression_next == TREE_VEC_LENGTH (compression_table)) { - tree new = make_tree_vec (2*compression_next); + tree new_table = make_tree_vec (2*compression_next); int i; for (i = 0; i < compression_next; i++) - TREE_VEC_ELT (new, i) = TREE_VEC_ELT (compression_table, i); + TREE_VEC_ELT (new_table, i) = TREE_VEC_ELT (compression_table, i); - ggc_del_root (&compression_table); - compression_table = new; - ggc_add_tree_root (&compression_table, 1); + compression_table = new_table; } TREE_VEC_ELT (compression_table, compression_next++) = type; } +/* Mangle an embedded resource file name. "_ZGr" is the prefix. A + '_' is prepended to the name so that names starting with a digit + can be demangled. The length and then the resulting name itself + are appended while escaping '$', '.', and '/' to: "$$", "$_", and + "$S". */ + +tree +java_mangle_resource_name (const char *name) +{ + int len = strlen (name); + char *buf = (char *) alloca (2 * len + 1); + char *pos; + const unsigned char *w1 = (const unsigned char *) name; + const unsigned char *w2; + const unsigned char *limit = w1 + len; + + pos = buf; + + init_mangling (); + MANGLE_RAW_STRING ("Gr"); + + *pos++ = '_'; + while (w1 < limit) + { + int ch; + w2 = w1; + ch = UTF8_GET (w1, limit); + gcc_assert (ch > 0); + switch (ch) + { + case '$': + *pos++ = '$'; + *pos++ = '$'; + break; + case '.': + *pos++ = '$'; + *pos++ = '_'; + break; + case '/': + *pos++ = '$'; + *pos++ = 'S'; + break; + default: + memcpy (pos, w2, w1 - w2); + pos += w1 - w2; + break; + } + } + append_gpp_mangled_name (buf, pos - buf); + + return finish_mangling (); +} + /* Mangling initialization routine. */ static void -init_mangling (obstack) - 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); + } - /* Mangled name are to be suffixed */ - obstack_grow (mangle_obstack, "_Z", 2); + gcc_assert (compression_table == NULL); + compression_table = make_tree_vec (10); - /* Register the compression table with the GC */ - ggc_add_tree_root (&compression_table, 1); + /* Mangled name are to be suffixed */ + MANGLE_RAW_STRING ("_Z"); } /* Mangling finalization routine. The mangled name is returned as a IDENTIFIER_NODE. */ static tree -finish_mangling () +finish_mangling (void) { tree result; - if (!compression_table) - /* Mangling already finished. */ - abort (); + gcc_assert (compression_table); - ggc_del_root (&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; } + +#include "gt-java-mangle.h"