1 /* Alignment
2  * Created by Evan Nemerson <evan@nemerson.com>
3  *
4  *   To the extent possible under law, the authors have waived all
5  *   copyright and related or neighboring rights to this code.  For
6  *   details, see the Creative Commons Zero 1.0 Universal license at
7  *   <https://creativecommons.org/publicdomain/zero/1.0/>
8  *
9  * SPDX-License-Identifier: CC0-1.0
10  *
11  **********************************************************************
12  *
13  * This is portability layer which should help iron out some
14  * differences across various compilers, as well as various verisons of
15  * C and C++.
16  *
17  * It was originally developed for SIMD Everywhere
18  * (<https://github.com/simd-everywhere/simde>), but since its only
19  * dependency is Hedley (<https://nemequ.github.io/hedley>, also CC0)
20  * it can easily be used in other projects, so please feel free to do
21  * so.
22  *
23  * If you do use this in your project, please keep a link to SIMDe in
24  * your code to remind you where to report any bugs and/or check for
25  * updated versions.
26  *
27  * # API Overview
28  *
29  * The API has several parts, and most macros have a few variations.
30  * There are APIs for declaring aligned fields/variables, optimization
31  * hints, and run-time alignment checks.
32  *
33  * Briefly, macros ending with "_TO" take numeric values and are great
34  * when you know the value you would like to use.  Macros ending with
35  * "_LIKE", on the other hand, accept a type and are used when you want
36  * to use the alignment of a type instead of hardcoding a value.
37  *
38  * Documentation for each section of the API is inline.
39  *
40  * True to form, MSVC is the main problem and imposes several
41  * limitations on the effectiveness of the APIs.  Detailed descriptions
42  * of the limitations of each macro are inline, but in general:
43  *
44  *  * On C11+ or C++11+ code written using this API will work.  The
45  *    ASSUME macros may or may not generate a hint to the compiler, but
46  *    that is only an optimization issue and will not actually cause
47  *    failures.
48  *  * If you're using pretty much any compiler other than MSVC,
49  *    everything should basically work as well as in C11/C++11.
50  */
51 
52 #if !defined(SIMDE_ALIGN_H)
53 #define SIMDE_ALIGN_H
54 
55 #include "hedley.h"
56 
57 /* I know this seems a little silly, but some non-hosted compilers
58  * don't have stddef.h, so we try to accomodate them. */
59 #if !defined(SIMDE_ALIGN_SIZE_T_)
60   #if defined(__SIZE_TYPE__)
61     #define SIMDE_ALIGN_SIZE_T_ __SIZE_TYPE__
62   #elif defined(__SIZE_T_TYPE__)
63     #define SIMDE_ALIGN_SIZE_T_ __SIZE_TYPE__
64   #elif defined(__cplusplus)
65     #include <cstddef>
66     #define SIMDE_ALIGN_SIZE_T_ size_t
67   #else
68     #include <stddef.h>
69     #define SIMDE_ALIGN_SIZE_T_ size_t
70   #endif
71 #endif
72 
73 #if !defined(SIMDE_ALIGN_INTPTR_T_)
74   #if defined(__INTPTR_TYPE__)
75     #define SIMDE_ALIGN_INTPTR_T_ __INTPTR_TYPE__
76   #elif defined(__PTRDIFF_TYPE__)
77     #define SIMDE_ALIGN_INTPTR_T_ __PTRDIFF_TYPE__
78   #elif defined(__PTRDIFF_T_TYPE__)
79     #define SIMDE_ALIGN_INTPTR_T_ __PTRDIFF_T_TYPE__
80   #elif defined(__cplusplus)
81     #include <cstddef>
82     #define SIMDE_ALIGN_INTPTR_T_ ptrdiff_t
83   #else
84     #include <stddef.h>
85     #define SIMDE_ALIGN_INTPTR_T_ ptrdiff_t
86   #endif
87 #endif
88 
89 #if defined(SIMDE_ALIGN_DEBUG)
90   #if defined(__cplusplus)
91     #include <cstdio>
92   #else
93     #include <stdio.h>
94   #endif
95 #endif
96 
97 /* SIMDE_ALIGN_OF(Type)
98  *
99  * The SIMDE_ALIGN_OF macro works like alignof, or _Alignof, or
100  * __alignof, or __alignof__, or __ALIGNOF__, depending on the compiler.
101  * It isn't defined everywhere (only when the compiler has some alignof-
102  * like feature we can use to implement it), but it should work in most
103  * modern compilers, as well as C11 and C++11.
104  *
105  * If we can't find an implementation for SIMDE_ALIGN_OF then the macro
106  * will not be defined, so if you can handle that situation sensibly
107  * you may need to sprinkle some ifdefs into your code.
108  */
109 #if \
110     (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
111     (0 && HEDLEY_HAS_FEATURE(c_alignof))
112   #define SIMDE_ALIGN_OF(Type) _Alignof(Type)
113 #elif \
114     (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
115     (0 && HEDLEY_HAS_FEATURE(cxx_alignof))
116   #define SIMDE_ALIGN_OF(Type) alignof(Type)
117 #elif \
118     HEDLEY_GCC_VERSION_CHECK(2,95,0) || \
119     HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
120     HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
121     HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
122     HEDLEY_TINYC_VERSION_CHECK(0,9,24) || \
123     HEDLEY_PGI_VERSION_CHECK(19,10,0) || \
124     HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
125     HEDLEY_TI_ARMCL_VERSION_CHECK(16,9,0) || \
126     HEDLEY_TI_CL2000_VERSION_CHECK(16,9,0) || \
127     HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
128     HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
129     HEDLEY_TI_CL430_VERSION_CHECK(16,9,0) || \
130     HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,2) || \
131     defined(__IBM__ALIGNOF__) || \
132     defined(__clang__)
133   #define SIMDE_ALIGN_OF(Type) __alignof__(Type)
134 #elif \
135   HEDLEY_IAR_VERSION_CHECK(8,40,0)
136   #define SIMDE_ALIGN_OF(Type) __ALIGNOF__(Type)
137 #elif \
138   HEDLEY_MSVC_VERSION_CHECK(19,0,0)
139   /* Probably goes back much further, but MS takes down their old docs.
140    * If you can verify that this works in earlier versions please let
141    * me know! */
142   #define SIMDE_ALIGN_OF(Type) __alignof(Type)
143 #endif
144 
145 /* SIMDE_ALIGN_MAXIMUM:
146  *
147  * This is the maximum alignment that the compiler supports.  You can
148  * define the value prior to including SIMDe if necessary, but in that
149  * case *please* submit an issue so we can add the platform to the
150  * detection code.
151  *
152  * Most compilers are okay with types which are aligned beyond what
153  * they think is the maximum, as long as the alignment is a power
154  * of two.  MSVC is the exception (of course), so we need to cap the
155  * alignment requests at values that the implementation supports.
156  *
157  * XL C/C++ will accept values larger than 16 (which is the alignment
158  * of an AltiVec vector), but will not reliably align to the larger
159  * value, so so we cap the value at 16 there.
160  *
161  * If the compiler accepts any power-of-two value within reason then
162  * this macro should be left undefined, and the SIMDE_ALIGN_CAP
163  * macro will just return the value passed to it. */
164 #if !defined(SIMDE_ALIGN_MAXIMUM)
165   #if defined(HEDLEY_MSVC_VERSION)
166     #if defined(_M_IX86) || defined(_M_AMD64)
167       #if HEDLEY_MSVC_VERSION_CHECK(19,14,0)
168         #define SIMDE_ALIGN_PLATFORM_MAXIMUM 64
169       #elif HEDLEY_MSVC_VERSION_CHECK(16,0,0)
170         /* VS 2010 is really a guess based on Wikipedia; if anyone can
171          * test with old VS versions I'd really appreciate it. */
172         #define SIMDE_ALIGN_PLATFORM_MAXIMUM 32
173       #else
174         #define SIMDE_ALIGN_PLATFORM_MAXIMUM 16
175       #endif
176     #elif defined(_M_ARM) || defined(_M_ARM64)
177       #define SIMDE_ALIGN_PLATFORM_MAXIMUM 8
178     #endif
179   #elif defined(HEDLEY_IBM_VERSION)
180     #define SIMDE_ALIGN_PLATFORM_MAXIMUM 16
181   #endif
182 #endif
183 
184 /* You can mostly ignore these; they're intended for internal use.
185  * If you do need to use them please let me know; if they fulfill
186  * a common use case I'll probably drop the trailing underscore
187  * and make them part of the public API. */
188 #if defined(SIMDE_ALIGN_PLATFORM_MAXIMUM)
189   #if SIMDE_ALIGN_PLATFORM_MAXIMUM >= 64
190     #define SIMDE_ALIGN_64_ 64
191     #define SIMDE_ALIGN_32_ 32
192     #define SIMDE_ALIGN_16_ 16
193     #define SIMDE_ALIGN_8_ 8
194   #elif SIMDE_ALIGN_PLATFORM_MAXIMUM >= 32
195     #define SIMDE_ALIGN_64_ 32
196     #define SIMDE_ALIGN_32_ 32
197     #define SIMDE_ALIGN_16_ 16
198     #define SIMDE_ALIGN_8_ 8
199   #elif SIMDE_ALIGN_PLATFORM_MAXIMUM >= 16
200     #define SIMDE_ALIGN_64_ 16
201     #define SIMDE_ALIGN_32_ 16
202     #define SIMDE_ALIGN_16_ 16
203     #define SIMDE_ALIGN_8_ 8
204   #elif SIMDE_ALIGN_PLATFORM_MAXIMUM >= 8
205     #define SIMDE_ALIGN_64_ 8
206     #define SIMDE_ALIGN_32_ 8
207     #define SIMDE_ALIGN_16_ 8
208     #define SIMDE_ALIGN_8_ 8
209   #else
210     #error Max alignment expected to be >= 8
211   #endif
212 #else
213   #define SIMDE_ALIGN_64_ 64
214   #define SIMDE_ALIGN_32_ 32
215   #define SIMDE_ALIGN_16_ 16
216   #define SIMDE_ALIGN_8_ 8
217 #endif
218 
219 /**
220  * SIMDE_ALIGN_CAP(Alignment)
221  *
222  * Returns the minimum of Alignment or SIMDE_ALIGN_MAXIMUM.
223  */
224 #if defined(SIMDE_ALIGN_MAXIMUM)
225   #define SIMDE_ALIGN_CAP(Alignment) (((Alignment) < (SIMDE_ALIGN_PLATFORM_MAXIMUM)) ? (Alignment) : (SIMDE_ALIGN_PLATFORM_MAXIMUM))
226 #else
227   #define SIMDE_ALIGN_CAP(Alignment) (Alignment)
228 #endif
229 
230 /* SIMDE_ALIGN_TO(Alignment)
231  *
232  * SIMDE_ALIGN_TO is used to declare types or variables.  It basically
233  * maps to the align attribute in most compilers, the align declspec
234  * in MSVC, or _Alignas/alignas in C11/C++11.
235  *
236  * Example:
237  *
238  *   struct i32x4 {
239  *     SIMDE_ALIGN_TO(16) int32_t values[4];
240  *   }
241  *
242  * Limitations:
243  *
244  * MSVC requires that the Alignment parameter be numeric; you can't do
245  * something like `SIMDE_ALIGN_TO(SIMDE_ALIGN_OF(int))`.  This is
246  * unfortunate because that's really how the LIKE macros are
247  * implemented, and I am not aware of a way to get anything like this
248  * to work without using the C11/C++11 keywords.
249  *
250  * It also means that we can't use SIMDE_ALIGN_CAP to limit the
251  * alignment to the value specified, which MSVC also requires, so on
252  * MSVC you should use the `SIMDE_ALIGN_TO_8/16/32/64` macros instead.
253  * They work like `SIMDE_ALIGN_TO(SIMDE_ALIGN_CAP(Alignment))` would,
254  * but should be safe to use on MSVC.
255  *
256  * All this is to say that, if you want your code to work on MSVC, you
257  * should use the SIMDE_ALIGN_TO_8/16/32/64 macros below instead of
258  * SIMDE_ALIGN_TO(8/16/32/64).
259  */
260 #if \
261     HEDLEY_HAS_ATTRIBUTE(aligned) || \
262     HEDLEY_GCC_VERSION_CHECK(2,95,0) || \
263     HEDLEY_CRAY_VERSION_CHECK(8,4,0) || \
264     HEDLEY_IBM_VERSION_CHECK(11,1,0) || \
265     HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
266     HEDLEY_PGI_VERSION_CHECK(19,4,0) || \
267     HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
268     HEDLEY_TINYC_VERSION_CHECK(0,9,24) || \
269     HEDLEY_TI_ARMCL_VERSION_CHECK(16,9,0) || \
270     HEDLEY_TI_CL2000_VERSION_CHECK(16,9,0) || \
271     HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
272     HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
273     HEDLEY_TI_CL430_VERSION_CHECK(16,9,0) || \
274     HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,2)
275   #define SIMDE_ALIGN_TO(Alignment) __attribute__((__aligned__(SIMDE_ALIGN_CAP(Alignment))))
276 #elif \
277     (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L))
278   #define SIMDE_ALIGN_TO(Alignment) _Alignas(SIMDE_ALIGN_CAP(Alignment))
279 #elif \
280     (defined(__cplusplus) && (__cplusplus >= 201103L))
281   #define SIMDE_ALIGN_TO(Alignment) alignas(SIMDE_ALIGN_CAP(Alignment))
282 #elif \
283     defined(HEDLEY_MSVC_VERSION)
284   #define SIMDE_ALIGN_TO(Alignment) __declspec(align(Alignment))
285   /* Unfortunately MSVC can't handle __declspec(align(__alignof(Type)));
286    * the alignment passed to the declspec has to be an integer. */
287   #define SIMDE_ALIGN_OF_UNUSABLE_FOR_LIKE
288 #endif
289 #define SIMDE_ALIGN_TO_64 SIMDE_ALIGN_TO(SIMDE_ALIGN_64_)
290 #define SIMDE_ALIGN_TO_32 SIMDE_ALIGN_TO(SIMDE_ALIGN_32_)
291 #define SIMDE_ALIGN_TO_16 SIMDE_ALIGN_TO(SIMDE_ALIGN_16_)
292 #define SIMDE_ALIGN_TO_8 SIMDE_ALIGN_TO(SIMDE_ALIGN_8_)
293 
294 /* SIMDE_ALIGN_ASSUME_TO(Pointer, Alignment)
295  *
296  * SIMDE_ALIGN_ASSUME_TO is semantically similar to C++20's
297  * std::assume_aligned, or __builtin_assume_aligned.  It tells the
298  * compiler to assume that the provided pointer is aligned to an
299  * `Alignment`-byte boundary.
300  *
301  * If you define SIMDE_ALIGN_DEBUG prior to including this header then
302  * SIMDE_ALIGN_ASSUME_TO will turn into a runtime check.   We don't
303  * integrate with NDEBUG in this header, but it may be a good idea to
304  * put something like this in your code:
305  *
306  *   #if !defined(NDEBUG)
307  *     #define SIMDE_ALIGN_DEBUG
308  *   #endif
309  *   #include <.../simde-align.h>
310  */
311 #if \
312     HEDLEY_HAS_BUILTIN(__builtin_assume_aligned) || \
313     HEDLEY_GCC_VERSION_CHECK(4,7,0)
314   #define SIMDE_ALIGN_ASSUME_TO_UNCHECKED(Pointer, Alignment) \
315     HEDLEY_REINTERPRET_CAST(__typeof__(Pointer), __builtin_assume_aligned(HEDLEY_CONST_CAST(void*, HEDLEY_REINTERPRET_CAST(const void*, Pointer)), Alignment))
316 #elif HEDLEY_INTEL_VERSION_CHECK(13,0,0)
317   #define SIMDE_ALIGN_ASSUME_TO_UNCHECKED(Pointer, Alignment) (__extension__ ({ \
318       __typeof__(v) simde_assume_aligned_t_ = (Pointer); \
319       __assume_aligned(simde_assume_aligned_t_, Alignment); \
320       simde_assume_aligned_t_; \
321     }))
322 #elif defined(__cplusplus) && (__cplusplus > 201703L)
323   #include <memory>
324   #define SIMDE_ALIGN_ASSUME_TO_UNCHECKED(Pointer, Alignment) std::assume_aligned<Alignment>(Pointer)
325 #else
326   #if defined(__cplusplus)
simde_align_assume_to_unchecked(T * ptr,const size_t alignment)327     template<typename T> HEDLEY_ALWAYS_INLINE static T* simde_align_assume_to_unchecked(T* ptr, const size_t alignment)
328   #else
329     HEDLEY_ALWAYS_INLINE static void* simde_align_assume_to_unchecked(void* ptr, const size_t alignment)
330   #endif
331   {
332     HEDLEY_ASSUME((HEDLEY_REINTERPRET_CAST(size_t, (ptr)) % SIMDE_ALIGN_CAP(alignment)) == 0);
333     return ptr;
334   }
335   #if defined(__cplusplus)
336     #define SIMDE_ALIGN_ASSUME_TO_UNCHECKED(Pointer, Alignment) simde_align_assume_to_unchecked((Pointer), (Alignment))
337   #else
338     #define SIMDE_ALIGN_ASSUME_TO_UNCHECKED(Pointer, Alignment) simde_align_assume_to_unchecked(HEDLEY_CONST_CAST(void*, HEDLEY_REINTERPRET_CAST(const void*, Pointer)), (Alignment))
339   #endif
340 #endif
341 
342 #if !defined(SIMDE_ALIGN_DEBUG)
343   #define SIMDE_ALIGN_ASSUME_TO(Pointer, Alignment) SIMDE_ALIGN_ASSUME_TO_UNCHECKED(Pointer, Alignment)
344 #else
345   #include <stdio.h>
346   #if defined(__cplusplus)
347     template<typename T>
348     static HEDLEY_ALWAYS_INLINE
349     T*
simde_align_assume_to_checked_uncapped(T * ptr,const size_t alignment,const char * file,int line,const char * ptrname)350     simde_align_assume_to_checked_uncapped(T* ptr, const size_t alignment, const char* file, int line, const char* ptrname)
351   #else
352     static HEDLEY_ALWAYS_INLINE
353     void*
354     simde_align_assume_to_checked_uncapped(void* ptr, const size_t alignment, const char* file, int line, const char* ptrname)
355   #endif
356   {
357     if (HEDLEY_UNLIKELY((HEDLEY_REINTERPRET_CAST(SIMDE_ALIGN_INTPTR_T_, (ptr)) % HEDLEY_STATIC_CAST(SIMDE_ALIGN_INTPTR_T_, SIMDE_ALIGN_CAP(alignment))) != 0)) {
358       fprintf(stderr, "%s:%d: alignment check failed for `%s' (%p %% %u == %u)\n",
359         file, line, ptrname, HEDLEY_REINTERPRET_CAST(const void*, ptr),
360         HEDLEY_STATIC_CAST(unsigned int, SIMDE_ALIGN_CAP(alignment)),
361         HEDLEY_STATIC_CAST(unsigned int, HEDLEY_REINTERPRET_CAST(SIMDE_ALIGN_INTPTR_T_, (ptr)) % HEDLEY_STATIC_CAST(SIMDE_ALIGN_INTPTR_T_, SIMDE_ALIGN_CAP(alignment))));
362     }
363 
364     return ptr;
365   }
366 
367   #if defined(__cplusplus)
368     #define SIMDE_ALIGN_ASSUME_TO(Pointer, Alignment) simde_align_assume_to_checked_uncapped((Pointer), (Alignment), __FILE__, __LINE__, #Pointer)
369   #else
370     #define SIMDE_ALIGN_ASSUME_TO(Pointer, Alignment) simde_align_assume_to_checked_uncapped(HEDLEY_CONST_CAST(void*, HEDLEY_REINTERPRET_CAST(const void*, Pointer)), (Alignment), __FILE__, __LINE__, #Pointer)
371   #endif
372 #endif
373 
374 /* SIMDE_ALIGN_LIKE(Type)
375  * SIMDE_ALIGN_LIKE_#(Type)
376  *
377  * The SIMDE_ALIGN_LIKE macros are similar to the SIMDE_ALIGN_TO macros
378  * except instead of an integer they take a type; basically, it's just
379  * a more convenient way to do something like:
380  *
381  *   SIMDE_ALIGN_TO(SIMDE_ALIGN_OF(Type))
382  *
383  * The versions with a numeric suffix will fall back on using a numeric
384  * value in the event we can't use SIMDE_ALIGN_OF(Type).  This is
385  * mainly for MSVC, where __declspec(align()) can't handle anything
386  * other than hard-coded numeric values.
387  */
388 #if defined(SIMDE_ALIGN_OF) && defined(SIMDE_ALIGN_TO) && !defined(SIMDE_ALIGN_OF_UNUSABLE_FOR_LIKE)
389   #define SIMDE_ALIGN_LIKE(Type) SIMDE_ALIGN_TO(SIMDE_ALIGN_OF(Type))
390   #define SIMDE_ALIGN_LIKE_64(Type) SIMDE_ALIGN_LIKE(Type)
391   #define SIMDE_ALIGN_LIKE_32(Type) SIMDE_ALIGN_LIKE(Type)
392   #define SIMDE_ALIGN_LIKE_16(Type) SIMDE_ALIGN_LIKE(Type)
393   #define SIMDE_ALIGN_LIKE_8(Type) SIMDE_ALIGN_LIKE(Type)
394 #else
395   #define SIMDE_ALIGN_LIKE_64(Type) SIMDE_ALIGN_TO_64
396   #define SIMDE_ALIGN_LIKE_32(Type) SIMDE_ALIGN_TO_32
397   #define SIMDE_ALIGN_LIKE_16(Type) SIMDE_ALIGN_TO_16
398   #define SIMDE_ALIGN_LIKE_8(Type) SIMDE_ALIGN_TO_8
399 #endif
400 
401 /* SIMDE_ALIGN_ASSUME_LIKE(Pointer, Type)
402  *
403  * Tihs is similar to SIMDE_ALIGN_ASSUME_TO, except that it takes a
404  * type instead of a numeric value. */
405 #if defined(SIMDE_ALIGN_OF) && defined(SIMDE_ALIGN_ASSUME_TO)
406   #define SIMDE_ALIGN_ASSUME_LIKE(Pointer, Type) SIMDE_ALIGN_ASSUME_TO(Pointer, SIMDE_ALIGN_OF(Type))
407 #endif
408 
409 /* SIMDE_ALIGN_CAST(Type, Pointer)
410  *
411  * SIMDE_ALIGN_CAST is like C++'s reinterpret_cast, but it will try
412  * to silence warnings that some compilers may produce if you try
413  * to assign to a type with increased alignment requirements.
414  *
415  * Note that it does *not* actually attempt to tell the compiler that
416  * the pointer is aligned like the destination should be; that's the
417  * job of the next macro.  This macro is necessary for stupid APIs
418  * like _mm_loadu_si128 where the input is a __m128i* but the function
419  * is specifically for data which isn't necessarily aligned to
420  * _Alignof(__m128i).
421  */
422 #if HEDLEY_HAS_WARNING("-Wcast-align") || defined(__clang__) || HEDLEY_GCC_VERSION_CHECK(3,4,0)
423   #define SIMDE_ALIGN_CAST(Type, Pointer) (__extension__({ \
424       HEDLEY_DIAGNOSTIC_PUSH \
425       _Pragma("GCC diagnostic ignored \"-Wcast-align\"") \
426       Type simde_r_ = HEDLEY_REINTERPRET_CAST(Type, Pointer); \
427       HEDLEY_DIAGNOSTIC_POP \
428       simde_r_; \
429     }))
430 #else
431   #define SIMDE_ALIGN_CAST(Type, Pointer) HEDLEY_REINTERPRET_CAST(Type, Pointer)
432 #endif
433 
434 /* SIMDE_ALIGN_ASSUME_CAST(Type, Pointer)
435  *
436  * This is sort of like a combination of a reinterpret_cast and a
437  * SIMDE_ALIGN_ASSUME_LIKE.  It uses SIMDE_ALIGN_ASSUME_LIKE to tell
438  * the compiler that the pointer is aligned like the specified type
439  * and casts the pointer to the specified type while suppressing any
440  * warnings from the compiler about casting to a type with greater
441  * alignment requirements.
442  */
443 #define SIMDE_ALIGN_ASSUME_CAST(Type, Pointer) SIMDE_ALIGN_ASSUME_LIKE(SIMDE_ALIGN_CAST(Type, Pointer), Type)
444 
445 #endif /* !defined(SIMDE_ALIGN_H) */
446