| Issue |
56671
|
| Summary |
Clang misaligns variables stored in coroutine frames
|
| Labels |
new issue
|
| Assignees |
|
| Reporter |
jacobsa
|
Clang seems to fail to correctly align objects in a coroutine frame that need more than 8 bytes of alignment on x86-64. Here is a program that demonstrates this by having a 64-byte-aligned object persist across a `co_await` ([Compiler Explorer](https://godbolt.org/z/bnxEY7Mf1)):
```c++
#include <stdlib.h>
#include <coroutine>
#include <cstdint>
#include <iostream>
struct Promise;
struct Task {
using promise_type = Promise;
};
// A promise type that never suspends.
struct Promise {
std::suspend_never initial_suspend() { return {}; }
void unhandled_exception() {}
std::suspend_never final_suspend() noexcept { return {}; }
Task get_return_object() { return Task{}; }
void return_value(const bool value) {}
};
// An awaitable that is always immediately ready with the value true.
struct Awaitable final {
// __attribute__((noinline)) apparently prevents the compiler from seeing that
// co_await can be a no-op.
bool __attribute__((noinline)) await_ready() { return true; }
void await_suspend(std::coroutine_handle<> h) {}
bool await_resume() { return true; }
};
// Crash if p is not aligned to 64 bytes.
void __attribute__((noinline)) CheckAlignment(void* const p) {
if (reinterpret_cast<intptr_t>(p) % 64 == 0) {
return;
}
std::cerr << "Bad alignment: " << p << "\n";
exit(1);
}
// A class that needs to be aligned to 64 bytes, and crashes if it isn't.
class HighlyAligned final {
public:
explicit HighlyAligned() { CheckAlignment(this); }
private:
alignas(64) char storage[16];
};
static_assert(alignof(HighlyAligned) == 64);
// A coroutine that creates an object that needs to be aligned to 64 bytes in
// the coroutine frame, ensuring it exists across a co_await.
Task Coroutine() {
auto a = HighlyAligned();
const bool result = co_await Awaitable{};
static_cast<void>(a);
co_return result;
}
int main(int argc, char** argv) {
Coroutine();
}
```
This dies pretty reliably with a `Bad alignment` message. If you instead change the program so that it creates `HighlyAligned` objects on the stack in `main`, it doesn't crash.
(For the record, [here](https://godbolt.org/z/bnxEY7Mf1) is a gtest version that is a little easier to work with but has more dependencies.)
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs