install EH code

From-SVN: r12549
This commit is contained in:
Mike Stump 1996-07-23 20:03:47 +00:00
parent 3d1953912d
commit 6adb4e3a29
11 changed files with 179 additions and 40 deletions

View File

@ -127,6 +127,14 @@ struct function
int emit_lineno;
struct goto_fixup *goto_fixup_chain;
/* For exception handling information. */
struct eh_stack ehstack;
struct eh_queue ehqueue;
rtx catch_clauses;
struct label_node *false_label_stack;
struct label_node *caught_return_label_stack;
tree protect_list;
/* For expr.c. */
int pending_stack_adjust;
int inhibit_defer_pop;

View File

@ -33,6 +33,7 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "integrate.h"
#include "real.h"
#include "except.h"
#include "function.h"
#include "bytecode.h"
@ -170,6 +171,19 @@ function_cannot_inline_p (fndecl)
if (current_function_has_nonlocal_goto)
return "function with nonlocal goto cannot be inline";
/* This is a hack, until the inliner is taught about eh regions at
the start of the function. */
for (insn = get_insns ();
insn &&
! (GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG);
insn = NEXT_INSN (insn))
{
if (insn && GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
return "function with complex parameters cannot be inline";
}
return 0;
}
@ -309,6 +323,7 @@ initialize_for_inline (fndecl, min_labelno, max_labelno, max_reg, copy)
the size of the incoming stack area for parameters,
the number of bytes popped on return,
the stack slot list,
the labels that are forced to exist,
some flags that are used to restore compiler globals,
the value of current_function_outgoing_args_size,
the original argument vector,
@ -335,7 +350,7 @@ finish_inline (fndecl, head)
tree fndecl;
rtx head;
{
NEXT_INSN (head) = get_first_nonparm_insn ();
FIRST_FUNCTION_INSN (head) = get_first_nonparm_insn ();
FIRST_PARM_INSN (head) = get_insns ();
DECL_SAVED_INSNS (fndecl) = head;
DECL_FRAME_SIZE (fndecl) = get_frame_size ();
@ -565,6 +580,15 @@ save_for_inline_copying (fndecl)
NOTE_SOURCE_FILE (insn) = (char *) copy;
NOTE_SOURCE_FILE (copy) = 0;
}
if (NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_BEG
|| NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_END)
{
/* We have to forward these both to match the new exception
region. */
NOTE_BLOCK_NUMBER (copy)
= CODE_LABEL_NUMBER (label_map[NOTE_BLOCK_NUMBER (copy)]);
}
RTX_INTEGRATED_P (copy) = RTX_INTEGRATED_P (insn);
break;
@ -1872,7 +1896,18 @@ expand_inline_function (fndecl, parms, target, ignore, type,
if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_BEG
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED)
{
copy = emit_note (NOTE_SOURCE_FILE (insn), NOTE_LINE_NUMBER (insn));
if (copy && (NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_BEG
|| NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_END))
{
rtx label = map->label_map[NOTE_BLOCK_NUMBER (copy)];
/* We have to forward these both to match the new exception
region. */
NOTE_BLOCK_NUMBER (copy) = CODE_LABEL_NUMBER (label);
}
}
else
copy = 0;
break;

View File

@ -60,6 +60,7 @@ Boston, MA 02111-1307, USA. */
#include "insn-flags.h"
#include "expr.h"
#include "real.h"
#include "except.h"
/* ??? Eventually must record somehow the labels used by jumps
from nested functions. */
@ -234,6 +235,16 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
for (insn = forced_labels; insn; insn = XEXP (insn, 1))
LABEL_NUSES (XEXP (insn, 0))++;
check_exception_handler_labels ();
/* Keep track of labels used for marking handlers for exception
regions; they cannot usually be deleted. */
for (insn = exception_handler_labels; insn; insn = XEXP (insn, 1))
LABEL_NUSES (XEXP (insn, 0))++;
exception_optimize ();
/* Delete all labels already not referenced.
Also find the last insn. */

