Issue |
159571
|
Summary |
crash on load of under-aligned i128 from coroutine frame
|
Labels |
coroutines
|
Assignees |
|
Reporter |
zmodem
|
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.
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs