This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

ia64 eh, part 23


Update the powerpc port for the changes to eh_return.


r~


        * config/rs6000/rs6000.c (rs6000_stack_info): Allocate space
        for eh_return data registers.
        (rs6000_emit_prologue): Save eh_return data registers.
        (rs6000_emit_epilogue): Force inline restores if eh_return.
        Restore eh_return data registers.  Mind EH_RETURN_STACKADJ_RTX.
        * config/rs6000/rs6000.h (rs6000_stack_t): Add ehrd_offset.
        (EH_RETURN_DATA_REGNO, EH_RETURN_STACKADJ_RTX): New.
        (EPILOGUE_USES): True for TOC_REGISTER if calls_eh_return and
        the target uses one.
        * config/rs6000/rs6000.md (eh_epilogue, eh_reg_restore): Remove.
        (return_eh_si, return_eh_di): Remove.
        (eh_return): New, from corpse of eh_epilogue.
        (eh_set_lr_si, eh_set_lr_di): New.

Index: config/rs6000/rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.171
diff -c -p -d -r1.171 rs6000.c
*** rs6000.c	2001/03/22 18:48:51	1.171
--- rs6000.c	2001/03/28 11:15:43
*************** rs6000_stack_info ()
*** 4808,4813 ****
--- 4808,4814 ----
    rs6000_stack_t *info_ptr = &info;
    int reg_size = TARGET_POWERPC64 ? 8 : 4;
    enum rs6000_abi abi;
+   int ehrd_size;
    int total_raw_size;
  
    /* Zero all fields portably */
*************** rs6000_stack_info ()
*** 4860,4865 ****
--- 4861,4879 ----
  	info_ptr->cr_size = reg_size;
      }
  
+   /* If the current function calls __builtin_eh_return, then we need
+      to allocate stack space for registers that will hold data for
+      the exception handler.  */
+   if (current_function_calls_eh_return)
+     {
+       unsigned int i;
+       for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM; ++i)
+ 	continue;
+       ehrd_size = i * UNITS_PER_WORD;
+     }
+   else
+     ehrd_size = 0;
+ 
    /* Determine various sizes */
    info_ptr->reg_size     = reg_size;
    info_ptr->fixed_size   = RS6000_SAVE_AREA;
*************** rs6000_stack_info ()
*** 4868,4873 ****
--- 4882,4888 ----
    info_ptr->parm_size    = RS6000_ALIGN (current_function_outgoing_args_size, 8);
    info_ptr->save_size    = RS6000_ALIGN (info_ptr->fp_size
  				  + info_ptr->gp_size
+ 				  + ehrd_size
  				  + info_ptr->cr_size
  				  + info_ptr->lr_size
  				  + info_ptr->toc_size, 8);
*************** rs6000_stack_info ()
*** 4883,4888 ****
--- 4898,4904 ----
      case ABI_AIX_NODESC:
        info_ptr->fp_save_offset   = - info_ptr->fp_size;
        info_ptr->gp_save_offset   = info_ptr->fp_save_offset - info_ptr->gp_size;
+       info_ptr->ehrd_offset      = info_ptr->gp_save_offset - ehrd_size;
        info_ptr->cr_save_offset   = reg_size; /* first word when 64-bit.  */
        info_ptr->lr_save_offset   = 2*reg_size;
        break;
*************** rs6000_stack_info ()
*** 4893,4898 ****
--- 4909,4915 ----
        info_ptr->gp_save_offset   = info_ptr->fp_save_offset - info_ptr->gp_size;
        info_ptr->cr_save_offset   = info_ptr->gp_save_offset - info_ptr->cr_size;
        info_ptr->toc_save_offset  = info_ptr->cr_save_offset - info_ptr->toc_size;
+       info_ptr->ehrd_offset      = info_ptr->toc_save_offset - ehrd_size;
        info_ptr->lr_save_offset   = reg_size;
        break;
      }
