summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog27
-rw-r--r--gcc/config/alpha/alpha.md47
-rw-r--r--gcc/config/mips/mips.md73
-rw-r--r--gcc/config/sparc/sparc.md44
-rw-r--r--gcc/except.c15
-rw-r--r--gcc/expr.c248
-rw-r--r--gcc/expr.h2
7 files changed, 265 insertions, 191 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f54e31ee091..3c23a831467 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,30 @@
+Mon Feb 2 19:18:14 1998 Richard Henderson <rth@cygnus.com>
+
+ * expr.c (expand_builtin_setjmp): Accept two new arguments for
+ the labels to branch to on first and subsequent executions. Don't
+ play with __dummy. Rename `setjmp' insn to `builtin_setjmp_setup',
+ and provide it with the jmp_buf. Use only one of
+ `builtin_setjmp_receiver' or `nonlocal_goto_receiver',
+ and provide the former with the target label.
+ (expand_builtin) [BUILTIN_SETJMP]: Generate a label for use by setjmp.
+ (expand_builtin) [BUILTIN_LONGJMP]: Split out to ...
+ (expand_builtin_longjmp): ... here. Recognize a `builtin_longjmp'
+ insn to replace all of the normal nonlocal_goto code. Don't play
+ with __dummy. Correct arguments to nonlocal_goto.
+ * expr.h (expand_builtin_setjmp): Update prototype.
+ * except.c (start_dynamic_handler): When using builtin_setjmp,
+ generate more accurate flow information.
+
+ * alpha.md (nonlocal_goto_receiver_osf): Delete.
+ (nonlocal_goto_receiver_vms): Rename to nonlocal_goto_receiver.
+ (builtin_longjmp, builtin_setjmp_receiver): New.
+ * sparc.md (update_return): Disambiguate unspec number.
+ (nonlocal_goto): Rearrange arguments to match caller in except.c.
+ (builtin_setjmp_setup): Rename from setjmp. Match and ignore the
+ jmp_buf operand.
+ * mips.md (nonlocal_goto_receiver, builtin_setjmp_receiver): Remove.
+ (builtin_setjmp_setup*, builtin_longjmp): New.
+
Mon Feb 2 16:43:10 1998 John Carr <jfc@mit.edu>
* mips.md: Change gen_rtx (CONST_INT) to GEN_INT.
diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md
index 44f9cb95876..b1cbc3bcbfd 100644
--- a/gcc/config/alpha/alpha.md
+++ b/gcc/config/alpha/alpha.md
@@ -5050,15 +5050,36 @@
}
}")
-;; Ideally we should be able to define nonlocal_goto and arrange
-;; for the pc to be in a known place. Or perhaps branch back via
-;; br instead of jmp.
-(define_insn "nonlocal_goto_receiver_osf"
- [(unspec_volatile [(const_int 0)] 2)]
+(define_expand "builtin_longjmp"
+ [(unspec_volatile [(match_operand 0 "register_operand" "r")] 3)]
"! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT"
- "br $29,$LGOTO%=\\n$LGOTO%=:\;ldgp $29,0($29)")
+ "
+{
+ /* The elements of the buffer are, in order: */
+ rtx fp = gen_rtx_MEM (Pmode, operands[0]);
+ rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], 8));
+ rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 16));
+ rtx pv = gen_rtx_REG (Pmode, 27);
+
+ /* This bit is the same as expand_builtin_longjmp. */
+ emit_move_insn (hard_frame_pointer_rtx, fp);
+ emit_move_insn (pv, lab);
+ emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
+ emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
+ emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
+
+ /* Load the label we are jumping through into $27 so that we know
+ where to look for it when we get back to setjmp's function for
+ restoring the gp. */
+ emit_indirect_jump (pv);
+}")
-(define_expand "nonlocal_goto_receiver_vms"
+(define_insn "builtin_setjmp_receiver"
+ [(unspec_volatile [(match_operand 0 "" "")] 2)]
+ "! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT"
+ "\\n$LSJ%=:\;ldgp $29,$LSJ%=-%l0($27)")
+
+(define_expand "nonlocal_goto_receiver"
[(unspec_volatile [(const_int 0)] 1)
(set (reg:DI 27) (mem:DI (reg:DI 29)))
(unspec_volatile [(const_int 0)] 1)
@@ -5066,18 +5087,6 @@
"TARGET_OPEN_VMS"
"")
-(define_expand "nonlocal_goto_receiver"
- [(unspec_volatile [(const_int 0)] 2)]
- ""
- "
-{
- if (TARGET_OPEN_VMS)
- emit_insn(gen_nonlocal_goto_receiver_vms ());
- else if (!TARGET_WINDOWS_NT)
- emit_insn(gen_nonlocal_goto_receiver_osf ());
- DONE;
-}")
-
(define_insn "arg_home"
[(unspec [(const_int 0)] 0)
(use (reg:DI 1))
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index eaf80efacb9..10c0bfe261b 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -8820,35 +8820,64 @@ move\\t%0,%z4\\n\\
(set_attr "mode" "none")
(set_attr "length" "6")])
-;; ??? This is a hack to work around a problem with expand_builtin_setjmp.
-;; It restores the frame pointer, and then does a call to restore the global
-;; pointer (gp) register. The call insn implicitly (via the assembler) reloads
-;; gp from the stack. However, call insns do not depend on $fp, so it is
-;; possible for the instruction scheduler to move the fp restore after the
-;; call, which then causes gp to be corrupted. We fix this by emitting a
-;; scheduler barrier. A better fix is to put code here that restores the
-;; $gp, and then the call is unnecessary. This is only a problem when PIC
-;; (TARGET_ABICALLS), and only when the gp register is caller-saved
-;; (irix5/o32, but not irix6/n32/n64).
-
-(define_expand "nonlocal_goto_receiver"
- [(const_int 0)]
- ""
+;; For o32/n32/n64, we save the gp in the jmp_buf as well. While it is
+;; possible to either pull it off the stack (in the o32 case) or recalculate
+;; it given t9 and our target label, it takes 3 or 4 insns to do so, and
+;; this is easy.
+
+(define_expand "builtin_setjmp_setup"
+ [(unspec [(match_operand 0 "register_operand" "r")] 20)]
+ "TARGET_ABICALLS"
"
{
- emit_insn (gen_blockage ());
+ if (TARGET_LONG64)
+ emit_insn (gen_builtin_setjmp_setup_64 (operands[0]));
+ else
+ emit_insn (gen_builtin_setjmp_setup_32 (operands[0]));
+ DONE;
}")
-;; For n32/n64, we need to restore gp after a builtin setjmp. We do this
-;; by making use of the fact that we've just called __dummy.
+(define_expand "builtin_setjmp_setup_32"
+ [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int 12)))
+ (reg:SI 28))]
+ "TARGET_ABICALLS && ! TARGET_LONG64"
+ "")
-(define_expand "builtin_setjmp_receiver"
- [(const_int 0)]
- "TARGET_ABICALLS && mips_abi != ABI_32"
+(define_expand "builtin_setjmp_setup_64"
+ [(set (mem:DI (plus:DI (match_operand:DI 0 "register_operand" "r")
+ (const_int 24)))
+ (reg:DI 28))]
+ "TARGET_ABICALLS && TARGET_LONG64"
+ "")
+
+;; For o32/n32/n64, we need to arrange for longjmp to put the
+;; target address in t9 so that we can use it for loading $gp.
+
+(define_expand "builtin_longjmp"
+ [(unspec_volatile [(match_operand 0 "register_operand" "r")] 3)]
+ "TARGET_ABICALLS"
"
{
- emit_insn (gen_loadgp (gen_rtx (SYMBOL_REF, Pmode, \"__dummy\")));
- emit_insn (gen_blockage ());
+ /* The elements of the buffer are, in order: */
+ int W = (TARGET_LONG64 ? 8 : 4);
+ rtx fp = gen_rtx_MEM (Pmode, operands[0]);
+ rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], 1*W));
+ rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 2*W));
+ rtx gpv = gen_rtx_MEM (Pmode, plus_constant (operands[0], 3*W));
+ rtx pv = gen_rtx_REG (Pmode, 25);
+ rtx gp = gen_rtx_REG (Pmode, 28);
+
+ /* This bit is the same as expand_builtin_longjmp. */
+ emit_move_insn (hard_frame_pointer_rtx, fp);
+ emit_move_insn (pv, lab);
+ emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
+ emit_move_insn (gp, gpv);
+ emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
+ emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
+ emit_insn (gen_rtx_USE (VOIDmode, gp));
+ emit_indirect_jump (pv);
+ DONE;
}")
;;
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 0cd564baa34..cf3c6c524f9 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -5640,7 +5640,7 @@
(define_insn "update_return"
[(unspec:SI [(match_operand:SI 0 "register_operand" "r")
- (match_operand:SI 1 "register_operand" "r")] 0)]
+ (match_operand:SI 1 "register_operand" "r")] 1)]
"! TARGET_ARCH64"
"cmp %1,0\;be,a .+8\;add %0,4,%0"
[(set_attr "type" "multi")])
@@ -5676,32 +5676,40 @@
;; ??? Doesn't work with -mflat.
(define_expand "nonlocal_goto"
- [(match_operand:SI 0 "general_operand" "")
+ [(match_operand:SI 0 "" "")
(match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_operand" "")
- (match_operand:SI 3 "" "")]
+ (match_operand:SI 3 "general_operand" "")]
""
"
{
+ rtx chain = operands[0];
+ rtx fp = operands[1];
+ rtx stack = operands[2];
+ rtx lab = operands[3];
+
/* Trap instruction to flush all the register windows. */
emit_insn (gen_flush_register_windows ());
- /* Load the fp value for the containing fn into %fp.
- This is needed because operands[2] refers to %fp.
- Virtual register instantiation fails if the virtual %fp isn't set from a
- register. Thus we must copy operands[0] into a register if it isn't
- already one. */
- if (GET_CODE (operands[0]) != REG)
- operands[0] = force_reg (Pmode, operands[0]);
- emit_move_insn (virtual_stack_vars_rtx, operands[0]);
+
+ /* Load the fp value for the containing fn into %fp. This is needed
+ because STACK refers to %fp. Note that virtual register instantiation
+ fails if the virtual %fp isn't set from a register. */
+ if (GET_CODE (fp) != REG)
+ fp = force_reg (Pmode, fp);
+ emit_move_insn (virtual_stack_vars_rtx, fp);
+
/* Find the containing function's current nonlocal goto handler,
which will do any cleanups and then jump to the label. */
- emit_move_insn (gen_rtx (REG, Pmode, 8), operands[1]);
+ emit_move_insn (gen_rtx (REG, Pmode, 8), lab);
+
/* Restore %fp from stack pointer value for containing function.
The restore insn that follows will move this to %sp,
and reload the appropriate value into %fp. */
- emit_move_insn (frame_pointer_rtx, operands[2]);
+ emit_move_insn (frame_pointer_rtx, stack);
+
/* Put in the static chain register the nonlocal label address. */
- emit_move_insn (static_chain_rtx, operands[3]);
+ emit_move_insn (static_chain_rtx, chain);
+
/* USE of frame_pointer_rtx added for consistency; not clear if
really needed. */
emit_insn (gen_rtx (USE, VOIDmode, frame_pointer_rtx));
@@ -5729,11 +5737,10 @@
[(set_attr "type" "misc")
(set_attr "length" "2")])
-;; Pattern for use after a setjmp to store FP and the return register
-;; into the stack area.
+;; Implement setjmp. Step one, set up the buffer.
-(define_expand "setjmp"
- [(const_int 0)]
+(define_expand "builtin_setjmp_setup"
+ [(unspec [(match_operand 0 "" "")] 3)]
""
"
{
@@ -5741,7 +5748,6 @@
emit_insn (gen_setjmp_64 ());
else
emit_insn (gen_setjmp_32 ());
-
DONE;
}")
diff --git a/gcc/except.c b/gcc/except.c
index fce1b723806..12abb103d65 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -945,15 +945,18 @@ start_dynamic_handler ()
#ifdef DONT_USE_BUILTIN_SETJMP
x = emit_library_call_value (setjmp_libfunc, NULL_RTX, 1, SImode, 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
- x = expand_builtin_setjmp (buf, NULL_RTX);
+ {
+ /* 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);
+ }
#endif
- /* If we come back here for a catch, transfer control to the
- handler. */
-
- jumpif_rtx (x, ehstack.top->entry->exception_handler_label);
-
/* We are committed to this, so update the handler chain. */
emit_move_insn (dhc, XEXP (arg, 0));
diff --git a/gcc/expr.c b/gcc/expr.c
index af90d2447b6..4d927d73052 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -7613,20 +7613,16 @@ expand_builtin_return_addr (fndecl_code, count, tem)
them. */
rtx
-expand_builtin_setjmp (buf_addr, target)
+expand_builtin_setjmp (buf_addr, target, first_label, next_label)
rtx buf_addr;
rtx target;
+ rtx first_label, next_label;
{
- rtx lab1 = gen_label_rtx (), lab2 = gen_label_rtx ();
+ rtx lab1 = 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;
@@ -7649,11 +7645,11 @@ expand_builtin_setjmp (buf_addr, target)
machine-dependent. */
emit_move_insn (gen_rtx_MEM (Pmode, buf_addr),
virtual_stack_vars_rtx);
- emit_move_insn
- (validize_mem (gen_rtx_MEM (Pmode,
+ emit_move_insn (validize_mem
+ (gen_rtx_MEM (Pmode,
plus_constant (buf_addr,
GET_MODE_SIZE (Pmode)))),
- gen_rtx_LABEL_REF (Pmode, lab1));
+ gen_rtx_LABEL_REF (Pmode, lab1));
#ifdef HAVE_save_stack_nonlocal
if (HAVE_save_stack_nonlocal)
@@ -7665,19 +7661,23 @@ expand_builtin_setjmp (buf_addr, target)
2 * GET_MODE_SIZE (Pmode)));
emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
-#ifdef HAVE_setjmp
- if (HAVE_setjmp)
- emit_insn (gen_setjmp ());
+ /* If there is further processing to do, do it. */
+#ifdef HAVE_builtin_setjmp_setup
+ if (HAVE_builtin_setjmp_setup)
+ emit_insn (gen_builtin_setjmp_setup (buf_addr));
#endif
- /* Set TARGET to zero and branch around the other case. */
+ /* Set TARGET to zero and branch to the first-time-through label. */
emit_move_insn (target, const0_rtx);
- emit_jump_insn (gen_jump (lab2));
+ emit_jump_insn (gen_jump (first_label));
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. */
+ /* Tell flow about the strange goings on. */
+ current_function_has_nonlocal_label = 1;
+
+ /* 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));
/* Mark the static chain as clobbered here so life information
@@ -7692,8 +7692,6 @@ expand_builtin_setjmp (buf_addr, target)
#endif
emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
- current_function_has_nonlocal_label = 1;
-
#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
if (fixed_regs[ARG_POINTER_REGNUM])
{
@@ -7721,49 +7719,107 @@ expand_builtin_setjmp (buf_addr, target)
}
#endif
+#ifdef HAVE_builtin_setjmp_receiver
+ if (HAVE_builtin_setjmp_receiver)
+ emit_insn (gen_builtin_setjmp_receiver (lab1));
+ else
+#endif
#ifdef HAVE_nonlocal_goto_receiver
- if (HAVE_nonlocal_goto_receiver)
- emit_insn (gen_nonlocal_goto_receiver ());
+ if (HAVE_nonlocal_goto_receiver)
+ emit_insn (gen_nonlocal_goto_receiver ());
+ else
#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);
+ ; /* Nothing */
+
+ /* Set TARGET, and branch to the next-time-through label. */
+ emit_move_insn (target, gen_lowpart (GET_MODE (target), static_chain_rtx));
+ emit_jump_insn (gen_jump (next_label));
+ emit_barrier ();
- /* 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);
+ return target;
+}
- 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);
+void
+expand_builtin_longjmp (buf_addr, value)
+ rtx buf_addr, value;
+{
+ rtx fp, lab, stack;
+ enum machine_mode sa_mode;
-#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
+#ifdef POINTERS_EXTEND_UNSIGNED
+ buf_addr = convert_memory_address (Pmode, buf_addr);
#endif
+ buf_addr = force_reg (Pmode, buf_addr);
+
+ /* The value sent by longjmp is not allowed to be zero. Force it
+ to one if so. */
+ if (GET_CODE (value) == CONST_INT)
+ {
+ if (INTVAL (value) == 0)
+ value = const1_rtx;
+ }
+ else
+ {
+ lab = gen_label_rtx ();
+
+ emit_cmp_insn (value, const0_rtx, NE, NULL_RTX, GET_MODE (value), 0, 0);
+ emit_jump_insn (gen_bne (lab));
+ emit_move_insn (value, const1_rtx);
+ emit_label (lab);
+ }
+
+ /* Make sure the value is in the right mode to be copied to the chain. */
+ if (GET_MODE (value) != VOIDmode)
+ value = gen_lowpart (GET_MODE (static_chain_rtx), value);
+
+#ifdef HAVE_builtin_longjmp
+ if (HAVE_builtin_longjmp)
+ {
+ /* Copy the "return value" to the static chain reg. */
+ emit_move_insn (static_chain_rtx, value);
+ emit_insn (gen_rtx_USE (VOIDmode, static_chain_rtx));
+ emit_insn (gen_builtin_longjmp (buf_addr));
+ }
+ else
#endif
+ {
+ fp = gen_rtx_MEM (Pmode, buf_addr);
+ lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr,
+ GET_MODE_SIZE (Pmode)));
-#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
+#ifdef HAVE_save_stack_nonlocal
+ sa_mode = (HAVE_save_stack_nonlocal
+ ? insn_operand_mode[(int) CODE_FOR_save_stack_nonlocal][0]
+ : Pmode);
+#else
+ sa_mode = Pmode;
#endif
- abort ();
-#ifdef HAVE_builtin_setjmp_receiver
- if (HAVE_builtin_setjmp_receiver)
- emit_insn (gen_builtin_setjmp_receiver ());
+ stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
+ 2 * GET_MODE_SIZE (Pmode)));
+
+ /* Pick up FP, label, and SP from the block and jump. This code is
+ from expand_goto in stmt.c; see there for detailed comments. */
+#if HAVE_nonlocal_goto
+ if (HAVE_nonlocal_goto)
+ emit_insn (gen_nonlocal_goto (value, fp, stack, lab));
+ else
#endif
+ {
+ lab = copy_to_reg (lab);
- emit_move_insn (target, const1_rtx);
- emit_label (lab2);
- return target;
+ /* Copy the "return value" to the static chain reg. */
+ emit_move_insn (static_chain_rtx, value);
+
+ emit_move_insn (hard_frame_pointer_rtx, fp);
+ emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
+
+ emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
+ emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
+ emit_insn (gen_rtx_USE (VOIDmode, static_chain_rtx));
+ emit_indirect_jump (lab);
+ }
+ }
}
@@ -8676,89 +8732,33 @@ expand_builtin (exp, target, subtarget, mode, ignore)
if (arglist == 0
|| TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
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;
+ }
- {
- rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
- VOIDmode, 0);
- return expand_builtin_setjmp (buf_addr, target);
- }
-
- /* __builtin_longjmp is passed a pointer to an array of five words
- and a value, which is a dummy. It's similar to the C library longjmp
- function but works with __builtin_setjmp above. */
+ /* __builtin_longjmp is passed a pointer to an array of five words.
+ It's similar to the C library longjmp function but works with
+ __builtin_setjmp above. */
case BUILT_IN_LONGJMP:
if (arglist == 0 || TREE_CHAIN (arglist) == 0
|| TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
break;
-
- {
- tree dummy_id = get_identifier ("__dummy");
- tree dummy_type = build_function_type (void_type_node, NULL_TREE);
- tree dummy_decl = build_decl (FUNCTION_DECL, dummy_id, dummy_type);
-#ifdef POINTERS_EXTEND_UNSIGNED
- rtx buf_addr
- = force_reg (Pmode,
- convert_memory_address
- (Pmode,
- expand_expr (TREE_VALUE (arglist),
- NULL_RTX, VOIDmode, 0)));
-#else
- rtx buf_addr
- = force_reg (Pmode, expand_expr (TREE_VALUE (arglist),
- NULL_RTX,
- VOIDmode, 0));
-#endif
- rtx fp = gen_rtx_MEM (Pmode, buf_addr);
- rtx lab = gen_rtx_MEM (Pmode,
- plus_constant (buf_addr,
- GET_MODE_SIZE (Pmode)));
- enum machine_mode sa_mode
-#ifdef HAVE_save_stack_nonlocal
- = (HAVE_save_stack_nonlocal
- ? insn_operand_mode[(int) CODE_FOR_save_stack_nonlocal][0]
- : Pmode);
-#else
- = Pmode;
-#endif
- rtx stack = gen_rtx_MEM (sa_mode,
- plus_constant (buf_addr,
- 2 * GET_MODE_SIZE (Pmode)));
-
- DECL_EXTERNAL (dummy_decl) = 1;
- TREE_PUBLIC (dummy_decl) = 1;
- make_decl_rtl (dummy_decl, NULL_PTR, 1);
-
- /* Expand the second expression just for side-effects. */
- expand_expr (TREE_VALUE (TREE_CHAIN (arglist)),
- const0_rtx, VOIDmode, 0);
-
- assemble_external (dummy_decl);
-
- /* Pick up FP, label, and SP from the block and jump. This code is
- from expand_goto in stmt.c; see there for detailed comments. */
-#if HAVE_nonlocal_goto
- if (HAVE_nonlocal_goto)
- emit_insn (gen_nonlocal_goto (fp, lab, stack,
- XEXP (DECL_RTL (dummy_decl), 0)));
else
-#endif
{
- lab = copy_to_reg (lab);
- emit_move_insn (hard_frame_pointer_rtx, fp);
- emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
-
- /* Put in the static chain register the address of the dummy
- function. */
- emit_move_insn (static_chain_rtx, XEXP (DECL_RTL (dummy_decl), 0));
- emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
- emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
- emit_insn (gen_rtx_USE (VOIDmode, static_chain_rtx));
- emit_indirect_jump (lab);
+ rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
+ VOIDmode, 0);
+ rtx value = expand_expr (TREE_VALUE (TREE_CHAIN (arglist)),
+ const0_rtx, VOIDmode, 0);
+ expand_builtin_longjmp (buf_addr, value);
+ return const0_rtx;
}
- return const0_rtx;
- }
-
/* Various hooks for the DWARF 2 __throw routine. */
case BUILT_IN_UNWIND_INIT:
expand_builtin_unwind_init ();
diff --git a/gcc/expr.h b/gcc/expr.h
index e818d5ab398..080992f3dd9 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -752,7 +752,7 @@ 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));
+extern rtx expand_builtin_setjmp PROTO((rtx, rtx, rtx, rtx));
#ifdef TREE_CODE
/* Generate code for computing expression EXP.