diff options
Diffstat (limited to 'gcc/java/except.c')
-rw-r--r-- | gcc/java/except.c | 75 |
1 files changed, 65 insertions, 10 deletions
diff --git a/gcc/java/except.c b/gcc/java/except.c index c5c7dcf27f4..b77842e8a66 100644 --- a/gcc/java/except.c +++ b/gcc/java/except.c @@ -170,6 +170,7 @@ link_handler (struct eh_range *range, struct eh_range *outer) TREE_VALUE (range->handlers)); h->next_sibling = NULL; h->expanded = 0; + h->stmt = NULL; /* Restart both from the top to avoid having to make this function smart about reentrancy. */ link_handler (h, &whole_range); @@ -287,6 +288,7 @@ add_handler (int start_pc, int end_pc, tree handler, tree type) h->handlers = build_tree_list (type, handler); h->next_sibling = NULL; h->expanded = 0; + h->stmt = NULL; if (prev == NULL) whole_range.first_child = h; @@ -294,7 +296,6 @@ add_handler (int start_pc, int end_pc, tree handler, tree type) prev->next_sibling = h; } - /* if there are any handlers for this range, issue start of region */ static void expand_start_java_handler (struct eh_range *range) @@ -304,8 +305,14 @@ expand_start_java_handler (struct eh_range *range) fprintf (stderr, "expand start handler pc %d --> %d\n", current_pc, range->end_pc); #endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */ + { + tree new = build (TRY_CATCH_EXPR, void_type_node, NULL, NULL); + TREE_SIDE_EFFECTS (new) = 1; + java_add_stmt (build_java_empty_stmt ()); + range->stmt = java_add_stmt (new); + } + range->expanded = 1; - expand_eh_region_start (); } tree @@ -348,7 +355,7 @@ prepare_eh_table_type (tree type) DECL_INITIAL (decl) = build_class_ref (type); layout_decl (decl, 0); pushdecl (decl); - exp = build1 (ADDR_EXPR, ptr_type_node, decl); + exp = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (decl)), decl); } else { @@ -370,6 +377,8 @@ prepare_eh_table_type (tree type) TYPE_CATCH_CLASSES (output_class)); } + exp = convert (ptr_type_node, exp); + *slot = tree_cons (type, exp, NULL_TREE); return exp; @@ -379,7 +388,10 @@ static int expand_catch_class (void **entry, void *x ATTRIBUTE_UNUSED) { struct treetreehash_entry *ite = (struct treetreehash_entry *) *entry; - tree decl = TREE_OPERAND (TREE_VALUE ((tree)ite->value), 0); + tree addr = TREE_VALUE ((tree)ite->value); + tree decl; + STRIP_NOPS (addr); + decl = TREE_OPERAND (addr, 0); rest_of_decl_compilation (decl, (char*) 0, global_bindings_p (), 0); return true; } @@ -420,8 +432,9 @@ static void expand_end_java_handler (struct eh_range *range) { tree handler = range->handlers; - force_poplevels (range->start_pc); - expand_start_all_catch (); + tree compound = NULL; + + force_poplevels (range->start_pc); for ( ; handler != NULL_TREE; handler = TREE_CHAIN (handler)) { /* For bytecode we treat exceptions a little unusually. A @@ -431,14 +444,56 @@ expand_end_java_handler (struct eh_range *range) extra (and difficult) work to get this to look like a gcc-style finally clause. */ tree type = TREE_PURPOSE (handler); + if (type == NULL) type = throwable_type_node; - expand_start_catch (prepare_eh_table_type (type)); - expand_goto (TREE_VALUE (handler)); - expand_end_catch (); + type = prepare_eh_table_type (type); + + if (compound) + { + /* If we already have a COMPOUND there is more than one + catch handler for this try block. Wrap the + TRY_CATCH_EXPR in operand 1 of COMPOUND with another + TRY_CATCH_EXPR. */ + tree inner_try_expr = TREE_OPERAND (compound, 1); + tree catch_expr + = build (CATCH_EXPR, void_type_node, type, + build (GOTO_EXPR, void_type_node, TREE_VALUE (handler))); + tree try_expr + = build (TRY_CATCH_EXPR, void_type_node, + inner_try_expr, catch_expr); + TREE_OPERAND (compound, 1) = try_expr; + } + else + { + tree *stmts = get_stmts (); + tree outer; + tree try_expr; + compound = range->stmt; + outer = TREE_OPERAND (compound, 0); + try_expr = TREE_OPERAND (compound, 1); + /* On the left of COMPOUND is the expresion to be evaluated + before the try handler is entered; on the right is a + TRY_FINALLY_EXPR with no operands as yet. In the current + statement list is an expression that we're going to move + inside the try handler. We'll create a new COMPOUND_EXPR + with the outer context on the left and the TRY_FINALLY_EXPR + on the right, then nullify both operands of COMPOUND, which + becomes the final expression in OUTER. This new compound + expression replaces the current statement list. */ + TREE_OPERAND (try_expr, 0) = *stmts; + TREE_OPERAND (try_expr, 1) + = build (CATCH_EXPR, void_type_node, type, + build (GOTO_EXPR, void_type_node, TREE_VALUE (handler))); + TREE_SIDE_EFFECTS (try_expr) = 1; + TREE_OPERAND (compound, 0) = build_java_empty_stmt (); + TREE_OPERAND (compound, 1) = build_java_empty_stmt (); + compound + = build (COMPOUND_EXPR, TREE_TYPE (try_expr), outer, try_expr); + *stmts = compound; + } } - expand_end_all_catch (); #if defined(DEBUG_JAVA_BINDING_LEVELS) indent (); fprintf (stderr, "expand end handler pc %d <-- %d\n", |