align.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // align implementation -*- C++ -*-
  2. // Copyright (C) 2014-2022 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /** @file bits/align.h
  21. * This is an internal header file, included by other library headers.
  22. * Do not attempt to use it directly. @headername{memory}
  23. */
  24. #ifndef _GLIBCXX_ALIGN_H
  25. #define _GLIBCXX_ALIGN_H 1
  26. #include <bits/c++config.h>
  27. #include <bit> // std::has_single_bit
  28. #include <stdint.h> // uintptr_t
  29. #include <debug/assertions.h> // _GLIBCXX_DEBUG_ASSERT
  30. namespace std _GLIBCXX_VISIBILITY(default)
  31. {
  32. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  33. /**
  34. * @brief Fit aligned storage in buffer.
  35. *
  36. * This function tries to fit @a __size bytes of storage with alignment
  37. * @a __align into the buffer @a __ptr of size @a __space bytes. If such
  38. * a buffer fits then @a __ptr is changed to point to the first byte of the
  39. * aligned storage and @a __space is reduced by the bytes used for alignment.
  40. *
  41. * C++11 20.6.5 [ptr.align]
  42. *
  43. * @param __align A fundamental or extended alignment value.
  44. * @param __size Size of the aligned storage required.
  45. * @param __ptr Pointer to a buffer of @a __space bytes.
  46. * @param __space Size of the buffer pointed to by @a __ptr.
  47. * @return the updated pointer if the aligned storage fits, otherwise nullptr.
  48. *
  49. * @ingroup memory
  50. */
  51. inline void*
  52. align(size_t __align, size_t __size, void*& __ptr, size_t& __space) noexcept
  53. {
  54. if (__space < __size)
  55. return nullptr;
  56. const auto __intptr = reinterpret_cast<uintptr_t>(__ptr);
  57. const auto __aligned = (__intptr - 1u + __align) & -__align;
  58. const auto __diff = __aligned - __intptr;
  59. if (__diff > (__space - __size))
  60. return nullptr;
  61. else
  62. {
  63. __space -= __diff;
  64. return __ptr = reinterpret_cast<void*>(__aligned);
  65. }
  66. }
  67. #if __cplusplus > 201703L
  68. #define __cpp_lib_assume_aligned 201811L
  69. /** @brief Inform the compiler that a pointer is aligned.
  70. *
  71. * @tparam _Align An alignment value (i.e. a power of two)
  72. * @tparam _Tp An object type
  73. * @param __ptr A pointer that is aligned to _Align
  74. *
  75. * C++20 20.10.6 [ptr.align]
  76. *
  77. * @ingroup memory
  78. */
  79. template<size_t _Align, class _Tp>
  80. [[nodiscard,__gnu__::__always_inline__]]
  81. constexpr _Tp*
  82. assume_aligned(_Tp* __ptr) noexcept
  83. {
  84. static_assert(std::has_single_bit(_Align));
  85. if (std::is_constant_evaluated())
  86. return __ptr;
  87. else
  88. {
  89. // This function is expected to be used in hot code, where
  90. // __glibcxx_assert would add unwanted overhead.
  91. _GLIBCXX_DEBUG_ASSERT((uintptr_t)__ptr % _Align == 0);
  92. return static_cast<_Tp*>(__builtin_assume_aligned(__ptr, _Align));
  93. }
  94. }
  95. #endif // C++2a
  96. _GLIBCXX_END_NAMESPACE_VERSION
  97. } // namespace
  98. #endif /* _GLIBCXX_ALIGN_H */