<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/54753>54753</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            "error: fixup value out of range" for aarch64-windows, for symbol references with a large offset
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            backend:AArch64,
            platform:windows
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          mstorsjo
      </td>
    </tr>
</table>

<pre>
    CC @efriedma-quic 

In https://github.com/llvm/llvm-project/issues/51720 we fixed issues where relocations against temporary symbols could end up with a too large offset. This is an issue as the ADRP relocations can store a 21 bit immediate (+/- 1 MB) offset against the symbol it points at. For those cases, we inserted extra temp symbols for large sections, to allow relocations against a temporary symbol to use these extra symbols instead of using the start of the section and a large offset.

The same issue can crop up elsewhere too, in code with references to symbols with large offsets.
```c
#define MAX_MEM_HANDLES  0x10000
struct mem_entry {
  void *ptr1, *ptr2; 
};

//extern struct mem_entry mem_entries[];
static struct mem_entry mem_entries[MAX_MEM_HANDLES];

void *getPtr(void) {
  return mem_entries + MAX_MEM_HANDLES;
}
```

```
$ bin/clang -target aarch64-windows -c aarch64-symbol-offset.c -O2 
error: fixup value out of range
1 error generated.
```

```
$ bin/clang -target aarch64-windows -S -o - aarch64-symbol-offset.c -O2
[...]
getPtr:                                 // @getPtr
        adrp    x0, mem_entries+1048576
        add     x0, x0, :lo12:mem_entries+1048576
        ret
```

(In this reduced case, it only triggers when built with `-O2`, but in the original case, it also triggered without `-O2`.)

For references to symbols in the current object file, we could potentially try to rewrite references to use the extra symbols that we've emitted with 1 MB intervals, but that's not correct if the symbol isn't static (and such rewrites aren't necessarily correct e.g. if the symbol can be weak and overridden by another symbol at link time), and clearly doesn't work if the symbol isn't defined in the current object file.

Curiously, if uncommenting the other declaration of `mem_entries`, `extern struct mem_entry mem_entries[];`, it does generate this code instead:
```
getPtr:                                 // @getPtr
        adrp    x8, mem_entries
        add     x8, x8, :lo12:mem_entries
        add     x0, x8, #256, lsl #12           // =1048576
        ret     
```

Therefore, it seems like the best solution would be to avoid forming address expressions in the form `symbol+offset`, if the offset is too large, and just add the offset as a separate operation instead. Where in the code is that decision taken, for how to form an address expression, deciding between an imediate symbol offset or a separate addition?
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJytV99v2zYQ_mvsF8KGTP_Mgx_spMUGLFuxFujeCko62Wwo0SOpOPnv9x0pJYqbphtWw5Al8e743d13x3Nuy8ft9bUYLTKqnKayVpO_W12IUXYzynbp-msjjiGc_Gi-G8n3-B50OLb5tLA1Hoy5738mJ2e_UhHwqL1vyeNmOVvLTJxJVPqBSpHei_ORHAlHxhYqaNt4oQ5KNz6IQPXJOuUehX-sc2u8KGxrSkFNKdqTOGNroUSwVhjlDiRsVXkKU_HpqD2sC9WkPYTyIhxJ7G7-_PBiowISPlhsr4SciVwHoeuaSq0CiZHcjOQesCdiJm5xc9Vt8IwPNhMyAc2T1U3ApgDw3josWk_YwbPr1-w1dMgFOE4Pwano3ZNjFTSSEx5BY3CsFKxQxtjzq9FR38SH5VtsCly4pl36DViFVAkXIKKbQwIflAv8Kj6kjRG1ErZfRHTIgE8sqmrqQsshLJw9cULIeErZRE4Yv8aaLSllylGFpaZAyoGzxxWXhpv5frdVlr5F9yznJVW6IXG7--vL7bvbL7_sfr_57d1HIbKHWYZPkvPBtUUQNdVfqAmIzWi9TytC3FtdIq-7U3Azxpdu5Wi-70m-vsHD0N3EcsSSHHPlwnZ_p5Hk5X60fNZGaANq5wcaF64MDaRrj_hA4UNwoCS_YCoOvHIUWoAbWIbG_jJMz4bh48sIv_D34qVcoCwahKAwCqyZBE4VyKdccVwtJmfdlPbsxaR4epUyO-moU4jJH7KLLjlnHToH1z_ocq8MCGTbyEAH65TEZiIKigM15FCJ5SUjfgbej2JixeQt0J3B5X46nXJi4mOXB_jwo08iDnfTTqfLVvqo0p349yFjHg5JIfezbLFZrleXCqV4VkhXwDB2Bvru_oUBsOStMMoNWnvgxumobAt0KW5dsYiRn8Y8Clg_HMjFht2IvNUmpOqFKQ7XKmLKkU7dxIZioaAbZYaWlPG2t4Q9WJ8J8GRiCm4PcXEnfb1xdJsUrcMaIOZ82oBZhrp2m86Kkw1Y1mij7MEjW3B0djrQhd2ucV60zXBU8BIm1_dYqnUIHep4JgAE-gJ47HvXWR7CXjQ2AAGwAZSuXhwVHvRcB9F1CESeO65vi2OPDD0euKJQQ4DnldOA35uj6WF6YZO7cI4-S-ou9m97jxLSZcmJesQbC1nXC8Mjo5s7EXRNHG5AZ53CkHLYprTUITxbd_cd8KkVl29k4cWhcd06bVtvHiMNcAQ1GBhqTkx3EiWAJaFqXTznuCeAD0NiJ4Lh5z9146QF6rFfTz0lUT0eTt3JyBPNa_Xx0yt-c1nxr9d5FEvX1-v8rfaQ1ORcLld8Z7zhp5l8Be385nvtIol9v2d84qMeg0tf256o9qDWXSqknDCkeGvamM5zrMac4kwTTzVo1px-QHfgOArvxL9xxuloxSKc8EQ-dLbUn_ucJmZ2Q5n2z5NgT-mvLc9JCM1ADrMgyptOKtLAnqjjW0eDqfgcJ5ie2JEhXR8APTXjE0HdcX1ex7HtiPkMTkWsKMNv3WFBVi3Z25zCmaiJs2k_aXa11QGEyQFAmNOMbzR_Py638_JqfqXGQQdD25GUPz5RpYwgL86_Hnu386ATdkP1cCIbt85s_8fUv1gv5-PjdlbJJc2zrFiWajZflYssW-RFUVVys8qrrBoblWOC3HLpSpmrAjHmqtztInS8S6SWJ6MCRxtrT-5IVPtYb2UmZbbIlqD01Xw2lfPqarnZLNBiZZmrGf-1qZU2U8Y6te4wdtsIO28PHotGe8yfT4sK6Ts0RNvUTcaqxWnltjX_ZfBf7Ti6uI3-_QPsyzVW">