Index: src/runtime/Makefile ================================================================== --- src/runtime/Makefile +++ src/runtime/Makefile @@ -30,15 +30,14 @@ INCLUDES = ObjFW_RT.h includesubdir = ObjFW_RT OBJS_EXTRA = ${LOOKUP_ASM_LOOKUP_ASM_A} LIB_OBJS_EXTRA = ${LOOKUP_ASM_LOOKUP_ASM_LIB_A} -AMIGA_LIB_OBJS_EXTRA = amiga-library.o ${LOOKUP_ASM_LOOKUP_ASM_A} +AMIGA_LIB_OBJS_EXTRA = amiga-library.amigalib.o ${LOOKUP_ASM_LOOKUP_ASM_A} include ../../buildsys.mk -${AMIGA_LIB}: ppcinline.h ppcinline.h: ObjFW_RT.fd protos.h cvinclude.pl \ --root ObjFW_RT \ --fd ObjFW_RT.fd \ --clib protos.h \ @@ -46,7 +45,8 @@ CPPFLAGS += -I. -I.. -I../.. \ -DOF_COMPILING_OBJFW_RT \ -DOBJFW_RT_LIB_MAJOR=${OBJFW_RT_LIB_MAJOR} \ -DOBJFW_RT_LIB_MINOR=${OBJFW_RT_LIB_MINOR} +AMIGALIB_CFLAGS += -DOF_AMIGA_LIBRARY LD = ${OBJC} FRAMEWORK_LIBS = ${LIBS} Index: src/runtime/ObjFW_RT.h ================================================================== --- src/runtime/ObjFW_RT.h +++ src/runtime/ObjFW_RT.h @@ -55,10 +55,23 @@ #define Nil (Class _Null_unspecified)0 #define nil (id _Null_unspecified)0 #define YES true #define NO false + +#if defined(__amigaos__) && !defined(__MORPHOS__) && !defined(__amigaos4__) +# define OBJC_M68K_REG(reg) __asm__(reg) +#else +# define OBJC_M68K_REG(reg) +#endif +#ifdef __MORPHOS__ +# define OBJC_M68K_FUNC(name, args) name(void) +# define OBJC_M68K_ARG(type, name, reg) type name = (type)reg; +#else +# define OBJC_M68K_FUNC(name, ...) name(__VA_ARGS__) +# define OBJC_M68K_ARG(type, name, reg) +#endif typedef struct objc_class *Class; typedef struct objc_object *id; typedef const struct objc_selector *SEL; #if !defined(__wii__) && !defined(__amigaos__) @@ -203,14 +216,13 @@ struct objc_protocol_list *_Nullable next; long count; Protocol *__unsafe_unretained _Nonnull list[1]; }; -#if 1 /* !defined(__MORPHOS__) || defined(OF_COMPILING_OBJFW_RT) */ -# ifdef __cplusplus +#ifdef __cplusplus extern "C" { -# endif +#endif extern SEL _Nonnull sel_registerName(const char *_Nonnull); extern const char *_Nonnull sel_getName(SEL _Nonnull); extern bool sel_isEqual(SEL _Nonnull, SEL _Nonnull); extern Class _Nonnull objc_allocateClassPair(Class _Nullable, const char *_Nonnull, size_t); @@ -245,32 +257,18 @@ objc_uncaught_exception_handler _Nullable); extern void objc_setForwardHandler(IMP _Nullable, IMP _Nullable); extern void objc_setEnumerationMutationHandler( objc_enumeration_mutation_handler _Nullable); extern void objc_zero_weak_references(id _Nonnull); -# ifdef __cplusplus -} -# endif -#else -# include -# ifdef __cplusplus -extern "C" { -# endif -extern struct Library *ObjFWRTBase; -# ifdef __cplusplus -} -# endif -# include "ppcinline.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif +# ifdef OF_AMIGAOS +extern struct Library *ObjFWRTBase; +# endif + /* * Used by the compiler, but can also be called manually. * - * They need to be in the glue code for the MorphOS library. + * They need to be in the glue code for the Amiga library. * * These declarations are also required to prevent Clang's implicit * declarations which include __declspec(dllimport) on Windows. */ struct objc_abi_module; Index: src/runtime/amiga-library.m ================================================================== --- src/runtime/amiga-library.m +++ src/runtime/amiga-library.m @@ -16,45 +16,186 @@ */ #include "config.h" #import "ObjFW_RT.h" -#import "macros.h" +#import "private.h" +#import "platform.h" + +#ifdef OF_AMIGAOS3 +# define INTUITION_CLASSES_H +#endif -#include -#include -#include +#include #include #include -#include #include + +#define CONCAT_VERSION2(major, minor) #major "." #minor +#define CONCAT_VERSION(major, minor) CONCAT_VERSION2(major, minor) +#define VERSION_STRING CONCAT_VERSION(OBJFW_RT_LIB_MAJOR, OBJFW_RT_LIB_MINOR) + +/* This always needs to be the first thing in the file. */ +int +_start() +{ + return -1; +} struct ObjFWRTBase { struct Library library; BPTR seg_list; }; -/* Forward declarations for all functions in the func_table */ -static struct Library *lib_init(struct ObjFWRTBase *base, BPTR seg_list, - struct ExecBase *exec_base); -static struct Library *lib_open(void); -static BPTR lib_close(void); -static BPTR lib_expunge(void); -static void lib_null(void); -void objc_set_exit(void OF_NO_RETURN_FUNC (*exit_fn_)(int status)); - -static ULONG func_table[] = { - FUNCARRAY_BEGIN, - FUNCARRAY_32BIT_NATIVE, +struct ExecBase *SysBase; +#ifdef OF_MORPHOS +const ULONG __abox__ = 1; +#endif +struct WBStartup *_WBenchMsg; +struct objc_libc *libc; +FILE *stdout; +FILE *stderr; + +static struct Library * +lib_init(struct ExecBase *exec_base OBJC_M68K_REG("a6"), + BPTR seg_list OBJC_M68K_REG("a0"), + struct ObjFWRTBase *base OBJC_M68K_REG("d0")) +{ + SysBase = exec_base; + + base->seg_list = seg_list; + + return &base->library; +} + +static struct Library * +OBJC_M68K_FUNC(lib_open, struct ObjFWRTBase *base OBJC_M68K_REG("a6")) +{ + OBJC_M68K_ARG(struct ObjFWRTBase *, base, REG_A6) + + base->library.lib_OpenCnt++; + base->library.lib_Flags &= ~LIBF_DELEXP; + + return &base->library; +} + +static BPTR +expunge(struct ObjFWRTBase *base) +{ + BPTR seg_list; + + if (base->library.lib_OpenCnt > 0) { + base->library.lib_Flags |= LIBF_DELEXP; + return 0; + } + + seg_list = base->seg_list; + + Remove(&base->library.lib_Node); + FreeMem((char *)base - base->library.lib_NegSize, + base->library.lib_NegSize + base->library.lib_PosSize); + + return seg_list; +} + +static BPTR +OBJC_M68K_FUNC(lib_expunge, struct ObjFWRTBase *base OBJC_M68K_REG("a6")) +{ + OBJC_M68K_ARG(struct ObjFWRTBase *, base, REG_A6) + + return expunge(base); +} + +static BPTR +OBJC_M68K_FUNC(lib_close, struct ObjFWRTBase *base OBJC_M68K_REG("a6")) +{ + OBJC_M68K_ARG(struct ObjFWRTBase *, base, REG_A6) + + if (--base->library.lib_OpenCnt == 0 && + (base->library.lib_Flags & LIBF_DELEXP)) + return expunge(base); + + return 0; +} + +static BPTR +lib_null(void) +{ + return 0; +} + +static void +objc_set_libc(struct objc_libc *libc_) +{ + libc = libc_; + + stdout = libc->stdout; + stderr = libc->stderr; +} + +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 +fputs(const char *restrict s, FILE *restrict stream) +{ + return libc->fputs(s, stream); +} + +void +exit(int status) +{ + libc->exit(status); +} + +void +abort(void) +{ + libc->abort(); +} + +static ULONG function_table[] = { (ULONG)lib_open, (ULONG)lib_close, (ULONG)lib_expunge, (ULONG)lib_null, - -1, - FUNCARRAY_32BIT_SYSTEMV, /* Functions for the glue code */ - (ULONG)objc_set_exit, + (ULONG)objc_set_libc, /* Used by the compiler - these need glue code */ (ULONG)__objc_exec_class, (ULONG)objc_msg_lookup, (ULONG)objc_msg_lookup_stret, (ULONG)objc_msg_lookup_super, @@ -99,122 +240,39 @@ (ULONG)objc_setUncaughtExceptionHandler, (ULONG)objc_setForwardHandler, (ULONG)objc_setEnumerationMutationHandler, (ULONG)objc_zero_weak_references, -1, - FUNCARRAY_END }; -static struct Library *lib_init(struct ObjFWRTBase *base, BPTR seg_list, - struct ExecBase *exec_base); - static struct { - LONG struct_size; - ULONG *func_table; - void *data_table; - struct Library *(*init_func)(struct ObjFWRTBase *base, BPTR seg_list, - struct ExecBase *exec_base); -} init_table = { - .struct_size = sizeof(struct ObjFWRTBase), - func_table, + ULONG data_size; + ULONG *function_table; + 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 = { + sizeof(struct ObjFWRTBase), + function_table, NULL, lib_init }; static struct Resident resident = { .rt_MatchWord = RTC_MATCHWORD, .rt_MatchTag = &resident, .rt_EndSkip = &resident + 1, - .rt_Flags = RTF_AUTOINIT | RTF_PPC, - .rt_Version = OBJFW_RT_LIB_MAJOR * 10 + OBJFW_RT_LIB_MINOR, + .rt_Flags = RTF_AUTOINIT +#ifndef OF_AMIGAOS3 + | RTF_PPC +#endif + , + .rt_Version = OBJFW_RT_LIB_MAJOR, .rt_Type = NT_LIBRARY, .rt_Pri = 0, .rt_Name = (char *)"objfw_rt.library", - .rt_IdString = (char *)"ObjFW_RT " PACKAGE_VERSION + .rt_IdString = (char *)"ObjFW_RT " VERSION_STRING " \xA9 2008-2018 Jonathan Schleifer", - .rt_Init = &init_table + .rt_Init = &initTable }; - -/* Magic required to make this a MorphOS binary */ -const ULONG __abox__ = 1; - -/* Global variables needed by libnix */ -int ThisRequiresConstructorHandling; -struct ExecBase *SysBase; -void *libnix_mempool; - -/* Functions passed in from the glue linklib */ -static void OF_NO_RETURN_FUNC (*exit_fn)(int status); - -void OF_NO_RETURN_FUNC -exit(int status) -{ - exit_fn(status); -} - -void -objc_set_exit(void OF_NO_RETURN_FUNC (*exit_fn_)(int status)) -{ - exit_fn = exit_fn_; -} - -/* Standard library functions */ -static struct Library *lib_init(struct ObjFWRTBase *base, BPTR seg_list, - struct ExecBase *exec_base) -{ - SysBase = exec_base; - - base->seg_list = seg_list; - - return &base->library; -} - -static struct Library * -lib_open(void) -{ - struct ObjFWRTBase *base = (struct ObjFWRTBase *)REG_A6; - - base->library.lib_OpenCnt++; - base->library.lib_Flags &= ~LIBF_DELEXP; - - return &base->library; -} - -static BPTR -expunge(struct ObjFWRTBase *base) -{ - /* Still in use - set delayed expunge flag and refuse to expunge */ - if (base->library.lib_OpenCnt > 0) { - base->library.lib_Flags |= LIBF_DELEXP; - return 0; - } - - Remove(&base->library.lib_Node); - FreeMem((char *)base - base->library.lib_NegSize, - base->library.lib_NegSize + base->library.lib_PosSize); - - return base->seg_list; -} - -static BPTR -lib_close(void) -{ - struct ObjFWRTBase *base = (struct ObjFWRTBase *)REG_A6; - - /* Not used anymore and delayed expunge flag set -> expunge */ - if (--base->library.lib_OpenCnt == 0 && - (base->library.lib_Flags & LIBF_DELEXP)) - return expunge(base); - - return 0; -} - -static BPTR -lib_expunge(void) -{ - return expunge((struct ObjFWRTBase *)REG_A6); -} - -static void -lib_null(void) -{ -} Index: src/runtime/private.h ================================================================== --- src/runtime/private.h +++ src/runtime/private.h @@ -131,10 +131,28 @@ #else IMP _Nullable buckets[256]; #endif } *_Nonnull buckets[256]; }; + +#ifdef OF_AMIGA_LIBRARY +# undef stdout +# undef stderr +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 (*fputs)(const char *, FILE *); + void (*exit)(int); + void (*abort)(void); + FILE *stdout; + FILE *stderr; +} *objc_libc; +extern FILE *stdout, *stderr; +#endif extern void objc_register_all_categories(struct objc_abi_symtab *_Nonnull); extern struct objc_category *_Nullable *_Nullable objc_categories_for_class(Class _Nonnull); extern void objc_unregister_all_categories(void);