Skip to content

Commit

Permalink
Workaround an alignment issue for 32-bit MinGW targets
Browse files Browse the repository at this point in the history
Long story short, 32-bit Windows only guarantees 8-byte alignment from malloc,
while MinGW generates a default operator new that assumes 16-byte alignment
from malloc. Forcing 32-byte alignment for affected structs will make MinGW use
the aligned operator new, ensuring correct (if excessive) alignment.
  • Loading branch information
kcat committed Jul 2, 2024
1 parent ae19ff2 commit ef13491
Show file tree
Hide file tree
Showing 12 changed files with 36 additions and 14 deletions.
18 changes: 18 additions & 0 deletions common/opthelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,24 @@
#define NOINLINE
#endif

#if defined(__MINGW32__) && defined(__i386__)
/* 32-bit MinGW targets have a bug where __STDCPP_DEFAULT_NEW_ALIGNMENT__
* reports 16, despite the default operator new calling standard malloc which
* only guarantees 8-byte alignment. As a result, structs that need and specify
* 16-byte alignment only get 8-byte alignment. Explicitly specifying 32-byte
* alignment forces the over-aligned operator new to be called, giving the
* correct (if larger than necessary) alignment.
*
* Technically this bug affects 32-bit GCC more generally, but typically only
* with fairly old glibc versions as newer versions do guarantee the 16-byte
* alignment as specified. MinGW is reliant on msvcrt.dll's malloc however,
* which can't be updated to give that guarantee.
*/
#define SIMDALIGN alignas(32)
#else
#define SIMDALIGN
#endif

/* Unlike the likely attribute, ASSUME requires the condition to be true or
* else it invokes undefined behavior. It's essentially an assert without
* actually checking the condition at run-time, allowing for stronger
Expand Down
2 changes: 1 addition & 1 deletion common/phase_shifter.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
* signal delay (FilterSize/2) to properly align.
*/
template<std::size_t FilterSize>
struct PhaseShifterT {
struct SIMDALIGN PhaseShifterT {
static_assert(FilterSize >= 16, "FilterSize needs to be at least 16");
static_assert((FilterSize&(FilterSize-1)) == 0, "FilterSize needs to be power-of-two");

Expand Down
3 changes: 2 additions & 1 deletion core/bformatdec.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@
#include "devformat.h"
#include "filters/splitter.h"
#include "front_stablizer.h"
#include "opthelpers.h"


using ChannelDec = std::array<float,MaxAmbiChannels>;

class BFormatDec {
class SIMDALIGN BFormatDec {
static constexpr size_t sHFBand{0};
static constexpr size_t sLFBand{1};
static constexpr size_t sNumBands{2};
Expand Down
3 changes: 2 additions & 1 deletion core/bsinc_tables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "alnumeric.h"
#include "alspan.h"
#include "bsinc_defs.h"
#include "opthelpers.h"
#include "resampler_limits.h"


Expand Down Expand Up @@ -153,7 +154,7 @@ constexpr BSincHeader bsinc24_hdr{60, 23};


template<const BSincHeader &hdr>
struct BSincFilterArray {
struct SIMDALIGN BSincFilterArray {
alignas(16) std::array<float, hdr.total_size> mTable{};

BSincFilterArray()
Expand Down
3 changes: 2 additions & 1 deletion core/cubic_tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
#include <cstddef>

#include "cubic_defs.h"
#include "opthelpers.h"


struct CubicTable {
struct SIMDALIGN CubicTable {
std::array<CubicCoefficients,CubicPhaseCount> mTable{};
};

Expand Down
2 changes: 1 addition & 1 deletion core/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ enum class DeviceState : std::uint8_t {
Playing
};

struct DeviceBase {
struct SIMDALIGN DeviceBase {
std::atomic<bool> Connected{true};
const DeviceType Type{};

Expand Down
3 changes: 2 additions & 1 deletion core/effects/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "alspan.h"
#include "core/bufferline.h"
#include "intrusive_ptr.h"
#include "opthelpers.h"

struct BufferStorage;
struct ContextBase;
Expand Down Expand Up @@ -193,7 +194,7 @@ struct EffectTarget {
RealMixParams *RealOut;
};

struct EffectState : public al::intrusive_ref<EffectState> {
struct SIMDALIGN EffectState : public al::intrusive_ref<EffectState> {
al::span<FloatBufferLine> mOutTarget;


Expand Down
1 change: 0 additions & 1 deletion core/hrtf.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

#include "almalloc.h"
#include "alspan.h"
#include "atomic.h"
#include "ambidefs.h"
#include "bufferline.h"
#include "flexarray.h"
Expand Down
2 changes: 1 addition & 1 deletion core/mastering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
/* These structures assume BufferLineSize is a power of 2. */
static_assert((BufferLineSize & (BufferLineSize-1)) == 0, "BufferLineSize is not a power of 2");

struct SlidingHold {
struct SIMDALIGN SlidingHold {
alignas(16) FloatBufferLine mValues;
std::array<uint,BufferLineSize> mExpiries;
uint mLowerIndex;
Expand Down
4 changes: 2 additions & 2 deletions core/mastering.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
#include <array>
#include <memory>

#include "almalloc.h"
#include "alnumeric.h"
#include "alspan.h"
#include "bufferline.h"
#include "opthelpers.h"
#include "vector.h"

struct SlidingHold;
Expand All @@ -25,7 +25,7 @@ using uint = unsigned int;
*
* http://c4dm.eecs.qmul.ac.uk/audioengineering/compressors/
*/
class Compressor {
class SIMDALIGN Compressor {
size_t mNumChans{0u};

struct AutoFlags {
Expand Down
5 changes: 3 additions & 2 deletions core/uhjfilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "alspan.h"
#include "bufferline.h"
#include "opthelpers.h"


inline constexpr std::size_t UhjLength256{256};
Expand Down Expand Up @@ -36,7 +37,7 @@ struct UhjAllPassFilter {
};


struct UhjEncoderBase {
struct SIMDALIGN UhjEncoderBase {
UhjEncoderBase() = default;
UhjEncoderBase(const UhjEncoderBase&) = delete;
UhjEncoderBase(UhjEncoderBase&&) = delete;
Expand Down Expand Up @@ -120,7 +121,7 @@ struct UhjEncoderIIR final : public UhjEncoderBase {
};


struct DecoderBase {
struct SIMDALIGN DecoderBase {
static constexpr std::size_t sMaxPadding{256};

/* For 2-channel UHJ, shelf filters should use these LF responses. */
Expand Down
4 changes: 2 additions & 2 deletions core/voice.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include <optional>
#include <string>

#include "almalloc.h"
#include "alspan.h"
#include "bufferline.h"
#include "buffer_storage.h"
Expand All @@ -20,6 +19,7 @@
#include "filters/splitter.h"
#include "mixer/defs.h"
#include "mixer/hrtfdefs.h"
#include "opthelpers.h"
#include "resampler_limits.h"
#include "uhjfilter.h"
#include "vector.h"
Expand Down Expand Up @@ -180,7 +180,7 @@ enum : uint {
VoiceFlagCount
};

struct Voice {
struct SIMDALIGN Voice {
enum State {
Stopped,
Playing,
Expand Down

0 comments on commit ef13491

Please sign in to comment.