except.c (start_dynamic_handler): Fix so that we can use __builtin_setjmp...

* except.c (start_dynamic_handler): Fix so that we can use
 	__builtin_setjmp, and default to using __builtin_setjmp instead of
 	setjmp.
	* expr.c (expand_builtin_setjmp): New routine, split out from
	existing inline code from expand_builtin.
	(expand_builtin): Split out code into expand_builtin_setjmp.
	* expr.h (expand_builtin_setjmp): Add declaration.
	* libgcc2.c (__sjthrow): Default to using __builtin_setjmp instead
 	of setjmp.
	(__sjpopnthrow): Likewise.
	* optabs.c (init_optabs): Likewise.

From-SVN: r14045
This commit is contained in:
Mike Stump 1997-05-07 22:50:11 +00:00
parent 24f2dbd6f7
commit 6e6a07d299
5 changed files with 190 additions and 163 deletions

View File

@ -693,9 +693,9 @@ add_partial_entry (handler)
when there are no more elements in the dynamic handler chain, when
the value is &top_elt from libgcc2.c. Immediately after the
pointer, is an area suitable for setjmp/longjmp when
USE_BUILTIN_SETJMP isn't defined, and an area suitable for
__builtin_setjmp/__builtin_longjmp when USE_BUILTIN_SETJMP is
defined.
DONT_USE_BUILTIN_SETJMP is defined, and an area suitable for
__builtin_setjmp/__builtin_longjmp when DONT_USE_BUILTIN_SETJMP
isn't defined.
This routine is here to facilitate the porting of this code to
systems with threads. One can either replace the routine we emit a
@ -843,10 +843,10 @@ static void
start_dynamic_handler ()
{
rtx dhc, dcc;
rtx x, arg;
rtx x, arg, buf;
int size;
#ifdef USE_BUILTIN_SETJMP
#ifndef DONT_USE_BUILTIN_SETJMP
/* The number of Pmode words for the setjmp buffer, when using the
builtin setjmp/longjmp, see expand_builtin, case
BUILT_IN_LONGJMP. */
@ -882,10 +882,14 @@ start_dynamic_handler ()
emit_move_insn (dcc, const0_rtx);
/* The jmpbuf starts two words into the area allocated. */
buf = plus_constant (XEXP (arg, 0), GET_MODE_SIZE (Pmode)*2);
#ifdef DONT_USE_BUILTIN_SETJMP
x = emit_library_call_value (setjmp_libfunc, NULL_RTX, 1, SImode, 1,
plus_constant (XEXP (arg, 0), GET_MODE_SIZE (Pmode)*2),
Pmode);
buf, Pmode);
#else
x = expand_builtin_setjmp (buf, NULL_RTX);
#endif
/* If we come back here for a catch, transfer control to the
handler. */

View File

