Commit e6cfb550 by Andrew MacLeod Committed by Andrew Macleod

See ChangeLog..

Tue Dec  8 15:32:56 EST 1998  Andrew MacLeod  <amacleod@cygnus.com>
See ChangeLog.. These are the files that were changed:
	* eh-common.h (struct eh_context): Add table_index for rethrows.
	* rtl.h (enum reg_note): Add REG_EH_REGION and REG_EH_RETHROW reg notes.
	* rtl.c (reg_note_name): Add strings for new reg_note enums.
	* expr.h (rethrow_libfunc): New library decl.
	* optabs.c (rethrow_libfunc): Initialize.
	* except.h (struct eh_entry): Add new field 'rethrow_label'.
	* except.c (create_rethrow_ref): New function to create a single
	* flow.c (make_edges): Add different edges for rethrow calls,
	* integrate.c (save_for_inline_eh_labelmap): New callback routine to
	* libgcc2.c (find_exception_handler): Generalize to enable it to
        * cp/except.c
        * cp/exception.cc

From-SVN: r24194
parent 2bfdc2d4
Tue Dec 8 15:32:56 EST 1998 Andrew MacLeod <amacleod@cygnus.com>
* eh-common.h (struct eh_context): Add table_index for rethrows.
* rtl.h (enum reg_note): Add REG_EH_REGION and REG_EH_RETHROW reg notes.
(SYMBOL_REF_NEED_ADJUST): New flag indicating symbol needs to be
processed when inlined or unrolled (ie duplicated in some way).
* rtl.c (reg_note_name): Add strings for new reg_note enums.
* expr.h (rethrow_libfunc): New library decl.
* optabs.c (rethrow_libfunc): Initialize.
* except.h (struct eh_entry): Add new field 'rethrow_label'.
(new_eh_region_entry): No longer exported from except.c.
(duplicate_handlers): Renamed to duplicate_eh_handlers and
different prototype.
(rethrow_symbol_map, rethrow_used): New exported functions.
(eh_region_from_symbol): New exported function.
* except.c (create_rethrow_ref): New function to create a single
SYMBOL_REF for a rethrow region.
(push_eh_entry): Initialize a rethrow ref.
(func_eh_entry): Add a rethrow_label field.
(new_eh_region_entry): Make static, and initialize the rethrow entry.
(duplicate_eh_handlers): Create a new region, and remap labels/symbols.
(eh_region_from_symbol): Find an EH region based on its rethrow symbol.
(rethrow_symbol_map): Given a label map, maps a rethrow symbol for
a region into an appropriate new symbol.
(rethrow_used): Indicate whether a rethrow symbol has been referenced.
(expand_eh_region_end): Don't issue jump around code for new-exceptions.
(end_catch_handler): Emit a barrier for new-exceptions since
control can never drop through the end of a catch block.
(expand_end_all_catch): new-exceptions never fall through a catch
block.
(expand_rethrow): use __rethrow routine for new exceptions.
(output_exception_table_entry): Generate rethrow labels, if needed.
(output_exception_table): Generate start and end rethrow labels.
(init_eh): Create rethrow symbols for beginning and end of table.
(scan_region): Don't eliminate EH regions which are the targets of
rethrows.
* flow.c (make_edges): Add different edges for rethrow calls,
identified by having the REG_EH_RETHROW reg label.
(delete_unreachable_blocks): Don't delete regions markers which are
the target of a rethrow.
* integrate.c (save_for_inline_eh_labelmap): New callback routine to
allow save_for_inline_copying to call duplicate_eh_handlers.
(save_for_inline_copying): Call duplicate_eh_handlers instead of
exposing internal details of exception regions.
(copy_for_inline): Check if SYMBOL_REFs need adjustment.
(expand_inline_function_eh_labelmap): New callback routine to
allow expand_inline_function to call duplicate_eh_handlers.
(expand_inline_function): Call duplicate_eh_handlers instead of
exposing internal details of exception regions.
(copy_rtx_and_substitute): Adjust SYMBOL_REFS if SYMBOL_REF_NEED_ADJUST
flag is set.
* libgcc2.c (find_exception_handler): Generalize to enable it to
pick up processing where it left off last time for a rethrow.
(__unwinding_cleanup): New function. debug hook which is called before
unwinding when __throw finds there is nothing but cleanups left.
(throw_helper): Common parts of __throw extracted out for reuse.
(__throw): Common parts moved to throw_helper.
(__rethrow): New function for performing rethrows.
Tue Dec 8 13:11:04 1998 Jeffrey A Law (law@cygnus.com)
* reload1.c (current_function_decl): Tweak declaration.
......
1998-12-08 Andrew MacLeod <amacleod@cygnus.com>
* cp/except.c (call_eh_info): use __start_cp_handler instead of
__cp_eh_info for getting the eh info pointer. Add table_index to
field list.
(push_eh_cleanup): Don't increment 'handlers' data field.
(process_start_catch_block): Don't set the 'caught' field.
* cp/exception.cc (CP_EH_INFO): New macro for getting the
exception info pointer within library routines.
(__cp_eh_info): Use CP_EH_INFO.
(__start_cp_handler): Get exception info pointer, set caught field,
and increment the handlers field. Avoids this being done by handlers.
(__uncatch_exception, __check_eh_spec): Use CP_EH_INFO macro.
(uncaught_exception): Use CP_EH_INFO macro.
Tue Dec 8 10:48:21 1998 Jeffrey A Law (law@cygnus.com)
* Make-lang.in (cxxmain.o): Depend on $(DEMANGLE_H), not demangle.h
......
......@@ -249,14 +249,14 @@ call_eh_info ()
{
tree fn;
fn = get_identifier ("__cp_eh_info");
fn = get_identifier ("__start_cp_handler");
if (IDENTIFIER_GLOBAL_VALUE (fn))
fn = IDENTIFIER_GLOBAL_VALUE (fn);
else
{
tree t1, t, fields[7];
/* Declare cp_eh_info * __cp_eh_info (void),
/* Declare cp_eh_info * __start_cp_handler (void),
as defined in exception.cc. */
push_obstacks_nochange ();
end_temporary_allocation ();
......@@ -270,9 +270,11 @@ call_eh_info ()
get_identifier ("dynamic_handler_chain"), ptr_type_node);
fields[2] = build_lang_field_decl (FIELD_DECL,
get_identifier ("info"), ptr_type_node);
fields[3] = build_lang_field_decl (FIELD_DECL,
get_identifier ("table_index"), ptr_type_node);
/* N.B.: The fourth field LEN is expected to be
the number of fields - 1, not the total number of fields. */
finish_builtin_type (t1, "eh_context", fields, 2, ptr_type_node);
finish_builtin_type (t1, "eh_context", fields, 3, ptr_type_node);
t1 = build_pointer_type (t1);
t1= make_lang_type (RECORD_TYPE);
......@@ -547,9 +549,6 @@ push_eh_cleanup ()
{
int yes;
expand_expr (build_unary_op (PREINCREMENT_EXPR, get_eh_handlers (), 1),
const0_rtx, VOIDmode, EXPAND_NORMAL);
yes = suspend_momentary ();
/* All cleanups must last longer than normal. */
expand_decl_cleanup (NULL_TREE, do_pop_exception ());
......@@ -701,9 +700,6 @@ process_start_catch_block (declspecs, declarator)
/* 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);
}
......
......@@ -117,13 +117,29 @@ __cp_exception_info (void)
return &((*__get_eh_info ())->value);
}
/* Compiler hook to return a pointer to the info for the current exception.
#define CP_EH_INFO ((cp_eh_info *) *__get_eh_info ())
/* Old Compiler hook to return a pointer to the info for the current exception.
Used by get_eh_info (). */
extern "C" cp_eh_info *
__cp_eh_info (void)
{
return *__get_eh_info ();
cp_eh_info *p = CP_EH_INFO;
return p;
}
/* Compiler hook to return a pointer to the info for the current exception,
Set the caught bit, and increment the number of handlers that are
looking at this exception. This makes handlers smaller. */
extern "C" cp_eh_info *
__start_cp_handler (void)
{
cp_eh_info *p = CP_EH_INFO;
p->caught = 1;
p->handlers++;
return p;
}
/* Allocate a buffer for a cp_eh_info and an exception object of size SIZE,
......@@ -242,7 +258,7 @@ __cp_pop_exception (cp_eh_info *p)
extern "C" void
__uncatch_exception (void)
{
cp_eh_info *p = __cp_eh_info ();
cp_eh_info *p = CP_EH_INFO;
if (p == 0)
terminate ();
p->caught = false;
......@@ -263,7 +279,7 @@ __uncatch_exception (void)
extern "C" void
__check_eh_spec (int n, const void **spec)
{
cp_eh_info *p = __cp_eh_info ();
cp_eh_info *p = CP_EH_INFO;
for (int i = 0; i < n; ++i)
{
......@@ -316,7 +332,7 @@ __throw_bad_typeid (void)
bool
std::uncaught_exception ()
{
cp_eh_info *p = __cp_eh_info ();
cp_eh_info *p = CP_EH_INFO;
return p && ! p->caught;
}
......
......@@ -29,6 +29,8 @@ struct eh_context
void **dynamic_handler_chain;
/* This is language dependent part of the eh context. */
void *info;
/* This is used to remember where we threw for re-throws */
void *table_index; /* address of exception table entry to rethrow from */
};
#ifndef EH_TABLE_LOOKUP
......
......@@ -65,6 +65,7 @@ struct eh_entry {
tree finalization;
int label_used;
rtx false_label;
rtx rethrow_label;
};
/* A list of EH_ENTRYs. ENTRY is the entry; CHAIN points to the next
......@@ -177,13 +178,6 @@ typedef struct handler_info
} handler_info;
/* Add a new eh_entry for this function, The parameter specifies what
exception region number NOTE insns use to delimit this range.
The integer returned is uniquely identifies this exception range
within an internal table. */
int new_eh_region_entry PROTO((int));
/* Add new handler information to an exception range. The first parameter
specifies the range number (returned from new_eh_entry()). The second
parameter specifies the handler. By default the handler is inserted at
......@@ -208,8 +202,19 @@ struct handler_info *get_new_handler PROTO((rtx, void *));
/* Make a duplicate of an exception region by copying all the handlers
for an exception region. Return the new handler index. */
int duplicate_handlers PROTO((int, int));
int duplicate_eh_handlers PROTO((int, int, rtx (*)(rtx)));
/* map symbol refs for rethrow */
rtx rethrow_symbol_map PROTO((rtx, rtx (*)(rtx)));
/* Is the rethrow label for a region used? */
int rethrow_used PROTO((int));
/* Return the region number a this is the rethrow label for. */
int eh_region_from_symbol PROTO((rtx));
/* Get a pointer to the first handler in an exception region's list. */
......
......@@ -443,6 +443,7 @@ extern rtx memset_libfunc;
extern rtx bzero_libfunc;
extern rtx throw_libfunc;
extern rtx rethrow_libfunc;
extern rtx sjthrow_libfunc;
extern rtx sjpopnthrow_libfunc;
extern rtx terminate_libfunc;
......
......@@ -721,6 +721,7 @@ make_edges (i)
int i;
{
rtx insn, x;
rtx pending_eh_region = NULL_RTX;
/* See if control drops into the next block. */
if (i + 1 < n_basic_blocks)
......@@ -801,6 +802,40 @@ make_edges (i)
}
}
/* If this is a call with an EH_RETHROW note, then we
know its a rethrow call, and we know exactly where
this call can end up going. */
else if (GET_CODE (insn) == CALL_INSN
&& (note = find_reg_note (insn, REG_EH_RETHROW, NULL_RTX)))
{
int region = XINT (XEXP (note, 0), 0);
/* if nested region is not 0, we know for sure it has been
processed. If it is zero, we dont know whether its an
outer region, or hasn't been seen yet, so defer it */
if (nested_eh_region[region] != 0)
{
/* start with the first region OUTSIDE the one specified
in the rethrow parameter. (since a rethrow behaves
as if a handler in the region didn't handle the
exception, so the handlers for the next outer region
are going to get a shot at it.*/
for ( region = nested_eh_region[region]; region;
region = nested_eh_region[region])
{
handler_info *ptr = get_first_handler (region);
for ( ; ptr ; ptr = ptr->next)
add_edge_to_label (i, ptr->handler_label);
}
}
else
{
/* Push this region onto a list, and after we've done the
whole procedure, we'll process everything on the list */
pending_eh_region = gen_rtx_EXPR_LIST (VOIDmode, insn,
pending_eh_region);
}
}
/* If this is a CALL_INSN, then mark it as reaching the active EH
handler for this CALL_INSN. If we're handling asynchronous
exceptions mark every insn as reaching the active EH handler.
......@@ -837,6 +872,24 @@ make_edges (i)
}
}
}
while (pending_eh_region != NULL_RTX)
{
rtx insn = XEXP (pending_eh_region, 0);
rtx note = find_reg_note (insn, REG_EH_RETHROW, NULL_RTX);
int region = XINT (XEXP (note, 0), 0);
/* start with the first region OUTSIDE the one specified
in the rethrow parameter */
for ( region = nested_eh_region[region]; region;
region = nested_eh_region[region])
{
handler_info *ptr = get_first_handler (region);
for ( ; ptr ; ptr = ptr->next)
add_edge_to_label (BLOCK_NUM (insn), ptr->handler_label);
}
pending_eh_region = XEXP (pending_eh_region, 1);
}
/* We know something about the structure of the function __throw in
libgcc2.c. It is the only function that ever contains eh_stub labels.
It modifies its return address so that the last block returns to one of
......@@ -918,8 +971,9 @@ delete_unreachable_blocks ()
NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END)
{
int num = CODE_LABEL_NUMBER (insn);
/* A NULL handler indicates a region is no longer needed */
if (get_first_handler (num) == NULL)
/* A NULL handler indicates a region is no longer needed,
unless its the target of a rethrow. */
if (get_first_handler (num) == NULL && !rethrow_used (num))
{
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
NOTE_SOURCE_FILE (insn) = 0;
......
......@@ -265,6 +265,16 @@ static rtvec copy_asm_constraints_vector;
/* In save_for_inline, nonzero if past the parm-initialization insns. */
static int in_nonparm_insns;
/* subroutines passed to duplicate_eh_handlers to map exception labels */
static rtx
save_for_inline_eh_labelmap (label)
rtx label;
{
int index = CODE_LABEL_NUMBER (label);
return label_map[index];
}
/* Subroutine for `save_for_inline{copying,nocopy}'. Performs initialization
needed to save FNDECL's insns and info for future inline expansion. */
......@@ -667,19 +677,8 @@ save_for_inline_copying (fndecl)
/* we have to duplicate the handlers for the original */
if (NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_BEG)
{
handler_info *ptr, *temp;
int nr;
nr = new_eh_region_entry (new_region);
ptr = get_first_handler (NOTE_BLOCK_NUMBER (copy));
for ( ; ptr; ptr = ptr->next)
{
temp = get_new_handler (
label_map[CODE_LABEL_NUMBER (ptr->handler_label)],
ptr->type_info);
add_new_handler (nr, temp);
}
}
duplicate_eh_handlers (NOTE_BLOCK_NUMBER (copy), new_region,
save_for_inline_eh_labelmap);
/* We have to forward these both to match the new exception
region. */
......@@ -1075,11 +1074,15 @@ copy_for_inline (orig)
{
case QUEUED:
case CONST_INT:
case SYMBOL_REF:
case PC:
case CC0:
return x;
case SYMBOL_REF:
if (! SYMBOL_REF_NEED_ADJUST (x))
return x;
return rethrow_symbol_map (x, save_for_inline_eh_labelmap);
case CONST_DOUBLE:
/* We have to make a new CONST_DOUBLE to ensure that we account for
it correctly. Using the old CONST_DOUBLE_MEM data is wrong. */
......@@ -1338,6 +1341,18 @@ process_reg_param (map, loc, copy)
}
map->reg_map[REGNO (loc)] = copy;
}
/* Used by duplicate_eh_handlers to map labels for the exception table */
static struct inline_remap *eif_eh_map;
static rtx
expand_inline_function_eh_labelmap (label)
rtx label;
{
int index = CODE_LABEL_NUMBER (label);
return get_label_from_map (eif_eh_map, index);
}
/* Integrate the procedure defined by FNDECL. Note that this function
may wind up calling itself. Since the static variables are not
reentrant, we do not assign them until after the possibility
......@@ -2055,17 +2070,12 @@ expand_inline_function (fndecl, parms, target, ignore, type,
/* we have to duplicate the handlers for the original */
if (NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_BEG)
{
handler_info *ptr, *temp;
int nr;
nr = new_eh_region_entry (CODE_LABEL_NUMBER (label));
ptr = get_first_handler (NOTE_BLOCK_NUMBER (copy));
for ( ; ptr; ptr = ptr->next)
{
temp = get_new_handler ( get_label_from_map (map,
CODE_LABEL_NUMBER (ptr->handler_label)),
ptr->type_info);
add_new_handler (nr, temp);
}
/* We need to duplicate the handlers for the EH region
and we need to indicate where the label map is */
eif_eh_map = map;
duplicate_eh_handlers (NOTE_BLOCK_NUMBER (copy),
CODE_LABEL_NUMBER (label),
expand_inline_function_eh_labelmap);
}
/* We have to forward these both to match the new exception
......@@ -2533,6 +2543,13 @@ copy_rtx_and_substitute (orig, map)
map)),
0);
}
else
if (SYMBOL_REF_NEED_ADJUST (orig))
{
eif_eh_map = map;
return rethrow_symbol_map (orig,
expand_inline_function_eh_labelmap);
}
return orig;
......
......@@ -119,6 +119,7 @@ rtx memset_libfunc;
rtx bzero_libfunc;
rtx throw_libfunc;
rtx rethrow_libfunc;
rtx sjthrow_libfunc;
rtx sjpopnthrow_libfunc;
rtx terminate_libfunc;
......@@ -4294,6 +4295,7 @@ init_optabs ()
bzero_libfunc = gen_rtx_SYMBOL_REF (Pmode, "bzero");
throw_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__throw");
rethrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__rethrow");
sjthrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__sjthrow");
sjpopnthrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__sjpopnthrow");
terminate_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__terminate");
......
......@@ -193,7 +193,8 @@ char *reg_note_name[] = { "", "REG_DEAD", "REG_INC", "REG_EQUIV", "REG_WAS_0",
"REG_DEP_ANTI", "REG_DEP_OUTPUT", "REG_BR_PROB",
"REG_EXEC_COUNT", "REG_NOALIAS", "REG_SAVE_AREA",
"REG_BR_PRED", "REG_EH_CONTEXT",
"REG_FRAME_RELATED_EXPR" };
"REG_FRAME_RELATED_EXPR", "REG_EH_REGION",
"REG_EH_RETHROW" };
static void dump_and_abort PROTO((int, int, FILE *)) ATTRIBUTE_NORETURN;
static void read_name PROTO((char *, FILE *));
......
......@@ -340,6 +340,14 @@ typedef struct rtvec_def{
REG_FRAME_RELATED_EXPR is attached to insns that are RTX_FRAME_RELATED_P,
but are too complex for DWARF to interpret what they imply. The attached
rtx is used instead of intuition. */
/* REG_EH_REGION is used to indicate what exception region an INSN
belongs in. This can be used to indicate what region a call may throw
to. a REGION of 0 indicates that a call cannot throw at all.
REG_EH_RETHROW is used to indicate what that a call is actually a
call to rethrow, and specifies which region the rethrow is targetting.
This provides a way to generate the non standard flow edges required
for a rethrow. */
#define REG_NOTES(INSN) ((INSN)->fld[6].rtx)
......@@ -353,7 +361,8 @@ enum reg_note { REG_DEAD = 1, REG_INC = 2, REG_EQUIV = 3, REG_WAS_0 = 4,
REG_DEP_ANTI = 14, REG_DEP_OUTPUT = 15, REG_BR_PROB = 16,
REG_EXEC_COUNT = 17, REG_NOALIAS = 18, REG_SAVE_AREA = 19,
REG_BR_PRED = 20, REG_EH_CONTEXT = 21,
REG_FRAME_RELATED_EXPR = 22 };
REG_FRAME_RELATED_EXPR = 22, REG_EH_REGION = 23,
REG_EH_RETHROW = 24 };
/* The base value for branch probability notes. */
#define REG_BR_PROB_BASE 10000
......@@ -617,6 +626,10 @@ extern char *note_insn_name[];
/* Flag in a SYMBOL_REF for machine-specific purposes. */
#define SYMBOL_REF_FLAG(RTX) ((RTX)->volatil)
/* 1 in a SYMBOL_REF if it represents a symbol which might have to change
if its inlined or unrolled. */
#define SYMBOL_REF_NEED_ADJUST(RTX) ((RTX)->in_struct)
/* 1 means a SYMBOL_REF has been the library function in emit_library_call. */
#define SYMBOL_REF_USED(RTX) ((RTX)->used)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment