[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:
parent
8a21007c94
commit
bf71cd2eaa
7 changed files with 108 additions and 131 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
131
gcc/cp/except.c
131
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:
|
||||
|
|
|
@ -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)
|
||||
|
|
55
gcc/except.c
55
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue