expr.c (expand_builtin_setjmp): Accept two new arguments for the labels to branch...
authorRichard Henderson <rth@cygnus.com>
Mon, 2 Feb 1998 19:28:57 +0000 (11:28 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Mon, 2 Feb 1998 19:28:57 +0000 (11:28 -0800)
 * 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

gcc/ChangeLog
gcc/config/alpha/alpha.md
gcc/config/mips/mips.md
gcc/config/sparc/sparc.md
gcc/except.c
gcc/expr.c
gcc/expr.h

index f54e31ee091b8f2d92508456f74b19a6b280c234..3c23a831467a09a79190564f281e87d0c255fd11 100644 (file)
@@ -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.
index 44f9cb95876dfd4a7e57515df12c226a427af5b1..b1cbc3bcbfdb9047913089a10f847b2f3fabc3eb 100644 (file)
     }
 }")
 
-;; 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)
   "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))
index eaf80efacb95a3918613a0a08d49b325704716f4..10c0bfe261bf1365e5ca779ce3d2dae772cfbf6d 100644 (file)
@@ -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;
 }")
 \f
 ;;
index 0cd564baa347ac040a4f01ea6d7200a7c6fa9f04..cf3c6c524f9433233594bd632d5a0de03ac9e2bb 100644 (file)
 
 (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")])
 
 ;; ??? 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));
   [(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)]
   ""
   "
 {
     emit_insn (gen_setjmp_64 ());
   else
     emit_insn (gen_setjmp_32 ());
-
   DONE;
 }")
 
index fce1b7238066e396c084aa3eeab294caded4a33c..12abb103d659bfed1960aafaa0f2ae26223c1018 100644 (file)
@@ -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));
index af90d2447b67450152b0128e22535d970edeaccf..4d927d73052a1072234b1935079ea1de7a5e4196 100644 (file)
@@ -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);
+       }
+    }
 }
 
 \f
@@ -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 ();
index e818d5ab398c9088c15af4658d9318ee2b6648af..080992f3dd953b6bca5d3ff0d229ba4526443879 100644 (file)
@@ -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.