constexpr_c_functions.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. //===----------------------------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #ifndef _LIBCPP___STRING_CONSTEXPR_C_FUNCTIONS_H
  9. #define _LIBCPP___STRING_CONSTEXPR_C_FUNCTIONS_H
  10. #include <__config>
  11. #include <__memory/addressof.h>
  12. #include <__memory/construct_at.h>
  13. #include <__type_traits/datasizeof.h>
  14. #include <__type_traits/is_always_bitcastable.h>
  15. #include <__type_traits/is_assignable.h>
  16. #include <__type_traits/is_constant_evaluated.h>
  17. #include <__type_traits/is_constructible.h>
  18. #include <__type_traits/is_equality_comparable.h>
  19. #include <__type_traits/is_same.h>
  20. #include <__type_traits/is_trivially_copyable.h>
  21. #include <__type_traits/is_trivially_lexicographically_comparable.h>
  22. #include <__type_traits/remove_cv.h>
  23. #include <__utility/is_pointer_in_range.h>
  24. #include <cstddef>
  25. #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
  26. # pragma GCC system_header
  27. #endif
  28. _LIBCPP_BEGIN_NAMESPACE_STD
  29. // Type used to encode that a function takes an integer that represents a number
  30. // of elements as opposed to a number of bytes.
  31. enum class __element_count : size_t {};
  32. inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 size_t __constexpr_strlen(const char* __str) {
  33. // GCC currently doesn't support __builtin_strlen for heap-allocated memory during constant evaluation.
  34. // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70816
  35. #ifdef _LIBCPP_COMPILER_GCC
  36. if (__libcpp_is_constant_evaluated()) {
  37. size_t __i = 0;
  38. for (; __str[__i] != '\0'; ++__i)
  39. ;
  40. return __i;
  41. }
  42. #endif
  43. return __builtin_strlen(__str);
  44. }
  45. // Because of __libcpp_is_trivially_lexicographically_comparable we know that comparing the object representations is
  46. // equivalent to a std::memcmp. Since we have multiple objects contiguously in memory, we can call memcmp once instead
  47. // of invoking it on every object individually.
  48. template <class _Tp, class _Up>
  49. _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int
  50. __constexpr_memcmp(const _Tp* __lhs, const _Up* __rhs, __element_count __n) {
  51. static_assert(__libcpp_is_trivially_lexicographically_comparable<_Tp, _Up>::value,
  52. "_Tp and _Up have to be trivially lexicographically comparable");
  53. auto __count = static_cast<size_t>(__n);
  54. if (__libcpp_is_constant_evaluated()) {
  55. #ifdef _LIBCPP_COMPILER_CLANG_BASED
  56. if (sizeof(_Tp) == 1 && !is_same<_Tp, bool>::value)
  57. return __builtin_memcmp(__lhs, __rhs, __count * sizeof(_Tp));
  58. #endif
  59. while (__count != 0) {
  60. if (*__lhs < *__rhs)
  61. return -1;
  62. if (*__rhs < *__lhs)
  63. return 1;
  64. --__count;
  65. ++__lhs;
  66. ++__rhs;
  67. }
  68. return 0;
  69. } else {
  70. return __builtin_memcmp(__lhs, __rhs, __count * sizeof(_Tp));
  71. }
  72. }
  73. // Because of __libcpp_is_trivially_equality_comparable we know that comparing the object representations is equivalent
  74. // to a std::memcmp(...) == 0. Since we have multiple objects contiguously in memory, we can call memcmp once instead
  75. // of invoking it on every object individually.
  76. template <class _Tp, class _Up>
  77. _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
  78. __constexpr_memcmp_equal(const _Tp* __lhs, const _Up* __rhs, __element_count __n) {
  79. static_assert(__libcpp_is_trivially_equality_comparable<_Tp, _Up>::value,
  80. "_Tp and _Up have to be trivially equality comparable");
  81. auto __count = static_cast<size_t>(__n);
  82. if (__libcpp_is_constant_evaluated()) {
  83. #ifdef _LIBCPP_COMPILER_CLANG_BASED
  84. if (sizeof(_Tp) == 1 && is_integral<_Tp>::value && !is_same<_Tp, bool>::value)
  85. return __builtin_memcmp(__lhs, __rhs, __count * sizeof(_Tp)) == 0;
  86. #endif
  87. while (__count != 0) {
  88. if (*__lhs != *__rhs)
  89. return false;
  90. --__count;
  91. ++__lhs;
  92. ++__rhs;
  93. }
  94. return true;
  95. } else {
  96. return __builtin_memcmp(__lhs, __rhs, __count * sizeof(_Tp)) == 0;
  97. }
  98. }
  99. template <class _Tp, class _Up>
  100. _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp* __constexpr_memchr(_Tp* __str, _Up __value, size_t __count) {
  101. static_assert(sizeof(_Tp) == 1 && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value,
  102. "Calling memchr on non-trivially equality comparable types is unsafe.");
  103. if (__libcpp_is_constant_evaluated()) {
  104. // use __builtin_char_memchr to optimize constexpr evaluation if we can
  105. #if _LIBCPP_STD_VER >= 17 && __has_builtin(__builtin_char_memchr)
  106. if constexpr (is_same_v<remove_cv_t<_Tp>, char> && is_same_v<remove_cv_t<_Up>, char>)
  107. return __builtin_char_memchr(__str, __value, __count);
  108. #endif
  109. for (; __count; --__count) {
  110. if (*__str == __value)
  111. return __str;
  112. ++__str;
  113. }
  114. return nullptr;
  115. } else {
  116. char __value_buffer = 0;
  117. __builtin_memcpy(&__value_buffer, &__value, sizeof(char));
  118. return static_cast<_Tp*>(__builtin_memchr(__str, __value_buffer, __count));
  119. }
  120. }
  121. // This function performs an assignment to an existing, already alive TriviallyCopyable object
  122. // from another TriviallyCopyable object.
  123. //
  124. // It basically works around the fact that TriviallyCopyable objects are not required to be
  125. // syntactically copy/move constructible or copy/move assignable. Technically, only one of the
  126. // four operations is required to be syntactically valid -- but at least one definitely has to
  127. // be valid.
  128. //
  129. // This is necessary in order to implement __constexpr_memmove below in a way that mirrors as
  130. // closely as possible what the compiler's __builtin_memmove is able to do.
  131. template <class _Tp, class _Up, __enable_if_t<is_assignable<_Tp&, _Up const&>::value, int> = 0>
  132. _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp& __assign_trivially_copyable(_Tp& __dest, _Up const& __src) {
  133. __dest = __src;
  134. return __dest;
  135. }
  136. // clang-format off
  137. template <class _Tp, class _Up, __enable_if_t<!is_assignable<_Tp&, _Up const&>::value &&
  138. is_assignable<_Tp&, _Up&&>::value, int> = 0>
  139. // clang-format on
  140. _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp& __assign_trivially_copyable(_Tp& __dest, _Up& __src) {
  141. __dest =
  142. static_cast<_Up&&>(__src); // this is safe, we're not actually moving anything since the assignment is trivial
  143. return __dest;
  144. }
  145. // clang-format off
  146. template <class _Tp, class _Up, __enable_if_t<!is_assignable<_Tp&, _Up const&>::value &&
  147. !is_assignable<_Tp&, _Up&&>::value &&
  148. is_constructible<_Tp, _Up const&>::value, int> = 0>
  149. // clang-format on
  150. _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& __assign_trivially_copyable(_Tp& __dest, _Up const& __src) {
  151. // _Tp is trivially destructible, so we don't need to call its destructor to end the lifetime of the object
  152. // that was there previously
  153. std::__construct_at(std::addressof(__dest), __src);
  154. return __dest;
  155. }
  156. // clang-format off
  157. template <class _Tp, class _Up, __enable_if_t<!is_assignable<_Tp&, _Up const&>::value &&
  158. !is_assignable<_Tp&, _Up&&>::value &&
  159. !is_constructible<_Tp, _Up const&>::value &&
  160. is_constructible<_Tp, _Up&&>::value, int> = 0>
  161. // clang-format on
  162. _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& __assign_trivially_copyable(_Tp& __dest, _Up& __src) {
  163. // _Tp is trivially destructible, so we don't need to call its destructor to end the lifetime of the object
  164. // that was there previously
  165. std::__construct_at(
  166. std::addressof(__dest),
  167. static_cast<_Up&&>(__src)); // this is safe, we're not actually moving anything since the constructor is trivial
  168. return __dest;
  169. }
  170. template <class _Tp, class _Up, __enable_if_t<__is_always_bitcastable<_Up, _Tp>::value, int> = 0>
  171. _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp*
  172. __constexpr_memmove(_Tp* __dest, _Up* __src, __element_count __n) {
  173. size_t __count = static_cast<size_t>(__n);
  174. if (__libcpp_is_constant_evaluated()) {
  175. #ifdef _LIBCPP_COMPILER_CLANG_BASED
  176. if (is_same<__remove_cv_t<_Tp>, __remove_cv_t<_Up> >::value) {
  177. ::__builtin_memmove(__dest, __src, __count * sizeof(_Tp));
  178. return __dest;
  179. }
  180. #endif
  181. if (std::__is_pointer_in_range(__src, __src + __count, __dest)) {
  182. for (; __count > 0; --__count)
  183. std::__assign_trivially_copyable(__dest[__count - 1], __src[__count - 1]);
  184. } else {
  185. for (size_t __i = 0; __i != __count; ++__i)
  186. std::__assign_trivially_copyable(__dest[__i], __src[__i]);
  187. }
  188. } else if (__count > 0) {
  189. ::__builtin_memmove(__dest, __src, (__count - 1) * sizeof(_Tp) + __libcpp_datasizeof<_Tp>::value);
  190. }
  191. return __dest;
  192. }
  193. _LIBCPP_END_NAMESPACE_STD
  194. #endif // _LIBCPP___STRING_CONSTEXPR_C_FUNCTIONS_H