@ -7880,6 +7880,169 @@ expand_builtin_return_addr (fndecl_code, count, tem)
#endif
return tem;
}
/* __builtin_setjmp is passed a pointer to an array of five words (not
all will be used on all machines). It operates similarly to the C
library function of the same name, but is more efficient. Much of
the code below (and for longjmp) is copied from the handling of
non-local gotos.
NOTE: This is intended for use by GNAT and the exception handling
scheme in the compiler and will only work in the method used by
them. */
rtx
expand_builtin_setjmp (buf_addr, target)
rtx buf_addr;
rtx target;
{
rtx lab1 = gen_label_rtx (), lab2 = gen_label_rtx ();
enum machine_mode sa_mode = Pmode, value_mode;
rtx stack_save;
int old_inhibit_defer_pop = inhibit_defer_pop;
int return_pops
= RETURN_POPS_ARGS (get_identifier ("__dummy"),
build_function_type (void_type_node, NULL_TREE),
0);
rtx next_arg_reg;
CUMULATIVE_ARGS args_so_far;
rtx op0;
int i;
value_mode = TYPE_MODE (integer_type_node);
#ifdef POINTERS_EXTEND_UNSIGNED
buf_addr = convert_memory_address (Pmode, buf_addr);
#endif
buf_addr = force_reg (Pmode, buf_addr);
if (target == 0 || GET_CODE (target) != REG
|| REGNO (target) < FIRST_PSEUDO_REGISTER)
target = gen_reg_rtx (value_mode);
emit_queue ();
CONST_CALL_P (emit_note (NULL_PTR, NOTE_INSN_SETJMP)) = 1;
current_function_calls_setjmp = 1;
/* We store the frame pointer and the address of lab1 in the buffer
and use the rest of it for the stack save area, which is
machine-dependent. */
emit_move_insn (gen_rtx (MEM, Pmode, buf_addr),
virtual_stack_vars_rtx);
emit_move_insn
(validize_mem (gen_rtx (MEM, Pmode,
plus_constant (buf_addr,
GET_MODE_SIZE (Pmode)))),
gen_rtx (LABEL_REF, Pmode, lab1));
#ifdef HAVE_save_stack_nonlocal
if (HAVE_save_stack_nonlocal)
sa_mode = insn_operand_mode[(int) CODE_FOR_save_stack_nonlocal][0];
#endif
stack_save = gen_rtx (MEM, sa_mode,
plus_constant (buf_addr,
2 * GET_MODE_SIZE (Pmode)));
emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
#ifdef HAVE_setjmp
if (HAVE_setjmp)
emit_insn (gen_setjmp ());
#endif
/* Set TARGET to zero and branch around the other case. */
emit_move_insn (target, const0_rtx);
emit_jump_insn (gen_jump (lab2));
emit_barrier ();
emit_label (lab1);
/* Note that setjmp clobbers FP when we get here, so we have to make
sure it's marked as used by this function. */
emit_insn (gen_rtx (USE, VOIDmode, hard_frame_pointer_rtx));
/* Mark the static chain as clobbered here so life information
doesn't get messed up for it. */
emit_insn (gen_rtx (CLOBBER, VOIDmode, static_chain_rtx));
/* Now put in the code to restore the frame pointer, and argument
pointer, if needed. The code below is from expand_end_bindings
in stmt.c; see detailed documentation there. */
#ifdef HAVE_nonlocal_goto
if (! HAVE_nonlocal_goto)
#endif
emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
current_function_has_nonlocal_goto = 1;
#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
if (fixed_regs[ARG_POINTER_REGNUM])
{
#ifdef ELIMINABLE_REGS
static struct elims {int from, to;} elim_regs[] = ELIMINABLE_REGS;
for (i = 0; i < sizeof elim_regs / sizeof elim_regs[0]; i++)
if (elim_regs[i].from == ARG_POINTER_REGNUM
&& elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
break;
if (i == sizeof elim_regs / sizeof elim_regs [0])
#endif
{
/* Now restore our arg pointer from the address at which it
was saved in our stack frame.
If there hasn't be space allocated for it yet, make
some now. */
if (arg_pointer_save_area == 0)
arg_pointer_save_area
= assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
emit_move_insn (virtual_incoming_args_rtx,
copy_to_reg (arg_pointer_save_area));
}
}
#endif
#ifdef HAVE_nonlocal_goto_receiver
if (HAVE_nonlocal_goto_receiver)
emit_insn (gen_nonlocal_goto_receiver ());
#endif
/* The static chain pointer contains the address of dummy function.
We need to call it here to handle some PIC cases of restoring a
global pointer. Then return 1. */
op0 = copy_to_mode_reg (Pmode, static_chain_rtx);
/* We can't actually call emit_library_call here, so do everything
it does, which isn't much for a libfunc with no args. */
op0 = memory_address (FUNCTION_MODE, op0);
INIT_CUMULATIVE_ARGS (args_so_far, NULL_TREE,
gen_rtx (SYMBOL_REF, Pmode, "__dummy"), 1);
next_arg_reg = FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1);
#ifndef ACCUMULATE_OUTGOING_ARGS
#ifdef HAVE_call_pop
if (HAVE_call_pop)
emit_call_insn (gen_call_pop (gen_rtx (MEM, FUNCTION_MODE, op0),
const0_rtx, next_arg_reg,
GEN_INT (return_pops)));
else
#endif
#endif
#ifdef HAVE_call
if (HAVE_call)
emit_call_insn (gen_call (gen_rtx (MEM, FUNCTION_MODE, op0),
const0_rtx, next_arg_reg, const0_rtx));
else
#endif
abort ();
emit_move_insn (target, const1_rtx);
emit_label (lab2);
return target;
}
/* Expand an expression EXP that calls a built-in function,
with result going to TARGET if that's convenient
@ -8718,15 +8881,6 @@ expand_builtin (exp, target, subtarget, mode, ignore)
break;
#endif
/* __builtin_setjmp is passed a pointer to an array of five words
(not all will be used on all machines). It operates similarly to
the C library function of the same name, but is more efficient.
Much of the code below (and for longjmp) is copied from the handling
of non-local gotos.
NOTE: This is intended for use by GNAT and will only work in
the method used by it. This code will likely NOT survive to
the GCC 2.8.0 release. */
case BUILT_IN_SETJMP:
if (arglist == 0
|| TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
@ -8735,148 +8889,7 @@ expand_builtin (exp, target, subtarget, mode, ignore)
{
rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
VOIDmode, 0);
rtx lab1 = gen_label_rtx (), lab2 = gen_label_rtx ();
enum machine_mode sa_mode = Pmode;
rtx stack_save;
int old_inhibit_defer_pop = inhibit_defer_pop;
int return_pops
= RETURN_POPS_ARGS (get_identifier ("__dummy"),
build_function_type (void_type_node, NULL_TREE),
0);
rtx next_arg_reg;
CUMULATIVE_ARGS args_so_far;
int i;
#ifdef POINTERS_EXTEND_UNSIGNED
buf_addr = convert_memory_address (Pmode, buf_addr);
#endif
buf_addr = force_reg (Pmode, buf_addr);
if (target == 0 || GET_CODE (target) != REG
|| REGNO (target) < FIRST_PSEUDO_REGISTER)
target = gen_reg_rtx (value_mode);
emit_queue ();
CONST_CALL_P (emit_note (NULL_PTR, NOTE_INSN_SETJMP)) = 1;
current_function_calls_setjmp = 1;
/* We store the frame pointer and the address of lab1 in the buffer
and use the rest of it for the stack save area, which is
machine-dependent. */
emit_move_insn (gen_rtx (MEM, Pmode, buf_addr),
virtual_stack_vars_rtx);
emit_move_insn
(validize_mem (gen_rtx (MEM, Pmode,
plus_constant (buf_addr,
GET_MODE_SIZE (Pmode)))),
gen_rtx (LABEL_REF, Pmode, lab1));
#ifdef HAVE_save_stack_nonlocal
if (HAVE_save_stack_nonlocal)
sa_mode = insn_operand_mode[(int) CODE_FOR_save_stack_nonlocal][0];
#endif
stack_save = gen_rtx (MEM, sa_mode,
plus_constant (buf_addr,
2 * GET_MODE_SIZE (Pmode)));
emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
#ifdef HAVE_setjmp
if (HAVE_setjmp)
emit_insn (gen_setjmp ());
#endif
/* Set TARGET to zero and branch around the other case. */
emit_move_insn (target, const0_rtx);
emit_jump_insn (gen_jump (lab2));
emit_barrier ();
emit_label (lab1);
/* Note that setjmp clobbers FP when we get here, so we have to
make sure it's marked as used by this function. */
emit_insn (gen_rtx (USE, VOIDmode, hard_frame_pointer_rtx));
/* Mark the static chain as clobbered here so life information
doesn't get messed up for it. */
emit_insn (gen_rtx (CLOBBER, VOIDmode, static_chain_rtx));
/* Now put in the code to restore the frame pointer, and argument
pointer, if needed. The code below is from expand_end_bindings
in stmt.c; see detailed documentation there. */
#ifdef HAVE_nonlocal_goto
if (! HAVE_nonlocal_goto)
#endif
emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
current_function_has_nonlocal_goto = 1;
#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
if (fixed_regs[ARG_POINTER_REGNUM])
{
#ifdef ELIMINABLE_REGS
static struct elims {int from, to;} elim_regs[] = ELIMINABLE_REGS;
for (i = 0; i < sizeof elim_regs / sizeof elim_regs[0]; i++)
if (elim_regs[i].from == ARG_POINTER_REGNUM
&& elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
break;
if (i == sizeof elim_regs / sizeof elim_regs [0])
#endif
{
/* Now restore our arg pointer from the address at which it
was saved in our stack frame.
If there hasn't be space allocated for it yet, make
some now. */
if (arg_pointer_save_area == 0)
arg_pointer_save_area
= assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
emit_move_insn (virtual_incoming_args_rtx,
copy_to_reg (arg_pointer_save_area));
}
}
#endif
#ifdef HAVE_nonlocal_goto_receiver
if (HAVE_nonlocal_goto_receiver)
emit_insn (gen_nonlocal_goto_receiver ());
#endif
/* The static chain pointer contains the address of dummy function.
We need to call it here to handle some PIC cases of restoring
a global pointer. Then return 1. */
op0 = copy_to_mode_reg (Pmode, static_chain_rtx);
/* We can't actually call emit_library_call here, so do everything
it does, which isn't much for a libfunc with no args. */
op0 = memory_address (FUNCTION_MODE, op0);
INIT_CUMULATIVE_ARGS (args_so_far, NULL_TREE,
gen_rtx (SYMBOL_REF, Pmode, "__dummy"), 1);
next_arg_reg = FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1);
#ifndef ACCUMULATE_OUTGOING_ARGS
#ifdef HAVE_call_pop
if (HAVE_call_pop)
emit_call_insn (gen_call_pop (gen_rtx (MEM, FUNCTION_MODE, op0),
const0_rtx, next_arg_reg,
GEN_INT (return_pops)));
else
#endif
#endif
#ifdef HAVE_call
if (HAVE_call)
emit_call_insn (gen_call (gen_rtx (MEM, FUNCTION_MODE, op0),
const0_rtx, next_arg_reg, const0_rtx));
else
#endif
abort ();
emit_move_insn (target, const1_rtx);
emit_label (lab2);
return target;
return expand_builtin_setjmp (buf_addr, target);
}
/* __builtin_longjmp is passed a pointer to an array of five words

View File

@ -685,6 +685,8 @@ extern rtx store_expr PROTO((tree, rtx, int));
Useful after calling expand_expr with 1 as sum_ok. */
extern rtx force_operand PROTO((rtx, rtx));
extern rtx expand_builtin_setjmp PROTO((rtx, rtx));
#ifdef TREE_CODE
/* Generate code for computing expression EXP.
An rtx for the computed value is returned. The value is never null.

View File

@ -3120,7 +3120,7 @@ __terminate ()
is raised when using the setjmp/longjmp exception handling codegen
method. */
extern longjmp (void *, int);
extern void longjmp (void *, int);
extern void *__eh_type;
@ -3169,7 +3169,11 @@ __sjthrow ()
buf[0] = (*dhc);
/* try { */
#ifdef DONT_USE_BUILTIN_SETJMP
if (! setjmp (&buf[2]))
#else
if (! __builtin_setjmp (&buf[2]))
#endif
{
*dhc = buf;
while (cleanup[0])
@ -3206,10 +3210,10 @@ __sjthrow ()
/* And then we jump to the handler. */
#ifdef USE_BUILTIN_SETJMP
__builtin_longjmp (jmpbuf, 1);
#else
#ifdef DONT_USE_BUILTIN_SETJMP
longjmp (jmpbuf, 1);
#else
__builtin_longjmp (jmpbuf, 1);
#endif
}
@ -3240,7 +3244,11 @@ __sjpopnthrow ()
buf[0] = (*dhc);
/* try { */
#ifdef DONT_USE_BUILTIN_SETJMP
if (! setjmp (&buf[2]))
#else
if (! __builtin_setjmp (&buf[2]))
#endif
{
*dhc = buf;
while (cleanup[0])

View File

@ -4277,7 +4277,7 @@ init_optabs ()
sjthrow_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__sjthrow");
sjpopnthrow_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__sjpopnthrow");
terminate_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__terminate");
#ifdef USE_BUILTIN_SETJMP
#ifndef DONT_USE_BUILTIN_SETJMP
setjmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__builtin_setjmp");
longjmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__builtin_longjmp");
#else