View File

@ -2989,6 +2989,13 @@ int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */
#endif /* L_exit */
#ifdef L_eh
#ifdef EH_TABLE_LOOKUP
EH_TABLE_LOOKUP
#else
typedef struct {
void *start;
void *end;
@ -3095,21 +3102,9 @@ void *pc;
#endif
#if 0
printf("find_first_eh_table_match(): else: returning NULL!\n");
printf ("find_first_eh_table_match(): else: returning NULL!\n");
#endif
return (void*)0;
}
void *
__throw_type_match (void *catch_type, void *throw_type, void* obj)
{
#if 0
printf("__throw_type_match (): catch_type = %s, throw_type = %s\n",
catch_type, throw_type);
#endif
if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0)
return obj;
return 0;
return (void *) 0;
}
void
@ -3140,6 +3135,19 @@ __register_exceptions (exception_table *table)
node->next = exception_table_list;
exception_table_list = node;
}
#endif
void *
__throw_type_match (void *catch_type, void *throw_type, void *obj)
{
#if 0
printf ("__throw_type_match (): catch_type = %s, throw_type = %s\n",
catch_type, throw_type);
#endif
if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0)
return obj;
return 0;
}
void
__empty ()

View File

@ -47,6 +47,7 @@ Boston, MA 02111-1307, USA. */
#include "flags.h"
#include "real.h"
#include "loop.h"
#include "except.h"
/* Vector mapping INSN_UIDs to luids.
The luids are like uids but increase monotonically always.
@ -2290,6 +2291,19 @@ find_and_verify_loops (f)
loop_invalid[loop_num] = 1;
}
/* Any loop containing a label used for an exception handler must be
invalidated, because it can be jumped into from anywhere. */
for (label = exception_handler_labels; label; label = XEXP (label, 1))
{
int loop_num;
for (loop_num = uid_loop_num[INSN_UID (XEXP (label, 0))];
loop_num != -1;
loop_num = loop_outer_loop[loop_num])
loop_invalid[loop_num] = 1;
}
/* Now scan all insn's in the function. If any JUMP_INSN branches into a
loop that it is not contained within, that loop is marked invalid.
If any INSN or CALL_INSN uses a label's address, then the loop containing

View File

@ -118,6 +118,8 @@ rtx bcmp_libfunc;
rtx memset_libfunc;
rtx bzero_libfunc;
rtx throw_libfunc;
rtx eqhf2_libfunc;
rtx nehf2_libfunc;
rtx gthf2_libfunc;
@ -4247,6 +4249,8 @@ init_optabs ()
memset_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memset");
bzero_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bzero");
throw_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__throw");
eqhf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqhf2");
nehf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nehf2");
gthf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gthf2");

View File

@ -140,6 +140,9 @@ extern void named_section PROTO((tree, char *));
/* Tell assembler to switch to the section for function DECL. */
extern void function_section PROTO((tree));
/* Tell assembler to switch to the section for the exception table. */
extern void exception_section PROTO((void));
/* Create the rtl to represent a function, for a function definition.
DECL is a FUNCTION_DECL node which describes which function.
The rtl is stored into DECL. */

View File

@ -108,6 +108,14 @@ print_rtx (in_rtx)
{
case 'S':
case 's':
if (i == 3 && GET_CODE (in_rtx) == NOTE
&& (NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_EH_REGION_BEG
|| NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_EH_REGION_END))
{
fprintf (outfile, " %d", NOTE_BLOCK_NUMBER (in_rtx));
sawclose = 1;
break;
}
if (XSTR (in_rtx, i) == 0)
fprintf (outfile, " \"\"");
else

View File

@ -111,9 +111,11 @@ Boston, MA 02111-1307, USA. */
reg_n_calls_crossed, and reg_live_length. Also, basic_block_head,
basic_block_end.
The information in the line number notes is carefully retained by this
pass. All other NOTE insns are grouped in their same relative order at
the beginning of basic blocks that have been scheduled. */
The information in the line number notes is carefully retained by
this pass. Notes that refer to the starting and ending of
exception regions are also carefully retained by this pass. All
other NOTE insns are grouped in their same relative order at the
beginning of basic blocks that have been scheduled. */
#include <stdio.h>
#include "config.h"
@ -2078,7 +2080,7 @@ sched_analyze_insn (x, insn, loop_notes)
sched_analyze_2 (XEXP (link, 0), insn);
}
/* If there is a LOOP_{BEG,END} note in the middle of a basic block, then
/* If there is a {LOOP,EHREGION}_{BEG,END} note in the middle of a basic block, then
we must be sure that no instructions are scheduled across it.
Otherwise, the reg_n_refs info (which depends on loop_depth) would
become incorrect. */
@ -2240,8 +2242,13 @@ sched_analyze (head, tail)
}
reg_pending_sets_all = 1;
/* Add a fake REG_NOTE which we will later convert
back into a NOTE_INSN_SETJMP note. */
/* Add a pair of fake REG_NOTEs which we will later
convert back into a NOTE_INSN_SETJMP note. See
reemit_notes for why we use a pair of of NOTEs. */
REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_DEAD,
GEN_INT (0),
REG_NOTES (insn));
REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_DEAD,
GEN_INT (NOTE_INSN_SETJMP),
REG_NOTES (insn));
@ -2285,12 +2292,18 @@ sched_analyze (head, tail)
last_function_call = insn;
n_insns += 1;
}
/* See comments on reemit_notes as to why we do this. */
else if (GET_CODE (insn) == NOTE
&& (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END
|| (NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP
&& GET_CODE (PREV_INSN (insn)) != CALL_INSN)))
{
loop_notes = gen_rtx (EXPR_LIST, REG_DEAD,
GEN_INT (NOTE_BLOCK_NUMBER (insn)), loop_notes);
loop_notes = gen_rtx (EXPR_LIST, REG_DEAD,
GEN_INT (NOTE_LINE_NUMBER (insn)), loop_notes);
CONST_CALL_P (loop_notes) = CONST_CALL_P (insn);
@ -3077,10 +3090,12 @@ unlink_notes (insn, tail)
/* Don't save away NOTE_INSN_SETJMPs, because they must remain
immediately after the call they follow. We use a fake
(REG_DEAD (const_int -1)) note to remember them.
Likewise with NOTE_INSN_LOOP_BEG and NOTE_INSN_LOOP_END. */
Likewise with NOTE_INSN_{LOOP,EHREGION}_{BEG, END}. */
else if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_SETJMP
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_BEG
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_END)
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_END
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_BEG
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_END)
{
/* Insert the note at the end of the notes list. */
PREV_INSN (insn) = note_list;
@ -3143,10 +3158,12 @@ finish_sometimes_live (regs_sometimes_live, sometimes_max)
}
}
/* Search INSN for fake REG_DEAD notes for NOTE_INSN_SETJMP,
NOTE_INSN_LOOP_BEG, and NOTE_INSN_LOOP_END; and convert them back
into NOTEs. LAST is the last instruction output by the instruction
scheduler. Return the new value of LAST. */
/* Search INSN for fake REG_DEAD note pairs for NOTE_INSN_SETJMP,
NOTE_INSN_{LOOP,EHREGION}_{BEG,END}; and convert them back into
NOTEs. The REG_DEAD note following first one is contains the saved
value for NOTE_BLOCK_NUMBER which is useful for
NOTE_INSN_EH_REGION_{BEG,END} NOTEs. LAST is the last instruction
output by the instruction scheduler. Return the new value of LAST. */
static rtx
reemit_notes (insn, last)
@ -3161,11 +3178,20 @@ reemit_notes (insn, last)
&& GET_CODE (XEXP (note, 0)) == CONST_INT)
{
if (INTVAL (XEXP (note, 0)) == NOTE_INSN_SETJMP)
{
CONST_CALL_P (emit_note_after (INTVAL (XEXP (note, 0)), insn))
= CONST_CALL_P (note);
remove_note (insn, note);
note = XEXP (note, 1);
}
else
{
last = emit_note_before (INTVAL (XEXP (note, 0)), last);
remove_note (insn, note);
note = XEXP (note, 1);
NOTE_BLOCK_NUMBER (last) = INTVAL (XEXP (note, 0));
}
remove_note (insn, note);
}
}
return last;
@ -3961,8 +3987,8 @@ schedule_block (b, file)
}
}
/* Put back NOTE_INSN_SETJMP, NOTE_INSN_LOOP_BEGIN, and
NOTE_INSN_LOOP_END notes. */
/* Put back NOTE_INSN_SETJMP,
NOTE_INSN_{LOOP,EHREGION}_{BEGIN,END} notes. */
/* To prime the loop. We need to handle INSN and all the insns in the
sched group. */

