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

    <tr>
        <th>Summary</th>
        <td>
            [coroutines] LLVM incorrectly allocates coroutines on a variable stack
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            coroutines
      </td>
    </tr>

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

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

<pre>
    Example:

```cpp
struct StubbyMessageBuffer {
  StubbyMessageBuffer();
 ~StubbyMessageBuffer();
};

// Reduced version of absl::cleanup
class Cleanup  {
 public:
  Cleanup(void (*cleanup)()) : cleanup_(cleanup){}

  ~Cleanup() {
    cleanup_();
  }

 private:
  // Strangely enough this doesn't work if cleanup_ is a std::function
  void (*cleanup_)();
};

MyTask FooBar() {
 StubbyMessageBuffer smb;
  #ifdef DO_CLEANUP
  // This is produced by a LOG(FATAL) or a LOG(QFATAL)
  Cleanup cu([]{abort();});
  #endif
 co_await 1;
  co_return;
}
```

When compiled with `-O1` and `DO_CLEANUP` undefined, `smb` is constructed and stored in the coroutine frame:

```llvm
define internal fastcc void @FooBar() [clone .resume](ptr noundef nonnull align 8 dereferenceable(32) %0) {
entry.resume:
  %ref.tmp3.reload.addr = getelementptr inbounds i8, ptr %0, i64 24
  %smb.reload.addr = getelementptr inbounds i8, ptr %0, i64 18
```

However, if `DO_CLEANUP` *is* defined, `smb` is no longer stored on the frame; instead, it is constructed and allocated in the coroutine resume function:

```llvm
define internal fastcc void @FooBar() [clone .resume](ptr noundef nonnull align 8 dereferenceable(32) %0) {
entry.resume:
  %smb = alloca %struct.StubbyMessageBuffer, align 1
```

This behavior is wrong; the constructor for `StubbyMessageBuffer` may have side effects, and if `FooBar()` calls a function that takes a reference / pointer to `smb`, `smb` still does not get created on the coroutine frame object, and we get a segfault.

godbolt: https://godbolt.org/z/oMfKqExMK
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzUVkFz2zYT_TXQZScaEhQl6qCDZEXfNxO7aZu0PXqWwFJEDQIqAMpRDvntHZCURDtyeuipMx5aXAKLt--9XRK9V3tDtGL5hnGOGs3XGm3KOGf5doJtqK1bXcKT0srT6v0XbA6aWLZmyZYl5-s86f_E4dBHfHCtCPAptGV5eiDvcU-btqrIAVts-jVw6zHjBeNLlp3XfPvnNWyxvf7ur3zH-A5-JdkKknAk55U1YCvA0usIPlsLTWjaAa7Q6D3c9SEYQTy0pVbiUi6c1zBeHK2S0EG55OLLARpfAsvWMMQfGS9GSxabiHgEF-DbNW2390oRjJO8YAZeZzk4dcRAI7ADD5-CQ7MnfQIytt3XEGrlQVryhvFFgGfrnkBVl5NAeUDwQfZMVa0RQVlzzvp94Y_Xyt8W5eH0Gf0T7KzdoPuu0FtO8U05LpdnqpJUwfbj4939-_VPv_38qs7PsSzl4eBsL3x5AoT7j_9jvNitP6_v45HWXWK_nIOvxAXRRnz5huVbtthgaV24lrfYvpKBZ2SkqoZ7YR_xGVWAdLRG2EdHoXXmBT8ve2fM1R81GRC2OShNEp5VqIHNk3cfUzZPAI2MdyMa5gm0RlKlDEnG7-LTyN08iWwIa_puJNlt9cE6kqAMhJpAWGfboAxB5bB5s7G1PjZ9qD8GlAnkDGqo0AchBlPMkpfy5huhrSGYOvJtQ5FPXhyCA2M7wGCsMa3WgFrtDRQgyVFFjowgLDUxXmS8y8Tz5IVhyAR3OqcdOz53VE1Dc8imjrRFOUUpHbBsC3sKpKkhEyICZcqIwYMqImUx1B9yB2o-Az4bpfRN-e-ypcUPxP6_faZjnGp3sQm_U5bxtfKMr-EtgY0Fbc0-Nkwvre2lHQTdgDI-EHYbVbhlCdTaCgy3XNEzDJcZ8N_3h2_KTsC-6C7ScTG9-aa5G45OfyBgN3dKqvGorIv8Pjtr9pH5nsuBbOugsi5qd-ukeQINnqDGI4FXkoCqikTwHQQjB2uM6YtbBGodh_VZHwg1Bgj4RDF64SpOSDjYThQI9uqfl2byQWndvRjA2BAtDsJRZwx7c1yALf8kEc4Yn6nbg-BpX2Grw3RM097K0uoQX4x1CAcfZekG9_Bgat2e8d1Xxnf2ofrw1_svDx8mcpXJZbbECa3SRZrOkpQns0m9Qp7nWZmgWBYJ5jxFuSjlYiGL5bLI51UyUSue8FmS8ZynacZnU-SlEEiztKiqskgkmyXUoNLT6N149kR539KqmOdFMtFYkvbDt9Glaj98HLlV3PSubPeezRKtfPDXNEEF3X1VjbblW7i___0BlBHWORJBny5d56-s-sgzwhGdivYGH1A8TVqnV68YU6Fuy6mwDeO7rvf6f-8OzvaC7LpiPOO7rp6_AwAA__8qVQTJ">