Deal with -fpic and inlined functions
authorMichael Meissner <meissner@gcc.gnu.org>
Thu, 11 Jul 1996 22:36:45 +0000 (22:36 +0000)
committerMichael Meissner <meissner@gcc.gnu.org>
Thu, 11 Jul 1996 22:36:45 +0000 (22:36 +0000)
From-SVN: r12428

gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h

index 921bc18664e86367e2f7c66b7ffc05510ead5d2c..536e1e404dd167744fa50fdcc31a4890dd20aade 100644 (file)
@@ -372,24 +372,6 @@ rs6000_immed_double_const (i0, i1, mode)
   return immed_double_const (i0, i1, mode);
 }
 
-\f
-/* Return the GOT register, creating it if needed.  */
-
-struct rtx_def *
-rs6000_got_register (value)
-     rtx value;
-{
-  if (!pic_offset_table_rtx)
-    {
-      if (reload_in_progress || reload_completed)
-       fatal_insn ("internal error -- needed new GOT register during reload phase to load:", value);
-
-      pic_offset_table_rtx = gen_reg_rtx (SImode);
-    }
-
-  return pic_offset_table_rtx;
-}
-
 \f
 /* Return non-zero if this function is known to have a null epilogue.  */
 
@@ -2077,6 +2059,81 @@ ccr_bit (op, scc_p)
       abort ();
     }
 }
+\f
+/* Return the GOT register, creating it if needed.  */
+
+struct rtx_def *
+rs6000_got_register (value)
+     rtx value;
+{
+  if (!pic_offset_table_rtx)
+    {
+      if (reload_in_progress || reload_completed)
+       fatal_insn ("internal error -- needed new GOT register during reload phase to load:", value);
+
+      current_function_uses_pic_offset_table = 1;
+      pic_offset_table_rtx = gen_rtx (REG, Pmode, GOT_TOC_REGNUM);
+    }
+
+  return pic_offset_table_rtx;
+}
+
+\f
+/* Replace all occurances of register FROM with an new pseduo register in an insn X.
+   Store the pseudo register used in REG.
+   This is only safe during FINALIZE_PIC, since the registers haven't been setup
+   yet.  */
+
+static rtx
+rs6000_replace_regno (x, from, reg)
+     rtx x;
+     int from;
+     rtx *reg;
+{
+  register int i, j;
+  register char *fmt;
+
+  /* Allow this function to make replacements in EXPR_LISTs.  */
+  if (!x)
+    return x;
+
+  switch (GET_CODE (x))
+    {
+    case SCRATCH:
+    case PC:
+    case CC0:
+    case CONST_INT:
+    case CONST_DOUBLE:
+    case CONST:
+    case SYMBOL_REF:
+    case LABEL_REF:
+      return x;
+
+    case REG:
+      if (REGNO (x) == from)
+       {
+         if (! *reg)
+           *reg = gen_reg_rtx (Pmode);
+
+         return *reg;
+       }
+
+      return x;
+    }
+
+  fmt = GET_RTX_FORMAT (GET_CODE (x));
+  for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
+    {
+      if (fmt[i] == 'e')
+       XEXP (x, i) = rs6000_replace_regno (XEXP (x, i), from, reg);
+      else if (fmt[i] == 'E')
+       for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+         XVECEXP (x, i, j) = rs6000_replace_regno (XVECEXP (x, i, j), from, reg);
+    }
+
+  return x;
+}  
+
 \f
 /* By generating position-independent code, when two different
    programs (A and B) share a common library (libC.a), the text of
@@ -2098,17 +2155,39 @@ rs6000_finalize_pic ()
 {
   if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
     {
-      /* If a PIC register has been created, insert the pic initialization
-        at the function beginning.  */
-      if (pic_offset_table_rtx)
+      /* Loop through all of the insns, replacing the special GOT_TOC_REGNUM
+        with an appropriate pseduo register.  If we find we need GOT/TOC,
+        add the appropriate init code.  */
+      if (flag_pic)
        {
          rtx insn = get_insns ();
-         rtx init = gen_init_v4_pic (pic_offset_table_rtx);
+         rtx reg = NULL_RTX;
+         rtx first_insn;
 
          if (GET_CODE (insn) == NOTE)
            insn = next_nonnote_insn (insn);
 
-         emit_insn_before (init, insn);
+         first_insn = insn;
+         for ( ; insn != NULL_RTX; insn = NEXT_INSN (insn))
+           {
+             if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+               {
+                 PATTERN (insn) = rs6000_replace_regno (PATTERN (insn),
+                                                        GOT_TOC_REGNUM,
+                                                        &reg);
+
+                 if (REG_NOTES (insn))
+                   REG_NOTES (insn) = rs6000_replace_regno (REG_NOTES (insn),
+                                                            GOT_TOC_REGNUM,
+                                                            &reg);
+               }
+           }
+
+         if (reg)
+           {
+             rtx init = gen_init_v4_pic (reg);
+             emit_insn_before (init, first_insn);
+           }
        }
     }
 }
index f291bae62a39d892db5ff4bb755a8d8a8163e895..58632eb9b3460369add533ec807fd238e1d4690f 100644 (file)
@@ -847,10 +847,16 @@ extern struct rs6000_cpu_select rs6000_select[];
 /* Special register that represents memory, used for float/int conversions.  */
 #define FPMEM_REGNUM 76
 
+/* Register to use as a placeholder for the GOT/allocated TOC register.
+   FINALIZE_PIC will change all uses of this register to a an appropriate
+   pseudo register when it adds the code to setup the GOT.  We use r2
+   because it is a reserved register in all of the ABI's.  */
+#define GOT_TOC_REGNUM 2
+
 /* Place that structure value return address is placed.
 
    On the RS/6000, it is passed as an extra parameter.  */
-#define STRUCT_VALUE   0
+#define STRUCT_VALUE 0
 \f
 /* Define the classes of registers for register constraints in the
    machine description.  Also define ranges of constants.