[multiple changes]

Tue Sep 15 14:10:54 EDT 1998  Andrew MacLeod  <amacleod@cygnus.com>
        * 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.
1998-09-15  Andrew MacLeod  <amacleod@cygnus.com>
        * cp/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().
        * cp/exception.cc (__cplus_type_matcher): Only check the exception
        language if there is an exception table.

From-SVN: r22425
This commit is contained in:
Andrew MacLeod 1998-09-15 11:20:52 +00:00 committed by Andrew Macleod
parent 8a21007c94
commit bf71cd2eaa
7 changed files with 108 additions and 131 deletions

View File

@ -1,3 +1,18 @@
Tue Sep 15 14:10:54 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
* 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 <amacleod@cygnus.com>
* config/i960/i960.h (SLOW_BYTE_ACCESS): Change definition to 1.

View File

@ -1,3 +1,13 @@
1998-09-15 Andrew MacLeod <amacleod@cygnus.com>
* 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 <amacleod@cygnus.com>
* search.c (expand_indirect_vtbls_init): Mark temporary stack slots

View File

@ -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:

View File

@ -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)

View File

@ -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;
}
}

View File

@ -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));

View File

@ -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. */