*************** rs6000_frame_related (insn, reg, val, re
*** 5585,5591 ****
  /* Emit function prologue as insns.  */
  
  void
! rs6000_emit_prologue()
  {
    rs6000_stack_t *info = rs6000_stack_info ();
    enum machine_mode reg_mode = TARGET_POWERPC64 ? DImode : SImode;
--- 5602,5608 ----
  /* Emit function prologue as insns.  */
  
  void
! rs6000_emit_prologue ()
  {
    rs6000_stack_t *info = rs6000_stack_info ();
    enum machine_mode reg_mode = TARGET_POWERPC64 ? DImode : SImode;
*************** rs6000_emit_prologue()
*** 5741,5746 ****
--- 5758,5788 ----
  	  }
      }
  
+   /* ??? There's no need to emit actual instructions here, but it's the
+      easiest way to get the frame unwind information emitted.  */
+   if (current_function_calls_eh_return)
+     {
+       unsigned int i, regno;
+       for (i = 0; ; ++i)
+ 	{
+ 	  rtx addr, reg, mem;
+ 
+ 	  regno = EH_RETURN_DATA_REGNO (i);
+ 	  if (regno == INVALID_REGNUM)
+ 	    break;
+ 
+ 	  reg = gen_rtx_REG (reg_mode, regno);
+ 	  addr = plus_constant (frame_reg_rtx,
+ 				info->ehrd_offset + sp_offset + reg_size * i);
+ 	  mem = gen_rtx_MEM (reg_mode, addr);
+ 	  MEM_ALIAS_SET (mem) = rs6000_sr_alias_set;
+ 
+ 	  insn = emit_move_insn (mem, reg);
+ 	  rs6000_frame_related (insn, frame_ptr_rtx, info->total_size, 
+ 				NULL_RTX, NULL_RTX);
+ 	}
+     }
+ 
    /* Save lr if we used it.  */
    if (info->lr_save_p)
      {
*************** output_prolog (file, size)
*** 5876,5882 ****
     need special notes to explain where r11 is in relation to the stack.  */
  
  void
! rs6000_emit_epilogue(sibcall)
       int sibcall;
  {
    rs6000_stack_t *info;
--- 5918,5924 ----
     need special notes to explain where r11 is in relation to the stack.  */
  
  void
! rs6000_emit_epilogue (sibcall)
       int sibcall;
  {
    rs6000_stack_t *info;
*************** rs6000_emit_epilogue(sibcall)
*** 5895,5900 ****
--- 5937,5943 ----
    using_load_multiple = (TARGET_MULTIPLE && ! TARGET_POWERPC64
  			 && info->first_gp_reg_save < 31);
    restoring_FPRs_inline = (sibcall
+ 			   || current_function_calls_eh_return
  			   || info->first_fp_reg_save == 64
  			   || FP_SAVE_INLINE (info->first_fp_reg_save));
    use_backchain_to_restore_sp = (frame_pointer_needed 
*************** rs6000_emit_epilogue(sibcall)
*** 5960,5965 ****
--- 6003,6028 ----
      emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM),
  		    gen_rtx_REG (Pmode, 0));
    
+   /* Load exception handler data registers, if needed.  */
+   if (current_function_calls_eh_return)
+     {
+       unsigned int i, regno;
+       for (i = 0; ; ++i)
+ 	{
+ 	  rtx addr, mem;
+ 
+ 	  regno = EH_RETURN_DATA_REGNO (i);
+ 	  if (regno == INVALID_REGNUM)
+ 	    break;
+ 
+ 	  addr = plus_constant (frame_reg_rtx,
+ 				info->ehrd_offset + sp_offset + reg_size * i);
+ 	  mem = gen_rtx_MEM (reg_mode, addr);
+ 	  MEM_ALIAS_SET (mem) = rs6000_sr_alias_set;
+ 
+ 	  emit_move_insn (gen_rtx_REG (reg_mode, regno), mem);
+ 	}
+     }
    
    /* Restore GPRs.  This is done as a PARALLEL if we are using
       the load-multiple instructions.  */
*************** rs6000_emit_epilogue(sibcall)
*** 6093,6098 ****
--- 6156,6169 ----
  		     : gen_adddi3 (sp_reg_rtx, sp_reg_rtx,
  				   GEN_INT (sp_offset)));
  	}
+     }
+ 
+   if (current_function_calls_eh_return)
+     {
+       rtx sa = EH_RETURN_STACKADJ_RTX;
+       emit_insn (Pmode == SImode
+ 		 ? gen_addsi3 (sp_reg_rtx, sp_reg_rtx, sa)
+ 		 : gen_adddi3 (sp_reg_rtx, sp_reg_rtx, sa));
      }
  
    if (!sibcall)
