diff --git a/ctl/new.cc b/ctl/new.cc index 7cac144ec..5df2d54ff 100644 --- a/ctl/new.cc +++ b/ctl/new.cc @@ -20,97 +20,80 @@ #include "libc/mem/mem.h" -using ctl::align_val_t; +COSMOPOLITAN_C_START_ -namespace { - -constexpr auto a1 = align_val_t(1); - -} // namespace - -void* -operator new(size_t n, align_val_t a) +static void* +_ctl_alloc(size_t n, size_t a) { void* p; - if (!(p = memalign(static_cast(a), n))) { + if (!(p = memalign(a, n))) __builtin_trap(); - } return p; } -void* -operator new[](size_t n, align_val_t a) +static void* +_ctl_alloc1(size_t n) { - return operator new(n, a); -} -void* -operator new(size_t n) -{ - return operator new(n, a1); -} -void* -operator new[](size_t n) -{ - return operator new(n, a1); + return _ctl_alloc(n, 1); } -void* -operator new(size_t, void* p) -{ - return p; -} -void* -operator new[](size_t, void* p) +static void* +_ctl_ret(size_t, void* p) { return p; } -void -operator delete(void* p) noexcept -{ - free(p); -} -void -operator delete[](void* p) noexcept -{ - free(p); -} -void -operator delete(void* p, align_val_t) noexcept -{ - free(p); -} -void -operator delete[](void* p, align_val_t) noexcept -{ - free(p); -} -void -operator delete(void* p, size_t) noexcept -{ - free(p); -} -void -operator delete[](void* p, size_t) noexcept -{ - free(p); -} -void -operator delete(void* p, size_t, align_val_t) noexcept -{ - free(p); -} -void -operator delete[](void* p, size_t, align_val_t) noexcept +static void +_ctl_free(void* p) { free(p); } -void -operator delete(void*, void*) noexcept -{ -} -void -operator delete[](void*, void*) noexcept +static void +_ctl_nop(void*, void*) { } + +COSMOPOLITAN_C_END_ + +#undef __weak_reference +#define __weak_reference(P, A) P __attribute__((weak, alias(#A))) + +/* The ISO says that these should be replaceable by user code. It also says + that the declarations for the first four (i.e. non placement-) operators + new are implicitly available in each translation unit, including the std + align_val_t parameter. (?) However, also _defines_ the align_val_t + type so you can’t just write your own. Our way through this morass is to + supply ours as ctl::align_val_t and not implicitly declare anything, for + now. If you have any brain cells left after reading this comment then go + look at the eight operator delete weak references to free in the below. */ + +__weak_reference(void* operator new(size_t, ctl::align_val_t), _ctl_alloc); +__weak_reference(void* operator new[](size_t, ctl::align_val_t), _ctl_alloc); +__weak_reference(void* operator new(size_t), _ctl_alloc1); +__weak_reference(void* operator new[](size_t), _ctl_alloc1); + +// XXX clang-format currently mutilates these for some reason. +// clang-format off + +__weak_reference(void* operator new(size_t, void*), _ctl_ret); +__weak_reference(void* operator new[](size_t, void*), _ctl_ret); + +__weak_reference(void operator delete(void*) noexcept, _ctl_free); +__weak_reference(void operator delete[](void*) noexcept, _ctl_free); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wattribute-alias=" +__weak_reference(void operator delete(void*, ctl::align_val_t) noexcept, + _ctl_free); +__weak_reference(void operator delete[](void*, ctl::align_val_t) noexcept, + _ctl_free); +__weak_reference(void operator delete(void*, size_t) noexcept, _ctl_free); +__weak_reference(void operator delete[](void*, size_t) noexcept, _ctl_free); +__weak_reference(void operator delete(void*, size_t, ctl::align_val_t) noexcept, + _ctl_free); +__weak_reference(void operator delete[](void*, size_t, ctl::align_val_t) + noexcept, _ctl_free); +#pragma GCC diagnostic pop + +__weak_reference(void operator delete(void*, void*) noexcept, _ctl_nop); +__weak_reference(void operator delete[](void*, void*) noexcept, _ctl_nop); diff --git a/ctl/new.h b/ctl/new.h index f227270ef..97fe85ef8 100644 --- a/ctl/new.h +++ b/ctl/new.h @@ -3,12 +3,11 @@ #ifndef COSMOPOLITAN_CTL_NEW_H_ #define COSMOPOLITAN_CTL_NEW_H_ -// XXX clang-format currently mutilates these for some reason. -// clang-format off - namespace ctl { -enum class align_val_t : size_t {}; +enum class align_val_t : size_t +{ +}; } // namespace ctl @@ -16,6 +15,10 @@ void* operator new(size_t); void* operator new[](size_t); void* operator new(size_t, ctl::align_val_t); void* operator new[](size_t, ctl::align_val_t); + +// XXX clang-format currently mutilates these for some reason. +// clang-format off + void* operator new(size_t, void*); void* operator new[](size_t, void*);