diff options
Diffstat (limited to 'gcc/java/class.c')
-rw-r--r-- | gcc/java/class.c | 207 |
1 files changed, 179 insertions, 28 deletions
diff --git a/gcc/java/class.c b/gcc/java/class.c index b1faafc..e9d8174 100644 --- a/gcc/java/class.c +++ b/gcc/java/class.c @@ -1,6 +1,6 @@ /* Functions related to building classes and their related objects. - Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, + 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of GCC. @@ -46,6 +46,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "cgraph.h" #include "tree-iterator.h" #include "cgraph.h" +#include "vecprim.h" /* DOS brain-damage */ #ifndef O_BINARY @@ -68,6 +69,8 @@ static void register_class (void); struct obstack temporary_obstack; +static const char *cyclic_inheritance_report; + /* The compiler generates different code depending on whether or not it can assume certain classes have been compiled down to native code or not. The compiler options -fassume-compiled= and @@ -497,6 +500,9 @@ set_class_decl_access_flags (int access_flags, tree class_decl) if (access_flags & ACC_PRIVATE) CLASS_PRIVATE (class_decl) = 1; if (access_flags & ACC_PROTECTED) CLASS_PROTECTED (class_decl) = 1; if (access_flags & ACC_STRICT) CLASS_STRICTFP (class_decl) = 1; + if (access_flags & ACC_ENUM) CLASS_ENUM (class_decl) = 1; + if (access_flags & ACC_SYNTHETIC) CLASS_SYNTHETIC (class_decl) = 1; + if (access_flags & ACC_ANNOTATION) CLASS_ANNOTATION (class_decl) = 1; } /* Return length of inheritance chain of CLAS, where java.lang.Object is 0, @@ -719,9 +725,6 @@ add_method_1 (tree this_class, int access_flags, tree name, tree function_type) DECL_FUNCTION_INITIALIZED_CLASS_TABLE (fndecl) = htab_create_ggc (50, htab_hash_pointer, htab_eq_pointer, NULL); - /* Initialize the static method invocation compound list */ - DECL_FUNCTION_STATIC_METHOD_INVOCATION_COMPOUND (fndecl) = NULL_TREE; - TREE_CHAIN (fndecl) = TYPE_METHODS (this_class); TYPE_METHODS (this_class) = fndecl; @@ -748,6 +751,9 @@ add_method_1 (tree this_class, int access_flags, tree name, tree function_type) if (access_flags & ACC_SYNCHRONIZED) METHOD_SYNCHRONIZED (fndecl) = 1; if (access_flags & ACC_ABSTRACT) METHOD_ABSTRACT (fndecl) = 1; if (access_flags & ACC_STRICT) METHOD_STRICTFP (fndecl) = 1; + if (access_flags & ACC_SYNTHETIC) DECL_ARTIFICIAL (fndecl) = 1; + if (access_flags & ACC_BRIDGE) METHOD_BRIDGE (fndecl) = 1; + if (access_flags & ACC_VARARGS) METHOD_VARARGS (fndecl) = 1; return fndecl; } @@ -780,6 +786,7 @@ add_field (tree class, tree name, tree field_type, int flags) TREE_CHAIN (field) = TYPE_FIELDS (class); TYPE_FIELDS (class) = field; DECL_CONTEXT (field) = class; + MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (field); if (flags & ACC_PUBLIC) FIELD_PUBLIC (field) = 1; if (flags & ACC_PROTECTED) FIELD_PROTECTED (field) = 1; @@ -791,15 +798,17 @@ add_field (tree class, tree name, tree field_type, int flags) TREE_THIS_VOLATILE (field) = 1; } if (flags & ACC_TRANSIENT) FIELD_TRANSIENT (field) = 1; + if (flags & ACC_ENUM) FIELD_ENUM (field) = 1; + if (flags & ACC_SYNTHETIC) FIELD_SYNTHETIC (field) = 1; if (is_static) { FIELD_STATIC (field) = 1; /* Always make field externally visible. This is required so that native methods can always access the field. */ TREE_PUBLIC (field) = 1; - /* Considered external until we know what classes are being - compiled into this object file. */ - DECL_EXTERNAL (field) = 1; + /* Considered external unless we are compiling it into this + object file. */ + DECL_EXTERNAL (field) = (is_compiled_class (class) != 2); } return field; @@ -1219,6 +1228,10 @@ get_access_flags_from_decl (tree decl) access_flags |= ACC_VOLATILE; if (FIELD_TRANSIENT (decl)) access_flags |= ACC_TRANSIENT; + if (FIELD_ENUM (decl)) + access_flags |= ACC_ENUM; + if (FIELD_SYNTHETIC (decl)) + access_flags |= ACC_SYNTHETIC; return access_flags; } if (TREE_CODE (decl) == TYPE_DECL) @@ -1241,6 +1254,12 @@ get_access_flags_from_decl (tree decl) access_flags |= ACC_PROTECTED; if (CLASS_STRICTFP (decl)) access_flags |= ACC_STRICT; + if (CLASS_ENUM (decl)) + access_flags |= ACC_ENUM; + if (CLASS_SYNTHETIC (decl)) + access_flags |= ACC_SYNTHETIC; + if (CLASS_ANNOTATION (decl)) + access_flags |= ACC_ANNOTATION; return access_flags; } if (TREE_CODE (decl) == FUNCTION_DECL) @@ -1265,6 +1284,12 @@ get_access_flags_from_decl (tree decl) access_flags |= ACC_STRICT; if (METHOD_INVISIBLE (decl)) access_flags |= ACC_INVISIBLE; + if (DECL_ARTIFICIAL (decl)) + access_flags |= ACC_SYNTHETIC; + if (METHOD_BRIDGE (decl)) + access_flags |= ACC_BRIDGE; + if (METHOD_VARARGS (decl)) + access_flags |= ACC_VARARGS; return access_flags; } gcc_unreachable (); @@ -1646,6 +1671,8 @@ make_class_data (tree type) to where objects actually point at, following new g++ ABI. */ tree dtable_start_offset = build_int_cst (NULL_TREE, 2 * POINTER_SIZE / BITS_PER_UNIT); + VEC(int, heap) *field_indexes; + tree first_real_field; this_class_addr = build_static_class_ref (type); decl = TREE_OPERAND (this_class_addr, 0); @@ -1655,15 +1682,28 @@ make_class_data (tree type) { tree dtable = get_dispatch_table (type, this_class_addr); uses_jv_markobj = uses_jv_markobj_p (dtable); - dtable_decl = build_dtable_decl (type); - DECL_INITIAL (dtable_decl) = dtable; - TREE_STATIC (dtable_decl) = 1; - DECL_ARTIFICIAL (dtable_decl) = 1; - DECL_IGNORED_P (dtable_decl) = 1; + if (type == class_type_node && class_dtable_decl != NULL_TREE) + { + /* We've already created some other class, and consequently + we made class_dtable_decl. Now we just want to fill it + in. */ + dtable_decl = class_dtable_decl; + } + else + { + dtable_decl = build_dtable_decl (type); + TREE_STATIC (dtable_decl) = 1; + DECL_ARTIFICIAL (dtable_decl) = 1; + DECL_IGNORED_P (dtable_decl) = 1; + } + TREE_PUBLIC (dtable_decl) = 1; + DECL_INITIAL (dtable_decl) = dtable; if (! flag_indirect_classes) rest_of_decl_compilation (dtable_decl, 1, 0); - if (type == class_type_node) + /* Maybe we're compiling Class as the first class. If so, set + class_dtable_decl to the decl we just made. */ + if (type == class_type_node && class_dtable_decl == NULL_TREE) class_dtable_decl = dtable_decl; } @@ -1673,7 +1713,54 @@ make_class_data (tree type) field = TREE_CHAIN (field); /* Skip dummy fields. */ if (field && DECL_NAME (field) == NULL_TREE) field = TREE_CHAIN (field); /* Skip dummy field for inherited data. */ - for ( ; field != NULL_TREE; field = TREE_CHAIN (field)) + first_real_field = field; + + /* First count static and instance fields. */ + for ( ; field != NULL_TREE; field = TREE_CHAIN (field)) + { + if (! DECL_ARTIFICIAL (field)) + { + if (FIELD_STATIC (field)) + static_field_count++; + else if (uses_jv_markobj || !flag_reduced_reflection) + instance_field_count++; + } + } + field_count = static_field_count + instance_field_count; + field_indexes = VEC_alloc (int, heap, field_count); + + /* gcj sorts fields so that static fields come first, followed by + instance fields. Unfortunately, by the time this takes place we + have already generated the reflection_data for this class, and + that data contians indexes into the fields. So, we generate a + permutation that maps each original field index to its final + position. Then we pass this permutation to + rewrite_reflection_indexes(), which fixes up the reflection + data. */ + { + int i; + int static_count = 0; + int instance_count = static_field_count; + int field_index; + + for (i = 0, field = first_real_field; + field != NULL_TREE; + field = TREE_CHAIN (field), i++) + { + if (! DECL_ARTIFICIAL (field)) + { + field_index = 0; + if (FIELD_STATIC (field)) + field_index = static_count++; + else if (uses_jv_markobj || !flag_reduced_reflection) + field_index = instance_count++; + VEC_quick_push (int, field_indexes, field_index); + } + } + } + + for (field = first_real_field; field != NULL_TREE; + field = TREE_CHAIN (field)) { if (! DECL_ARTIFICIAL (field)) { @@ -1683,7 +1770,6 @@ make_class_data (tree type) as it is used in the creation of the field itself. */ tree init = make_field_value (field); tree initial = DECL_INITIAL (field); - static_field_count++; static_fields = tree_cons (NULL_TREE, init, static_fields); /* If the initial value is a string constant, prevent output_constant from trying to assemble the value. */ @@ -1696,12 +1782,11 @@ make_class_data (tree type) else if (uses_jv_markobj || !flag_reduced_reflection) { tree init = make_field_value (field); - instance_field_count++; instance_fields = tree_cons (NULL_TREE, init, instance_fields); } } } - field_count = static_field_count + instance_field_count; + if (field_count > 0) { static_fields = nreverse (static_fields); @@ -1781,8 +1866,10 @@ make_class_data (tree type) DECL_ARTIFICIAL (class_dtable_decl) = 1; DECL_IGNORED_P (class_dtable_decl) = 1; if (is_compiled_class (class_type_node) != 2) - DECL_EXTERNAL (class_dtable_decl) = 1; - rest_of_decl_compilation (class_dtable_decl, 1, 0); + { + DECL_EXTERNAL (class_dtable_decl) = 1; + rest_of_decl_compilation (class_dtable_decl, 1, 0); + } } super = CLASSTYPE_SUPER (type); @@ -2001,6 +2088,48 @@ make_class_data (tree type) PUSH_FIELD_VALUE (cons, "aux_info", null_pointer_node); PUSH_FIELD_VALUE (cons, "engine", null_pointer_node); + if (TYPE_REFLECTION_DATA (current_class)) + { + int i; + int count = TYPE_REFLECTION_DATASIZE (current_class); + VEC (constructor_elt, gc) *v + = VEC_alloc (constructor_elt, gc, count); + unsigned char *data = TYPE_REFLECTION_DATA (current_class); + tree max_index = build_int_cst (sizetype, count); + tree index = build_index_type (max_index); + tree type = build_array_type (unsigned_byte_type_node, index); + char buf[64]; + tree array; + static int reflection_data_count; + + sprintf (buf, "_reflection_data_%d", reflection_data_count++); + array = build_decl (VAR_DECL, get_identifier (buf), type); + + rewrite_reflection_indexes (field_indexes); + + for (i = 0; i < count; i++) + { + constructor_elt *elt = VEC_quick_push (constructor_elt, v, NULL); + elt->index = build_int_cst (sizetype, i); + elt->value = build_int_cstu (byte_type_node, data[i]); + } + + DECL_INITIAL (array) = build_constructor (type, v); + TREE_STATIC (array) = 1; + DECL_ARTIFICIAL (array) = 1; + DECL_IGNORED_P (array) = 1; + TREE_READONLY (array) = 1; + TREE_CONSTANT (DECL_INITIAL (array)) = 1; + rest_of_decl_compilation (array, 1, 0); + + PUSH_FIELD_VALUE (cons, "reflection_data", build_address_of (array)); + + free (data); + TYPE_REFLECTION_DATA (current_class) = NULL; + } + else + PUSH_FIELD_VALUE (cons, "reflection_data", null_pointer_node); + FINISH_RECORD_CONSTRUCTOR (cons); DECL_INITIAL (decl) = cons; @@ -2066,11 +2195,13 @@ is_compiled_class (tree class) return 1; if (TYPE_ARRAY_P (class)) return 0; + /* We have to check this explicitly to avoid trying to load a class + that we're currently parsing. */ if (class == current_class) return 2; seen_in_zip = (TYPE_JCF (class) && JCF_SEEN_IN_ZIP (TYPE_JCF (class))); - if (CLASS_FROM_CURRENTLY_COMPILED_P (class) || seen_in_zip) + if (CLASS_FROM_CURRENTLY_COMPILED_P (class)) { /* The class was seen in the current ZIP file and will be available as a compiled class in the future but may not have @@ -2182,7 +2313,7 @@ push_super_field (tree this_class, tree super_class) /* Handle the different manners we may have to lay out a super class. */ static tree -maybe_layout_super_class (tree super_class, tree this_class) +maybe_layout_super_class (tree super_class, tree this_class ATTRIBUTE_UNUSED) { if (!super_class) return NULL_TREE; @@ -2201,6 +2332,7 @@ maybe_layout_super_class (tree super_class, tree this_class) super_class = TREE_TYPE (super_class); else { +#if 0 /* do_resolve_class expects an EXPR_WITH_FILE_LOCATION, so we give it one. */ tree this_wrap = NULL_TREE; @@ -2226,6 +2358,8 @@ maybe_layout_super_class (tree super_class, tree this_class) if (!super_class) return NULL_TREE; /* FIXME, NULL_TREE not checked by caller. */ super_class = TREE_TYPE (super_class); +#endif + gcc_unreachable (); } } if (!TYPE_SIZE (super_class)) @@ -2234,6 +2368,22 @@ maybe_layout_super_class (tree super_class, tree this_class) return super_class; } +/* safe_layout_class just makes sure that we can load a class without + disrupting the current_class, input_file, input_line, etc, information + about the class processed currently. */ + +void +safe_layout_class (tree class) +{ + tree save_current_class = current_class; + location_t save_location = input_location; + + layout_class (class); + + current_class = save_current_class; + input_location = save_location; +} + void layout_class (tree this_class) { @@ -2450,9 +2600,10 @@ layout_class_method (tree this_class, tree super_class, tree method_name = DECL_NAME (method_decl); TREE_PUBLIC (method_decl) = 1; - /* Considered external until we know what classes are being - compiled into this object file. */ - DECL_EXTERNAL (method_decl) = 1; + /* Considered external unless it is being compiled into this object + file. */ + DECL_EXTERNAL (method_decl) = ((is_compiled_class (this_class) != 2) + || METHOD_NATIVE (method_decl)); if (ID_INIT_P (method_name)) { @@ -2464,14 +2615,14 @@ layout_class_method (tree this_class, tree super_class, p = ptr; } DECL_CONSTRUCTOR_P (method_decl) = 1; - build_java_argument_signature (TREE_TYPE (method_decl)); + build_java_signature (TREE_TYPE (method_decl)); } else if (! METHOD_STATIC (method_decl)) { tree method_sig = - build_java_argument_signature (TREE_TYPE (method_decl)); + build_java_signature (TREE_TYPE (method_decl)); bool method_override = false; - tree super_method = lookup_argument_method (super_class, method_name, + tree super_method = lookup_java_method (super_class, method_name, method_sig); if (super_method != NULL_TREE && ! METHOD_DUMMY (super_method)) |