Commit 00150bf9 by Andrew Haley Committed by Andrew Haley

verify.c (verify_jvm_instructions): Comment change only.

2004-07-20  Andrew Haley  <aph@redhat.com>

	* verify.c (verify_jvm_instructions): Comment change only.

	* typeck.c (build_java_array_type): Add size field to array name.

	* java-tree.h (LOCAL_SLOT_P): New.
	(update_aliases): Add PC argument.
	(pushdecl_function_level): New function.

	* java-gimplify.c (java_gimplify_expr): Handle VAR_DECL,
	MODIFY_EXPR, and SAVE_EXPR.
	(java_gimplify_modify_expr): New function.

	* expr.c (push_type_0): Call find_stack_slot() to create temporary.
	(expand_iinc): Pass PC to update_aliases().
	(STORE_INTERNAL): Likewise.
	(process_jvm_instruction): Likewise.

	* decl.c (base_decl_map): New variable.
	(uniq): New variable.
	(update_aliases): Rewrite with more thorough checking.
	(debug_variable_p): New function.
	(push_jvm_slot): Don't initialize local variable.  Don't pushdecl.
	(check_local_named_variable): Delete whole function.
	(initialize_local_variable): New function.
	(check_local_unnamed_variable): Add checks and comments.
	(find_local_variable): Rewrite.
	(java_replace_reference): New function.
	(function_binding_level): New variable.
	(pushdecl_function_level): New function.
	(maybe_pushlevels): Set DECL_LOCAL_END_PC.
	(maybe_pushlevels): Call pushdecl() on each of the new decls.
	(start_java_method): Reset uniq.  Create base_decl_map.  Set
	function_binding_level.
	(end_java_method): Null unused fields to save memory.

From-SVN: r85009
parent 5d16533a
2004-07-20 Andrew Haley <aph@redhat.com>
* verify.c (verify_jvm_instructions): Comment change only.
* typeck.c (build_java_array_type): Add size field to array name.
* java-tree.h (LOCAL_SLOT_P): New.
(update_aliases): Add PC argument.
(pushdecl_function_level): New function.
* java-gimplify.c (java_gimplify_expr): Handle VAR_DECL,
MODIFY_EXPR, and SAVE_EXPR.
(java_gimplify_modify_expr): New function.
* expr.c (push_type_0): Call find_stack_slot() to create temporary.
(expand_iinc): Pass PC to update_aliases().
(STORE_INTERNAL): Likewise.
(process_jvm_instruction): Likewise.
* decl.c (base_decl_map): New variable.
(uniq): New variable.
(update_aliases): Rewrite with more thorough checking.
(debug_variable_p): New function.
(push_jvm_slot): Don't initialize local variable. Don't pushdecl.
(check_local_named_variable): Delete whole function.
(initialize_local_variable): New function.
(check_local_unnamed_variable): Add checks and comments.
(find_local_variable): Rewrite.
(java_replace_reference): New function.
(function_binding_level): New variable.
(pushdecl_function_level): New function.
(maybe_pushlevels): Set DECL_LOCAL_END_PC.
(maybe_pushlevels): Call pushdecl() on each of the new decls.
(start_java_method): Reset uniq. Create base_decl_map. Set
function_binding_level.
(end_java_method): Null unused fields to save memory.
2004-07-20 Nathan Sidwell <nathan@codesourcery.com> 2004-07-20 Nathan Sidwell <nathan@codesourcery.com>
* class.c (add_interface_do): Remove. * class.c (add_interface_do): Remove.
......
...@@ -57,7 +57,6 @@ static tree lookup_name_current_level (tree); ...@@ -57,7 +57,6 @@ static tree lookup_name_current_level (tree);
static tree push_promoted_type (const char *, tree); static tree push_promoted_type (const char *, tree);
static struct binding_level *make_binding_level (void); static struct binding_level *make_binding_level (void);
static tree create_primitive_vtable (const char *); static tree create_primitive_vtable (const char *);
static tree check_local_named_variable (tree, tree, int, int *);
static tree check_local_unnamed_variable (tree, tree, tree); static tree check_local_unnamed_variable (tree, tree, tree);
/* Name of the Cloneable class. */ /* Name of the Cloneable class. */
...@@ -76,14 +75,20 @@ tree java_io_serializable_identifier_node; ...@@ -76,14 +75,20 @@ tree java_io_serializable_identifier_node;
static GTY(()) tree decl_map; static GTY(()) tree decl_map;
/* The base_decl_map is contains one variable of ptr_type: this is
used to contain every variable of reference type that is ever
stored in a local variable slot. */
static GTY(()) tree base_decl_map;
/* An index used to make temporary identifiers unique. */
static int uniq;
/* A list of local variables VAR_DECLs for this method that we have seen /* 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. */ debug information, but we have not reached their starting (byte) PC yet. */
static GTY(()) tree pending_local_decls; static GTY(()) tree pending_local_decls;
/* Push a local variable or stack slot into the decl_map,
and assign it an rtl. */
#if defined(DEBUG_JAVA_BINDING_LEVELS) #if defined(DEBUG_JAVA_BINDING_LEVELS)
int binding_depth = 0; int binding_depth = 0;
int is_class_level = 0; int is_class_level = 0;
...@@ -99,51 +104,67 @@ indent (void) ...@@ -99,51 +104,67 @@ indent (void)
} }
#endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */ #endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
/* Copy the value in decl into every alias in the same local variable /* True if decl is a named local variable, i.e. if it is an alias
slot. */ that's used only for debugging purposes. */
static bool
debug_variable_p (tree decl)
{
if (TREE_CODE (decl) == PARM_DECL)
return false;
if (LOCAL_SLOT_P (decl))
return false;
return true;
}
/* Copy the value in decl into every live alias in the same local
variable slot. Some of these will be dead stores removed by the
optimizer. */
void void
update_aliases (tree decl, int index) update_aliases (tree decl, int index, int pc)
{ {
tree tmp = TREE_VEC_ELT (decl_map, index); tree decl_type = TREE_TYPE (decl);
tree type = TREE_TYPE (decl); tree tmp;
while (tmp != NULL_TREE)
if (debug_variable_p (decl))
abort ();
for (tmp = TREE_VEC_ELT (decl_map, index);
tmp != NULL_TREE;
tmp = DECL_LOCAL_SLOT_CHAIN (tmp))
{ {
tree tmp_type = TREE_TYPE (tmp);
if (tmp != decl if (tmp != decl
&& ! LOCAL_VAR_OUT_OF_SCOPE_P (tmp) && LOCAL_SLOT_P (tmp) == 0
&& TYPE_MODE (type) == TYPE_MODE (TREE_TYPE (tmp))) && (pc == -1
|| (pc >= DECL_LOCAL_START_PC (tmp)
&& pc <= DECL_LOCAL_END_PC (tmp)))
&& (tmp_type == decl_type
|| (INTEGRAL_TYPE_P (tmp_type)
&& INTEGRAL_TYPE_P (decl_type)
&& TYPE_PRECISION (decl_type) <= 32
&& TYPE_PRECISION (tmp_type) <= 32)
|| (TREE_CODE (tmp_type) == POINTER_TYPE
&& TREE_CODE (decl_type) == POINTER_TYPE)))
{ {
tree src = build1 (NOP_EXPR, TREE_TYPE (tmp), decl); tree src = build1 (NOP_EXPR, tmp_type, decl);
java_add_stmt (build2 (MODIFY_EXPR, TREE_TYPE (tmp), tmp, src)); if (LOCAL_VAR_OUT_OF_SCOPE_P (tmp))
abort ();
java_add_stmt
(build (MODIFY_EXPR, tmp_type, tmp, src));
} }
tmp = DECL_LOCAL_SLOT_CHAIN (tmp);
} }
} }
static tree static tree
push_jvm_slot (int index, tree decl) push_jvm_slot (int index, tree decl)
{ {
tree type = TREE_TYPE (decl);
tree tmp;
DECL_CONTEXT (decl) = current_function_decl; DECL_CONTEXT (decl) = current_function_decl;
layout_decl (decl, 0); layout_decl (decl, 0);
/* Look for another variable of the same mode in this slot. */
tmp = TREE_VEC_ELT (decl_map, index);
while (tmp != NULL_TREE)
{
if (! LOCAL_VAR_OUT_OF_SCOPE_P (tmp)
&& TYPE_MODE (type) == TYPE_MODE (TREE_TYPE (tmp)))
{
/* At the point of its creation this decl inherits whatever
is in the slot. */
tree src = build1 (NOP_EXPR, TREE_TYPE (decl), tmp);
java_add_stmt (build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, src));
break;
}
tmp = DECL_LOCAL_SLOT_CHAIN (tmp);
}
/* Now link the decl into the decl_map. */ /* Now link the decl into the decl_map. */
if (DECL_LANG_SPECIFIC (decl) == NULL) if (DECL_LANG_SPECIFIC (decl) == NULL)
{ {
...@@ -155,31 +176,54 @@ push_jvm_slot (int index, tree decl) ...@@ -155,31 +176,54 @@ push_jvm_slot (int index, tree decl)
DECL_LOCAL_SLOT_CHAIN (decl) = TREE_VEC_ELT (decl_map, index); DECL_LOCAL_SLOT_CHAIN (decl) = TREE_VEC_ELT (decl_map, index);
TREE_VEC_ELT (decl_map, index) = decl; TREE_VEC_ELT (decl_map, index) = decl;
if (TREE_CODE (decl) != PARM_DECL)
pushdecl (decl);
return decl; return decl;
} }
/* Find out if 'decl' passed in fits the defined PC location better than /* At the point of its creation a local variable decl inherits
'best'. Return decl if it does, return best if it doesn't. If decl whatever is already in the same slot. In the case of a local
is returned, then updated is set to true. */ variable that is declared but unused, we won't find anything. */
static tree static void
check_local_named_variable (tree best, tree decl, int pc, int *updated) initialize_local_variable (tree decl, int index)
{ {
if (pc >= DECL_LOCAL_START_PC (decl) tree decl_type = TREE_TYPE (decl);
&& pc < DECL_LOCAL_END_PC (decl)) if (TREE_CODE (decl_type) == POINTER_TYPE)
{ {
if (best == NULL_TREE tree tmp = TREE_VEC_ELT (base_decl_map, index);
|| (DECL_LOCAL_START_PC (decl) > DECL_LOCAL_START_PC (best)
&& DECL_LOCAL_END_PC (decl) < DECL_LOCAL_END_PC (best))) if (tmp)
{ {
*updated = 1; /* At the point of its creation this decl inherits whatever
return decl; is in the slot. */
tree src = build1 (NOP_EXPR, decl_type, tmp);
java_add_stmt
(build (MODIFY_EXPR, decl_type, decl, src));
} }
} }
else
{
tree tmp;
return best; for (tmp = TREE_VEC_ELT (decl_map, index);
tmp != NULL_TREE;
tmp = DECL_LOCAL_SLOT_CHAIN (tmp))
{
tree tmp_type = TREE_TYPE (tmp);
if (tmp != decl
&& ! debug_variable_p (tmp)
&& (tmp_type == decl_type
|| (INTEGRAL_TYPE_P (tmp_type)
&& INTEGRAL_TYPE_P (decl_type)
&& TYPE_PRECISION (decl_type) <= 32
&& TYPE_PRECISION (tmp_type) <= 32
&& TYPE_PRECISION (tmp_type) >= TYPE_PRECISION (decl_type))))
{
java_add_stmt
(build (MODIFY_EXPR, decl_type, decl, tmp));
return;
}
}
}
} }
/* Find the best declaration based upon type. If 'decl' fits 'type' better /* Find the best declaration based upon type. If 'decl' fits 'type' better
...@@ -188,16 +232,25 @@ check_local_named_variable (tree best, tree decl, int pc, int *updated) ...@@ -188,16 +232,25 @@ check_local_named_variable (tree best, tree decl, int pc, int *updated)
static tree static tree
check_local_unnamed_variable (tree best, tree decl, tree type) check_local_unnamed_variable (tree best, tree decl, tree type)
{ {
if (TREE_TYPE (decl) == type tree decl_type = TREE_TYPE (decl);
|| (TREE_CODE (TREE_TYPE (decl)) == TREE_CODE (type)
&& TYPE_PRECISION (TREE_TYPE (decl)) <= 32 if (LOCAL_VAR_OUT_OF_SCOPE_P (decl))
abort ();
/* Use the same decl for all integer types <= 32 bits. This is
necessary because sometimes a value is stored as (for example)
boolean but loaded as int. */
if (decl_type == type
|| (INTEGRAL_TYPE_P (decl_type)
&& INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (decl_type) <= 32
&& TYPE_PRECISION (type) <= 32 && TYPE_PRECISION (type) <= 32
&& TREE_CODE (type) != POINTER_TYPE) && TYPE_PRECISION (decl_type) >= TYPE_PRECISION (type))
|| (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE || (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
&& type == ptr_type_node)) && type == ptr_type_node))
{ {
if (best == NULL_TREE if (best == NULL_TREE
|| (TREE_TYPE (decl) == type && TREE_TYPE (best) != type)) || (decl_type == type && TREE_TYPE (best) != type))
return decl; return decl;
} }
...@@ -210,63 +263,103 @@ check_local_unnamed_variable (tree best, tree decl, tree type) ...@@ -210,63 +263,103 @@ check_local_unnamed_variable (tree best, tree decl, tree type)
If there is no existing matching decl, allocate one. */ If there is no existing matching decl, allocate one. */
tree tree
find_local_variable (int index, tree type, int pc) find_local_variable (int index, tree type, int pc ATTRIBUTE_UNUSED)
{ {
tree decl = TREE_VEC_ELT (decl_map, index); tree tmp = TREE_VEC_ELT (decl_map, index);
tree best = NULL_TREE; tree decl = NULL_TREE;
int found_scoped_var = 0;
/* Scan through every declaration that has been created in this slot. */ /* Scan through every declaration that has been created in this
while (decl != NULL_TREE) slot. We're only looking for variables that correspond to local
index declarations and PARM_DECLs, not named variables: such
local variables are used only for debugging information. */
while (tmp != NULL_TREE)
{ {
bool has_name = false; if (! debug_variable_p (tmp))
tree name = DECL_NAME (decl); decl = check_local_unnamed_variable (decl, tmp, type);
if (name && IDENTIFIER_POINTER (name)) tmp = DECL_LOCAL_SLOT_CHAIN (tmp);
has_name = IDENTIFIER_POINTER (name)[0] != '#';
/* 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 (has_name)
{
/* 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. /* If we don't find a match, create one with the type passed in.
Ths name of the variable is #n#m, which n is the variable index The name of the variable is #n#m, which n is the variable index
in the local variable area and m is a dummy identifier for in the local variable area and m is a dummy identifier for
uniqueness -- multiple variables may share the same local uniqueness -- multiple variables may share the same local
variable index. */ variable index. We don't call pushdecl() to push pointer types
into a binding expr because they'll all be replaced by a single
variable that is used for every reference in that local variable
slot. */
if (! decl)
{ {
char buf[64]; char buf[64];
tree name; tree name;
static int uniq; sprintf (buf, "#slot#%d#%d", index, uniq++);
sprintf (buf, "#%d#%d", index, uniq++); name = get_identifier (buf);
name = get_identifier (buf); decl = build_decl (VAR_DECL, name, type);
DECL_IGNORED_P (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
decl = push_jvm_slot (index, decl);
LOCAL_SLOT_P (decl) = 1;
if (TREE_CODE (type) != POINTER_TYPE)
pushdecl_function_level (decl);
}
return push_jvm_slot (index, build_decl (VAR_DECL, name, type)); /* As well as creating a local variable that matches the type, we
} also create a base variable (of ptr_type) that will hold all its
aliases. */
if (TREE_CODE (type) == POINTER_TYPE
&& ! TREE_VEC_ELT (base_decl_map, index))
{
char buf[64];
tree name;
tree base_decl;
sprintf (buf, "#ref#%d#%d", index, uniq++);
name = get_identifier (buf);
base_decl
= TREE_VEC_ELT (base_decl_map, index)
= build_decl (VAR_DECL, name, ptr_type_node);
pushdecl_function_level (base_decl);
DECL_IGNORED_P (base_decl) = 1;
DECL_ARTIFICIAL (base_decl) = 1;
}
return decl;
}
/* Called during gimplification for every variable. If the variable
is a temporary of pointer type, replace it with a common variable
thath is used to hold all pointer types that are ever stored in
that slot. Set WANT_LVALUE if you want a variable that is to be
written to. */
tree
java_replace_reference (tree var_decl, bool want_lvalue)
{
tree decl_type;
if (! base_decl_map)
return var_decl;
decl_type = TREE_TYPE (var_decl);
if (TREE_CODE (decl_type) == POINTER_TYPE)
{
if (DECL_LANG_SPECIFIC (var_decl)
&& LOCAL_SLOT_P (var_decl))
{
int index = DECL_LOCAL_SLOT_NUMBER (var_decl);
tree base_decl = TREE_VEC_ELT (base_decl_map, index);
if (! base_decl)
abort ();
if (! want_lvalue)
base_decl = build1 (NOP_EXPR, decl_type, base_decl);
return base_decl;
}
}
return var_decl;
} }
...@@ -331,6 +424,11 @@ static GTY(()) struct binding_level *free_binding_level; ...@@ -331,6 +424,11 @@ static GTY(()) struct binding_level *free_binding_level;
static GTY(()) struct binding_level *global_binding_level; static GTY(()) struct binding_level *global_binding_level;
/* The binding level that holds variables declared at the outermost
level within a function body. */
static struct binding_level *function_binding_level;
/* A PC value bigger than any PC value we may ever may encounter. */ /* A PC value bigger than any PC value we may ever may encounter. */
#define LARGEST_PC (( (unsigned int)1 << (HOST_BITS_PER_INT - 1)) - 1) #define LARGEST_PC (( (unsigned int)1 << (HOST_BITS_PER_INT - 1)) - 1)
...@@ -1174,6 +1272,20 @@ pushdecl_top_level (tree x) ...@@ -1174,6 +1272,20 @@ pushdecl_top_level (tree x)
return t; return t;
} }
/* Like pushdecl, only it places X in FUNCTION_BINDING_LEVEL, if appropriate. */
tree
pushdecl_function_level (tree x)
{
tree t;
struct binding_level *b = current_binding_level;
current_binding_level = function_binding_level;
t = pushdecl (x);
current_binding_level = b;
return t;
}
/* Nonzero if we are currently in the global binding level. */ /* Nonzero if we are currently in the global binding level. */
int int
...@@ -1497,9 +1609,13 @@ maybe_pushlevels (int pc) ...@@ -1497,9 +1609,13 @@ maybe_pushlevels (int pc)
pending_local_decls = *ptr; pending_local_decls = *ptr;
*ptr = NULL_TREE; *ptr = NULL_TREE;
/* Force non-nested range to be nested in current range. */ /* Force non-nested range to be nested in current range by
truncating variable lifetimes. */
if (end_pc > current_binding_level->end_pc) if (end_pc > current_binding_level->end_pc)
end_pc = current_binding_level->end_pc; {
end_pc = current_binding_level->end_pc;
DECL_LOCAL_END_PC (decl) = end_pc;
}
maybe_start_try (pc, end_pc); maybe_start_try (pc, end_pc);
...@@ -1512,6 +1628,8 @@ maybe_pushlevels (int pc) ...@@ -1512,6 +1628,8 @@ maybe_pushlevels (int pc)
{ {
next = TREE_CHAIN (decl); next = TREE_CHAIN (decl);
push_jvm_slot (DECL_LOCAL_SLOT_NUMBER (decl), decl); push_jvm_slot (DECL_LOCAL_SLOT_NUMBER (decl), decl);
pushdecl (decl);
initialize_local_variable (decl, DECL_LOCAL_SLOT_NUMBER (decl));
} }
} }
...@@ -1698,11 +1816,14 @@ start_java_method (tree fndecl) ...@@ -1698,11 +1816,14 @@ start_java_method (tree fndecl)
tree tem, *ptr; tree tem, *ptr;
int i; int i;
uniq = 0;
current_function_decl = fndecl; current_function_decl = fndecl;
announce_function (fndecl); announce_function (fndecl);
i = DECL_MAX_LOCALS(fndecl) + DECL_MAX_STACK(fndecl); i = DECL_MAX_LOCALS(fndecl) + DECL_MAX_STACK(fndecl);
decl_map = make_tree_vec (i); decl_map = make_tree_vec (i);
base_decl_map = make_tree_vec (i);
type_map = xrealloc (type_map, i * sizeof (tree)); type_map = xrealloc (type_map, i * sizeof (tree));
#if defined(DEBUG_JAVA_BINDING_LEVELS) #if defined(DEBUG_JAVA_BINDING_LEVELS)
...@@ -1751,6 +1872,8 @@ start_java_method (tree fndecl) ...@@ -1751,6 +1872,8 @@ start_java_method (tree fndecl)
/* Push local variables. */ /* Push local variables. */
pushlevel (2); pushlevel (2);
function_binding_level = current_binding_level;
} }
void void
...@@ -1777,6 +1900,14 @@ end_java_method (void) ...@@ -1777,6 +1900,14 @@ end_java_method (void)
DECL_STRUCT_FUNCTION (fndecl) = NULL; DECL_STRUCT_FUNCTION (fndecl) = NULL;
DECL_INITIAL (fndecl) = NULL_TREE; DECL_INITIAL (fndecl) = NULL_TREE;
} }
if (! flag_unit_at_a_time)
{
/* Nulling these fields when we no longer need them saves
memory. */
DECL_SAVED_TREE (fndecl) = NULL;
DECL_STRUCT_FUNCTION (fndecl) = NULL;
DECL_INITIAL (fndecl) = NULL_TREE;
}
current_function_decl = NULL_TREE; current_function_decl = NULL_TREE;
} }
......
...@@ -255,6 +255,9 @@ push_type_0 (tree type) ...@@ -255,6 +255,9 @@ push_type_0 (tree type)
n_words = 1 + TYPE_IS_WIDE (type); n_words = 1 + TYPE_IS_WIDE (type);
if (stack_pointer + n_words > DECL_MAX_STACK (current_function_decl)) if (stack_pointer + n_words > DECL_MAX_STACK (current_function_decl))
return 0; return 0;
/* Allocate decl for this variable now, so we get a temporary that
survives the whole method. */
find_stack_slot (stack_pointer, type);
stack_type_map[stack_pointer++] = type; stack_type_map[stack_pointer++] = type;
n_words--; n_words--;
while (--n_words >= 0) while (--n_words >= 0)
...@@ -368,7 +371,7 @@ pop_type (tree type) ...@@ -368,7 +371,7 @@ pop_type (tree type)
return type; return type;
} }
/* Return 1f if SOURCE_TYPE can be safely widened to TARGET_TYPE. /* Return 1 if SOURCE_TYPE can be safely widened to TARGET_TYPE.
Handles array types and interfaces. */ Handles array types and interfaces. */
int int
...@@ -1289,7 +1292,7 @@ expand_iinc (unsigned int local_var_index, int ival, int pc) ...@@ -1289,7 +1292,7 @@ expand_iinc (unsigned int local_var_index, int ival, int pc)
constant_value = build_int_2 (ival, ival < 0 ? -1 : 0); constant_value = build_int_2 (ival, ival < 0 ? -1 : 0);
res = fold (build2 (PLUS_EXPR, int_type_node, local_var, constant_value)); res = fold (build2 (PLUS_EXPR, int_type_node, local_var, constant_value));
java_add_stmt (build2 (MODIFY_EXPR, TREE_TYPE (local_var), local_var, res)); java_add_stmt (build2 (MODIFY_EXPR, TREE_TYPE (local_var), local_var, res));
update_aliases (local_var, local_var_index); update_aliases (local_var, local_var_index, pc);
} }
...@@ -2758,7 +2761,8 @@ process_jvm_instruction (int PC, const unsigned char* byte_ops, ...@@ -2758,7 +2761,8 @@ process_jvm_instruction (int PC, const unsigned char* byte_ops,
{ \ { \
int saw_index = 0; \ int saw_index = 0; \
int index = OPERAND_VALUE; \ int index = OPERAND_VALUE; \
build_java_ret (find_local_variable (index, ptr_type_node, oldpc)); \ build_java_ret \
(find_local_variable (index, return_address_type_node, oldpc)); \
} }
#define JSR(OPERAND_TYPE, OPERAND_VALUE) \ #define JSR(OPERAND_TYPE, OPERAND_VALUE) \
...@@ -2937,7 +2941,7 @@ process_jvm_instruction (int PC, const unsigned char* byte_ops, ...@@ -2937,7 +2941,7 @@ process_jvm_instruction (int PC, const unsigned char* byte_ops,
decl = find_local_variable (index, type, oldpc); \ decl = find_local_variable (index, type, oldpc); \
set_local_type (index, type); \ set_local_type (index, type); \
java_add_stmt (build2 (MODIFY_EXPR, type, decl, value)); \ java_add_stmt (build2 (MODIFY_EXPR, type, decl, value)); \
update_aliases (decl, index); \ update_aliases (decl, index, PC); \
} }
#define STORE(OPERAND_TYPE, OPERAND_VALUE) \ #define STORE(OPERAND_TYPE, OPERAND_VALUE) \
......
...@@ -37,6 +37,7 @@ static tree java_gimplify_default_expr (tree); ...@@ -37,6 +37,7 @@ static tree java_gimplify_default_expr (tree);
static tree java_gimplify_block (tree); static tree java_gimplify_block (tree);
static tree java_gimplify_new_array_init (tree); static tree java_gimplify_new_array_init (tree);
static tree java_gimplify_try_expr (tree); static tree java_gimplify_try_expr (tree);
static tree java_gimplify_modify_expr (tree);
static void dump_java_tree (enum tree_dump_index, tree); static void dump_java_tree (enum tree_dump_index, tree);
...@@ -117,6 +118,21 @@ java_gimplify_expr (tree *expr_p, tree *pre_p ATTRIBUTE_UNUSED, ...@@ -117,6 +118,21 @@ java_gimplify_expr (tree *expr_p, tree *pre_p ATTRIBUTE_UNUSED,
*expr_p = build_exception_object_ref (TREE_TYPE (*expr_p)); *expr_p = build_exception_object_ref (TREE_TYPE (*expr_p));
break; break;
case VAR_DECL:
*expr_p = java_replace_reference (*expr_p, /* want_lvalue */ false);
return GS_UNHANDLED;
case MODIFY_EXPR:
*expr_p = java_gimplify_modify_expr (*expr_p);
return GS_UNHANDLED;
case SAVE_EXPR:
if (TREE_CODE (TREE_OPERAND (*expr_p, 0)) == VAR_DECL)
TREE_OPERAND (*expr_p, 0)
= java_replace_reference (TREE_OPERAND (*expr_p, 0),
/* want_lvalue */ false);
return GS_UNHANDLED;
/* These should already be lowered before we get here. */ /* These should already be lowered before we get here. */
case URSHIFT_EXPR: case URSHIFT_EXPR:
case COMPARE_EXPR: case COMPARE_EXPR:
...@@ -140,6 +156,33 @@ java_gimplify_expr (tree *expr_p, tree *pre_p ATTRIBUTE_UNUSED, ...@@ -140,6 +156,33 @@ java_gimplify_expr (tree *expr_p, tree *pre_p ATTRIBUTE_UNUSED,
return GS_OK; return GS_OK;
} }
/* This is specific to the bytecode compiler. If a variable has
LOCAL_SLOT_P set, replace an assignment to it with an assignment to
the corresponding variable that holds all its aliases. */
static tree
java_gimplify_modify_expr (tree modify_expr)
{
tree lhs = TREE_OPERAND (modify_expr, 0);
tree rhs = TREE_OPERAND (modify_expr, 1);
tree lhs_type = TREE_TYPE (lhs);
if (TREE_CODE (lhs) == VAR_DECL
&& DECL_LANG_SPECIFIC (lhs)
&& LOCAL_SLOT_P (lhs)
&& TREE_CODE (lhs_type) == POINTER_TYPE)
{
tree new_lhs = java_replace_reference (lhs, /* want_lvalue */ true);
tree new_rhs = build1 (NOP_EXPR, TREE_TYPE (new_lhs), rhs);
modify_expr = build (MODIFY_EXPR, TREE_TYPE (new_lhs),
new_lhs, new_rhs);
modify_expr = build1 (NOP_EXPR, lhs_type, modify_expr);
}
return modify_expr;
}
static tree static tree
java_gimplify_case_expr (tree expr) java_gimplify_case_expr (tree expr)
{ {
......
...@@ -925,6 +925,8 @@ union lang_tree_node ...@@ -925,6 +925,8 @@ union lang_tree_node
/* True if NODE is a variable that is out of scope. */ /* True if NODE is a variable that is out of scope. */
#define LOCAL_VAR_OUT_OF_SCOPE_P(NODE) \ #define LOCAL_VAR_OUT_OF_SCOPE_P(NODE) \
(DECL_LANG_SPECIFIC (NODE)->u.v.freed) (DECL_LANG_SPECIFIC (NODE)->u.v.freed)
#define LOCAL_SLOT_P(NODE) \
(DECL_LANG_SPECIFIC (NODE)->u.v.local_slot)
/* 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) \
...@@ -1010,7 +1012,8 @@ struct lang_decl_var GTY(()) ...@@ -1010,7 +1012,8 @@ struct lang_decl_var GTY(())
tree owner; tree owner;
unsigned int final_iud : 1; /* Final initialized upon declaration */ unsigned int final_iud : 1; /* Final initialized upon declaration */
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; /* 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. */
}; };
/* This is what 'lang_decl' really points to. */ /* This is what 'lang_decl' really points to. */
...@@ -1176,7 +1179,7 @@ extern void set_java_signature (tree, tree); ...@@ -1176,7 +1179,7 @@ extern void set_java_signature (tree, tree);
extern tree build_static_field_ref (tree); extern tree build_static_field_ref (tree);
extern tree build_address_of (tree); extern tree build_address_of (tree);
extern tree find_local_variable (int index, tree type, int pc); extern tree find_local_variable (int index, tree type, int pc);
extern void update_aliases (tree decl, int index); extern void update_aliases (tree decl, int index, int pc);
extern tree find_stack_slot (int index, tree type); extern tree find_stack_slot (int index, tree type);
extern tree build_prim_array_type (tree, HOST_WIDE_INT); extern tree build_prim_array_type (tree, HOST_WIDE_INT);
extern tree build_java_array_type (tree, HOST_WIDE_INT); extern tree build_java_array_type (tree, HOST_WIDE_INT);
...@@ -1254,6 +1257,8 @@ extern void java_layout_seen_class_methods (void); ...@@ -1254,6 +1257,8 @@ extern void java_layout_seen_class_methods (void);
extern void check_for_initialization (tree, tree); extern void check_for_initialization (tree, tree);
extern tree pushdecl_top_level (tree); extern tree pushdecl_top_level (tree);
extern tree pushdecl_function_level (tree);
extern tree java_replace_reference (tree, bool);
extern int alloc_class_constant (tree); extern int alloc_class_constant (tree);
extern void init_expr_processing (void); extern void init_expr_processing (void);
extern void push_super_field (tree, tree); extern void push_super_field (tree, tree);
......
...@@ -391,9 +391,17 @@ build_java_array_type (tree element_type, HOST_WIDE_INT length) ...@@ -391,9 +391,17 @@ build_java_array_type (tree element_type, HOST_WIDE_INT length)
el_name = TYPE_NAME (el_name); el_name = TYPE_NAME (el_name);
if (TREE_CODE (el_name) == TYPE_DECL) if (TREE_CODE (el_name) == TYPE_DECL)
el_name = DECL_NAME (el_name); el_name = DECL_NAME (el_name);
TYPE_NAME (t) = build_decl (TYPE_DECL, {
identifier_subst (el_name, "", '.', '.', "[]"), char suffix[12];
if (length >= 0)
sprintf (suffix, "[%d]", (int)length);
else
strcpy (suffix, "[]");
TYPE_NAME (t)
= build_decl (TYPE_DECL,
identifier_subst (el_name, "", '.', '.', suffix),
t); t);
}
set_java_signature (t, sig); set_java_signature (t, sig);
set_super_info (0, t, object_type_node, 0); set_super_info (0, t, object_type_node, 0);
......
...@@ -734,8 +734,8 @@ verify_jvm_instructions (JCF* jcf, const unsigned char *byte_ops, long length) ...@@ -734,8 +734,8 @@ verify_jvm_instructions (JCF* jcf, const unsigned char *byte_ops, long length)
handlers. */ handlers. */
prev_eh_ranges = NULL_EH_RANGE; prev_eh_ranges = NULL_EH_RANGE;
/* Allocate decl and rtx for this variable now, so if we're not /* Allocate decl for this variable now, so we get a temporary
optimizing, we get a temporary that survives the whole method. */ ! that survives the whole method. */
find_local_variable (index, type, oldpc); find_local_variable (index, type, oldpc);
if (TYPE_IS_WIDE (type)) if (TYPE_IS_WIDE (type))
......
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