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 #ifndef _LIBCPP___TYPE_TRAITS_ALIGNED_STORAGE_H 10 #define _LIBCPP___TYPE_TRAITS_ALIGNED_STORAGE_H 11 12 #include <__config> 13 #include <__type_traits/conditional.h> 14 #include <__type_traits/integral_constant.h> 15 #include <__type_traits/nat.h> 16 #include <__type_traits/type_list.h> 17 #include <cstddef> 18 19 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 20 # pragma GCC system_header 21 #endif 22 23 _LIBCPP_BEGIN_NAMESPACE_STD 24 25 template <class _Tp> 26 struct __align_type { 27 static const size_t value = _LIBCPP_PREFERRED_ALIGNOF(_Tp); 28 typedef _Tp type; 29 }; 30 31 struct __struct_double { 32 long double __lx; 33 }; 34 struct __struct_double4 { 35 double __lx[4]; 36 }; 37 38 // clang-format off 39 typedef __type_list<__align_type<unsigned char>, 40 __type_list<__align_type<unsigned short>, 41 __type_list<__align_type<unsigned int>, 42 __type_list<__align_type<unsigned long>, 43 __type_list<__align_type<unsigned long long>, 44 __type_list<__align_type<double>, 45 __type_list<__align_type<long double>, 46 __type_list<__align_type<__struct_double>, 47 __type_list<__align_type<__struct_double4>, 48 __type_list<__align_type<int*>, 49 __nat 50 > > > > > > > > > > __all_types; 51 // clang-format on 52 53 template <size_t _Align> 54 struct _ALIGNAS(_Align) __fallback_overaligned {}; 55 56 template <class _TL, size_t _Align> 57 struct __find_pod; 58 59 template <class _Hp, size_t _Align> 60 struct __find_pod<__type_list<_Hp, __nat>, _Align> { 61 typedef __conditional_t<_Align == _Hp::value, typename _Hp::type, __fallback_overaligned<_Align> > type; 62 }; 63 64 template <class _Hp, class _Tp, size_t _Align> 65 struct __find_pod<__type_list<_Hp, _Tp>, _Align> { 66 typedef __conditional_t<_Align == _Hp::value, typename _Hp::type, typename __find_pod<_Tp, _Align>::type> type; 67 }; 68 69 template <class _TL, size_t _Len> 70 struct __find_max_align; 71 72 template <class _Hp, size_t _Len> 73 struct __find_max_align<__type_list<_Hp, __nat>, _Len> : public integral_constant<size_t, _Hp::value> {}; 74 75 template <size_t _Len, size_t _A1, size_t _A2> 76 struct __select_align { 77 private: 78 static const size_t __min = _A2 < _A1 ? _A2 : _A1; 79 static const size_t __max = _A1 < _A2 ? _A2 : _A1; 80 81 public: 82 static const size_t value = _Len < __max ? __min : __max; 83 }; 84 85 template <class _Hp, class _Tp, size_t _Len> 86 struct __find_max_align<__type_list<_Hp, _Tp>, _Len> 87 : public integral_constant<size_t, __select_align<_Len, _Hp::value, __find_max_align<_Tp, _Len>::value>::value> {}; 88 89 template <size_t _Len, size_t _Align = __find_max_align<__all_types, _Len>::value> 90 struct _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_TEMPLATE_VIS aligned_storage { 91 typedef typename __find_pod<__all_types, _Align>::type _Aligner; 92 union type { 93 _Aligner __align; 94 unsigned char __data[(_Len + _Align - 1) / _Align * _Align]; 95 }; 96 }; 97 98 #if _LIBCPP_STD_VER >= 14 99 100 _LIBCPP_SUPPRESS_DEPRECATED_PUSH 101 template <size_t _Len, size_t _Align = __find_max_align<__all_types, _Len>::value> 102 using aligned_storage_t _LIBCPP_DEPRECATED_IN_CXX23 = typename aligned_storage<_Len, _Align>::type; 103 _LIBCPP_SUPPRESS_DEPRECATED_POP 104 105 #endif 106 107 #define _CREATE_ALIGNED_STORAGE_SPECIALIZATION(n) \ 108 template <size_t _Len> \ 109 struct _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_TEMPLATE_VIS aligned_storage<_Len, n> { \ 110 struct _ALIGNAS(n) type { \ 111 unsigned char __lx[(_Len + n - 1) / n * n]; \ 112 }; \ 113 } 114 115 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x1); 116 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x2); 117 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x4); 118 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x8); 119 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x10); 120 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x20); 121 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x40); 122 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x80); 123 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x100); 124 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x200); 125 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x400); 126 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x800); 127 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x1000); 128 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x2000); 129 // PE/COFF does not support alignment beyond 8192 (=0x2000) 130 #if !defined(_LIBCPP_OBJECT_FORMAT_COFF) 131 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x4000); 132 #endif // !defined(_LIBCPP_OBJECT_FORMAT_COFF) 133 134 #undef _CREATE_ALIGNED_STORAGE_SPECIALIZATION 135 136 _LIBCPP_END_NAMESPACE_STD 137 138 #endif // _LIBCPP___TYPE_TRAITS_ALIGNED_STORAGE_H 139