[taken from gcc-2.95.3-latest-cvs]

Bring back the sjlj eh fixes.
	* expr.c (expand_builtin_setjmp_setup): New.
	(expand_builtin_setjmp_receiver): New.
	(expand_builtin_setjmp): Split out _setup and _receiver functions.
	Move argument parsing in from ...
	(expand_builtin): ... here.
	* except.c (receive_exception_label): Branch around receiver
	unless new-style exceptions.  Call expand_builtin_setjmp_receiver.
	(start_dynamic_handler): Call expand_builtin_setjmp_setup.
	* expr.h: Update builtin setjmp decls.


git-svn-id: file:///srv/svn/repos/haiku/trunk/buildtools@9589 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Oliver Tappe 2004-10-28 18:21:33 +00:00
parent cf64b0106b
commit 8d8ec347b1
3 changed files with 130 additions and 67 deletions

View File

@ -723,21 +723,41 @@ static void
receive_exception_label (handler_label)
rtx handler_label;
{
rtx around_label = NULL_RTX;
if (! flag_new_exceptions || exceptions_via_longjmp)
{
around_label = gen_label_rtx ();
emit_jump (around_label);
emit_barrier ();
}
emit_label (handler_label);
#ifdef HAVE_exception_receiver
if (! exceptions_via_longjmp)
{
#ifdef HAVE_exception_receiver
if (HAVE_exception_receiver)
emit_insn (gen_exception_receiver ());
else
#endif
#ifdef HAVE_nonlocal_goto_receiver
if (! exceptions_via_longjmp)
if (HAVE_nonlocal_goto_receiver)
emit_insn (gen_nonlocal_goto_receiver ());
else
#endif
{ /* Nothing */ }
}
else
{
#ifndef DONT_USE_BUILTIN_SETJMP
expand_builtin_setjmp_receiver (handler_label);
#endif
}
if (around_label)
emit_label (around_label);
}
struct func_eh_entry
{
@ -1320,7 +1340,7 @@ static void
start_dynamic_handler ()
{
rtx dhc, dcc;
rtx x, arg, buf;
rtx arg, buf;
int size;
#ifndef DONT_USE_BUILTIN_SETJMP
@ -1362,18 +1382,17 @@ start_dynamic_handler ()
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,
{
rtx x;
x = emit_library_call_value (setjmp_libfunc, NULL_RTX, LCT_CONST,
TYPE_MODE (integer_type_node), 1,
buf, Pmode);
/* If we come back here for a catch, transfer control to the handler. */
jumpif_rtx (x, ehstack.top->entry->exception_handler_label);
#else
{
/* A label to continue execution for the no exception case. */
rtx noex = gen_label_rtx();
x = expand_builtin_setjmp (buf, NULL_RTX, noex,
ehstack.top->entry->exception_handler_label);
emit_label (noex);
}
#else
expand_builtin_setjmp_setup (buf,
ehstack.top->entry->exception_handler_label);
#endif
/* We are committed to this, so update the handler chain. */

View File

@ -192,6 +192,7 @@ static rtx expand_builtin PROTO((tree, rtx, rtx,
static int apply_args_size PROTO((void));
static int apply_result_size PROTO((void));
static rtx result_vector PROTO((int, rtx));
static rtx expand_builtin_setjmp PROTO((tree, rtx));
static rtx expand_builtin_apply_args PROTO((void));
static rtx expand_builtin_apply PROTO((rtx, rtx, rtx));
static void expand_builtin_return PROTO((rtx));
@ -449,6 +450,9 @@ protect_from_queue (x, modify)
QUEUED_INSN (y));
return temp;
}
/* Copy the address into a pseudo, so that the returned value
remains correct across calls to emit_queue. */
XEXP (new, 0) = copy_to_reg (XEXP (new, 0));
return new;
}
/* Otherwise, recursively protect the subexpressions of all
@ -475,9 +479,11 @@ protect_from_queue (x, modify)
}
return x;
}
/* If the increment has not happened, use the variable itself. */
/* If the increment has not happened, use the variable itself. Copy it
into a new pseudo so that the value remains correct across calls to
emit_queue. */
if (QUEUED_INSN (x) == 0)
return QUEUED_VAR (x);
return copy_to_reg (QUEUED_VAR (x));
/* If the increment has happened and a pre-increment copy exists,
use that copy. */
if (QUEUED_COPY (x) != 0)
@ -8076,7 +8082,9 @@ expand_expr (exp, target, tmode, modifier)
if (ignore)
return op0;
op0 = protect_from_queue (op0, 0);
/* Pass 1 for MODIFY, so that protect_from_queue doesn't get
clever and returns a REG when given a MEM. */
op0 = protect_from_queue (op0, 1);
/* We would like the object in memory. If it is a constant,
we can have it be statically allocated into memory. For
@ -8544,44 +8552,29 @@ expand_builtin_return_addr (fndecl_code, count, tem)
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.
/* Construct the leading half of a __builtin_setjmp call. Control will
return to RECEIVER_LABEL. This is used directly by sjlj exception
handling code. */
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, first_label, next_label)
void
expand_builtin_setjmp_setup (buf_addr, receiver_label)
rtx buf_addr;
rtx target;
rtx first_label, next_label;
rtx receiver_label;
{
rtx lab1 = gen_label_rtx ();
enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
enum machine_mode value_mode;
rtx stack_save;
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 ();
/* 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. */
/* We store the frame pointer and the address of receiver_label in
the buffer and use the rest of it for the stack save area, which
is machine-dependent. */
#ifndef BUILTIN_SETJMP_FRAME_VALUE
#define BUILTIN_SETJMP_FRAME_VALUE virtual_stack_vars_rtx
@ -8593,7 +8586,7 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label)
(gen_rtx_MEM (Pmode,
plus_constant (buf_addr,
GET_MODE_SIZE (Pmode)))),
force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, lab1)));
force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
stack_save = gen_rtx_MEM (sa_mode,
plus_constant (buf_addr,
@ -8606,20 +8599,22 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label)
emit_insn (gen_builtin_setjmp_setup (buf_addr));
#endif
/* Set TARGET to zero and branch to the first-time-through label. */
emit_move_insn (target, const0_rtx);
emit_jump_insn (gen_jump (first_label));
emit_barrier ();
emit_label (lab1);
/* Tell flow about the strange goings on. Putting `lab1' on
`nonlocal_goto_handler_labels' to indicates that function
calls may traverse the arc back to this label. */
/* Tell optimize_save_area_alloca that extra work is going to
need to go on during alloca. */
current_function_calls_setjmp = 1;
/* Set this so all the registers get saved in our frame; we need to be
able to copy the saved values for any registers from frames we unwind. */
current_function_has_nonlocal_label = 1;
nonlocal_goto_handler_labels =
gen_rtx_EXPR_LIST (VOIDmode, lab1, nonlocal_goto_handler_labels);
}
/* Construct the trailing part of a __builtin_setjmp call.
This is used directly by sjlj exception handling code. */
void
expand_builtin_setjmp_receiver (receiver_label)
rtx receiver_label ATTRIBUTE_UNUSED;
{
/* Clobber the 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));
@ -8666,7 +8661,7 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label)
#ifdef HAVE_builtin_setjmp_receiver
if (HAVE_builtin_setjmp_receiver)
emit_insn (gen_builtin_setjmp_receiver (lab1));
emit_insn (gen_builtin_setjmp_receiver (receiver_label));
else
#endif
#ifdef HAVE_nonlocal_goto_receiver
@ -8678,10 +8673,66 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label)
; /* Nothing */
}
/* Set TARGET, and branch to the next-time-through label. */
emit_move_insn (target, const1_rtx);
emit_jump_insn (gen_jump (next_label));
/* @@@ This is a kludge. Not all machine descriptions define a blockage
insn, but we must not allow the code we just generated to be reordered
by scheduling. Specifically, the update of the frame pointer must
happen immediately, not later. So emit an ASM_INPUT to act as blockage
insn. */
emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
}
/* __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. */
static rtx
expand_builtin_setjmp (arglist, target)
tree arglist;
rtx target;
{
rtx buf_addr, next_lab, cont_lab;
if (arglist == 0
|| TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
return NULL_RTX;
if (target == 0 || GET_CODE (target) != REG
|| REGNO (target) < FIRST_PSEUDO_REGISTER)
target = gen_reg_rtx (TYPE_MODE (integer_type_node));
buf_addr = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
next_lab = gen_label_rtx ();
cont_lab = gen_label_rtx ();
expand_builtin_setjmp_setup (buf_addr, next_lab);
/* Set TARGET to zero and branch to the continue label. */
emit_move_insn (target, const0_rtx);
emit_jump_insn (gen_jump (cont_lab));
emit_barrier ();
emit_label (next_lab);
expand_builtin_setjmp_receiver (next_lab);
/* Set TARGET to one. */
emit_move_insn (target, const1_rtx);
emit_label (cont_lab);
/* Tell flow about the strange goings on. Putting `next_lab' on
`nonlocal_goto_handler_labels' to indicates that function
calls may traverse the arc back to this label. */
current_function_has_nonlocal_label = 1;
nonlocal_goto_handler_labels
= gen_rtx_EXPR_LIST (VOIDmode, next_lab, nonlocal_goto_handler_labels);
return target;
}
@ -9703,18 +9754,10 @@ expand_builtin (exp, target, subtarget, mode, ignore)
#endif
case BUILT_IN_SETJMP:
if (arglist == 0
|| TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
target = expand_builtin_setjmp (arglist, target);
if (target)
return target;
break;
else
{
rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
VOIDmode, 0);
rtx lab = gen_label_rtx ();
rtx ret = expand_builtin_setjmp (buf_addr, target, lab, lab);
emit_label (lab);
return ret;
}
/* __builtin_longjmp is passed a pointer to an array of five words.
It's similar to the C library longjmp function but works with

View File

@ -831,7 +831,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, rtx, rtx));
extern void expand_builtin_setjmp_setup PARAMS ((rtx, rtx));
extern void expand_builtin_setjmp_receiver PARAMS ((rtx));
#ifdef TREE_CODE
/* Generate code for computing expression EXP.