]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR target/17224 (relocation truncated to fit: GPREL22)
authorRichard Henderson <rth@redhat.com>
Mon, 29 Nov 2004 19:19:20 +0000 (11:19 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Mon, 29 Nov 2004 19:19:20 +0000 (11:19 -0800)
        PR target/17224
        * config/ia64/ia64.c (sdata_symbolic_operand): Deny offsets
        outside the referenced object.

From-SVN: r91480

gcc/ChangeLog
gcc/config/ia64/ia64.c

index 6717fe694e1fda722426af2b0da44da46ce123d1..714d1fefa1afa7fca187e58341d43fd91a8edc75 100644 (file)
@@ -1,3 +1,9 @@
+2004-11-29  Richard Henderson  <rth@redhat.com>
+
+       PR target/17224
+       * config/ia64/ia64.c (sdata_symbolic_operand): Deny offsets
+       outside the referenced object.
+
 2004-11-28  Andreas Fischer <a_fisch@gmx.de>
            Alan Modra  <amodra@bigpond.net.au>
 
index 6b8ce82de72377b27627efe37f46c35abc673805..3549c280d67a190139a24a34452d8dc367a2451d 100644 (file)
@@ -390,20 +390,55 @@ call_operand (rtx op, enum machine_mode mode)
 int
 sdata_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
+  HOST_WIDE_INT offset = 0, size = 0;
+
   switch (GET_CODE (op))
     {
     case CONST:
-      if (GET_CODE (XEXP (op, 0)) != PLUS
-         || GET_CODE (XEXP (XEXP (op, 0), 0)) != SYMBOL_REF)
+      op = XEXP (op, 0);
+      if (GET_CODE (op) != PLUS
+         || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
+         || GET_CODE (XEXP (op, 1)) != CONST_INT)
        break;
-      op = XEXP (XEXP (op, 0), 0);
+      offset = INTVAL (XEXP (op, 1));
+      op = XEXP (op, 0);
       /* FALLTHRU */
 
     case SYMBOL_REF:
       if (CONSTANT_POOL_ADDRESS_P (op))
-       return GET_MODE_SIZE (get_pool_mode (op)) <= ia64_section_threshold;
+       {
+         size = GET_MODE_SIZE (get_pool_mode (op));
+         if (size > ia64_section_threshold)
+           return false;
+       }
       else
-       return SYMBOL_REF_LOCAL_P (op) && SYMBOL_REF_SMALL_P (op);
+       {
+         tree t;
+
+         if (!SYMBOL_REF_LOCAL_P (op) || !SYMBOL_REF_SMALL_P (op))
+           return false;
+
+         /* Note that in addition to DECLs, we can get various forms
+            of constants here.  */
+         t = SYMBOL_REF_DECL (op);
+         if (DECL_P (t))
+           t = DECL_SIZE_UNIT (t);
+         else
+           t = TYPE_SIZE_UNIT (TREE_TYPE (t));
+         if (t && host_integerp (t, 0))
+           {
+             size = tree_low_cst (t, 0);
+             if (size < 0)
+               size = 0;
+           }
+       }
+
+      /* Deny the stupid user trick of addressing outside the object.  Such
+        things quickly result in GPREL22 relocation overflows.  Of course,
+        they're also highly undefined.  From a pure pedant's point of view
+        they deserve a slap on the wrist (such as provided by a relocation
+        overflow), but that just leads to bugzilla noise.  */
+      return (offset >= 0 && offset <= size);
 
     default:
       break;