re PR target/11535 (__builtin_return_address may not work on ia64)
authorRichard Henderson <rth@redhat.com>
Fri, 8 Aug 2003 23:49:57 +0000 (16:49 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Fri, 8 Aug 2003 23:49:57 +0000 (16:49 -0700)
        PR target/11535
        * config/ia64/ia64.c (ia64_initial_elimination_offset): Remove
        RETURN_ADDRESS_POINTER_REGNUM.
        (ia64_expand_prologue): Don't frob it.
        (ia64_output_function_epilogue): Likewise.
        (ia64_return_addr_rtx): New.
        (ia64_split_return_addr_rtx): New.
        * config/ia64/ia64-protos.h: Update.
        * config/ia64/ia64.h (FIRST_PSEUDO_REGISTER): Decrement.
        (RETURN_ADDRESS_POINTER_REGNUM): Remove.
        (GENERAL_REGNO_P): Don't check it.
        (AR_*_REGNUM): Renumber.
        (FIXED_REGISTERS): Remove RETURN_ADDRESS_POINTER_REGNUM.
        (CALL_USED_REGISTERS, CALL_REALLY_USED_REGISTERS): Likewise.
        (REG_ALLOC_ORDER, REG_CLASS_CONTENTS): Likewise.
        (ELIMINABLE_REGS, REGISTER_NAMES): Likewise.
        (RETURN_ADDR_RTX): Use ia64_return_addr_rtx.
        * config/ia64/ia64.md (UNSPEC_RET_ADDR): New.
        (movdi_ret_addr): New.

From-SVN: r70263

gcc/ChangeLog
gcc/config/ia64/ia64-protos.h
gcc/config/ia64/ia64.c
gcc/config/ia64/ia64.h
gcc/config/ia64/ia64.md

index fc9d95c5f3aa5a2cd013e15ec776f0501ac5a3dd..7663d3afefa891746b39b1c6707efb22ca7bb3dc 100644 (file)
@@ -1,3 +1,25 @@
+2003-08-08  Richard Henderson  <rth@redhat.com>
+
+        PR target/11535
+        * config/ia64/ia64.c (ia64_initial_elimination_offset): Remove 
+        RETURN_ADDRESS_POINTER_REGNUM.
+        (ia64_expand_prologue): Don't frob it.
+        (ia64_output_function_epilogue): Likewise.
+        (ia64_return_addr_rtx): New.
+        (ia64_split_return_addr_rtx): New.
+        * config/ia64/ia64-protos.h: Update.
+        * config/ia64/ia64.h (FIRST_PSEUDO_REGISTER): Decrement.
+        (RETURN_ADDRESS_POINTER_REGNUM): Remove.
+        (GENERAL_REGNO_P): Don't check it.
+        (AR_*_REGNUM): Renumber.
+        (FIXED_REGISTERS): Remove RETURN_ADDRESS_POINTER_REGNUM.
+        (CALL_USED_REGISTERS, CALL_REALLY_USED_REGISTERS): Likewise.
+        (REG_ALLOC_ORDER, REG_CLASS_CONTENTS): Likewise.
+        (ELIMINABLE_REGS, REGISTER_NAMES): Likewise.
+        (RETURN_ADDR_RTX): Use ia64_return_addr_rtx.
+        * config/ia64/ia64.md (UNSPEC_RET_ADDR): New.
+        (movdi_ret_addr): New.
+
 2003-08-08  Geoffrey Keating  <geoffk@apple.com>
 
        * config.gcc (powerpc-*-darwin*): Don't build a soft-float multilib.
index 030c5ed667b54bd7bdd3b8c60d5c7af5170f024e..4f89f48f9bdf9c76bf76fdc5bc5645f16d1d4e05 100644 (file)
@@ -139,6 +139,9 @@ extern void ia64_init_builtins PARAMS((void));
 extern void ia64_override_options PARAMS((void));
 extern int ia64_dbx_register_number PARAMS((int));
 
+extern rtx ia64_return_addr_rtx PARAMS ((HOST_WIDE_INT, rtx));
+extern void ia64_split_return_addr_rtx PARAMS ((rtx));
+
 #ifdef SDATA_SECTION_ASM_OP
 extern void sdata_section PARAMS ((void));
 #endif
index f2e27d0105fff111af0bbd947a07f59765c92af8..5a101287ea8bee5517f45f2cbeff6fc21092d69b 100644 (file)
@@ -2197,10 +2197,6 @@ ia64_initial_elimination_offset (from, to)
        abort ();
       break;
 
-    case RETURN_ADDRESS_POINTER_REGNUM:
-      offset = 0;
-      break;
-
     default:
       abort ();
     }
