OSDN Git Service

* reload.c (operands_match_p): Handle rtvecs.
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 25 Aug 1998 12:23:51 +0000 (12:23 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 25 Aug 1998 12:23:51 +0000 (12:23 +0000)
        * i386.c (legitimate_pic_address_disp_p): New.
        (legitimate_address_p): Use it.
        (legitimize_pic_address): Use unspecs to represent @GOT and @GOTOFF.
        Handle constant pool symbols just like statics.
        (emit_pic_move): Use Pmode not SImode for clarity.
        (output_pic_addr_const) [SYMBOL_REF]: Remove @GOT and @GOTOFF hacks.
        [UNSPEC]: New, handling what we killed above.
        [PLUS]: Detect and abort on invalid symbol arithmetic.
        * i386.h (CONSTANT_ADDRESS_P): Remove HIGH.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@21968 138bc75d-0d04-0410-961f-82ee72b054a4

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

index c7197ec..4e1dd65 100644 (file)
@@ -1,3 +1,17 @@
+Tue Aug 25 12:23:20 PDT 1998  Richard Henderson  <rth@cygnus.com>
+
+        * reload.c (operands_match_p): Handle rtvecs.
+
+        * i386.c (legitimate_pic_address_disp_p): New.
+        (legitimate_address_p): Use it.
+        (legitimize_pic_address): Use unspecs to represent @GOT and @GOTOFF.
+        Handle constant pool symbols just like statics.
+        (emit_pic_move): Use Pmode not SImode for clarity.
+        (output_pic_addr_const) [SYMBOL_REF]: Remove @GOT and @GOTOFF hacks.
+        [UNSPEC]: New, handling what we killed above.
+        [PLUS]: Detect and abort on invalid symbol arithmetic.
+        * i386.h (CONSTANT_ADDRESS_P): Remove HIGH.
+
 Tue Aug 25 12:02:23 1998  Mark Mitchell  <mark@markmitchell.com>
 
        * alias.c: Include output.h.
index 73036ea..b316130 100644 (file)
@@ -2507,6 +2507,37 @@ do {                                                                     \
     }                                                                  \
 } while (0)
 
+static int
+legitimate_pic_address_disp_p (disp)
+     register rtx disp;
+{
+  if (GET_CODE (disp) != CONST)
+    return 0;
+  disp = XEXP (disp, 0);
+
+  if (GET_CODE (disp) == PLUS)
+    {
+      if (GET_CODE (XEXP (disp, 1)) != CONST_INT)
+       return 0;
+      disp = XEXP (disp, 0);
+    }
+
+  if (GET_CODE (disp) != UNSPEC
+      || XVECLEN (disp, 0) != 1)
+    return 0;
+
+  /* Must be @GOT or @GOTOFF.  */
+  if (XINT (disp, 1) != 6
+      && XINT (disp, 1) != 7)
+    return 0;
+
+  if (GET_CODE (XVECEXP (disp, 0, 0)) != SYMBOL_REF
+      && GET_CODE (XVECEXP (disp, 0, 0)) != LABEL_REF)
+    return 0;
+
+  return 1;
+}
+
 int
 legitimate_address_p (mode, addr, strict)
      enum machine_mode mode;
@@ -2668,20 +2699,10 @@ legitimate_address_p (mode, addr, strict)
        }
     }
 
-  /* Validate displacement
-     Constant pool addresses must be handled special.  They are
-     considered legitimate addresses, but only if not used with regs.
-     When printed, the output routines know to print the reference with the
-     PIC reg, even though the PIC reg doesn't appear in the RTL. */
+  /* Validate displacement.  */
   if (disp)
     {
-      if (GET_CODE (disp) == SYMBOL_REF
-         && CONSTANT_POOL_ADDRESS_P (disp)
-         && base == 0
-         && indx == 0)
-       ;
-
-      else if (!CONSTANT_ADDRESS_P (disp))
+      if (!CONSTANT_ADDRESS_P (disp))
        {
          ADDR_INVALID ("Displacement is not valid.\n", disp);
          return FALSE;
@@ -2693,20 +2714,32 @@ legitimate_address_p (mode, addr, strict)
          return FALSE;
        }
 
-      else if (flag_pic && SYMBOLIC_CONST (disp)
-              && base != pic_offset_table_rtx
-              && (indx != pic_offset_table_rtx || scale != NULL_RTX))
+      if (flag_pic && SYMBOLIC_CONST (disp))
        {
-         ADDR_INVALID ("Displacement is an invalid pic reference.\n", disp);
-         return FALSE;
+         if (! legitimate_pic_address_disp_p (disp))
+           {
+             ADDR_INVALID ("Displacement is an invalid PIC construct.\n",
+                           disp);
+             return FALSE;
+           }
+
+         if (base != pic_offset_table_rtx
+             && (indx != pic_offset_table_rtx || scale != NULL_RTX))
+           {
+             ADDR_INVALID ("PIC displacement against invalid base.\n", disp);
+             return FALSE;
+           }
        }
 
-      else if (HALF_PIC_P () && HALF_PIC_ADDRESS_P (disp)
-              && (base != NULL_RTX || indx != NULL_RTX))
+      else if (HALF_PIC_P ())
        {
-         ADDR_INVALID ("Displacement is an invalid half-pic reference.\n",
-                       disp);
-         return FALSE;
+         if (! HALF_PIC_ADDRESS_P (disp)
+             || (base != NULL_RTX || indx != NULL_RTX))
+           {
+             ADDR_INVALID ("Displacement is an invalid half-pic reference.\n",
+                           disp);
+             return FALSE;
+           }
        }
     }
 
@@ -2720,29 +2753,20 @@ legitimate_address_p (mode, addr, strict)
 /* Return a legitimate reference for ORIG (an address) using the
    register REG.  If REG is 0, a new pseudo is generated.
 
-   There are three types of references that must be handled:
+   There are two types of references that must be handled:
 
    1. Global data references must load the address from the GOT, via
       the PIC reg.  An insn is emitted to do this load, and the reg is
       returned.
 
-   2. Static data references must compute the address as an offset
-      from the GOT, whose base is in the PIC reg.  An insn is emitted to
-      compute the address into a reg, and the reg is returned.  Static
-      data objects have SYMBOL_REF_FLAG set to differentiate them from
-      global data objects.
-
-   3. Constant pool addresses must be handled special.  They are
-      considered legitimate addresses, but only if not used with regs.
-      When printed, the output routines know to print the reference with the
-      PIC reg, even though the PIC reg doesn't appear in the RTL.
+   2. Static data references, constant pool addresses, and code labels
+      compute the address as an offset from the GOT, whose base is in
+      the PIC reg.  Static data objects have SYMBOL_REF_FLAG set to
+      differentiate them from global data objects.  The returned
+      address is the PIC reg + an unspec constant.
 
    GO_IF_LEGITIMATE_ADDRESS rejects symbolic references unless the PIC
-   reg also appears in the address (except for constant pool references,
-   noted above).
-
-   "switch" statements also require special handling when generating
-   PIC code.  See comments by the `casesi' insn in i386.md for details.  */
+   reg also appears in the address.  */
 
 rtx
 legitimize_pic_address (orig, reg)
@@ -2751,60 +2775,99 @@ legitimize_pic_address (orig, reg)
 {
   rtx addr = orig;
   rtx new = orig;
+  rtx base;
 
-  if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
+  if (GET_CODE (addr) == LABEL_REF
+      || (GET_CODE (addr) == SYMBOL_REF
+         && (CONSTANT_POOL_ADDRESS_P (addr)
+             || SYMBOL_REF_FLAG (addr))))
     {
-      if (GET_CODE (addr) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (addr))
-       reg = new = orig;
-      else
-       {
-         if (reg == 0)
-           reg = gen_reg_rtx (Pmode);
+      /* This symbol may be referenced via a displacement from the PIC
+        base address (@GOTOFF).  */
 
-         if ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FLAG (addr))
-             || GET_CODE (addr) == LABEL_REF)
-           new = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig);
-         else
-           new = gen_rtx_MEM (Pmode,
-                          gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig));
+      current_function_uses_pic_offset_table = 1;
+      new = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, addr), 7);
+      new = gen_rtx_CONST (VOIDmode, new);
+      new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
 
+      if (reg != 0)
+       {
          emit_move_insn (reg, new);
+         new = reg;
        }
-      current_function_uses_pic_offset_table = 1;
-      return reg;
     }