View File

@ -41,6 +41,7 @@ Boston, MA 02111-1307, USA. */
#include "rtl.h"
#include "tree.h"
#include "flags.h"
#include "except.h"
#include "function.h"
#include "insn-flags.h"
#include "insn-config.h"
@ -134,8 +135,6 @@ extern tree rtl_expr_chain;
cleanup list whenever an empty list is required. */
static tree empty_cleanup_list;
#endif
extern void (*interim_eh_hook) PROTO((tree));
/* Functions and data structures for expanding case statements. */
@ -473,9 +472,7 @@ void
init_stmt ()
{
gcc_obstack_init (&stmt_obstack);
#if 0
empty_cleanup_list = build_tree_list (NULL_TREE, NULL_TREE);
#endif
init_eh ();
}
void
@ -498,6 +495,8 @@ init_stmt_for_function ()
/* We are not processing a ({...}) grouping. */
expr_stmts_for_value = 0;
last_expr_type = 0;
init_eh_for_function ();
}
void
@ -518,6 +517,7 @@ save_stmt_status (p)
p->emit_filename = emit_filename;
p->emit_lineno = emit_lineno;
p->goto_fixup_chain = goto_fixup_chain;
save_eh_status (p);
}
void
@ -538,6 +538,7 @@ restore_stmt_status (p)
emit_filename = p->emit_filename;
emit_lineno = p->emit_lineno;
goto_fixup_chain = p->goto_fixup_chain;
restore_eh_status (p);
}
/* Emit a no-op instruction. */
@ -3730,7 +3731,7 @@ expand_decl_cleanup (decl, cleanup)
= temp_tree_cons (decl, cleanup, thisblock->data.block.cleanups);
/* If this block has a cleanup, it belongs in stack_block_stack. */
stack_block_stack = thisblock;
(*interim_eh_hook) (NULL_TREE);
expand_eh_region_start ();
}
return 1;
}
@ -3831,7 +3832,7 @@ expand_cleanups (list, dont_do, in_fixup, reachable)
else
{
if (! in_fixup)
(*interim_eh_hook) (TREE_VALUE (tail));
expand_eh_region_end (TREE_VALUE (tail));
if (reachable)
{

View File

@ -33,6 +33,7 @@ Boston, MA 02111-1307, USA. */
#include "rtl.h"
#include "tree.h"
#include "flags.h"
#include "except.h"
#include "function.h"
#include "expr.h"
#include "output.h"
@ -414,6 +415,26 @@ variable_section (decl, reloc)
#endif
}
}
/* Tell assembler to switch to the section for the exception handling
table. */
void
exception_section ()
{
#ifdef ASM_OUTPUT_SECTION_NAME
named_section (NULL_TREE, ".gcc_except_table");
#else
if (flag_pic)
data_section ();
else
#if defined (EXCEPTION_SECTION)
EXCEPTION_SECTION ();
#else
readonly_data_section ();
#endif
#endif
}
/* Create the rtl to represent a function, for a function definition.
DECL is a FUNCTION_DECL node which describes which function.