Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -44,10 +44,11 @@ AC_DEFINE(__have_longlong64, 1, [Required for AmigaOS to correctly define PRI?64]) AC_SUBST(NOIXEMUL, -noixemul) AC_SUBST(OBJFW_RT_AMIGA_LIB, objfw_rt.library) + AC_SUBST(OBJFW_RT_AMIGA_LINKLIB, libobjfw_rt.linklib.a) AC_SUBST(OBJFW_RT_INLINE_H, ObjFW_RT_inline.h) AC_SUBST(SFDC_TARGET, m68k-amigaos) ;; powerpc-*-amigaos*) enable_shared="no" @@ -59,10 +60,11 @@ LDFLAGS="$LDFLAGS -noixemul" enable_files="yes" # Required for reading ENV: AC_SUBST(NOIXEMUL, -noixemul) AC_SUBST(OBJFW_RT_AMIGA_LIB, objfw_rt.library) + AC_SUBST(OBJFW_RT_AMIGA_LINKLIB, libobjfw_rt.linklib.a) AC_SUBST(OBJFW_RT_INLINE_H, ObjFW_RT_inline.h) AC_SUBST(SFDC_TARGET, ppc-morphos) ]) enable_shared="no" Index: extra.mk.in ================================================================== --- extra.mk.in +++ extra.mk.in @@ -8,10 +8,11 @@ OBJFW_RT_SHARED_LIB = @OBJFW_RT_SHARED_LIB@ OBJFW_RT_STATIC_LIB = @OBJFW_RT_STATIC_LIB@ OBJFW_RT_FRAMEWORK = @OBJFW_RT_FRAMEWORK@ OBJFW_RT_AMIGA_LIB = @OBJFW_RT_AMIGA_LIB@ +OBJFW_RT_AMIGA_LINKLIB = @OBJFW_RT_AMIGA_LINKLIB@ OBJFW_RT_LIB_MAJOR = 0 OBJFW_RT_LIB_MINOR = 0 OBJFW_RT_LIB_MAJOR_MINOR = ${OBJFW_RT_LIB_MAJOR}.${OBJFW_RT_LIB_MINOR} OBJFW_BRIDGE_SHARED_LIB = @OBJFW_BRIDGE_SHARED_LIB@ Index: src/runtime/Makefile ================================================================== --- src/runtime/Makefile +++ src/runtime/Makefile @@ -1,8 +1,9 @@ include ../../extra.mk SUBDIRS = lookup-asm +SUBDIRS_AFTER = linklib CLEAN = ${OBJFW_RT_INLINE_H} SHARED_LIB = ${OBJFW_RT_SHARED_LIB} STATIC_LIB = ${OBJFW_RT_STATIC_LIB} FRAMEWORK = ${OBJFW_RT_FRAMEWORK} @@ -54,5 +55,10 @@ -DOBJFW_RT_LIB_MAJOR=${OBJFW_RT_LIB_MAJOR} \ -DOBJFW_RT_LIB_MINOR=${OBJFW_RT_LIB_MINOR} AMIGA_LIB_CFLAGS += -DOBJC_COMPILING_AMIGA_LIBRARY 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 Index: src/runtime/ObjFW_RT.h ================================================================== --- src/runtime/ObjFW_RT.h +++ src/runtime/ObjFW_RT.h @@ -219,12 +219,19 @@ }; #ifdef __cplusplus extern "C" { #endif -# ifdef OBJC_AMIGA_LIBRARY -# import "ObjFW_RT_inline.h" +# if defined(OBJC_AMIGA_LIBRARY) || defined(OBJC_COMPILING_AMIGA_LINKLIB) +# if defined(__amigaos__) && !defined(__MORPHOS__) && !defined(__amigaos4__) +# define INTUITION_CLASSES_H +# endif +# include +# include "ObjFW_RT_inline.h" +# if defined(__amigaos__) && !defined(__MORPHOS__) && !defined(__amigaos4__) +# undef INTUITION_CLASSES_H +# endif extern struct Library *ObjFWRTBase; # else extern SEL _Nonnull sel_registerName( const char *_Nonnull name OBJC_M68K_REG("a0")); extern const char *_Nonnull sel_getName(SEL _Nonnull sel OBJC_M68K_REG("a0")); @@ -304,10 +311,12 @@ extern IMP _Nonnull objc_msg_lookup_super_stret( struct objc_super *_Nonnull super, SEL _Nonnull sel); extern id _Nullable objc_lookUpClass(const char *_Nonnull name); extern id _Nullable objc_getClass(const char *_Nonnull name); extern id _Nonnull objc_getRequiredClass(const char *_Nonnull name); +extern Class _Nullable objc_lookup_class(const char *_Nonnull name); +extern Class _Nonnull objc_get_class(const char *_Nonnull name); extern void objc_exception_throw(id _Nullable object); extern int objc_sync_enter(id _Nullable object); extern int objc_sync_exit(id _Nullable object); extern id _Nullable objc_getProperty(id _Nonnull self, SEL _Nonnull _cmd, ptrdiff_t offset, bool atomic); Index: src/runtime/ObjFW_RT.sfd ================================================================== --- src/runtime/ObjFW_RT.sfd +++ src/runtime/ObjFW_RT.sfd @@ -4,26 +4,28 @@ ==bias 30 ==public * Functions for the linklib void objc_init(struct objc_libc *libc)(a0) * Used by the compiler - these need glue code -void glue___objc_exec_class(void *module)(a0) -IMP glue_objc_msg_lookup(id obj, SEL sel)(a0,a1) -IMP glue_objc_msg_lookup_stret(id obj, SEL sel)(a0,a1) -IMP glue_objc_msg_lookup_super(struct objc_super *super, SEL sel)(a0,a1) -IMP glue_objc_msg_lookup_super_stret(struct objc_super *super, SEL sel)(a0,a1) -id glue_objc_lookUpClass(const char *name)(a0) -id glue_objc_getClass(const char *name)(a0) -id glue_objc_getRequiredClass(const char *name)(a0) -void glue_objc_exception_throw(id object)(a0) -int glue_objc_sync_enter(id object)(a0) -int glue_objc_sync_exit(id object)(a0) -id glue_objc_getProperty(id self, SEL _cmd, ptrdiff_t offset, bool atomic)(a0,a1,d0,d1) -void glue_objc_setProperty(id self, SEL _cmd, ptrdiff_t offset, id value, bool atomic, signed char copy)(a0,a1,d0,a2,d1,d2) -void glue_objc_getPropertyStruct(void *dest, const void *src, ptrdiff_t size, bool atomic, bool strong)(a0,a1,d0,d1,d2) -void glue_objc_setPropertyStruct(void *dest, const void *src, ptrdiff_t size, bool atomic, bool strong)(a0,a1,d0,d1,d2) -void glue_objc_enumerationMutation(id obj)(a0) +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) +IMP _Nonnull glue_objc_msg_lookup_super_stret(struct objc_super *_Nonnull super, SEL _Nonnull sel)(a0,a1) +id _Nullable glue_objc_lookUpClass(const char *_Nonnull name)(a0) +id _Nullable glue_objc_getClass(const char *_Nonnull name)(a0) +id _Nonnull glue_objc_getRequiredClass(const char *_Nonnull name)(a0) +Class _Nullable glue_objc_lookup_class(const char *_Nonnull name)(a0) +Class _Nonnull glue_objc_get_class(const char *_Nonnull name)(a0) +void glue_objc_exception_throw(id _Nonnull object)(a0) +int glue_objc_sync_enter(id _Nullable object)(a0) +int glue_objc_sync_exit(id _Nullable object)(a0) +id glue_objc_getProperty(id _Nonnull self, SEL _Nonnull _cmd, ptrdiff_t offset, bool atomic)(a0,a1,d0,d1) +void glue_objc_setProperty(id _Nonnull self, SEL _Nonnull _cmd, ptrdiff_t offset, id value, bool atomic, signed char copy)(a0,a1,d0,a2,d1,d2) +void glue_objc_getPropertyStruct(void *_Nonnull dest, const void *_Nonnull src, ptrdiff_t size, bool atomic, bool strong)(a0,a1,d0,d1,d2) +void glue_objc_setPropertyStruct(void *_Nonnull dest, const void *_Nonnull src, ptrdiff_t size, bool atomic, bool strong)(a0,a1,d0,d1,d2) +void glue_objc_enumerationMutation(id _Nonnull obj)(a0) * Functions declared in ObjFW_RT.h SEL _Nonnull sel_registerName(const char *_Nonnull name)(a0) const char *_Nonnull sel_getName(SEL _Nonnull sel)(a0) bool sel_isEqual(SEL _Nonnull sel1, SEL _Nonnull sel2)(a0,a1) Class _Nonnull objc_allocateClassPair(Class _Nullable superclass, const char *_Nonnull name, size_t extra_bytes)(a0,a1,d0) Index: src/runtime/amiga-glue.m ================================================================== --- src/runtime/amiga-glue.m +++ src/runtime/amiga-glue.m @@ -22,11 +22,11 @@ #import "macros.h" void glue___objc_exec_class(void *module OBJC_M68K_REG("a0")) { - glue___objc_exec_class(module); + __objc_exec_class(module); } IMP glue_objc_msg_lookup(id obj OBJC_M68K_REG("a0"), SEL sel OBJC_M68K_REG("a1")) { @@ -69,10 +69,22 @@ id glue_objc_getRequiredClass(const char *name OBJC_M68K_REG("a0")) { return objc_getRequiredClass(name); } + +Class +glue_objc_lookup_class(const char *name OBJC_M68K_REG("a0")) +{ + return objc_lookup_class(name); +} + +Class +glue_objc_get_class(const char *name OBJC_M68K_REG("a0")) +{ + return objc_get_class(name); +} void glue_objc_exception_throw(id object OBJC_M68K_REG("a0")) { objc_exception_throw(object); Index: src/runtime/amiga-library.m ================================================================== --- src/runtime/amiga-library.m +++ src/runtime/amiga-library.m @@ -139,12 +139,12 @@ { uintptr_t *iter, *iter0; libc = libc_; - stdout = libc->stdout; - stderr = libc->stderr; + stdout = libc->stdout_; + stderr = libc->stderr_; iter0 = &__CTOR_LIST__[1]; for (iter = iter0; *iter != 0; iter++); while (iter > iter0) { @@ -228,11 +228,11 @@ ULONG *data_table; struct Library *(*init_func)( struct ExecBase *exec_base OBJC_M68K_REG("a6"), BPTR seg_list OBJC_M68K_REG("a0"), struct ObjFWRTBase *base OBJC_M68K_REG("d0")); -} initTable = { +} init_table = { sizeof(struct ObjFWRTBase), function_table, NULL, lib_init }; @@ -250,7 +250,7 @@ .rt_Type = NT_LIBRARY, .rt_Pri = 0, .rt_Name = (char *)"objfw_rt.library", .rt_IdString = (char *)"ObjFW_RT " VERSION_STRING " \xA9 2008-2018 Jonathan Schleifer", - .rt_Init = &initTable + .rt_Init = &init_table }; ADDED src/runtime/linklib/Makefile Index: src/runtime/linklib/Makefile ================================================================== --- src/runtime/linklib/Makefile +++ src/runtime/linklib/Makefile @@ -0,0 +1,9 @@ +include ../../../extra.mk + +STATIC_LIB = ${OBJFW_RT_AMIGA_LINKLIB} +SRCS = linklib.m + +include ../../../buildsys.mk + +CPPFLAGS += -DOBJC_COMPILING_AMIGA_LINKLIB -I.. -I../.. -I../../.. +LD = ${OBJC} ADDED src/runtime/linklib/linklib.m Index: src/runtime/linklib/linklib.m ================================================================== --- src/runtime/linklib/linklib.m +++ src/runtime/linklib/linklib.m @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018 + * Jonathan Schleifer + * + * 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 "ObjFW_RT.h" +#import "private.h" +#import "macros.h" + +#include +#include +#include + +struct Library *ObjFWRTBase; + +static void __attribute__((__constructor__)) +init(void) +{ + static bool initialized = false; + static struct objc_libc libc; + + if (initialized) + return; + + if ((ObjFWRTBase = OpenLibrary("objfw_rt.library", 0)) == NULL) { + fputs("Failed to open objfw_rt.library!\n", stderr); + abort(); + } + + libc = (struct objc_libc){ + .malloc = malloc, + .calloc = calloc, + .realloc = realloc, + .free = free, + .vfprintf = vfprintf, + .fputs = fputs, + .exit = exit, + .abort = abort, + .stdout_ = stdout, + .stderr_ = stderr + }; + objc_init(&libc); + + initialized = true; +} + +OF_DESTRUCTOR() +{ + CloseLibrary(ObjFWRTBase); +} + +void +__objc_exec_class(void *module) +{ + /* + * The compiler generates constructors that call into this, so it is + * possible that we are not set up yet when we get called. + */ + init(); + + glue___objc_exec_class(module); +} + +IMP +objc_msg_lookup(id obj, SEL sel) +{ + return glue_objc_msg_lookup(obj, sel); +} + +IMP +objc_msg_lookup_stret(id obj, SEL sel) +{ + return glue_objc_msg_lookup_stret(obj, sel); +} + +IMP +objc_msg_lookup_super(struct objc_super *super, SEL sel) +{ + return glue_objc_msg_lookup_super(super, sel); +} + +IMP +objc_msg_lookup_super_stret(struct objc_super *super, SEL sel) +{ + return glue_objc_msg_lookup_super_stret(super, sel); +} + +id +objc_lookUpClass(const char *name) +{ + return glue_objc_lookUpClass(name); +} + +id +objc_getClass(const char *name) +{ + return glue_objc_getClass(name); +} + +id +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) +{ + glue_objc_exception_throw(object); + + 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 obj) +{ + glue_objc_enumerationMutation(obj); +} Index: src/runtime/private.h ================================================================== --- src/runtime/private.h +++ src/runtime/private.h @@ -132,25 +132,29 @@ IMP _Nullable buckets[256]; #endif } *_Nonnull buckets[256]; }; -#ifdef OBJC_COMPILING_AMIGA_LIBRARY -# undef stdout -# undef stderr +#if defined(OBJC_COMPILING_AMIGA_LIBRARY) || \ + defined(OBJC_COMPILING_AMIGA_LINKLIB) extern struct objc_libc { void *(*malloc)(size_t); void *(*calloc)(size_t, size_t); void *(*realloc)(void *, size_t); void (*free)(void *); - int (*vfprintf)(FILE *, const char *, _BSD_VA_LIST_); + int (*vfprintf)(FILE *, const char *, va_list); int (*fputs)(const char *, FILE *); void (*exit)(int); void (*abort)(void); - FILE *stdout; - FILE *stderr; + FILE *stdout_; + FILE *stderr_; } *objc_libc; +#endif + +#ifdef OBJC_COMPILING_AMIGA_LIBRARY +# undef stdout +# undef stderr extern FILE *stdout, *stderr; extern void glue___objc_exec_class(void *_Nonnull module OBJC_M68K_REG("a0")); extern IMP _Nonnull glue_objc_msg_lookup(id _Nullable obj OBJC_M68K_REG("a0"), SEL _Nonnull sel OBJC_M68K_REG("a1")); @@ -165,10 +169,14 @@ extern id _Nullable glue_objc_lookUpClass( const char *_Nonnull name OBJC_M68K_REG("a0")); extern id _Nullable glue_objc_getClass( const char *_Nonnull name OBJC_M68K_REG("a0")); extern id _Nonnull glue_objc_getRequiredClass( + const char *_Nonnull name OBJC_M68K_REG("a0")); +extern Class _Nullable glue_objc_lookup_class( + const char *_Nonnull name OBJC_M68K_REG("a0")); +extern Class _Nonnull glue_objc_get_class( const char *_Nonnull name OBJC_M68K_REG("a0")); extern void glue_objc_exception_throw(id _Nullable object OBJC_M68K_REG("a0")); extern int glue_objc_sync_enter(id _Nullable object OBJC_M68K_REG("a0")); extern int glue_objc_sync_exit(id _Nullable object OBJC_M68K_REG("a0")); extern id _Nullable glue_objc_getProperty(id _Nonnull self OBJC_M68K_REG("a0"),