diff options
-rw-r--r-- | gcc/java/ChangeLog | 40 | ||||
-rw-r--r-- | gcc/java/decl.c | 115 | ||||
-rw-r--r-- | gcc/java/except.c | 61 | ||||
-rw-r--r-- | gcc/java/expr.c | 4 | ||||
-rw-r--r-- | gcc/java/java-except.h | 7 | ||||
-rw-r--r-- | gcc/java/java-tree.h | 3 |
6 files changed, 207 insertions, 23 deletions
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index c5406c8..28cfbcc 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -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. diff --git a/gcc/java/decl.c b/gcc/java/decl.c index 5513203..5669b3f 100644 --- a/gcc/java/decl.c +++ b/gcc/java/decl.c @@ -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); diff --git a/gcc/java/except.c b/gcc/java/except.c index f44f072..1fb5934 100644 --- a/gcc/java/except.c +++ b/gcc/java/except.c @@ -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; diff --git a/gcc/java/expr.c b/gcc/java/expr.c index 430db4a..3c1c0ff 100644 --- a/gcc/java/expr.c +++ b/gcc/java/expr.c @@ -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) diff --git a/gcc/java/java-except.h b/gcc/java/java-except.h index 49ef54b..e069053 100644 --- a/gcc/java/java-except.h +++ b/gcc/java/java-except.h @@ -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)); diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h index a8370c4..288a6cb 100644 --- a/gcc/java/java-tree.h +++ b/gcc/java/java-tree.h @@ -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 |