except.c (start_dynamic_handler): Fix so that we can use __builtin_setjmp...
authorMike Stump <mrs@gcc.gnu.org>
Wed, 7 May 1997 22:50:11 +0000 (22:50 +0000)
committerMike Stump <mrs@gcc.gnu.org>
Wed, 7 May 1997 22:50:11 +0000 (22:50 +0000)
* except.c (start_dynamic_handler): Fix so that we can use
  __builtin_setjmp, and default to using __builtin_setjmp instead of
  setjmp.
* expr.c (expand_builtin_setjmp): New routine, split out from
existing inline code from expand_builtin.
(expand_builtin): Split out code into expand_builtin_setjmp.
* expr.h (expand_builtin_setjmp): Add declaration.
* libgcc2.c (__sjthrow): Default to using __builtin_setjmp instead
  of setjmp.
(__sjpopnthrow): Likewise.
* optabs.c (init_optabs): Likewise.

From-SVN: r14045

gcc/except.c
gcc/expr.c
gcc/expr.h
gcc/libgcc2.c
gcc/optabs.c

index 71925a5..91afbc3 100644 (file)
@@ -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.  */
index 1dc79b6..4e3c981 100644 (file)
@@ -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;
+}
+
 \f
 /* 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
index ee954ef..bb957b7 100644 (file)
@@ -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.
index 107c4bf..09b6a15 100644 (file)
@@ -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])
index b93a383..992660d 100644 (file)
@@ -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