Commit 6fd1c67b by Richard Henderson Committed by Richard Henderson

expr.c (expand_builtin_setjmp): Accept two new arguments for the labels to…

expr.c (expand_builtin_setjmp): Accept two new arguments for the labels to branch to on first and subsequent...

 * 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.

From-SVN: r17602
parent 95936d18
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> Mon Feb 2 16:43:10 1998 John Carr <jfc@mit.edu>
* mips.md: Change gen_rtx (CONST_INT) to GEN_INT. * mips.md: Change gen_rtx (CONST_INT) to GEN_INT.
......
...@@ -5050,15 +5050,36 @@ ...@@ -5050,15 +5050,36 @@
} }
}") }")
;; Ideally we should be able to define nonlocal_goto and arrange (define_expand "builtin_longjmp"
;; for the pc to be in a known place. Or perhaps branch back via [(unspec_volatile [(match_operand 0 "register_operand" "r")] 3)]
;; br instead of jmp.
(define_insn "nonlocal_goto_receiver_osf"
[(unspec_volatile [(const_int 0)] 2)]
"! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT" "! 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) [(unspec_volatile [(const_int 0)] 1)
(set (reg:DI 27) (mem:DI (reg:DI 29))) (set (reg:DI 27) (mem:DI (reg:DI 29)))
(unspec_volatile [(const_int 0)] 1) (unspec_volatile [(const_int 0)] 1)
...@@ -5066,18 +5087,6 @@ ...@@ -5066,18 +5087,6 @@
"TARGET_OPEN_VMS" "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" (define_insn "arg_home"
[(unspec [(const_int 0)] 0) [(unspec [(const_int 0)] 0)
(use (reg:DI 1)) (use (reg:DI 1))
......
...@@ -8820,35 +8820,64 @@ move\\t%0,%z4\\n\\ ...@@ -8820,35 +8820,64 @@ move\\t%0,%z4\\n\\
(set_attr "mode" "none") (set_attr "mode" "none")
(set_attr "length" "6")]) (set_attr "length" "6")])
;; ??? This is a hack to work around a problem with expand_builtin_setjmp. ;; For o32/n32/n64, we save the gp in the jmp_buf as well. While it is
;; It restores the frame pointer, and then does a call to restore the global ;; possible to either pull it off the stack (in the o32 case) or recalculate
;; pointer (gp) register. The call insn implicitly (via the assembler) reloads ;; it given t9 and our target label, it takes 3 or 4 insns to do so, and
;; gp from the stack. However, call insns do not depend on $fp, so it is ;; this is easy.
;; 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 (define_expand "builtin_setjmp_setup"
;; scheduler barrier. A better fix is to put code here that restores the [(unspec [(match_operand 0 "register_operand" "r")] 20)]
;; $gp, and then the call is unnecessary. This is only a problem when PIC "TARGET_ABICALLS"
;; (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)]
""
" "
{ {
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 (define_expand "builtin_setjmp_setup_32"
;; by making use of the fact that we've just called __dummy. [(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" (define_expand "builtin_setjmp_setup_64"
[(const_int 0)] [(set (mem:DI (plus:DI (match_operand:DI 0 "register_operand" "r")
"TARGET_ABICALLS && mips_abi != ABI_32" (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\"))); /* The elements of the buffer are, in order: */
emit_insn (gen_blockage ()); 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;
}") }")
;; ;;
......
...@@ -5640,7 +5640,7 @@ ...@@ -5640,7 +5640,7 @@
(define_insn "update_return" (define_insn "update_return"
[(unspec:SI [(match_operand:SI 0 "register_operand" "r") [(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" "! TARGET_ARCH64"
"cmp %1,0\;be,a .+8\;add %0,4,%0" "cmp %1,0\;be,a .+8\;add %0,4,%0"
[(set_attr "type" "multi")]) [(set_attr "type" "multi")])
...@@ -5676,32 +5676,40 @@ ...@@ -5676,32 +5676,40 @@
;; ??? Doesn't work with -mflat. ;; ??? Doesn't work with -mflat.
(define_expand "nonlocal_goto" (define_expand "nonlocal_goto"
[(match_operand:SI 0 "general_operand" "") [(match_operand:SI 0 "" "")
(match_operand:SI 1 "general_operand" "") (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "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. */ /* Trap instruction to flush all the register windows. */
emit_insn (gen_flush_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. /* Load the fp value for the containing fn into %fp. This is needed
Virtual register instantiation fails if the virtual %fp isn't set from a because STACK refers to %fp. Note that virtual register instantiation
register. Thus we must copy operands[0] into a register if it isn't fails if the virtual %fp isn't set from a register. */
already one. */ if (GET_CODE (fp) != REG)
if (GET_CODE (operands[0]) != REG) fp = force_reg (Pmode, fp);
operands[0] = force_reg (Pmode, operands[0]); emit_move_insn (virtual_stack_vars_rtx, fp);
emit_move_insn (virtual_stack_vars_rtx, operands[0]);
/* Find the containing function's current nonlocal goto handler, /* Find the containing function's current nonlocal goto handler,
which will do any cleanups and then jump to the label. */ 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. /* Restore %fp from stack pointer value for containing function.
The restore insn that follows will move this to %sp, The restore insn that follows will move this to %sp,
and reload the appropriate value into %fp. */ 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. */ /* 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 /* USE of frame_pointer_rtx added for consistency; not clear if
really needed. */ really needed. */
emit_insn (gen_rtx (USE, VOIDmode, frame_pointer_rtx)); emit_insn (gen_rtx (USE, VOIDmode, frame_pointer_rtx));
...@@ -5729,11 +5737,10 @@ ...@@ -5729,11 +5737,10 @@
[(set_attr "type" "misc") [(set_attr "type" "misc")
(set_attr "length" "2")]) (set_attr "length" "2")])
;; Pattern for use after a setjmp to store FP and the return register ;; Implement setjmp. Step one, set up the buffer.
;; into the stack area.
(define_expand "setjmp" (define_expand "builtin_setjmp_setup"
[(const_int 0)] [(unspec [(match_operand 0 "" "")] 3)]
"" ""
" "
{ {
...@@ -5741,7 +5748,6 @@ ...@@ -5741,7 +5748,6 @@
emit_insn (gen_setjmp_64 ()); emit_insn (gen_setjmp_64 ());
else else
emit_insn (gen_setjmp_32 ()); emit_insn (gen_setjmp_32 ());
DONE; DONE;
}") }")
......
...@@ -945,15 +945,18 @@ start_dynamic_handler () ...@@ -945,15 +945,18 @@ start_dynamic_handler ()
#ifdef DONT_USE_BUILTIN_SETJMP #ifdef DONT_USE_BUILTIN_SETJMP
x = emit_library_call_value (setjmp_libfunc, NULL_RTX, 1, SImode, 1, x = emit_library_call_value (setjmp_libfunc, NULL_RTX, 1, SImode, 1,
buf, Pmode); 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 #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 #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. */ /* We are committed to this, so update the handler chain. */
emit_move_insn (dhc, XEXP (arg, 0)); emit_move_insn (dhc, XEXP (arg, 0));
......
...@@ -752,7 +752,7 @@ extern rtx store_expr PROTO((tree, rtx, int)); ...@@ -752,7 +752,7 @@ extern rtx store_expr PROTO((tree, rtx, int));
Useful after calling expand_expr with 1 as sum_ok. */ Useful after calling expand_expr with 1 as sum_ok. */
extern rtx force_operand PROTO((rtx, rtx)); 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 #ifdef TREE_CODE
/* Generate code for computing expression EXP. /* Generate code for computing expression EXP.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment