OSDN Git Service

2004-07-20 Andrew Haley <aph@redhat.com>
authoraph <aph@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 21 Jul 2004 16:03:43 +0000 (16:03 +0000)
committeraph <aph@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 21 Jul 2004 16:03:43 +0000 (16:03 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@85009 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/java/ChangeLog
gcc/java/decl.c
gcc/java/expr.c
gcc/java/java-gimplify.c
gcc/java/java-tree.h
gcc/java/typeck.c
gcc/java/verify.c

index b2322fd..2dc5583 100644 (file)
@@ -1,3 +1,40 @@
+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>
 
        * class.c (add_interface_do): Remove.
 2004-07-20  Nathan Sidwell  <nathan@codesourcery.com>
 
        * class.c (add_interface_do): Remove.
index 761ebb2..35a9218 100644 (file)
@@ -57,7 +57,6 @@ static tree lookup_name_current_level (tree);
 static tree push_promoted_type (const char *, tree);
 static struct binding_level *make_binding_level (void);
 static tree create_primitive_vtable (const char *);
 static tree push_promoted_type (const char *, tree);
 static struct binding_level *make_binding_level (void);
 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);
 
 /* Name of the Cloneable class.  */
 static tree check_local_unnamed_variable (tree, tree, tree);
 
 /* Name of the Cloneable class.  */
@@ -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
    debug information, but we have not reached their starting (byte) PC yet. */
 
 static GTY(()) tree pending_local_decls;
 
 /* 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. */
 
 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)
 int binding_depth = 0;
 int is_class_level = 0;
 #if defined(DEBUG_JAVA_BINDING_LEVELS)
 int binding_depth = 0;
 int is_class_level = 0;
@@ -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
-   slot.  */
+/* True if decl is a named local variable, i.e. if it is an alias
+   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 type = TREE_TYPE (decl);
-  while (tmp != NULL_TREE)
+  tree decl_type = TREE_TYPE (decl);
+  tree tmp;
+
+  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)
-         && TYPE_MODE (type) == TYPE_MODE (TREE_TYPE (tmp)))
+         && LOCAL_SLOT_P (tmp) == 0
+         && (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);
-         java_add_stmt (build2 (MODIFY_EXPR, TREE_TYPE (tmp), tmp, src));
+         tree src = build1 (NOP_EXPR, tmp_type, decl);
+         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
 push_jvm_slot (int index, tree decl)
 {
     }
 }
 
 static tree
 push_jvm_slot (int index, tree decl)
 {
-  tree type = TREE_TYPE (decl);
-  tree tmp;
-
   DECL_CONTEXT (decl) = current_function_decl;
   layout_decl (decl, 0);
 
   DECL_CONTEXT (decl) = current_function_decl;
   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. */
   if (DECL_LANG_SPECIFIC (decl) == NULL)
     {
   /* Now link the decl into the decl_map. */
   if (DECL_LANG_SPECIFIC (decl) == NULL)
     {
@@ -155,31 +176,54 @@ push_jvm_slot (int index, tree decl)
   DECL_LOCAL_SLOT_CHAIN (decl) = TREE_VEC_ELT (decl_map, index);
   TREE_VEC_ELT (decl_map, index) = decl;
 
   DECL_LOCAL_SLOT_CHAIN (decl) = TREE_VEC_ELT (decl_map, index);
   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
-   'best'.  Return decl if it does, return best if it doesn't.  If decl
-   is returned, then updated is set to true.  */
+/*  At the point of its creation a local variable decl inherits
+    whatever is already in the same slot.  In the case of a local
+    variable that is declared but unused, we won't find anything.  */
 
 
-static tree
-check_local_named_variable (tree best, tree decl, int pc, int *updated)
+static void
+initialize_local_variable (tree decl, int index)
 {
 {
-  if (pc >= DECL_LOCAL_START_PC (decl)
-      && pc < DECL_LOCAL_END_PC (decl))
+  tree decl_type = TREE_TYPE (decl);
+  if (TREE_CODE (decl_type) == POINTER_TYPE)
     {
     {
-      if (best == NULL_TREE
-         || (DECL_LOCAL_START_PC (decl) > DECL_LOCAL_START_PC (best)
-             && DECL_LOCAL_END_PC (decl) < DECL_LOCAL_END_PC (best)))
+      tree tmp = TREE_VEC_ELT (base_decl_map, index);
+
+      if (tmp)
         {
         {
-         *updated = 1;
-         return decl;
+         /* At the point of its creation this decl inherits whatever
+            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)
 static tree
 check_local_unnamed_variable (tree best, tree decl, tree type)
 {
 static tree
 check_local_unnamed_variable (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
+  tree decl_type = TREE_TYPE (decl);
+  
+  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
            && type == ptr_type_node))
       {
        if (best == NULL_TREE
        || (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
            && type == ptr_type_node))
       {
        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)
    If there is no existing matching decl, allocate one.  */
 
 tree
    If there is no existing matching decl, allocate one.  */
 
 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 best = NULL_TREE;
-  int found_scoped_var = 0;
+  tree tmp = TREE_VEC_ELT (decl_map, index);
+  tree decl = NULL_TREE;
 
 
-  /* Scan through every declaration that has been created in this slot. */
-  while (decl != NULL_TREE)
+  /* Scan through every declaration that has been created in this
+     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;
-      tree name = DECL_NAME (decl);
-      if (name && IDENTIFIER_POINTER (name))
-       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 (! debug_variable_p (tmp))
+       decl = check_local_unnamed_variable (decl, tmp, type);
+      tmp = DECL_LOCAL_SLOT_CHAIN (tmp);
     }
 
     }
 
-  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
      uniqueness -- multiple variables may share the same local
      in the local variable area and m is a dummy identifier for
      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];
     tree name;
   {
     char buf[64];
     tree name;
-    static int uniq;
-    sprintf (buf, "#%d#%d", index, uniq++);
-    name = get_identifier (buf);
+      sprintf (buf, "#slot#%d#%d", index, uniq++);
+      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;
 
 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. */
 
 #define LARGEST_PC (( (unsigned int)1 << (HOST_BITS_PER_INT - 1)) - 1)
 /* 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)
@@ -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.  */
 
 int
 /* Nonzero if we are currently in the global binding level.  */
 
 int
@@ -1497,9 +1609,13 @@ maybe_pushlevels (int pc)
       pending_local_decls = *ptr;
       *ptr = NULL_TREE;
 
       pending_local_decls = *ptr;
       *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)
        {
          next = TREE_CHAIN (decl);
          push_jvm_slot (DECL_LOCAL_SLOT_NUMBER (decl), decl);
        {
          next = TREE_CHAIN (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)
   tree tem, *ptr;
   int i;
 
   tree tem, *ptr;
   int i;
 
+  uniq = 0;
+
   current_function_decl = fndecl;
   announce_function (fndecl);
 
   i = DECL_MAX_LOCALS(fndecl) + DECL_MAX_STACK(fndecl);
   decl_map = make_tree_vec (i);
   current_function_decl = fndecl;
   announce_function (fndecl);
 
   i = DECL_MAX_LOCALS(fndecl) + DECL_MAX_STACK(fndecl);
   decl_map = make_tree_vec (i);
+  base_decl_map = make_tree_vec (i);
   type_map = xrealloc (type_map, i * sizeof (tree));
 
 #if defined(DEBUG_JAVA_BINDING_LEVELS)
   type_map = xrealloc (type_map, i * sizeof (tree));
 
 #if defined(DEBUG_JAVA_BINDING_LEVELS)
@@ -1751,6 +1872,8 @@ start_java_method (tree fndecl)
 
   /* Push local variables.  */
   pushlevel (2);
 
   /* Push local variables.  */
   pushlevel (2);
+
+  function_binding_level = current_binding_level;
 }
 
 void
 }
 
 void
@@ -1777,6 +1900,14 @@ end_java_method (void)
       DECL_STRUCT_FUNCTION (fndecl) = NULL;
       DECL_INITIAL (fndecl) = NULL_TREE;
     }
       DECL_STRUCT_FUNCTION (fndecl) = NULL;
       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;
 }
 
index 228c1d1..73e3e81 100644 (file)
@@ -255,6 +255,9 @@ push_type_0 (tree type)
   n_words = 1 + TYPE_IS_WIDE (type);
   if (stack_pointer + n_words > DECL_MAX_STACK (current_function_decl))
     return 0;
   n_words = 1 + TYPE_IS_WIDE (type);
   if (stack_pointer + n_words > DECL_MAX_STACK (current_function_decl))
     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;
   n_words--;
   while (--n_words >= 0)
   stack_type_map[stack_pointer++] = type;
   n_words--;
   while (--n_words >= 0)
@@ -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.  */
 
 int
    Handles array types and interfaces.  */
 
 int
@@ -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);
   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));
   constant_value = build_int_2 (ival, ival < 0 ? -1 : 0);
   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));
