i386.c (general_no_elim_operand): Disallow virtual regs.
authorRichard Henderson <rth@redhat.com>
Wed, 28 Mar 2001 11:14:40 +0000 (03:14 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Wed, 28 Mar 2001 11:14:40 +0000 (03:14 -0800)
        * 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.

From-SVN: r40926

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/config/i386/i386.md
gcc/config/i386/linux.h

index 66122d4f86acef3473d19017d8858e2e9a9ca3b8..c94073eded9cd9e601806026a41a26ac105d92c3 100644 (file)
@@ -1,13 +1,24 @@
 2001-03-28  Richard Henderson  <rth@redhat.com>
 
-        * config/alpha/alpha.c (alpha_sa_mask): Add EH_RETURN_DATA_REGNOs.
-        (alpha_mark_machine_status): No eh_epilogue_sp_ofs ...
-        (alpha_expand_epilogue): ... use EH_RETURN_STACKADJ_RTX instead.
-        * config/alpha/alpha.h (machine_function): Remove eh_epilogue_sp_ofs.
-        (EH_RETURN_DATA_REGNO): New.
-        (EH_RETURN_STACKADJ_RTX, EH_RETURN_HANDLER_RTX): New.
-        * config/alpha/alpha.md (eh_epilogue): Remove.
-        (exception_receiver): Use $26 for ldgp input.
+       * 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.
+
+       * config/alpha/alpha.c (alpha_sa_mask): Add EH_RETURN_DATA_REGNOs.
+       (alpha_mark_machine_status): No eh_epilogue_sp_ofs ...
+       (alpha_expand_epilogue): ... use EH_RETURN_STACKADJ_RTX instead.
+       * config/alpha/alpha.h (machine_function): Remove eh_epilogue_sp_ofs.
+       (EH_RETURN_DATA_REGNO): New.
+       (EH_RETURN_STACKADJ_RTX, EH_RETURN_HANDLER_RTX): New.
+       * config/alpha/alpha.md (eh_epilogue): Remove.
+       (exception_receiver): Use $26 for ldgp input.
        * config/alpha/linux.h (MD_FALLBACK_FRAME_STATE_FOR): New.
 
 2001-03-28  Richard Henderson  <rth@redhat.com>
index b12d625652377a535d3dcf4953c794cc576d380c..57db899d641e216ea317cdb768ba5aebf74f95ad 100644 (file)
@@ -566,7 +566,7 @@ static int ix86_split_to_parts PARAMS ((rtx, rtx *, enum machine_mode));
 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_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 *));
@@ -606,7 +606,7 @@ static int ix86_fp_comparison_arithmetics_cost PARAMS ((enum rtx_code code));
 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 int ix86_save_reg PARAMS ((int, bool));
 static void ix86_compute_frame_layout PARAMS ((struct ix86_frame *));
 \f
 /* Sometimes certain combinations of command options do not make
@@ -1475,6 +1475,10 @@ general_no_elim_operand (op, mode)
       || 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);
 }
@@ -2249,17 +2253,35 @@ gen_push (arg)
 
 /* 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));
+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.  */
@@ -2271,7 +2293,7 @@ ix86_nsaved_regs ()
   int regno;
 
   for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
-    if (ix86_save_reg (regno))
+    if (ix86_save_reg (regno, true))
       nregs++;
   return nregs;
 }
@@ -2423,7 +2445,7 @@ ix86_emit_save_regs ()
   rtx insn;
 
   for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
-    if (ix86_save_reg (regno))
+    if (ix86_save_reg (regno, true))
       {
        insn = emit_insn (gen_push (gen_rtx_REG (Pmode, regno)));
        RTX_FRAME_RELATED_P (insn) = 1;
@@ -2535,14 +2557,15 @@ ix86_emit_epilogue_esp_adjustment (tsize)
 /* 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;
+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))
+    if (ix86_save_reg (regno, maybe_eh_return))
       {
        emit_move_insn (gen_rtx_REG (Pmode, regno),
                        adj_offsettable_operand (gen_rtx_MEM (Pmode,
@@ -2555,8 +2578,8 @@ ix86_emit_restore_regs_using_mov (pointer, offset)
 /* Restore function stack, frame, and registers.  */
 
 void
-ix86_expand_epilogue (emit_return)
-     int emit_return;
+ix86_expand_epilogue (style)
+     int style;
 {
   int regno;
   int sp_valid = !frame_pointer_needed || current_function_sp_is_unchanging;
@@ -2588,7 +2611,8 @@ ix86_expand_epilogue (emit_return)
   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))
+         && 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
@@ -2597,12 +2621,41 @@ ix86_expand_epilogue (emit_return)
         mode.  */
 
       if (!frame_pointer_needed || (sp_valid && !frame.to_allocate))
-       ix86_emit_restore_regs_using_mov (stack_pointer_rtx, 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);
+       ix86_emit_restore_regs_using_mov (hard_frame_pointer_rtx,
+                                         offset, style == 2);
 
-      if (!frame_pointer_needed)
-       ix86_emit_epilogue_esp_adjustment (frame.to_allocate + frame.nregs * UNITS_PER_WORD);
+      /* 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 ());
@@ -2635,7 +2688,7 @@ ix86_expand_epilogue (emit_return)
        ix86_emit_epilogue_esp_adjustment (frame.to_allocate);
 
       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
-       if (ix86_save_reg (regno))
+       if (ix86_save_reg (regno, false))
          {
            if (TARGET_64BIT)
              emit_insn (gen_popdi1 (gen_rtx_REG (Pmode, regno)));
@@ -2652,7 +2705,7 @@ ix86_expand_epilogue (emit_return)
     }
 
   /* Sibcall epilogues don't want a return instruction.  */
-  if (! emit_return)
+  if (style == 0)
     return;
 
   if (current_function_pops_args && current_function_args_size)
index 1552b413efce98dda5bba80c01685aad8c7fc4bb..cd9e54aa607c212930d7d3955bb0171326dbd772 100644 (file)
@@ -2779,10 +2779,10 @@ extern int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER];
   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)))
+#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)
@@ -2790,6 +2790,10 @@ extern int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER];
 /* 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 8f6c36b31157087ca7156e5d8882d239f258a07c..0d61b8eaf26e1d6decdec37924a8681f2bc1dbeb 100644 (file)
@@ -73,6 +73,7 @@
 ;; 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.
   ""
   "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))))]
   DONE;
 }")
 
-(define_expand "exception_receiver"
-  [(const_int 0)]
-  "flag_pic"
-  "
-{
-  load_pic_register ();
-  DONE;
-}")
-
 (define_expand "builtin_setjmp_receiver"
   [(label_ref (match_operand 0 "" ""))]
   "flag_pic"
index a5c725a334a8c3460696668e6740aa5c631a01e3..138a2469117822bd7c5d741ae5836053db49006d 100644 (file)
@@ -188,3 +188,65 @@ Boston, MA 02111-1307, USA.  */
     }                                  \
   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)