-
-  else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
+  else if (GET_CODE (addr) == SYMBOL_REF)
     {
-      rtx base;
+      /* This symbol must be referenced via a load from the
+        Global Offset Table (@GOT). */
+
+      current_function_uses_pic_offset_table = 1;
+      new = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, addr), 6);
+      new = gen_rtx_CONST (VOIDmode, new);
+      new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
+      new = gen_rtx_MEM (Pmode, new);
+      RTX_UNCHANGING_P (new) = 1;
 
+      if (reg == 0)
+       reg = gen_reg_rtx (Pmode);
+      emit_move_insn (reg, new);
+      new = reg;
+    }      
+  else
+    {
       if (GET_CODE (addr) == CONST)
        {
          addr = XEXP (addr, 0);
-         if (GET_CODE (addr) != PLUS)
-           abort ();
+         if (GET_CODE (addr) == UNSPEC)
+           {
+             /* Check that the unspec is one of the ones we generate?  */
+           }
+         else if (GET_CODE (addr) != PLUS)
+           abort();
        }
+      if (GET_CODE (addr) == PLUS)
+       {
+         rtx op0 = XEXP (addr, 0), op1 = XEXP (addr, 1);
+
+         /* Check first to see if this is a constant offset from a @GOTOFF
+            symbol reference.  */
+         if ((GET_CODE (op0) == LABEL_REF
+              || (GET_CODE (op0) == SYMBOL_REF
+                  && (CONSTANT_POOL_ADDRESS_P (op0)
+                      || SYMBOL_REF_FLAG (op0))))
+             && GET_CODE (op1) == CONST_INT)
+           {
+             current_function_uses_pic_offset_table = 1;
+             new = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, op0), 7);
+             new = gen_rtx_PLUS (VOIDmode, new, op1);
+             new = gen_rtx_CONST (VOIDmode, new);
+             new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
 
-      if (XEXP (addr, 0) == pic_offset_table_rtx)
-       return orig;
-
-      if (reg == 0)
-       reg = gen_reg_rtx (Pmode);
-
-      base = legitimize_pic_address (XEXP (addr, 0), reg);
-      addr = legitimize_pic_address (XEXP (addr, 1),
-                                    base == reg ? NULL_RTX : reg);
-
-      if (GET_CODE (addr) == CONST_INT)
-       return plus_constant (base, INTVAL (addr));
+             if (reg != 0)
+               {
+                 emit_move_insn (reg, new);
+                 new = reg;
+               }
+           }
+         else
+           {
+             base = legitimize_pic_address (XEXP (addr, 0), reg);
+             new  = legitimize_pic_address (XEXP (addr, 1),
+                                            base == reg ? NULL_RTX : reg);
 
-      if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
-       {
-         base = gen_rtx (PLUS, Pmode, base, XEXP (addr, 0));
-         addr = XEXP (addr, 1);
+             if (GET_CODE (new) == CONST_INT)
+               new = plus_constant (base, INTVAL (new));
+             else
+               {
+                 if (GET_CODE (new) == PLUS && CONSTANT_P (XEXP (new, 1)))
+                   {
+                     base = gen_rtx_PLUS (Pmode, base, XEXP (new, 0));
+                     new = XEXP (new, 1);
+                   }
+                 new = gen_rtx_PLUS (Pmode, base, new);
+               }
+           }
        }
-
-      return gen_rtx (PLUS, Pmode, base, addr);
     }
   return new;
 }
@@ -2819,7 +2882,7 @@ emit_pic_move (operands, mode)
   rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
 
   if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
-    operands[1] = force_reg (SImode, operands[1]);
+    operands[1] = force_reg (Pmode, operands[1]);
   else
     operands[1] = legitimize_pic_address (operands[1], temp);
 }
@@ -3032,31 +3095,14 @@ output_pic_addr_const (file, x, code)
       break;
 
     case SYMBOL_REF:
-    case LABEL_REF:
-      if (GET_CODE (x) == SYMBOL_REF)
-       assemble_name (file, XSTR (x, 0));
-      else
-       {
-         ASM_GENERATE_INTERNAL_LABEL (buf, "L",
-                                      CODE_LABEL_NUMBER (XEXP (x, 0)));
-         assemble_name (asm_out_file, buf);
-       }
-
-      if (code == 'X')
-       ; /* No suffix, dammit. */
-      else if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
-       fprintf (file, "@GOTOFF(%%ebx)");
-      else if (code == 'P')
-       fprintf (file, "@PLT");
-      else if (GET_CODE (x) == LABEL_REF)
-       fprintf (file, "@GOTOFF");
-      else if (! SYMBOL_REF_FLAG (x))
-       fprintf (file, "@GOT");
-      else
-       fprintf (file, "@GOTOFF");
-
+      assemble_name (file, XSTR (x, 0));
+      if (code == 'P' && ! SYMBOL_REF_FLAG (x))
+       fputs ("@PLT", file);
       break;
 
