spb/forge Public MIT
Forge — LLM training from scratch in pure C++20 + Metal on Apple Silicon.
C++ 61.2%
C 23%
Python 7.6%
TeX 7.2%
CMake 1.1%
1//-------------------------------------------------------------------------------------------------------------------------------------------------------------2//3// Foundation/NSObject.hpp4//5// Copyright 2020-2024 Apple Inc.6//7// Licensed under the Apache License, Version 2.0 (the "License");8// you may not use this file except in compliance with the License.9// You may obtain a copy of the License at10//11// http://www.apache.org/licenses/LICENSE-2.012//13// Unless required by applicable law or agreed to in writing, software14// distributed under the License is distributed on an "AS IS" BASIS,15// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.16// See the License for the specific language governing permissions and17// limitations under the License.18//19//-------------------------------------------------------------------------------------------------------------------------------------------------------------2021#pragma once2223//-------------------------------------------------------------------------------------------------------------------------------------------------------------2425#include "NSDefines.hpp"26#include "NSPrivate.hpp"27#include "NSTypes.hpp"2829#include <objc/message.h>30#include <objc/runtime.h>3132#include <type_traits>3334//-------------------------------------------------------------------------------------------------------------------------------------------------------------3536namespace NS37{38template <class _Class, class _Base = class Object>39class _NS_EXPORT Referencing : public _Base40{41public:42 _Class* retain();43 void release();4445 _Class* autorelease();4647 UInteger retainCount() const;48};4950template <class _Class, class _Base = class Object>51class Copying : public Referencing<_Class, _Base>52{53public:54 _Class* copy() const;55};5657template <class _Class, class _Base = class Object>58class SecureCoding : public Referencing<_Class, _Base>59{60};6162class Object : public Referencing<Object, objc_object>63{64public:65 UInteger hash() const;66 bool isEqual(const Object* pObject) const;6768 class String* description() const;69 class String* debugDescription() const;7071protected:72 friend class Referencing<Object, objc_object>;7374 template <class _Class>75 static _Class* alloc(const char* pClassName);76 template <class _Class>77 static _Class* alloc(const void* pClass);78 template <class _Class>79 _Class* init();8081 template <class _Dst>82 static _Dst bridgingCast(const void* pObj);83 static class MethodSignature* methodSignatureForSelector(const void* pObj, SEL selector);84 static bool respondsToSelector(const void* pObj, SEL selector);85 template <typename _Type>86 static constexpr bool doesRequireMsgSendStret();87 template <typename _Ret, typename... _Args>88 static _Ret sendMessage(const void* pObj, SEL selector, _Args... args);89 template <typename _Ret, typename... _Args>90 static _Ret sendMessageSafe(const void* pObj, SEL selector, _Args... args);9192private:93 Object() = delete;94 Object(const Object&) = delete;95 ~Object() = delete;9697 Object& operator=(const Object&) = delete;98};99}100101//-------------------------------------------------------------------------------------------------------------------------------------------------------------102103template <class _Class, class _Base /* = Object */>104_NS_INLINE _Class* NS::Referencing<_Class, _Base>::retain()105{106 return Object::sendMessage<_Class*>(this, _NS_PRIVATE_SEL(retain));107}108109//-------------------------------------------------------------------------------------------------------------------------------------------------------------110111template <class _Class, class _Base /* = Object */>112_NS_INLINE void NS::Referencing<_Class, _Base>::release()113{114 Object::sendMessage<void>(this, _NS_PRIVATE_SEL(release));115}116117//-------------------------------------------------------------------------------------------------------------------------------------------------------------118119template <class _Class, class _Base /* = Object */>120_NS_INLINE _Class* NS::Referencing<_Class, _Base>::autorelease()121{122 return Object::sendMessage<_Class*>(this, _NS_PRIVATE_SEL(autorelease));123}124125//-------------------------------------------------------------------------------------------------------------------------------------------------------------126127template <class _Class, class _Base /* = Object */>128_NS_INLINE NS::UInteger NS::Referencing<_Class, _Base>::retainCount() const129{130 return Object::sendMessage<UInteger>(this, _NS_PRIVATE_SEL(retainCount));131}132133//-------------------------------------------------------------------------------------------------------------------------------------------------------------134135template <class _Class, class _Base /* = Object */>136_NS_INLINE _Class* NS::Copying<_Class, _Base>::copy() const137{138 return Object::sendMessage<_Class*>(this, _NS_PRIVATE_SEL(copy));139}140141//-------------------------------------------------------------------------------------------------------------------------------------------------------------142143template <class _Dst>144_NS_INLINE _Dst NS::Object::bridgingCast(const void* pObj)145{146#ifdef __OBJC__147 return (__bridge _Dst)pObj;148#else149 return (_Dst)pObj;150#endif // __OBJC__151}152153//-------------------------------------------------------------------------------------------------------------------------------------------------------------154155template <typename _Type>156_NS_INLINE constexpr bool NS::Object::doesRequireMsgSendStret()157{158#if (defined(__i386__) || defined(__x86_64__))159 constexpr size_t kStructLimit = (sizeof(std::uintptr_t) << 1);160161 return sizeof(_Type) > kStructLimit;162#elif defined(__arm64__)163 return false;164#elif defined(__arm__)165 constexpr size_t kStructLimit = sizeof(std::uintptr_t);166167 return std::is_class_v<_Type> && (sizeof(_Type) > kStructLimit);168#else169#error "Unsupported architecture!"170#endif171}172173//-------------------------------------------------------------------------------------------------------------------------------------------------------------174175template <>176_NS_INLINE constexpr bool NS::Object::doesRequireMsgSendStret<void>()177{178 return false;179}180181//-------------------------------------------------------------------------------------------------------------------------------------------------------------182183template <typename _Ret, typename... _Args>184_NS_INLINE _Ret NS::Object::sendMessage(const void* pObj, SEL selector, _Args... args)185{186#if (defined(__i386__) || defined(__x86_64__))187 if constexpr (std::is_floating_point<_Ret>())188 {189 using SendMessageProcFpret = _Ret (*)(const void*, SEL, _Args...);190191 const SendMessageProcFpret pProc = reinterpret_cast<SendMessageProcFpret>(&objc_msgSend_fpret);192193 return (*pProc)(pObj, selector, args...);194 }195 else196#endif // ( defined( __i386__ ) || defined( __x86_64__ ) )197#if !defined(__arm64__)198 if constexpr (doesRequireMsgSendStret<_Ret>())199 {200 using SendMessageProcStret = void (*)(_Ret*, const void*, SEL, _Args...);201202 const SendMessageProcStret pProc = reinterpret_cast<SendMessageProcStret>(&objc_msgSend_stret);203 _Ret ret;204205 (*pProc)(&ret, pObj, selector, args...);206207 return ret;208 }209 else210#endif // !defined( __arm64__ )211 {212 using SendMessageProc = _Ret (*)(const void*, SEL, _Args...);213214 const SendMessageProc pProc = reinterpret_cast<SendMessageProc>(&objc_msgSend);215216 return (*pProc)(pObj, selector, args...);217 }218}219220//-------------------------------------------------------------------------------------------------------------------------------------------------------------221222_NS_INLINE NS::MethodSignature* NS::Object::methodSignatureForSelector(const void* pObj, SEL selector)223{224 return sendMessage<MethodSignature*>(pObj, _NS_PRIVATE_SEL(methodSignatureForSelector_), selector);225}226227//-------------------------------------------------------------------------------------------------------------------------------------------------------------228229_NS_INLINE bool NS::Object::respondsToSelector(const void* pObj, SEL selector)230{231 return sendMessage<bool>(pObj, _NS_PRIVATE_SEL(respondsToSelector_), selector);232}233234//-------------------------------------------------------------------------------------------------------------------------------------------------------------235236template <typename _Ret, typename... _Args>237_NS_INLINE _Ret NS::Object::sendMessageSafe(const void* pObj, SEL selector, _Args... args)238{239 if ((respondsToSelector(pObj, selector)) || (nullptr != methodSignatureForSelector(pObj, selector)))240 {241 return sendMessage<_Ret>(pObj, selector, args...);242 }243244 if constexpr (!std::is_void<_Ret>::value)245 {246 return _Ret(0);247 }248}249250//-------------------------------------------------------------------------------------------------------------------------------------------------------------251252template <class _Class>253_NS_INLINE _Class* NS::Object::alloc(const char* pClassName)254{255 return sendMessage<_Class*>(objc_lookUpClass(pClassName), _NS_PRIVATE_SEL(alloc));256}257258//-------------------------------------------------------------------------------------------------------------------------------------------------------------259260template <class _Class>261_NS_INLINE _Class* NS::Object::alloc(const void* pClass)262{263 return sendMessage<_Class*>(pClass, _NS_PRIVATE_SEL(alloc));264}265266//-------------------------------------------------------------------------------------------------------------------------------------------------------------267268template <class _Class>269_NS_INLINE _Class* NS::Object::init()270{271 return sendMessage<_Class*>(this, _NS_PRIVATE_SEL(init));272}273274//-------------------------------------------------------------------------------------------------------------------------------------------------------------275276_NS_INLINE NS::UInteger NS::Object::hash() const277{278 return sendMessage<UInteger>(this, _NS_PRIVATE_SEL(hash));279}280281//-------------------------------------------------------------------------------------------------------------------------------------------------------------282283_NS_INLINE bool NS::Object::isEqual(const Object* pObject) const284{285 return sendMessage<bool>(this, _NS_PRIVATE_SEL(isEqual_), pObject);286}287288//-------------------------------------------------------------------------------------------------------------------------------------------------------------289290_NS_INLINE NS::String* NS::Object::description() const291{292 return sendMessage<String*>(this, _NS_PRIVATE_SEL(description));293}294295//-------------------------------------------------------------------------------------------------------------------------------------------------------------296297_NS_INLINE NS::String* NS::Object::debugDescription() const298{299 return sendMessageSafe<String*>(this, _NS_PRIVATE_SEL(debugDescription));300}301302//-------------------------------------------------------------------------------------------------------------------------------------------------------------303