In aarch64_classify_symbol symbols are allowed large offsets on relocations.
This means the offset can use all of the +/-4GB offset, leaving no offset
available for the symbol itself.  This results in relocation overflow and
link-time errors for simple expressions like &global_array + 0xffffff00.

To avoid this, unless the offset_within_block_p is true, limit the offset
to +/-1MB so that the symbol needs to be within a 3.9GB offset from its
references.  For the tiny code model use a 64KB offset, allowing most of
the 1MB range for code/data between the symbol and its references.

    gcc/
        PR target/98618
        * config/aarch64/aarch64.c (aarch64_classify_symbol):
        Apply reasonable limit to symbol offsets.

    testsuite/
        PR target/98616
        * gcc.target/aarch64/symbol-range.c: Improve testcase.
        * gcc.target/aarch64/symbol-range-tiny.c: Likewise.

From-SVN: r277068
(cherry picked from commit 7d3b27ff12610fde9d6c4b56abc70c6ee9b6b3db)

---

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 
5a8acf8607a735d241c8849a449c000996d96931..6a42c06f04730d0bc55294f0eca59b9711952a2e
 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2021-01-12  Wilco Dijkstra  <wdijk...@arm.com>
+
+       Backport from mainline:
+       2019-10-16  Wilco Dijkstra  <wdijk...@arm.com>
+
+       PR target/98618
+       * config/aarch64/aarch64.c (aarch64_classify_symbol):
+       Apply reasonable limit to symbol offsets.
+
 2021-01-06  2019-07-10  Marc Glisse  <marc.gli...@inria.fr>
 
        PR testsuite/90806
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 
9189777da7e120b9a0912d8501f2da8db144d334..bce50aea01e58f72ab59b30ce43969b48f5ca1b1
 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -13297,26 +13297,31 @@ aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset)
             the offset does not cause overflow of the final address.  But
             we have no way of knowing the address of symbol at compile time
             so we can't accurately say if the distance between the PC and
-            symbol + offset is outside the addressible range of +/-1M in the
-            TINY code model.  So we rely on images not being greater than
-            1M and cap the offset at 1M and anything beyond 1M will have to
-            be loaded using an alternative mechanism.  Furthermore if the
-            symbol is a weak reference to something that isn't known to
-            resolve to a symbol in this module, then force to memory.  */
-         if ((SYMBOL_REF_WEAK (x)
-              && !aarch64_symbol_binds_local_p (x))
-             || !IN_RANGE (offset, -1048575, 1048575))
+            symbol + offset is outside the addressible range of +/-1MB in the
+            TINY code model.  So we limit the maximum offset to +/-64KB and
+            assume the offset to the symbol is not larger than +/-(1MB - 64KB).
+            If offset_within_block_p is true we allow larger offsets.
+            Furthermore force to memory if the symbol is a weak reference to
+            something that doesn't resolve to a symbol in this module.  */
+
+         if (SYMBOL_REF_WEAK (x) && !aarch64_symbol_binds_local_p (x))
            return SYMBOL_FORCE_TO_MEM;
+         if (!(IN_RANGE (offset, -0x10000, 0x10000)
+               || offset_within_block_p (x, offset)))
+           return SYMBOL_FORCE_TO_MEM;
+
          return SYMBOL_TINY_ABSOLUTE;
 
        case AARCH64_CMODEL_SMALL:
          /* Same reasoning as the tiny code model, but the offset cap here is
-            4G.  */
-         if ((SYMBOL_REF_WEAK (x)
-              && !aarch64_symbol_binds_local_p (x))
-             || !IN_RANGE (offset, HOST_WIDE_INT_C (-4294967263),
-                           HOST_WIDE_INT_C (4294967264)))
+            1MB, allowing +/-3.9GB for the offset to the symbol.  */
+
+         if (SYMBOL_REF_WEAK (x) && !aarch64_symbol_binds_local_p (x))
            return SYMBOL_FORCE_TO_MEM;
+         if (!(IN_RANGE (offset, -0x100000, 0x100000)
+               || offset_within_block_p (x, offset)))
+           return SYMBOL_FORCE_TO_MEM;
+
          return SYMBOL_SMALL_ABSOLUTE;
 
        case AARCH64_CMODEL_TINY_PIC:
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 
835bf14107ffdef3b700dc00399a2d03e298f062..e25e5d85063e9e5bffa932dccfa19d9ec2550606
 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,12 @@
+2021-01-12  Wilco Dijkstra  <wdijk...@arm.com>
+
+       Backported from mainline:
+       2019-10-16  Wilco Dijkstra  <wdijk...@arm.com>
+
+       PR target/98618
+       * gcc.target/aarch64/symbol-range.c: Improve testcase.
+       * gcc.target/aarch64/symbol-range-tiny.c: Likewise.
+
 2021-01-07  Paul Thomas  <pa...@gcc.gnu.org>
 
        Backported from master:
diff --git a/gcc/testsuite/gcc.target/aarch64/symbol-range-tiny.c 
b/gcc/testsuite/gcc.target/aarch64/symbol-range-tiny.c
index 
d7e46b059e41f2672b3a1da5506fa8944e752e01..fc6a4f3ec780d9fa86de1c8e1a42a55992ee8b2d
 100644
--- a/gcc/testsuite/gcc.target/aarch64/symbol-range-tiny.c
+++ b/gcc/testsuite/gcc.target/aarch64/symbol-range-tiny.c
@@ -1,12 +1,12 @@
-/* { dg-do compile } */
+/* { dg-do link } */
 /* { dg-options "-O3 -save-temps -mcmodel=tiny" } */
 
-int fixed_regs[0x00200000];
+char fixed_regs[0x00080000];
 
 int
-foo()
+main ()
 {
-  return fixed_regs[0x00080000];
+  return fixed_regs[0x000ff000];
 }
 
 /* { dg-final { scan-assembler-not "adr\tx\[0-9\]+, fixed_regs\\\+" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/symbol-range.c 
b/gcc/testsuite/gcc.target/aarch64/symbol-range.c
index 
6574cf4310430b847e77ea56bf8f20ef312d53e4..d8e82fa1b2829fd300b6ccf7f80241e5573e7e17
 100644
--- a/gcc/testsuite/gcc.target/aarch64/symbol-range.c
+++ b/gcc/testsuite/gcc.target/aarch64/symbol-range.c
@@ -1,12 +1,12 @@
-/* { dg-do compile } */
+/* { dg-do link } */
 /* { dg-options "-O3 -save-temps -mcmodel=small" } */
 
-int fixed_regs[0x200000000ULL];
+char fixed_regs[0x80000000];
 
 int
-foo()
+main ()
 {
-  return fixed_regs[0x100000000ULL];
+  return fixed_regs[0xfffff000];
 }
 
 /* { dg-final { scan-assembler-not "adrp\tx\[0-9\]+, fixed_regs\\\+" } } */

Reply via email to