<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">