1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // UNSUPPORTED: c++03 10 // REQUIRES: has-1024-bit-atomics 11 // ADDITIONAL_COMPILE_FLAGS: -Wno-psabi 12 // ... since C++20 std::__atomic_base initializes, so we get a warning about an 13 // ABI change for vector variants since the constructor code for that is 14 // different if one were to compile with architecture-specific vector 15 // extensions enabled. 16 // This however isn't ABI breaking as it was impossible for any code to trigger 17 // this without using libc++ internals. 18 19 // GCC currently fails because it needs -fabi-version=6 to fix mangling of 20 // std::atomic when used with __attribute__((vector(X))). 21 // XFAIL: gcc 22 23 // This fails on PowerPC, as the LLIArr2 and Padding structs do not have 24 // adequate alignment, despite these types returning true for the query of 25 // being lock-free. This is an issue that occurs when linking in the 26 // PowerPC GNU libatomic library into the test. 27 // XFAIL: target=powerpc{{.*}}le-unknown-linux-gnu 28 29 // <atomic> 30 31 // Verify that the content of atomic<T> is properly aligned if the type is 32 // lock-free. This can't be observed through the atomic<T> API. It is 33 // nonetheless required for correctness of the implementation: lock-free implies 34 // that ISA instructions are used, and these instructions assume "suitable 35 // alignment". Supported architectures all require natural alignment for 36 // lock-freedom (e.g. load-linked / store-conditional, or cmpxchg). 37 38 #include <atomic> 39 #include <cassert> 40 #include <cstddef> 41 42 template <typename T> 43 struct atomic_test : public std::__atomic_base<T> { atomic_testatomic_test44 atomic_test() { 45 if (this->is_lock_free()) { 46 using AtomicImpl = decltype(this->__a_); 47 assert(alignof(AtomicImpl) >= sizeof(AtomicImpl) && 48 "expected natural alignment for lock-free type"); 49 } 50 } 51 }; 52 main(int,char **)53int main(int, char**) { 54 55 // structs and unions can't be defined in the template invocation. 56 // Work around this with a typedef. 57 #define CHECK_ALIGNMENT(T) \ 58 do { \ 59 typedef T type; \ 60 atomic_test<type> t; \ 61 } while (0) 62 63 CHECK_ALIGNMENT(bool); 64 CHECK_ALIGNMENT(char); 65 CHECK_ALIGNMENT(signed char); 66 CHECK_ALIGNMENT(unsigned char); 67 CHECK_ALIGNMENT(char16_t); 68 CHECK_ALIGNMENT(char32_t); 69 #ifndef TEST_HAS_NO_WIDE_CHARACTERS 70 CHECK_ALIGNMENT(wchar_t); 71 #endif 72 CHECK_ALIGNMENT(short); 73 CHECK_ALIGNMENT(unsigned short); 74 CHECK_ALIGNMENT(int); 75 CHECK_ALIGNMENT(unsigned int); 76 CHECK_ALIGNMENT(long); 77 CHECK_ALIGNMENT(unsigned long); 78 CHECK_ALIGNMENT(long long); 79 CHECK_ALIGNMENT(unsigned long long); 80 CHECK_ALIGNMENT(std::nullptr_t); 81 CHECK_ALIGNMENT(void *); 82 CHECK_ALIGNMENT(float); 83 CHECK_ALIGNMENT(double); 84 CHECK_ALIGNMENT(long double); 85 CHECK_ALIGNMENT(int __attribute__((vector_size(1 * sizeof(int))))); 86 CHECK_ALIGNMENT(int __attribute__((vector_size(2 * sizeof(int))))); 87 CHECK_ALIGNMENT(int __attribute__((vector_size(4 * sizeof(int))))); 88 CHECK_ALIGNMENT(int __attribute__((vector_size(16 * sizeof(int))))); 89 CHECK_ALIGNMENT(int __attribute__((vector_size(32 * sizeof(int))))); 90 CHECK_ALIGNMENT(float __attribute__((vector_size(1 * sizeof(float))))); 91 CHECK_ALIGNMENT(float __attribute__((vector_size(2 * sizeof(float))))); 92 CHECK_ALIGNMENT(float __attribute__((vector_size(4 * sizeof(float))))); 93 CHECK_ALIGNMENT(float __attribute__((vector_size(16 * sizeof(float))))); 94 CHECK_ALIGNMENT(float __attribute__((vector_size(32 * sizeof(float))))); 95 CHECK_ALIGNMENT(double __attribute__((vector_size(1 * sizeof(double))))); 96 CHECK_ALIGNMENT(double __attribute__((vector_size(2 * sizeof(double))))); 97 CHECK_ALIGNMENT(double __attribute__((vector_size(4 * sizeof(double))))); 98 CHECK_ALIGNMENT(double __attribute__((vector_size(16 * sizeof(double))))); 99 CHECK_ALIGNMENT(double __attribute__((vector_size(32 * sizeof(double))))); 100 CHECK_ALIGNMENT(struct Empty {}); 101 CHECK_ALIGNMENT(struct OneInt { int i; }); 102 CHECK_ALIGNMENT(struct IntArr2 { int i[2]; }); 103 CHECK_ALIGNMENT(struct FloatArr3 { float i[3]; }); 104 CHECK_ALIGNMENT(struct LLIArr2 { long long int i[2]; }); 105 CHECK_ALIGNMENT(struct LLIArr4 { long long int i[4]; }); 106 CHECK_ALIGNMENT(struct LLIArr8 { long long int i[8]; }); 107 CHECK_ALIGNMENT(struct LLIArr16 { long long int i[16]; }); 108 CHECK_ALIGNMENT(struct Padding { char c; /* padding */ long long int i; }); 109 CHECK_ALIGNMENT(union IntFloat { int i; float f; }); 110 CHECK_ALIGNMENT(enum class StrongEnum { foo }); 111 112 return 0; 113 } 114