1 //===-- Libc specific custom operator new and delete ------------*- C++ -*-===// 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 LLVM_LIBC_SRC___SUPPORT_CPP_NEW_H 10 #define LLVM_LIBC_SRC___SUPPORT_CPP_NEW_H 11 12 #include "hdr/func/aligned_alloc.h" 13 #include "hdr/func/free.h" 14 #include "hdr/func/malloc.h" 15 #include "src/__support/common.h" 16 #include "src/__support/macros/config.h" 17 #include "src/__support/macros/properties/os.h" 18 19 #include <stddef.h> // For size_t 20 21 // Defining members in the std namespace is not preferred. But, we do it here 22 // so that we can use it to define the operator new which takes std::align_val_t 23 // argument. 24 namespace std { 25 26 enum class align_val_t : size_t {}; 27 28 } // namespace std 29 30 namespace LIBC_NAMESPACE_DECL { 31 32 class AllocChecker { 33 bool success = false; 34 35 LIBC_INLINE AllocChecker &operator=(bool status) { 36 success = status; 37 return *this; 38 } 39 40 public: 41 LIBC_INLINE AllocChecker() = default; 42 43 LIBC_INLINE operator bool() const { return success; } 44 45 LIBC_INLINE static void *alloc(size_t s, AllocChecker &ac) { 46 void *mem = ::malloc(s); 47 ac = (mem != nullptr); 48 return mem; 49 } 50 51 LIBC_INLINE static void *aligned_alloc(size_t s, std::align_val_t align, 52 AllocChecker &ac) { 53 #ifdef LIBC_TARGET_OS_IS_WINDOWS 54 // std::aligned_alloc is not available on Windows because std::free on 55 // Windows cannot deallocate any over-aligned memory. Microsoft provides an 56 // alternative for std::aligned_alloc named _aligned_malloc, but it must be 57 // paired with _aligned_free instead of std::free. 58 void *mem = ::_aligned_malloc(static_cast<size_t>(align), s); 59 #else 60 void *mem = ::aligned_alloc(static_cast<size_t>(align), s); 61 #endif 62 ac = (mem != nullptr); 63 return mem; 64 } 65 }; 66 67 } // namespace LIBC_NAMESPACE_DECL 68 69 LIBC_INLINE void *operator new(size_t size, 70 LIBC_NAMESPACE::AllocChecker &ac) noexcept { 71 return LIBC_NAMESPACE::AllocChecker::alloc(size, ac); 72 } 73 74 LIBC_INLINE void *operator new(size_t size, std::align_val_t align, 75 LIBC_NAMESPACE::AllocChecker &ac) noexcept { 76 return LIBC_NAMESPACE::AllocChecker::aligned_alloc(size, align, ac); 77 } 78 79 LIBC_INLINE void *operator new[](size_t size, 80 LIBC_NAMESPACE::AllocChecker &ac) noexcept { 81 return LIBC_NAMESPACE::AllocChecker::alloc(size, ac); 82 } 83 84 LIBC_INLINE void *operator new[](size_t size, std::align_val_t align, 85 LIBC_NAMESPACE::AllocChecker &ac) noexcept { 86 return LIBC_NAMESPACE::AllocChecker::aligned_alloc(size, align, ac); 87 } 88 89 LIBC_INLINE void *operator new(size_t, void *p) { return p; } 90 91 LIBC_INLINE void *operator new[](size_t, void *p) { return p; } 92 93 // The ideal situation would be to define the various flavors of operator delete 94 // inlinelike we do with operator new above. However, since we need operator 95 // delete prototypes to match those specified by the C++ standard, we cannot 96 // define them inline as the C++ standard does not allow inline definitions of 97 // replacement operator delete implementations. Note also that we assign a 98 // special linkage name to each of these replacement operator delete functions. 99 // This is because, if we do not give them a special libc internal linkage name, 100 // they will replace operator delete for the entire application. Including this 101 // header file in all libc source files where operator delete is called ensures 102 // that only libc call sites use these replacement operator delete functions. 103 104 #define DELETE_NAME(name) \ 105 __asm__(LIBC_MACRO_TO_STRING(LIBC_NAMESPACE) "_" LIBC_MACRO_TO_STRING(name)) 106 107 void operator delete(void *) noexcept DELETE_NAME(delete); 108 void operator delete(void *, std::align_val_t) noexcept 109 DELETE_NAME(delete_aligned); 110 void operator delete(void *, size_t) noexcept DELETE_NAME(delete_sized); 111 void operator delete(void *, size_t, std::align_val_t) noexcept 112 DELETE_NAME(delete_sized_aligned); 113 void operator delete[](void *) noexcept DELETE_NAME(delete_array); 114 void operator delete[](void *, std::align_val_t) noexcept 115 DELETE_NAME(delete_array_aligned); 116 void operator delete[](void *, size_t) noexcept DELETE_NAME(delete_array_sized); 117 void operator delete[](void *, size_t, std::align_val_t) noexcept 118 DELETE_NAME(delete_array_sized_aligned); 119 120 #undef DELETE_NAME 121 122 #endif // LLVM_LIBC_SRC___SUPPORT_CPP_NEW_H 123