diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 05ded0c495c..44e65f40e87 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +Tue Sep 15 14:10:54 EDT 1998 Andrew MacLeod + + * except.h (struct eh_entry): Add false_label field. + (end_catch_handler): Add prototype. + * except.c (push_eh_entry): Set false_label field to NULL_RTX. + (start_catch_handler): When using old style exceptions, issue + runtime typematch code before continuing with the handler. + (end_catch_handler): New function, generates label after handler + if needed by older style exceptions. + (expand_start_all_catch): No need to check for new style exceptions. + (output_exception_table_entry): Only output the first handler label + for old style exceptions. + * libgcc2.c (__eh_rtime_match): New routine to lump runtime matching + mechanism into one function, if a runtime matcher is provided. + Tue Sep 15 13:53:59 EDT 1998 Andrew MacLeod * config/i960/i960.h (SLOW_BYTE_ACCESS): Change definition to 1. diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6fd77b1a162..9ed5652f39f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +1998-09-15 Andrew MacLeod + + * except.c (expand_start_catch_block): No need to check for new + exception model. + (process_start_catch_block_old): Deleted. + (process_start_catch_block): Add call to start_decl_1(). + (expand_end_catch_block): Add call to end_catch_handler(). + * exception.cc (__cplus_type_matcher): Only check the exception + language if there is an exception table. + 1998-09-15 Andrew MacLeod * search.c (expand_indirect_vtbls_init): Mark temporary stack slots diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 69315beba39..c3ae3575d65 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -597,135 +597,14 @@ expand_start_catch_block (declspecs, declarator) if (! doing_eh (1)) return; - if (flag_new_exceptions) - process_start_catch_block (declspecs, declarator); - else - process_start_catch_block_old (declspecs, declarator); + process_start_catch_block (declspecs, declarator); } -/* This function performs the expand_start_catch_block functionality for - exceptions implemented in the old style, where catch blocks were all - called, and had to check the runtime information themselves. */ - -static void -process_start_catch_block_old (declspecs, declarator) - tree declspecs, declarator; -{ - rtx false_label_rtx; - tree decl = NULL_TREE; - tree init; - - /* Create a binding level for the eh_info and the exception object - cleanup. */ - pushlevel (0); - expand_start_bindings (0); - - false_label_rtx = gen_label_rtx (); - push_label_entry (&false_label_stack, false_label_rtx, NULL_TREE); - - emit_line_note (input_filename, lineno); - - push_eh_info (); - - if (declspecs) - { - decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE); - - if (decl == NULL_TREE) - error ("invalid catch parameter"); - } - - if (decl) - { - tree exp; - rtx call_rtx, return_value_rtx; - tree init_type; - - /* Make sure we mark the catch param as used, otherwise we'll get - a warning about an unused ((anonymous)). */ - TREE_USED (decl) = 1; - - /* Figure out the type that the initializer is. */ - init_type = TREE_TYPE (decl); - if (TREE_CODE (init_type) != REFERENCE_TYPE - && TREE_CODE (init_type) != POINTER_TYPE) - init_type = build_reference_type (init_type); - - exp = get_eh_value (); - - /* Since pointers are passed by value, initialize a reference to - pointer catch parm with the address of the value slot. */ - if (TREE_CODE (init_type) == REFERENCE_TYPE - && TREE_CODE (TREE_TYPE (init_type)) == POINTER_TYPE) - exp = build_unary_op (ADDR_EXPR, exp, 1); - - exp = expr_tree_cons (NULL_TREE, - build_eh_type_type (TREE_TYPE (decl)), - expr_tree_cons (NULL_TREE, - get_eh_type (), - expr_tree_cons (NULL_TREE, exp, NULL_TREE))); - exp = build_function_call (CatchMatch, exp); - call_rtx = expand_call (exp, NULL_RTX, 0); - - return_value_rtx = hard_function_value (ptr_type_node, exp); - - /* did the throw type match function return TRUE? */ - emit_cmp_insn (return_value_rtx, const0_rtx, EQ, NULL_RTX, - GET_MODE (return_value_rtx), 0, 0); - - /* if it returned FALSE, jump over the catch block, else fall into it */ - emit_jump_insn (gen_beq (false_label_rtx)); - - push_eh_cleanup (); - - /* Create a binding level for the parm. */ - pushlevel (0); - expand_start_bindings (0); - - init = convert_from_reference (make_tree (init_type, call_rtx)); - - /* If the constructor for the catch parm exits via an exception, we - must call terminate. See eh23.C. */ - if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))) - { - /* Generate the copy constructor call directly so we can wrap it. - See also expand_default_init. */ - init = ocp_convert (TREE_TYPE (decl), init, - CONV_IMPLICIT|CONV_FORCE_TEMP, 0); - init = build (TRY_CATCH_EXPR, TREE_TYPE (init), init, - build_terminate_handler ()); - } - - /* Let `cp_finish_decl' know that this initializer is ok. */ - DECL_INITIAL (decl) = init; - decl = pushdecl (decl); - - start_decl_1 (decl); - cp_finish_decl (decl, DECL_INITIAL (decl), - NULL_TREE, 0, LOOKUP_ONLYCONVERTING); - } - else - { - push_eh_cleanup (); - - /* Create a binding level for the parm. */ - pushlevel (0); - expand_start_bindings (0); - - /* Fall into the catch all section. */ - } - - init = build_modify_expr (get_eh_caught (), NOP_EXPR, integer_one_node); - expand_expr (init, const0_rtx, VOIDmode, EXPAND_NORMAL); - - emit_line_note (input_filename, lineno); -} - /* This function performs the expand_start_catch_block functionality for exceptions implemented in the new style. __throw determines whether a handler needs to be called or not, so the handler itself has to do - nothing additionaal. */ + nothing additional. */ static void process_start_catch_block (declspecs, declarator) @@ -806,6 +685,7 @@ process_start_catch_block (declspecs, declarator) DECL_INITIAL (decl) = init; decl = pushdecl (decl); + start_decl_1 (decl); cp_finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING); } else @@ -849,10 +729,7 @@ expand_end_catch_block () documentation. */ expand_goto (top_label_entry (&caught_return_label_stack)); - /* label we emit to jump to if this catch block didn't match. */ - /* This the closing } in the `if (eq) {' of the documentation. */ - if (! flag_new_exceptions) - emit_label (pop_label_entry (&false_label_stack)); + end_catch_handler (); } /* An exception spec is implemented more or less like: diff --git a/gcc/cp/exception.cc b/gcc/cp/exception.cc index 4c10404cad8..5fafd1f0683 100644 --- a/gcc/cp/exception.cc +++ b/gcc/cp/exception.cc @@ -157,7 +157,9 @@ __cplus_type_matcher (cp_eh_info *info, rtimetype match_info, { void *ret; - if (exception_table->lang.language != EH_LANG_C_plus_plus) + /* No exception table implies the old style mechanism, so don't check. */ + if (exception_table != NULL && + exception_table->lang.language != EH_LANG_C_plus_plus) return NULL; if (match_info == CATCH_ALL_TYPE) diff --git a/gcc/except.c b/gcc/except.c index 5f2c61ad388..f0d00094f85 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -597,6 +597,7 @@ push_eh_entry (stack) entry->finalization = NULL_TREE; entry->label_used = 0; entry->exception_handler_label = gen_exception_label (); + entry->false_label = NULL_RTX; node->entry = entry; node->chain = stack->top; @@ -1600,6 +1601,54 @@ start_catch_handler (rtime) receive_exception_label (handler_label); add_new_handler (eh_region_entry, get_new_handler (handler_label, rtime)); + + if (flag_new_exceptions && ! exceptions_via_longjmp) + return; + + /* Under the old mechanism, as well as setjmp/longjmp, we need to + issue code to compare 'rtime' to the value in eh_info, via the + matching function in eh_info. If its is false, we branch around + the handler we are about to issue. */ + + if (rtime != NULL_TREE && rtime != CATCH_ALL_TYPE) + { + rtx call_rtx, rtime_address; + + if (catchstack.top->entry->false_label != NULL_RTX) + error ("never issued previous false_label"); + catchstack.top->entry->false_label = gen_exception_label (); + + rtime_address = expand_expr (rtime, NULL_RTX, Pmode, EXPAND_INITIALIZER); + rtime_address = force_reg (Pmode, rtime_address); + + /* Now issue the call, and branch around handler if needed */ + call_rtx = emit_library_call_value ( + gen_rtx_SYMBOL_REF (Pmode, "__eh_rtime_match"), NULL_RTX, + 0, SImode, 1, rtime_address, Pmode); + + /* Did the function return true? */ + emit_cmp_insn (call_rtx, const0_rtx, EQ, NULL_RTX, + GET_MODE (call_rtx), 0 ,0); + emit_jump_insn (gen_beq (catchstack.top->entry->false_label)); + } +} + +/* Called to end a catch clause. If we aren't using the new exception + model tabel mechanism, we need to issue the branch-around label + for the end of the catch block. */ + +void +end_catch_handler () +{ + if (! doing_eh (1) || (flag_new_exceptions && ! exceptions_via_longjmp)) + return; + + /* A NULL label implies the catch clause was a catch all or cleanup */ + if (catchstack.top->entry->false_label == NULL_RTX) + return; + + emit_label (catchstack.top->entry->false_label); + catchstack.top->entry->false_label = NULL_RTX; } /* Generate RTL for the start of a group of catch clauses. @@ -1693,9 +1742,6 @@ expand_start_all_catch () ehstack.top->entry->outer_context = outer_context; } - /* We also have to start the handler if we aren't using the new model. */ - if (! flag_new_exceptions) - start_catch_handler (NULL); } /* Finish up the catch block. At this point all the insns for the @@ -1927,6 +1973,9 @@ output_exception_table_entry (file, n) POINTER_SIZE / BITS_PER_UNIT); } putc ('\n', file); /* blank line */ + /* We only output the first label under the old scheme */ + if (! flag_new_exceptions) + break; } } diff --git a/gcc/except.h b/gcc/except.h index d20b6067cb0..5416e598760 100644 --- a/gcc/except.h +++ b/gcc/except.h @@ -53,6 +53,10 @@ struct label_node { label or not. New ones are needed for additional catch blocks if it has. + FALSE_LABEL is used when either setjmp/longjmp exceptions are in + use, or old style table exceptions. It contains the label for + branching to the next runtime type check as handlers are processed. + FINALIZATION is the tree codes for the handler, or is NULL_TREE if one hasn't been generated yet, or is integer_zero_node to mark the end of a group of try blocks. */ @@ -62,6 +66,7 @@ struct eh_entry { rtx exception_handler_label; tree finalization; int label_used; + rtx false_label; }; /* A list of EH_ENTRYs. ENTRY is the entry; CHAIN points to the next @@ -237,6 +242,10 @@ extern void add_eh_table_entry PROTO((int n)); extern void start_catch_handler PROTO((tree)); #endif +/* End an individual catch clause. */ + +extern void end_catch_handler PROTO((void)); + /* Returns a non-zero value if we need to output an exception table. */ extern int exception_table_p PROTO((void)); diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c index 7c26e6bc946..6f2fcfd9796 100644 --- a/gcc/libgcc2.c +++ b/gcc/libgcc2.c @@ -3355,6 +3355,21 @@ __sjpopnthrow () /* Support code for all exception region-based exception handling. */ +int +__eh_rtime_match (void *rtime) +{ + void *info; + __eh_matcher matcher; + void *ret; + + info = *(__get_eh_info ()); + matcher = ((__eh_info *)info)->match_function; + if (!matcher) + perror ("No runtime type matcher available"); + ret = (*matcher) (info, rtime, (void *)0); + return ((int)ret); +} + /* This value identifies the place from which an exception is being thrown. */