Fix memory alignment on 32-bit Windows.

This commit is contained in:
Pāvels Nadtočajevs 2025-11-25 12:24:46 +02:00
parent 369afc7b46
commit 51ff09dc1e
No known key found for this signature in database
GPG key ID: 8413210218EF35D2
2 changed files with 13 additions and 4 deletions

View file

@ -41,7 +41,16 @@ constexpr size_t get_aligned_address(size_t p_address, size_t p_alignment) {
return (n_bytes_unaligned == 0) ? p_address : (p_address + p_alignment - n_bytes_unaligned); return (n_bytes_unaligned == 0) ? p_address : (p_address + p_alignment - n_bytes_unaligned);
} }
// Alignment: ↓ max_align_t ↓ uint64_t ↓ max_align_t #if defined(__MINGW32__) && !defined(__MINGW64__)
// Note: Using hardcoded value, since the value can end up different in different compile units on 32-bit windows
// due to a compiler bug (see GH-113145)
static constexpr size_t MAX_ALIGN = 16;
static_assert(MAX_ALIGN % alignof(max_align_t) == 0);
#else
static constexpr size_t MAX_ALIGN = alignof(max_align_t);
#endif
// Alignment: ↓ max_align_t ↓ uint64_t ↓ MAX_ALIGN
// ┌─────────────────┬──┬────────────────┬──┬───────────... // ┌─────────────────┬──┬────────────────┬──┬───────────...
// │ uint64_t │░░│ uint64_t │░░│ T[] // │ uint64_t │░░│ uint64_t │░░│ T[]
// │ alloc size │░░│ element count │░░│ data // │ alloc size │░░│ element count │░░│ data
@ -50,7 +59,7 @@ constexpr size_t get_aligned_address(size_t p_address, size_t p_alignment) {
inline constexpr size_t SIZE_OFFSET = 0; inline constexpr size_t SIZE_OFFSET = 0;
inline constexpr size_t ELEMENT_OFFSET = get_aligned_address(SIZE_OFFSET + sizeof(uint64_t), alignof(uint64_t)); inline constexpr size_t ELEMENT_OFFSET = get_aligned_address(SIZE_OFFSET + sizeof(uint64_t), alignof(uint64_t));
inline constexpr size_t DATA_OFFSET = get_aligned_address(ELEMENT_OFFSET + sizeof(uint64_t), alignof(max_align_t)); inline constexpr size_t DATA_OFFSET = get_aligned_address(ELEMENT_OFFSET + sizeof(uint64_t), MAX_ALIGN);
template <bool p_ensure_zero = false> template <bool p_ensure_zero = false>
void *alloc_static(size_t p_bytes, bool p_pad_align = false); void *alloc_static(size_t p_bytes, bool p_pad_align = false);

View file

@ -60,7 +60,7 @@ public:
static constexpr USize MAX_INT = INT64_MAX; static constexpr USize MAX_INT = INT64_MAX;
private: private:
// Alignment: ↓ max_align_t ↓ USize ↓ USize ↓ max_align_t // Alignment: ↓ max_align_t ↓ USize ↓ USize ↓ MAX_ALIGN
// ┌────────────────────┬──┬───────────────┬──┬─────────────┬──┬───────────... // ┌────────────────────┬──┬───────────────┬──┬─────────────┬──┬───────────...
// │ SafeNumeric<USize> │░░│ USize │░░│ USize │░░│ T[] // │ SafeNumeric<USize> │░░│ USize │░░│ USize │░░│ T[]
// │ ref. count │░░│ data capacity │░░│ data size │░░│ data // │ ref. count │░░│ data capacity │░░│ data size │░░│ data
@ -70,7 +70,7 @@ private:
static constexpr size_t REF_COUNT_OFFSET = 0; static constexpr size_t REF_COUNT_OFFSET = 0;
static constexpr size_t CAPACITY_OFFSET = Memory::get_aligned_address(REF_COUNT_OFFSET + sizeof(SafeNumeric<USize>), alignof(USize)); static constexpr size_t CAPACITY_OFFSET = Memory::get_aligned_address(REF_COUNT_OFFSET + sizeof(SafeNumeric<USize>), alignof(USize));
static constexpr size_t SIZE_OFFSET = Memory::get_aligned_address(CAPACITY_OFFSET + sizeof(USize), alignof(USize)); static constexpr size_t SIZE_OFFSET = Memory::get_aligned_address(CAPACITY_OFFSET + sizeof(USize), alignof(USize));
static constexpr size_t DATA_OFFSET = Memory::get_aligned_address(SIZE_OFFSET + sizeof(USize), alignof(max_align_t)); static constexpr size_t DATA_OFFSET = Memory::get_aligned_address(SIZE_OFFSET + sizeof(USize), Memory::MAX_ALIGN);
mutable T *_ptr = nullptr; mutable T *_ptr = nullptr;