X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fjava%2Fclass.c;h=6d748a4fcac0ae1cc0d3d156b2c9cf7d31130d7d;hb=8f3ce25c56cf99dcb8f3c5a081f0143ebf461165;hp=8539219e3c2d7f36acbcfa4c2469974f40eba2d1;hpb=533bc3bcb62597cbc76c65fe24116a10d95461cd;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/java/class.c b/gcc/java/class.c index 8539219e3c2..6d748a4fcac 100644 --- a/gcc/java/class.c +++ b/gcc/java/class.c @@ -1,5 +1,5 @@ /* Functions related to building classes and their related objects. - Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1996, 97-98, 1999 Free Software Foundation, Inc. This file is part of GNU CC. @@ -28,10 +28,13 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "system.h" #include "tree.h" #include "rtl.h" +#include "flags.h" #include "java-tree.h" #include "jcf.h" #include "obstack.h" #include "toplev.h" +#include "output.h" +#include "parse.h" static tree mangle_class_field PROTO ((tree class)); @@ -94,13 +97,13 @@ identifier_subst (old_id, prefix, old_char, new_char, suffix) tree mangled_classname (prefix, type) - char *prefix; - tree type; + const char *prefix; + tree type; { tree ident = TYPE_NAME (type); if (TREE_CODE (ident) != IDENTIFIER_NODE) ident = DECL_NAME (ident); - return identifier_subst (ident, prefix, '/', '_', ""); + return identifier_subst (ident, prefix, '.', '_', ""); } tree @@ -138,7 +141,10 @@ tree unmangle_classname (name, name_length) const char *name; int name_length; { - return ident_subst (name, name_length, "", '/', '.', ""); + tree to_return = ident_subst (name, name_length, "", '/', '.', ""); + if (to_return != get_identifier ((char *)name)) + QUALIFIED_P (to_return) = 1; + return to_return; } tree @@ -350,6 +356,7 @@ add_interface (this_class, interface_class) add_interface_do (basetype_vec, interface_class, i); } +#if 0 /* Return the address of a pointer to the first FUNCTION_DECL in the list (*LIST) whose DECL_NAME is NAME. */ @@ -362,6 +369,7 @@ find_named_method (list, name) list = &TREE_CHAIN (*list); return list; } +#endif tree build_java_method_type (fntype, this_class, access_flags) @@ -562,10 +570,10 @@ build_utf8_ref (name) buf_ptr = &buf[strlen (buf)]; while (--name_len >= 0) { - char c = *name_ptr++; + unsigned char c = *name_ptr++; if (c & 0x80) continue; - if (!isalpha(c) && !isdigit(c)) + if (!ISALPHA(c) && !ISDIGIT(c)) c = '_'; *buf_ptr++ = c; if (buf_ptr >= buf + 50) @@ -633,6 +641,34 @@ build_class_ref (type) { char *name; char buffer[25]; + if (flag_emit_class_files) + { + const char *prim_class_name; + tree prim_class; + if (type == char_type_node) + prim_class_name = "java.lang.Character"; + else if (type == boolean_type_node) + prim_class_name = "java.lang.Boolean"; + else if (type == byte_type_node) + prim_class_name = "java.lang.Byte"; + else if (type == short_type_node) + prim_class_name = "java.lang.Short"; + else if (type == int_type_node) + prim_class_name = "java.lang.Integer"; + else if (type == long_type_node) + prim_class_name = "java.lang.Long"; + else if (type == float_type_node) + prim_class_name = "java.lang.Float"; + else if (type == double_type_node) + prim_class_name = "java.lang.Double"; + else if (type == void_type_node) + prim_class_name = "java.lang.Void"; + else + fatal ("internal error - bad type to build_class_ref"); + prim_class = lookup_class (get_identifier (prim_class_name)); + return build (COMPONENT_REF, NULL_TREE, + prim_class, TYPE_identifier_node); + } decl_name = TYPE_NAME (type); if (TREE_CODE (decl_name) == TYPE_DECL) decl_name = DECL_NAME (decl_name); @@ -804,7 +840,12 @@ make_field_value (tree fdecl) if (resolved) type = build_class_ref (type); else - type = build_utf8_ref (build_java_signature (type)); + { + tree signature = build_java_signature (type); + type = build_utf8_ref (unmangle_classname + (IDENTIFIER_POINTER(signature), + IDENTIFIER_LENGTH(signature))); + } PUSH_FIELD_VALUE (finit, "type", type); flags = get_access_flags_from_decl (fdecl); if (! resolved) @@ -850,8 +891,14 @@ make_method_value (mdecl, this_class_addr) build_utf8_ref (DECL_CONSTRUCTOR_P (mdecl) ? init_identifier_node : DECL_NAME (mdecl))); - PUSH_FIELD_VALUE (minit, "signature", - build_utf8_ref (build_java_signature (TREE_TYPE (mdecl)))); + { + tree signature = build_java_signature (TREE_TYPE (mdecl)); + PUSH_FIELD_VALUE (minit, "signature", + (build_utf8_ref + (unmangle_classname + (IDENTIFIER_POINTER(signature), + IDENTIFIER_LENGTH(signature))))); + } PUSH_FIELD_VALUE (minit, "accflags", build_int_2 (accflags, 0)); PUSH_FIELD_VALUE (minit, "ncode", code); FINISH_RECORD_CONSTRUCTOR (minit); @@ -991,7 +1038,11 @@ make_class_data (type) for (method = TYPE_METHODS (CLASS_TO_HANDLE_TYPE (type)); method != NULL_TREE; method = TREE_CHAIN (method)) { - tree init = make_method_value (method, this_class_addr); + tree init; + if (METHOD_PRIVATE (method) + && (flag_inline_functions || optimize)) + continue; + init = make_method_value (method, this_class_addr); method_count++; methods = tree_cons (NULL_TREE, init, methods); } @@ -1070,9 +1121,9 @@ make_class_data (type) START_RECORD_CONSTRUCTOR (temp, object_type_node); #if 0 - PUSH_FIELD_VALUE (temp, "dtable", NULL_TREE); + PUSH_FIELD_VALUE (temp, "vtable", NULL_TREE); #else - PUSH_FIELD_VALUE (temp, "dtable", + PUSH_FIELD_VALUE (temp, "vtable", build1 (ADDR_EXPR, dtable_ptr_type, class_dtable_decl)); #endif PUSH_FIELD_VALUE (temp, "sync_info", null_pointer_node); @@ -1080,17 +1131,17 @@ make_class_data (type) START_RECORD_CONSTRUCTOR (cons, class_type_node); PUSH_SUPER_VALUE (cons, temp); PUSH_FIELD_VALUE (cons, "next", null_pointer_node); - PUSH_FIELD_VALUE (cons, "name", - build_utf8_ref (build_internal_class_name (type))); + PUSH_FIELD_VALUE (cons, "name", build_utf8_ref (DECL_NAME (type_decl))); PUSH_FIELD_VALUE (cons, "accflags", build_int_2 (get_access_flags_from_decl (type_decl), 0)); - PUSH_FIELD_VALUE (cons, "superclass", super); + PUSH_FIELD_VALUE (cons, "superclass", + CLASS_INTERFACE (type_decl) ? null_pointer_node : super); PUSH_FIELD_VALUE (cons, "constants", constant_pool_constructor); PUSH_FIELD_VALUE (cons, "methods", build1 (ADDR_EXPR, method_ptr_type_node, methods_decl)); PUSH_FIELD_VALUE (cons, "method_count", build_int_2 (method_count, 0)); - PUSH_FIELD_VALUE (cons, "dtable_method_count", TYPE_NVIRTUALS (type)); + PUSH_FIELD_VALUE (cons, "vtable_method_count", TYPE_NVIRTUALS (type)); PUSH_FIELD_VALUE (cons, "fields", fields_decl == NULL_TREE ? null_pointer_node : build1 (ADDR_EXPR, field_ptr_type_node, fields_decl)); @@ -1098,8 +1149,7 @@ make_class_data (type) PUSH_FIELD_VALUE (cons, "field_count", build_int_2 (field_count, 0)); PUSH_FIELD_VALUE (cons, "static_field_count", build_int_2 (static_field_count, 0)); - /* For now, we let Kaffe fill in the dtable. */ - PUSH_FIELD_VALUE (cons, "dtable", + PUSH_FIELD_VALUE (cons, "vtable", dtable_decl == NULL_TREE ? null_pointer_node : build1 (ADDR_EXPR, dtable_ptr_type, dtable_decl)); PUSH_FIELD_VALUE (cons, "interfaces", interfaces); @@ -1115,6 +1165,35 @@ make_class_data (type) rest_of_decl_compilation (decl, (char*) 0, 1, 0); } +void +finish_class (cl) + tree cl; +{ + tree method; + + /* Emit deferred inline methods. */ + for ( method = TYPE_METHODS (CLASS_TO_HANDLE_TYPE (current_class)); + method != NULL_TREE; method = TREE_CHAIN (method)) + { + if (! TREE_ASM_WRITTEN (method) && DECL_SAVED_INSNS (method) != 0) + { + /* It's a deferred inline method. Decide if we need to emit it. */ + if (flag_keep_inline_functions + || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (method)) + || ! METHOD_PRIVATE (method)) + { + temporary_allocation (); + output_inline_function (method); + permanent_allocation (1); + } + } + } + + make_class_data (current_class); + register_class (); + rest_of_decl_compilation (TYPE_NAME (current_class), (char*) 0, 1, 0); +} + /* Return 2 if CLASS is compiled by this compilation job; return 1 if CLASS can otherwise be assumed to be compiled; return 0 if we cannot assume that CLASS is compiled. @@ -1320,39 +1399,55 @@ push_super_field (this_class, super_class) DECL_SIZE (base_decl) = TYPE_SIZE (super_class); } +/* Handle the different manners we may have to lay out a super class. */ + +static tree +maybe_layout_super_class (super_class) + tree super_class; +{ + if (TREE_CODE (super_class) == RECORD_TYPE) + { + if (!CLASS_LOADED_P (super_class) + && CLASS_FROM_SOURCE_P (super_class)) + safe_layout_class (super_class); + if (!CLASS_LOADED_P (super_class)) + load_class (super_class, 1); + } + /* We might have to layout the class before its dependency on + the super class gets resolved by java_complete_class */ + else if (TREE_CODE (super_class) == TREE_LIST) + { + tree name = TYPE_NAME (TREE_PURPOSE (super_class)); + load_class (name, 1); + super_class = IDENTIFIER_CLASS_VALUE (name); + if (!super_class) + return NULL_TREE; /* FIXME, NULL_TREE not checked by caller. */ + super_class = TREE_TYPE (super_class); + } + if (!TYPE_SIZE (super_class)) + safe_layout_class (super_class); + + return super_class; +} + void layout_class (this_class) tree this_class; { tree super_class = CLASSTYPE_SUPER (this_class); - tree handle_type = CLASS_TO_HANDLE_TYPE (this_class); - tree method_decl, field; - tree dtable_count; - int i; + tree field; if (super_class) { - /* Class seen in source are now complete and can be layed out. - Once layed out, a class seen in the source has its - CLASS_LOADED_P flag set */ - if (CLASS_FROM_SOURCE_P (super_class) && !CLASS_LOADED_P (super_class)) - safe_layout_class (super_class); - if (! CLASS_LOADED_P (super_class)) - load_class (super_class, 1); + super_class = maybe_layout_super_class (super_class); if (TREE_CODE (TYPE_SIZE (super_class)) == ERROR_MARK) { TYPE_SIZE (this_class) = error_mark_node; return; } - dtable_count = TYPE_NVIRTUALS (super_class); - if (TYPE_SIZE (this_class) == NULL_TREE) push_super_field (this_class, super_class); } - else - { - dtable_count = integer_zero_node; - } for (field = TYPE_FIELDS (this_class); field != NULL_TREE; field = TREE_CHAIN (field)) @@ -1365,171 +1460,197 @@ layout_class (this_class) } layout_type (this_class); +} + +void +layout_class_methods (this_class) + tree this_class; +{ + tree method_decl, dtable_count; + tree super_class, handle_type; + if (TYPE_NVIRTUALS (this_class)) + return; + + push_obstacks (&permanent_obstack, &permanent_obstack); + super_class = CLASSTYPE_SUPER (this_class); + handle_type = CLASS_TO_HANDLE_TYPE (this_class); + + if (super_class) + { + super_class = maybe_layout_super_class (super_class); + if (!TYPE_NVIRTUALS (super_class)) + layout_class_methods (super_class); + dtable_count = TYPE_NVIRTUALS (super_class); + } + else + dtable_count = integer_zero_node; + TYPE_METHODS (handle_type) = nreverse (TYPE_METHODS (handle_type)); - for (method_decl = TYPE_METHODS (handle_type), i = 0; - method_decl; method_decl = TREE_CHAIN (method_decl), i++) + for (method_decl = TYPE_METHODS (handle_type); + method_decl; method_decl = TREE_CHAIN (method_decl)) + dtable_count = layout_class_method (this_class, super_class, + method_decl, dtable_count); + + TYPE_NVIRTUALS (this_class) = dtable_count; + +#ifdef JAVA_USE_HANDLES + layout_type (handle_type); +#endif + pop_obstacks (); +} + +/* Lay METHOD_DECL out, returning a possibly new value of + DTABLE_COUNT. */ + +tree +layout_class_method (this_class, super_class, method_decl, dtable_count) + tree this_class, super_class, method_decl, dtable_count; +{ + char *ptr; + char *asm_name; + tree arg, arglist, t; + int method_name_needs_escapes = 0; + tree method_name = DECL_NAME (method_decl); + int method_name_is_wfl = + (TREE_CODE (method_name) == EXPR_WITH_FILE_LOCATION); + if (method_name_is_wfl) + method_name = java_get_real_method_name (method_decl); + + if (method_name != init_identifier_node + && method_name != finit_identifier_node) { - char *ptr; - char buf[8]; - char *asm_name; - tree method_name = DECL_NAME (method_decl); -#if 1 - /* Remove this once we no longer need old (Kaffe / JDK 1.0) mangling. */ - if (! flag_assume_compiled && METHOD_NATIVE (method_decl)) + int encoded_len + = unicode_mangling_length (IDENTIFIER_POINTER (method_name), + IDENTIFIER_LENGTH (method_name)); + if (encoded_len > 0) { - for (ptr = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class))); - *ptr; ) - { - int ch = *ptr++; - if (ch == '.') - ch = '_'; - obstack_1grow (&temporary_obstack, (char) ch); - } - obstack_1grow (&temporary_obstack, (char) '_'); - if (method_name == init_identifier_node) - obstack_grow (&temporary_obstack, "INIT", 4); - else - obstack_grow (&temporary_obstack, - IDENTIFIER_POINTER (method_name), - IDENTIFIER_LENGTH (method_name)); + method_name_needs_escapes = 1; + emit_unicode_mangled_name (&temporary_obstack, + IDENTIFIER_POINTER (method_name), + IDENTIFIER_LENGTH (method_name)); } else -#endif { - int len; tree arg, arglist, t; - int method_name_needs_escapes = 0; - if (method_name != init_identifier_node - && method_name != finit_identifier_node) + obstack_grow (&temporary_obstack, + IDENTIFIER_POINTER (method_name), + IDENTIFIER_LENGTH (method_name)); + } + } + + obstack_grow (&temporary_obstack, "__", 2); + if (method_name == finit_identifier_node) + obstack_grow (&temporary_obstack, "finit", 5); + append_gpp_mangled_type (&temporary_obstack, this_class); + TREE_PUBLIC (method_decl) = 1; + + t = TREE_TYPE (method_decl); + arglist = TYPE_ARG_TYPES (t); + if (TREE_CODE (t) == METHOD_TYPE) + arglist = TREE_CHAIN (arglist); + for (arg = arglist; arg != end_params_node; ) + { + tree a = arglist; + tree argtype = TREE_VALUE (arg); + int tindex = 1; + if (TREE_CODE (argtype) == POINTER_TYPE) + { + /* This is O(N**2). Do we care? Cfr gcc/cp/method.c. */ + while (a != arg && argtype != TREE_VALUE (a)) + a = TREE_CHAIN (a), tindex++; + } + else + a = arg; + if (a != arg) + { + char buf[12]; + int nrepeats = 0; + do { - int encoded_len - = unicode_mangling_length (IDENTIFIER_POINTER (method_name), - IDENTIFIER_LENGTH (method_name)); - if (encoded_len > 0) - { - method_name_needs_escapes = 1; - emit_unicode_mangled_name (&temporary_obstack, - IDENTIFIER_POINTER (method_name), - IDENTIFIER_LENGTH (method_name)); - } - else - { - obstack_grow (&temporary_obstack, - IDENTIFIER_POINTER (method_name), - IDENTIFIER_LENGTH (method_name)); - } + arg = TREE_CHAIN (arg); nrepeats++; } - - obstack_grow (&temporary_obstack, "__", 2); - if (method_name == finit_identifier_node) - obstack_grow (&temporary_obstack, "finit", 5); - append_gpp_mangled_type (&temporary_obstack, this_class); - TREE_PUBLIC (method_decl) = 1; - - t = TREE_TYPE (method_decl); - arglist = TYPE_ARG_TYPES (t); - if (TREE_CODE (t) == METHOD_TYPE) - arglist = TREE_CHAIN (arglist); - for (arg = arglist; arg != NULL_TREE; ) + while (arg != end_params_node && argtype == TREE_VALUE (arg)); + if (nrepeats > 1) { - tree a = arglist; - tree argtype = TREE_VALUE (arg); - int tindex = 1; - if (TREE_CODE (argtype) == POINTER_TYPE) - { - /* This is O(N**2). Do we care? Cfr gcc/cp/method.c. */ - while (a != arg && argtype != TREE_VALUE (a)) - a = TREE_CHAIN (a), tindex++; - } - else - a = arg; - if (a != arg) - { - char buf[12]; - int nrepeats = 0; - do - { - arg = TREE_CHAIN (arg); nrepeats++; - } - while (arg != NULL_TREE && argtype == TREE_VALUE (arg)); - if (nrepeats > 1) - { - obstack_1grow (&temporary_obstack, 'N'); - sprintf (buf, "%d", nrepeats); - obstack_grow (&temporary_obstack, buf, strlen (buf)); - if (nrepeats > 9) - obstack_1grow (&temporary_obstack, '_'); - } - else - obstack_1grow (&temporary_obstack, 'T'); - sprintf (buf, "%d", tindex); - obstack_grow (&temporary_obstack, buf, strlen (buf)); - if (tindex > 9) - obstack_1grow (&temporary_obstack, '_'); - } - else - { - append_gpp_mangled_type (&temporary_obstack, argtype); - arg = TREE_CHAIN (arg); - } + obstack_1grow (&temporary_obstack, 'N'); + sprintf (buf, "%d", nrepeats); + obstack_grow (&temporary_obstack, buf, strlen (buf)); + if (nrepeats > 9) + obstack_1grow (&temporary_obstack, '_'); } - if (method_name_needs_escapes) - obstack_1grow (&temporary_obstack, 'U'); + else + obstack_1grow (&temporary_obstack, 'T'); + sprintf (buf, "%d", tindex); + obstack_grow (&temporary_obstack, buf, strlen (buf)); + if (tindex > 9) + obstack_1grow (&temporary_obstack, '_'); } - obstack_1grow (&temporary_obstack, '\0'); - asm_name = obstack_finish (&temporary_obstack); - DECL_ASSEMBLER_NAME (method_decl) = get_identifier (asm_name); - if (! METHOD_ABSTRACT (method_decl)) - make_function_rtl (method_decl); - obstack_free (&temporary_obstack, asm_name); - - if (method_name == init_identifier_node) + else { - char *p = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class))); - for (ptr = p; *ptr; ) - { - if (*ptr++ == '.') - p = ptr; - } - DECL_NAME (method_decl) = get_identifier (p); - DECL_CONSTRUCTOR_P (method_decl) = 1; + append_gpp_mangled_type (&temporary_obstack, argtype); + arg = TREE_CHAIN (arg); } - else if (! METHOD_STATIC (method_decl) && !DECL_ARTIFICIAL (method_decl)) + } + if (method_name_needs_escapes) + obstack_1grow (&temporary_obstack, 'U'); + + obstack_1grow (&temporary_obstack, '\0'); + asm_name = obstack_finish (&temporary_obstack); + DECL_ASSEMBLER_NAME (method_decl) = get_identifier (asm_name); + if (! METHOD_ABSTRACT (method_decl)) + make_function_rtl (method_decl); + obstack_free (&temporary_obstack, asm_name); + + if (method_name == init_identifier_node) + { + char *p = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class))); + for (ptr = p; *ptr; ) { - tree method_sig = build_java_argument_signature (TREE_TYPE (method_decl)); - tree super_method = lookup_argument_method (super_class, method_name, + if (*ptr++ == '.') + p = ptr; + } + if (method_name_is_wfl) + EXPR_WFL_NODE (DECL_NAME (method_decl)) = get_identifier (p); + else + DECL_NAME (method_decl) = get_identifier (p); + DECL_CONSTRUCTOR_P (method_decl) = 1; + build_java_argument_signature (TREE_TYPE (method_decl)); + } + else if (! METHOD_STATIC (method_decl) && !DECL_ARTIFICIAL (method_decl)) + { + tree method_sig = + build_java_argument_signature (TREE_TYPE (method_decl)); + tree super_method = lookup_argument_method (super_class, method_name, method_sig); - if (super_method != NULL_TREE) - { - DECL_VINDEX (method_decl) = DECL_VINDEX (super_method); - if (DECL_VINDEX (method_decl) == NULL_TREE) - error_with_decl (method_decl, - "non-static method '%s' overrides static method"); + if (super_method != NULL_TREE) + { + DECL_VINDEX (method_decl) = DECL_VINDEX (super_method); + if (DECL_VINDEX (method_decl) == NULL_TREE && + ! TREE_PRIVATE (method_decl)) + error_with_decl (method_decl, + "non-static method '%s' overrides static method"); #if 0 - else if (TREE_TYPE (TREE_TYPE (method_decl)) - != TREE_TYPE (TREE_TYPE (super_method))) - { - error_with_decl (method_decl, - "Method `%s' redefined with different return type"); - error_with_decl (super_method, - "Overridden decl is here"); - } -#endif - } - else if (! METHOD_FINAL (method_decl) - && ! CLASS_FINAL (TYPE_NAME (this_class))) + else if (TREE_TYPE (TREE_TYPE (method_decl)) + != TREE_TYPE (TREE_TYPE (super_method))) { - DECL_VINDEX (method_decl) = dtable_count; - dtable_count = build_int_2 (1+TREE_INT_CST_LOW (dtable_count), 0); + error_with_decl (method_decl, + "Method `%s' redefined with different return type"); + error_with_decl (super_method, + "Overridden decl is here"); } +#endif + } + else if (! METHOD_FINAL (method_decl) + && ! METHOD_PRIVATE (method_decl) + && ! CLASS_FINAL (TYPE_NAME (this_class)) + && dtable_count) + { + DECL_VINDEX (method_decl) = dtable_count; + dtable_count = build_int_2 (1+TREE_INT_CST_LOW (dtable_count), 0); } } - TYPE_NVIRTUALS (this_class) = dtable_count; - -#ifdef JAVA_USE_HANDLES - layout_type (handle_type); -#endif + return dtable_count; } static tree registered_class = NULL_TREE; @@ -1560,7 +1681,7 @@ emit_register_classes () extern tree get_file_function_name PROTO((int)); tree init_name = get_file_function_name ('I'); - tree init_type = build_function_type (void_type_node, NULL_TREE); + tree init_type = build_function_type (void_type_node, end_params_node); tree init_decl; tree t; @@ -1585,7 +1706,6 @@ emit_register_classes () poplevel (1, 0, 1); { /* Force generation, even with -O3 or deeper. Gross hack. FIXME */ - extern int flag_inline_functions; int saved_flag = flag_inline_functions; flag_inline_functions = 0; rest_of_compilation (init_decl);