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

Reply via email to