/* * kernel/lib/cxxabi.cpp * * C++ ABI runtime support for a freestanding kernel. * * The compiler emits calls to these functions for: * - Pure virtual function calls (__cxa_pure_virtual) * - Global object destructors (__cxa_atexit, __dso_handle) * - new/delete operators * * Compile with -fno-exceptions -fno-rtti, so we don't need * exception handling or typeinfo support. */ #include #include #include extern "C" { /* * Called when a pure virtual function is invoked. * This should never happen in correct code — it's a fatal error. */ [[noreturn]] void __cxa_pure_virtual() { kernel::GetKernel().Panic("pure virtual function called"); } /* * Static local variable guards (thread-safe init in the Itanium ABI). * * The ABI stores the "initialized" flag in the least-significant byte of the * 64-bit guard variable (Itanium C++ ABI 3.3.2 and 3.3.3 ). On little-endian targets * (x86_64, AArch64) that byte is at the lowest address, so casting the * guard pointer to uint8_t* and reading/writing byte 0 is correct. * * In a single-CPU kernel with no preemption, the full acquire/release * protocol is unnecessary — we just check and set the byte. */ int __cxa_guard_acquire(uint64_t* guard) { return !(*reinterpret_cast(guard)); } void __cxa_guard_release(uint64_t* guard) { *reinterpret_cast(guard) = 1; } void __cxa_guard_abort(uint64_t* guard) { (void)guard; } /* * atexit support — for global object destructors. * In a kernel, we never "exit", so this is a no-op. */ int __cxa_atexit(void (*)(void*), void*, void*) { return 0; } void* __dso_handle = nullptr; } /* extern "C" */ /* * Placement new — always needed. * Sized new/delete — routed through kernel heap once available (Phase 3). */ // [[nodiscard]]: ignoring the returned pointer from new is always a bug. [[nodiscard]] void* operator new(size_t size) { (void)size; return nullptr; /* TODO: kmalloc */ } [[nodiscard]] void* operator new[](size_t size) { (void)size; return nullptr; /* TODO: kmalloc */ } void operator delete(void* ptr) noexcept { (void)ptr; /* TODO: kfree */ } void operator delete[](void* ptr) noexcept { (void)ptr; /* TODO: kfree */ } void operator delete(void* ptr, size_t) noexcept { (void)ptr; /* TODO: kfree */ } void operator delete[](void* ptr, size_t) noexcept { (void)ptr; /* TODO: kfree */ } /* Placement new — doesn't allocate, just returns the pointer */ inline void* operator new(size_t, void* ptr) noexcept { return ptr; } inline void* operator new[](size_t, void* ptr) noexcept { return ptr; }