bitwise_cast.hpp 5.5 KB

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