Wilco Dijkstra via Gcc-patches <gcc-patches@gcc.gnu.org> writes: > 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)
OK, thanks. Although it's not a regression, it's a difficult bug to work around. Richard > > --- > > 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\\\+" } } */