Artifact 570378ad75920f7d6203234be029ee45a276e40c69a7117d9ac7fc8dfc8cbb7f:
- File
src/runtime/linklib/linklib.m
— part of check-in
[49aee5736e]
at
2020-01-25 20:04:54
on branch trunk
— tlskey.m: Use hashtable from runtime on AmigaOS
tlskey.m used OFMapTable only on AmigaOS. This became a problem when
autorelease pools were moved into the runtime, as autorelease pools use
TLS. The build then broke, as there suddenly was a dependency from the
runtime on ObjFW.This now uses the hashtable from the runtime and also no longer uses
OFList, thus fixing the build. As we always use the runtime on AmigaOS
anyway, this is fine. (user: js, size: 14186) [annotate] [blame] [check-ins using] [more...]
/* * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, * 2018, 2019, 2020 * Jonathan Schleifer <js@nil.im> * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in * the packaging of this file. * * Alternatively, it may be distributed under the terms of the GNU General * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #include "config.h" #import "ObjFWRT.h" #import "private.h" #import "macros.h" #include <proto/exec.h> struct ObjFWRTBase; #import "inline.h" #include <stdio.h> #include <stdlib.h> #if defined(OF_AMIGAOS_M68K) # include <stabs.h> # define SYM(name) __asm__("_" name) #elif defined(OF_MORPHOS) # include <constructor.h> # define SYM(name) __asm__(name) #endif #ifdef HAVE_SJLJ_EXCEPTIONS extern int _Unwind_SjLj_RaiseException(void *); #else extern int _Unwind_RaiseException(void *); #endif extern void _Unwind_DeleteException(void *); extern void *_Unwind_GetLanguageSpecificData(void *); extern uintptr_t _Unwind_GetRegionStart(void *); extern uintptr_t _Unwind_GetDataRelBase(void *); extern uintptr_t _Unwind_GetTextRelBase(void *); extern uintptr_t _Unwind_GetIP(void *); extern uintptr_t _Unwind_GetGR(void *, int); extern void _Unwind_SetIP(void *, uintptr_t); extern void _Unwind_SetGR(void *, int, uintptr_t); #ifdef HAVE_SJLJ_EXCEPTIONS extern void _Unwind_SjLj_Resume(void *); #else extern void _Unwind_Resume(void *); #endif extern void __register_frame_info(const void *, void *); extern void *__deregister_frame_info(const void *); struct Library *ObjFWRTBase; void *__objc_class_name_Protocol; static void ctor(void) { static bool initialized = false; struct objc_libc libc = { .malloc = malloc, .calloc = calloc, .realloc = realloc, .free = free, .vfprintf = vfprintf, .fflush = fflush, .abort = abort, #ifdef HAVE_SJLJ_EXCEPTIONS ._Unwind_SjLj_RaiseException = _Unwind_SjLj_RaiseException, #else ._Unwind_RaiseException = _Unwind_RaiseException, #endif ._Unwind_DeleteException = _Unwind_DeleteException, ._Unwind_GetLanguageSpecificData = _Unwind_GetLanguageSpecificData, ._Unwind_GetRegionStart = _Unwind_GetRegionStart, ._Unwind_GetDataRelBase = _Unwind_GetDataRelBase, ._Unwind_GetTextRelBase = _Unwind_GetTextRelBase, ._Unwind_GetIP = _Unwind_GetIP, ._Unwind_GetGR = _Unwind_GetGR, ._Unwind_SetIP = _Unwind_SetIP, ._Unwind_SetGR = _Unwind_SetGR, #ifdef HAVE_SJLJ_EXCEPTIONS ._Unwind_SjLj_Resume = _Unwind_SjLj_Resume, #else ._Unwind_Resume = _Unwind_Resume, #endif .__register_frame_info = __register_frame_info, .__deregister_frame_info = __deregister_frame_info, }; if (initialized) return; if ((ObjFWRTBase = OpenLibrary(OBJFWRT_AMIGA_LIB, OBJFWRT_LIB_MINOR)) == NULL) { fputs("Failed to open " OBJFWRT_AMIGA_LIB "!\n", stderr); abort(); } if (!glue_objc_init(1, &libc, stdout, stderr)) { fputs("Failed to initialize " OBJFWRT_AMIGA_LIB "!\n", stderr); abort(); } initialized = true; } static void __attribute__((__unused__)) dtor(void) { CloseLibrary(ObjFWRTBase); } #if defined(OF_AMIGAOS_M68K) ADD2INIT(ctor, -2); ADD2EXIT(dtor, -2); #elif defined(OF_MORPHOS) CONSTRUCTOR_P(ObjFWRT, 4000) { ctor(); return 0; } DESTRUCTOR_P(ObjFWRT, 4000) { dtor(); } #endif void __objc_exec_class(struct objc_module *module) { /* * The compiler generates constructors that call into this, so it is * possible that we are not set up yet when we get called. */ ctor(); glue___objc_exec_class(module); } IMP objc_msg_lookup(id object, SEL selector) { return glue_objc_msg_lookup(object, selector); } IMP objc_msg_lookup_stret(id object, SEL selector) { return glue_objc_msg_lookup_stret(object, selector); } IMP objc_msg_lookup_super(struct objc_super *super, SEL selector) { return glue_objc_msg_lookup_super(super, selector); } IMP objc_msg_lookup_super_stret(struct objc_super *super, SEL selector) { return glue_objc_msg_lookup_super_stret(super, selector); } Class objc_lookUpClass(const char *name) { return glue_objc_lookUpClass(name); } Class objc_getClass(const char *name) { return glue_objc_getClass(name); } Class objc_getRequiredClass(const char *name) { return glue_objc_getRequiredClass(name); } Class objc_lookup_class(const char *name) { return glue_objc_lookup_class(name); } Class objc_get_class(const char *name) { return glue_objc_get_class(name); } void objc_exception_throw(id object) { #ifdef OF_AMIGAOS_M68K /* * This does not use the glue code to hack around a compiler bug. * * When using the generated inline stubs, the compiler does not emit * any frame information, making the unwind fail. As unwind always * starts from objc_exception_throw(), this means exceptions would * never work. If, however, we're using a function pointer instead of * the inline stub, the compiler does generate a frame and everything * works fine. */ register void *a6 __asm__("a6") = ObjFWRTBase; uintptr_t throw = (((uintptr_t)ObjFWRTBase) - 0x60); ((void (*)(id __asm__("a0")))throw)(object); (void)a6; #else glue_objc_exception_throw(object); #endif OF_UNREACHABLE } int objc_sync_enter(id object) { return glue_objc_sync_enter(object); } int objc_sync_exit(id object) { return glue_objc_sync_exit(object); } id objc_getProperty(id self, SEL _cmd, ptrdiff_t offset, bool atomic) { return glue_objc_getProperty(self, _cmd, offset, atomic); } void objc_setProperty(id self, SEL _cmd, ptrdiff_t offset, id value, bool atomic, signed char copy) { glue_objc_setProperty(self, _cmd, offset, value, atomic, copy); } void objc_getPropertyStruct(void *dest, const void *src, ptrdiff_t size, bool atomic, bool strong) { glue_objc_getPropertyStruct(dest, src, size, atomic, strong); } void objc_setPropertyStruct(void *dest, const void *src, ptrdiff_t size, bool atomic, bool strong) { glue_objc_setPropertyStruct(dest, src, size, atomic, strong); } void objc_enumerationMutation(id object) { #ifdef OF_AMIGAOS_M68K /* * This does not use the glue code to hack around a compiler bug. * * When using the generated inline stubs, the compiler does not emit * any frame information, making the unwind fail. As a result * objc_enumerationMutation() might throw an exception that could never * be caught. If, however, we're using a function pointer instead of * the inline stub, the compiler does generate a frame and everything * works fine. */ register void *a6 __asm__("a6") = ObjFWRTBase; uintptr_t enumerationMutation = (((uintptr_t)ObjFWRTBase) - 0x8A); ((void (*)(id __asm__("a0")))enumerationMutation)(object); (void)a6; #else glue_objc_enumerationMutation(object); #endif OF_UNREACHABLE } #ifdef HAVE_SJLJ_EXCEPTIONS int __gnu_objc_personality_sj0(int version, int actions, uint64_t exClass, void *ex, void *ctx) { # ifdef OF_AMIGAOS_M68K return glue___gnu_objc_personality(version, actions, &exClass, ex, ctx); # else return glue___gnu_objc_personality(version, actions, exClass, ex, ctx); # endif } #else int __gnu_objc_personality_v0(int version, int actions, uint64_t exClass, void *ex, void *ctx) { # ifdef OF_AMIGAOS_M68K return glue___gnu_objc_personality(version, actions, &exClass, ex, ctx); # else return glue___gnu_objc_personality(version, actions, exClass, ex, ctx); # endif } #endif id objc_retain(id object) { return glue_objc_retain(object); } id objc_retainBlock(id block) { return glue_objc_retainBlock(block); } id objc_retainAutorelease(id object) { return glue_objc_retainAutorelease(object); } void objc_release(id object) { glue_objc_release(object); } id objc_autorelease(id object) { return glue_objc_autorelease(object); } id objc_autoreleaseReturnValue(id object) { return glue_objc_autoreleaseReturnValue(object); } id objc_retainAutoreleaseReturnValue(id object) { return glue_objc_retainAutoreleaseReturnValue(object); } id objc_retainAutoreleasedReturnValue(id object) { return glue_objc_retainAutoreleasedReturnValue(object); } id objc_storeStrong(id *object, id value) { return glue_objc_storeStrong(object, value); } id objc_storeWeak(id *object, id value) { return glue_objc_storeWeak(object, value); } id objc_loadWeakRetained(id *object) { return glue_objc_loadWeakRetained(object); } id objc_initWeak(id *object, id value) { return glue_objc_initWeak(object, value); } void objc_destroyWeak(id *object) { glue_objc_destroyWeak(object); } id objc_loadWeak(id *object) { return glue_objc_loadWeak(object); } void objc_copyWeak(id *dest, id *src) { glue_objc_copyWeak(dest, src); } void objc_moveWeak(id *dest, id *src) { glue_objc_moveWeak(dest, src); } SEL sel_registerName(const char *name) { return glue_sel_registerName(name); } const char * sel_getName(SEL selector) { return glue_sel_getName(selector); } bool sel_isEqual(SEL selector1, SEL selector2) { return glue_sel_isEqual(selector1, selector2); } Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes) { return glue_objc_allocateClassPair(superclass, name, extraBytes); } void objc_registerClassPair(Class class) { glue_objc_registerClassPair(class); } unsigned int objc_getClassList(Class *buffer, unsigned int count) { return glue_objc_getClassList(buffer, count); } Class * objc_copyClassList(unsigned int *length) { return glue_objc_copyClassList(length); } bool class_isMetaClass(Class class) { return glue_class_isMetaClass(class); } const char * class_getName(Class class) { return glue_class_getName(class); } Class class_getSuperclass(Class class) { return glue_class_getSuperclass(class); } unsigned long class_getInstanceSize(Class class) { return glue_class_getInstanceSize(class); } bool class_respondsToSelector(Class class, SEL selector) { return glue_class_respondsToSelector(class, selector); } bool class_conformsToProtocol(Class class, Protocol *protocol) { return glue_class_conformsToProtocol(class, protocol); } IMP class_getMethodImplementation(Class class, SEL selector) { return glue_class_getMethodImplementation(class, selector); } IMP class_getMethodImplementation_stret(Class class, SEL selector) { return glue_class_getMethodImplementation_stret(class, selector); } Method class_getInstanceMethod(Class class, SEL selector) { return glue_class_getInstanceMethod(class, selector); } bool class_addMethod(Class class, SEL selector, IMP implementation, const char *typeEncoding) { return glue_class_addMethod(class, selector, implementation, typeEncoding); } IMP class_replaceMethod(Class class, SEL selector, IMP implementation, const char *typeEncoding) { return glue_class_replaceMethod(class, selector, implementation, typeEncoding); } Class object_getClass(id object) { return glue_object_getClass(object); } Class object_setClass(id object, Class class) { return glue_object_setClass(object, class); } const char * object_getClassName(id object) { return glue_object_getClassName(object); } const char * protocol_getName(Protocol *protocol) { return glue_protocol_getName(protocol); } bool protocol_isEqual(Protocol *protocol1, Protocol *protocol2) { return glue_protocol_isEqual(protocol1, protocol2); } bool protocol_conformsToProtocol(Protocol *protocol1, Protocol *protocol2) { return glue_protocol_conformsToProtocol(protocol1, protocol2); } objc_uncaught_exception_handler_t objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler_t handler) { return glue_objc_setUncaughtExceptionHandler(handler); } void objc_setForwardHandler(IMP forward, IMP stretForward) { glue_objc_setForwardHandler(forward, stretForward); } void objc_setEnumerationMutationHandler(objc_enumeration_mutation_handler_t handler) { glue_objc_setEnumerationMutationHandler(handler); } id objc_constructInstance(Class class, void *_Nullable bytes) { return glue_objc_constructInstance(class, bytes); } void objc_exit(void) { glue_objc_exit(); } Ivar * class_copyIvarList(Class class, unsigned int *outCount) { return glue_class_copyIvarList(class, outCount); } const char * ivar_getName(Ivar ivar) { return glue_ivar_getName(ivar); } const char * ivar_getTypeEncoding(Ivar ivar) { return glue_ivar_getTypeEncoding(ivar); } ptrdiff_t ivar_getOffset(Ivar ivar) { return glue_ivar_getOffset(ivar); } Method * class_copyMethodList(Class class, unsigned int *outCount) { return glue_class_copyMethodList(class, outCount); } SEL method_getName(Method method) { return glue_method_getName(method); } const char * method_getTypeEncoding(Method method) { return glue_method_getTypeEncoding(method); } objc_property_t * class_copyPropertyList(Class class, unsigned int *outCount) { return glue_class_copyPropertyList(class, outCount); } const char * property_getName(objc_property_t property) { return glue_property_getName(property); } char * property_copyAttributeValue(objc_property_t property, const char *name) { return glue_property_copyAttributeValue(property, name); } void * objc_destructInstance(id object) { return glue_objc_destructInstance(object); } void * objc_autoreleasePoolPush(void) { return glue_objc_autoreleasePoolPush(); } void objc_autoreleasePoolPop(void *pool) { glue_objc_autoreleasePoolPop(pool); } id _objc_rootAutorelease(id object) { return glue__objc_rootAutorelease(object); } struct objc_hashtable * objc_hashtable_new(objc_hashtable_hash_func hash, objc_hashtable_equal_func equal, uint32_t size) { return glue_objc_hashtable_new(hash, equal, size); } void objc_hashtable_set(struct objc_hashtable *table, const void *key, const void *object) { glue_objc_hashtable_set(table, key, object); } void * objc_hashtable_get(struct objc_hashtable *table, const void *key) { return glue_objc_hashtable_get(table, key); } void objc_hashtable_delete(struct objc_hashtable *table, const void *key) { glue_objc_hashtable_delete(table, key); } void objc_hashtable_free(struct objc_hashtable *table) { glue_objc_hashtable_free(table); }