Artifact 3100a404979790862e2735e685284288dbfa3c317e25ba44eb3f1e1d8f2294bd:
- File
src/runtime/amiga-library.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: 17797) [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" #include <exec/libraries.h> #include <exec/nodes.h> #include <exec/resident.h> #include <proto/exec.h> #define CONCAT_VERSION2(major, minor) #major "." #minor #define CONCAT_VERSION(major, minor) CONCAT_VERSION2(major, minor) #define VERSION_STRING CONCAT_VERSION(OBJFWRT_LIB_MAJOR, OBJFWRT_LIB_MINOR) #if defined(OF_AMIGAOS_M68K) # define DATA_OFFSET 0x7FFE #elif defined(OF_MORPHOS) # define DATA_OFFSET 0x8000 #endif #ifdef OF_AMIGAOS_M68K # define OBJC_M68K_REG(reg) __asm__(#reg) #else # define OBJC_M68K_REG(reg) #endif /* This always needs to be the first thing in the file. */ int _start() { return -1; } struct ObjFWRTBase { struct Library library; void *segList; struct ObjFWRTBase *parent; char *dataSeg; bool initialized; }; #ifdef OF_AMIGAOS_M68K extern uintptr_t __CTOR_LIST__[]; extern const void *_EH_FRAME_BEGINS__; extern void *_EH_FRAME_OBJECTS__; #endif extern bool glue_objc_init(void); extern void glue___objc_exec_class(void); extern IMP glue_objc_msg_lookup(void); extern IMP glue_objc_msg_lookup_stret(void); extern IMP glue_objc_msg_lookup_super(void); extern IMP glue_objc_msg_lookup_super_stret(void); extern Class glue_objc_lookUpClass(void); extern Class glue_objc_getClass(void); extern Class glue_objc_getRequiredClass(void); extern Class glue_objc_lookup_class(void); extern Class glue_objc_get_class(void); extern void glue_objc_exception_throw(void); extern int glue_objc_sync_enter(void); extern int glue_objc_sync_exit(void); extern id glue_objc_getProperty(void); extern void glue_objc_setProperty(void); extern void glue_objc_getPropertyStruct(void); extern void glue_objc_setPropertyStruct(void); extern void glue_objc_enumerationMutation(void); extern int glue___gnu_objc_personality(void); extern id glue_objc_retain(void); extern id glue_objc_retainBlock(void); extern id glue_objc_retainAutorelease(void); extern void glue_objc_release(void); extern id glue_objc_autorelease(void); extern id glue_objc_autoreleaseReturnValue(void); extern id glue_objc_retainAutoreleaseReturnValue(void); extern id glue_objc_retainAutoreleasedReturnValue(void); extern id glue_objc_storeStrong(void); extern id glue_objc_storeWeak(void); extern id glue_objc_loadWeakRetained(void); extern id glue_objc_initWeak(void); extern void glue_objc_destroyWeak(void); extern id glue_objc_loadWeak(void); extern void glue_objc_copyWeak(void); extern void glue_objc_moveWeak(void); extern SEL glue_sel_registerName(void); extern const char *glue_sel_getName(void); extern bool glue_sel_isEqual(void); extern Class glue_objc_allocateClassPair(void); extern void glue_objc_registerClassPair(void); extern unsigned int glue_objc_getClassList(void); extern Class *glue_objc_copyClassList(void); extern bool glue_class_isMetaClass(void); extern const char *glue_class_getName(void); extern Class glue_class_getSuperclass(void); extern unsigned long glue_class_getInstanceSize(void); extern bool glue_class_respondsToSelector(void); extern bool glue_class_conformsToProtocol(void); extern IMP glue_class_getMethodImplementation(void); extern IMP glue_class_getMethodImplementation_stret(void); extern Method glue_class_getInstanceMethod(void); extern bool glue_class_addMethod(void); extern IMP glue_class_replaceMethod(void); extern Class glue_object_getClass(void); extern Class glue_object_setClass(void); extern const char *glue_object_getClassName(void); extern const char *glue_protocol_getName(void); extern bool glue_protocol_isEqual(void); extern bool glue_protocol_conformsToProtocol(void); extern objc_uncaught_exception_handler_t glue_objc_setUncaughtExceptionHandler(void); extern void glue_objc_setForwardHandler(void); extern void glue_objc_setEnumerationMutationHandler(void); extern id glue_objc_constructInstance(void); extern void glue_objc_exit(void); extern Ivar *glue_class_copyIvarList(void); extern const char *glue_ivar_getName(void); extern const char *glue_ivar_getTypeEncoding(void); extern ptrdiff_t glue_ivar_getOffset(void); extern Method *glue_class_copyMethodList(void); extern SEL glue_method_getName(void); extern const char *glue_method_getTypeEncoding(void); extern objc_property_t *glue_class_copyPropertyList(void); extern const char *glue_property_getName(void); extern char *glue_property_copyAttributeValue(void); extern void *glue_objc_destructInstance(void); extern void *glue_objc_autoreleasePoolPush(void); extern void glue_objc_autoreleasePoolPop(void); extern id glue__objc_rootAutorelease(void); extern struct objc_hashtable *glue_objc_hashtable_new(void); extern void glue_objc_hashtable_set(void); extern void *glue_objc_hashtable_get(void); extern void glue_objc_hashtable_delete(void); extern void glue_objc_hashtable_free(void); #ifdef OF_MORPHOS const ULONG __abox__ = 1; #endif struct ExecBase *SysBase; struct objc_libc libc; FILE *stdout; FILE *stderr; #if defined(OF_AMIGAOS_M68K) __asm__ ( ".text\n" ".globl ___restore_a4\n" ".align 1\n" "___restore_a4:\n" " movea.l 42(a6), a4\n" " rts" ); #elif defined(OF_MORPHOS) /* All __saveds functions in this file need to use the M68K ABI */ __asm__ ( ".section .text\n" ".align 2\n" "__restore_r13:\n" " lwz %r13, 56(%r2)\n" " lwz %r13, 44(%r13)\n" " blr\n" ); #endif static OF_INLINE char * getDataSeg(void) { char *dataSeg; #if defined(OF_AMIGAOS_M68K) __asm__ ( "move.l #___a4_init, %0" : "=r"(dataSeg) ); #elif defined(OF_MORPHOS) __asm__ ( "lis %0, __r13_init@ha\n\t" "la %0, __r13_init@l(%0)" : "=r"(dataSeg) ); #endif return dataSeg; } static OF_INLINE size_t getDataSize(void) { size_t dataSize; #if defined(OF_AMIGAOS_M68K) __asm__ ( "move.l #___data_size, %0\n\t" "add.l #___bss_size, %0" : "=r"(dataSize) ); #elif defined(OF_MORPHOS) __asm__ ( "lis %0, __sdata_size@ha\n\t" "la %0, __sdata_size@l(%0)\n\t" "lis %%r9, __sbss_size@ha\n\t" "la %%r9, __sbss_size@l(%%r9)\n\t" "add %0, %0, %%r9" : "=r"(dataSize) :: "r9" ); #endif return dataSize; } static OF_INLINE size_t * getDataDataRelocs(void) { size_t *dataDataRelocs; #if defined(OF_AMIGAOS_M68K) __asm__ ( "move.l #___datadata_relocs, %0" : "=r"(dataDataRelocs) ); #elif defined(OF_MORPHOS) __asm__ ( "lis %0, __datadata_relocs@ha\n\t" "la %0, __datadata_relocs@l(%0)\n\t" : "=r"(dataDataRelocs) ); #endif return dataDataRelocs; } static struct Library * lib_init(struct ObjFWRTBase *base OBJC_M68K_REG(d0), void *segList OBJC_M68K_REG(a0), struct ExecBase *sysBase OBJC_M68K_REG(a6)) { #if defined(OF_AMIGAOS_M68K) __asm__ __volatile__ ( "move.l a6, _SysBase" :: "a"(sysBase) ); #elif defined(OF_MORPHOS) __asm__ __volatile__ ( "lis %%r9, SysBase@ha\n\t" "stw %0, SysBase@l(%%r9)" :: "r"(sysBase) : "r9" ); #endif base->segList = segList; base->parent = NULL; base->dataSeg = getDataSeg(); return &base->library; } struct Library *__saveds lib_open(void) { OBJC_M68K_ARG(struct ObjFWRTBase *, base, a6) struct ObjFWRTBase *child; size_t dataSize, *dataDataRelocs; ptrdiff_t displacement; if (base->parent != NULL) return NULL; base->library.lib_OpenCnt++; base->library.lib_Flags &= ~LIBF_DELEXP; /* * We cannot use malloc here, as that depends on the libc passed from * the application. */ if ((child = AllocMem(base->library.lib_NegSize + base->library.lib_PosSize, MEMF_ANY)) == NULL) { base->library.lib_OpenCnt--; return NULL; } memcpy(child, (char *)base - base->library.lib_NegSize, base->library.lib_NegSize + base->library.lib_PosSize); child = (struct ObjFWRTBase *) ((char *)child + base->library.lib_NegSize); child->library.lib_OpenCnt = 1; child->parent = base; dataSize = getDataSize(); if ((child->dataSeg = AllocMem(dataSize, MEMF_ANY)) == NULL) { FreeMem((char *)child - child->library.lib_NegSize, child->library.lib_NegSize + child->library.lib_PosSize); base->library.lib_OpenCnt--; return NULL; } memcpy(child->dataSeg, base->dataSeg - DATA_OFFSET, dataSize); dataDataRelocs = getDataDataRelocs(); displacement = child->dataSeg - (base->dataSeg - DATA_OFFSET); for (size_t i = 1; i <= dataDataRelocs[0]; i++) *(long *)(child->dataSeg + dataDataRelocs[i]) += displacement; child->dataSeg += DATA_OFFSET; return &child->library; } static void * expunge(struct ObjFWRTBase *base) { void *segList; if (base->parent != NULL) { base->parent->library.lib_Flags |= LIBF_DELEXP; return 0; } if (base->library.lib_OpenCnt > 0) { base->library.lib_Flags |= LIBF_DELEXP; return 0; } segList = base->segList; Remove(&base->library.lib_Node); FreeMem((char *)base - base->library.lib_NegSize, base->library.lib_NegSize + base->library.lib_PosSize); return segList; } static void *__saveds lib_expunge(void) { OBJC_M68K_ARG(struct ObjFWRTBase *, base, a6) return expunge(base); } static void *__saveds lib_close(void) { OBJC_M68K_ARG(struct ObjFWRTBase *, base, a6) if (base->parent != NULL) { struct ObjFWRTBase *parent; #ifdef OF_AMIGAOS_M68K if (base->initialized) for (size_t i = 1; i <= (size_t)_EH_FRAME_BEGINS__; i++) libc.__deregister_frame_info( (&_EH_FRAME_BEGINS__)[i]); #endif parent = base->parent; FreeMem(base->dataSeg - DATA_OFFSET, getDataSize()); FreeMem((char *)base - base->library.lib_NegSize, base->library.lib_NegSize + base->library.lib_PosSize); base = parent; } if (--base->library.lib_OpenCnt == 0 && (base->library.lib_Flags & LIBF_DELEXP)) return expunge(base); return NULL; } static void * lib_null(void) { return NULL; } bool objc_init(unsigned int version, struct objc_libc *libc_, FILE *stdout_, FILE *stderr_) { #ifdef OF_AMIGAOS_M68K OBJC_M68K_ARG(struct ObjFWRTBase *, base, a6) #else register struct ObjFWRTBase *r12 __asm__("r12"); struct ObjFWRTBase *base = r12; #endif uintptr_t *iter, *iter0; if (version > 1) return false; memcpy(&libc, libc_, sizeof(libc)); stdout = stdout_; stderr = stderr_; #ifdef OF_AMIGAOS_M68K if ((size_t)_EH_FRAME_BEGINS__ != (size_t)_EH_FRAME_OBJECTS__) return false; for (size_t i = 1; i <= (size_t)_EH_FRAME_BEGINS__; i++) libc.__register_frame_info((&_EH_FRAME_BEGINS__)[i], (&_EH_FRAME_OBJECTS__)[i]); iter0 = &__CTOR_LIST__[1]; #elif defined(OF_MORPHOS) __asm__ ( "lis %0, ctors+4@ha\n\t" "la %0, ctors+4@l(%0)\n\t" : "=r"(iter0) ); #endif for (iter = iter0; *iter != 0; iter++); while (iter > iter0) { void (*ctor)(void) = (void (*)(void))*--iter; ctor(); } base->initialized = true; return true; } void * malloc(size_t size) { return libc.malloc(size); } void * calloc(size_t count, size_t size) { return libc.calloc(count, size); } void * realloc(void *ptr, size_t size) { return libc.realloc(ptr, size); } void free(void *ptr) { libc.free(ptr); } int fprintf(FILE *restrict stream, const char *restrict fmt, ...) { int ret; va_list args; va_start(args, fmt); ret = libc.vfprintf(stream, fmt, args); va_end(args); return ret; } int fflush(FILE *restrict stream) { return libc.fflush(stream); } void abort(void) { libc.abort(); OF_UNREACHABLE } #ifdef HAVE_SJLJ_EXCEPTIONS int _Unwind_SjLj_RaiseException(void *ex) { return libc._Unwind_SjLj_RaiseException(ex); } #else int _Unwind_RaiseException(void *ex) { return libc._Unwind_RaiseException(ex); } #endif void _Unwind_DeleteException(void *ex) { libc._Unwind_DeleteException(ex); } void * _Unwind_GetLanguageSpecificData(void *ctx) { return libc._Unwind_GetLanguageSpecificData(ctx); } uintptr_t _Unwind_GetRegionStart(void *ctx) { return libc._Unwind_GetRegionStart(ctx); } uintptr_t _Unwind_GetDataRelBase(void *ctx) { return libc._Unwind_GetDataRelBase(ctx); } uintptr_t _Unwind_GetTextRelBase(void *ctx) { return libc._Unwind_GetTextRelBase(ctx); } uintptr_t _Unwind_GetIP(void *ctx) { return libc._Unwind_GetIP(ctx); } uintptr_t _Unwind_GetGR(void *ctx, int gr) { return libc._Unwind_GetGR(ctx, gr); } void _Unwind_SetIP(void *ctx, uintptr_t ip) { libc._Unwind_SetIP(ctx, ip); } void _Unwind_SetGR(void *ctx, int gr, uintptr_t value) { libc._Unwind_SetGR(ctx, gr, value); } #ifdef HAVE_SJLJ_EXCEPTIONS void _Unwind_SjLj_Resume(void *ex) { libc._Unwind_SjLj_Resume(ex); } #else void _Unwind_Resume(void *ex) { libc._Unwind_Resume(ex); } #endif #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" static CONST_APTR functionTable[] = { #ifdef OF_MORPHOS (CONST_APTR)FUNCARRAY_BEGIN, (CONST_APTR)FUNCARRAY_32BIT_NATIVE, #endif (CONST_APTR)lib_open, (CONST_APTR)lib_close, (CONST_APTR)lib_expunge, (CONST_APTR)lib_null, #ifdef OF_MORPHOS (CONST_APTR)-1, (CONST_APTR)FUNCARRAY_32BIT_SYSTEMV, #endif (CONST_APTR)glue_objc_init, (CONST_APTR)glue___objc_exec_class, (CONST_APTR)glue_objc_msg_lookup, (CONST_APTR)glue_objc_msg_lookup_stret, (CONST_APTR)glue_objc_msg_lookup_super, (CONST_APTR)glue_objc_msg_lookup_super_stret, (CONST_APTR)glue_objc_lookUpClass, (CONST_APTR)glue_objc_getClass, (CONST_APTR)glue_objc_getRequiredClass, (CONST_APTR)glue_objc_lookup_class, (CONST_APTR)glue_objc_get_class, (CONST_APTR)glue_objc_exception_throw, (CONST_APTR)glue_objc_sync_enter, (CONST_APTR)glue_objc_sync_exit, (CONST_APTR)glue_objc_getProperty, (CONST_APTR)glue_objc_setProperty, (CONST_APTR)glue_objc_getPropertyStruct, (CONST_APTR)glue_objc_setPropertyStruct, (CONST_APTR)glue_objc_enumerationMutation, (CONST_APTR)glue___gnu_objc_personality, (CONST_APTR)glue_objc_retain, (CONST_APTR)glue_objc_retainBlock, (CONST_APTR)glue_objc_retainAutorelease, (CONST_APTR)glue_objc_release, (CONST_APTR)glue_objc_autorelease, (CONST_APTR)glue_objc_autoreleaseReturnValue, (CONST_APTR)glue_objc_retainAutoreleaseReturnValue, (CONST_APTR)glue_objc_retainAutoreleasedReturnValue, (CONST_APTR)glue_objc_storeStrong, (CONST_APTR)glue_objc_storeWeak, (CONST_APTR)glue_objc_loadWeakRetained, (CONST_APTR)glue_objc_initWeak, (CONST_APTR)glue_objc_destroyWeak, (CONST_APTR)glue_objc_loadWeak, (CONST_APTR)glue_objc_copyWeak, (CONST_APTR)glue_objc_moveWeak, (CONST_APTR)glue_sel_registerName, (CONST_APTR)glue_sel_getName, (CONST_APTR)glue_sel_isEqual, (CONST_APTR)glue_objc_allocateClassPair, (CONST_APTR)glue_objc_registerClassPair, (CONST_APTR)glue_objc_getClassList, (CONST_APTR)glue_objc_copyClassList, (CONST_APTR)glue_class_isMetaClass, (CONST_APTR)glue_class_getName, (CONST_APTR)glue_class_getSuperclass, (CONST_APTR)glue_class_getInstanceSize, (CONST_APTR)glue_class_respondsToSelector, (CONST_APTR)glue_class_conformsToProtocol, (CONST_APTR)glue_class_getMethodImplementation, (CONST_APTR)glue_class_getMethodImplementation_stret, (CONST_APTR)glue_class_getInstanceMethod, (CONST_APTR)glue_class_addMethod, (CONST_APTR)glue_class_replaceMethod, (CONST_APTR)glue_object_getClass, (CONST_APTR)glue_object_setClass, (CONST_APTR)glue_object_getClassName, (CONST_APTR)glue_protocol_getName, (CONST_APTR)glue_protocol_isEqual, (CONST_APTR)glue_protocol_conformsToProtocol, (CONST_APTR)glue_objc_setUncaughtExceptionHandler, (CONST_APTR)glue_objc_setForwardHandler, (CONST_APTR)glue_objc_setEnumerationMutationHandler, (CONST_APTR)glue_objc_constructInstance, (CONST_APTR)glue_objc_exit, (CONST_APTR)glue_class_copyIvarList, (CONST_APTR)glue_ivar_getName, (CONST_APTR)glue_ivar_getTypeEncoding, (CONST_APTR)glue_ivar_getOffset, (CONST_APTR)glue_class_copyMethodList, (CONST_APTR)glue_method_getName, (CONST_APTR)glue_method_getTypeEncoding, (CONST_APTR)glue_class_copyPropertyList, (CONST_APTR)glue_property_getName, (CONST_APTR)glue_property_copyAttributeValue, (CONST_APTR)glue_objc_destructInstance, (CONST_APTR)glue_objc_autoreleasePoolPush, (CONST_APTR)glue_objc_autoreleasePoolPop, (CONST_APTR)glue__objc_rootAutorelease, (CONST_APTR)glue_objc_hashtable_new, (CONST_APTR)glue_objc_hashtable_set, (CONST_APTR)glue_objc_hashtable_get, (CONST_APTR)glue_objc_hashtable_delete, (CONST_APTR)glue_objc_hashtable_free, (CONST_APTR)-1, #ifdef OF_MORPHOS (CONST_APTR)FUNCARRAY_END #endif }; #pragma GCC diagnostic pop static struct { ULONG dataSize; CONST_APTR *functionTable; ULONG *dataTable; struct Library *(*initFunc)( struct ObjFWRTBase *base OBJC_M68K_REG(d0), void *segList OBJC_M68K_REG(a0), struct ExecBase *execBase OBJC_M68K_REG(a6)); } init_table = { sizeof(struct ObjFWRTBase), functionTable, NULL, lib_init }; struct Resident resident = { .rt_MatchWord = RTC_MATCHWORD, .rt_MatchTag = &resident, .rt_EndSkip = &resident + 1, .rt_Flags = RTF_AUTOINIT #ifdef OF_MORPHOS | RTF_PPC | RTF_EXTENDED #endif , .rt_Version = OBJFWRT_LIB_MAJOR, .rt_Type = NT_LIBRARY, .rt_Pri = 0, .rt_Name = (char *)OBJFWRT_AMIGA_LIB, .rt_IdString = (char *)"ObjFWRT " VERSION_STRING " \xA9 2008-2019 Jonathan Schleifer", .rt_Init = &init_table, #ifdef OF_MORPHOS .rt_Revision = OBJFWRT_LIB_MINOR, .rt_Tags = NULL, #endif }; #ifdef OF_MORPHOS __asm__ ( ".section .ctors, \"aw\", @progbits\n" "ctors:\n" " .long -1\n" ".section .text" ); #endif