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

    <tr>
        <th>Summary</th>
        <td>
            wrong code due to incompatibility between C++20 coroutines and 32-bit Windows x86 ABI
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            c++20,
            clang:codegen,
            miscompilation,
            ABI,
            coroutines
      </td>
    </tr>

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

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

<pre>
    Testcase is a little large, [see it on compiler explorer here](https://godbolt.org/z/5WY1hnh5j).

The 32-bit Windows ABI passes objects of non-trivially-copyable class type by value on the stack.
The C++20 coroutines feature can suspend execution after an argument to a function has finished being evaluated and before the function call happens. In this testcase, that happens here:

```c++
  consume_two(co_await make(), co_await make());
```

This code is therefore not lowerable: the language rules don't permit us to make a copy of the result of the first argument, the ABI requires that we construct it directly into a stack slot where `consume_two` will find it, and the function containing that stack slot returns between the object being constructed and the call to `consume_two`.

After the coroutine lowering pass runs, we have this IR:

```llvm
define internal fastcc void @"?my_task@@YA?AUtask@@XZ.resume"(ptr noalias nonnull align 4 dereferenceable(72) %0) #3 personality ptr @__CxxFrameHandler3 !dbg !880 {
  ; ...
  %argmem.reload.addr = getelementptr inbounds %"?my_task@@YA?AUtask@@XZ.Frame", ptr %0, i32 0, i32 6, !dbg !884
  ; ...
  call void @"?consume_two@@YAXUNoisy@@0@Z"(ptr inalloca(<{ %struct.Noisy, %struct.Noisy }>) %argmem.reload.addr), !dbg !886
```

... which doesn't satisfy the rules for `inalloca` arguments. (The verifier doesn't complain about this, but presumably it should!)

It's not clear to me what the machine code we generate in this case actually does, and I don't have a Windows machine / emulator on which to test, but I don't see how it can be generating correct code!

We should decide what we want to do here. It seems like there are a few options:

- We could reject use of C++20 coroutines on this ABI.
- We could introduce an extra copy of these function arguments in the case where the function evaluation could be interrupted by a suspension. Note that this is not conforming and would reject valid code; the testcase is valid even if `Noisy` is noncopyable.
- We could reorder the evaluation of function arguments on this ABI so that all suspensions are performed before any arguments are constructed. Note that this is not conforming due to the C++17 evaluation order rules, but we already don't follow those rules in some cases because they're incompatible with callee-cleanup argument passing.

