]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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> // size_t | |
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 |