- Notifications
You must be signed in to change notification settings - Fork 15.3k
Labels
coroutinesC++20 coroutinesC++20 coroutines
Description
Using clang/llvm/libc++ at head (0996696):
#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.
Metadata
Metadata
Assignees
Labels
coroutinesC++20 coroutinesC++20 coroutines