Index: config/rs6000/rs6000.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.105
diff -c -p -d -r1.105 rs6000.h
*** rs6000.h	2001/02/08 20:30:16	1.105
--- rs6000.h	2001/03/28 11:15:43
*************** typedef struct rs6000_stack {
*** 1180,1185 ****
--- 1180,1186 ----
    int cr_save_offset;		/* offset to save CR from initial SP */
    int toc_save_offset;		/* offset to save the TOC pointer */
    int varargs_save_offset;	/* offset to save the varargs registers */
+   int ehrd_offset;		/* offset to EH return data */
    int reg_size;			/* register size (4 or 8) */
    int varargs_size;		/* size to hold V.4 args passed in regs */
    int vars_size;		/* variable save area size */
*************** typedef struct rs6000_args
*** 1569,1576 ****
     and frame pointer registers are already be assumed to be used as
     needed.  */
  
! #define	EPILOGUE_USES(REGNO)	\
!   (reload_completed && (REGNO) == LINK_REGISTER_REGNUM)
  
  /* This macro generates the assembly code for function exit,
     on machines that need it.  If FUNCTION_EPILOGUE is not defined
--- 1570,1580 ----
     and frame pointer registers are already be assumed to be used as
     needed.  */
  
! #define	EPILOGUE_USES(REGNO)					\
!   ((reload_completed && (REGNO) == LINK_REGISTER_REGNUM)	\
!    || (current_function_calls_eh_return				\
!        && TARGET_TOC						\
!        && (REGNO) == TOC_REGISTER))
  
  /* This macro generates the assembly code for function exit,
     on machines that need it.  If FUNCTION_EPILOGUE is not defined
*************** do {									\
*** 2640,2645 ****
--- 2644,2653 ----
  
  #define INCOMING_RETURN_ADDR_RTX   gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)
  #define DWARF_FRAME_RETURN_COLUMN  DWARF_FRAME_REGNUM (LINK_REGISTER_REGNUM)
+ 
+ /* Describe how we implement __builtin_eh_return.  */
+ #define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 3 : INVALID_REGNUM)
+ #define EH_RETURN_STACKADJ_RTX  gen_rtx_REG (Pmode, 10)
  
  /* Define results of standard character escape sequences.  */
  #define TARGET_BELL 007
Index: config/rs6000/rs6000.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.109
diff -c -p -d -r1.109 rs6000.md
*** rs6000.md	2001/03/08 05:44:49	1.109
--- rs6000.md	2001/03/28 11:15:43
*************** operands[2] = GEN_INT (INTVAL (operands[
*** 13381,13498 ****
   "TARGET_64BIT"
   "b %z2")
  
! ; This is used in compiling the routines __throw and __rethrow.
! ; It's a little different to the usual definition...
! 
! (define_expand "eh_epilogue"
!   [(use (match_operand 0 "general_operand" "r"))
!    (use (match_operand 1 "general_operand" "r"))
!    (use (match_operand 2 "general_operand" "c"))]
    ""
    "
  {
!   rtx stack_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
!   rtx insn;
! 
!   /* This is required for binary compatibility.  If it's wrong,
!      it probably means that eh_regs() in except.c is broken.  */
!   if (GET_CODE (operands[0]) != REG || REGNO (operands[0]) != 3)
!     abort();
! 
!   /* These can be anything that doesn't interfere with the epilogue.  */
!   if (GET_CODE (operands[1]) != REG || REGNO (operands[1]) != 4)
!     {
!       rtx r = gen_rtx_REG (Pmode, 4);
!       emit_move_insn (r, operands[1]);
!       operands[1] = r;
!     }
! 
!   if (GET_CODE (operands[2]) != REG 
! 	|| REGNO (operands[2]) != COUNT_REGISTER_REGNUM)
!     {
!       rtx r = gen_rtx_REG (Pmode, COUNT_REGISTER_REGNUM);
!       emit_move_insn (r, operands[2]);
!       operands[2] = r;
!     }
! 
! #if TARGET_AIX
!     rs6000_emit_eh_toc_restore (operands[1]);
! #endif
! 
!   emit_insn (gen_eh_reg_restore ());
! 
!   if (Pmode == SImode)
!     emit_insn (gen_addsi3 (stack_reg, stack_reg, operands[1]));
!   else
!     emit_insn (gen_adddi3 (stack_reg, stack_reg, operands[1]));
!   
!   if (Pmode == SImode)
!     insn = emit_jump_insn (gen_return_eh_si (operands[2]));
    else
!     insn = emit_jump_insn (gen_return_eh_di (operands[2]));
!   emit_barrier_after (insn);
! 
    DONE;
  }")
  
! ; We can't expand this before we know which registers are restored,
! ; but we do want to expand it before flow2 because that way flow2 can
! ; remove the redundant loads of the link register.
! (define_expand "eh_reg_restore"
!   [(unspec_volatile [(const_int 0)] 9)]
!   ""
!   "")
  
  (define_split
!   [(unspec_volatile [(const_int 0)] 9)]
!   "reload_completed && TARGET_SCHED_PROLOG"
!   [(unspec_volatile [(const_int 0)] 9)]
    "
  {
!   rs6000_emit_epilogue (TRUE);
!   DONE;
! }")
! 
! (define_insn ""
!   [(unspec_volatile [(const_int 0)] 9)]
!   ""
!   "*
! {
!   if (TARGET_SCHED_PROLOG)
!     return \"#\";
  
!   /* This is slightly ugly, but at least we don't have multiple
!      copies of the epilogue-emitting code.  */
!   start_sequence ();
  
!   /* A NOTE_INSN_DELETED is supposed to be at the start
!      and end of the \"toplevel\" insn chain.  */
!   emit_note (0, NOTE_INSN_DELETED);
!   rs6000_emit_epilogue (TRUE);
!   emit_note (0, NOTE_INSN_DELETED);
  
!   if (TARGET_DEBUG_STACK)
!     debug_rtx_list (get_insns(), 100);
!   final (get_insns(), asm_out_file, FALSE, FALSE);
!   end_sequence ();
!   return \"\";
  }")
- 
- 
- (define_insn "return_eh_si"
-   [(return)
-    (use (match_operand:SI 0 "register_operand" "lc"))
-    (use (reg:SI 2))
-    (use (reg:SI 3))]
-   "TARGET_32BIT"
-   "b%T0"
-   [(set_attr "type" "jmpreg")])
- 
- (define_insn "return_eh_di"
-   [(return)
-    (use (match_operand:DI 0 "register_operand" "lc"))
-    (use (reg:DI 2))
-    (use (reg:DI 3))]
-   "TARGET_64BIT"
-   "b%T0"
-   [(set_attr "type" "jmpreg")])
--- 13381,13446 ----
   "TARGET_64BIT"
   "b %z2")
  
! ; 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_TOC)
!     rs6000_emit_eh_toc_restore (operands[0]);
!   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;
  }")
  
! ; We can't expand this before we know where the link register is stored.
! (define_insn "eh_set_lr_si"
!   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] 9)
!    (clobber (match_scratch:SI 1 "=&r"))]
!   "TARGET_32BIT"
!   "#")
! 
! (define_insn "eh_set_lr_di"
!   [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")] 9)
!    (clobber (match_scratch:DI 1 "=&r"))]
!   "TARGET_64BIT"
!   "#")
  
  (define_split
!   [(unspec_volatile [(match_operand 0 "register_operand" "")] 9)
!    (clobber (match_scratch 1 ""))]
!   "reload_completed"
!   [(const_int 0)]
    "
  {
!   rs6000_stack_t *info = rs6000_stack_info ();
  
!   if (info->lr_save_p)
!     {
!       rtx frame_rtx = stack_pointer_rtx;
!       int sp_offset = 0;
!       rtx tmp;
  
!       if (frame_pointer_needed
! 	  || current_function_calls_alloca
! 	  || info->total_size > 32767)
! 	{
! 	  emit_move_insn (operands[1], gen_rtx_MEM (Pmode, frame_rtx));
! 	  frame_rtx = operands[1];
! 	}
!       else if (info->push_p)
! 	sp_offset = info->total_size;
  
!       tmp = plus_constant (frame_rtx, info->lr_save_offset + sp_offset);
!       tmp = gen_rtx_MEM (Pmode, tmp);
!       emit_move_insn (tmp, operands[0]);
!     }
!   else
!     emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM), operands[0]);
!   DONE;
  }")


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]