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
9 #ifndef _LIBCPP___NEW_ALLOCATE_H
10 #define _LIBCPP___NEW_ALLOCATE_H
11
12 #include <__config>
13 #include <__cstddef/max_align_t.h>
14 #include <__cstddef/size_t.h>
15 #include <__new/align_val_t.h>
16 #include <__new/global_new_delete.h> // for _LIBCPP_HAS_SIZED_DEALLOCATION
17 #include <__type_traits/type_identity.h>
18 #include <__utility/element_count.h>
19
20 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
21 # pragma GCC system_header
22 #endif
23
24 _LIBCPP_BEGIN_NAMESPACE_STD
25
__is_overaligned_for_new(size_t __align)26 _LIBCPP_CONSTEXPR inline _LIBCPP_HIDE_FROM_ABI bool __is_overaligned_for_new(size_t __align) _NOEXCEPT {
27 #ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__
28 return __align > __STDCPP_DEFAULT_NEW_ALIGNMENT__;
29 #else
30 return __align > _LIBCPP_ALIGNOF(max_align_t);
31 #endif
32 }
33
34 template <class... _Args>
__libcpp_operator_new(_Args...__args)35 _LIBCPP_HIDE_FROM_ABI void* __libcpp_operator_new(_Args... __args) {
36 #if __has_builtin(__builtin_operator_new) && __has_builtin(__builtin_operator_delete)
37 return __builtin_operator_new(__args...);
38 #else
39 return ::operator new(__args...);
40 #endif
41 }
42
43 template <class... _Args>
__libcpp_operator_delete(_Args...__args)44 _LIBCPP_HIDE_FROM_ABI void __libcpp_operator_delete(_Args... __args) _NOEXCEPT {
45 #if __has_builtin(__builtin_operator_new) && __has_builtin(__builtin_operator_delete)
46 __builtin_operator_delete(__args...);
47 #else
48 ::operator delete(__args...);
49 #endif
50 }
51
52 template <class _Tp>
53 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI _Tp*
54 __libcpp_allocate(__element_count __n, size_t __align = _LIBCPP_ALIGNOF(_Tp)) {
55 size_t __size = static_cast<size_t>(__n) * sizeof(_Tp);
56 #if _LIBCPP_HAS_ALIGNED_ALLOCATION
57 if (__is_overaligned_for_new(__align)) {
58 const align_val_t __align_val = static_cast<align_val_t>(__align);
59 return static_cast<_Tp*>(std::__libcpp_operator_new(__size, __align_val));
60 }
61 #endif
62
63 (void)__align;
64 return static_cast<_Tp*>(std::__libcpp_operator_new(__size));
65 }
66
67 #if _LIBCPP_HAS_SIZED_DEALLOCATION
68 # define _LIBCPP_ONLY_IF_SIZED_DEALLOCATION(...) __VA_ARGS__
69 #else
70 # define _LIBCPP_ONLY_IF_SIZED_DEALLOCATION(...) /* nothing */
71 #endif
72
73 template <class _Tp>
74 inline _LIBCPP_HIDE_FROM_ABI void __libcpp_deallocate(
75 __type_identity_t<_Tp>* __ptr, __element_count __n, size_t __align = _LIBCPP_ALIGNOF(_Tp)) _NOEXCEPT {
76 size_t __size = static_cast<size_t>(__n) * sizeof(_Tp);
77 (void)__size;
78 #if !_LIBCPP_HAS_ALIGNED_ALLOCATION
79 (void)__align;
80 return std::__libcpp_operator_delete(__ptr _LIBCPP_ONLY_IF_SIZED_DEALLOCATION(, __size));
81 #else
82 if (__is_overaligned_for_new(__align)) {
83 const align_val_t __align_val = static_cast<align_val_t>(__align);
84 return std::__libcpp_operator_delete(__ptr _LIBCPP_ONLY_IF_SIZED_DEALLOCATION(, __size), __align_val);
85 } else {
86 return std::__libcpp_operator_delete(__ptr _LIBCPP_ONLY_IF_SIZED_DEALLOCATION(, __size));
87 }
88 #endif
89 }
90
91 #undef _LIBCPP_ONLY_IF_SIZED_DEALLOCATION
92
93 template <class _Tp>
94 inline _LIBCPP_HIDE_FROM_ABI void
95 __libcpp_deallocate_unsized(__type_identity_t<_Tp>* __ptr, size_t __align = _LIBCPP_ALIGNOF(_Tp)) _NOEXCEPT {
96 #if !_LIBCPP_HAS_ALIGNED_ALLOCATION
97 (void)__align;
98 return std::__libcpp_operator_delete(__ptr);
99 #else
100 if (__is_overaligned_for_new(__align)) {
101 const align_val_t __align_val = static_cast<align_val_t>(__align);
102 return std::__libcpp_operator_delete(__ptr, __align_val);
103 } else {
104 return std::__libcpp_operator_delete(__ptr);
105 }
106 #endif
107 }
108 _LIBCPP_END_NAMESPACE_STD
109
110 #endif // _LIBCPP___NEW_ALLOCATE_H
111