[MSVC appears to do something like the third option](https://godbolt.org/z/4Yr7bsnMs). Note that MSVC doesn't call `await_resume` on either awaitable until both are ready. While this behavior directly violates the [C++ sequencing rules](http://eel.is/c++draft/intro.execution#11.sentence-2), which don't permit anything else to be interleaved between the `await_suspend` and `await_resume` calls on a coroutine, maybe that's the best we can do, and it would be compatible with MSVC.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJyMV01z4zYS_TXwpcssCtTnQQfJXtX6kBx2k51MLq4m2RSRAQEFAEUrv36rAYqSZiapKVuWCZHA69evX7fQe3U0RFux2IvF6xP2obVu-9flaLVV9VNp68v2F_KhQk-gPCBoFYIm0OiOJOQLiMXeE4EKYA1UtjspTQ7o46StIwctORKLVyHXbQgnL4qdkAchD0dbl1aHzLqjkIe_hDwsPn2etaZd_CHkJhP5q8h36e8vLUEhn0sV4JMytR087PZvcELvyYMt_6AqeLANGGueg1NnhVpfnit7umCpCSqN3kO4nAjKC5xR98RYQ0vgA1ZfstsxL0LuhdzLHCrrbB-UIQ8NYegdQYUGfO9PZGqgD6r6oKwBbAI5QAPojn1HJkCwgND0poqft-ihUUb5lmooSZkjEGPAQDWg4bXGOopwpocq1BpaPJ3I-AzeGKzyEMZEMO2hxXC9I5Fc7O5JE8s8_VYppLQKUFnj-47ew2CFXFf2HQdUATr8QkKuhdzw5t9d3ohi_9Xej1lSHipbR5kERhTDMjaAtgM5ToUodjFOjebY45HA9Zo81NYIuQpwItepAL1nCvloQOAscm75MUe-1-F61Sjnw8R64oSiMhz92StHPpE0UAw6uL4KLNNaOaqCvoAyMVNRA-C1DTAwbGDS7lha5jAorTmJNah4EKftMV_WBFSGkxvPvNvTUeid8VBSGIiS7JJmRzVM4EY98A0x_8F-C-WhMHZRevH-q1oT17wtlwe43ngGPBC0eKYko7f__J1WtD53aammhndTJpAzqKFBH6oKzlbVIOa5kFIUh-7yHtB_4et5_nknisPu19vCb79nnLCO-Ga5PgUHxqJW6LlQTa81oFZHA3OoWS3kyFQUZSLXKynkBoRc5Om9KFgd3hrUKlyANxPz_P395ePj4LCjf6OpNbkChJzV5ZHf1uscxGoSvij2kGXZdCkX6I4ddZkjbbHOsK4diOIVjhRIE2uKT1GmtL2pPT_wg1FHQDHolwQ0RvECqpAw_bOM3nkHdv43QKMUHnm_l8SI4rdff7bKX9Ilv36_sa4Mam0r5EIuXsRqz4iS5LL0VITysARi9SqKf41J-Jap0SjuA1j-gzlkWQZDq6oWaks-VbvHoHxzSZUdfaCxjhU_4V3mU3n7DIRcs0WfyalGkbvbibuORmUAS9uHKHIGV_YBTlGCWHK5B_Ct7XUt5Izh38F7C0KufPSqShO66D8EA5cyw-uwarkcor0NBEcy5DBwfaSSiu0Rq9Bz54nIrjbxNrlbLECcWth1TyEPQF2vMVjHbSnRFGx0-2sYt12417Z24Gi4H5UTmGQljr0t4uQo70L8RGP0UFOl6jG4gWDA1LJqG9tIBm_xkM6DVl8oOTkgv6ChAeyJDc9_5SDP8InZ4e0dRW_rPbFRf7eh2pG13f4t--Z5ZYKzdV8R91T6CO6hB_g70520kdJAKQvJwx_ceey3yaj5jHJ0Ntef2HXLC7eB2Nm9siaDn22gZOQRpxqlYU1jXcdEc2aH-3DPqFWdeC_28fRwNzWlT-lMBlTDEk9lt8zT1uY6qnzLhiPr6tHk78KwzfdouOMVvE0BsHvcQvMxkydyHAhNsweay902fMtdU_oBOuqeomJvE9Rs9QA3xhCL_KrogQC1I6wvk7Qbq7UdILTWXx1BGfC2S5nlFloh6yq0dBFy5TiLXPsYFM95gwpttEuiZy5j059uQxm3Q2WOD_1TLPY__fd_L8BTFDo_VgEfGFoO61oAHLarR-n_2DA7_-xWpTc_eR5m7wiM5905F6dHLPM4bb2P7XKZcyZJcelB_CSOsb0JSkNpQxszFLnL4FOr9NjXS2rxrKy7TThnZTWGOAgRD-pjcsDTnz2ZimNMSZlimkIi0hnb6GGcH2uHTRDyEMszm8ZfIYvZLPNkAjfvZzn2havXP8x1aC6JV9I-6uVahprwHMV4m5AmTsaBO_YCU3-PK-Ywah9vHsMYOryUifVo7rxrST7Ng2igtleLVmGs5ZLgazlxvrKnelvUm2KDT7SdLVf5fL6erYundrvBBpsNVUVV5eV6vSlrKdfrZU5Ii_WsWj2prcylnMl8JWeyyItstuaf1WyNxaZsCinmOXWodMajF-vnSXnf03axKdbySWNJ2scvZ1JWVytNowWv8Bwtih3bzpHMtN4pn76IYUrRuLzbv90endyYlxavT27LCJ7L_ujFPNfKB3_DFFTQtB2cjT2mpmvB38pPxbHsmsHvuj5T_dXXuI_1ks3qqXd6-1VFqdD2ZVbZTshDHEvT2_PJWTZcViITxQqNXP0_AAD__weA47s">