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 22


Update the x86 port for the changes to eh_return.


r~


        * config/i386/i386.c (general_no_elim_operand): Disallow virtual regs.
        (ix86_save_reg): If maybe_eh_return, true for EH_RETURN_DATA_REGNOs.
        True for pic register if current_function_calls_eh_return.
        (ix86_expand_epilogue): Change "emit_return" argument into "style".
        Handle eh_return requirements.
        * config/i386/i386.h (EH_RETURN_DATA_REGNO): New.
        (EH_RETURN_STACKADJ_RTX): New.
        * config/i386/i386.md (exception_receiver): Remove.
        (eh_return, eh_return_1): New.
        * config/i386/linux.h (MD_FALLBACK_FRAME_STATE_FOR): New.

Index: config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.243
diff -c -p -d -r1.243 i386.c
*** i386.c	2001/03/26 12:36:34	1.243
--- i386.c	2001/03/28 11:10:27
*************** static int ix86_split_to_parts PARAMS ((
*** 566,572 ****
  static int ix86_safe_length_prefix PARAMS ((rtx));
  static int ix86_nsaved_regs PARAMS((void));
  static void ix86_emit_save_regs PARAMS((void));
! static void ix86_emit_restore_regs_using_mov PARAMS ((rtx, int));
  static void ix86_emit_epilogue_esp_adjustment PARAMS((int));
  static void ix86_set_move_mem_attrs_1 PARAMS ((rtx, rtx, rtx, rtx, rtx));
  static void ix86_sched_reorder_pentium PARAMS((rtx *, rtx *));
--- 566,572 ----
  static int ix86_safe_length_prefix PARAMS ((rtx));
  static int ix86_nsaved_regs PARAMS((void));
  static void ix86_emit_save_regs PARAMS((void));
! static void ix86_emit_restore_regs_using_mov PARAMS ((rtx, int, bool));
  static void ix86_emit_epilogue_esp_adjustment PARAMS((int));
  static void ix86_set_move_mem_attrs_1 PARAMS ((rtx, rtx, rtx, rtx, rtx));
  static void ix86_sched_reorder_pentium PARAMS((rtx *, rtx *));
*************** static int ix86_fp_comparison_arithmetic
*** 606,612 ****
  static int ix86_fp_comparison_fcomi_cost PARAMS ((enum rtx_code code));
  static int ix86_fp_comparison_sahf_cost PARAMS ((enum rtx_code code));
  static int ix86_fp_comparison_cost PARAMS ((enum rtx_code code));
! static int ix86_save_reg PARAMS ((int));
  static void ix86_compute_frame_layout PARAMS ((struct ix86_frame *));
  
  /* Sometimes certain combinations of command options do not make
--- 606,612 ----
  static int ix86_fp_comparison_fcomi_cost PARAMS ((enum rtx_code code));
  static int ix86_fp_comparison_sahf_cost PARAMS ((enum rtx_code code));
  static int ix86_fp_comparison_cost PARAMS ((enum rtx_code code));
! static int ix86_save_reg PARAMS ((int, bool));
  static void ix86_compute_frame_layout PARAMS ((struct ix86_frame *));
  
  /* Sometimes certain combinations of command options do not make
*************** general_no_elim_operand (op, mode)
*** 1475,1480 ****
--- 1475,1484 ----
        || t == virtual_incoming_args_rtx || t == virtual_stack_vars_rtx
        || t == virtual_stack_dynamic_rtx)
      return 0;
+   if (REG_P (t)
+       && REGNO (t) >= FIRST_VIRTUAL_REGISTER
+       && REGNO (t) <= LAST_VIRTUAL_REGISTER)
+     return 0;
  
    return general_operand (op, mode);
  }
*************** gen_push (arg)
*** 2249,2265 ****
  
  /* Return 1 if we need to save REGNO.  */
  static int
! ix86_save_reg (regno)
! 	int regno;
  {
!   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
! 				  || current_function_uses_const_pool)
! 		     && !TARGET_64BIT;
!   return ((regs_ever_live[regno] && !call_used_regs[regno]
! 	   && !fixed_regs[regno]
! 	   && (regno != HARD_FRAME_POINTER_REGNUM || !frame_pointer_needed))
! 	  || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used));
  
  }
  
  /* Return number of registers to be saved on the stack.  */
--- 2253,2287 ----
  
  /* Return 1 if we need to save REGNO.  */
  static int
