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 | |
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> |
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> |
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(args: __size, args: __align_val)); |
60 | } |
61 | #endif |
62 | |
63 | (void)__align; |
64 | return static_cast<_Tp*>(std::__libcpp_operator_new(args: __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 | |