java-except.h (struct eh_range): Add `expanded' field.
authorAndrew Haley <aph@cygnus.com>
Wed, 9 Feb 2000 14:08:44 +0000 (14:08 +0000)
committerAndrew Haley <aph@gcc.gnu.org>
Wed, 9 Feb 2000 14:08:44 +0000 (14:08 +0000)
2000-01-25  Andrew Haley  <aph@cygnus.com>

        * java-except.h (struct eh_range): Add `expanded' field.
        (maybe_start_try): Add end_pc arg.
        (maybe_end_try): Ditto.
* java-tree.h (force_poplevels): new function.
        * expr.c (expand_byte_code): Don't call maybe_start_try or
        maybe_end_try.
        * except.c (add_handler): Reset expanded.
        (expand_start_java_handler): Set expanded.
        (check_start_handlers): Don't expand a start handler that's
        already been expanded.
        (maybe_start_try): Add end_pc arg.  Only expand a handler which
        ends after end_pc.
(expand_end_java_handler): call force_poplevels.
(force_poplevels): new function.
        * decl.c (binding_level): Add start_pc of binding level.
        (maybe_pushlevels): Call maybe_start_try when pushing binding
        levels.
        (maybe_poplevels): Call maybe_end_try when popping binding levels.
        (LARGEST_PC): Define.
        (clear_binding_level): Use LARGEST_PC.

* java-tree.h (DEBUG_JAVA_BINDING_LEVELS): new define.
* decl.c (DEBUG_JAVA_BINDING_LEVELS): new define.
(binding_depth, is_class_level, current_pc): new variables.
        (struct binding_level): ditto.
(indent): new function.
(push_jvm_slot): add debugging info.
(maybe_pushlevels): ditto.
(maybe_poplevels): ditto.
(pushlevel): ditto.
(poplevel): ditto.
(start_java_method): ditto.
(give_name_to_locals): comment only.
* except.c (binding_depth, is_class_level, current_pc):
new variables.
(expand_start_java_handler): add debugging info.
(expand_end_java_handler): ditto.

From-SVN: r31861

gcc/java/ChangeLog
gcc/java/decl.c
gcc/java/except.c
gcc/java/expr.c
gcc/java/java-except.h
gcc/java/java-tree.h

