re PR target/17224 (relocation truncated to fit: GPREL22)
authorRichard Henderson <rth@redhat.com>
Mon, 29 Nov 2004 18:42:26 +0000 (10:42 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Mon, 29 Nov 2004 18:42:26 +0000 (10:42 -0800)
        PR target/17224
        * config/ia64/predicates.md (sdata_symbolic_operand): Deny offsets
        outside the referenced object.

From-SVN: r91478

gcc/ChangeLog
gcc/config/ia64/predicates.md

index c5801c2da637331dfc0e6fa7a856ca417db70738..ed8056abb4d071541b3d4b3c180c7bb01e83aa6f 100644 (file)
@@ -1,3 +1,9 @@
+2004-11-29  Richard Henderson  <rth@redhat.com>
+
+       PR target/17224
+       * config/ia64/predicates.md (sdata_symbolic_operand): Deny offsets
+       outside the referenced object.
+
 2004-11-29  Kazu Hirata  <kazu@cs.umass.edu>
 
        * tree-if-conv.c (replace_phi_with_cond_modify_expr): Use
index b66df845baa3c77522d978db72a4d3b4803a3595..6166612ecad209083945d282e361e945fc4eb6b6 100644 (file)
 (define_predicate "sdata_symbolic_operand" 
   (match_code "symbol_ref,const")
 {
+  HOST_WIDE_INT offset = 0, size = 0;
+
   switch (GET_CODE (op))
     {
     case CONST:
       op = XEXP (op, 0);
       if (GET_CODE (op) != PLUS
-         || GET_CODE (XEXP (op, 0)) != SYMBOL_REF)
+         || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
+         || GET_CODE (XEXP (op, 1)) != CONST_INT)
        return false;
+      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:
       abort ();