@@ -2551,17 +2547,6 @@ ia64_expand_prologue ()
       reg_names[current_frame_info.reg_fp] = tmp;
     }
 
-  /* Fix up the return address placeholder.  */
-  /* ??? We can fail if __builtin_return_address is used, and we didn't
-     allocate a register in which to save b0.  I can't think of a way to
-     eliminate RETURN_ADDRESS_POINTER_REGNUM to a local register and
-     then be sure that I got the right one.  Further, reload doesn't seem
-     to care if an eliminable register isn't used, and "eliminates" it
-     anyway.  */
-  if (regs_ever_live[RETURN_ADDRESS_POINTER_REGNUM]
-      && current_frame_info.reg_save_b0 != 0)
-    XINT (return_address_pointer_rtx, 0) = current_frame_info.reg_save_b0;
-
   /* We don't need an alloc instruction if we've used no outputs or locals.  */
   if (current_frame_info.n_local_regs == 0
       && current_frame_info.n_output_regs == 0
@@ -3118,6 +3103,72 @@ ia64_direct_return ()
   return 0;
 }
 
+/* Return the magic cookie that we use to hold the return address
+   during early compilation.  */
+
+rtx
+ia64_return_addr_rtx (count, frame)
+     HOST_WIDE_INT count;
+     rtx frame ATTRIBUTE_UNUSED;
+{
+  if (count != 0)
+    return NULL;
+  return gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_RET_ADDR);
+}
+
+/* Split this value after reload, now that we know where the return
+   address is saved.  */
+
+void
+ia64_split_return_addr_rtx (dest)
+     rtx dest;
+{
+  rtx src;
+
+  if (TEST_HARD_REG_BIT (current_frame_info.mask, BR_REG (0)))
+    {
+      if (current_frame_info.reg_save_b0 != 0)
+       src = gen_rtx_REG (DImode, current_frame_info.reg_save_b0);
+      else
+       {
+         HOST_WIDE_INT off;
+         unsigned int regno;
+
+         /* Compute offset from CFA for BR0.  */
+         /* ??? Must be kept in sync with ia64_expand_prologue.  */
+         off = (current_frame_info.spill_cfa_off
+                + current_frame_info.spill_size);
+         for (regno = GR_REG (1); regno <= GR_REG (31); ++regno)
+           if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
+             off -= 8;
+
+         /* Convert CFA offset to a register based offset.  */
+         if (frame_pointer_needed)
+           src = hard_frame_pointer_rtx;
+         else
+           {
+             src = stack_pointer_rtx;
+             off += current_frame_info.total_size;
+           }
+
+         /* Load address into scratch register.  */
+         if (CONST_OK_FOR_I (off))
+           emit_insn (gen_adddi3 (dest, src, GEN_INT (off)));
+         else
+           {
+             emit_move_insn (dest, GEN_INT (off));
+             emit_insn (gen_adddi3 (dest, src, dest));
+           }
+
+         src = gen_rtx_MEM (Pmode, dest);
+       }
+    }
+  else
+    src = gen_rtx_REG (DImode, BR_REG (0));
+
+  emit_move_insn (dest, src);
+}
+
 int
 ia64_hard_regno_rename_ok (from, to)
      int from;
