X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fjava%2Fdecl.c;h=18b1ec54ecd587a82de4adb99b6e8c5953483b40;hb=65f74cf78c01a259951c5ab69549daf85a4b9aed;hp=06156330b596bdbb34ae4fc005941485b8abe93a;hpb=9a5bbcc22a3ee7c6f724e92e6367716b100fc4f7;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/java/decl.c b/gcc/java/decl.c index 06156330b59..18b1ec54ecd 100644 --- a/gcc/java/decl.c +++ b/gcc/java/decl.c @@ -1,6 +1,7 @@ /* Process declarations and variables for the GNU compiler for the Java(TM) language. - Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 + Free Software Foundation, Inc. This file is part of GNU CC. @@ -35,8 +36,8 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "toplev.h" #include "function.h" #include "except.h" -#include "defaults.h" #include "java-except.h" +#include "ggc.h" #if defined (DEBUG_JAVA_BINDING_LEVELS) extern void indent PROTO((void)); @@ -49,15 +50,13 @@ static struct binding_level *make_binding_level PARAMS ((void)); static boolean emit_init_test_initialization PARAMS ((struct hash_entry *, hash_table_key)); static tree create_primitive_vtable PARAMS ((const char *)); +static tree check_local_named_variable PARAMS ((tree, tree, int, int *)); +static tree check_local_unnamed_variable PARAMS ((tree, tree, tree)); /* Set to non-zero value in order to emit class initilization code before static field references. */ extern int always_initialize_class_p; -#ifndef INT_TYPE_SIZE -#define INT_TYPE_SIZE BITS_PER_WORD -#endif - /* The DECL_MAP is a mapping from (index, type) to a decl node. If index < max_locals, it is the index of a local variable. if index >= max_locals, then index-max_locals is a stack slot. @@ -71,7 +70,9 @@ tree decl_map; /* A list of local variables VAR_DECLs for this method that we have seen debug information, but we have not reached their starting (byte) PC yet. */ -tree pending_local_decls = NULL_TREE; +static tree pending_local_decls = NULL_TREE; + +tree throw_node [2]; /* Push a local variable or stack slot into the decl_map, and assign it an rtl. */ @@ -126,8 +127,7 @@ push_jvm_slot (index, decl) /* Now link the decl into the decl_map. */ if (DECL_LANG_SPECIFIC (decl) == NULL) { - DECL_LANG_SPECIFIC (decl) - = (struct lang_decl *) permalloc (sizeof (struct lang_decl_var)); + MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl); DECL_LOCAL_START_PC (decl) = 0; DECL_LOCAL_END_PC (decl) = DECL_CODE_LENGTH (current_function_decl); DECL_LOCAL_SLOT_NUMBER (decl) = index; @@ -137,6 +137,58 @@ push_jvm_slot (index, decl) return decl; } +/* Find out if 'decl' passed in fits the defined PC location better than + 'best'. Return decl if it does, return best if it doesn't. If decl + is returned, then updated is set to true. */ + +static tree +check_local_named_variable (best, decl, pc, updated) + tree best; + tree decl; + int pc; + int *updated; +{ + if (pc >= DECL_LOCAL_START_PC (decl) + && pc < DECL_LOCAL_END_PC (decl)) + { + if (best == NULL_TREE + || (DECL_LOCAL_START_PC (decl) > DECL_LOCAL_START_PC (best) + && DECL_LOCAL_END_PC (decl) < DECL_LOCAL_END_PC (best))) + { + *updated = 1; + return decl; + } + } + + return best; +} + +/* Find the best declaration based upon type. If 'decl' fits 'type' better + than 'best', return 'decl'. Otherwise return 'best'. */ + +static tree +check_local_unnamed_variable (best, decl, type) + tree best; + tree decl; + tree type; +{ + if (TREE_TYPE (decl) == type + || (TREE_CODE (TREE_TYPE (decl)) == TREE_CODE (type) + && TYPE_PRECISION (TREE_TYPE (decl)) <= 32 + && TYPE_PRECISION (type) <= 32 + && TREE_CODE (type) != POINTER_TYPE) + || (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE + && type == ptr_type_node)) + { + if (best == NULL_TREE + || (TREE_TYPE (decl) == type && TREE_TYPE (best) != type)) + return decl; + } + + return best; +} + + /* Find a VAR_DECL (or PARM_DECL) at local index INDEX that has type TYPE, that is valid at PC (or -1 if any pc). If there is no existing matching decl, allocate one. */ @@ -149,33 +201,41 @@ find_local_variable (index, type, pc) { tree decl = TREE_VEC_ELT (decl_map, index); tree best = NULL_TREE; + int found_scoped_var = 0; + /* Scan through every declaration that has been created in this slot. */ while (decl != NULL_TREE) { - int in_range; - in_range = pc < 0 - || (pc >= DECL_LOCAL_START_PC (decl) - && pc < DECL_LOCAL_END_PC (decl)); - - if ((TREE_TYPE (decl) == type - || (TREE_CODE (TREE_TYPE (decl)) == TREE_CODE (type) - && TYPE_PRECISION (TREE_TYPE (decl)) <= 32 - && TYPE_PRECISION (type) <= 32 - && TREE_CODE (type) != POINTER_TYPE) - || (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE - && type == ptr_type_node)) - && in_range) + /* Variables created in give_name_to_locals() have a name and have + a specified scope, so we can handle them specifically. We want + to use the specific decls created for those so they are assigned + the right variables in the debugging information. */ + if (DECL_NAME (decl) != NULL_TREE) { - if (best == NULL_TREE - || (TREE_TYPE (decl) == type && TREE_TYPE (best) != type) - || DECL_LOCAL_START_PC (decl) > DECL_LOCAL_START_PC (best) - || DECL_LOCAL_END_PC (decl) < DECL_LOCAL_START_PC (decl)) - best = decl; - } + /* This is a variable we have a name for, so it has a scope + supplied in the class file. But it only matters when we + actually have a PC to use. If pc<0, then we are asking + for a stack slot and this decl won't be one of those. */ + if (pc >= 0) + best = check_local_named_variable (best, decl, pc, + &found_scoped_var); + } + /* We scan for type information unless we found a variable in the + proper scope already. */ + else if (!found_scoped_var) + { + /* If we don't have scoping information for a variable, we use + a different method to look it up. */ + best = check_local_unnamed_variable (best, decl, type); + } + decl = DECL_LOCAL_SLOT_CHAIN (decl); } + if (best != NULL_TREE) return best; + + /* If we don't find a match, create one with the type passed in. */ return push_jvm_slot (index, build_decl (VAR_DECL, NULL_TREE, type)); } @@ -287,121 +347,10 @@ static int keep_next_level_flag; if it has subblocks. */ static int keep_next_if_subblocks; + +tree java_global_trees[JTI_MAX]; -tree object_type_node; -tree unqualified_object_id_node; -tree object_ptr_type_node; -tree string_type_node; -tree string_ptr_type_node; -tree throwable_type_node; -tree runtime_exception_type_node; -tree error_exception_type_node; -tree rawdata_ptr_type_node; -tree *predef_filenames; -int predef_filenames_size; - -tree boolean_type_node; - -tree return_address_type_node; - -tree byte_type_node; -tree short_type_node; -tree int_type_node; -tree long_type_node; - -tree promoted_byte_type_node; -tree promoted_short_type_node; -tree promoted_char_type_node; -tree promoted_boolean_type_node; - -tree unsigned_byte_type_node; -tree unsigned_short_type_node; -tree unsigned_int_type_node; -tree unsigned_long_type_node; - -/* The type for struct methodtable. */ -tree methodtable_type; -tree methodtable_ptr_type; - -tree utf8const_type; -tree utf8const_ptr_type; -tree class_type_node; -tree class_ptr_type; -tree field_type_node; -tree field_ptr_type_node; -tree field_info_union_node; -tree jexception_type; -tree jexception_ptr_type; -tree lineNumberEntry_type; -tree lineNumbers_type; -tree constants_type_node; -tree dtable_type; -tree dtable_ptr_type; -tree method_type_node; -tree method_ptr_type_node; -tree nativecode_ptr_array_type_node; -tree one_elt_array_domain_type; -tree access_flags_type_node; -tree class_dtable_decl; - -/* Expressions that are constants with value zero, of types - `long', `float' and `double'. */ -tree long_zero_node; -tree float_zero_node; -tree double_zero_node; - -tree empty_stmt_node; - -/* Nodes for boolean constants TRUE and FALSE. */ -tree boolean_true_node; -tree boolean_false_node; - -tree TYPE_identifier_node; -tree init_identifier_node; -tree clinit_identifier_node; -tree finit_identifier_node; -tree void_signature_node; -tree length_identifier_node; -tree this_identifier_node; -tree super_identifier_node; -tree continue_identifier_node; -tree access0_identifier_node; /* 1.1 */ -tree end_params_node; - -/* References to internal libjava functions we use. */ -tree alloc_object_node; -tree soft_instanceof_node; -tree soft_checkcast_node; -tree soft_initclass_node; -tree soft_newarray_node; -tree soft_anewarray_node; -tree soft_multianewarray_node; -tree soft_badarrayindex_node; -tree soft_nullpointer_node; -tree throw_node [2]; -tree soft_checkarraystore_node; -tree soft_monitorenter_node; -tree soft_monitorexit_node; -tree soft_lookupinterfacemethod_node; -tree soft_lookupjnimethod_node; -tree soft_getjnienvnewframe_node; -tree soft_jnipopsystemframe_node; -tree soft_fmod_node; -tree soft_exceptioninfo_call_node; -tree soft_idiv_node; -tree soft_irem_node; -tree soft_ldiv_node; -tree soft_lrem_node; - -/* Declarations for vtables for primitive arrays. */ -tree boolean_array_vtable; -tree byte_array_vtable; -tree char_array_vtable; -tree short_array_vtable; -tree int_array_vtable; -tree long_array_vtable; -tree float_array_vtable; -tree double_array_vtable; +tree predef_filenames[PREDEF_FILENAMES_SIZE]; /* Build (and pushdecl) a "promoted type" for all standard types shorter than int. */ @@ -429,11 +378,6 @@ push_promoted_type (name, actual_type) return type; } -/* Nodes for integer constants. */ -tree integer_two_node; -tree integer_four_node; -tree integer_negative_one_node; - /* Return a definition for a builtin function named NAME and whose data type is TYPE. TYPE should be a function type with argument types. FUNCTION_CODE tells later passes how to compile calls to this function. @@ -455,7 +399,7 @@ builtin_function (name, type, function_code, class, library_name) TREE_PUBLIC (decl) = 1; if (library_name) DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name); - make_decl_rtl (decl, NULL_PTR, 1); + make_decl_rtl (decl, NULL_PTR); pushdecl (decl); DECL_BUILT_IN_CLASS (decl) = class; DECL_FUNCTION_CODE (decl) = function_code; @@ -473,7 +417,7 @@ create_primitive_vtable (name) sprintf (buf, "_Jv_%sVTable", name); r = build_decl (VAR_DECL, get_identifier (buf), ptr_type_node); DECL_EXTERNAL (r) = 1; - make_decl_rtl (r, buf, 1); + make_decl_rtl (r, buf); return r; } @@ -484,6 +428,8 @@ init_decl_processing () tree field = NULL_TREE; tree t; + init_class_processing (); + current_function_decl = NULL; current_binding_level = NULL_BINDING_LEVEL; free_binding_level = NULL_BINDING_LEVEL; @@ -528,7 +474,7 @@ init_decl_processing () integer_one_node = build_int_2 (1, 0); integer_two_node = build_int_2 (2, 0); integer_four_node = build_int_2 (4, 0); - integer_negative_one_node = build_int_2 (-1, 0); + integer_minus_one_node = build_int_2 (-1, -1); size_zero_node = size_int (0); size_one_node = size_int (1); @@ -626,10 +572,8 @@ init_decl_processing () rawdata_ptr_type_node = promote_type (lookup_class (get_identifier ("gnu.gcj.RawData"))); - /* This section has to be updated as items are added to the previous - section. */ - predef_filenames_size = 7; - predef_filenames = (tree *)xmalloc (predef_filenames_size * sizeof (tree)); + /* If you add to this section, don't forget to increase + PREDEF_FILENAMES_SIZE. */ predef_filenames [0] = get_identifier ("java/lang/Class.java"); predef_filenames [1] = get_identifier ("java/lang/Error.java"); predef_filenames [2] = get_identifier ("java/lang/Object.java"); @@ -646,13 +590,19 @@ init_decl_processing () TYPE_identifier_node = get_identifier ("TYPE"); init_identifier_node = get_identifier (""); clinit_identifier_node = get_identifier (""); - finit_identifier_node = get_identifier ("$finit$"); + /* Legacy `$finit$' special method identifier. This needs to be + recognized as equivalent to `finit$' but isn't generated anymore. */ + finit_leg_identifier_node = get_identifier ("$finit$"); + /* The new `finit$' special method identifier. This one is now + generated in place of `$finit$'. */ + finit_identifier_node = get_identifier ("finit$"); void_signature_node = get_identifier ("()V"); length_identifier_node = get_identifier ("length"); this_identifier_node = get_identifier ("this"); super_identifier_node = get_identifier ("super"); continue_identifier_node = get_identifier ("continue"); access0_identifier_node = get_identifier ("access$0"); + classdollar_identifier_node = get_identifier ("class$"); /* for lack of a better place to put this stub call */ init_expr_processing(); @@ -723,6 +673,7 @@ init_decl_processing () PUSH_FIELD (class_type_node, field, "depth", short_type_node); PUSH_FIELD (class_type_node, field, "ancestors", ptr_type_node); PUSH_FIELD (class_type_node, field, "idt", ptr_type_node); + PUSH_FIELD (class_type_node, field, "arrayclass", ptr_type_node); for (t = TYPE_FIELDS (class_type_node); t != NULL_TREE; t = TREE_CHAIN (t)) FIELD_PRIVATE (t) = 1; push_super_field (class_type_node, object_type_node); @@ -826,7 +777,7 @@ init_decl_processing () t = tree_cons (NULL_TREE, int_type_node, tree_cons (NULL_TREE, int_type_node, endlink)); soft_newarray_node - = builtin_function ("_Jv_NewArray", + = builtin_function ("_Jv_NewPrimArray", build_function_type(ptr_type_node, t), 0, NOT_BUILT_IN, NULL_PTR); DECL_IS_MALLOC (soft_newarray_node) = 1; @@ -955,7 +906,17 @@ init_decl_processing () build_function_type (long_type_node, t), 0, NOT_BUILT_IN, NULL_PTR); - init_class_processing (); + init_jcf_parse (); + + /* Register nodes with the garbage collector. */ + ggc_add_tree_root (java_global_trees, + sizeof (java_global_trees) / sizeof (tree)); + ggc_add_tree_root (throw_node, + sizeof (throw_node) / sizeof (tree)); + ggc_add_tree_root (predef_filenames, + sizeof (predef_filenames) / sizeof (tree)); + ggc_add_tree_root (&decl_map, 1); + ggc_add_tree_root (&pending_local_decls, 1); } @@ -1584,6 +1545,10 @@ set_block (block) register tree block; { current_binding_level->this_block = block; + current_binding_level->names = chainon (current_binding_level->names, + BLOCK_VARS (block)); + current_binding_level->blocks = chainon (current_binding_level->blocks, + BLOCK_SUBBLOCKS (block)); } /* integrate_decl_tree calls this function. */ @@ -1595,8 +1560,8 @@ copy_lang_decl (node) int lang_decl_size = TREE_CODE (node) == VAR_DECL ? sizeof (struct lang_decl_var) : sizeof (struct lang_decl); - struct lang_decl *x = (struct lang_decl *) oballoc (lang_decl_size); - bcopy ((PTR) DECL_LANG_SPECIFIC (node), (PTR) x, lang_decl_size); + struct lang_decl *x = (struct lang_decl *) ggc_alloc (lang_decl_size); + memcpy (x, DECL_LANG_SPECIFIC (node), lang_decl_size); DECL_LANG_SPECIFIC (node) = x; } @@ -1616,6 +1581,7 @@ give_name_to_locals (jcf) JCF *jcf; { int i, n = DECL_LOCALVARIABLES_OFFSET (current_function_decl); + int code_offset = DECL_CODE_OFFSET (current_function_decl); tree parm; pending_local_decls = NULL_TREE; if (n == 0) @@ -1652,8 +1618,14 @@ give_name_to_locals (jcf) "bad PC range for debug info for local `%s'"); end_pc = DECL_CODE_LENGTH (current_function_decl); } - DECL_LANG_SPECIFIC (decl) - = (struct lang_decl *) permalloc (sizeof (struct lang_decl_var)); + + /* Adjust start_pc if necessary so that the local's first + store operation will use the relevant DECL as a + destination. Fore more information, read the leading + comments for expr.c:maybe_adjust_start_pc. */ + start_pc = maybe_adjust_start_pc (jcf, code_offset, start_pc, slot); + + MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl); DECL_LOCAL_SLOT_NUMBER (decl) = slot; DECL_LOCAL_START_PC (decl) = start_pc; #if 0 @@ -1762,10 +1734,6 @@ complete_start_java_method (fndecl) emit_init_test_initialization, 0); } - /* Allocate further tree nodes temporarily during compilation - of this function only. */ - temporary_allocation (); - #if 0 /* If this fcn was already referenced via a block-scope `extern' decl (or an implicit decl), propagate certain information about the usage. */ @@ -1841,7 +1809,7 @@ start_java_method (fndecl) i = DECL_MAX_LOCALS(fndecl) + DECL_MAX_STACK(fndecl); decl_map = make_tree_vec (i); - type_map = (tree *) oballoc (i * sizeof (tree)); + type_map = (tree *) xrealloc (type_map, i * sizeof (tree)); #if defined(DEBUG_JAVA_BINDING_LEVELS) fprintf (stderr, "%s:\n", (*decl_printable_name) (fndecl, 2)); @@ -1855,8 +1823,8 @@ start_java_method (fndecl) { tree parm_name = NULL_TREE, parm_decl; tree parm_type = TREE_VALUE (tem); - if (i >= DECL_MAX_LOCALS(fndecl)) - fatal ("function has more parameters than local slots"); + if (i >= DECL_MAX_LOCALS (fndecl)) + abort (); parm_decl = build_decl (PARM_DECL, parm_name, parm_type); DECL_CONTEXT (parm_decl) = fndecl; @@ -1920,6 +1888,64 @@ end_java_method () rest_of_compilation (fndecl); current_function_decl = NULL_TREE; - permanent_allocation (1); asynchronous_exceptions = flag_asynchronous_exceptions; } + +/* Mark language-specific parts of T for garbage-collection. */ + +void +lang_mark_tree (t) + tree t; +{ + if (TREE_CODE (t) == IDENTIFIER_NODE) + { + struct lang_identifier *li = (struct lang_identifier *) t; + ggc_mark_tree (li->global_value); + ggc_mark_tree (li->local_value); + ggc_mark_tree (li->utf8_ref); + } + else if (TREE_CODE (t) == VAR_DECL + || TREE_CODE (t) == PARM_DECL + || TREE_CODE (t) == FIELD_DECL) + { + struct lang_decl_var *ldv = + ((struct lang_decl_var *) DECL_LANG_SPECIFIC (t)); + if (ldv) + { + ggc_mark (ldv); + ggc_mark_tree (ldv->slot_chain); + ggc_mark_tree (ldv->am); + ggc_mark_tree (ldv->wfl); + } + } + else if (TREE_CODE (t) == FUNCTION_DECL) + { + struct lang_decl *ld = DECL_LANG_SPECIFIC (t); + + if (ld) + { + ggc_mark (ld); + ggc_mark_tree (ld->wfl); + ggc_mark_tree (ld->throws_list); + ggc_mark_tree (ld->function_decl_body); + ggc_mark_tree (ld->called_constructor); + ggc_mark_tree (ld->inner_access); + } + } + else if (TYPE_P (t)) + { + struct lang_type *lt = TYPE_LANG_SPECIFIC (t); + + if (lt) + { + ggc_mark (lt); + ggc_mark_tree (lt->signature); + ggc_mark_tree (lt->cpool_data_ref); + ggc_mark_tree (lt->finit_stmt_list); + ggc_mark_tree (lt->clinit_stmt_list); + ggc_mark_tree (lt->ii_block); + ggc_mark_tree (lt->dot_class); + ggc_mark_tree (lt->package_list); + } + } +}