Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -257,6 +257,7 @@ LD = ${OBJC} FRAMEWORK_LIBS := -Fruntime \ ${RUNTIME_FRAMEWORK_LIBS} \ ${REEXPORT_RUNTIME_FRAMEWORK} \ ${LIBS} -LIBS := -Lruntime ${RUNTIME_LIBS} ${REEXPORT_RUNTIME} ${LIBS} +LIBS := -Lruntime -Lruntime/linklib ${RUNTIME_LIBS} ${REEXPORT_RUNTIME} ${LIBS} +AMIGA_LIB_LIBS = ${LIBS} Index: src/amiga-glue.m ================================================================== --- src/amiga-glue.m +++ src/amiga-glue.m @@ -15,15 +15,16 @@ * file. */ #include "config.h" +#import "amiga-library.h" #import "platform.h" #ifdef OF_AMIGAOS_M68K # define PPC_PARAMS(...) (void) -# define M68K_ARG OBJC_M68K_ARG +# define M68K_ARG OF_M68K_ARG #else # define PPC_PARAMS(...) (__VA_ARGS__) # define M68K_ARG(...) #endif @@ -36,9 +37,15 @@ " lwz %r13, 44(%r12)\n" " blr\n" ); #endif -/* To not have an empty compilation unit for now. */ -__asm__ ( - "" -); +bool __saveds +glue_of_init PPC_PARAMS(unsigned int version, struct of_libc *libc, + FILE *stderr_) +{ + M68K_ARG(unsigned int, version, d0) + M68K_ARG(struct objc_libc *, libc, a0) + M68K_ARG(FILE *, stderr_, a1) + + return of_init(version, libc, stderr_); +} ADDED src/amiga-library.h Index: src/amiga-library.h ================================================================== --- src/amiga-library.h +++ src/amiga-library.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018, 2019, 2020 + * 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. + */ + +#import "macros.h" + +#if defined(OF_COMPILING_AMIGA_LIBRARY) || defined(OF_COMPILING_AMIGA_LINKLIB) +struct of_libc { + void *_Nullable (*_Nonnull malloc)(size_t); + void *_Nullable (*_Nonnull calloc)(size_t, size_t); + void *_Nullable (*_Nonnull realloc)(void *_Nullable, size_t); + void (*_Nonnull free)(void *_Nullable); + int (*_Nonnull vfprintf)(FILE *_Nonnull restrict, + const char *restrict _Nonnull, va_list); + int (*_Nonnull vsnprintf)(const char *_Nonnull restrict, size_t, + const char *_Nonnull restrict, va_list); + void (*_Nonnull exit)(int); + void (*_Nonnull abort)(void); + char *(*_Nonnull setlocale)(int, const char *_Nullable); + void (*_Nonnull __register_frame_info)(const void *_Nonnull, + void *_Nonnull); + void *(*_Nonnull __deregister_frame_info)(const void *_Nonnull); +}; +#endif Index: src/amiga-library.m ================================================================== --- src/amiga-library.m +++ src/amiga-library.m @@ -15,16 +15,17 @@ * file. */ #include "config.h" -#import "OFObject.h" - #include #include #include #include + +#import "amiga-library.h" +#import "macros.h" #define CONCAT_VERSION2(major, minor) #major "." #minor #define CONCAT_VERSION(major, minor) CONCAT_VERSION2(major, minor) #define VERSION_STRING CONCAT_VERSION(OBJFW_LIB_MAJOR, OBJFW_LIB_MINOR) @@ -59,14 +60,18 @@ extern uintptr_t __CTOR_LIST__[]; extern const void *_EH_FRAME_BEGINS__; extern void *_EH_FRAME_OBJECTS__; #endif +extern bool glue_of_init(void); + #ifdef OF_MORPHOS const ULONG __abox__ = 1; #endif struct ExecBase *SysBase; +struct of_libc libc; +FILE *stderr; #if defined(OF_AMIGAOS_M68K) __asm__ ( ".text\n" ".globl ___restore_a4\n" @@ -290,10 +295,125 @@ static void * lib_null(void) { return NULL; } + +bool +of_init(unsigned int version, struct of_libc *libc_, FILE *stderr_) +{ +#ifdef OF_AMIGAOS_M68K + OF_M68K_ARG(struct ObjFWBase *, base, a6) +#else + register struct ObjFWBase *r12 __asm__("r12"); + struct ObjFWBase *base = r12; +#endif + uintptr_t *iter, *iter0; + + if (version > 1) + return false; + + if (base->initialized) + return true; + + memcpy(&libc, libc_, sizeof(libc)); + 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 +vsnprintf(char *restrict str, size_t size, const char *restrict fmt, + va_list args) +{ + return libc.vsnprintf(str, size, fmt, args); +} + +void +exit(int status) +{ + libc.exit(status); + + OF_UNREACHABLE +} + +void +abort(void) +{ + libc.abort(); + + OF_UNREACHABLE +} + +char * +setlocale(int category, const char *locale) +{ + return libc.setlocale(category, locale); +} #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" static CONST_APTR functionTable[] = { #ifdef OF_MORPHOS @@ -306,10 +426,11 @@ (CONST_APTR)lib_null, #ifdef OF_MORPHOS (CONST_APTR)-1, (CONST_APTR)FUNCARRAY_32BIT_SYSTEMV, #endif + (CONST_APTR)glue_of_init, #ifdef OF_MORPHOS (CONST_APTR)FUNCARRAY_END #endif }; #pragma GCC diagnostic pop Index: src/macros.h ================================================================== --- src/macros.h +++ src/macros.h @@ -316,10 +316,12 @@ # else # define OF_M68K_ARG(type, name, reg) \ register type reg_##name __asm__(#reg); \ type name = reg_##name; # endif +# undef stderr +extern FILE *stderr; #endif #ifdef __GNUC__ # ifdef OF_X86_64 # define OF_X86_64_ASM Index: src/runtime/amiga-library.m ================================================================== --- src/runtime/amiga-library.m +++ src/runtime/amiga-library.m @@ -151,12 +151,11 @@ #ifdef OF_MORPHOS const ULONG __abox__ = 1; #endif struct ExecBase *SysBase; struct objc_libc libc; -FILE *stdout; -FILE *stderr; +FILE *stdout, *stderr; #if defined(OF_AMIGAOS_M68K) __asm__ ( ".text\n" ".globl ___restore_a4\n" @@ -405,10 +404,13 @@ #endif uintptr_t *iter, *iter0; if (version > 1) return false; + + if (base->initialized) + return true; memcpy(&libc, libc_, sizeof(libc)); stdout = stdout_; stderr = stderr_; Index: src/runtime/private.h ================================================================== --- src/runtime/private.h +++ src/runtime/private.h @@ -223,11 +223,12 @@ struct objc_libc { void *_Nullable (*_Nonnull malloc)(size_t); void *_Nullable (*_Nonnull calloc)(size_t, size_t); void *_Nullable (*_Nonnull realloc)(void *_Nullable, size_t); void (*_Nonnull free)(void *_Nullable); - int (*_Nonnull vfprintf)(FILE *_Nonnull, const char *_Nonnull, va_list); + int (*_Nonnull vfprintf)(FILE *_Nonnull restrict, + const char *_Nonnull restrict, va_list); int (*_Nonnull fflush)(FILE *_Nonnull); void (*_Nonnull abort)(void); # ifdef HAVE_SJLJ_EXCEPTIONS int (*_Nonnull _Unwind_SjLj_RaiseException)(void *_Nonnull); # else