+    case LABEL_REF:
+      x = XEXP (x, 0);
+      /* FALLTHRU */
     case CODE_LABEL:
       ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
       assemble_name (asm_out_file, buf);
@@ -3094,17 +3140,17 @@ output_pic_addr_const (file, x, code)
       if (GET_CODE (XEXP (x, 0)) == CONST_INT)
        {
          output_pic_addr_const (file, XEXP (x, 0), code);
-         if (INTVAL (XEXP (x, 1)) >= 0)
-           fprintf (file, "+");
+         fprintf (file, "+");
          output_pic_addr_const (file, XEXP (x, 1), code);
        }
-      else
+      else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
        {
          output_pic_addr_const (file, XEXP (x, 1), code);
-         if (INTVAL (XEXP (x, 0)) >= 0)
-           fprintf (file, "+");
+         fprintf (file, "+");
          output_pic_addr_const (file, XEXP (x, 0), code);
        }
+      else
+       abort ();
       break;
 
     case MINUS:
@@ -3113,6 +3159,27 @@ output_pic_addr_const (file, x, code)
       output_pic_addr_const (file, XEXP (x, 1), code);
       break;
 
+     case UNSPEC:
+       if (XVECLEN (x, 0) != 1)
+       abort ();
+       output_pic_addr_const (file, XVECEXP (x, 0, 0), code);
+       switch (XINT (x, 1))
+       {
+       case 6:
+         fputs ("@GOT", file);
+         break;
+       case 7:
+         fputs ("@GOTOFF", file);
+         break;
+       case 8:
+         fputs ("@PLT", file);
+         break;
+       default:
+         output_operand_lossage ("invalid UNSPEC as operand");
+         break;
+       }
+       break;
+
     default:
       output_operand_lossage ("invalid expression as operand");
     }
index 540cfec..75e0298 100644 (file)
@@ -1703,10 +1703,9 @@ do {                                             \
 
 #define MAX_REGS_PER_ADDRESS 2
 
-#define CONSTANT_ADDRESS_P(X)   \
-  (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF             \
-   || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST               \
-   || GET_CODE (X) == HIGH)
+#define CONSTANT_ADDRESS_P(X)                                  \
+  (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF     \
+   || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST)
 
 /* Nonzero if the constant value X is a legitimate general operand.
    It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */
index ca63bf4..e65ca1c 100644 (file)
@@ -64,6 +64,9 @@
 ;;    prevent insns referencing it being scheduled across the initial
 ;;    decrement of the stack pointer.
 ;; 5  This is a `bsf' operation.
+;; 6  This is the @GOT offset of a PIC address.
+;; 7  This is the @GOTOFF offset of a PIC address.
+;; 8  This is a reference to a symbol's @PLT address.
 \f
 ;; This shadows the processor_type enumeration, so changes must be made
 ;; to i386.h at the same time.
index b1483d1..d3dc14f 100644 (file)
@@ -2031,7 +2031,7 @@ operands_match_p (x, y)
   fmt = GET_RTX_FORMAT (code);
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     {
-      int val;
+      int val, j;
       switch (fmt[i])
        {
        case 'w':
@@ -2057,6 +2057,19 @@ operands_match_p (x, y)
        case '0':
          break;
 
+       case 'E':
+         if (XVECLEN (x, i) != XVECLEN (y, i))
+           return 0;
+         for (j = XVECLEN (x, i) - 1; j >= 0; --j)
+           {
+             val = operands_match_p (XVECEXP (x, i, j), XVECEXP (y, i, j));
+             if (val == 0)
+               return 0;
+             if (val == 2)
+               success_2 = 1;
+           }
+         break;
+
          /* It is believed that rtx's at this level will never
             contain anything but integers and other rtx's,
             except for within LABEL_REFs and SYMBOL_REFs.  */