aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/except.c18
-rw-r--r--gcc/expr.c315
-rw-r--r--gcc/expr.h2
-rw-r--r--gcc/libgcc2.c16
-rw-r--r--gcc/optabs.c2
5 files changed, 190 insertions, 163 deletions
diff --git a/gcc/except.c b/gcc/except.c
index 71925a5..91afbc3 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -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. */
diff --git a/gcc/expr.c b/gcc/expr.c
index 1dc79b6..4e3c981 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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
diff --git a/gcc/expr.h b/gcc/expr.h
index ee954ef..bb957b7 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -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.
diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c
index 107c4bf..09b6a15 100644
--- a/gcc/libgcc2.c
+++ b/gcc/libgcc2.c
@@ -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])
diff --git a/gcc/optabs.c b/gcc/optabs.c
index b93a383..992660d 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -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