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\\\+" } } */

Reply via email to