Merge pull request #12162 from AlexFigas/feat/libc-aligned-array-operators

feat(libc): export the remaining aligned and array operator new and delete overloads
This commit is contained in:
Adrià authored and GitHub committed 2026-10-29 14:39:44 +01:00
commit e87f2d9394
4 files changed
+100 -1

No files matched your search

+8
View File
@@ -944,6 +944,14 @@ void* APS5_VABI _Znam_nid_postfix(std::size_t size);
void* APS5_VABI _ZnwmSt11align_val_t_nid_postfix(std::size_t size, std::size_t alignment);
void* APS5_VABI _ZnwmRKSt9nothrow_t_nid_postfix(std::size_t size, const void*) noexcept;
void* APS5_VABI _ZnamRKSt9nothrow_t_nid_postfix(std::size_t size, const void*) noexcept;
void* APS5_VABI _ZnwmSt11align_val_tRKSt9nothrow_t_nid_postfix(std::size_t size, std::size_t alignment, const void*) noexcept;
void* APS5_VABI _ZnamSt11align_val_t_nid_postfix(std::size_t size, std::size_t alignment);
void* APS5_VABI _ZnamSt11align_val_tRKSt9nothrow_t_nid_postfix(std::size_t size, std::size_t alignment, const void*) noexcept;
void APS5_VABI _ZdaPvRKSt9nothrow_t_nid_postfix(void* pointer, const void*) noexcept;
void APS5_VABI _ZdlPvSt11align_val_tRKSt9nothrow_t_nid_postfix(void* pointer, std::size_t alignment, const void*) noexcept;
void APS5_VABI _ZdaPvSt11align_val_t_nid_postfix(void* pointer, std::size_t alignment);
void APS5_VABI _ZdaPvmSt11align_val_t_nid_postfix(void* pointer, std::size_t, std::size_t alignment);
void APS5_VABI _ZdaPvSt11align_val_tRKSt9nothrow_t_nid_postfix(void* pointer, std::size_t alignment, const void*) noexcept;
void APS5_VABI _ZdlPv_nid_postfix(void* pointer);
void APS5_VABI _ZdlPvRKSt9nothrow_t_nid_postfix(void* pointer, const void*) noexcept;
void APS5_VABI _ZdaPv_nid_postfix(void* pointer);
+40
View File
@@ -156,4 +156,44 @@ void APS5_VABI _ZdlPvmSt11align_val_t_nid_postfix(void* pointer, std::size_t, st
if (pointer != nullptr) ApplicationHeapFree_nid_no_patch(pointer);
}
void* APS5_VABI _ZnwmSt11align_val_tRKSt9nothrow_t_nid_postfix(std::size_t size, std::size_t alignment, const void*) noexcept {
try {
return _ZnwmSt11align_val_t_nid_postfix(size, alignment);
} catch (const std::bad_alloc&) {
return nullptr;
}
}
void* APS5_VABI _ZnamSt11align_val_t_nid_postfix(std::size_t size, std::size_t alignment) {
return _ZnwmSt11align_val_t_nid_postfix(size, alignment);
}
void* APS5_VABI _ZnamSt11align_val_tRKSt9nothrow_t_nid_postfix(std::size_t size, std::size_t alignment, const void*) noexcept {
try {
return _ZnamSt11align_val_t_nid_postfix(size, alignment);
} catch (const std::bad_alloc&) {
return nullptr;
}
}
void APS5_VABI _ZdaPvRKSt9nothrow_t_nid_postfix(void* pointer, const void*) noexcept {
_ZdaPv_nid_postfix(pointer);
}
void APS5_VABI _ZdlPvSt11align_val_tRKSt9nothrow_t_nid_postfix(void* pointer, std::size_t alignment, const void*) noexcept {
_ZdlPvSt11align_val_t_nid_postfix(pointer, alignment);
}
void APS5_VABI _ZdaPvSt11align_val_t_nid_postfix(void* pointer, std::size_t alignment) {
_ZdlPvSt11align_val_t_nid_postfix(pointer, alignment);
}
void APS5_VABI _ZdaPvmSt11align_val_t_nid_postfix(void* pointer, std::size_t, std::size_t alignment) {
_ZdaPvSt11align_val_t_nid_postfix(pointer, alignment);
}
void APS5_VABI _ZdaPvSt11align_val_tRKSt9nothrow_t_nid_postfix(void* pointer, std::size_t alignment, const void*) noexcept {
_ZdaPvSt11align_val_t_nid_postfix(pointer, alignment);
}
}
+50 -1
View File
@@ -17,7 +17,7 @@ using Handler = void (APS5_VABI*)();
namespace {
alignas(16) std::array<std::byte, 64> storage{};
alignas(256) std::array<std::byte, 64> storage{};
unsigned failuresLeft = 0;
unsigned allocations = 0;
unsigned releases = 0;
@@ -99,6 +99,9 @@ int RunDefaultHeap() {
REQUIRE(Throws([] { _Znam_nid_postfix(huge); }));
REQUIRE(_ZnwmRKSt9nothrow_t_nid_postfix(huge, nullptr) == nullptr);
REQUIRE(_ZnamRKSt9nothrow_t_nid_postfix(huge, nullptr) == nullptr);
REQUIRE(Throws([] { _ZnamSt11align_val_t_nid_postfix(huge, 64); }));
REQUIRE(_ZnwmSt11align_val_tRKSt9nothrow_t_nid_postfix(huge, 64, nullptr) == nullptr);
REQUIRE(_ZnamSt11align_val_tRKSt9nothrow_t_nid_postfix(huge, 64, nullptr) == nullptr);
handlerCalls = 0;
REQUIRE(_ZSt15set_new_handlerPFvvE_nid_postfix(&uninstallingHandler) == nullptr);
@@ -204,6 +207,52 @@ int main(int argc, char** argv) {
REQUIRE(_ZnwmSt11align_val_t_nid_postfix(8, 16) == storage.data() && handlerCalls == 2 && allocations == 3);
_ZSt15set_new_handlerPFvvE_nid_postfix(nullptr);
Reset(0);
void* array = _ZnamSt11align_val_t_nid_postfix(40, 64);
REQUIRE(array == storage.data() && lastSize == 40 && lastAlignment == 64 && allocations == 1);
_ZdaPvSt11align_val_t_nid_postfix(array, 64);
REQUIRE(releases == 1);
Reset(0);
REQUIRE(_ZnamSt11align_val_t_nid_postfix(0, 32) == storage.data() && lastSize == 1 && lastAlignment == 32);
Reset(1);
REQUIRE(Throws([] { _ZnamSt11align_val_t_nid_postfix(8, 32); }) && handlerCalls == 0 && allocations == 1);
Reset(0);
REQUIRE(_ZnwmSt11align_val_tRKSt9nothrow_t_nid_postfix(24, 128, &nothrowTag) == storage.data() && lastSize == 24 && lastAlignment == 128);
Reset(1);
REQUIRE(_ZnwmSt11align_val_tRKSt9nothrow_t_nid_postfix(24, 128, &nothrowTag) == nullptr && allocations == 1);
Reset(0);
REQUIRE(_ZnamSt11align_val_tRKSt9nothrow_t_nid_postfix(56, 256, &nothrowTag) == storage.data() && lastSize == 56 && lastAlignment == 256);
Reset(1);
REQUIRE(_ZnamSt11align_val_tRKSt9nothrow_t_nid_postfix(56, 256, &nothrowTag) == nullptr && allocations == 1);
_ZSt15set_new_handlerPFvvE_nid_postfix(&countingHandler);
Reset(2);
REQUIRE(_ZnamSt11align_val_t_nid_postfix(8, 64) == storage.data() && handlerCalls == 2 && allocations == 3);
Reset(1);
REQUIRE(_ZnwmSt11align_val_tRKSt9nothrow_t_nid_postfix(8, 64, &nothrowTag) == storage.data() && handlerCalls == 1 && allocations == 2);
Reset(1);
REQUIRE(_ZnamSt11align_val_tRKSt9nothrow_t_nid_postfix(8, 64, &nothrowTag) == storage.data() && handlerCalls == 1 && allocations == 2);
_ZSt15set_new_handlerPFvvE_nid_postfix(&throwingHandler);
Reset(1);
REQUIRE(_ZnwmSt11align_val_tRKSt9nothrow_t_nid_postfix(8, 64, &nothrowTag) == nullptr && handlerCalls == 1 && allocations == 1);
Reset(1);
REQUIRE(_ZnamSt11align_val_tRKSt9nothrow_t_nid_postfix(8, 64, &nothrowTag) == nullptr && handlerCalls == 1 && allocations == 1);
_ZSt15set_new_handlerPFvvE_nid_postfix(nullptr);
Reset(0);
_ZdaPvRKSt9nothrow_t_nid_postfix(storage.data(), &nothrowTag);
_ZdlPvSt11align_val_tRKSt9nothrow_t_nid_postfix(storage.data(), 64, &nothrowTag);
_ZdaPvmSt11align_val_t_nid_postfix(storage.data(), 40, 64);
_ZdaPvSt11align_val_tRKSt9nothrow_t_nid_postfix(storage.data(), 64, &nothrowTag);
REQUIRE(releases == 4);
_ZdaPvRKSt9nothrow_t_nid_postfix(nullptr, &nothrowTag);
_ZdlPvSt11align_val_tRKSt9nothrow_t_nid_postfix(nullptr, 64, &nothrowTag);
_ZdaPvSt11align_val_t_nid_postfix(nullptr, 64);
_ZdaPvmSt11align_val_t_nid_postfix(nullptr, 0, 64);
_ZdaPvSt11align_val_tRKSt9nothrow_t_nid_postfix(nullptr, 64, &nothrowTag);
REQUIRE(releases == 4);
std::puts("Guest new handler checks passed");
return 0;
}
+2
View File
@@ -109,6 +109,8 @@
- [strtof and wcstof](../../../core/libs/prx/libc/src/Strings.cpp) (libc) round to the nearest float, where the console's `_Stof` in `libSceLibcInternal.sprx` (0x734a0) does not always: about a third of decimal inputs within a relative 2^-51 of a point halfway between two floats, and some hexadecimal inputs with more than 24 significant bits, come out one unit apart in the last place (`1e-40` is `0x1.16c3p-133` there and `0x1.16c2p-133` here). The console's own rounding is not reproduced
- [strtof and wcstof](../../../core/libs/prx/libc/src/Strings.cpp) (libc) - `ERANGE` follows the `libc.prx` bundled with PPSA08427 (J03547016) and PPSA03671 (J03848509), both run side by side with this libc on a Linux host: a decimal input whose result is a nonzero subnormal sets it only when inexact, a hexadecimal one only when it lies below the smallest subnormal and rounds up to it, and underflow to zero and overflow set it. Both builds also take a `NAN(...)` payload in `strtof` from the sequence's leading digits (`nan(0x123)` is `0x7fc00123`, `-nan(5)` is `0xffc00005`); the sign is kept here, the payload is not. `libSceLibcInternal`'s `_Stof` differs: no `ERANGE` for hexadecimal input, a positive `nan`, and after a minus sign a failed parse is `-0.0` for a lone sign and `+0.0` before an `inf`/`nan` spelling, the reverse of `libc.prx`. Decimal `strtod` sets `ERANGE` for a nonzero subnormal in J03547016 but not in J03848509 or `libSceLibcInternal`, whose result is kept.
- [operator new](../../../core/libs/prx/libc/src/StdioExtras.cpp) (libc) - the `nothrow` forms return null only for `std::bad_alloc`, where the `libc.prx` bundled with PPSA21564 (build `J03093718`) catches every exception there, so a new handler that throws anything else ends the process instead of returning null. The aligned forms throw `std::bad_alloc` for an alignment of zero or one that is not a power of two, where that binary calls `abort`.
- [Guest time conversions](../../../core/libs/prx/libc/src/Time.cpp) rewrite the host process `TZ` when a guest changes its own `TZ`, so other host consumers of that variable (including libSceRtc local time) shift too; code outside libc does not take the zone lock. Zone syntax follows the host C runtime, not FreeBSD: Windows only accepts the `std offset [dst]` form, treats an empty guest `TZ` as `UTC0` and reads `:Europe/Berlin` as an abbreviation (for example `rop`); only Linux honours zone file names. If the guest accepts a `TZ` value that the host rejects (on Windows, for example, one longer than the host environment limit), conversions throw `std::runtime_error`. A `tm_zone` saved before a `TZ` change can refer to storage now holding the new zone name; `strftime` does not read it.
- [cbrtf](../../../core/libs/prx/libc/src/Math.cpp) (libc) is FreeBSD msun's [`s_cbrtf.c`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/lib/msun/src/s_cbrtf.c): a 5-bit first guess from the exponent bits, then two Newton steps in double precision. It sets no `errno`, as the `libc.prx` that titles ship does not. Floating-point exceptions are not compared. It gives the same bits as the `cbrtf` of the `libc.prx` bundled with PPSA07923, PPSA05916 and PPSA13934 for all 2^32 arguments, run on a Windows host.
- [logf](../../../core/libs/prx/libc/src/Math.cpp) (libc) is FreeBSD msun's [`e_logf.c`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/lib/msun/src/e_logf.c), with `vzero` read at run time as msun's `volatile` read does. As in the `libc.prx` that titles ship, `errno` is set to `ERANGE` for ±0 and to `EDOM` for every argument with the sign bit set, negative NaNs and -inf included; positive NaNs and +inf leave it unchanged. Floating-point exceptions are not compared. It gives the same bits and `errno` as the `logf` of the `libc.prx` bundled with PPSA07923 and PPSA05916 for all 2^32 arguments, run on a Windows host. The FMA-contracted build bundled with PPSA13934 differs from it by 1 ulp on 961,881 arguments, so no single port matches every title's last bit.