bitwise_cast.hpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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
  8. * Copyright (c) 2013-2018, 2020-2021 Andrey Semashev
  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. #ifndef BOOST_ATOMIC_DETAIL_BITWISE_CAST_HPP_INCLUDED_
  16. #define BOOST_ATOMIC_DETAIL_BITWISE_CAST_HPP_INCLUDED_
  17. #include <cstddef>
  18. #include <boost/atomic/detail/config.hpp>
  19. #include <boost/atomic/detail/addressof.hpp>
  20. #include <boost/atomic/detail/string_ops.hpp>
  21. #include <boost/atomic/detail/type_traits/remove_cv.hpp>
  22. #include <boost/atomic/detail/type_traits/integral_constant.hpp>
  23. #include <boost/atomic/detail/type_traits/has_unique_object_representations.hpp>
  24. #include <boost/atomic/detail/header.hpp>
  25. #ifdef BOOST_HAS_PRAGMA_ONCE
  26. #pragma once
  27. #endif
  28. #if !defined(BOOST_ATOMIC_DETAIL_NO_HAS_UNIQUE_OBJECT_REPRESENTATIONS)
  29. #if defined(__has_builtin)
  30. #if __has_builtin(__builtin_bit_cast)
  31. #define BOOST_ATOMIC_DETAIL_BIT_CAST(x, y) __builtin_bit_cast(x, y)
  32. #endif
  33. #endif
  34. #if !defined(BOOST_ATOMIC_DETAIL_BIT_CAST) && defined(BOOST_MSVC) && BOOST_MSVC >= 1926
  35. #define BOOST_ATOMIC_DETAIL_BIT_CAST(x, y) __builtin_bit_cast(x, y)
  36. #endif
  37. #endif // !defined(BOOST_ATOMIC_DETAIL_NO_HAS_UNIQUE_OBJECT_REPRESENTATIONS)
  38. #if defined(BOOST_NO_CXX11_CONSTEXPR) || !defined(BOOST_ATOMIC_DETAIL_BIT_CAST) || !defined(BOOST_ATOMIC_DETAIL_HAS_BUILTIN_ADDRESSOF)
  39. #define BOOST_ATOMIC_DETAIL_NO_CXX11_CONSTEXPR_BITWISE_CAST
  40. #endif
  41. #if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_CONSTEXPR_BITWISE_CAST)
  42. #define BOOST_ATOMIC_DETAIL_CONSTEXPR_BITWISE_CAST BOOST_CONSTEXPR
  43. #else
  44. #define BOOST_ATOMIC_DETAIL_CONSTEXPR_BITWISE_CAST
  45. #endif
  46. #if defined(BOOST_GCC) && BOOST_GCC >= 80000
  47. #pragma GCC diagnostic push
  48. // 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.
  49. #pragma GCC diagnostic ignored "-Wclass-memaccess"
  50. #endif
  51. namespace boost {
  52. namespace atomics {
  53. namespace detail {
  54. template< std::size_t ValueSize, typename To >
  55. BOOST_FORCEINLINE void clear_tail_padding_bits(To& to, atomics::detail::true_type) BOOST_NOEXCEPT
  56. {
  57. BOOST_ATOMIC_DETAIL_MEMSET(reinterpret_cast< unsigned char* >(atomics::detail::addressof(to)) + ValueSize, 0, sizeof(To) - ValueSize);
  58. }
  59. template< std::size_t ValueSize, typename To >
  60. BOOST_FORCEINLINE void clear_tail_padding_bits(To&, atomics::detail::false_type) BOOST_NOEXCEPT
  61. {
  62. }
  63. template< std::size_t ValueSize, typename To >
  64. BOOST_FORCEINLINE void clear_tail_padding_bits(To& to) BOOST_NOEXCEPT
  65. {
  66. atomics::detail::clear_tail_padding_bits< ValueSize >(to, atomics::detail::integral_constant< bool, ValueSize < sizeof(To) >());
  67. }
  68. template< typename To, std::size_t FromValueSize, typename From >
  69. BOOST_FORCEINLINE To bitwise_cast_memcpy(From const& from) BOOST_NOEXCEPT
  70. {
  71. typedef typename atomics::detail::remove_cv< To >::type unqualified_to_t;
  72. unqualified_to_t to;
  73. #if !defined(BOOST_ATOMIC_NO_CLEAR_PADDING)
  74. From from2(from);
  75. BOOST_ATOMIC_DETAIL_CLEAR_PADDING(atomics::detail::addressof(from2));
  76. BOOST_ATOMIC_DETAIL_MEMCPY
  77. (
  78. atomics::detail::addressof(to),
  79. atomics::detail::addressof(from2),
  80. (FromValueSize < sizeof(unqualified_to_t) ? FromValueSize : sizeof(unqualified_to_t))
  81. );
  82. #else
  83. BOOST_ATOMIC_DETAIL_MEMCPY
  84. (
  85. atomics::detail::addressof(to),
  86. atomics::detail::addressof(from),
  87. (FromValueSize < sizeof(unqualified_to_t) ? FromValueSize : sizeof(unqualified_to_t))
  88. );
  89. #endif
  90. atomics::detail::clear_tail_padding_bits< FromValueSize >(to);
  91. return to;
  92. }
  93. #if defined(BOOST_ATOMIC_DETAIL_BIT_CAST)
  94. template< typename To, std::size_t FromValueSize, typename From >
  95. BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_BITWISE_CAST To bitwise_cast_impl(From const& from, atomics::detail::true_type) BOOST_NOEXCEPT
  96. {
  97. // This implementation is only called when the From type has no padding and From and To have the same size
  98. return BOOST_ATOMIC_DETAIL_BIT_CAST(typename atomics::detail::remove_cv< To >::type, from);
  99. }
  100. template< typename To, std::size_t FromValueSize, typename From >
  101. BOOST_FORCEINLINE To bitwise_cast_impl(From const& from, atomics::detail::false_type) BOOST_NOEXCEPT
  102. {
  103. return atomics::detail::bitwise_cast_memcpy< To, FromValueSize >(from);
  104. }
  105. template< typename To, std::size_t FromValueSize, typename From >
  106. BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_BITWISE_CAST To bitwise_cast(From const& from) BOOST_NOEXCEPT
  107. {
  108. return atomics::detail::bitwise_cast_impl< To, FromValueSize >(from, atomics::detail::integral_constant< bool,
  109. FromValueSize == sizeof(To) && atomics::detail::has_unique_object_representations< From >::value >());
  110. }
  111. #else // defined(BOOST_ATOMIC_DETAIL_BIT_CAST)
  112. template< typename To, std::size_t FromValueSize, typename From >
  113. BOOST_FORCEINLINE To bitwise_cast(From const& from) BOOST_NOEXCEPT
  114. {
  115. return atomics::detail::bitwise_cast_memcpy< To, FromValueSize >(from);
  116. }
  117. #endif // defined(BOOST_ATOMIC_DETAIL_BIT_CAST)
  118. //! 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.
  119. template< typename To, typename From >
  120. BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_BITWISE_CAST To bitwise_cast(From const& from) BOOST_NOEXCEPT
  121. {
  122. return atomics::detail::bitwise_cast< To, sizeof(From) >(from);
  123. }
  124. } // namespace detail
  125. } // namespace atomics
  126. } // namespace boost
  127. #if defined(BOOST_GCC) && BOOST_GCC >= 80000
  128. #pragma GCC diagnostic pop
  129. #endif
  130. #include <boost/atomic/detail/footer.hpp>
  131. #endif // BOOST_ATOMIC_DETAIL_BITWISE_CAST_HPP_INCLUDED_