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