! ix86_save_reg (regno, maybe_eh_return)
!      int regno;
!      bool maybe_eh_return;
  {
!   if (flag_pic
!       && ! TARGET_64BIT
!       && regno == PIC_OFFSET_TABLE_REGNUM
!       && (current_function_uses_pic_offset_table
! 	  || current_function_uses_const_pool
! 	  || current_function_calls_eh_return))
!     return 1;
  
+   if (current_function_calls_eh_return && maybe_eh_return)
+     {
+       unsigned i;
+       for (i = 0; ; i++)
+ 	{
+ 	  unsigned test = EH_RETURN_DATA_REGNO(i);
+ 	  if (test == INVALID_REGNUM)
+ 	    break;
+ 	  if (test == (unsigned) regno)
+ 	    return 1;
+ 	}
+     }
+ 
+   return (regs_ever_live[regno]
+ 	  && !call_used_regs[regno]
+ 	  && !fixed_regs[regno]
+ 	  && (regno != HARD_FRAME_POINTER_REGNUM || !frame_pointer_needed));
  }
  
  /* Return number of registers to be saved on the stack.  */
*************** ix86_nsaved_regs ()
*** 2271,2277 ****
    int regno;
  
    for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
!     if (ix86_save_reg (regno))
        nregs++;
    return nregs;
  }
--- 2293,2299 ----
    int regno;
  
    for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
!     if (ix86_save_reg (regno, true))
        nregs++;
    return nregs;
  }
*************** ix86_emit_save_regs ()
*** 2423,2429 ****
    rtx insn;
  
    for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
!     if (ix86_save_reg (regno))
        {
  	insn = emit_insn (gen_push (gen_rtx_REG (Pmode, regno)));
  	RTX_FRAME_RELATED_P (insn) = 1;
--- 2445,2451 ----
    rtx insn;
  
    for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
!     if (ix86_save_reg (regno, true))
        {
  	insn = emit_insn (gen_push (gen_rtx_REG (Pmode, regno)));
  	RTX_FRAME_RELATED_P (insn) = 1;
*************** ix86_emit_epilogue_esp_adjustment (tsize
*** 2535,2548 ****
  /* Emit code to restore saved registers using MOV insns.  First register
     is restored from POINTER + OFFSET.  */
  static void
! ix86_emit_restore_regs_using_mov (pointer, offset)
! 	rtx pointer;
! 	int offset;
  {
    int regno;
  
    for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
!     if (ix86_save_reg (regno))
        {
  	emit_move_insn (gen_rtx_REG (Pmode, regno),
  			adj_offsettable_operand (gen_rtx_MEM (Pmode,
--- 2557,2571 ----
  /* Emit code to restore saved registers using MOV insns.  First register
     is restored from POINTER + OFFSET.  */
  static void
! ix86_emit_restore_regs_using_mov (pointer, offset, maybe_eh_return)
!      rtx pointer;
!      int offset;
!      bool maybe_eh_return;
  {
    int regno;
  
    for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
!     if (ix86_save_reg (regno, maybe_eh_return))
        {
  	emit_move_insn (gen_rtx_REG (Pmode, regno),
  			adj_offsettable_operand (gen_rtx_MEM (Pmode,
*************** ix86_emit_restore_regs_using_mov (pointe
*** 2555,2562 ****
  /* Restore function stack, frame, and registers.  */
  
  void
! ix86_expand_epilogue (emit_return)
!      int emit_return;
  {
    int regno;
    int sp_valid = !frame_pointer_needed || current_function_sp_is_unchanging;
--- 2578,2585 ----
  /* Restore function stack, frame, and registers.  */
  
  void
! ix86_expand_epilogue (style)
!      int style;
  {
    int regno;
    int sp_valid = !frame_pointer_needed || current_function_sp_is_unchanging;
*************** ix86_expand_epilogue (emit_return)
*** 2588,2594 ****
    if ((!sp_valid && frame.nregs <= 1)
        || (frame_pointer_needed && !frame.nregs && frame.to_allocate)
        || (frame_pointer_needed && TARGET_USE_LEAVE && !optimize_size
! 	  && frame.nregs == 1))
      {
        /* Restore registers.  We can use ebp or esp to address the memory
  	 locations.  If both are available, default to ebp, since offsets
--- 2611,2618 ----
    if ((!sp_valid && frame.nregs <= 1)
        || (frame_pointer_needed && !frame.nregs && frame.to_allocate)
        || (frame_pointer_needed && TARGET_USE_LEAVE && !optimize_size
! 	  && frame.nregs == 1)
!       || style == 2)
      {
        /* Restore registers.  We can use ebp or esp to address the memory
  	 locations.  If both are available, default to ebp, since offsets
*************** ix86_expand_epilogue (emit_return)
*** 2597,2608 ****
  	 mode.  */
  
        if (!frame_pointer_needed || (sp_valid && !frame.to_allocate))
! 	ix86_emit_restore_regs_using_mov (stack_pointer_rtx, frame.to_allocate);
        else
! 	ix86_emit_restore_regs_using_mov (hard_frame_pointer_rtx, offset);
  
!       if (!frame_pointer_needed)
! 	ix86_emit_epilogue_esp_adjustment (frame.to_allocate + frame.nregs * UNITS_PER_WORD);
        /* If not an i386, mov & pop is faster than "leave".  */
        else if (TARGET_USE_LEAVE || optimize_size)
  	emit_insn (TARGET_64BIT ? gen_leave_rex64 () : gen_leave ());
--- 2621,2661 ----
  	 mode.  */
  
        if (!frame_pointer_needed || (sp_valid && !frame.to_allocate))
! 	ix86_emit_restore_regs_using_mov (stack_pointer_rtx,
! 					  frame.to_allocate, style == 2);
        else
! 	ix86_emit_restore_regs_using_mov (hard_frame_pointer_rtx,
! 					  offset, style == 2);
  
!       /* eh_return epilogues need %ecx added to the stack pointer.  */
!       if (style == 2)
! 	{
! 	  rtx tmp, sa = EH_RETURN_STACKADJ_RTX;
! 
! 	  if (frame_pointer_needed)
! 	    {
! 	      tmp = gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx, sa);
! 	      tmp = plus_constant (tmp, UNITS_PER_WORD);
! 	      emit_insn (gen_rtx_SET (VOIDmode, sa, tmp));
! 
! 	      tmp = gen_rtx_MEM (Pmode, hard_frame_pointer_rtx);
! 	      emit_move_insn (hard_frame_pointer_rtx, tmp);
! 
! 	      emit_insn (gen_pro_epilogue_adjust_stack
! 			 (stack_pointer_rtx, sa, const0_rtx,
! 			  hard_frame_pointer_rtx));
! 	    }
! 	  else
! 	    {
! 	      tmp = gen_rtx_PLUS (Pmode, stack_pointer_rtx, sa);
! 	      tmp = plus_constant (tmp, (frame.to_allocate
!                                          + frame.nregs * UNITS_PER_WORD));
! 	      emit_insn (gen_rtx_SET (VOIDmode, stack_pointer_rtx, tmp));
! 	    }
! 	}
!       else if (!frame_pointer_needed)
! 	ix86_emit_epilogue_esp_adjustment (frame.to_allocate
! 					   + frame.nregs * UNITS_PER_WORD);
        /* If not an i386, mov & pop is faster than "leave".  */
        else if (TARGET_USE_LEAVE || optimize_size)
  	emit_insn (TARGET_64BIT ? gen_leave_rex64 () : gen_leave ());
*************** ix86_expand_epilogue (emit_return)
*** 2635,2641 ****
  	ix86_emit_epilogue_esp_adjustment (frame.to_allocate);
  
        for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
! 	if (ix86_save_reg (regno))
  	  {
  	    if (TARGET_64BIT)
  	      emit_insn (gen_popdi1 (gen_rtx_REG (Pmode, regno)));
--- 2688,2694 ----
  	ix86_emit_epilogue_esp_adjustment (frame.to_allocate);
  
        for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
! 	if (ix86_save_reg (regno, false))
  	  {
  	    if (TARGET_64BIT)
  	      emit_insn (gen_popdi1 (gen_rtx_REG (Pmode, regno)));
*************** ix86_expand_epilogue (emit_return)
*** 2652,2658 ****
      }
  
    /* Sibcall epilogues don't want a return instruction.  */
!   if (! emit_return)
      return;
  
    if (current_function_pops_args && current_function_args_size)
--- 2705,2711 ----
      }
  
    /* Sibcall epilogues don't want a return instruction.  */
!   if (style == 0)
      return;
  
    if (current_function_pops_args && current_function_args_size)
Index: config/i386/i386.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.h,v
retrieving revision 1.172
diff -c -p -d -r1.172 i386.h
*** i386.h	2001/03/26 12:36:35	1.172
--- i386.h	2001/03/28 11:10:27
*************** extern int const svr4_dbx_register_map[F
*** 2779,2794 ****
    gen_rtx_MEM (VOIDmode, gen_rtx_REG (VOIDmode, STACK_POINTER_REGNUM))
   
  /* After the prologue, RA is at -4(AP) in the current frame.  */
! #define RETURN_ADDR_RTX(COUNT, FRAME)					\
!   ((COUNT) == 0								\
!    ? gen_rtx_MEM (Pmode, plus_constant (arg_pointer_rtx, TARGET_64BIT ? -8 : -4))\
!    : gen_rtx_MEM (Pmode, plus_constant (FRAME, TARGET_64BIT ? 8 : 4)))
  
  /* PC is dbx register 8; let's use that column for RA. */
  #define DWARF_FRAME_RETURN_COLUMN 	(TARGET_64BIT ? 16 : 8)
  
  /* Before the prologue, the top of the frame is at 4(%esp).  */
  #define INCOMING_FRAME_SP_OFFSET UNITS_PER_WORD
  
  /* This is how to output the definition of a user-level label named NAME,
     such as the label on a static function or variable NAME.  */
--- 2779,2798 ----
    gen_rtx_MEM (VOIDmode, gen_rtx_REG (VOIDmode, STACK_POINTER_REGNUM))
   
  /* After the prologue, RA is at -4(AP) in the current frame.  */
! #define RETURN_ADDR_RTX(COUNT, FRAME)					   \
!   ((COUNT) == 0								   \
!    ? gen_rtx_MEM (Pmode, plus_constant (arg_pointer_rtx, -UNITS_PER_WORD)) \
!    : gen_rtx_MEM (Pmode, plus_constant (FRAME, UNITS_PER_WORD)))
  
  /* PC is dbx register 8; let's use that column for RA. */
  #define DWARF_FRAME_RETURN_COLUMN 	(TARGET_64BIT ? 16 : 8)
  
  /* Before the prologue, the top of the frame is at 4(%esp).  */
  #define INCOMING_FRAME_SP_OFFSET UNITS_PER_WORD
+ 
+ /* Describe how we implement __builtin_eh_return.  */
+ #define EH_RETURN_DATA_REGNO(N)	((N) < 2 ? (N) : INVALID_REGNUM)
+ #define EH_RETURN_STACKADJ_RTX	gen_rtx_REG (Pmode, 2)
  
  /* This is how to output the definition of a user-level label named NAME,
     such as the label on a static function or variable NAME.  */
Index: config/i386/i386.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.md,v
retrieving revision 1.249
diff -c -p -d -r1.249 i386.md
*** i386.md	2001/03/26 13:56:34	1.249
--- i386.md	2001/03/28 11:10:27
***************
*** 73,78 ****
--- 73,79 ----
  ;; 10 This is a `sahf' operation.
  ;; 11 This is a `fstcw' operation
  ;; 12 This is behaviour of add when setting carry flag.
+ ;; 13 This is a `eh_return' placeholder.
  
  ;; For SSE/MMX support:
  ;; 30 This is `fix', guaranteed to be truncating.
***************
*** 13017,13022 ****
--- 13018,13052 ----
    ""
    "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
+      stack address we wish to restore.  */
+   tmp = gen_rtx_PLUS (Pmode, arg_pointer_rtx, sa);
+   tmp = plus_constant (tmp, -UNITS_PER_WORD);
+   tmp = gen_rtx_MEM (Pmode, tmp);
+   emit_move_insn (tmp, ra);
+ 
+   emit_insn (gen_eh_return_1 (sa));
+   emit_barrier ();
+   DONE;
+ }")
+ 
+ (define_insn_and_split "eh_return_1"
+   [(unspec_volatile [(match_operand 0 "register_operand" "c")] 13)]
+   ""
+   "#"
+   "reload_completed"
+   [(const_int 1)]
+   "ix86_expand_epilogue (2); DONE;")
+ 
  (define_insn "leave"
    [(set (reg:SI 7) (reg:SI 6))
     (set (reg:SI 6) (mem:SI (pre_dec:SI (reg:SI 7))))]
***************
*** 15751,15765 ****
  							    operands[1])));
  
    emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
-   DONE;
- }")
- 
- (define_expand "exception_receiver"
-   [(const_int 0)]
-   "flag_pic"
-   "
- {
-   load_pic_register ();
    DONE;
  }")
  
--- 15781,15786 ----
Index: config/i386/linux.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/linux.h,v
retrieving revision 1.24
diff -c -p -d -r1.24 linux.h
*** linux.h	2001/03/19 18:07:32	1.24
--- linux.h	2001/03/28 11:10:27
*************** Boston, MA 02111-1307, USA.  */
*** 188,190 ****
--- 188,252 ----
      }					\
    while (0)
  #endif
+ 
+ /* Do code reading to identify a signal frame, and set the frame
+    state data appropriately.  See unwind-dw2.c for the structs.  */
+ 
+ #ifdef IN_LIBGCC2
+ #include <signal.h>
+ #include <sys/ucontext.h>
+ #endif
+ 
+ #define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS)		\
+   do {									\
+     unsigned char *pc_ = (CONTEXT)->ra;					\
+     struct sigcontext *sc_;						\
+     long new_cfa_;							\
+ 									\
+     /* popl %eax ; movl $__NR_sigreturn,%eax ; int $0x80  */		\
+     if (*(unsigned short *)(pc_+0) == 0xb858				\
+ 	&& *(unsigned int *)(pc_+2) == 119				\
+ 	&& *(unsigned short *)(pc_+6) == 0x80cd)			\
+       sc_ = (CONTEXT)->cfa + 4;						\
+     /* movl $__NR_rt_sigreturn,%eax ; int $0x80  */			\
+     else if (*(unsigned char *)(pc_+0) == 0xb8				\
+ 	     && *(unsigned int *)(pc_+1) == 173				\
+ 	     && *(unsigned short *)(pc_+5) == 0x80cd)			\
+       {									\
+ 	struct rt_sigframe {						\
+ 	  int sig;							\
+ 	  struct siginfo *pinfo;					\
+ 	  void *puc;							\
+ 	  struct siginfo info;						\
+ 	  struct ucontext uc;						\
+ 	} *rt_ = (CONTEXT)->cfa;					\
+ 	sc_ = (struct sigcontext *) &rt_->uc.uc_mcontext;		\
+       }									\
+     else								\
+       break;								\
+ 									\
+     new_cfa_ = sc_->esp;						\
+     (FS)->cfa_how = CFA_REG_OFFSET;					\
+     (FS)->cfa_reg = 4;							\
+     (FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa;		\
+ 									\
+     /* The SVR4 register numbering macros aren't usable in libgcc.  */	\
+     (FS)->regs.reg[0].how = REG_SAVED_OFFSET;				\
+     (FS)->regs.reg[0].loc.offset = (long)&sc_->eax - new_cfa_;		\
+     (FS)->regs.reg[3].how = REG_SAVED_OFFSET;				\
+     (FS)->regs.reg[3].loc.offset = (long)&sc_->ebx - new_cfa_;		\
+     (FS)->regs.reg[1].how = REG_SAVED_OFFSET;				\
+     (FS)->regs.reg[1].loc.offset = (long)&sc_->ecx - new_cfa_;		\
+     (FS)->regs.reg[2].how = REG_SAVED_OFFSET;				\
+     (FS)->regs.reg[2].loc.offset = (long)&sc_->edx - new_cfa_;		\
+     (FS)->regs.reg[6].how = REG_SAVED_OFFSET;				\
+     (FS)->regs.reg[6].loc.offset = (long)&sc_->esi - new_cfa_;		\
+     (FS)->regs.reg[7].how = REG_SAVED_OFFSET;				\
+     (FS)->regs.reg[7].loc.offset = (long)&sc_->edi - new_cfa_;		\
+     (FS)->regs.reg[5].how = REG_SAVED_OFFSET;				\
+     (FS)->regs.reg[5].loc.offset = (long)&sc_->ebp - new_cfa_;		\
+     (FS)->regs.reg[8].how = REG_SAVED_OFFSET;				\
+     (FS)->regs.reg[8].loc.offset = (long)&sc_->eip - new_cfa_;		\
+     (FS)->retaddr_column = 8;						\
+     goto SUCCESS;							\
+   } while (0)


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