<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/95099>95099</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
ARM64 (and other) assembler immediate arithmetic is broken, and evaluated too early
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
distorted-mdw
</td>
</tr>
</table>
<pre>
GNU as accepts the following (https://gcc.godbolt.org/z/e1fed5vhM)
```assembler
.text
proc:
movz x0, #thing
add x0, x0, #thing
eor x0, x0, #thing
ldr x0, [x1, #thing]
ldp x0, x1, [x2, #thing]
ldr q0, [x0, #thing]
ldp q0, q1, [x0, #thing]
ret
.balign 16
base:
.skip 16
thing = . - base
.skip 16
```
and produces
```
0000000000000000 <proc>:
0: d2800200 mov x0, #0x10 // #16
4: 91004000 add x0, x0, #0x10
8: d27c0000 eor x0, x0, #0x10
c: f9400820 ldr x0, [x1, #16]
10: a9410440 ldp x0, x1, [x2, #16]
14: 3dc00400 ldr q0, [x0, #16]
18: ad408400 ldp q0, q1, [x0, #16]
1c: d65f03c0 ret
```
as I expect.
Clang rejects this (https://gcc.godbolt.org/z/W8PTq9aqG), reporting
```
t.S:3:11: error: immediate must be an integer in range [0, 65535].
movz x0, #thing
^
t.S:4:14: error: expected compatible register, symbol or integer in range [0, 4095]
add x0, x0, #thing
^
t.S:5:14: error: expected compatible register or logical immediate
eor x0, x0, #thing
^
t.S:6:15: error: index must be an integer in range [-256, 255].
ldr x0, [x1, #thing]
^
t.S:7:19: error: invalid operand for instruction
ldp x0, x1, [x2, #thing]
^
t.S:8:15: error: index must be an integer in range [-256, 255].
ldr q0, [x0, #thing]
^
t.S:9:19: error: invalid operand for instruction
ldp q0, q1, [x0, #thing]
^
```
The errors for `ldp` are unhelpfully vague, but the caret position hints
that assembler is objecting to the immediate operand. The `eor` error
is a little unhelpful, but I understand that it's hard to characterize the
acceptable ARM64 logical immediate values. The other messages are
simply incorrect: it's clear that `thing` has the value 16, which is
easily in range.
It doesn't help to float the data definition above the code which
references it (https://gcc.godbolt.org/z/sejn5frx9); nor does it help to
replace the expressions with their literal values
(https://gcc.godbolt.org/z/v9GKnf8b8). However, doing _both_ of these
things is successful (https://gcc.godbolt.org/z/Gjrjc6a7M).
```assembler
.text
.balign 16
base:
.skip 16
thing = 16 // . - base
.skip 16
proc:
movz x0, #thing
add x0, x0, #thing
eor x0, x0, #thing
ldr x0, [x1, #thing]
ldp x0, x1, [x2, #thing]
ldr q0, [x0, #thing]
ldp q0, q1, [x0, #thing]
ret
```
I guess, therefore, that there are at least two underlying bugs:
* the assembler tries to resolve immediate values in the first
pass; and
* the assembler doesn't understand that the difference between two
defined symbols in the same section is a plain integer.
ARM64 is where I tripped over this, but it seems that other targets are
affected also. For example, the ARM32 fragment
```assembler
.text
.arch armv7-a
.fpu neon
proc:
mov r0, #thing
add r0, r0, #thing
eor r0, r0, #thing
ldr r0, [r1, #thing]
ldrd r0, r1, [r2, #thing]
vldr d0, [r0, #thing]
bx r14
.balign 16
base:
.skip 16
thing = . - base
.skip 16
```
is acceptable to GNU as (https://gcc.godbolt.org/z/G454KvrE6) but Clang
objects to the `mov`, `ldrd`, and `vldr` instructions
(https://gcc.godbolt.org/z/es33YqrfM).
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsWF1v47oR_TX0yyAGRUuy9eCHbLLZLi5uUbS3KPp0QYkjibuUqJCU4-yvL0hK_sqXF9vHawRwLHFmDs_MHI7ErZVNj7gl2SeS3S_46FpttkJap41DcdOJp0WpxfP2y9__DdwCryocnAXXItRaKf0k-wYI27TODZasbgl7IOyhqaplo0WplVtq0xD28IOwB0xqFNmu_Z2wgtB7Qm9JTuMftxa7UqGJ12HpcO_i_4PRlXccb0yfTu9--O89JewOCFu5VvbN-RouBBzXvLcStblypRKnK0n2aZ-cLc7uL9cPp56T2Yp9YBWjPB6i0KuixPWPyXVWBieGZ85LrmTTQ5LHCyW3-IL4pf0ufbB5UXANZHUPS7iBYDJ5u1h4SHX8yXsBg9FirNC-uoBefICs7mIpfD4FRcnqFgTbUMooPakOOKsOuk8ONy8-sWD9ohkpAKTea5FQmtKj1zfqyfs-GG68IYBg64qemL5RYGemVTSti5TSDaMfV1ySn6Q0CUTwIk1omtJry-_cRRoRrEQVNn6K4GUlnptO--YipZsz0_cL89xJYEDkWU1XFX1ZpRcFZOEr4H7Ayi1Py_hO8b4Bg9-wCjol7bXy9J_NP_54LPjjFy9P7A4MDtq4gwRcxHfLf5HV7YqsbpPE40ZjtPH_yK5DIblD6EbroETgPcjeYYMGZA-G9w16FgIJeZatMpLdT3uIwvaqApHs82lkn6yYsUPkyAYKqHQ3cCdLhWCwkdah8Q7tc1dqBdq8DSelRXZMia_4jzUxttE5uuzn0HlMSjey4urI3xTF9847IC4C5z5wdp6QXuD-o2TcsCz33ll2mg1f-tdK_as8rD2c4gLOjispQA9ovArWIR_WmbFyUveHyMO1h8ZFyM3_nYFrj6FXGSh-hYGfO9BewXDRtH-0GGHYEJTkVImB5BS4QRj7FtVQj0o9w443I_pg5ejCsFNxgw4GbaWHCK3snZ1PQO7gML-AtKBLLz7-XHQ6GB8lYdryEsBDITlFbXz8yE3wJy1wUNI5dQJphvIVxl6gsc7zFiJLR9jaQsuN8OGqlhteOTTyB_rYk1iGsY37lrv95-95-rLZYMfViHYCpl2LBjq0ljdoPTvRj5XdoJ5B9pU2BisXshkBVAq5iZBITmOCcgotj8NicO-HAXYHT62sWpATf8itDD5jKZ6J-VcHQqPtCVs78FT4LdZK85gUwR0HgbXsY1Z4qXcY06UFxjjRkcEaDfYVWpDu2gPB4rc-q82-8AfC6hP02gQ43sUEZvY-KF7FyLgfDFordW_hSbrWX5TGJxQNVxPN0x6vg7ErvvzW15tyQ1ixBPibfsJdFHShfZH9WWrX_gm69qHm-SskwPpqtGNVobX1qK7d95dv5luV87Wf05cfDOrzWHic1391jkzyeSb7aKL89ceDvx4NLqzemramdoRmRGu9qRcIrLXB-CM2pMEgpNyBQm4duCcd9Uo9--yWY2MPqZphEnYb-uaooM5ItL7RDVqtdvhCpLxWhAdQaaw7bnfg1vo25b34KMRRVC7lNMiKrCe1gBLdE2Lvd3IMFBQHxTRPHeBY3iFYDGcYBBUfFJeHw_ZM2KIKSwtPgbWvftPDgAL0zjPQSjsrvnRgETsb4UVhdtw06E50mdd1nK24snoJ8KAN4J53g5ryE3R_xaA2vOmwv0zyFV09X-Kman33mG63vuFza9bD6O_2OB_fb7VlnOmveGqPa95bObfmxyvnpjFz05iPWtOIE89z05j3W3M3hRGHKO-3ZrmP3yZJz-t1YvpdGb36OfwNvb3obzm_2gkzgtMwve-59sRIs_S3nfmcE1aEqg1PYdF1nIbsPAuRnHZ65wN7bvwAZsT0yzchyann0Y8OJyPhzx2YaFer_z6a-uT8WojtShSrgi9wm6yTTULXlG4W7bYoUs7SOlnn6zpPMOVVhmK1LtOk3CBu6oXcMspSmidJkmR5ulkmIst4va6qNauRs4ykFDsu1VKpXedRLKS1I26LjBbFQvESlQ3v1xjr8QnCTcIYye4XZuttboIuplRJ6-zRi5NO4TYKBWEbT07ofk_xybh50EZupGs7dLLyulIa_R37mVX0wsm9QDitAblRz4vRqO0Fm9K1Y7msdEfYg8cxfd0MRvscEvYQ0FvCHuLudlv2vwAAAP__yZOq-Q">