[AMDGPU] Mark AGPR tuple implicit in the first instr of AGPR spills. (#115285)
[llvm-project.git] / libcxx / test / support / count_new.h
blobc8169d3acceabdf9f19772637e6c26749baf7eb6
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 //===----------------------------------------------------------------------===//
9 #ifndef COUNT_NEW_H
10 #define COUNT_NEW_H
12 #include <algorithm>
13 #include <cassert>
14 #include <cerrno>
15 #include <cstdlib>
16 #include <new>
17 #include <type_traits>
19 #include "test_macros.h"
21 #if defined(TEST_HAS_SANITIZERS)
22 #define DISABLE_NEW_COUNT
23 #endif
25 namespace detail
27 [[noreturn]] inline void throw_bad_alloc_helper() {
28 #ifndef TEST_HAS_NO_EXCEPTIONS
29 throw std::bad_alloc();
30 #else
31 std::abort();
32 #endif
36 class MemCounter
38 public:
39 // Make MemCounter super hard to accidentally construct or copy.
40 class MemCounterCtorArg_ {};
41 explicit MemCounter(MemCounterCtorArg_) { reset(); }
43 private:
44 MemCounter(MemCounter const &);
45 MemCounter & operator=(MemCounter const &);
47 public:
48 // All checks return true when disable_checking is enabled.
49 static const bool disable_checking;
51 // Disallow any allocations from occurring. Useful for testing that
52 // code doesn't perform any allocations.
53 bool disable_allocations;
55 // number of allocations to throw after. Default (unsigned)-1. If
56 // throw_after has the default value it will never be decremented.
57 static const unsigned never_throw_value = static_cast<unsigned>(-1);
58 unsigned throw_after;
60 int outstanding_new;
61 int new_called;
62 int delete_called;
63 int aligned_new_called;
64 int aligned_delete_called;
65 std::size_t last_new_size;
66 std::size_t last_new_align;
67 std::size_t last_delete_align;
69 int outstanding_array_new;
70 int new_array_called;
71 int delete_array_called;
72 int aligned_new_array_called;
73 int aligned_delete_array_called;
74 std::size_t last_new_array_size;
75 std::size_t last_new_array_align;
76 std::size_t last_delete_array_align;
78 public:
79 void newCalled(std::size_t s)
81 assert(disable_allocations == false);
82 if (throw_after == 0) {
83 throw_after = never_throw_value;
84 detail::throw_bad_alloc_helper();
85 } else if (throw_after != never_throw_value) {
86 --throw_after;
88 ++new_called;
89 ++outstanding_new;
90 last_new_size = s;
93 void alignedNewCalled(std::size_t s, std::size_t a) {
94 newCalled(s);
95 ++aligned_new_called;
96 last_new_align = a;
99 void deleteCalled(void * p)
101 if (p) {
102 --outstanding_new;
103 ++delete_called;
107 void alignedDeleteCalled(void *p, std::size_t a) {
108 if (p) {
109 deleteCalled(p);
110 ++aligned_delete_called;
111 last_delete_align = a;
115 void newArrayCalled(std::size_t s)
117 assert(disable_allocations == false);
118 if (throw_after == 0) {
119 throw_after = never_throw_value;
120 detail::throw_bad_alloc_helper();
121 } else {
122 // don't decrement throw_after here. newCalled will end up doing that.
124 ++outstanding_array_new;
125 ++new_array_called;
126 last_new_array_size = s;
129 void alignedNewArrayCalled(std::size_t s, std::size_t a) {
130 newArrayCalled(s);
131 ++aligned_new_array_called;
132 last_new_array_align = a;
135 void deleteArrayCalled(void * p)
137 assert(p);
138 --outstanding_array_new;
139 ++delete_array_called;
142 void alignedDeleteArrayCalled(void * p, std::size_t a) {
143 deleteArrayCalled(p);
144 ++aligned_delete_array_called;
145 last_delete_array_align = a;
148 void disableAllocations()
150 disable_allocations = true;
153 void enableAllocations()
155 disable_allocations = false;
158 void reset()
160 disable_allocations = false;
161 throw_after = never_throw_value;
163 outstanding_new = 0;
164 new_called = 0;
165 delete_called = 0;
166 aligned_new_called = 0;
167 aligned_delete_called = 0;
168 last_new_size = 0;
169 last_new_align = 0;
171 outstanding_array_new = 0;
172 new_array_called = 0;
173 delete_array_called = 0;
174 aligned_new_array_called = 0;
175 aligned_delete_array_called = 0;
176 last_new_array_size = 0;
177 last_new_array_align = 0;
180 public:
181 bool checkOutstandingNewEq(int n) const
183 return disable_checking || n == outstanding_new;
186 bool checkOutstandingNewLessThanOrEqual(int n) const
188 return disable_checking || outstanding_new <= n;
191 bool checkOutstandingNewNotEq(int n) const
193 return disable_checking || n != outstanding_new;
196 bool checkNewCalledEq(int n) const
198 return disable_checking || n == new_called;
201 bool checkNewCalledNotEq(int n) const
203 return disable_checking || n != new_called;
206 bool checkNewCalledGreaterThan(int n) const
208 return disable_checking || new_called > n;
211 bool checkDeleteCalledEq(int n) const
213 return disable_checking || n == delete_called;
216 bool checkDeleteCalledNotEq(int n) const
218 return disable_checking || n != delete_called;
221 bool checkDeleteCalledGreaterThan(int n) const
223 return disable_checking || delete_called > n;
226 bool checkAlignedNewCalledEq(int n) const
228 return disable_checking || n == aligned_new_called;
231 bool checkAlignedNewCalledNotEq(int n) const
233 return disable_checking || n != aligned_new_called;
236 bool checkAlignedNewCalledGreaterThan(int n) const
238 return disable_checking || aligned_new_called > n;
241 bool checkAlignedDeleteCalledEq(int n) const
243 return disable_checking || n == aligned_delete_called;
246 bool checkAlignedDeleteCalledNotEq(int n) const
248 return disable_checking || n != aligned_delete_called;
251 bool checkLastNewSizeEq(std::size_t n) const
253 return disable_checking || n == last_new_size;
256 bool checkLastNewSizeNotEq(std::size_t n) const
258 return disable_checking || n != last_new_size;
261 bool checkLastNewSizeGe(std::size_t n) const
263 return disable_checking || last_new_size >= n;
266 bool checkLastNewAlignEq(std::size_t n) const
268 return disable_checking || n == last_new_align;
271 bool checkLastNewAlignNotEq(std::size_t n) const
273 return disable_checking || n != last_new_align;
276 bool checkLastNewAlignGe(std::size_t n) const
278 return disable_checking || last_new_align >= n;
281 bool checkLastDeleteAlignEq(std::size_t n) const
283 return disable_checking || n == last_delete_align;
286 bool checkLastDeleteAlignNotEq(std::size_t n) const
288 return disable_checking || n != last_delete_align;
291 bool checkOutstandingArrayNewEq(int n) const
293 return disable_checking || n == outstanding_array_new;
296 bool checkOutstandingArrayNewNotEq(int n) const
298 return disable_checking || n != outstanding_array_new;
301 bool checkNewArrayCalledEq(int n) const
303 return disable_checking || n == new_array_called;
306 bool checkNewArrayCalledNotEq(int n) const
308 return disable_checking || n != new_array_called;
311 bool checkDeleteArrayCalledEq(int n) const
313 return disable_checking || n == delete_array_called;
316 bool checkDeleteArrayCalledNotEq(int n) const
318 return disable_checking || n != delete_array_called;
321 bool checkAlignedNewArrayCalledEq(int n) const
323 return disable_checking || n == aligned_new_array_called;
326 bool checkAlignedNewArrayCalledNotEq(int n) const
328 return disable_checking || n != aligned_new_array_called;
331 bool checkAlignedNewArrayCalledGreaterThan(int n) const
333 return disable_checking || aligned_new_array_called > n;
336 bool checkAlignedDeleteArrayCalledEq(int n) const
338 return disable_checking || n == aligned_delete_array_called;
341 bool checkAlignedDeleteArrayCalledNotEq(int n) const
343 return disable_checking || n != aligned_delete_array_called;
346 bool checkLastNewArraySizeEq(std::size_t n) const
348 return disable_checking || n == last_new_array_size;
351 bool checkLastNewArraySizeNotEq(std::size_t n) const
353 return disable_checking || n != last_new_array_size;
356 bool checkLastNewArrayAlignEq(std::size_t n) const
358 return disable_checking || n == last_new_array_align;
361 bool checkLastNewArrayAlignNotEq(std::size_t n) const
363 return disable_checking || n != last_new_array_align;
367 #ifdef DISABLE_NEW_COUNT
368 const bool MemCounter::disable_checking = true;
369 #else
370 const bool MemCounter::disable_checking = false;
371 #endif
373 TEST_DIAGNOSTIC_PUSH
374 TEST_MSVC_DIAGNOSTIC_IGNORED(4640) // '%s' construction of local static object is not thread safe (/Zc:threadSafeInit-)
375 inline MemCounter* getGlobalMemCounter() {
376 static MemCounter counter((MemCounter::MemCounterCtorArg_()));
377 return &counter;
379 TEST_DIAGNOSTIC_POP
381 MemCounter &globalMemCounter = *getGlobalMemCounter();
383 #ifndef DISABLE_NEW_COUNT
384 // operator new(size_t[, nothrow_t]) and operator delete(size_t[, nothrow_t])
385 void* operator new(std::size_t s) TEST_THROW_SPEC(std::bad_alloc) {
386 getGlobalMemCounter()->newCalled(s);
387 if (s == 0)
388 ++s;
389 void* p = std::malloc(s);
390 if (p == nullptr)
391 detail::throw_bad_alloc_helper();
392 return p;
395 void* operator new(std::size_t s, std::nothrow_t const&) TEST_NOEXCEPT {
396 # ifdef TEST_HAS_NO_EXCEPTIONS
397 getGlobalMemCounter()->newCalled(s);
398 # else
399 try {
400 getGlobalMemCounter()->newCalled(s);
401 } catch (std::bad_alloc const&) {
402 return nullptr;
404 # endif
405 return std::malloc(s);
408 void operator delete(void* p) TEST_NOEXCEPT {
409 getGlobalMemCounter()->deleteCalled(p);
410 std::free(p);
413 void operator delete(void* p, std::nothrow_t const&) TEST_NOEXCEPT {
414 getGlobalMemCounter()->deleteCalled(p);
415 std::free(p);
418 // operator new[](size_t[, nothrow_t]) and operator delete[](size_t[, nothrow_t])
419 void* operator new[](std::size_t s) TEST_THROW_SPEC(std::bad_alloc) {
420 getGlobalMemCounter()->newArrayCalled(s);
421 if (s == 0)
422 s++;
423 void* p = std::malloc(s);
424 if (p == nullptr)
425 detail::throw_bad_alloc_helper();
426 return p;
429 void* operator new[](std::size_t s, std::nothrow_t const&) TEST_NOEXCEPT {
430 # ifdef TEST_HAS_NO_EXCEPTIONS
431 getGlobalMemCounter()->newArrayCalled(s);
432 # else
433 try {
434 getGlobalMemCounter()->newArrayCalled(s);
435 } catch (std::bad_alloc const&) {
436 return nullptr;
438 # endif
439 return std::malloc(s);
442 void operator delete[](void* p) TEST_NOEXCEPT {
443 getGlobalMemCounter()->deleteArrayCalled(p);
444 std::free(p);
447 void operator delete[](void* p, std::nothrow_t const&) TEST_NOEXCEPT {
448 getGlobalMemCounter()->deleteArrayCalled(p);
449 std::free(p);
452 # ifndef TEST_HAS_NO_ALIGNED_ALLOCATION
453 # if defined(_LIBCPP_MSVCRT_LIKE) || (!defined(_LIBCPP_VERSION) && defined(_WIN32))
454 # define USE_ALIGNED_ALLOC
455 # endif
457 # if defined(__APPLE__)
458 # if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
459 __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101500)
460 # define TEST_HAS_NO_C11_ALIGNED_ALLOC
461 # endif
462 # elif defined(__ANDROID__) && __ANDROID_API__ < 28
463 # define TEST_HAS_NO_C11_ALIGNED_ALLOC
464 # endif
466 inline void* allocate_aligned_impl(std::size_t size, std::align_val_t align) {
467 const std::size_t alignment = static_cast<std::size_t>(align);
468 void* ret = nullptr;
469 # ifdef USE_ALIGNED_ALLOC
470 ret = _aligned_malloc(size, alignment);
471 # elif TEST_STD_VER >= 17 && !defined(TEST_HAS_NO_C11_ALIGNED_ALLOC)
472 size_t rounded_size = (size + alignment - 1) & ~(alignment - 1);
473 ret = aligned_alloc(alignment, size > rounded_size ? size : rounded_size);
474 # else
475 assert(posix_memalign(&ret, std::max(alignment, sizeof(void*)), size) != EINVAL);
476 # endif
477 return ret;
480 inline void free_aligned_impl(void* ptr, std::align_val_t) {
481 if (ptr) {
482 # ifdef USE_ALIGNED_ALLOC
483 ::_aligned_free(ptr);
484 # else
485 ::free(ptr);
486 # endif
490 // operator new(size_t, align_val_t[, nothrow_t]) and operator delete(size_t, align_val_t[, nothrow_t])
491 void* operator new(std::size_t s, std::align_val_t av) TEST_THROW_SPEC(std::bad_alloc) {
492 getGlobalMemCounter()->alignedNewCalled(s, static_cast<std::size_t>(av));
493 void* p = allocate_aligned_impl(s, av);
494 if (p == nullptr)
495 detail::throw_bad_alloc_helper();
496 return p;
499 void* operator new(std::size_t s, std::align_val_t av, std::nothrow_t const&) TEST_NOEXCEPT {
500 # ifdef TEST_HAS_NO_EXCEPTIONS
501 getGlobalMemCounter()->alignedNewCalled(s, static_cast<std::size_t>(av));
502 # else
503 try {
504 getGlobalMemCounter()->alignedNewCalled(s, static_cast<std::size_t>(av));
505 } catch (std::bad_alloc const&) {
506 return nullptr;
508 # endif
509 return allocate_aligned_impl(s, av);
512 void operator delete(void* p, std::align_val_t av) TEST_NOEXCEPT {
513 getGlobalMemCounter()->alignedDeleteCalled(p, static_cast<std::size_t>(av));
514 free_aligned_impl(p, av);
517 void operator delete(void* p, std::align_val_t av, std::nothrow_t const&) TEST_NOEXCEPT {
518 getGlobalMemCounter()->alignedDeleteCalled(p, static_cast<std::size_t>(av));
519 free_aligned_impl(p, av);
522 // operator new[](size_t, align_val_t[, nothrow_t]) and operator delete[](size_t, align_val_t[, nothrow_t])
523 void* operator new[](std::size_t s, std::align_val_t av) TEST_THROW_SPEC(std::bad_alloc) {
524 getGlobalMemCounter()->alignedNewArrayCalled(s, static_cast<std::size_t>(av));
525 void* p = allocate_aligned_impl(s, av);
526 if (p == nullptr)
527 detail::throw_bad_alloc_helper();
528 return p;
531 void* operator new[](std::size_t s, std::align_val_t av, std::nothrow_t const&) TEST_NOEXCEPT {
532 # ifdef TEST_HAS_NO_EXCEPTIONS
533 getGlobalMemCounter()->alignedNewArrayCalled(s, static_cast<std::size_t>(av));
534 # else
535 try {
536 getGlobalMemCounter()->alignedNewArrayCalled(s, static_cast<std::size_t>(av));
537 } catch (std::bad_alloc const&) {
538 return nullptr;
540 # endif
541 return allocate_aligned_impl(s, av);
544 void operator delete[](void* p, std::align_val_t av) TEST_NOEXCEPT {
545 getGlobalMemCounter()->alignedDeleteArrayCalled(p, static_cast<std::size_t>(av));
546 free_aligned_impl(p, av);
549 void operator delete[](void* p, std::align_val_t av, std::nothrow_t const&) TEST_NOEXCEPT {
550 getGlobalMemCounter()->alignedDeleteArrayCalled(p, static_cast<std::size_t>(av));
551 free_aligned_impl(p, av);
554 # endif // TEST_HAS_NO_ALIGNED_ALLOCATION
556 #endif // DISABLE_NEW_COUNT
558 struct DisableAllocationGuard {
559 explicit DisableAllocationGuard(bool disable = true) : m_disabled(disable)
561 // Don't re-disable if already disabled.
562 if (globalMemCounter.disable_allocations == true) m_disabled = false;
563 if (m_disabled) globalMemCounter.disableAllocations();
566 void release() {
567 if (m_disabled) globalMemCounter.enableAllocations();
568 m_disabled = false;
571 ~DisableAllocationGuard() {
572 release();
575 private:
576 bool m_disabled;
578 DisableAllocationGuard(DisableAllocationGuard const&);
579 DisableAllocationGuard& operator=(DisableAllocationGuard const&);
582 #if TEST_STD_VER >= 20
584 struct ConstexprDisableAllocationGuard {
585 TEST_CONSTEXPR_CXX14 explicit ConstexprDisableAllocationGuard(bool disable = true) : m_disabled(disable)
587 if (!TEST_IS_CONSTANT_EVALUATED) {
588 // Don't re-disable if already disabled.
589 if (globalMemCounter.disable_allocations == true) m_disabled = false;
590 if (m_disabled) globalMemCounter.disableAllocations();
591 } else {
592 m_disabled = false;
596 TEST_CONSTEXPR_CXX14 void release() {
597 if (!TEST_IS_CONSTANT_EVALUATED) {
598 if (m_disabled) globalMemCounter.enableAllocations();
599 m_disabled = false;
603 TEST_CONSTEXPR_CXX20 ~ConstexprDisableAllocationGuard() {
604 release();
607 private:
608 bool m_disabled;
610 ConstexprDisableAllocationGuard(ConstexprDisableAllocationGuard const&);
611 ConstexprDisableAllocationGuard& operator=(ConstexprDisableAllocationGuard const&);
614 #endif
616 struct RequireAllocationGuard {
617 explicit RequireAllocationGuard(std::size_t RequireAtLeast = 1)
618 : m_req_alloc(RequireAtLeast),
619 m_new_count_on_init(globalMemCounter.new_called),
620 m_outstanding_new_on_init(globalMemCounter.outstanding_new),
621 m_exactly(false)
625 void requireAtLeast(std::size_t N) { m_req_alloc = N; m_exactly = false; }
626 void requireExactly(std::size_t N) { m_req_alloc = N; m_exactly = true; }
628 ~RequireAllocationGuard() {
629 assert(globalMemCounter.checkOutstandingNewEq(static_cast<int>(m_outstanding_new_on_init)));
630 std::size_t Expect = m_new_count_on_init + m_req_alloc;
631 assert(globalMemCounter.checkNewCalledEq(static_cast<int>(Expect)) ||
632 (!m_exactly && globalMemCounter.checkNewCalledGreaterThan(static_cast<int>(Expect))));
635 private:
636 std::size_t m_req_alloc;
637 const std::size_t m_new_count_on_init;
638 const std::size_t m_outstanding_new_on_init;
639 bool m_exactly;
640 RequireAllocationGuard(RequireAllocationGuard const&);
641 RequireAllocationGuard& operator=(RequireAllocationGuard const&);
644 #endif /* COUNT_NEW_H */