1 | // (C) Copyright John Maddock 2000. |
2 | // Use, modification and distribution are subject to the Boost Software License, |
3 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
4 | // http://www.boost.org/LICENSE_1_0.txt). |
5 | // |
6 | // See http://www.boost.org/libs/type_traits for most recent version including documentation. |
7 | |
8 | #ifndef BOOST_TT_TYPE_WITH_ALIGNMENT_INCLUDED |
9 | #define BOOST_TT_TYPE_WITH_ALIGNMENT_INCLUDED |
10 | |
11 | #include <boost/type_traits/alignment_of.hpp> |
12 | #include <boost/type_traits/is_pod.hpp> |
13 | #include <boost/static_assert.hpp> |
14 | #include <boost/config.hpp> |
15 | #include <cstddef> |
16 | #include <boost/detail/workaround.hpp> |
17 | |
18 | #ifdef BOOST_MSVC |
19 | # pragma warning(push) |
20 | # pragma warning(disable: 4121) // alignment is sensitive to packing |
21 | #endif |
22 | |
23 | #ifdef _MSC_VER |
24 | #include <boost/type_traits/conditional.hpp> |
25 | #endif |
26 | |
27 | namespace boost { |
28 | namespace detail{ |
29 | |
30 | #ifndef __BORLANDC__ |
31 | |
32 | union max_align |
33 | { |
34 | char c; |
35 | short s; |
36 | int i; |
37 | long l; |
38 | #ifndef BOOST_NO_LONG_LONG |
39 | boost::long_long_type ll; |
40 | #endif |
41 | #ifdef BOOST_HAS_INT128 |
42 | boost::int128_type i128; |
43 | #endif |
44 | float f; |
45 | double d; |
46 | long double ld; |
47 | #ifdef BOOST_HAS_FLOAT128 |
48 | __float128 f128; |
49 | #endif |
50 | }; |
51 | |
52 | template <std::size_t Target, bool check> struct long_double_alignment{ typedef long double type; }; |
53 | template <std::size_t Target> struct long_double_alignment<Target, false>{ typedef boost::detail::max_align type; }; |
54 | |
55 | template <std::size_t Target, bool check> struct double_alignment{ typedef double type; }; |
56 | template <std::size_t Target> struct double_alignment<Target, false>{ typedef typename long_double_alignment<Target, boost::alignment_of<long double>::value >= Target>::type type; }; |
57 | |
58 | #ifndef BOOST_NO_LONG_LONG |
59 | template <std::size_t Target, bool check> struct long_long_alignment{ typedef boost::long_long_type type; }; |
60 | template <std::size_t Target> struct long_long_alignment<Target, false>{ typedef typename double_alignment<Target, boost::alignment_of<double>::value >= Target>::type type; }; |
61 | #endif |
62 | |
63 | template <std::size_t Target, bool check> struct long_alignment{ typedef long type; }; |
64 | #ifndef BOOST_NO_LONG_LONG |
65 | template <std::size_t Target> struct long_alignment<Target, false>{ typedef typename long_long_alignment<Target, boost::alignment_of<boost::long_long_type>::value >= Target>::type type; }; |
66 | #else |
67 | template <std::size_t Target> struct long_alignment<Target, false>{ typedef typename double_alignment<Target, boost::alignment_of<double>::value >= Target>::type type; }; |
68 | #endif |
69 | |
70 | template <std::size_t Target, bool check> struct int_alignment{ typedef int type; }; |
71 | template <std::size_t Target> struct int_alignment<Target, false>{ typedef typename long_alignment<Target, boost::alignment_of<long>::value >= Target>::type type; }; |
72 | |
73 | template <std::size_t Target, bool check> struct short_alignment{ typedef short type; }; |
74 | template <std::size_t Target> struct short_alignment<Target, false>{ typedef typename int_alignment<Target, boost::alignment_of<int>::value >= Target>::type type; }; |
75 | |
76 | template <std::size_t Target, bool check> struct char_alignment{ typedef char type; }; |
77 | template <std::size_t Target> struct char_alignment<Target, false>{ typedef typename short_alignment<Target, boost::alignment_of<short>::value >= Target>::type type; }; |
78 | |
79 | } |
80 | |
81 | template <std::size_t Align> |
82 | struct type_with_alignment |
83 | { |
84 | typedef typename boost::detail::char_alignment<Align, boost::alignment_of<char>::value >= Align>::type type; |
85 | }; |
86 | |
87 | #if (defined(__GNUC__) || (defined (__SUNPRO_CC) && (__SUNPRO_CC >= 0x5130)) || defined(__clang__)) && !defined(BOOST_TT_DISABLE_INTRINSICS) |
88 | namespace tt_align_ns { |
89 | struct __attribute__((__aligned__(2))) a2 {}; |
90 | struct __attribute__((__aligned__(4))) a4 {}; |
91 | struct __attribute__((__aligned__(8))) a8 {}; |
92 | struct __attribute__((__aligned__(16))) a16 {}; |
93 | struct __attribute__((__aligned__(32))) a32 {}; |
94 | struct __attribute__((__aligned__(64))) a64 {}; |
95 | struct __attribute__((__aligned__(128))) a128 {}; |
96 | } |
97 | |
98 | template<> struct type_with_alignment<1> { public: typedef char type; }; |
99 | template<> struct type_with_alignment<2> { public: typedef tt_align_ns::a2 type; }; |
100 | template<> struct type_with_alignment<4> { public: typedef tt_align_ns::a4 type; }; |
101 | template<> struct type_with_alignment<8> { public: typedef tt_align_ns::a8 type; }; |
102 | template<> struct type_with_alignment<16> { public: typedef tt_align_ns::a16 type; }; |
103 | template<> struct type_with_alignment<32> { public: typedef tt_align_ns::a32 type; }; |
104 | template<> struct type_with_alignment<64> { public: typedef tt_align_ns::a64 type; }; |
105 | template<> struct type_with_alignment<128> { public: typedef tt_align_ns::a128 type; }; |
106 | |
107 | template<> struct is_pod< ::boost::tt_align_ns::a2> : public true_type{}; |
108 | template<> struct is_pod< ::boost::tt_align_ns::a4> : public true_type{}; |
109 | template<> struct is_pod< ::boost::tt_align_ns::a8> : public true_type{}; |
110 | template<> struct is_pod< ::boost::tt_align_ns::a16> : public true_type{}; |
111 | template<> struct is_pod< ::boost::tt_align_ns::a32> : public true_type{}; |
112 | template<> struct is_pod< ::boost::tt_align_ns::a64> : public true_type{}; |
113 | template<> struct is_pod< ::boost::tt_align_ns::a128> : public true_type{}; |
114 | |
115 | #endif |
116 | #if (defined(BOOST_MSVC) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && !defined(BOOST_TT_DISABLE_INTRINSICS) |
117 | // |
118 | // MSVC supports types which have alignments greater than the normal |
119 | // maximum: these are used for example in the types __m64 and __m128 |
120 | // to provide types with alignment requirements which match the SSE |
121 | // registers. Therefore we extend type_with_alignment<> to support |
122 | // such types, however, we have to be careful to use a builtin type |
123 | // whenever possible otherwise we break previously working code: |
124 | // see http://article.gmane.org/gmane.comp.lib.boost.devel/173011 |
125 | // for an example and test case. Thus types like a8 below will |
126 | // be used *only* if the existing implementation can't provide a type |
127 | // with suitable alignment. This does mean however, that type_with_alignment<> |
128 | // may return a type which cannot be passed through a function call |
129 | // by value (and neither can any type containing such a type like |
130 | // Boost.Optional). However, this only happens when we have no choice |
131 | // in the matter because no other "ordinary" type is available. |
132 | // |
133 | namespace tt_align_ns { |
134 | struct __declspec(align(8)) a8 { |
135 | char m[8]; |
136 | typedef a8 type; |
137 | }; |
138 | struct __declspec(align(16)) a16 { |
139 | char m[16]; |
140 | typedef a16 type; |
141 | }; |
142 | struct __declspec(align(32)) a32 { |
143 | char m[32]; |
144 | typedef a32 type; |
145 | }; |
146 | struct __declspec(align(64)) a64 |
147 | { |
148 | char m[64]; |
149 | typedef a64 type; |
150 | }; |
151 | struct __declspec(align(128)) a128 { |
152 | char m[128]; |
153 | typedef a128 type; |
154 | }; |
155 | } |
156 | |
157 | template<> struct type_with_alignment<8> |
158 | { |
159 | typedef boost::conditional< |
160 | ::boost::alignment_of<boost::detail::max_align>::value < 8, |
161 | tt_align_ns::a8, |
162 | boost::detail::char_alignment<8, false> >::type t1; |
163 | public: |
164 | typedef t1::type type; |
165 | }; |
166 | template<> struct type_with_alignment<16> |
167 | { |
168 | typedef boost::conditional< |
169 | ::boost::alignment_of<boost::detail::max_align>::value < 16, |
170 | tt_align_ns::a16, |
171 | boost::detail::char_alignment<16, false> >::type t1; |
172 | public: |
173 | typedef t1::type type; |
174 | }; |
175 | template<> struct type_with_alignment<32> |
176 | { |
177 | typedef boost::conditional< |
178 | ::boost::alignment_of<boost::detail::max_align>::value < 32, |
179 | tt_align_ns::a32, |
180 | boost::detail::char_alignment<32, false> >::type t1; |
181 | public: |
182 | typedef t1::type type; |
183 | }; |
184 | template<> struct type_with_alignment<64> { |
185 | typedef boost::conditional< |
186 | ::boost::alignment_of<boost::detail::max_align>::value < 64, |
187 | tt_align_ns::a64, |
188 | boost::detail::char_alignment<64, false> >::type t1; |
189 | public: |
190 | typedef t1::type type; |
191 | }; |
192 | template<> struct type_with_alignment<128> { |
193 | typedef boost::conditional< |
194 | ::boost::alignment_of<boost::detail::max_align>::value < 128, |
195 | tt_align_ns::a128, |
196 | boost::detail::char_alignment<128, false> >::type t1; |
197 | public: |
198 | typedef t1::type type; |
199 | }; |
200 | |
201 | template<> struct is_pod< ::boost::tt_align_ns::a8> : public true_type{}; |
202 | template<> struct is_pod< ::boost::tt_align_ns::a16> : public true_type{}; |
203 | template<> struct is_pod< ::boost::tt_align_ns::a32> : public true_type{}; |
204 | template<> struct is_pod< ::boost::tt_align_ns::a64> : public true_type{}; |
205 | template<> struct is_pod< ::boost::tt_align_ns::a128> : public true_type{}; |
206 | |
207 | #endif |
208 | |
209 | #else |
210 | |
211 | // |
212 | // Borland specific version, we have this for two reasons: |
213 | // 1) The version above doesn't always compile (with the new test cases for example) |
214 | // 2) Because of Borlands #pragma option we can create types with alignments that are |
215 | // greater that the largest aligned builtin type. |
216 | |
217 | namespace tt_align_ns{ |
218 | #pragma option push -a16 |
219 | struct a2{ short s; }; |
220 | struct a4{ int s; }; |
221 | struct a8{ double s; }; |
222 | struct a16{ long double s; }; |
223 | #pragma option pop |
224 | } |
225 | |
226 | namespace detail { |
227 | |
228 | typedef ::boost::tt_align_ns::a16 max_align; |
229 | |
230 | } |
231 | //#if ! BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x610)) |
232 | template <> struct is_pod< ::boost::tt_align_ns::a2> : public true_type{}; |
233 | template <> struct is_pod< ::boost::tt_align_ns::a4> : public true_type{}; |
234 | template <> struct is_pod< ::boost::tt_align_ns::a8> : public true_type{}; |
235 | template <> struct is_pod< ::boost::tt_align_ns::a16> : public true_type{}; |
236 | //#endif |
237 | |
238 | template <std::size_t N> struct type_with_alignment |
239 | { |
240 | // We should never get to here, but if we do use the maximally |
241 | // aligned type: |
242 | // BOOST_STATIC_ASSERT(0); |
243 | typedef tt_align_ns::a16 type; |
244 | }; |
245 | template <> struct type_with_alignment<1>{ typedef char type; }; |
246 | template <> struct type_with_alignment<2>{ typedef tt_align_ns::a2 type; }; |
247 | template <> struct type_with_alignment<4>{ typedef tt_align_ns::a4 type; }; |
248 | template <> struct type_with_alignment<8>{ typedef tt_align_ns::a8 type; }; |
249 | template <> struct type_with_alignment<16>{ typedef tt_align_ns::a16 type; }; |
250 | |
251 | #endif |
252 | |
253 | } // namespace boost |
254 | |
255 | #ifdef BOOST_MSVC |
256 | # pragma warning(pop) |
257 | #endif |
258 | |
259 | #endif // BOOST_TT_TYPE_WITH_ALIGNMENT_INCLUDED |
260 | |
261 | |
262 | |