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