backport unwind fixes to 3.3

Richard Henderson rth@redhat.com
Fri Jun 6 08:52:00 GMT 2003


This is a backport of your mainline EH cleanups to 3.3.
Can you give this a try on s390?  The change in how the
stack pointer is handled is rather desirable for various
odd-ball cases like signal trampoline unwind info.


r~


Index: except.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/except.c,v
retrieving revision 1.233.2.5
diff -c -p -d -r1.233.2.5 except.c
*** except.c	2 May 2003 21:01:15 -0000	1.233.2.5
--- except.c	6 Jun 2003 08:44:20 -0000
*************** Software Foundation, 59 Temple Place - S
*** 74,85 ****
  
  /* Provide defaults for stuff that may not be defined when using
     sjlj exceptions.  */
- #ifndef EH_RETURN_STACKADJ_RTX
- #define EH_RETURN_STACKADJ_RTX 0
- #endif
- #ifndef EH_RETURN_HANDLER_RTX
- #define EH_RETURN_HANDLER_RTX 0
- #endif
  #ifndef EH_RETURN_DATA_REGNO
  #define EH_RETURN_DATA_REGNO(N) INVALID_REGNUM
  #endif
--- 74,79 ----
*************** expand_builtin_frob_return_addr (addr_tr
*** 3075,3151 ****
  
  void
  expand_builtin_eh_return (stackadj_tree, handler_tree)
!     tree stackadj_tree, handler_tree;
  {
!   rtx stackadj, handler;
! 
!   stackadj = expand_expr (stackadj_tree, cfun->eh->ehr_stackadj, VOIDmode, 0);
!   handler = expand_expr (handler_tree, cfun->eh->ehr_handler, VOIDmode, 0);
  
  #ifdef POINTERS_EXTEND_UNSIGNED
!   if (GET_MODE (stackadj) != Pmode)
!     stackadj = convert_memory_address (Pmode, stackadj);
! 
!   if (GET_MODE (handler) != Pmode)
!     handler = convert_memory_address (Pmode, handler);
  #endif
  
!   if (! cfun->eh->ehr_label)
!     {
!       cfun->eh->ehr_stackadj = copy_to_reg (stackadj);
!       cfun->eh->ehr_handler = copy_to_reg (handler);
!       cfun->eh->ehr_label = gen_label_rtx ();
!     }
!   else
!     {
!       if (stackadj != cfun->eh->ehr_stackadj)
! 	emit_move_insn (cfun->eh->ehr_stackadj, stackadj);
!       if (handler != cfun->eh->ehr_handler)
! 	emit_move_insn (cfun->eh->ehr_handler, handler);
!     }
  
    emit_jump (cfun->eh->ehr_label);
  }
  
  void
  expand_eh_return ()
  {
!   rtx sa, ra, around_label;
  
    if (! cfun->eh->ehr_label)
      return;
  
-   sa = EH_RETURN_STACKADJ_RTX;
-   if (! sa)
-     {
-       error ("__builtin_eh_return not supported on this target");
-       return;
-     }
- 
    current_function_calls_eh_return = 1;
  
    around_label = gen_label_rtx ();
-   emit_move_insn (sa, const0_rtx);
    emit_jump (around_label);
  
    emit_label (cfun->eh->ehr_label);
    clobber_return_register ();
  
  #ifdef HAVE_eh_return
    if (HAVE_eh_return)
!     emit_insn (gen_eh_return (cfun->eh->ehr_stackadj, cfun->eh->ehr_handler));
    else
  #endif
      {
!       ra = EH_RETURN_HANDLER_RTX;
!       if (! ra)
! 	{
! 	  error ("__builtin_eh_return not supported on this target");
! 	  ra = gen_reg_rtx (Pmode);
! 	}
! 
!       emit_move_insn (sa, cfun->eh->ehr_stackadj);
!       emit_move_insn (ra, cfun->eh->ehr_handler);
      }
  
    emit_label (around_label);
--- 3069,3141 ----
  
  void
  expand_builtin_eh_return (stackadj_tree, handler_tree)
!     tree stackadj_tree ATTRIBUTE_UNUSED;
!     tree handler_tree;
  {
!   rtx tmp;
  
+ #ifdef EH_RETURN_STACKADJ_RTX
+   tmp = expand_expr (stackadj_tree, cfun->eh->ehr_stackadj, VOIDmode, 0);
  #ifdef POINTERS_EXTEND_UNSIGNED
!   if (GET_MODE (tmp) != Pmode)
!     tmp = convert_memory_address (Pmode, tmp);
! #endif
!   if (!cfun->eh->ehr_stackadj)
!     cfun->eh->ehr_stackadj = copy_to_reg (tmp);
!   else if (tmp != cfun->eh->ehr_stackadj)
!     emit_move_insn (cfun->eh->ehr_stackadj, tmp);
  #endif
  
!   tmp = expand_expr (handler_tree, cfun->eh->ehr_handler, VOIDmode, 0);
! #ifdef POINTERS_EXTEND_UNSIGNED
!   if (GET_MODE (tmp) != Pmode)
!     tmp = convert_memory_address (Pmode, tmp);
! #endif
!   if (!cfun->eh->ehr_handler)
!     cfun->eh->ehr_handler = copy_to_reg (tmp);
!   else if (tmp != cfun->eh->ehr_handler)
!     emit_move_insn (cfun->eh->ehr_handler, tmp);
  
+   if (!cfun->eh->ehr_label)
+     cfun->eh->ehr_label = gen_label_rtx ();
    emit_jump (cfun->eh->ehr_label);
  }
  
  void
  expand_eh_return ()
  {
!   rtx around_label;
  
    if (! cfun->eh->ehr_label)
      return;
  
    current_function_calls_eh_return = 1;
  
+ #ifdef EH_RETURN_STACKADJ_RTX
+   emit_move_insn (EH_RETURN_STACKADJ_RTX, const0_rtx);
+ #endif
+ 
    around_label = gen_label_rtx ();
    emit_jump (around_label);
  
    emit_label (cfun->eh->ehr_label);
    clobber_return_register ();
  
+ #ifdef EH_RETURN_STACKADJ_RTX
+   emit_move_insn (EH_RETURN_STACKADJ_RTX, cfun->eh->ehr_stackadj);
+ #endif
+ 
  #ifdef HAVE_eh_return
    if (HAVE_eh_return)
!     emit_insn (gen_eh_return (cfun->eh->ehr_handler));
    else
  #endif
      {
! #ifdef EH_RETURN_HANDLER_RTX
!       emit_move_insn (EH_RETURN_HANDLER_RTX, cfun->eh->ehr_handler);
! #else
!       error ("__builtin_eh_return not supported on this target");
! #endif
      }
  
    emit_label (around_label);
Index: except.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/except.h,v
retrieving revision 1.65.8.2
diff -c -p -d -r1.65.8.2 except.h
*** except.h	5 May 2003 16:59:21 -0000	1.65.8.2
--- except.h	6 Jun 2003 08:44:20 -0000
*************** extern tree (*lang_eh_runtime_type) PARA
*** 155,161 ****
  #if ! (defined (EH_RETURN_DATA_REGNO)			\
         && (defined (IA64_UNWIND_INFO)			\
  	   || (DWARF2_UNWIND_INFO			\
- 	       && defined (EH_RETURN_STACKADJ_RTX)	\
  	       && (defined (EH_RETURN_HANDLER_RTX)	\
  		   || defined (HAVE_eh_return)))))
  #define MUST_USE_SJLJ_EXCEPTIONS	1
--- 155,160 ----
*************** extern tree (*lang_eh_runtime_type) PARA
*** 171,179 ****
  #  define USING_SJLJ_EXCEPTIONS		0
  #  ifndef EH_RETURN_DATA_REGNO
      #error "EH_RETURN_DATA_REGNO required"
- #  endif
- #  ifndef EH_RETURN_STACKADJ_RTX
-     #error "EH_RETURN_STACKADJ_RTX required"
  #  endif
  #  if !defined(EH_RETURN_HANDLER_RTX) && !defined(HAVE_eh_return)
      #error "EH_RETURN_HANDLER_RTX or eh_return required"
--- 170,175 ----
Index: unwind-dw2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/unwind-dw2.c,v
retrieving revision 1.22.2.5
diff -c -p -d -r1.22.2.5 unwind-dw2.c
*** unwind-dw2.c	7 May 2003 19:32:36 -0000	1.22.2.5
--- unwind-dw2.c	6 Jun 2003 08:44:20 -0000
*************** static void
*** 1046,1055 ****
  uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
  {
    struct _Unwind_Context orig_context = *context;
-   _Unwind_Word tmp_sp;
    void *cfa;
    long i;
  
    /* Special handling here: Many machines do not use a frame pointer,
       and track the CFA only through offsets from the stack pointer from
       one frame to the next.  In this case, the stack pointer is never
--- 1046,1055 ----
  uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
  {
    struct _Unwind_Context orig_context = *context;
    void *cfa;
    long i;
  
+ #ifdef EH_RETURN_STACKADJ_RTX
    /* Special handling here: Many machines do not use a frame pointer,
       and track the CFA only through offsets from the stack pointer from
       one frame to the next.  In this case, the stack pointer is never
*************** uw_update_context_1 (struct _Unwind_Cont
*** 1059,1070 ****
       In very special situations (such as unwind info for signal return),
       there may be location expressions that use the stack pointer as well.
  
!      Given that other unwind mechanisms generally won't work if you try
!      to represent stack pointer saves and restores directly, we don't
!      bother conditionalizing this at all.  */
! #ifndef __s390__
!   tmp_sp = (_Unwind_Ptr) context->cfa;
!   orig_context.reg[__builtin_dwarf_sp_column ()] = &tmp_sp;
  #endif
  
    /* Compute this frame's CFA.  */
--- 1059,1078 ----
       In very special situations (such as unwind info for signal return),
       there may be location expressions that use the stack pointer as well.
  
!      Do this conditionally for one frame.  This allows the unwind info
!      for one frame to save a copy of the stack pointer from the previous
!      frame, and be able to use much easier CFA mechanisms to do it.
!      Always zap the saved stack pointer value for the next frame; carrying
!      the value over from one frame to another doesn't make sense.  */
! 
!   _Unwind_Word tmp_sp;
! 
!   if (!orig_context.reg[__builtin_dwarf_sp_column ()])
!     {
!       tmp_sp = (_Unwind_Ptr) context->cfa;
!       orig_context.reg[__builtin_dwarf_sp_column ()] = &tmp_sp;
!     }
!   context->reg[__builtin_dwarf_sp_column ()] = NULL;
  #endif
  
    /* Compute this frame's CFA.  */
*************** uw_init_context_1 (struct _Unwind_Contex
*** 1157,1162 ****
--- 1165,1171 ----
  {
    void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
    _Unwind_FrameState fs;
+   _Unwind_Word sp_slot;
  
    memset (context, 0, sizeof (struct _Unwind_Context));
    context->ra = ra;
*************** uw_init_context_1 (struct _Unwind_Contex
*** 1165,1174 ****
      abort ();
  
    /* Force the frame state to use the known cfa value.  */
!   context->cfa = outer_cfa;
! #ifdef __s390__
!   context->reg[__builtin_dwarf_sp_column ()] = &outer_cfa;
! #endif
    fs.cfa_how = CFA_REG_OFFSET;
    fs.cfa_reg = __builtin_dwarf_sp_column ();
    fs.cfa_offset = 0;
--- 1174,1181 ----
      abort ();
  
    /* Force the frame state to use the known cfa value.  */
!   sp_slot = (_Unwind_Ptr) outer_cfa;
!   context->reg[__builtin_dwarf_sp_column ()] = &sp_slot;
    fs.cfa_how = CFA_REG_OFFSET;
    fs.cfa_reg = __builtin_dwarf_sp_column ();
    fs.cfa_offset = 0;
*************** uw_install_context_1 (struct _Unwind_Con
*** 1227,1237 ****
  	memcpy (c, t, dwarf_reg_size_table[i]);
      }
  
!   /* We adjust SP by the difference between CURRENT and TARGET's CFA.  */
!   if (STACK_GROWS_DOWNWARD)
!     return target->cfa - current->cfa + target->args_size;
!   else
!     return current->cfa - target->cfa - target->args_size;
  }
  
  static inline _Unwind_Ptr
--- 1234,1259 ----
  	memcpy (c, t, dwarf_reg_size_table[i]);
      }
  
! #ifdef EH_RETURN_STACKADJ_RTX
!   {
!     void *target_cfa;
! 
!     /* If the last frame records a saved stack pointer, use it.  */
!     if (target->reg[__builtin_dwarf_sp_column ()])
!       target_cfa = (void *)(_Unwind_Ptr)
!         _Unwind_GetGR (target, __builtin_dwarf_sp_column ());
!     else
!       target_cfa = target->cfa;
! 
!     /* We adjust SP by the difference between CURRENT and TARGET's CFA.  */
!     if (STACK_GROWS_DOWNWARD)
!       return target_cfa - current->cfa + target->args_size;
!     else
!       return current->cfa - target_cfa - target->args_size;
!   }
! #else
!   return 0;
! #endif
  }
  
  static inline _Unwind_Ptr
Index: config/i386/i386.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.md,v
retrieving revision 1.404.2.16
diff -c -p -d -r1.404.2.16 i386.md
*** config/i386/i386.md	1 Jun 2003 16:15:09 -0000	1.404.2.16
--- config/i386/i386.md	6 Jun 2003 08:44:21 -0000
***************
*** 13607,13617 ****
    "ix86_expand_epilogue (0); DONE;")
  
  (define_expand "eh_return"
!   [(use (match_operand 0 "register_operand" ""))
!    (use (match_operand 1 "register_operand" ""))]
    ""
  {
!   rtx tmp, sa = operands[0], ra = operands[1];
  
    /* Tricky bit: we write the address of the handler to which we will
       be returning into someone else's stack frame, one word below the
--- 13607,13616 ----
    "ix86_expand_epilogue (0); DONE;")
  
  (define_expand "eh_return"
!   [(use (match_operand 0 "register_operand" ""))]
    ""
  {
!   rtx tmp, sa = EH_RETURN_STACKADJ_RTX, ra = operands[0];
  
    /* Tricky bit: we write the address of the handler to which we will
       be returning into someone else's stack frame, one word below the
Index: config/mips/mips.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.md,v
retrieving revision 1.153.2.2
diff -c -p -d -r1.153.2.2 mips.md
*** config/mips/mips.md	28 Feb 2003 15:02:22 -0000	1.153.2.2
--- config/mips/mips.md	6 Jun 2003 08:44:21 -0000
*************** ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n
*** 10069,10089 ****
  
  ;; This is used in compiling the unwind routines.
  (define_expand "eh_return"
!   [(use (match_operand 0 "general_operand" ""))
!    (use (match_operand 1 "general_operand" ""))]
    ""
    "
  {
    enum machine_mode gpr_mode = TARGET_64BIT ? DImode : SImode;
  
!   if (GET_MODE (operands[1]) != gpr_mode)
!     operands[1] = convert_to_mode (gpr_mode, operands[1], 0);
    if (TARGET_64BIT)
!     emit_insn (gen_eh_set_lr_di (operands[1]));
    else
!     emit_insn (gen_eh_set_lr_si (operands[1]));
  
-   emit_move_insn (EH_RETURN_STACKADJ_RTX, operands[0]);
    DONE;
  }")
  
--- 10069,10087 ----
  
  ;; This is used in compiling the unwind routines.
  (define_expand "eh_return"
!   [(use (match_operand 0 "general_operand" ""))]
    ""
    "
  {
    enum machine_mode gpr_mode = TARGET_64BIT ? DImode : SImode;
  
!   if (GET_MODE (operands[0]) != gpr_mode)
!     operands[0] = convert_to_mode (gpr_mode, operands[0], 0);
    if (TARGET_64BIT)
!     emit_insn (gen_eh_set_lr_di (operands[0]));
    else
!     emit_insn (gen_eh_set_lr_si (operands[0]));
  
    DONE;
  }")
  
Index: config/rs6000/rs6000.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.224.2.3
diff -c -p -d -r1.224.2.3 rs6000.md
*** config/rs6000/rs6000.md	6 Apr 2003 02:02:21 -0000	1.224.2.3
--- config/rs6000/rs6000.md	6 Jun 2003 08:44:21 -0000
***************
*** 14875,14893 ****
  
  ; This is used in compiling the unwind routines.
  (define_expand "eh_return"
!   [(use (match_operand 0 "general_operand" ""))
!    (use (match_operand 1 "general_operand" ""))]
    ""
    "
  {
  #if TARGET_AIX
!     rs6000_emit_eh_toc_restore (operands[0]);
  #endif
    if (TARGET_32BIT)
!     emit_insn (gen_eh_set_lr_si (operands[1]));
    else
!     emit_insn (gen_eh_set_lr_di (operands[1]));
!   emit_move_insn (EH_RETURN_STACKADJ_RTX, operands[0]);
    DONE;
  }")
  
--- 14875,14891 ----
  
  ; This is used in compiling the unwind routines.
  (define_expand "eh_return"
!   [(use (match_operand 0 "general_operand" ""))]
    ""
    "
  {
  #if TARGET_AIX
!   rs6000_emit_eh_toc_restore (EH_RETURN_STACKADJ_RTX);
  #endif
    if (TARGET_32BIT)
!     emit_insn (gen_eh_set_lr_si (operands[0]));
    else
!     emit_insn (gen_eh_set_lr_di (operands[0]));
    DONE;
  }")
  
Index: config/s390/s390.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.h,v
retrieving revision 1.53.2.6
diff -c -p -d -r1.53.2.6 s390.h
*** config/s390/s390.h	29 Apr 2003 14:31:53 -0000	1.53.2.6
--- config/s390/s390.h	6 Jun 2003 08:44:21 -0000
*************** extern int current_function_outgoing_arg
*** 510,516 ****
  
  /* Describe how we implement __builtin_eh_return.  */
  #define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 6 : INVALID_REGNUM)
- #define EH_RETURN_STACKADJ_RTX  gen_rtx_REG (Pmode, 10)
  #define EH_RETURN_HANDLER_RTX \
    gen_rtx_MEM (Pmode, plus_constant (arg_pointer_rtx, \
                                       TARGET_64BIT? -48 : -40))
--- 510,515 ----



More information about the Gcc-patches mailing list