<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/55957>55957</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
stackmaps can't express values spanning more than a single register.
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
vext01
</td>
</tr>
</table>
<pre>
A value greater than the size of a register may still be allocated to registers: the value may get split up into parts and span multiple registers.
As far as I can see, this can happen for two reasons:
- As an optimisation (because registers are faster than memory).
- As an ABI constraint over a call boundary (e.g. Sys V has rules for breaking struct fields into individual arguments, and for returning 128-bit values).
At present, if you pass a live variable to `llvm.experimental.stackmap`, and that value that gets split across registers, then the stackmap record will report only the first register in the set of "split-across" registers.
To demonstrate:
```
%s = type {i64, i64}
declare %s @f(%s)
define i64 @main(i32 %argc, ptr %argv) {
%s2 = call %s @f(%s zeroinitializer)
call void (i64, i32, ...) @llvm.experimental.stackmap(i64 99, i32 0, %s %s2)
%f1 = extractvalue %s %s2, 0
%f2 = extractvalue %s %s2, 1
%sum = add i64 %f1, %f2
ret i64 %sum
}
```
Compile with `-O3` here's the code:
```
0x08000040 55 push rbp
0x08000041 4889e5 mov rbp, rsp
0x08000044 31ff xor edi, edi
0x08000046 31f6 xor esi, esi
0x08000048 e8fb010000 call reloc.target.f ;[1]; RELOC 32 f
0x0800004d 4801d0 add rax, rdx
0x08000050 5d pop rbp
0x08000051 c3 ret
```
Here we see that `%s zeroinitializer` has been assigned to `rdi:rsi` as part of the sys-v calling convention. These are the first two argument registers, so it's as if the struct has been chopped in two and passed as separate args.
We also see that the return value `%s2` is in `rax:rdx`, also due to the calling convention for 128-bit return values.
Yet the stackmap record for this code is:
```
LLVM StackMap Version: 3
Num Functions: 1
Function address: 0, stack size: 8, callsite record count: 1
Num Constants: 0
Num Records: 1
Record ID: 99, instruction offset: 13
1 locations:
#1: Register R#0, size: 8 <--------------- %s2
0 live-outs: [ ]
```
And `R#0` is `rax`.
This is confusing/wrong, as it looks like the 128-bit value has someone been stored in a 64-bit register, but all that has really happened is that the record fails to mention `rdx`.
Fixing this would require changing the [stackmap format](https://llvm.org/docs/StackMaps.html#stack-map-format) to allow it to express a list of registers, instead of just one.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzdWMtu2zgU_Rp7Q1jQw3bshRdOMsEUaKdAWmQwS1qibDaSqCEpx-7Xz7mX8itNMosW7WAEwxIf98lD6lytTLFfLMVWVp0Sa6ukV1b4jWzwp4TTX5UwpZDCqrV2NFbLvXBeV5VYKSGryuQQKYQ3xylukC1ZOiglgbXywrWV9qJrhW4wuZXWOyGbAv0wVneV122lTkqiQXw7iJfhf-lEKa2QTrwTOaY7pQbpDYxox-2NbFvViNLA9yfyRDrTkB9BXIzEkowJ03pdaye9No0YpLOVymXnzqwKaRVMuWMWalUbux-k8-iZquU1XIERbyUCEmYLCQlnKDGmawpp92RBRetIfNo78QAnnbBdpRz7uYKTj7pZI5m2y70otaoKF5Kjm0JvddHJCv6su1o13lG8lC6Stcp3tiHhJJ2NVkgrp9qd3OzT5kVrlYM4SetS7E2HzDsEICq9pRWyWq6QdhgdTOOq2taR2rXKarIpq8h5mT_WssXgwQGkpbcXHrG2rl9cmVsD5Scg8BqpHku9KgznxhbiiTBkVWssstdUe55Uauv8CWy6FwV8gMJBmrKdUbCD5itw-WxEgXXjxfHqCAMKIvxCM504Mchuhd-3SgyurvV0zHnC7er2XF-h8oqAESTGcYmFpWfk-3JaqRtF8jSpBi4wT2cpyWEdc1Leets3t5Amqz2uWHnK_jCIntsSX5U1utFeywq70j6zLYLU1uiCYHcIJUvpFkURGxu_tcIsJObzXk7wggcvyLNv7KG3TNhftUOecx8wcS5xI-Lz2em_zU7Oc9HVPF0WRcgometdKtNLV7AfDnMg1o8dl_DZqvP_jalbDdw_ab8h5I8-ZvgXG2VxsFw5Rl1uilexI86ueBfPYlzjOLQnk_NR0XZuAxdXrfje6w3TSWiPZ7O5OpmvzVawacqbdd_vwa-43oh6HNpZUpZnwzuckEKoQlPUuP08V3_g9UbU09BG1NOz4T5qF6J2_7uoZ6GtZuUqTqiHm3zoYf-DhkQeh6ry0REKg-x6MLlOBpNbPIn7395_vBE4186h8l-63oi9CO3xLE6K-DhMJyNilzve3cXuZzr7w67Xo54cjtPiQqA1dIz9iOP0l11vxNyf43l2IYD328tvoXD7HW8t8UQ0qadkzNZeoAz0hgMJXSlQMrBAvW4Cc8eAxXGZLS2OD0zCHOLnxLmYfu3daMtbjSgnSO8W1AEMOhKfN2CXzJlP5I0I-IG1XlJBB2br-fUKA7rXHdjv0a18Y0DlC2Z-pAiEkwgrejDDKbgFRkf6Lxnfn1SLQP8xBaQ70OSeq_Y5SSk-TTybo8bmQdTF7sBvSUfRMR9mCvBNzMy_D6z73MClP38p_yLp5QqFqxaQC_hx4hcvre_79w8fxCdS8QEqHpBGeEDVVRbG_wBHuuuanBzjqutIoA69dEigAuBBjpAd4rqOumbURUE67dXBxxzliz_TRlZuiExLKkNY0bH_nkUubYc-8e6Wens-2YR1Jo9MWYLPs0R22gmJ4EpSX5RtYbekWUKz7w9FwT16QiyHKHDU34wur55UHvXEXPCMTBdCwItB0IvhdYa4BPLQFYwFzPSAmcaXxQYtJ69oU3YOaBmkd0_W0P2Gge4Rmnl0cOAx7JOLoo2h70ytDEoH3gLOGxt2gBTTcQ-0EDupXHWe6u4Ac64pFZr7vgYmQXe-BQLspK4cgbruUcw7_ptQ7vSO0M4AfTJdVUD-705je-eohddhTFHyjrgGoGvpKZXpbON9y6uX3uHHpYaxlI7C5DgA7g5IdtHG1xUSy1pGUDPq1aBIgZP0VeGJ8oZn1CqEXy5YHZ9IF0cKAUvJgvq_dDTeqGhYLLJins3l0GtfqcXBV_5UgOPHH5WGjctfILiaRqmvQtkvBa3k2feIaNjZanEZ4RrFQ7eKclP34fa3UWvNF5UjnDvtHNfld5PJfHI13CziZJpOy9VUyUTOx3kWp-VYJVfjdBbPk5Ush5VcqcotkGPUt41CHkgFnpHjoV6kcZrGU8zNJuNxHBVqNs5niSySyXyu0gwlnkLhWUWH7A_tgl1adWtH9R-CcafB_iWg2Bz0y85vjF1sUaPFyZAtL9jzfwA_ANoh">