Wilco Dijkstra <wilco.dijks...@arm.com> 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. > > gcc/testsuite/ > PR target/98618 > * gcc.target/aarch64/symbol-range.c: Improve testcase. > * gcc.target/aarch64/symbol-range-tiny.c: Likewise. > > (cherry picked from commit 7d3b27ff12610fde9d6c4b56abc70c6ee9b6b3db)
OK on the same basis as GCC9. Thanks, Richard > > --- > diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c > index > e8e73b8ea92b0dd3b9de661652c30c26c07bec86..7c4cf75b5a5e2394dc0b3f69b68d93df8f88111f > 100644 > --- a/gcc/config/aarch64/aarch64.c > +++ b/gcc/config/aarch64/aarch64.c > @@ -12011,26 +12011,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/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\\\+" } } */