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