]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /* |
2 | * Distributed under the Boost Software License, Version 1.0. | |
3 | * (See accompanying file LICENSE_1_0.txt or copy at | |
4 | * http://www.boost.org/LICENSE_1_0.txt) | |
5 | * | |
6 | * Copyright (c) 2009 Helge Bahmann | |
7 | * Copyright (c) 2012 Tim Blechmann | |
1e59de90 | 8 | * Copyright (c) 2013-2018, 2020-2021 Andrey Semashev |
7c673cae FG |
9 | */ |
10 | /*! | |
11 | * \file atomic/detail/bitwise_cast.hpp | |
12 | * | |
13 | * This header defines \c bitwise_cast used to convert between storage and value types | |
14 | */ | |
15 | ||
16 | #ifndef BOOST_ATOMIC_DETAIL_BITWISE_CAST_HPP_INCLUDED_ | |
17 | #define BOOST_ATOMIC_DETAIL_BITWISE_CAST_HPP_INCLUDED_ | |
18 | ||
11fdf7f2 | 19 | #include <cstddef> |
7c673cae | 20 | #include <boost/atomic/detail/config.hpp> |
11fdf7f2 TL |
21 | #include <boost/atomic/detail/addressof.hpp> |
22 | #include <boost/atomic/detail/string_ops.hpp> | |
23 | #include <boost/atomic/detail/type_traits/integral_constant.hpp> | |
1e59de90 | 24 | #include <boost/atomic/detail/type_traits/has_unique_object_representations.hpp> |
20effc67 | 25 | #include <boost/atomic/detail/header.hpp> |
7c673cae FG |
26 | |
27 | #ifdef BOOST_HAS_PRAGMA_ONCE | |
28 | #pragma once | |
29 | #endif | |
30 | ||
1e59de90 TL |
31 | #if !defined(BOOST_ATOMIC_DETAIL_NO_HAS_UNIQUE_OBJECT_REPRESENTATIONS) |
32 | ||
33 | #if defined(__has_builtin) | |
34 | #if __has_builtin(__builtin_bit_cast) | |
35 | #define BOOST_ATOMIC_DETAIL_BIT_CAST(x, y) __builtin_bit_cast(x, y) | |
36 | #endif | |
37 | #endif | |
38 | ||
39 | #if !defined(BOOST_ATOMIC_DETAIL_BIT_CAST) && defined(BOOST_MSVC) && BOOST_MSVC >= 1926 | |
40 | #define BOOST_ATOMIC_DETAIL_BIT_CAST(x, y) __builtin_bit_cast(x, y) | |
41 | #endif | |
42 | ||
43 | #endif // !defined(BOOST_ATOMIC_DETAIL_NO_HAS_UNIQUE_OBJECT_REPRESENTATIONS) | |
44 | ||
45 | #if defined(BOOST_NO_CXX11_CONSTEXPR) || !defined(BOOST_ATOMIC_DETAIL_BIT_CAST) || !defined(BOOST_ATOMIC_DETAIL_HAS_BUILTIN_ADDRESSOF) | |
46 | #define BOOST_ATOMIC_DETAIL_NO_CXX11_CONSTEXPR_BITWISE_CAST | |
47 | #endif | |
48 | ||
49 | #if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_CONSTEXPR_BITWISE_CAST) | |
50 | #define BOOST_ATOMIC_DETAIL_CONSTEXPR_BITWISE_CAST BOOST_CONSTEXPR | |
51 | #else | |
52 | #define BOOST_ATOMIC_DETAIL_CONSTEXPR_BITWISE_CAST | |
53 | #endif | |
54 | ||
f67539c2 TL |
55 | #if defined(BOOST_GCC) && BOOST_GCC >= 80000 |
56 | #pragma GCC diagnostic push | |
57 | // copying an object of non-trivial type X from an array of Y. This is benign because we use memcpy to copy trivially copyable objects. | |
58 | #pragma GCC diagnostic ignored "-Wclass-memaccess" | |
59 | #endif | |
60 | ||
7c673cae FG |
61 | namespace boost { |
62 | namespace atomics { | |
63 | namespace detail { | |
64 | ||
1e59de90 | 65 | template< std::size_t ValueSize, typename To > |
f67539c2 | 66 | BOOST_FORCEINLINE void clear_tail_padding_bits(To& to, atomics::detail::true_type) BOOST_NOEXCEPT |
b32b8144 | 67 | { |
1e59de90 | 68 | BOOST_ATOMIC_DETAIL_MEMSET(reinterpret_cast< unsigned char* >(atomics::detail::addressof(to)) + ValueSize, 0, sizeof(To) - ValueSize); |
b32b8144 FG |
69 | } |
70 | ||
1e59de90 | 71 | template< std::size_t ValueSize, typename To > |
f67539c2 TL |
72 | BOOST_FORCEINLINE void clear_tail_padding_bits(To&, atomics::detail::false_type) BOOST_NOEXCEPT |
73 | { | |
74 | } | |
75 | ||
1e59de90 | 76 | template< std::size_t ValueSize, typename To > |
f67539c2 | 77 | BOOST_FORCEINLINE void clear_tail_padding_bits(To& to) BOOST_NOEXCEPT |
11fdf7f2 | 78 | { |
1e59de90 | 79 | atomics::detail::clear_tail_padding_bits< ValueSize >(to, atomics::detail::integral_constant< bool, ValueSize < sizeof(To) >()); |
11fdf7f2 TL |
80 | } |
81 | ||
1e59de90 TL |
82 | template< typename To, std::size_t FromValueSize, typename From > |
83 | BOOST_FORCEINLINE To bitwise_cast_memcpy(From const& from) BOOST_NOEXCEPT | |
7c673cae | 84 | { |
11fdf7f2 | 85 | To to; |
1e59de90 TL |
86 | #if !defined(BOOST_ATOMIC_NO_CLEAR_PADDING) |
87 | From from2(from); | |
88 | BOOST_ATOMIC_DETAIL_CLEAR_PADDING(atomics::detail::addressof(from2)); | |
89 | BOOST_ATOMIC_DETAIL_MEMCPY | |
90 | ( | |
91 | atomics::detail::addressof(to), | |
92 | atomics::detail::addressof(from2), | |
93 | (FromValueSize < sizeof(To) ? FromValueSize : sizeof(To)) | |
94 | ); | |
95 | #else | |
7c673cae FG |
96 | BOOST_ATOMIC_DETAIL_MEMCPY |
97 | ( | |
11fdf7f2 | 98 | atomics::detail::addressof(to), |
b32b8144 | 99 | atomics::detail::addressof(from), |
1e59de90 | 100 | (FromValueSize < sizeof(To) ? FromValueSize : sizeof(To)) |
7c673cae | 101 | ); |
1e59de90 TL |
102 | #endif |
103 | atomics::detail::clear_tail_padding_bits< FromValueSize >(to); | |
11fdf7f2 TL |
104 | return to; |
105 | } | |
106 | ||
1e59de90 TL |
107 | #if defined(BOOST_ATOMIC_DETAIL_BIT_CAST) |
108 | ||
109 | template< typename To, std::size_t FromValueSize, typename From > | |
110 | BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_BITWISE_CAST To bitwise_cast_impl(From const& from, atomics::detail::true_type) BOOST_NOEXCEPT | |
111 | { | |
112 | // This implementation is only called when the From type has no padding and From and To have the same size | |
113 | return BOOST_ATOMIC_DETAIL_BIT_CAST(To, from); | |
114 | } | |
115 | ||
116 | template< typename To, std::size_t FromValueSize, typename From > | |
117 | BOOST_FORCEINLINE To bitwise_cast_impl(From const& from, atomics::detail::false_type) BOOST_NOEXCEPT | |
118 | { | |
119 | return atomics::detail::bitwise_cast_memcpy< To, FromValueSize >(from); | |
120 | } | |
121 | ||
122 | template< typename To, std::size_t FromValueSize, typename From > | |
123 | BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_BITWISE_CAST To bitwise_cast(From const& from) BOOST_NOEXCEPT | |
124 | { | |
125 | return atomics::detail::bitwise_cast_impl< To, FromValueSize >(from, atomics::detail::integral_constant< bool, | |
126 | FromValueSize == sizeof(To) && atomics::detail::has_unique_object_representations< From >::value >()); | |
127 | } | |
128 | ||
129 | #else // defined(BOOST_ATOMIC_DETAIL_BIT_CAST) | |
130 | ||
131 | template< typename To, std::size_t FromValueSize, typename From > | |
11fdf7f2 | 132 | BOOST_FORCEINLINE To bitwise_cast(From const& from) BOOST_NOEXCEPT |
1e59de90 TL |
133 | { |
134 | return atomics::detail::bitwise_cast_memcpy< To, FromValueSize >(from); | |
135 | } | |
136 | ||
137 | #endif // defined(BOOST_ATOMIC_DETAIL_BIT_CAST) | |
138 | ||
139 | //! Converts the source object to the target type, possibly by padding or truncating it on the right, and clearing any padding bits (if supported by compiler). Preserves value bits unchanged. | |
140 | template< typename To, typename From > | |
141 | BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_BITWISE_CAST To bitwise_cast(From const& from) BOOST_NOEXCEPT | |
11fdf7f2 TL |
142 | { |
143 | return atomics::detail::bitwise_cast< To, sizeof(From) >(from); | |
7c673cae FG |
144 | } |
145 | ||
146 | } // namespace detail | |
147 | } // namespace atomics | |
148 | } // namespace boost | |
149 | ||
f67539c2 TL |
150 | #if defined(BOOST_GCC) && BOOST_GCC >= 80000 |
151 | #pragma GCC diagnostic pop | |
152 | #endif | |
153 | ||
20effc67 TL |
154 | #include <boost/atomic/detail/footer.hpp> |
155 | ||
7c673cae | 156 | #endif // BOOST_ATOMIC_DETAIL_BITWISE_CAST_HPP_INCLUDED_ |