FastLED 3.9.15
Loading...
Searching...
No Matches
align.h
Go to the documentation of this file.
1#pragma once
2
9
10#include "fl/stl/cstddef.h"
11#include "platforms/is_platform.h" // IWYU pragma: keep
12#include "fl/stl/noexcept.h"
13
14// ============================================================================
15// FL_ALIGNAS(N) - Numeric alignment specifier
16// ============================================================================
17// Aligns storage to N bytes (must be a power of 2).
18// Usage: struct FL_ALIGNAS(8) AlignedStruct { char data[10]; };
19#if defined(FL_IS_AVR)
20 // AVR (8-bit): No alignment required - make it a no-op to save RAM
21 #define FL_ALIGNAS(N) /* nothing */
22#elif defined(ESP8266)
23 // ESP8266: Cap at 4 bytes - memalign() not available in libstdc++.
24 // Over-aligned types (alignas(N) with N > default new alignment)
25 // trigger aligned operator new, which calls memalign() and fails at link time.
26 #define FL_ALIGNAS(N) __attribute__((aligned(4)))
27#elif defined(__GNUC__) && !defined(__clang__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 500
28 // GCC 4.x: Use __attribute__ syntax (more reliable than alignas)
29 #define FL_ALIGNAS(N) __attribute__((aligned(N)))
30#else
31 // Modern compilers (GCC 5.0+, Clang, MSVC): Use C++11 alignas
32 #define FL_ALIGNAS(N) alignas(N)
33#endif
34
35// ============================================================================
36// FL_ALIGN - Fixed alignment (Emscripten: 8 bytes, others: no-op)
37// ============================================================================
38#ifdef FL_IS_WASM
39 #define FL_ALIGN_BYTES 8
40 #define FL_ALIGN FL_ALIGNAS(FL_ALIGN_BYTES)
41#else
42 #define FL_ALIGN_BYTES 1
43 #define FL_ALIGN
44#endif
45
46// ============================================================================
47// FL_ALIGN_AS(T) - Type-based alignment using alignof(T)
48// ============================================================================
49// Aligns storage to match the alignment requirements of type T.
50// Usage: struct FL_ALIGN_AS(int) AlignedStruct { char data[10]; };
51#if defined(FL_IS_AVR)
52 // AVR (8-bit): No alignment required - make it a no-op to save RAM
53 #define FL_ALIGN_AS(T) /* nothing */
54#elif defined(__EMSCRIPTEN__)
55 // Emscripten/WASM: No-op to avoid alignment issues in WASM builds
56 #define FL_ALIGN_AS(T) /* nothing */
57#elif defined(ESP8266)
58 // ESP8266: Cap at 4 bytes (see FL_ALIGNAS above for rationale)
59 #define FL_ALIGN_AS(T) __attribute__((aligned(4)))
60#elif defined(__GNUC__) && !defined(__clang__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 500
61 // GCC 4.x: Use __attribute__ syntax with __alignof__ (more reliable than alignas)
62 // This avoids potential issues with alignas(alignof(T)) on older GCC versions
63 #define FL_ALIGN_AS(T) __attribute__((aligned(__alignof__(T))))
64#else
65 // Modern compilers (GCC 5.0+, Clang, MSVC, Emscripten): Use C++11 alignas
66 #define FL_ALIGN_AS(T) alignas(alignof(T))
67#endif
68
69// ============================================================================
70// FL_ALIGN_MAX - Maximum platform alignment (for generic storage)
71// ============================================================================
72// Aligns storage to the maximum alignment requirement on the platform.
73// Suitable for generic type-erased storage that may hold any type.
74// Usage: struct FL_ALIGN_MAX GenericStorage { char bytes[64]; };
75#if defined(FL_IS_AVR)
76 // AVR (8-bit): No alignment required - make it a no-op to save RAM
77 #define FL_ALIGN_MAX /* nothing */
78#elif defined(ESP8266)
79 // ESP8266: Cap at 4 bytes (see FL_ALIGNAS above for rationale)
80 #define FL_ALIGN_MAX __attribute__((aligned(4)))
81#elif defined(__GNUC__) && !defined(__clang__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 500
82 // GCC 4.x: Use __attribute__ syntax with max alignment
83 // Note: max_align_t might not be available on all GCC 4.x targets, use conservative 8-byte alignment
84 #define FL_ALIGN_MAX __attribute__((aligned(8)))
85#else
86 // Modern compilers: Use C++11 alignas(max_align_t)
87 #define FL_ALIGN_MAX alignas(max_align_t)
88#endif
89
90// ============================================================================
91// FL_ALIGN_AS_T(expr) - Template expression-based alignment
92// ============================================================================
93// Workaround for GCC 4.8.3 bug: alignas() doesn't recognize template-dependent
94// expressions as compile-time constants. Use __attribute__ syntax instead.
95// For GCC < 5.0, use conservative fixed alignment; for modern compilers, use computed value.
96//
97// Usage: class FL_ALIGN_AS_T(max_align<Types...>::value) variant {};
98#if defined(FL_IS_AVR)
99 // AVR (8-bit): No alignment required, make it a no-op to save RAM
100 #define FL_ALIGN_AS_T(expr) /* nothing */
101#elif defined(__EMSCRIPTEN__)
102 // Emscripten/WASM: No-op to avoid alignment issues in WASM builds
103 #define FL_ALIGN_AS_T(expr) /* nothing */
104#elif defined(ESP8266)
105 // ESP8266: Cap at 4 bytes (see FL_ALIGNAS above for rationale)
106 #define FL_ALIGN_AS_T(expr) __attribute__((aligned(4)))
107#elif defined(__GNUC__) && !defined(__clang__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 500
108 // GCC 4.x has alignas() bug with template-dependent expressions
109 // ARM/32-bit platforms: Use 8-byte alignment (safe for double/i64)
110 #define FL_ALIGN_AS_T(expr) __attribute__((aligned(8)))
111#else
112 // Modern compilers (GCC 5.0+, Clang): Use template-computed optimal alignment
113 #define FL_ALIGN_AS_T(expr) alignas(expr)
114#endif
115
116// ============================================================================
117// fl::assume_aligned<N>(ptr) - Pointer alignment hint for the optimizer
118// ============================================================================
119// Tells the compiler that ptr is aligned to N bytes, enabling better codegen
120// (SIMD loads, wider memory ops). This is a hint only — it does not enforce
121// alignment at the call site.
122
123namespace fl {
124
125template <fl::size_t N, typename T>
126inline T *assume_aligned(T *ptr) FL_NOEXCEPT {
127#if defined(FL_IS_AVR)
128 return ptr;
129#elif defined(FL_IS_CLANG) || defined(FL_IS_GCC)
130 return static_cast<T *>(__builtin_assume_aligned(ptr, N));
131#elif defined(FL_IS_WIN_MSVC)
132 // MSVC: __assume tells the optimizer the pointer is N-byte aligned.
133 // No __builtin_assume_aligned equivalent exists on MSVC.
134 __assume(((char *)ptr - (char *)0) % N == 0);
135 return ptr;
136#else
137 return ptr;
138#endif
139}
140
141template <fl::size_t N, typename T>
142inline const T *assume_aligned(const T *ptr) FL_NOEXCEPT {
143#if defined(FL_IS_AVR)
144 return ptr;
145#elif defined(FL_IS_CLANG) || defined(FL_IS_GCC)
146 return static_cast<const T *>(__builtin_assume_aligned(ptr, N));
147#elif defined(FL_IS_WIN_MSVC)
148 __assume(((const char *)ptr - (const char *)0) % N == 0);
149 return ptr;
150#else
151 return ptr;
152#endif
153}
154
155// ============================================================================
156// aligned_ptr<T, N> - Pointer wrapper encoding alignment in the type system
157// ============================================================================
158// Carries alignment as a template parameter so it propagates through call
159// chains via type checking. Functions that require aligned pointers should
160// accept aligned_ptr<T, N> instead of T* to prevent silent alignment loss.
161template <typename T, fl::size_t N>
164
165 public:
168
169 T *get() const FL_NOEXCEPT { return assume_aligned<N>(mPtr); }
170 T &operator[](fl::size_t i) const FL_NOEXCEPT { return get()[i]; }
171 explicit operator bool() const FL_NOEXCEPT { return mPtr != nullptr; }
172};
173
174} // namespace fl
T & operator[](fl::size_t i) const FL_NOEXCEPT
Definition align.h:170
aligned_ptr() FL_NOEXCEPT
Definition align.h:166
aligned_ptr(T *p) FL_NOEXCEPT
Definition align.h:167
T * get() const FL_NOEXCEPT
Definition align.h:169
__SIZE_TYPE__ size_t
Definition s16x16x4.h:16
T * assume_aligned(T *ptr) FL_NOEXCEPT
Definition align.h:126
Base definition for an LED controller.
Definition crgb.hpp:179
#define FL_NOEXCEPT