@@ -3267,9 +3318,6 @@ ia64_output_function_epilogue (file, size)
 {
   int i;
 
-  /* Reset from the function's potential modifications.  */
-  XINT (return_address_pointer_rtx, 0) = RETURN_ADDRESS_POINTER_REGNUM;
-
   if (current_frame_info.reg_fp)
     {
       const char *tmp = reg_names[HARD_FRAME_POINTER_REGNUM];
index fe2c8038ebf0501a9a80ab975deba23aedd31391..a8bc569a7f05ea35f0d343a85ab018f39d0b7769 100644 (file)
@@ -455,7 +455,7 @@ while (0)
    64 predicate registers, 8 branch registers, one frame pointer,
    and several "application" registers.  */
 
-#define FIRST_PSEUDO_REGISTER 335
+#define FIRST_PSEUDO_REGISTER 334
 
 /* Ranges for the various kinds of registers.  */
 #define ADDL_REGNO_P(REGNO) ((unsigned HOST_WIDE_INT) (REGNO) <= 3)
@@ -464,9 +464,7 @@ while (0)
 #define PR_REGNO_P(REGNO) ((REGNO) >= 256 && (REGNO) <= 319)
 #define BR_REGNO_P(REGNO) ((REGNO) >= 320 && (REGNO) <= 327)
 #define GENERAL_REGNO_P(REGNO) \
-  (GR_REGNO_P (REGNO)                                                  \
-   || (REGNO) == FRAME_POINTER_REGNUM                                  \
-   || (REGNO) == RETURN_ADDRESS_POINTER_REGNUM)
+  (GR_REGNO_P (REGNO) || (REGNO) == FRAME_POINTER_REGNUM)
 
 #define GR_REG(REGNO) ((REGNO) + 0)
 #define FR_REG(REGNO) ((REGNO) + 128)
@@ -476,11 +474,11 @@ while (0)
 #define IN_REG(REGNO) ((REGNO) + 112)
 #define LOC_REG(REGNO) ((REGNO) + 32)
 
-#define AR_CCV_REGNUM  330
-#define AR_UNAT_REGNUM  331
-#define AR_PFS_REGNUM  332
-#define AR_LC_REGNUM   333
-#define AR_EC_REGNUM   334
+#define AR_CCV_REGNUM  329
+#define AR_UNAT_REGNUM  330
+#define AR_PFS_REGNUM  331
+#define AR_LC_REGNUM   332
+#define AR_EC_REGNUM   333
 
 #define IN_REGNO_P(REGNO) ((REGNO) >= IN_REG (0) && (REGNO) <= IN_REG (7))
 #define LOC_REGNO_P(REGNO) ((REGNO) >= LOC_REG (0) && (REGNO) <= LOC_REG (79))
@@ -543,8 +541,8 @@ while (0)
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,      \
   /* Branch registers.  */                             \
   0, 0, 0, 0, 0, 0, 0, 0,                              \
-  /*FP RA CCV UNAT PFS LC EC */                                \
-     1, 1,  1,   1,  1, 0, 1                           \
+  /*FP CCV UNAT PFS LC EC */                           \
+     1,  1,   1,  1, 0, 1                              \
  }
 
 /* Like `FIXED_REGISTERS' but has 1 for each register that is clobbered
@@ -578,8 +576,8 @@ while (0)
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,      \
   /* Branch registers.  */                             \
   1, 0, 0, 0, 0, 0, 1, 1,                              \
-  /*FP RA CCV UNAT PFS LC EC */                                \
-     1, 1,  1,   1,  1, 0, 1                           \
+  /*FP CCV UNAT PFS LC EC */                           \
+     1,  1,   1,  1, 0, 1                              \
 }
 
 /* Like `CALL_USED_REGISTERS' but used to overcome a historical
@@ -616,8 +614,8 @@ while (0)
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,      \
   /* Branch registers.  */                             \
   1, 0, 0, 0, 0, 0, 1, 1,                              \
-  /*FP RA CCV UNAT PFS LC EC */                                \
-     0, 0,  1,   0,  1, 0, 0                           \
+  /*FP CCV UNAT PFS LC EC */                           \
+     0,  1,   0,  1, 0, 0                              \
 }
 
 
@@ -763,7 +761,7 @@ while (0)
   /* Special branch registers.  */                                        \
   R_BR (0),                                                               \
   /* Other fixed registers.  */                                                   \
-  FRAME_POINTER_REGNUM, RETURN_ADDRESS_POINTER_REGNUM,                    \
+  FRAME_POINTER_REGNUM,                                                   \
   AR_CCV_REGNUM, AR_UNAT_REGNUM, AR_PFS_REGNUM, AR_LC_REGNUM,             \
   AR_EC_REGNUM                                                            \
 }
@@ -892,11 +890,11 @@ enum reg_class
   /* AR_M_REGS.  */                                    \
   { 0x00000000, 0x00000000, 0x00000000, 0x00000000,    \
     0x00000000, 0x00000000, 0x00000000, 0x00000000,    \
-    0x00000000, 0x00000000, 0x0C00 },                  \
+    0x00000000, 0x00000000, 0x0600 },                  \
   /* AR_I_REGS.  */                                    \
   { 0x00000000, 0x00000000, 0x00000000, 0x00000000,    \
     0x00000000, 0x00000000, 0x00000000, 0x00000000,    \
-    0x00000000, 0x00000000, 0x7000 },                  \
+    0x00000000, 0x00000000, 0x3800 },                  \
   /* ADDL_REGS.  */                                    \
   { 0x0000000F, 0x00000000, 0x00000000, 0x00000000,    \
     0x00000000, 0x00000000, 0x00000000, 0x00000000,    \
@@ -904,7 +902,7 @@ enum reg_class
   /* GR_REGS.  */                                      \
   { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,    \
     0x00000000, 0x00000000, 0x00000000, 0x00000000,    \
-    0x00000000, 0x00000000, 0x0300 },                  \
+    0x00000000, 0x00000000, 0x0100 },                  \
   /* FR_REGS.  */                                      \
   { 0x00000000, 0x00000000, 0x00000000, 0x00000000,    \
     0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,    \
@@ -912,15 +910,15 @@ enum reg_class
   /* GR_AND_BR_REGS.  */                               \
   { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,    \
     0x00000000, 0x00000000, 0x00000000, 0x00000000,    \
-    0x00000000, 0x00000000, 0x03FF },                  \
+    0x00000000, 0x00000000, 0x01FF },                  \
   /* GR_AND_FR_REGS.  */                               \
   { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,    \
     0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,    \
-    0x00000000, 0x00000000, 0x0300 },                  \
+    0x00000000, 0x00000000, 0x0100 },                  \
   /* ALL_REGS.  */                                     \
   { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,    \
     0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,    \
-    0xFFFFFFFF, 0xFFFFFFFF, 0x7FFF },                  \
+    0xFFFFFFFF, 0xFFFFFFFF, 0x3FFF },                  \
 }
 
 /* A C expression whose value is a register class containing hard register
@@ -1142,7 +1140,7 @@ enum reg_class
    DYNAMIC_CHAIN_ADDRESS and SETUP_FRAME_ADDRESS (for the reg stack flush).  */
 
 #define RETURN_ADDR_RTX(COUNT, FRAME) \
-  ((COUNT) == 0 ? return_address_pointer_rtx : const0_rtx)
+  ia64_return_addr_rtx (COUNT, FRAME)
 
 /* A C expression whose value is RTL representing the location of the incoming
    return address at the beginning of any function, before the prologue.  This
@@ -1203,13 +1201,6 @@ enum reg_class
       REGNO_POINTER_ALIGN (ARG_POINTER_REGNUM) = 64;   \
   } while (0)
 
-/* The register number for the return address register.  For IA-64, this
-   is not actually a pointer as the name suggests, but that's a name that
-   gen_rtx_REG already takes care to keep unique.  We modify
-   return_address_pointer_rtx in ia64_expand_prologue to reference the
-   final output regnum.  */
-#define RETURN_ADDRESS_POINTER_REGNUM 329
-
 /* Register numbers used for passing a function's static chain pointer.  */
 /* ??? The ABI sez the static chain should be passed as a normal parameter.  */
 #define STATIC_CHAIN_REGNUM 15
@@ -1233,7 +1224,6 @@ enum reg_class
   {ARG_POINTER_REGNUM,  HARD_FRAME_POINTER_REGNUM},                    \
   {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},                                \
   {FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},                   \
-  {RETURN_ADDRESS_POINTER_REGNUM, BR_REG (0)},                         \
 }
 
 /* A C expression that returns nonzero if the compiler is allowed to try to
@@ -1879,8 +1869,8 @@ do {                                                                      \
   "p60", "p61", "p62", "p63",                                          \
   /* Branch registers.  */                                             \
   "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7",                      \
-  /* Frame pointer.  Return address.  */                               \
-  "sfp", "retaddr", "ar.ccv", "ar.unat", "ar.pfs", "ar.lc", "ar.ec",   \
+  /* Frame pointer.  Application registers.  */                                \
+  "sfp", "ar.ccv", "ar.unat", "ar.pfs", "ar.lc", "ar.ec",      \
 }
 
 /* If defined, a C initializer for an array of structures containing a name and
index faff0ee5c55fd1d9cf0c9271dbba55dfd41f7e5e..0d0999fa6dbd9b00f6719cc2feeced0229c4a01e 100644 (file)
@@ -73,6 +73,7 @@
    (UNSPEC_BUNDLE_SELECTOR     23)
    (UNSPEC_ADDP4               24)
    (UNSPEC_PROLOGUE_USE                25)
+   (UNSPEC_RET_ADDR            26)
   ])
 
 (define_constants
   operands[3] = pic_offset_table_rtx;
 })
 
+;; This is used as a placeholder for the return address during early
+;; compilation.  We won't know where we've placed this until during
+;; reload, at which point it can wind up in b0, a general register,
+;; or memory.  The only safe destination under these conditions is a
+;; general register.
+
+(define_insn_and_split "*movdi_ret_addr"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (unspec:DI [(const_int 0)] UNSPEC_RET_ADDR))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+{
+  ia64_split_return_addr_rtx (operands[0]);
+  DONE;
+}
+  [(set_attr "itanium_class" "ialu")])
+
 (define_insn "*load_symptr_high"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (plus:DI (high:DI (match_operand 1 "got_symbolic_operand" "s"))