index c5406c8..28cfbcc 100644 (file)
@@ -1,3 +1,43 @@
+2000-01-25  Andrew Haley  <aph@cygnus.com>
+
+        * java-except.h (struct eh_range): Add `expanded' field.
+        (maybe_start_try): Add end_pc arg.
+        (maybe_end_try): Ditto.
+       * java-tree.h (force_poplevels): new function.
+        * expr.c (expand_byte_code): Don't call maybe_start_try or
+        maybe_end_try.
+        * except.c (add_handler): Reset expanded.
+        (expand_start_java_handler): Set expanded.
+        (check_start_handlers): Don't expand a start handler that's
+        already been expanded.
+        (maybe_start_try): Add end_pc arg.  Only expand a handler which
+        ends after end_pc.
+       (expand_end_java_handler): call force_poplevels.
+       (force_poplevels): new function.
+        * decl.c (binding_level): Add start_pc of binding level.
+        (maybe_pushlevels): Call maybe_start_try when pushing binding
+        levels.
+        (maybe_poplevels): Call maybe_end_try when popping binding levels.
+        (LARGEST_PC): Define.
+        (clear_binding_level): Use LARGEST_PC.
+
+       * java-tree.h (DEBUG_JAVA_BINDING_LEVELS): new define.
+       * decl.c (DEBUG_JAVA_BINDING_LEVELS): new define.
+       (binding_depth, is_class_level, current_pc): new variables.
+        (struct binding_level): ditto.
+       (indent): new function.
+       (push_jvm_slot): add debugging info.
+       (maybe_pushlevels): ditto.
+       (maybe_poplevels): ditto.
+       (pushlevel): ditto.
+       (poplevel): ditto.
+       (start_java_method): ditto.
+       (give_name_to_locals): comment only.
+       * except.c (binding_depth, is_class_level, current_pc): 
+       new variables.
+       (expand_start_java_handler): add debugging info.
+       (expand_end_java_handler): ditto.
+       
 2000-02-05  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * gjavah.c (overloaded_jni_method_exists_p): Add prototype.
index 5513203..5669b3f 100644 (file)
@@ -29,12 +29,19 @@ The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 #include "config.h"
 #include "system.h"
 #include "tree.h"
+#include "toplev.h"
+#include "flags.h"
 #include "java-tree.h"
 #include "jcf.h"
 #include "toplev.h"
 #include "function.h"
 #include "except.h"
 #include "defaults.h"
+#include "java-except.h"
+
+#if defined (DEBUG_JAVA_BINDING_LEVELS)
+extern void indent PROTO((void));
+#endif
 
 static tree push_jvm_slot PARAMS ((int, tree));
 static tree lookup_name_current_level PARAMS ((tree));
@@ -63,6 +70,21 @@ tree pending_local_decls = NULL_TREE;
 /* 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;
+int current_pc;
+
+void
+indent ()
+{
+  register unsigned i;
+
+  for (i = 0; i < binding_depth*2; i++)
+    putc (' ', stderr);
+}
+#endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
+
 static tree
 push_jvm_slot (index, decl)
      int index;
@@ -199,6 +221,12 @@ struct binding_level
 
     /* The bytecode PC that marks the end of this level. */
     int end_pc;
+    int start_pc;
+
+#if defined(DEBUG_JAVA_BINDING_LEVELS)
+    /* Binding depth at which this level began.  */
+    unsigned binding_depth;
+#endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
   };
 
 #define NULL_BINDING_LEVEL (struct binding_level *) NULL
@@ -217,11 +245,15 @@ static struct binding_level *free_binding_level;
 
 static struct binding_level *global_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)
+
 /* Binding level structures are initialized by copying this one.  */
 
 static struct binding_level clear_binding_level
   = {NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE,
-       NULL_BINDING_LEVEL, 0, 0, 0, 0, 1000000000};
+       NULL_BINDING_LEVEL, 0, 0, 0, 0, LARGEST_PC, 0, 0};
 
 #if 0
 /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
@@ -1123,6 +1155,14 @@ pushlevel (unused)
   keep_next_level_flag = 0;
   newlevel->keep_if_subblocks = keep_next_if_subblocks;
   keep_next_if_subblocks = 0;
+#if defined(DEBUG_JAVA_BINDING_LEVELS)
+  newlevel->binding_depth = binding_depth;
+  indent ();
+  fprintf (stderr, "push %s level 0x%08x pc %d\n",
+          (is_class_level) ? "class" : "block", newlevel, current_pc);
+  is_class_level = 0;
+  binding_depth++;
+#endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
 }
 
 /* Exit a binding level.
@@ -1155,6 +1195,26 @@ poplevel (keep, reverse, functionbody)
   tree decl;
   int block_previously_created;
 
+#if defined(DEBUG_JAVA_BINDING_LEVELS)
+  binding_depth--;
+  indent ();
+  if (current_binding_level->end_pc != LARGEST_PC)
+    fprintf (stderr, "pop  %s level 0x%08x pc %d (end pc %d)\n",
+            (is_class_level) ? "class" : "block", current_binding_level, current_pc,
+            current_binding_level->end_pc);
+  else
+    fprintf (stderr, "pop  %s level 0x%08x pc %d\n",
+            (is_class_level) ? "class" : "block", current_binding_level, current_pc);
+#if 0
+  if (is_class_level != (current_binding_level == class_binding_level))
+    {
+      indent ();
+      fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n");
+    }
+  is_class_level = 0;
+#endif
+#endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
+
   keep |= current_binding_level->keep;
 
   /* Get the decls in the order they were written.
@@ -1334,6 +1394,10 @@ void
 maybe_pushlevels (pc)
      int pc;
 {
+#if defined(DEBUG_JAVA_BINDING_LEVELS)
+  current_pc = pc;
+#endif
+
   while (pending_local_decls != NULL_TREE &&
         DECL_LOCAL_START_PC (pending_local_decls) <= pc)
     {
@@ -1352,24 +1416,57 @@ maybe_pushlevels (pc)
       if (end_pc > current_binding_level->end_pc)
        end_pc = current_binding_level->end_pc;
 
+      maybe_start_try (pc, end_pc);
+      
       pushlevel (1);
       expand_start_bindings (0);
+
       current_binding_level->end_pc = end_pc;
-      
+      current_binding_level->start_pc = pc;      
       current_binding_level->names = decl;
       for ( ; decl != NULL_TREE;  decl = TREE_CHAIN (decl))
        {
          push_jvm_slot (DECL_LOCAL_SLOT_NUMBER (decl), decl);
        }
-    }
+    }      
+
+  maybe_start_try (pc, 0);
 }
 
 void
 maybe_poplevels (pc)
      int pc;
 {
+#if defined(DEBUG_JAVA_BINDING_LEVELS)
+  current_pc = pc;
+#endif
+
   while (current_binding_level->end_pc <= pc)
     {
+      tree decls = getdecls ();        
+      expand_end_bindings (getdecls (), 1, 0);
+      maybe_end_try (current_binding_level->start_pc, pc);
+      poplevel (1, 0, 0);
+    }
+  maybe_end_try (0, pc);
+}
+
+/* Terminate any binding which began during the range beginning at
+   start_pc.  This tidies up improperly nested local variable ranges
+   and exception handlers; a variable declared within an exception
+   range is forcibly terminated when that exception ends. */
+
+void
+force_poplevels (start_pc)
+     int start_pc;
+{
+  while (current_binding_level->start_pc > start_pc)
+    {
+      tree decls = getdecls ();        
+      if (pedantic && current_binding_level->start_pc > start_pc)
+       warning_with_decl (current_function_decl, 
+                          "In %s: overlapped variable and exception ranges at %d",
+                          current_binding_level->start_pc);
       expand_end_bindings (getdecls (), 1, 0);
       poplevel (1, 0, 0);
     }
@@ -1468,6 +1565,14 @@ give_name_to_locals (jcf)
            = (struct lang_decl *) permalloc (sizeof (struct lang_decl_var));
          DECL_LOCAL_SLOT_NUMBER (decl) = slot;
          DECL_LOCAL_START_PC (decl) = start_pc;
+#if 0
+         /* FIXME: The range used internally for exceptions and local
+            variable ranges, is a half-open interval: 
+            start_pc <= pc < end_pc.  However, the range used in the
+            Java VM spec is inclusive at both ends: 
+            start_pc <= pc <= end_pc. */
+         end_pc++;
+#endif
          DECL_LOCAL_END_PC (decl) = end_pc;
 
          /* Now insert the new decl in the proper place in
@@ -1612,6 +1717,10 @@ start_java_method (fndecl)
   decl_map = make_tree_vec (i);
   type_map = (tree *) oballoc (i * sizeof (tree));
 
+#if defined(DEBUG_JAVA_BINDING_LEVELS)
+  fprintf (stderr, "%s:\n", (*decl_printable_name) (fndecl, 2));
+  current_pc = 0;
+#endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
   pushlevel (1);  /* Push parameters. */
 
   ptr = &DECL_ARGUMENTS (fndecl);
index f44f072..1fb5934 100644 (file)
@@ -42,7 +42,6 @@ static void expand_end_java_handler PARAMS ((struct eh_range *));
 static struct eh_range *find_handler_in_range PARAMS ((int, struct eh_range *,
                                                      struct eh_range *));
 static void link_handler PARAMS ((struct eh_range *, struct eh_range *));
-static void check_start_handlers PARAMS ((struct eh_range *, int));
 
 extern struct obstack permanent_obstack;
 
@@ -62,6 +61,14 @@ static struct eh_range *cache_next_child;
 
 struct eh_range whole_range;
 
+#if defined(DEBUG_JAVA_BINDING_LEVELS)
+int binding_depth;
+int is_class_level;
+int current_pc;
+extern void indent ();
+
+#endif
+
 /* Search for the most specific eh_range containing PC.
    Assume PC is within RANGE.
    CHILD is a list of children of RANGE such that any
@@ -278,6 +285,7 @@ add_handler (start_pc, end_pc, handler, type)
   h->outer = NULL;
   h->handlers = build_tree_list (type, handler);
   h->next_sibling = NULL;
+  h->expanded = 0;
 
   if (prev == NULL)
     whole_range.first_child = h;
@@ -289,8 +297,14 @@ add_handler (start_pc, end_pc, handler, type)
 /* if there are any handlers for this range, issue start of region */
 static void
 expand_start_java_handler (range)
-  struct eh_range *range ATTRIBUTE_UNUSED;
+  struct eh_range *range;
 {
+#if defined(DEBUG_JAVA_BINDING_LEVELS)
+  indent ();
+  fprintf (stderr, "expand start handler pc %d --> %d\n",
+          current_pc, range->end_pc);
+#endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
+  range->expanded = 1;
   push_obstacks (&permanent_obstack, &permanent_obstack);
   expand_eh_region_start ();
   pop_obstacks ();
@@ -327,8 +341,9 @@ prepare_eh_table_type (type)
 static void
 expand_end_java_handler (range)
      struct eh_range *range;
-{
+{  
   tree handler = range->handlers;
+  force_poplevels (range->start_pc);
   push_obstacks (&permanent_obstack, &permanent_obstack);
   expand_start_all_catch ();
   pop_obstacks ();
@@ -341,6 +356,11 @@ expand_end_java_handler (range)
       end_catch_handler ();
     }
   expand_end_all_catch ();
+#if defined(DEBUG_JAVA_BINDING_LEVELS)
+  indent ();
+  fprintf (stderr, "expand end handler pc %d <-- %d\n",
+          current_pc, range->start_pc);
+#endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
 }
 
 /* Recursive helper routine for maybe_start_handlers. */
@@ -353,35 +373,48 @@ check_start_handlers (range, pc)
   if (range != NULL_EH_RANGE && range->start_pc == pc)
     {
       check_start_handlers (range->outer, pc);
-      expand_start_java_handler (range);
+      if (!range->expanded)
+       expand_start_java_handler (range);
     }
 }
 
-struct eh_range *current_range;
 
-/* Emit any start-of-try-range start at PC. */
+static struct eh_range *current_range;
+
+/* Emit any start-of-try-range starting at start_pc and ending after
+   end_pc. */
 
 void
-maybe_start_try (pc)
-     int pc;
+maybe_start_try (start_pc, end_pc)
+     int start_pc;
+     int end_pc;
 {
+  struct eh_range *range;
   if (! doing_eh (1))
     return;
 
-  current_range = find_handler (pc);
-  check_start_handlers (current_range, pc);
+  range = find_handler (start_pc);
+  while (range != NULL_EH_RANGE && range->start_pc == start_pc
+        && range->end_pc < end_pc)
+    range = range->outer;
+        
+  current_range = range;
+  check_start_handlers (range, start_pc, end_pc);
 }
 
-/* Emit any end-of-try-range end at PC. */
+/* Emit any end-of-try-range ending at end_pc and starting before
+   start_pc. */
 
 void
-maybe_end_try (pc)
-     int pc;
+maybe_end_try (start_pc, end_pc)
+     int start_pc;
+     int end_pc;
 {
   if (! doing_eh (1))
     return;
 
-  while (current_range != NULL_EH_RANGE && current_range->end_pc <= pc)
+  while (current_range != NULL_EH_RANGE && current_range->end_pc <= end_pc
+        && current_range->start_pc >= start_pc)
     {
       expand_end_java_handler (current_range);
       current_range = current_range->outer;
index 430db4a..3c1c0ff 100644 (file)
@@ -2289,13 +2289,9 @@ expand_byte_code (jcf, method)
                }
            }
        }
-      maybe_start_try (PC);
       maybe_pushlevels (PC);
-
       PC = process_jvm_instruction (PC, byte_ops, length);
-
       maybe_poplevels (PC);
-      maybe_end_try (PC);
     } /* for */
   
   if (dead_code_index != -1)
index 49ef54b..e069053 100644 (file)
@@ -47,6 +47,9 @@ struct eh_range
 
     /* The next child of outer, in address order. */
     struct eh_range *next_sibling;
+
+    /* True if this range has already been expanded. */
+    int expanded;
   };
 
 /* A dummy range that represents the entire method. */
@@ -60,9 +63,9 @@ extern void method_init_exceptions PARAMS ((void));
 
 extern void emit_handlers PARAMS ((void));
 
-extern void maybe_start_try PARAMS ((int));
+extern void maybe_start_try PARAMS ((int, int));
 
-extern void maybe_end_try PARAMS ((int));
+extern void maybe_end_try PARAMS ((int, int));
 
 extern void add_handler PARAMS ((int, int, tree, tree));
 
index a8370c4..288a6cb 100644 (file)
@@ -592,6 +592,7 @@ extern int class_depth PARAMS ((tree));
 extern int verify_jvm_instructions PARAMS ((struct JCF *, const unsigned char *, long));
 extern void maybe_pushlevels PARAMS ((int));
 extern void maybe_poplevels PARAMS ((int));
+extern void force_poplevels PARAMS ((int));
 extern int process_jvm_instruction PARAMS ((int, const unsigned char *, long));
 extern void set_local_type PARAMS ((int, tree));
 extern int merge_type_state PARAMS ((tree));
@@ -944,3 +945,5 @@ extern int java_error_count;                                        \
      if (java_error_count > save_error_count)                          \
        return;                                                         \
    }
+
+#undef DEBUG_JAVA_BINDING_LEVELS