Index: src/runtime/Makefile ================================================================== --- src/runtime/Makefile +++ src/runtime/Makefile @@ -58,7 +58,7 @@ LD = ${OBJC} FRAMEWORK_LIBS = ${LIBS} # For 68000, GCC emits calls to helper functions that expect a4 to be set. # Remove this once the library is using -fbaserel. -AMIGA_LIB_CFLAGS += -mcpu=68020 -AMIGA_LIB_LDFLAGS += -mcpu=68020 -nostdlib -lnix +AMIGA_LIB_CFLAGS += -mcpu=68020 -fbaserel +AMIGA_LIB_LDFLAGS += -mcpu=68020 -fbaserel -nostdlib -lnix Index: src/runtime/ObjFW_RT.h ================================================================== --- src/runtime/ObjFW_RT.h +++ src/runtime/ObjFW_RT.h @@ -343,11 +343,12 @@ extern id _Nullable objc_storeStrong(id _Nullable *_Nonnull object, id _Nullable value); extern id _Nullable objc_storeWeak(id _Nullable *_Nonnull object, id _Nullable value); extern id _Nullable objc_loadWeakRetained(id _Nullable *_Nonnull object); -extern id objc_initWeak(id _Nullable *_Nonnull object, id _Nullable value); +extern _Nullable id objc_initWeak(id _Nullable *_Nonnull object, + id _Nullable value); extern void objc_destroyWeak(id _Nullable *_Nonnull object); extern id _Nullable objc_loadWeak(id _Nullable *_Nonnull object); extern void objc_copyWeak(id _Nullable *_Nonnull dest, id _Nullable *_Nonnull src); extern void objc_moveWeak(id _Nullable *_Nonnull dest, Index: src/runtime/ObjFW_RT.sfd ================================================================== --- src/runtime/ObjFW_RT.sfd +++ src/runtime/ObjFW_RT.sfd @@ -2,11 +2,11 @@ ==basetype struct Library * ==libname objfw_rt.library ==bias 30 ==public * Functions for the linklib -void objc_init(struct objc_libc *libc)(a0) +void objc_init(struct objc_libc *libc, FILE *stdout, FILE *stdin)(a0,a1,a2) * Used by the compiler - these need glue code void glue___objc_exec_class(void *_Nonnull module)(a0) IMP _Nonnull glue_objc_msg_lookup(id _Nullable obj, SEL _Nonnull sel)(a0,a1) IMP _Nonnull glue_objc_msg_lookup_stret(id _Nullable obj, SEL _Nonnull sel)(a0,a1) IMP _Nonnull glue_objc_msg_lookup_super(struct objc_super *_Nonnull super, SEL _Nonnull sel)(a0,a1) @@ -34,11 +34,11 @@ id _Nullable glue_objc_retainAutoreleaseReturnValue(id _Nullable object)(a0) id _Nullable glue_objc_retainAutoreleasedReturnValue(id _Nullable object)(a0) id _Nullable glue_objc_storeStrong(id _Nullable *_Nonnull object, id _Nullable value)(a0/a1) id _Nullable glue_objc_storeWeak(id _Nullable *_Nonnull object, id _Nullable value)(a0,a1) id _Nullable glue_objc_loadWeakRetained(id _Nullable *_Nonnull object)(a0) -id glue_objc_initWeak(id _Nullable *_Nonnull object, id _Nullable value)(a0,a1) +id _Nullable glue_objc_initWeak(id _Nullable *_Nonnull object, id _Nullable value)(a0,a1) void glue_objc_destroyWeak(id _Nullable *_Nonnull object)(a0) id _Nullable glue_objc_loadWeak(id _Nullable *_Nonnull object)(a0) void glue_objc_copyWeak(id _Nullable *_Nonnull dest, id _Nullable *_Nonnull src)(a0,a1) void glue_objc_moveWeak(id _Nullable *_Nonnull dest, id _Nullable *_Nonnull src)(a0,a1) * Functions declared in ObjFW_RT.h Index: src/runtime/amiga-glue.m ================================================================== --- src/runtime/amiga-glue.m +++ src/runtime/amiga-glue.m @@ -19,238 +19,230 @@ #import "ObjFW_RT.h" #import "private.h" #import "macros.h" -void +void __saveds glue___objc_exec_class(void *module OBJC_M68K_REG("a0")) { __objc_exec_class(module); } -IMP +IMP __saveds glue_objc_msg_lookup(id obj OBJC_M68K_REG("a0"), SEL sel OBJC_M68K_REG("a1")) { return objc_msg_lookup(obj, sel); } -IMP +IMP __saveds glue_objc_msg_lookup_stret(id obj OBJC_M68K_REG("a0"), SEL sel OBJC_M68K_REG("a1")) { return objc_msg_lookup_stret(obj, sel); } -IMP +IMP __saveds glue_objc_msg_lookup_super(struct objc_super *super OBJC_M68K_REG("a0"), SEL sel OBJC_M68K_REG("a1")) { return objc_msg_lookup_super(super, sel); } -IMP +IMP __saveds glue_objc_msg_lookup_super_stret(struct objc_super *super OBJC_M68K_REG("a0"), SEL sel OBJC_M68K_REG("a1")) { return objc_msg_lookup_super_stret(super, sel); } -Class +Class __saveds glue_objc_lookUpClass(const char *name OBJC_M68K_REG("a0")) { return objc_lookUpClass(name); } -Class +Class __saveds glue_objc_getClass(const char *name OBJC_M68K_REG("a0")) { return objc_getClass(name); } -Class +Class __saveds glue_objc_getRequiredClass(const char *name OBJC_M68K_REG("a0")) { return objc_getRequiredClass(name); } -Class +Class __saveds glue_objc_lookup_class(const char *name OBJC_M68K_REG("a0")) { return objc_lookup_class(name); } -Class +Class __saveds glue_objc_get_class(const char *name OBJC_M68K_REG("a0")) { return objc_get_class(name); } -void +void __saveds glue_objc_exception_throw(id object OBJC_M68K_REG("a0")) { objc_exception_throw(object); OF_UNREACHABLE } -int +int __saveds glue_objc_sync_enter(id object OBJC_M68K_REG("a0")) { return objc_sync_enter(object); } -int +int __saveds glue_objc_sync_exit(id object OBJC_M68K_REG("a0")) { return objc_sync_exit(object); } -id +id __saveds glue_objc_getProperty(id self OBJC_M68K_REG("a0"), SEL _cmd OBJC_M68K_REG("a1"), ptrdiff_t offset OBJC_M68K_REG("d0"), bool atomic OBJC_M68K_REG("d1")) { return objc_getProperty(self, _cmd, offset, atomic); } -void +void __saveds glue_objc_setProperty(id self OBJC_M68K_REG("a0"), SEL _cmd OBJC_M68K_REG("a1"), ptrdiff_t offset OBJC_M68K_REG("d0"), id value OBJC_M68K_REG("a2"), bool atomic OBJC_M68K_REG("d1"), signed char copy OBJC_M68K_REG("d2")) { objc_setProperty(self, _cmd, offset, value, atomic, copy); } -void +void __saveds glue_objc_getPropertyStruct(void *dest OBJC_M68K_REG("a0"), const void *src OBJC_M68K_REG("a1"), ptrdiff_t size OBJC_M68K_REG("d0"), bool atomic OBJC_M68K_REG("d1"), bool strong OBJC_M68K_REG("d2")) { objc_getPropertyStruct(dest, src, size, atomic, strong); } -void +void __saveds glue_objc_setPropertyStruct(void *dest OBJC_M68K_REG("a0"), const void *src OBJC_M68K_REG("a1"), ptrdiff_t size OBJC_M68K_REG("d0"), bool atomic OBJC_M68K_REG("d1"), bool strong OBJC_M68K_REG("d2")) { objc_setPropertyStruct(dest, src, size, atomic, strong); } -void +void __saveds glue_objc_enumerationMutation(id obj OBJC_M68K_REG("a0")) { objc_enumerationMutation(obj); } -int +int __saveds glue___gnu_objc_personality_v0(int version OBJC_M68K_REG("d0"), int actions OBJC_M68K_REG("d1"), uint64_t *ex_class OBJC_M68K_REG("d2"), void *ex OBJC_M68K_REG("a0"), void *ctx OBJC_M68K_REG("a1")) { return __gnu_objc_personality_v0(version, actions, *ex_class, ex, ctx); } -id -_Nullable glue_objc_retain(id _Nullable object OBJC_M68K_REG("a0")) +id __saveds +glue_objc_retain(id object OBJC_M68K_REG("a0")) { return objc_retain(object); } -id -_Nullable glue_objc_retainBlock(id _Nullable block OBJC_M68K_REG("a0")) +id __saveds +glue_objc_retainBlock(id block OBJC_M68K_REG("a0")) { return objc_retainBlock(block); } -id -_Nullable glue_objc_retainAutorelease(id _Nullable object OBJC_M68K_REG("a0")) +id __saveds +glue_objc_retainAutorelease(id object OBJC_M68K_REG("a0")) { return objc_retainAutorelease(object); } -void -glue_objc_release(id _Nullable object OBJC_M68K_REG("a0")) +void __saveds +glue_objc_release(id object OBJC_M68K_REG("a0")) { objc_release(object); } -id -_Nullable glue_objc_autorelease(id _Nullable object OBJC_M68K_REG("a0")) +id __saveds +glue_objc_autorelease(id object OBJC_M68K_REG("a0")) { return objc_autorelease(object); } -id -_Nullable glue_objc_autoreleaseReturnValue( - id _Nullable object OBJC_M68K_REG("a0")) +id __saveds +glue_objc_autoreleaseReturnValue(id object OBJC_M68K_REG("a0")) { return objc_autoreleaseReturnValue(object); } -id -_Nullable glue_objc_retainAutoreleaseReturnValue( - id _Nullable object OBJC_M68K_REG("a0")) +id __saveds +glue_objc_retainAutoreleaseReturnValue(id object OBJC_M68K_REG("a0")) { return objc_retainAutoreleaseReturnValue(object); } -id -_Nullable glue_objc_retainAutoreleasedReturnValue( - id _Nullable object OBJC_M68K_REG("a0")) +id __saveds +glue_objc_retainAutoreleasedReturnValue(id object OBJC_M68K_REG("a0")) { return objc_retainAutoreleasedReturnValue(object); } -id -_Nullable glue_objc_storeStrong( - id _Nullable *_Nonnull object OBJC_M68K_REG("a0"), - id _Nullable value OBJC_M68K_REG("a1")) +id __saveds +glue_objc_storeStrong(id *object OBJC_M68K_REG("a0"), + id value OBJC_M68K_REG("a1")) { return objc_storeStrong(object, value); } -id -_Nullable glue_objc_storeWeak(id _Nullable *_Nonnull object OBJC_M68K_REG("a0"), - id _Nullable value OBJC_M68K_REG("a1")) +id __saveds +glue_objc_storeWeak(id *object OBJC_M68K_REG("a0"), + id value OBJC_M68K_REG("a1")) { return objc_storeWeak(object, value); } -id -_Nullable glue_objc_loadWeakRetained( - id _Nullable *_Nonnull object OBJC_M68K_REG("a0")) +id __saveds +glue_objc_loadWeakRetained(id *object OBJC_M68K_REG("a0")) { return objc_loadWeakRetained(object); } -id -glue_objc_initWeak(id _Nullable *_Nonnull object OBJC_M68K_REG("a0"), - id _Nullable value OBJC_M68K_REG("a1")) +id __saveds +glue_objc_initWeak(id *object OBJC_M68K_REG("a0"), id value OBJC_M68K_REG("a1")) { return objc_initWeak(object, value); } -void -glue_objc_destroyWeak(id _Nullable *_Nonnull object OBJC_M68K_REG("a0")) +void __saveds +glue_objc_destroyWeak(id *object OBJC_M68K_REG("a0")) { objc_destroyWeak(object); } -id -_Nullable glue_objc_loadWeak(id _Nullable *_Nonnull object OBJC_M68K_REG("a0")) +id __saveds +glue_objc_loadWeak(id *object OBJC_M68K_REG("a0")) { return objc_loadWeak(object); } -void -glue_objc_copyWeak(id _Nullable *_Nonnull dest OBJC_M68K_REG("a0"), - id _Nullable *_Nonnull src OBJC_M68K_REG("a1")) +void __saveds +glue_objc_copyWeak(id *dest OBJC_M68K_REG("a0"), id *src OBJC_M68K_REG("a1")) { objc_copyWeak(dest, src); } -void -glue_objc_moveWeak(id _Nullable *_Nonnull dest OBJC_M68K_REG("a0"), - id _Nullable *_Nonnull src OBJC_M68K_REG("a1")) +void __saveds +glue_objc_moveWeak(id *dest OBJC_M68K_REG("a0"), id *src OBJC_M68K_REG("a1")) { objc_moveWeak(dest, src); } Index: src/runtime/amiga-library.m ================================================================== --- src/runtime/amiga-library.m +++ src/runtime/amiga-library.m @@ -43,32 +43,57 @@ struct ObjFWRTBase { struct Library library; void *seg_list; bool initialized; + void *data_seg; + struct objc_libc libc; }; extern uintptr_t __CTOR_LIST__[], __DTOR_LIST__[]; extern const void *_EH_FRAME_BEGINS__; extern void *_EH_FRAME_OBJECTS__; +extern void *__a4_init; struct ExecBase *SysBase; #ifdef OF_MORPHOS const ULONG __abox__ = 1; #endif -struct objc_libc *libc; FILE *stdout; FILE *stderr; + +__asm__ ( + ".text\n" + ".globl ___restore_a4\n" + "___restore_a4:\n" + " movea.l 40(a6), a4\n" + " rts" +); + +static OF_INLINE void * +get_data_seg(void) +{ + void *data_seg; + + __asm__ __volatile__ ( + "lea.l ___a4_init, %0" : "=a"(data_seg) + ); + + return data_seg; +} static struct Library * -lib_init(struct ExecBase *exec_base OBJC_M68K_REG("a6"), +lib_init(struct ExecBase *sys_base OBJC_M68K_REG("a6"), void *seg_list OBJC_M68K_REG("a0"), struct ObjFWRTBase *base OBJC_M68K_REG("d0")) { - SysBase = exec_base; + __asm__ __volatile__ ( + "move.l a6, _SysBase" :: "a"(sys_base) + ); base->seg_list = seg_list; + base->data_seg = get_data_seg(); return &base->library; } static struct Library * @@ -99,27 +124,28 @@ base->library.lib_NegSize + base->library.lib_PosSize); return seg_list; } -static void * +static void *__saveds OBJC_M68K_FUNC(lib_expunge, struct ObjFWRTBase *base OBJC_M68K_REG("a6")) { OBJC_M68K_ARG(struct ObjFWRTBase *, base, REG_A6) return expunge(base); } -static void * +static void *__saveds OBJC_M68K_FUNC(lib_close, struct ObjFWRTBase *base OBJC_M68K_REG("a6")) { OBJC_M68K_ARG(struct ObjFWRTBase *, base, REG_A6) if (base->initialized && (size_t)_EH_FRAME_BEGINS__ == (size_t)_EH_FRAME_OBJECTS__) for (size_t i = 1; i <= (size_t)_EH_FRAME_BEGINS__; i++) - libc->__deregister_frame_info((&_EH_FRAME_BEGINS__)[i]); + base->libc.__deregister_frame_info( + (&_EH_FRAME_BEGINS__)[i]); if (--base->library.lib_OpenCnt == 0 && (base->library.lib_Flags & LIBF_DELEXP)) return expunge(base); @@ -130,24 +156,26 @@ lib_null(void) { return 0; } -static void +static void __saveds objc_init(struct ObjFWRTBase *base OBJC_M68K_REG("a6"), - struct objc_libc *libc_ OBJC_M68K_REG("a0")) + struct objc_libc *libc OBJC_M68K_REG("a0"), + FILE *stdout_ OBJC_M68K_REG("a1"), FILE *stderr_ OBJC_M68K_REG("a2")) { uintptr_t *iter, *iter0; - libc = libc_; + memcpy(&base->libc, libc, sizeof(base->libc)); - stdout = libc->stdout_; - stderr = libc->stderr_; + stdout = stdout_; + stderr = stderr_; if ((size_t)_EH_FRAME_BEGINS__ == (size_t)_EH_FRAME_OBJECTS__) for (size_t i = 1; i <= (size_t)_EH_FRAME_BEGINS__; i++) - libc->__register_frame_info((&_EH_FRAME_BEGINS__)[i], + base->libc.__register_frame_info( + (&_EH_FRAME_BEGINS__)[i], (&_EH_FRAME_OBJECTS__)[i]); iter0 = &__CTOR_LIST__[1]; for (iter = iter0; *iter != 0; iter++); @@ -160,126 +188,163 @@ } void * malloc(size_t size) { - return libc->malloc(size); + register struct ObjFWRTBase *base OBJC_M68K_REG("a6"); + + return base->libc.malloc(size); } void * calloc(size_t count, size_t size) { - return libc->calloc(count, size); + register struct ObjFWRTBase *base OBJC_M68K_REG("a6"); + + return base->libc.calloc(count, size); } void * realloc(void *ptr, size_t size) { - return libc->realloc(ptr, size); + register struct ObjFWRTBase *base OBJC_M68K_REG("a6"); + + return base->libc.realloc(ptr, size); } void free(void *ptr) { - libc->free(ptr); + register struct ObjFWRTBase *base OBJC_M68K_REG("a6"); + + base->libc.free(ptr); } int fprintf(FILE *restrict stream, const char *restrict fmt, ...) { + register struct ObjFWRTBase *base OBJC_M68K_REG("a6"); int ret; va_list args; va_start(args, fmt); - ret = libc->vfprintf(stream, fmt, args); + ret = base->libc.vfprintf(stream, fmt, args); va_end(args); return ret; } int fputs(const char *restrict s, FILE *restrict stream) { - return libc->fputs(s, stream); + register struct ObjFWRTBase *base OBJC_M68K_REG("a6"); + + return base->libc.fputs(s, stream); } void exit(int status) { - libc->exit(status); + register struct ObjFWRTBase *base OBJC_M68K_REG("a6"); + + base->libc.exit(status); } void abort(void) { - libc->abort(); + register struct ObjFWRTBase *base OBJC_M68K_REG("a6"); + + base->libc.abort(); } int _Unwind_RaiseException(void *ex) { - return libc->_Unwind_RaiseException(ex); + register struct ObjFWRTBase *base OBJC_M68K_REG("a6"); + + return base->libc._Unwind_RaiseException(ex); } void _Unwind_DeleteException(void *ex) { - libc->_Unwind_DeleteException(ex); + register struct ObjFWRTBase *base OBJC_M68K_REG("a6"); + + base->libc._Unwind_DeleteException(ex); } void * _Unwind_GetLanguageSpecificData(void *ctx) { - return libc->_Unwind_GetLanguageSpecificData(ctx); + register struct ObjFWRTBase *base OBJC_M68K_REG("a6"); + + return base->libc._Unwind_GetLanguageSpecificData(ctx); } uintptr_t _Unwind_GetRegionStart(void *ctx) { - return libc->_Unwind_GetRegionStart(ctx); + register struct ObjFWRTBase *base OBJC_M68K_REG("a6"); + + return base->libc._Unwind_GetRegionStart(ctx); } uintptr_t _Unwind_GetDataRelBase(void *ctx) { - return libc->_Unwind_GetDataRelBase(ctx); + register struct ObjFWRTBase *base OBJC_M68K_REG("a6"); + + return base->libc._Unwind_GetDataRelBase(ctx); } uintptr_t _Unwind_GetTextRelBase(void *ctx) { - return libc->_Unwind_GetTextRelBase(ctx); + register struct ObjFWRTBase *base OBJC_M68K_REG("a6"); + + return base->libc._Unwind_GetTextRelBase(ctx); } uintptr_t _Unwind_GetIP(void *ctx) { - return libc->_Unwind_GetIP(ctx); + register struct ObjFWRTBase *base OBJC_M68K_REG("a6"); + + return base->libc._Unwind_GetIP(ctx); } uintptr_t _Unwind_GetGR(void *ctx, int gr) { - return libc->_Unwind_GetGR(ctx, gr); + register struct ObjFWRTBase *base OBJC_M68K_REG("a6"); + + return base->libc._Unwind_GetGR(ctx, gr); } void _Unwind_SetIP(void *ctx, uintptr_t ip) { - libc->_Unwind_SetIP(ctx, ip); + register struct ObjFWRTBase *base OBJC_M68K_REG("a6"); + + base->libc._Unwind_SetIP(ctx, ip); } void _Unwind_SetGR(void *ctx, int gr, uintptr_t value) { - libc->_Unwind_SetGR(ctx, gr, value); + register struct ObjFWRTBase *base OBJC_M68K_REG("a6"); + + base->libc._Unwind_SetGR(ctx, gr, value); } void _Unwind_Resume(void *ex) { - libc->_Unwind_Resume(ex); + register struct ObjFWRTBase *base OBJC_M68K_REG("a6"); + + base->libc._Unwind_Resume(ex); } #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" static CONST_APTR function_table[] = { Index: src/runtime/arc.m ================================================================== --- src/runtime/arc.m +++ src/runtime/arc.m @@ -268,11 +268,11 @@ if (!of_spinlock_unlock(&spinlock)) OBJC_ERROR("Failed to unlock spinlock!") #endif } -void +void __saveds objc_zero_weak_references(id value OBJC_M68K_REG("a0")) { struct weak_ref *ref; #ifdef OF_HAVE_THREADS Index: src/runtime/class.m ================================================================== --- src/runtime/class.m +++ src/runtime/class.m @@ -414,11 +414,11 @@ } process_load_queue(); } -Class +Class __saveds objc_allocateClassPair(Class superclass OBJC_M68K_REG("a0"), const char *name OBJC_M68K_REG("a1"), size_t extra_bytes OBJC_M68K_REG("d0")) { struct objc_class *cls, *metaclass; @@ -450,11 +450,11 @@ superclass->isa->instance_size : 0) + (long)extra_bytes; return cls; } -void +void __saveds objc_registerClassPair(Class cls OBJC_M68K_REG("a0")) { objc_global_mutex_lock(); register_class((struct objc_abi_class *)cls); @@ -527,11 +527,11 @@ objc_get_class(const char *name) { return objc_getRequiredClass(name); } -unsigned int +unsigned int __saveds objc_getClassList(Class *buf OBJC_M68K_REG("a0"), unsigned int count OBJC_M68K_REG("d0")) { unsigned int j; objc_global_mutex_lock(); @@ -568,11 +568,11 @@ objc_global_mutex_unlock(); return j; } -Class * +Class *__saveds objc_copyClassList(unsigned int *len OBJC_M68K_REG("a0")) { Class *ret; unsigned int count; @@ -592,47 +592,47 @@ objc_global_mutex_unlock(); return ret; } -bool +bool __saveds class_isMetaClass(Class cls OBJC_M68K_REG("a0")) { if (cls == Nil) return false; return (cls->info & OBJC_CLASS_INFO_METACLASS); } -const char * +const char *__saveds class_getName(Class cls OBJC_M68K_REG("a0")) { if (cls == Nil) return ""; return cls->name; } -Class +Class __saveds class_getSuperclass(Class cls OBJC_M68K_REG("a0")) { if (cls == Nil) return Nil; return cls->superclass; } -unsigned long +unsigned long __saveds class_getInstanceSize(Class cls OBJC_M68K_REG("a0")) { if (cls == Nil) return 0; return cls->instance_size; } -IMP +IMP __saveds class_getMethodImplementation(Class cls OBJC_M68K_REG("a0"), SEL sel OBJC_M68K_REG("a1")) { /* * We use a dummy object here so that the normal lookup is used, even @@ -653,11 +653,11 @@ dummy.isa = cls; return objc_msg_lookup((id)&dummy, sel); } -IMP +IMP __saveds class_getMethodImplementation_stret(Class cls OBJC_M68K_REG("a0"), SEL sel OBJC_M68K_REG("a1")) { /* * Same as above, but use objc_msg_lookup_stret instead, so that the @@ -721,11 +721,11 @@ cls->methodlist = ml; objc_update_dtable(cls); } -const char * +const char *__saveds class_getMethodTypeEncoding(Class cls OBJC_M68K_REG("a0"), SEL sel OBJC_M68K_REG("a1")) { struct objc_method *method; @@ -746,11 +746,11 @@ return class_getMethodTypeEncoding(cls->superclass, sel); return NULL; } -bool +bool __saveds class_addMethod(Class cls OBJC_M68K_REG("a0"), SEL sel OBJC_M68K_REG("a1"), IMP imp OBJC_M68K_REG("a2"), const char *types OBJC_M68K_REG("a3")) { bool ret; @@ -765,11 +765,11 @@ objc_global_mutex_unlock(); return ret; } -IMP +IMP __saveds class_replaceMethod(Class cls OBJC_M68K_REG("a0"), SEL sel OBJC_M68K_REG("a1"), IMP newimp OBJC_M68K_REG("a2"), const char *types OBJC_M68K_REG("a3")) { struct objc_method *method; IMP oldimp; @@ -788,11 +788,11 @@ objc_global_mutex_unlock(); return oldimp; } -Class +Class __saveds object_getClass(id obj_ OBJC_M68K_REG("a0")) { struct objc_object *obj; if (obj_ == nil) @@ -801,11 +801,11 @@ obj = (struct objc_object *)obj_; return obj->isa; } -Class +Class __saveds object_setClass(id obj_ OBJC_M68K_REG("a0"), Class cls OBJC_M68K_REG("a1")) { struct objc_object *obj; Class old; @@ -818,11 +818,11 @@ obj->isa = cls; return old; } -const char * +const char *__saveds object_getClassName(id obj OBJC_M68K_REG("a0")) { return class_getName(object_getClass(obj)); } Index: src/runtime/exception.m ================================================================== --- src/runtime/exception.m +++ src/runtime/exception.m @@ -758,11 +758,11 @@ uncaught_exception_handler(object); OBJC_ERROR("_Unwind_RaiseException() returned!") } -objc_uncaught_exception_handler +objc_uncaught_exception_handler __saveds objc_setUncaughtExceptionHandler( objc_uncaught_exception_handler handler OBJC_M68K_REG("a0")) { objc_uncaught_exception_handler old = uncaught_exception_handler; uncaught_exception_handler = handler; Index: src/runtime/linklib/linklib.m ================================================================== --- src/runtime/linklib/linklib.m +++ src/runtime/linklib/linklib.m @@ -76,14 +76,12 @@ ._Unwind_SetIP = _Unwind_SetIP, ._Unwind_SetGR = _Unwind_SetGR, ._Unwind_Resume = _Unwind_Resume, .__register_frame_info = __register_frame_info, .__deregister_frame_info = __deregister_frame_info, - .stdout_ = stdout, - .stderr_ = stderr }; - objc_init(&libc); + objc_init(&libc, stdout, stderr); initialized = true; } OF_DESTRUCTOR() @@ -168,12 +166,14 @@ * 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 OBJC_M68K_REG("a6") = ObjFWRTBase; uintptr_t throw = (((uintptr_t)ObjFWRTBase) - 0x60); ((void (*)(id OBJC_M68K_REG("a0")))throw)(object); + (void)a6; OF_UNREACHABLE } int @@ -226,16 +226,20 @@ * 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. */ - uintptr_t throw = (((uintptr_t)ObjFWRTBase) - 0x8A); - ((void (*)(id OBJC_M68K_REG("a0")))throw)(object); + register void *a6 OBJC_M68K_REG("a6") = ObjFWRTBase; + uintptr_t enumerationMutation = (((uintptr_t)ObjFWRTBase) - 0x8A); + ((void (*)(id OBJC_M68K_REG("a0")))enumerationMutation)(object); + (void)a6; + + OF_UNREACHABLE } int __gnu_objc_personality_v0(int version, int actions, uint64_t ex_class, void *ex, void *ctx) { return glue___gnu_objc_personality_v0(version, actions, &ex_class, ex, ctx); } Index: src/runtime/lookup.m ================================================================== --- src/runtime/lookup.m +++ src/runtime/lookup.m @@ -114,19 +114,19 @@ { return common_method_not_found(obj, sel, objc_msg_lookup_stret, forward_handler_stret); } -void +void __saveds objc_setForwardHandler(IMP forward OBJC_M68K_REG("a0"), IMP forward_stret OBJC_M68K_REG("a1")) { forward_handler = forward; forward_handler_stret = forward_stret; } -bool +bool __saveds class_respondsToSelector(Class cls OBJC_M68K_REG("a0"), SEL sel OBJC_M68K_REG("a1")) { if (cls == Nil) return false; Index: src/runtime/misc.m ================================================================== --- src/runtime/misc.m +++ src/runtime/misc.m @@ -23,11 +23,11 @@ #include "ObjFW_RT.h" #include "private.h" static objc_enumeration_mutation_handler enumeration_mutation_handler = NULL; -void +void __saveds objc_enumerationMutation(id obj) { if (enumeration_mutation_handler != NULL) enumeration_mutation_handler(obj); else Index: src/runtime/private.h ================================================================== --- src/runtime/private.h +++ src/runtime/private.h @@ -156,12 +156,10 @@ void (*_Unwind_SetIP)(void *_Nonnull, uintptr_t); void (*_Unwind_SetGR)(void *_Nonnull, int, uintptr_t); void (*_Unwind_Resume)(void *); void (*__register_frame_info)(const void *, void *); void (*__deregister_frame_info)(const void *); - FILE *stdout_; - FILE *stderr_; } *objc_libc; #endif #ifdef OBJC_COMPILING_AMIGA_LIBRARY # undef stdout @@ -233,20 +231,26 @@ extern id _Nullable glue_objc_storeWeak( id _Nullable *_Nonnull object OBJC_M68K_REG("a0"), id _Nullable value OBJC_M68K_REG("a1")); extern id _Nullable glue_objc_loadWeakRetained( id _Nullable *_Nonnull object OBJC_M68K_REG("a0")); -extern id glue_objc_initWeak(id _Nullable *_Nonnull object OBJC_M68K_REG("a0"), +extern id _Nullable glue_objc_initWeak( + id _Nullable *_Nonnull object OBJC_M68K_REG("a0"), id _Nullable value OBJC_M68K_REG("a1")); extern void glue_objc_destroyWeak( id _Nullable *_Nonnull object OBJC_M68K_REG("a0")); extern id _Nullable glue_objc_loadWeak( id _Nullable *_Nonnull object OBJC_M68K_REG("a0")); extern void glue_objc_copyWeak(id _Nullable *_Nonnull dest OBJC_M68K_REG("a0"), id _Nullable *_Nonnull src OBJC_M68K_REG("a1")); extern void glue_objc_moveWeak(id _Nullable *_Nonnull dest OBJC_M68K_REG("a0"), id _Nullable *_Nonnull src OBJC_M68K_REG("a1")); +#else +# ifdef __saveds +# undef __saveds +# endif +# define __saveds #endif extern void objc_register_all_categories(struct objc_abi_symtab *_Nonnull); extern struct objc_category *_Nullable *_Nullable objc_categories_for_class(Class _Nonnull); Index: src/runtime/protocol.m ================================================================== --- src/runtime/protocol.m +++ src/runtime/protocol.m @@ -23,24 +23,24 @@ #import "private.h" @implementation Protocol @end -const char * +const char *__saveds protocol_getName(Protocol *p OBJC_M68K_REG("a0")) { return p->name; } -bool +bool __saveds protocol_isEqual(Protocol *a OBJC_M68K_REG("a0"), Protocol *b OBJC_M68K_REG("a1")) { return (strcmp(protocol_getName(a), protocol_getName(b)) == 0); } -bool +bool __saveds protocol_conformsToProtocol(Protocol *a OBJC_M68K_REG("a0"), Protocol *b OBJC_M68K_REG("a1")) { if (protocol_isEqual(a, b)) return true; @@ -52,11 +52,11 @@ return true; return false; } -bool +bool __saveds class_conformsToProtocol(Class cls OBJC_M68K_REG("a0"), Protocol *p OBJC_M68K_REG("a1")) { struct objc_category **cats; Index: src/runtime/selector.m ================================================================== --- src/runtime/selector.m +++ src/runtime/selector.m @@ -38,11 +38,11 @@ static uint32_t selectors_cnt = 0; static struct objc_sparsearray *selector_names = NULL; static void **free_list = NULL; static size_t free_list_cnt = 0; -void +void __saveds objc_register_selector(struct objc_abi_selector *sel) { struct objc_selector *rsel; const char *name; @@ -113,11 +113,11 @@ for (sel = symtab->sel_refs; sel->name != NULL; sel++) objc_register_selector(sel); } -const char * +const char *__saveds sel_getName(SEL sel OBJC_M68K_REG("a0")) { const char *ret; objc_global_mutex_lock(); @@ -125,11 +125,11 @@ objc_global_mutex_unlock(); return ret; } -bool +bool __saveds sel_isEqual(SEL sel1 OBJC_M68K_REG("a0"), SEL sel2 OBJC_M68K_REG("a1")) { return (sel1->uid == sel2->uid); }