<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/159571>159571</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
crash on load of under-aligned i128 from coroutine frame
</td>
</tr>
<tr>
<th>Labels</th>
<td>
coroutines
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
zmodem
</td>
</tr>
</table>
<pre>
Using clang/llvm/libc++ at head (09966960c692be63b192448e8c2b6bfebad3c3b8):
```
#include <coroutine>
// Boilerplate based on https://theshoemaker.de/posts/yet-another-cpp-coroutine-tutorial
class Task {
public:
struct FinalAwaiter {
bool await_ready() const noexcept { return false; }
template <typename P> auto await_suspend(std::coroutine_handle<P> handle) noexcept {
return handle.promise().continuation;
}
void await_resume() const noexcept { }
};
struct Promise {
std::coroutine_handle<> continuation;
Task get_return_object() {
return Task { std::coroutine_handle<Promise>::from_promise(*this) };
}
void unhandled_exception() noexcept { }
void return_void() noexcept { }
std::suspend_always initial_suspend() noexcept { return {}; }
FinalAwaiter final_suspend() noexcept { return {}; }
};
using promise_type = Promise;
Task() = default;
~Task() { if (handle_) { handle_.destroy(); } }
struct Awaiter {
std::coroutine_handle<Promise> handle;
bool await_ready() const noexcept { return !handle || handle.done(); }
auto await_suspend(std::coroutine_handle<> calling) noexcept {
handle.promise().continuation = calling;
return handle;
}
void await_resume() const noexcept { }
};
auto operator co_await() noexcept { return Awaiter{handle_}; }
void run() {
handle_.promise().continuation = std::noop_coroutine();
handle_.resume();
}
private:
explicit Task(std::coroutine_handle<Promise> handle) : handle_(handle) { }
std::coroutine_handle<Promise> handle_;
};
// End of boilerplate.
// loosely based on std::variant<int, __int128>
struct Alt1 { __int128 i; };
struct Union : public Alt1 { };
struct Base {
Union u;
char idx;
};
struct Impl : public Base {
char c[15];
};
struct Variant : public Impl { };
// Just to put more stuff in the frame.
struct Stuff { void *p, *q; };
#pragma clang optimize off
void use(Variant& v) {}
void use2(Stuff &s) {}
#pragma clang optimize on
Task __attribute__((noinline)) foo(Stuff s, Variant v) {
auto s2 = s;
Variant copy_of_v = v;
use(copy_of_v);
use2(s2);
co_return;
}
int main() {
Task t = foo({}, {});
t.run();
}
```
```
$ build/bin/clang++ -std=c++20 -O3 /tmp/a.cc -fcoro-aligned-allocation
$ gdb a.out
(gdb) r
Program received signal SIGSEGV, Segmentation fault.
0x00005555555552a0 in foo(Stuff, Variant) [clone .resume] ()
(gdb) disas
Dump of assembler code for function _Z3foo5Stuff7Variant.resume:
0x0000555555555290 <+0>: push %rbx
0x0000555555555291 <+1>: sub $0x30,%rsp
0x0000555555555295 <+5>: mov %rdi,%rbx
0x0000555555555298 <+8>: movups 0x18(%rdi),%xmm0
0x000055555555529c <+12>: movaps %xmm0,(%rsp)
=> 0x00005555555552a0 <+16>: movaps 0x28(%rdi),%xmm0
```
It seems the `__int128` is stored at offset `0x28` (40) in the coroutine frame, which is not a multiple of 16.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJy0WM2O47gRfhr2pWCDoizZPvhgt8eLzSUDTHYPuQgURdnMUqRCUh73HvLsAX8ky57umUyCGA2MZbG-qvrql0OtFWfF-Q4VB1QcX-jgLtrs_ux0w7uXWjdvu9-sUGdgkqozIicpr53_R9QMkQMiB6AOLpw2gMgGb7dluS0xK7ek5mVeZ1uyWm34hpG6rFte0yZneb1BZIvyPcLhr8TpD-8RyYVicmg4oPyVaaMHJxRH-ad0lpwQOcFBC8lNL6njUFPLG9AKLs711qOGM-7C7UXzjv7BzbLhiJx6bZ1F5PTG3YIq7S7cLFjfLyYtCzc4bQSVCO-ZpNbC36j9A9D6gPC-H2opWDQaAMA6MzAHJ6Go3H-lwnGTTkL61FpLoP5VZTht3hDxbgPTyjpQmt8Y752XAcPdYBS0VFqO8gOg9XGG43gXPUX5q3vruaIdh88o_wR0cDppsIPtuWoQ2VjXeCvz_eRXdaGqkRzlr0EqPZHtgxEzhf6TTIpnl73RnbA8erBkWjmhBuqEViifSz4aftWimQiwQ8c_ZuAu6L8FzEeeP0cLniz9nq_e1Y8tDZE9c2-Zd7TS9T84c8nAD-kY8-G7ipOpPmfDkdborpozuHcXYaOe47v8BeIGFRGbKvLkXYjmfcDcRHlyyX__scTkScqgisqv9M2CUMIJKmeJ9Q1QIsWzFRwZkR9qovUP_w3KPBf8wxC6UOKx8oUAKD_CxPYsZ3yYxlDmR2h4Swfp7lD_mh9YH0C0vndFuqvxx_S4bLh1RqfqTfYlGx9T9KkL_GcpMlZj_j91DkSyiANo_YrWr2PdNlrxB8NnSn66eYSColIKPwa-bR4_bBUhFiNA_t2Gk17_H9pJ8Fr33FCnDTBdBcDv5GWKKlofxvx4ztJYc4N6bB5j-vyAj4lwpXVf3QfeGLQ51NzrO4FTKvZGXKnj9xHFb70UTLixHn4uI0PxTMqn-hjLI_n_U5hVCsUUkzjNP6kGdAv1fagvH6a91Npy-Xaf9JPSKzWCKofyV6EcIq9QVUK5jGziwjAWpnRZsHl8C2KMYDAjHftNxaDsIc76u9zzyQOdTaIoNowBYRdqQDS3J1eT5K9dL-cqHpCCKEPFIStQcXwf4Pfo8RwjYs7NvFP3l8E6cBr6wUGnDQfrhrYFocBdOLSGdoHrBP4lvPRQIacR2feeVET2_3wgLC5qvaHnjsa9EHTvRCf-5KDbFuF9nGAh7ZPFiJRwHesj5M54hiCySZpJaR-OfKxFRTPCQK4q6pwR9eB4VYXy2CgtlAx1tPWArdaTEutdGmm8zsd96A2WxLpM8RwPMt2_VbqtruHtdYx2dHF6OSvM5Jgl99-YTtvGPbTBCaEcdFQ8NZC4bLigL9qfaPERSd9GZLec-s8D9nyzfl60V1APQjaInGqv-pT2-7DRL0KFHdOCTzAs_pqDX6q7HpETXTIGi9ZX_IJKf3toFlRKzeKeFcHPTQ10qQcXnjfnpva-GYT3n40-G9qB4YyLK2_AX0CohC-__vLl0y-_e_--8HPHlYttMgxvn6X4hjHGxfghFPtEnsV2FtlAZHFgUisOY-csjpBImtvUCEstwvvj0PW-D1FreVdL7sdDw6HVBtpBsWBL9fe81boI2tZJ1Yg-9t1nM7fYb-6IHHBcCcMw6wd78c2bFKa-eblvpLIklc2k7FCHlk9W-JZjRF69vO0_0FskhCIhdPoKSWcjknBU_o7wJglvZuo7fR16C_iWbQKPEWcboW5dh991hI2OkDtUp6-0tzCKeYBN8iVGJz_6sfFOxBNW-Q0WvpGPrXqqhF8dWM47G7ogKvE0NkoMwoJ12vDG32t121ru_JEAX2KfQCvs0yb10GnuxW7qU_DrRbCLx1HaAYVukE700rdGyMrlS7PLm22-pS98l62LDcEEl_nLZVeusgYX26bIaJHXpOU15qymtGyzosSseBE7gkmBt9kmy8l6lS8LktV5wQgrt5tNS0q0wryjQi79HX2pzflFWDvwXVZsi3X2ImnNpQ0XfUImuy0ixF_8zc5LLerhbNEKS2GdveM44STfMUPtxQ9gqWkY2YNquBl7AAg_Wv1t55mUl8HI3eP1_CzcZaiXTHez_1Lw-nuj403sFGz3F_Zk_nVH_h0AAP__Zgjt8g">