mips.c (mips_offset_within_object_p): New function.
authorRichard Sandiford <rsandifo@redhat.com>
Sun, 25 Jan 2004 21:27:37 +0000 (21:27 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Sun, 25 Jan 2004 21:27:37 +0000 (21:27 +0000)
* config/mips/mips.c (mips_offset_within_object_p): New function.
(mips_symbolic_constant_p): Use it in the SYMBOL_SMALL_DATA and
SYMBOL_CONSTANT_POOL cases.  Also use it for SYMBOL_GENERAL if the
ABI has 64-bit pointers and the object file only allows 32-bit symbols.

From-SVN: r76586

gcc/ChangeLog
gcc/config/mips/mips.c

index b9492736dd10bb859a8cef9859e1f70eec509190..ccad5da79dc29e0c61c2c2bfd16c06527d1301a2 100644 (file)
@@ -1,3 +1,10 @@
+2004-01-25  Richard Sandiford  <rsandifo@redhat.com>
+
+       * config/mips/mips.c (mips_offset_within_object_p): New function.
+       (mips_symbolic_constant_p): Use it in the SYMBOL_SMALL_DATA and
+       SYMBOL_CONSTANT_POOL cases.  Also use it for SYMBOL_GENERAL if the
+       ABI has 64-bit pointers and the object file only allows 32-bit symbols.
+
 2004-01-25  Kazu Hirata  <kazu@cs.umass.edu>
 
        * config/sh/sh.h (PROMOTE_FUNCTION_ARGS): Remove.
index 1c87e1115735193819845835ef47d5d6629da043..df338f71c228e202c28799b9ae9879fcd2817a44 100644 (file)
@@ -191,6 +191,7 @@ struct mips_integer_op;
 
 static enum mips_symbol_type mips_classify_symbol (rtx);
 static void mips_split_const (rtx, rtx *, HOST_WIDE_INT *);
+static bool mips_offset_within_object_p (rtx, HOST_WIDE_INT);
 static bool mips_symbolic_constant_p (rtx, enum mips_symbol_type *);
 static bool mips_valid_base_register_p (rtx, enum machine_mode, int);
 static bool mips_symbolic_address_p (enum mips_symbol_type, enum machine_mode);
@@ -914,6 +915,29 @@ mips_split_const (rtx x, rtx *base, HOST_WIDE_INT *offset)
 }
 
 
+/* Return true if SYMBOL is a SYMBOL_REF and OFFSET + SYMBOL points
+   to the same object as SYMBOL.  */
+
+static bool
+mips_offset_within_object_p (rtx symbol, HOST_WIDE_INT offset)
+{
+  if (GET_CODE (symbol) != SYMBOL_REF)
+    return false;
+
+  if (CONSTANT_POOL_ADDRESS_P (symbol)
+      && offset >= 0
+      && offset < (int) GET_MODE_SIZE (get_pool_mode (symbol)))
+    return true;
+
+  if (SYMBOL_REF_DECL (symbol) != 0
+      && offset >= 0
+      && offset < int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (symbol))))
+    return true;
+
+  return false;
+}
+
+
 /* Return true if X is a symbolic constant that can be calculated in
    the same way as a bare symbol.  If it is, store the type of the
    symbol in *SYMBOL_TYPE.  */
@@ -939,21 +963,22 @@ mips_symbolic_constant_p (rtx x, enum mips_symbol_type *symbol_type)
   switch (*symbol_type)
     {
     case SYMBOL_GENERAL:
-      /* %hi() and %lo() can handle anything.  */
+      /* If the target has 64-bit pointers and the object file only
+        supports 32-bit symbols, the values of those symbols will be
+        sign-extended.  In this case we can't allow an arbitrary offset
+        in case the 32-bit value X + OFFSET has a different sign from X.  */
+      if (Pmode == DImode && !ABI_HAS_64BIT_SYMBOLS)
+       return mips_offset_within_object_p (x, offset);
+
+      /* In other cases the relocations can handle any offset.  */
       return true;
 
     case SYMBOL_SMALL_DATA:
-      /* Make sure that the offset refers to something within the
-        -G limit.  If the offset is allowed to grow too much,
-        it could overflow the range of %gp_rel().  */
-      return (offset > 0 && offset < mips_section_threshold);
-
     case SYMBOL_CONSTANT_POOL:
-      /* Similarly check the range of offsets for mips16 constant
-        pool entries.  */
-      return (CONSTANT_POOL_ADDRESS_P (x)
-             && offset > 0
-             && offset < (int) GET_MODE_SIZE (get_pool_mode (x)));
+      /* Make sure that the offset refers to something within the
+        underlying object.  This should guarantee that the final
+        PC- or GP-relative offset is within the 16-bit limit.  */
+      return mips_offset_within_object_p (x, offset);
 
     case SYMBOL_GOT_LOCAL:
     case SYMBOL_GOTOFF_PAGE: