ObjFW  Diff

Differences From Artifact [3a04605e77]:

To Artifact [9f14e5de8b]:


15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

37









38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

55
56
57






























































58





59
60
61
62
63

64
65
66

67
68
69
70
71
72
73
74













75
76
77
78
79
80

81
82

83







84
85
86

























87
88
89
90
91
92

93
94

95







96
97
98
99
100
101
102
103
104

105
106

107







108
109
110
111
112
113
114
115
116
117
118
119

120
121
122
123
124
125
126
 * file.
 */

#include "config.h"

#import "ObjFW_RT.h"
#import "private.h"
#import "platform.h"

#ifdef OF_AMIGAOS3
# define INTUITION_CLASSES_H
#endif

#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(OBJFW_RT_LIB_MAJOR, OBJFW_RT_LIB_MINOR)


#define DATA_OFFSET 0x7FFE










/* This always needs to be the first thing in the file. */
int
_start()
{
	return -1;
}

struct ObjFWRTBase {
	struct Library library;
	void *seg_list;
	struct ObjFWRTBase *parent;
	char *data_seg;
	bool initialized;
	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, *__data_size;






#ifdef OF_MORPHOS
const ULONG __abox__ = 1;
#endif
struct ExecBase *SysBase;

FILE *stdout;
FILE *stderr;


__asm__ (
    ".text\n"
    ".globl ___restore_a4\n"
    ".align 1\n"
    "___restore_a4:\n"
    "	movea.l	42(a6), a4\n"
    "	rts"
);














static OF_INLINE char *
get_data_seg(void)
{
	char *data_seg;


	__asm__ __volatile__ (
	    "move.l	#___a4_init, %0" : "=r"(data_seg)

	);








	return data_seg;
}


























static OF_INLINE size_t *
get_datadata_relocs(void)
{
	size_t *datadata_relocs;


	__asm__ __volatile__ (
	    "move.l	#___datadata_relocs, %0" : "=r"(datadata_relocs)

	);








	return datadata_relocs;
}

static struct Library *
lib_init(struct ExecBase *sys_base OBJC_M68K_REG("a6"),
    void *seg_list OBJC_M68K_REG("a0"),
    struct ObjFWRTBase *base OBJC_M68K_REG("d0"))
{

	__asm__ __volatile__ (
	    "move.l	a6, _SysBase" :: "a"(sys_base)

	);








	base->seg_list = seg_list;
	base->parent = NULL;
	base->data_seg = get_data_seg();

	return &base->library;
}

struct Library *__saveds
OBJC_M68K_FUNC(lib_open, struct ObjFWRTBase *base OBJC_M68K_REG("a6"))
{
	OBJC_M68K_ARG(struct ObjFWRTBase *, base, REG_A6)

	struct ObjFWRTBase *child;
	size_t data_size, *datadata_relocs;
	ptrdiff_t displacement;

	if (base->parent != NULL)
		return NULL;








<














>
|
>
>
>
>
>
>
>
>
>














<


>
|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>





>



>








>
>
>
>
>
>
>
>
>
>
>
>
>






>
|
|
>

>
>
>
>
>
>
>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






>
|
|
>

>
>
>
>
>
>
>





|
|
|

>

|
>

>
>
>
>
>
>
>









|

|
>







15
16
17
18
19
20
21

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
 * file.
 */

#include "config.h"

#import "ObjFW_RT.h"
#import "private.h"


#ifdef OF_AMIGAOS3
# define INTUITION_CLASSES_H
#endif

#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(OBJFW_RT_LIB_MAJOR, OBJFW_RT_LIB_MINOR)

#if defined(OF_AMIGAOS3)
# define DATA_OFFSET 0x7FFE
#elif defined(OF_MORPHOS)
# define DATA_OFFSET 0x8000
#endif

#ifdef OF_AMIGAOS3
# 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 *seg_list;
	struct ObjFWRTBase *parent;
	char *data_seg;
	bool initialized;

};

#ifdef OF_AMIGAOS3
extern uintptr_t __CTOR_LIST__[];
extern const void *_EH_FRAME_BEGINS__;
extern void *_EH_FRAME_OBJECTS__;
#endif

extern void __objc_exec_class_m68k(void);
extern IMP _Nonnull objc_msg_lookup_m68k(void);
extern IMP _Nonnull objc_msg_lookup_stret_m68k(void);
extern IMP _Nonnull objc_msg_lookup_super_m68k(void);
extern IMP _Nonnull objc_msg_lookup_super_stret_m68k(void);
extern Class _Nullable objc_lookUpClass_m68k(void);
extern Class _Nullable objc_getClass_m68k(void);
extern Class _Nonnull objc_getRequiredClass_m68k(void);
extern Class _Nullable objc_lookup_class_m68k(void);
extern Class _Nonnull objc_get_class_m68k(void);
extern void objc_exception_throw_m68k(void);
extern int objc_sync_enter_m68k(void);
extern int objc_sync_exit_m68k(void);
extern id _Nullable objc_getProperty_m68k(void);
extern void objc_setProperty_m68k(void);
extern void objc_getPropertyStruct_m68k(void);
extern void objc_setPropertyStruct_m68k(void);
extern void objc_enumerationMutation_m68k(void);
extern int __gnu_objc_personality_sj0_m68k(void);
extern int __gnu_objc_personality_v0_m68k(void);
extern id _Nullable objc_retain_m68k(void);
extern id _Nullable objc_retainBlock_m68k(void);
extern id _Nullable objc_retainAutorelease_m68k(void);
extern void objc_release_m68k(void);
extern id _Nullable objc_autorelease_m68k(void);
extern id _Nullable objc_autoreleaseReturnValue_m68k(void);
extern id _Nullable objc_retainAutoreleaseReturnValue_m68k(void);
extern id _Nullable objc_retainAutoreleasedReturnValue_m68k(void);
extern id _Nullable objc_storeStrong_m68k(void);
extern id _Nullable objc_storeWeak_m68k(void);
extern id _Nullable objc_loadWeakRetained_m68k(void);
extern id _Nullable objc_initWeak_m68k(void);
extern void objc_destroyWeak_m68k(void);
extern id _Nullable objc_loadWeak_m68k(void);
extern void objc_copyWeak_m68k(void);
extern void objc_moveWeak_m68k(void);
extern SEL _Nonnull sel_registerName_m68k(void);
extern const char *_Nonnull sel_getName_m68k(void);
extern bool sel_isEqual_m68k(void);
extern Class _Nonnull objc_allocateClassPair_m68k(void);
extern void objc_registerClassPair_m68k(void);
extern unsigned int objc_getClassList_m68k(void);
extern Class _Nonnull *_Nonnull objc_copyClassList_m68k(void);
extern bool class_isMetaClass_m68k(void);
extern const char *_Nullable class_getName_m68k(void);
extern Class _Nullable class_getSuperclass_m68k(void);
extern unsigned long class_getInstanceSize_m68k(void);
extern bool class_respondsToSelector_m68k(void);
extern bool class_conformsToProtocol_m68k(void);
extern IMP _Nullable class_getMethodImplementation_m68k(void);
extern IMP _Nullable class_getMethodImplementation_stret_m68k(void);
extern const char *_Nullable class_getMethodTypeEncoding_m68k(void);
extern bool class_addMethod_m68k(void);
extern IMP _Nullable class_replaceMethod_m68k(void);
extern Class _Nullable object_getClass_m68k(void);
extern Class _Nullable object_setClass_m68k(void);
extern const char *_Nullable object_getClassName_m68k(void);
extern const char *_Nonnull protocol_getName_m68k(void);
extern bool protocol_isEqual_m68k(void);
extern bool protocol_conformsToProtocol_m68k(void);
extern void objc_exit_m68k(void);
extern _Nullable objc_uncaught_exception_handler
    objc_setUncaughtExceptionHandler_m68k(void);
extern void objc_setForwardHandler_m68k(void);
extern void objc_setEnumerationMutationHandler_m68k(void);
extern void objc_zero_weak_references_m68k(void);

#ifdef OF_MORPHOS
const ULONG __abox__ = 1;
#endif
struct ExecBase *SysBase;
struct objc_libc libc;
FILE *stdout;
FILE *stderr;

#if defined(OF_AMIGAOS3)
__asm__ (
    ".text\n"
    ".globl ___restore_a4\n"
    ".align 1\n"
    "___restore_a4:\n"
    "	movea.l	42(a6), a4\n"
    "	rts"
);
#elif defined(OF_MORPHOS)
__asm__ (
    ".section .text\n"
    ".globl __restore_r13\n"
    ".align 2\n"
    "__restore_r13:\n"
    "	lwz	%r13, 56(%r2)\n"
    "	lwz	%r13, 44(%r13)\n"
    "	blr\n"
    ".type __restore_r13, @function\n"
    ".size __restore_r13, .-__restore_r13"
);
#endif

static OF_INLINE char *
get_data_seg(void)
{
	char *data_seg;

#if defined(OF_AMIGAOS3)
	__asm__ (
	    "move.l	#___a4_init, %0"
	    : "=r"(data_seg)
	);
#elif defined(OF_MORPHOS)
	__asm__ (
	    "lis	%0, __r13_init@ha\n\t"
	    "la		%0, __r13_init@l(%0)"
	    : "=r"(data_seg)
	);
#endif

	return data_seg;
}

static OF_INLINE size_t
get_data_size(void)
{
	size_t data_size;

#if defined(OF_AMIGAOS3)
	__asm__ (
	    "move.l	#___data_size, %0"
	    : "=r"(data_size)
	);
#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"(data_size)
	    :: "r9"
	);
#endif

	return data_size;
}

static OF_INLINE size_t *
get_datadata_relocs(void)
{
	size_t *datadata_relocs;

#if defined(OF_AMIGAOS3)
	__asm__ (
	    "move.l	#___datadata_relocs, %0"
	    : "=r"(datadata_relocs)
	);
#elif defined(OF_MORPHOS)
	__asm__ (
	    "lis	%0, __datadata_relocs@ha\n\t"
	    "la		%0, __datadata_relocs@l(%0)\n\t"
	    : "=r"(datadata_relocs)
	);
#endif

	return datadata_relocs;
}

static struct Library *
lib_init(struct ObjFWRTBase *base OBJC_M68K_REG(d0),
    void *seg_list OBJC_M68K_REG(a0),
    struct ExecBase *sys_base OBJC_M68K_REG(a6))
{
#if defined(OF_AMIGAOS3)
	__asm__ __volatile__ (
	    "move.l	a6, _SysBase"
	    :: "a"(sys_base)
	);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "lis	%%r9, SysBase@ha\n\t"
	    "stw	%0, SysBase@l(%%r9)"
	    :: "r"(sys_base) : "r9"
	);
#endif

	base->seg_list = seg_list;
	base->parent = NULL;
	base->data_seg = get_data_seg();

	return &base->library;
}

struct Library *__saveds
lib_open(void)
{
	OBJC_M68K_ARG(struct ObjFWRTBase *, base, a6)

	struct ObjFWRTBase *child;
	size_t data_size, *datadata_relocs;
	ptrdiff_t displacement;

	if (base->parent != NULL)
		return NULL;

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
	    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;

	data_size = (uintptr_t)&__data_size -
	    ((uintptr_t)&__a4_init - DATA_OFFSET);

	if ((child->data_seg = AllocMem(data_size, MEMF_ANY)) == NULL) {
		FreeMem((char *)child - child->library.lib_NegSize,
		    child->library.lib_NegSize + child->library.lib_PosSize);
		base->library.lib_OpenCnt--;
		return NULL;
	}







|
<







285
286
287
288
289
290
291
292

293
294
295
296
297
298
299
	    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;

	data_size = get_data_size();


	if ((child->data_seg = AllocMem(data_size, MEMF_ANY)) == NULL) {
		FreeMem((char *)child - child->library.lib_NegSize,
		    child->library.lib_NegSize + child->library.lib_PosSize);
		base->library.lib_OpenCnt--;
		return NULL;
	}
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210

211
212
213
214

215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239



240
241
242

243
244
245
246
247
248
249
250
251
252
253
254

255
256
257
258
259
260
261
262








263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334

335
336
337
338
339

340

341
342
343



344



345
346
347
348
349
350
351

352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423



424



425
426
427
428
429
430
431

432
433
434
435




436
437
438
439
440
441



442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467



468
469
470
471
472
473
474
475




476









	FreeMem((char *)base - base->library.lib_NegSize,
	    base->library.lib_NegSize + base->library.lib_PosSize);

	return seg_list;
}

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 *__saveds
OBJC_M68K_FUNC(lib_close, struct ObjFWRTBase *base OBJC_M68K_REG("a6"))
{
	OBJC_M68K_ARG(struct ObjFWRTBase *, base, REG_A6)

	if (base->parent != NULL) {
		struct ObjFWRTBase *parent;


		if (base->initialized)
			for (size_t i = 1; i <= (size_t)_EH_FRAME_BEGINS__; i++)
				base->libc.__deregister_frame_info(
				    (&_EH_FRAME_BEGINS__)[i]);


		parent = base->parent;

		FreeMem(base->data_seg - DATA_OFFSET, (uintptr_t)&__data_size -
		    ((uintptr_t)&__a4_init - DATA_OFFSET));
		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 0;
}

static void *
lib_null(void)
{
	return 0;
}

static bool __saveds



objc_init(unsigned int version OBJC_M68K_REG("d0"),
    struct objc_libc *libc OBJC_M68K_REG("a0"),
    FILE *stdout_ OBJC_M68K_REG("a1"), FILE *stderr_ OBJC_M68K_REG("a2"))

{
	register struct ObjFWRTBase *base OBJC_M68K_REG("a6");
	uintptr_t *iter, *iter0;

	if (version > 1)
		return false;

	memcpy(&base->libc, libc, sizeof(base->libc));

	stdout = stdout_;
	stderr = stderr_;


	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++)
		base->libc.__register_frame_info((&_EH_FRAME_BEGINS__)[i],
		    (&_EH_FRAME_OBJECTS__)[i]);

	iter0 = &__CTOR_LIST__[1];








	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)
{
	register struct ObjFWRTBase *base OBJC_M68K_REG("a6");

	return base->libc.malloc(size);
}

void *
calloc(size_t count, size_t size)
{
	register struct ObjFWRTBase *base OBJC_M68K_REG("a6");

	return base->libc.calloc(count, size);
}

void *
realloc(void *ptr, size_t size)
{
	register struct ObjFWRTBase *base OBJC_M68K_REG("a6");

	return base->libc.realloc(ptr, size);
}

void
free(void *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 = base->libc.vfprintf(stream, fmt, args);
	va_end(args);

	return ret;
}

int
fflush(FILE *restrict stream)
{
	register struct ObjFWRTBase *base OBJC_M68K_REG("a6");

	return base->libc.fflush(stream);
}

void
exit(int status)
{
	register struct ObjFWRTBase *base OBJC_M68K_REG("a6");

	base->libc.exit(status);

}

void
abort(void)
{

	register struct ObjFWRTBase *base OBJC_M68K_REG("a6");


	base->libc.abort();
}







int
_Unwind_RaiseException(void *ex)
{
	register struct ObjFWRTBase *base OBJC_M68K_REG("a6");

	return base->libc._Unwind_RaiseException(ex);
}


void
_Unwind_DeleteException(void *ex)
{
	register struct ObjFWRTBase *base OBJC_M68K_REG("a6");

	base->libc._Unwind_DeleteException(ex);
}

void *
_Unwind_GetLanguageSpecificData(void *ctx)
{
	register struct ObjFWRTBase *base OBJC_M68K_REG("a6");

	return base->libc._Unwind_GetLanguageSpecificData(ctx);
}

uintptr_t
_Unwind_GetRegionStart(void *ctx)
{
	register struct ObjFWRTBase *base OBJC_M68K_REG("a6");

	return base->libc._Unwind_GetRegionStart(ctx);
}

uintptr_t
_Unwind_GetDataRelBase(void *ctx)
{
	register struct ObjFWRTBase *base OBJC_M68K_REG("a6");

	return base->libc._Unwind_GetDataRelBase(ctx);
}

uintptr_t
_Unwind_GetTextRelBase(void *ctx)
{
	register struct ObjFWRTBase *base OBJC_M68K_REG("a6");

	return base->libc._Unwind_GetTextRelBase(ctx);
}

uintptr_t
_Unwind_GetIP(void *ctx)
{
	register struct ObjFWRTBase *base OBJC_M68K_REG("a6");

	return base->libc._Unwind_GetIP(ctx);
}

uintptr_t
_Unwind_GetGR(void *ctx, int gr)
{
	register struct ObjFWRTBase *base OBJC_M68K_REG("a6");

	return base->libc._Unwind_GetGR(ctx, gr);
}

void
_Unwind_SetIP(void *ctx, uintptr_t 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)
{
	register struct ObjFWRTBase *base OBJC_M68K_REG("a6");

	base->libc._Unwind_SetGR(ctx, gr, value);
}







void
_Unwind_Resume(void *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[] = {




	(CONST_APTR)lib_open,
	(CONST_APTR)lib_close,
	(CONST_APTR)lib_expunge,
	(CONST_APTR)lib_null,
#include "amiga-library-functable.inc"
	(CONST_APTR)-1,



};
#pragma GCC diagnostic pop

static struct {
	ULONG data_size;
	CONST_APTR *function_table;
	ULONG *data_table;
	struct Library *(*init_func)(
	    struct ExecBase *exec_base OBJC_M68K_REG("a6"),
	    void *seg_list OBJC_M68K_REG("a0"),
	    struct ObjFWRTBase *base OBJC_M68K_REG("d0"));
} init_table = {
	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
#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 " VERSION_STRING
	    " \xA9 2008-2018 Jonathan Schleifer",
	.rt_Init = &init_table




};
















|

|





|

|




>


|

>



|
<










|





|



>
>
>
|
|
|
>
|
<





<
|



>




|



>
>
>
>
>
>
>
>















<
<
|





<
<
|





<
<
|





<
<
|





<




|








<
<
|





|

<
>





>
|
>
|
<
|
>
>
>
|
>
>
>



<
<
|

>




<
<
|





<
<
|





<
<
|





<
<
|





<
<
|





<
<
|





<
<
|





<
<
|





|
|
<
|
>
>
>
|
>
>
>



<
<
|

>




>
>
>
>






>
>
>








|
|
|







|







>
>
>







|
>
>
>
>

>
>
>
>
>
>
>
>
>
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363

364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391

392
393
394
395
396

397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432


433
434
435
436
437
438


439
440
441
442
443
444


445
446
447
448
449
450


451
452
453
454
455
456

457
458
459
460
461
462
463
464
465
466
467
468
469


470
471
472
473
474
475
476
477

478
479
480
481
482
483
484
485
486
487

488
489
490
491
492
493
494
495
496
497
498


499
500
501
502
503
504
505


506
507
508
509
510
511


512
513
514
515
516
517


518
519
520
521
522
523


524
525
526
527
528
529


530
531
532
533
534
535


536
537
538
539
540
541


542
543
544
545
546
547


548
549
550
551
552
553
554
555

556
557
558
559
560
561
562
563
564
565
566


567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
	FreeMem((char *)base - base->library.lib_NegSize,
	    base->library.lib_NegSize + base->library.lib_PosSize);

	return seg_list;
}

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_AMIGAOS3
		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->data_seg - DATA_OFFSET, get_data_size());

		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;
}

static bool __saveds
objc_init_m68k(void)
{
	OBJC_M68K_ARG(struct ObjFWRTBase *, base, a6)
	OBJC_M68K_ARG(unsigned int, version, d0)
	OBJC_M68K_ARG(struct objc_libc *, libc_, a0)
	OBJC_M68K_ARG(FILE *, stdout_, a1)
	OBJC_M68K_ARG(FILE *, stderr_, a2)


	uintptr_t *iter, *iter0;

	if (version > 1)
		return false;


	memcpy(&libc, libc_, sizeof(libc));
	stdout = stdout_;
	stderr = stderr_;

#ifdef OF_AMIGAOS3
	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
exit(int status)
{
	libc.exit(status);


	OF_UNREACHABLE
}

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 function_table[] = {
#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,
#include "amiga-library-functable.inc"
	(CONST_APTR)-1,
#ifdef OF_MORPHOS
	(CONST_APTR)FUNCARRAY_END
#endif
};
#pragma GCC diagnostic pop

static struct {
	ULONG data_size;
	CONST_APTR *function_table;
	ULONG *data_table;
	struct Library *(*init_func)(
	    struct ObjFWRTBase *base OBJC_M68K_REG(d0),
	    void *seg_list OBJC_M68K_REG(a0),
	    struct ExecBase *exec_base OBJC_M68K_REG(a6));
} init_table = {
	sizeof(struct ObjFWRTBase),
	function_table,
	NULL,
	lib_init
};

struct Resident resident = {
	.rt_MatchWord = RTC_MATCHWORD,
	.rt_MatchTag = &resident,
	.rt_EndSkip = &resident + 1,
	.rt_Flags = RTF_AUTOINIT
#ifndef OF_AMIGAOS3
	    | RTF_PPC
#endif
#ifdef OF_MORPHOS
	    | RTF_EXTENDED
#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 " VERSION_STRING
	    " \xA9 2008-2018 Jonathan Schleifer",
	.rt_Init = &init_table,
#ifdef OF_MORPHOS
	.rt_Revision = OBJFW_RT_LIB_MINOR,
	.rt_Tags = NULL,
#endif
};

#ifdef OF_MORPHOS
__asm__ (
    ".section .ctors, \"aw\", @progbits\n"
    "ctors:\n"
    "	.long -1\n"
    ".section .text"
);
#endif