-  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,
   {                                                                    \
     int saw_index = 0;                                                 \
     int index     = OPERAND_VALUE;                                     \
   {                                                                    \
     int saw_index = 0;                                                 \
     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,
     decl = find_local_variable (index, type, oldpc);           \
     set_local_type (index, type);                              \
     java_add_stmt (build2 (MODIFY_EXPR, type, decl, value));   \
     decl = find_local_variable (index, type, oldpc);           \
     set_local_type (index, type);                              \
     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) \
index 64cb7ce..eb277f8 100644 (file)
@@ -37,6 +37,7 @@ static tree java_gimplify_default_expr (tree);
 static tree java_gimplify_block (tree);
 static tree java_gimplify_new_array_init (tree);
 static tree java_gimplify_try_expr (tree);
 static tree java_gimplify_block (tree);
 static tree java_gimplify_new_array_init (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,
       *expr_p = build_exception_object_ref (TREE_TYPE (*expr_p));
       break;
 
       *expr_p = build_exception_object_ref (TREE_TYPE (*expr_p));
       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.  */
     case URSHIFT_EXPR:
     case COMPARE_EXPR:
     /* These should already be lowered before we get here.  */
     case URSHIFT_EXPR:
     case COMPARE_EXPR:
@@ -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
 java_gimplify_case_expr (tree expr)
 {
 static tree
 java_gimplify_case_expr (tree expr)
 {
index 5f33ec5..44a2ed9 100644 (file)
@@ -925,6 +925,8 @@ union lang_tree_node
 /* True if NODE is a variable that is out of scope.  */
 #define LOCAL_VAR_OUT_OF_SCOPE_P(NODE) \
     (DECL_LANG_SPECIFIC (NODE)->u.v.freed)
 /* True if NODE is a variable that is out of scope.  */
 #define LOCAL_VAR_OUT_OF_SCOPE_P(NODE) \
     (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. */
 #define MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC(T)                 \
   if (DECL_LANG_SPECIFIC (T) == NULL)                          \
 /* Create a DECL_LANG_SPECIFIC if necessary. */
 #define MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC(T)                 \
   if (DECL_LANG_SPECIFIC (T) == NULL)                          \
@@ -1010,7 +1012,8 @@ struct lang_decl_var GTY(())
   tree owner;
   unsigned int final_iud : 1;  /* Final initialized upon declaration */
   unsigned int cif : 1;                /* True: decl is a class initialization flag */
   tree owner;
   unsigned int final_iud : 1;  /* Final initialized upon declaration */
   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);
 extern tree build_static_field_ref (tree);
 extern tree build_address_of (tree);
 extern tree find_local_variable (int index, tree type, int pc);
 extern tree build_static_field_ref (tree);
 extern tree build_address_of (tree);
 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 build_prim_array_type (tree, HOST_WIDE_INT);
 extern tree build_java_array_type (tree, HOST_WIDE_INT);
 extern tree find_stack_slot (int index, tree type);
 extern tree build_prim_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);
 extern void check_for_initialization (tree, tree);
 
 extern tree pushdecl_top_level (tree);
 extern void check_for_initialization (tree, 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 void init_expr_processing (void);
 extern void push_super_field (tree, tree);
 extern int alloc_class_constant (tree);
 extern void init_expr_processing (void);
 extern void push_super_field (tree, tree);
index 0e6e404..5c38bb8 100644 (file)
@@ -391,9 +391,17 @@ build_java_array_type (tree element_type, HOST_WIDE_INT length)
   el_name = TYPE_NAME (el_name);
   if (TREE_CODE (el_name) == TYPE_DECL)
     el_name = DECL_NAME (el_name);
   el_name = TYPE_NAME (el_name);
   if (TREE_CODE (el_name) == TYPE_DECL)
     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_super_info (0, t, object_type_node, 0);
 
   set_java_signature (t, sig);
   set_super_info (0, t, object_type_node, 0);
index 8482469..89b9d95 100644 (file)
@@ -734,8 +734,8 @@ verify_jvm_instructions (JCF* jcf, const unsigned char *byte_ops, long length)
         handlers.  */
        prev_eh_ranges = NULL_EH_RANGE;
 
         handlers.  */
        prev_eh_ranges = NULL_EH_RANGE;
 
-       /* Allocate decl and rtx for this variable now, so if we're not
-          optimizing, we get a temporary that survives the whole method.  */
+       /* Allocate decl for this variable now, so we get a temporary
+!         that survives the whole method. */
        find_local_variable (index, type, oldpc);
 
         if (TYPE_IS_WIDE (type))
        find_local_variable (index, type, oldpc);
 
         if (TYPE_IS_WIDE (type))