From a39d31bc0c617e5bc7e57e513ba165e00ed46580 Mon Sep 17 00:00:00 2001 From: Kresten Krab Thorup Date: Thu, 30 Jun 1994 16:18:55 +0000 Subject: [PATCH] This patch makes selectors in the Objective-C language be pointers to a struct { void *sel_id... This patch makes selectors in the Objective-C language be pointers to a struct { void *sel_id, char *sel_types }, where the sel_types element is the type encoding of the method arguments. From-SVN: r7622 --- gcc/objc/Object.h | 10 +- gcc/objc/archive.c | 529 ++++++++++++++++++++++++----------------- gcc/objc/class.c | 116 +++++---- gcc/objc/encoding.c | 18 +- gcc/objc/hash.c | 2 + gcc/objc/init.c | 35 ++- gcc/objc/misc.c | 14 +- gcc/objc/objc-api.h | 19 +- gcc/objc/objc.h | 50 ++-- gcc/objc/objects.c | 2 +- gcc/objc/runtime.h | 6 +- gcc/objc/sarray.c | 7 +- gcc/objc/selector.c | 171 +++++++++++-- gcc/objc/sendmsg.c | 164 +++++++++---- gcc/objc/typedstream.h | 6 +- 15 files changed, 729 insertions(+), 420 deletions(-) diff --git a/gcc/objc/Object.h b/gcc/objc/Object.h index cb409d23cf52..e2722dc18fb2 100644 --- a/gcc/objc/Object.h +++ b/gcc/objc/Object.h @@ -1,5 +1,5 @@ /* Interface for the Object class for Objective-C. - Copyright (C) 1993 Free Software Foundation, Inc. + Copyright (C) 1993, 1994 Free Software Foundation, Inc. This file is part of GNU CC. @@ -93,8 +93,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ - perform:(SEL)aSel with:anObject1 with:anObject2; /* Forwarding */ -- forward:(SEL)aSel :(arglist_t)argFrame; -- performv:(SEL)aSel :(arglist_t)argFrame; +- (retval_t)forward:(SEL)aSel :(arglist_t)argFrame; +- (retval_t)performv:(SEL)aSel :(arglist_t)argFrame; /* Posing */ + poseAs:(Class*)aClassObject; @@ -112,14 +112,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Archiving */ + (int)version; + setVersion:(int)aVersion; - -#ifndef __alpha__ /* TypedStream not supported on alpha yet. */ + (int)streamVersion: (TypedStream*)aStream; - read: (TypedStream*)aStream; - write: (TypedStream*)aStream; -#endif - - awake; @end diff --git a/gcc/objc/archive.c b/gcc/objc/archive.c index 1e776c71598d..71cac4f39b2e 100644 --- a/gcc/objc/archive.c +++ b/gcc/objc/archive.c @@ -24,14 +24,18 @@ You should have received a copy of the GNU General Public License along with however invalidate any other reasons why the executable file might be covered by the GNU General Public License. */ -/* -** Note: This version assumes that int and longs are both 32bit. -*/ - -#ifndef __alpha__ - #include "runtime.h" #include "typedstream.h" +#include "encoding.h" + +extern int fflush(FILE*); + +#define ROUND(V, A) \ + ({ typeof(V) __v=(V); typeof(A) __a=(A); \ + __a*((__v+__a-1)/__a); }) + +#define PTR2LONG(P) (((char*)(P))-(char*)0) +#define LONG2PTR(L) (((char*)0)+(L)) #define __objc_fatal(format, args...) \ { fprintf(stderr, "archiving: "); \ @@ -43,22 +47,20 @@ You should have received a copy of the GNU General Public License along with static int objc_read_class (struct objc_typed_stream* stream, Class** class); -static int -objc_sizeof_type(const char* type); +int objc_sizeof_type(const char* type); static int -objc_write_use_common (struct objc_typed_stream* stream, unsigned int key); +objc_write_use_common (struct objc_typed_stream* stream, unsigned long key); static int objc_write_register_common (struct objc_typed_stream* stream, - unsigned int key); + unsigned long key); static int objc_write_class (struct objc_typed_stream* stream, struct objc_class* class); -static const char* -__objc_skip_type (const char* type); +const char* objc_skip_type (const char* type); static void __objc_finish_write_root_object(struct objc_typed_stream*); static void __objc_finish_read_root_object(struct objc_typed_stream*); @@ -112,15 +114,29 @@ objc_write_char (struct objc_typed_stream* stream, char value) static __inline__ int __objc_code_unsigned_short (unsigned char* buf, unsigned short val) { - if (val <= 0xffU) - return __objc_code_unsigned_char (buf, val); - + if ((val&_B_VALUE) == val) + { + buf[0] = val|_B_SINT; + return 1; + } else { - buf[0] = _B_NINT|0x02; - buf[1] = val/0x100; - buf[2] = val%0x100; - return 3; + int c, b; + + buf[0] = _B_NINT; + + for (c= sizeof(short); c != 0; c -= 1) + if (((val>>(8*(c-1)))%0x100) != 0) + break; + + buf[0] |= c; + + for (b = 1; c != 0; c--, b++) + { + buf[b] = (val >> (8*(c-1)))%0x100; + } + + return b; } } @@ -135,18 +151,11 @@ objc_write_unsigned_short (struct objc_typed_stream* stream, unsigned short valu static __inline__ int __objc_code_short (unsigned char* buf, short val) { - if (val > 0) - return __objc_code_unsigned_short (buf, val); - - if (val > -0x7f) /* val > -128 */ - return __objc_code_char (buf, val); - - else - { - int len = __objc_code_unsigned_short (buf, -val); - buf[0] |= _B_SIGN; - return len; - } + int sign = (val < 0); + int size = __objc_code_unsigned_short (buf, sign ? -val : val); + if (sign) + buf[0] |= _B_SIGN; + return size; } int @@ -161,26 +170,29 @@ objc_write_short (struct objc_typed_stream* stream, short value) static __inline__ int __objc_code_unsigned_int (unsigned char* buf, unsigned int val) { - if (val < 0x10000) - return __objc_code_unsigned_short (buf, val%0x10000); - - else if (val < 0x1000000) + if ((val&_B_VALUE) == val) { - buf[0] = _B_NINT|3; - buf[1] = val/0x10000; - buf[2] = (val%0x10000)/0x100; - buf[3] = val%0x100; - return 4; + buf[0] = val|_B_SINT; + return 1; } - else { - buf[0] = _B_NINT|4; - buf[1] = val/0x1000000; - buf[2] = (val%0x1000000)/0x10000; - buf[3] = (val%0x10000)/0x100; - buf[4] = val%0x100; - return 5; + int c, b; + + buf[0] = _B_NINT; + + for (c= sizeof(int); c != 0; c -= 1) + if (((val>>(8*(c-1)))%0x100) != 0) + break; + + buf[0] |= c; + + for (b = 1; c != 0; c--, b++) + { + buf[b] = (val >> (8*(c-1)))%0x100; + } + + return b; } } @@ -195,28 +207,77 @@ objc_write_unsigned_int (struct objc_typed_stream* stream, unsigned int value) static __inline__ int __objc_code_int (unsigned char* buf, int val) { - if (val >= 0) - return __objc_code_unsigned_int (buf, val); + int sign = (val < 0); + int size = __objc_code_unsigned_int (buf, sign ? -val : val); + if (sign) + buf[0] |= _B_SIGN; + return size; +} - if (val > -0x7f) - return __objc_code_char (buf, val); +int +objc_write_int (struct objc_typed_stream* stream, int value) +{ + unsigned char buf[sizeof(int)+1]; + int len = __objc_code_int (buf, value); + return (*stream->write)(stream->physical, buf, len); +} +static __inline__ int +__objc_code_unsigned_long (unsigned char* buf, unsigned long val) +{ + if ((val&_B_VALUE) == val) + { + buf[0] = val|_B_SINT; + return 1; + } else { - int len = __objc_code_unsigned_int (buf, -val); - buf[0] |= _B_SIGN; - return len; + int c, b; + + buf[0] = _B_NINT; + + for (c= sizeof(long); c != 0; c -= 1) + if (((val>>(8*(c-1)))%0x100) != 0) + break; + + buf[0] |= c; + + for (b = 1; c != 0; c--, b++) + { + buf[b] = (val >> (8*(c-1)))%0x100; + } + + return b; } } int -objc_write_int (struct objc_typed_stream* stream, int value) +objc_write_unsigned_long (struct objc_typed_stream* stream, unsigned long value) { - unsigned char buf[sizeof(int)+1]; - int len = __objc_code_int (buf, value); + unsigned char buf[sizeof(unsigned long)+1]; + int len = __objc_code_unsigned_long (buf, value); return (*stream->write)(stream->physical, buf, len); } +static __inline__ int +__objc_code_long (unsigned char* buf, long val) +{ + int sign = (val < 0); + int size = __objc_code_unsigned_long (buf, sign ? -val : val); + if (sign) + buf[0] |= _B_SIGN; + return size; +} + +int +objc_write_long (struct objc_typed_stream* stream, long value) +{ + unsigned char buf[sizeof(long)+1]; + int len = __objc_code_long (buf, value); + return (*stream->write)(stream->physical, buf, len); +} + + int objc_write_string (struct objc_typed_stream* stream, const unsigned char* string, unsigned int nbytes) @@ -240,13 +301,13 @@ int objc_write_string_atomic (struct objc_typed_stream* stream, unsigned char* string, unsigned int nbytes) { - unsigned int key; - if ((key = (unsigned int)hash_value_for_key (stream->stream_table, string))) + unsigned long key; + if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, string)))) return objc_write_use_common (stream, key); else { int length; - hash_add (&stream->stream_table, (void*)key=(unsigned int)string, string); + hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(string)), string); if ((length = objc_write_register_common (stream, key))) return objc_write_string (stream, string, nbytes); return length; @@ -254,10 +315,10 @@ objc_write_string_atomic (struct objc_typed_stream* stream, } static int -objc_write_register_common (struct objc_typed_stream* stream, unsigned int key) +objc_write_register_common (struct objc_typed_stream* stream, unsigned long key) { - unsigned char buf[sizeof (unsigned int)+2]; - int len = __objc_code_unsigned_int (buf+1, key); + unsigned char buf[sizeof (unsigned long)+2]; + int len = __objc_code_unsigned_long (buf+1, key); if (len == 1) { buf[0] = _B_RCOMM|0x01; @@ -272,10 +333,10 @@ objc_write_register_common (struct objc_typed_stream* stream, unsigned int key) } static int -objc_write_use_common (struct objc_typed_stream* stream, unsigned int key) +objc_write_use_common (struct objc_typed_stream* stream, unsigned long key) { - unsigned char buf[sizeof (unsigned int)+2]; - int len = __objc_code_unsigned_int (buf+1, key); + unsigned char buf[sizeof (unsigned long)+2]; + int len = __objc_code_unsigned_long (buf+1, key); if (len == 1) { buf[0] = _B_UCOMM|0x01; @@ -305,7 +366,7 @@ __inline__ int __objc_write_object (struct objc_typed_stream* stream, id object) { unsigned char buf = '\0'; - SEL write_sel = sel_get_uid ("write:"); + SEL write_sel = sel_get_any_uid ("write:"); if (object) { __objc_write_extension (stream, _BX_OBJECT); @@ -320,12 +381,12 @@ __objc_write_object (struct objc_typed_stream* stream, id object) int objc_write_object_reference (struct objc_typed_stream* stream, id object) { - unsigned int key; - if ((key = (unsigned int)hash_value_for_key (stream->object_table, object))) + unsigned long key; + if ((key = PTR2LONG(hash_value_for_key (stream->object_table, object)))) return objc_write_use_common (stream, key); __objc_write_extension (stream, _BX_OBJREF); - return objc_write_unsigned_int (stream, (unsigned int)object); + return objc_write_unsigned_long (stream, PTR2LONG (object)); } int @@ -348,8 +409,8 @@ objc_write_root_object (struct objc_typed_stream* stream, id object) int objc_write_object (struct objc_typed_stream* stream, id object) { - unsigned int key; - if ((key = (unsigned int)hash_value_for_key (stream->object_table, object))) + unsigned long key; + if ((key = PTR2LONG(hash_value_for_key (stream->object_table, object)))) return objc_write_use_common (stream, key); else if (object == nil) @@ -358,20 +419,26 @@ objc_write_object (struct objc_typed_stream* stream, id object) else { int length; - hash_add (&stream->object_table, (void*)key=(unsigned int)object, object); + hash_add (&stream->object_table, LONG2PTR(key=PTR2LONG(object)), object); if ((length = objc_write_register_common (stream, key))) return __objc_write_object (stream, object); return length; } } +#ifdef __alpha__ +extern int atoi (const char*); +extern size_t strlen(const char*); +extern size_t strcpy(char*, const char*); +#endif + __inline__ int __objc_write_class (struct objc_typed_stream* stream, struct objc_class* class) { __objc_write_extension (stream, _BX_CLASS); objc_write_string_atomic(stream, (char*)class->name, strlen((char*)class->name)); - return objc_write_unsigned_int (stream, CLS_GETNUMBER(class)); + return objc_write_unsigned_long (stream, CLS_GETNUMBER(class)); } @@ -379,13 +446,13 @@ static int objc_write_class (struct objc_typed_stream* stream, struct objc_class* class) { - unsigned int key; - if ((key = (unsigned int)hash_value_for_key (stream->stream_table, class))) + unsigned long key; + if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, class)))) return objc_write_use_common (stream, key); else { int length; - hash_add (&stream->stream_table, (void*)key=(unsigned int)class, class); + hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(class)), class); if ((length = objc_write_register_common (stream, key))) return __objc_write_class (stream, class); return length; @@ -405,13 +472,13 @@ int objc_write_selector (struct objc_typed_stream* stream, SEL selector) { const char* sel_name = sel_get_name (selector); - unsigned int key; - if ((key = (unsigned int)hash_value_for_key (stream->stream_table, sel_name))) + unsigned long key; + if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, sel_name)))) return objc_write_use_common (stream, key); else { int length; - hash_add (&stream->stream_table, (void*)key=(unsigned int)sel_name, (char*)sel_name); + hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(sel_name)), (char*)sel_name); if ((length = objc_write_register_common (stream, key))) return __objc_write_selector (stream, selector); return length; @@ -551,6 +618,33 @@ objc_read_int (struct objc_typed_stream* stream, int* value) return len; } +__inline__ int +objc_read_long (struct objc_typed_stream* stream, long* value) +{ + unsigned char buf[sizeof(long)+1]; + int len; + if ((len = (*stream->read)(stream->physical, buf, 1))) + { + if ((buf[0] & _B_CODE) == _B_SINT) + (*value) = (buf[0] & _B_VALUE); + + else + { + int pos = 1; + int nbytes = buf[0] & _B_NUMBER; + if (nbytes > sizeof (long)) + __objc_fatal("expected long, got bigger"); + len = (*stream->read)(stream->physical, buf+1, nbytes); + (*value) = 0; + while (pos <= nbytes) + (*value) = ((*value)*0x100) + buf[pos++]; + if (buf[0] & _B_SIGN) + (*value) = -(*value); + } + } + return len; +} + __inline__ int __objc_read_nbyte_uint (struct objc_typed_stream* stream, unsigned int nbytes, unsigned int* val) @@ -587,6 +681,42 @@ objc_read_unsigned_int (struct objc_typed_stream* stream, return len; } +int +__objc_read_nbyte_ulong (struct objc_typed_stream* stream, + unsigned int nbytes, unsigned long* val) +{ + int len, pos = 0; + unsigned char buf[sizeof(unsigned long)+1]; + + if (nbytes > sizeof (long)) + __objc_fatal("expected long, got bigger"); + + len = (*stream->read)(stream->physical, buf, nbytes); + (*val) = 0; + while (pos < nbytes) + (*val) = ((*val)*0x100) + buf[pos++]; + return len; +} + + +__inline__ int +objc_read_unsigned_long (struct objc_typed_stream* stream, + unsigned long* value) +{ + unsigned char buf[sizeof(unsigned long)+1]; + int len; + if ((len = (*stream->read)(stream->physical, buf, 1))) + { + if ((buf[0] & _B_CODE) == _B_SINT) + (*value) = (buf[0] & _B_VALUE); + + else + len = __objc_read_nbyte_ulong (stream, (buf[0] & _B_VALUE), value); + + } + return len; +} + __inline__ int objc_read_string (struct objc_typed_stream* stream, char** string) @@ -595,11 +725,11 @@ objc_read_string (struct objc_typed_stream* stream, int len; if ((len = (*stream->read)(stream->physical, buf, 1))) { - unsigned int key = 0; + unsigned long key = 0; if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */ { - len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key); + len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key); len = (*stream->read)(stream->physical, buf, 1); } @@ -609,7 +739,7 @@ objc_read_string (struct objc_typed_stream* stream, int length = buf[0]&_B_VALUE; (*string) = (char*)__objc_xmalloc(length+1); if (key) - hash_add (&stream->stream_table, (void*)key, *string); + hash_add (&stream->stream_table, LONG2PTR(key), *string); len = (*stream->read)(stream->physical, *string, length); (*string)[length] = '\0'; } @@ -618,9 +748,9 @@ objc_read_string (struct objc_typed_stream* stream, case _B_UCOMM: { char *tmp; - len = __objc_read_nbyte_uint (stream, (buf[0] & _B_VALUE), &key); - tmp = hash_value_for_key (stream->stream_table, (void*)key); - *string = __objc_xmalloc (strlen (tmp) + 1); + len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key); + tmp = hash_value_for_key (stream->stream_table, LONG2PTR (key)); + *string = __objc_xmalloc (strlen(tmp) + 1); strcpy (*string, tmp); } break; @@ -632,7 +762,7 @@ objc_read_string (struct objc_typed_stream* stream, if (len) { (*string) = (char*)__objc_xmalloc(nbytes+1); if (key) - hash_add (&stream->stream_table, (void*)key, *string); + hash_add (&stream->stream_table, LONG2PTR(key), *string); len = (*stream->read)(stream->physical, *string, nbytes); (*string)[nbytes] = '\0'; } @@ -655,12 +785,12 @@ objc_read_object (struct objc_typed_stream* stream, id* object) int len; if ((len = (*stream->read)(stream->physical, buf, 1))) { - SEL read_sel = sel_get_uid ("read:"); - unsigned int key = 0; + SEL read_sel = sel_get_any_uid ("read:"); + unsigned long key = 0; if ((buf[0]&_B_CODE) == _B_RCOMM) /* register common */ { - len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key); + len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key); len = (*stream->read)(stream->physical, buf, 1); } @@ -676,7 +806,7 @@ objc_read_object (struct objc_typed_stream* stream, id* object) /* register? */ if (key) - hash_add (&stream->object_table, (void*)key, *object); + hash_add (&stream->object_table, LONG2PTR(key), *object); /* send -read: */ if (__objc_responds_to (*object, read_sel)) @@ -692,16 +822,16 @@ objc_read_object (struct objc_typed_stream* stream, id* object) { if (key) __objc_fatal("cannot register use upcode..."); - len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key); - (*object) = hash_value_for_key (stream->object_table, (void*)key); + len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key); + (*object) = hash_value_for_key (stream->object_table, LONG2PTR(key)); } else if (buf[0] == (_B_EXT | _BX_OBJREF)) /* a forward reference */ { struct objc_list* other; - len = objc_read_unsigned_int (stream, &key); - other = (struct objc_list*)hash_value_for_key (stream->object_refs, (void*)key); - hash_add (&stream->object_refs, (void*)key, (void*)list_cons(object, other)); + len = objc_read_unsigned_long (stream, &key); + other = (struct objc_list*)hash_value_for_key (stream->object_refs, LONG2PTR(key)); + hash_add (&stream->object_refs, LONG2PTR(key), (void*)list_cons(object, other)); } else if (buf[0] == (_B_EXT | _BX_OBJROOT)) /* a root object */ @@ -725,18 +855,18 @@ objc_read_class (struct objc_typed_stream* stream, Class** class) int len; if ((len = (*stream->read)(stream->physical, buf, 1))) { - unsigned int key = 0; + unsigned long key = 0; if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */ { - len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key); + len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key); len = (*stream->read)(stream->physical, buf, 1); } if (buf[0] == (_B_EXT | _BX_CLASS)) { char* class_name; - int version; + unsigned long version; /* get class */ len = objc_read_string (stream, &class_name); @@ -745,9 +875,9 @@ objc_read_class (struct objc_typed_stream* stream, Class** class) /* register */ if (key) - hash_add (&stream->stream_table, (void*)key, *class); + hash_add (&stream->stream_table, LONG2PTR(key), *class); - objc_read_unsigned_int(stream, &version); + objc_read_unsigned_long(stream, &version); hash_add (&stream->class_table, (*class)->name, (void*)version); } @@ -755,10 +885,10 @@ objc_read_class (struct objc_typed_stream* stream, Class** class) { if (key) __objc_fatal("cannot register use upcode..."); - len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key); - (*class) = hash_value_for_key (stream->stream_table, (void*)key); + len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key); + (*class) = hash_value_for_key (stream->stream_table, LONG2PTR(key)); if (!*class) - __objc_fatal("cannot find class for key %x", key); + __objc_fatal("cannot find class for key %lu", key); } else @@ -774,11 +904,11 @@ objc_read_selector (struct objc_typed_stream* stream, SEL* selector) int len; if ((len = (*stream->read)(stream->physical, buf, 1))) { - unsigned int key = 0; + unsigned long key = 0; if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */ { - len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key); + len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key); len = (*stream->read)(stream->physical, buf, 1); } @@ -788,20 +918,20 @@ objc_read_selector (struct objc_typed_stream* stream, SEL* selector) /* get selector */ len = objc_read_string (stream, &selector_name); - (*selector) = sel_get_uid(selector_name); + (*selector) = sel_get_any_uid(selector_name); free (selector_name); /* register */ if (key) - hash_add (&stream->stream_table, (void*)key, *selector); + hash_add (&stream->stream_table, LONG2PTR(key), (void*)*selector); } else if ((buf[0]&_B_CODE) == _B_UCOMM) { if (key) __objc_fatal("cannot register use upcode..."); - len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key); - (*selector) = hash_value_for_key (stream->stream_table, (void*)key); + len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key); + (*selector) = hash_value_for_key (stream->stream_table, LONG2PTR(key)); } else @@ -810,96 +940,6 @@ objc_read_selector (struct objc_typed_stream* stream, SEL* selector) return len; } -static int -objc_sizeof_type(const char* type) -{ - switch(*type) { - case _C_ID: return sizeof(id); - break; - - case _C_CLASS: - return sizeof(Class*); - break; - - case _C_SEL: - return sizeof(SEL); - break; - - case _C_CHR: - return sizeof(char); - break; - - case _C_UCHR: - return sizeof(unsigned char); - break; - - case _C_SHT: - return sizeof(short); - break; - - case _C_USHT: - return sizeof(unsigned short); - break; - - case _C_INT: - case _C_LNG: - return sizeof(int); - break; - - case _C_UINT: - case _C_ULNG: - return sizeof(unsigned int); - break; - - case _C_ATOM: - case _C_CHARPTR: - return sizeof(char*); - break; - - default: - fprintf(stderr, "objc_sizeof_type: cannot parse typespec: %s\n", type); - abort(); - } -} - - -static const char* -__objc_skip_type (const char* type) -{ - switch (*type) { - case _C_ID: - case _C_CLASS: - case _C_SEL: - case _C_CHR: - case _C_UCHR: - case _C_CHARPTR: - case _C_ATOM: - case _C_SHT: - case _C_USHT: - case _C_INT: - case _C_UINT: - case _C_LNG: - case _C_ULNG: - case _C_FLT: - case _C_DBL: - return ++type; - break; - - case _C_ARY_B: - while(isdigit(*++type)); - type = __objc_skip_type(type); - if (*type == _C_ARY_E) - return ++type; - else - __objc_fatal("cannot parse typespec: %s", type); - break; - - default: - fprintf(stderr, "__objc_skip_type: cannot parse typespec: %s\n", type); - abort(); - } -} - /* ** USER LEVEL FUNCTIONS */ @@ -942,15 +982,21 @@ objc_write_type(TypedStream* stream, const char* type, const void* data) break; case _C_INT: - case _C_LNG: return objc_write_int(stream, *(int*)data); break; case _C_UINT: - case _C_ULNG: return objc_write_unsigned_int(stream, *(unsigned int*)data); break; + case _C_LNG: + return objc_write_long(stream, *(long*)data); + break; + + case _C_ULNG: + return objc_write_unsigned_long(stream, *(unsigned long*)data); + break; + case _C_CHARPTR: return objc_write_string (stream, *(char**)data, strlen(*(char**)data)); break; @@ -967,6 +1013,22 @@ objc_write_type(TypedStream* stream, const char* type, const void* data) } break; + case _C_STRUCT_B: + { + int acc_size = 0; + int align; + while (*type != _C_STRUCT_E && *type++ != '='); /* skip "=" */ + while (*type != _C_STRUCT_E); + { + align = objc_alignof_type (type); /* padd to alignment */ + acc_size += ROUND (acc_size, align); + objc_write_type (stream, type, ((char*)data)+acc_size); + acc_size += objc_sizeof_type (type); /* add component size */ + type = objc_skip_typespec (type); /* skip component */ + } + return 1; + } + default: fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type); abort(); @@ -1014,15 +1076,21 @@ objc_read_type(TypedStream* stream, const char* type, void* data) break; case _C_INT: - case _C_LNG: return objc_read_int (stream, (int*)data); break; case _C_UINT: - case _C_ULNG: return objc_read_unsigned_int (stream, (unsigned int*)data); break; + case _C_LNG: + return objc_read_long (stream, (long*)data); + break; + + case _C_ULNG: + return objc_read_unsigned_long (stream, (unsigned long*)data); + break; + case _C_CHARPTR: case _C_ATOM: return objc_read_string (stream, (char**)data); @@ -1036,6 +1104,22 @@ objc_read_type(TypedStream* stream, const char* type, void* data) } break; + case _C_STRUCT_B: + { + int acc_size = 0; + int align; + while (*type != _C_STRUCT_E && *type++ != '='); /* skip "=" */ + while (*type != _C_STRUCT_E); + { + align = objc_alignof_type (type); /* padd to alignment */ + acc_size += ROUND (acc_size, align); + objc_read_type (stream, type, ((char*)data)+acc_size); + acc_size += objc_sizeof_type (type); /* add component size */ + type = objc_skip_typespec (type); /* skip component */ + } + return 1; + } + default: fprintf(stderr, "objc_read_type: cannot parse typespec: %s\n", type); abort(); @@ -1061,7 +1145,7 @@ objc_write_types (TypedStream* stream, const char* type, ...) va_start(args, type); - for (c = type; *c; c = __objc_skip_type (c)) + for (c = type; *c; c = objc_skip_typespec (c)) { switch(*c) { case _C_ID: @@ -1095,15 +1179,21 @@ objc_write_types (TypedStream* stream, const char* type, ...) break; case _C_INT: - case _C_LNG: res = objc_write_int(stream, *va_arg(args, int*)); break; case _C_UINT: - case _C_ULNG: res = objc_write_unsigned_int(stream, *va_arg(args, unsigned int*)); break; + case _C_LNG: + res = objc_write_long(stream, *va_arg(args, long*)); + break; + + case _C_ULNG: + res = objc_write_unsigned_long(stream, *va_arg(args, unsigned long*)); + break; + case _C_CHARPTR: { char** str = va_arg(args, char**); @@ -1124,7 +1214,7 @@ objc_write_types (TypedStream* stream, const char* type, ...) const char* t = c; while (isdigit(*++t)); res = objc_write_array (stream, t, len, va_arg(args, void*)); - t = __objc_skip_type (t); + t = objc_skip_typespec (t); if (*t != _C_ARY_E) __objc_fatal("expected `]', got: %s", t); } @@ -1154,7 +1244,7 @@ objc_read_types(TypedStream* stream, const char* type, ...) va_start(args, type); - for (c = type; *c; c = __objc_skip_type(c)) + for (c = type; *c; c = objc_skip_typespec(c)) { switch(*c) { case _C_ID: @@ -1186,15 +1276,21 @@ objc_read_types(TypedStream* stream, const char* type, ...) break; case _C_INT: - case _C_LNG: res = objc_read_int(stream, va_arg(args, int*)); break; case _C_UINT: - case _C_ULNG: res = objc_read_unsigned_int(stream, va_arg(args, unsigned int*)); break; + case _C_LNG: + res = objc_read_long(stream, va_arg(args, long*)); + break; + + case _C_ULNG: + res = objc_read_unsigned_long(stream, va_arg(args, unsigned long*)); + break; + case _C_CHARPTR: case _C_ATOM: { @@ -1209,7 +1305,7 @@ objc_read_types(TypedStream* stream, const char* type, ...) const char* t = c; while (isdigit(*++t)); res = objc_read_array (stream, t, len, va_arg(args, void*)); - t = __objc_skip_type (t); + t = objc_skip_typespec (t); if (*t != _C_ARY_E) __objc_fatal("expected `]', got: %s", t); } @@ -1331,7 +1427,7 @@ static void __objc_finish_write_root_object(struct objc_typed_stream* stream) static void __objc_finish_read_root_object(struct objc_typed_stream* stream) { node_ptr node; - SEL awake_sel = sel_get_uid ("awake"); + SEL awake_sel = sel_get_any_uid ("awake"); /* resolve object forward references */ for (node = hash_next (stream->object_refs, NULL); node; @@ -1379,8 +1475,6 @@ static void __objc_finish_read_root_object(struct objc_typed_stream* stream) TypedStream* objc_open_typed_stream (FILE* physical, int mode) { - int fflush(FILE*); - TypedStream* s = (TypedStream*)__objc_xmalloc(sizeof(TypedStream)); s->mode = mode; @@ -1483,13 +1577,12 @@ objc_flush_typed_stream (TypedStream* stream) (*stream->flush)(stream->physical); } -int +long objc_get_stream_class_version (TypedStream* stream, Class* class) { if (stream->class_table) - return (int) hash_value_for_key (stream->class_table, class->name); + return PTR2LONG(hash_value_for_key (stream->class_table, class->name)); else return class_get_version (class); } -#endif /* __alpha__ */ diff --git a/gcc/objc/class.c b/gcc/objc/class.c index 7521ad66d200..e5a3505112ad 100644 --- a/gcc/objc/class.c +++ b/gcc/objc/class.c @@ -132,6 +132,27 @@ objc_get_class (const char *name) abort(); } +/* This function provides a way to enumerate all the classes in the + executable. Pass *ENUM_STATE == NULL to start the enumeration. The + function will return 0 when there are no more classes. + For example: + id class; + void *es = NULL; + while ((class = objc_next_class(&es))) + ... do something with class; +*/ +Class* +objc_next_class(void **enum_state) +{ + /* make sure the table is there */ + assert(__objc_class_hash); + + *(node_ptr*)enum_state = + hash_next(__objc_class_hash, *(node_ptr*)enum_state); + if (*(node_ptr*)enum_state) + return (*(node_ptr*)enum_state)->value; + return (Class*)0; +} /* Resolve super/subclass links for all classes. The only thing we can be sure of is that the class_pointer for class objects point @@ -217,6 +238,9 @@ void __objc_resolve_class_links() Class* class_pose_as (Class* impostor, Class* super_class) { + node_ptr node; + Class* class1; + if (!CLS_ISRESOLV (impostor)) __objc_resolve_class_links (); @@ -230,19 +254,13 @@ class_pose_as (Class* impostor, Class* super_class) { Class **subclass = &(super_class->subclass_list); - BOOL super_is_base_class = NO; /* move subclasses of super_class to impostor */ while (*subclass) { Class *nextSub = (*subclass)->sibling_class; - /* this happens when super_class is a base class */ - if (*subclass == CLASSOF (super_class)) - { - super_is_base_class = YES; - } - else if (*subclass != impostor) + if (*subclass != impostor) { Class *sub = *subclass; @@ -250,11 +268,18 @@ class_pose_as (Class* impostor, Class* super_class) sub->sibling_class = impostor->subclass_list; sub->super_class = impostor; impostor->subclass_list = sub; - - /* meta classes */ - CLASSOF (sub)->sibling_class = CLASSOF (impostor)->subclass_list; - CLASSOF (sub)->super_class = CLASSOF (impostor); - CLASSOF (impostor)->subclass_list = CLASSOF (sub); + + /* It will happen that SUB is not a class object if it is + the top of the meta class hierachy chain. (root + meta-class objects inherit theit class object) If that is + the case... dont mess with the meta-meta class. */ + if (CLS_ISCLASS (sub)) + { + /* meta classes */ + CLASSOF (sub)->sibling_class = CLASSOF (impostor)->subclass_list; + CLASSOF (sub)->super_class = CLASSOF (impostor); + CLASSOF (impostor)->subclass_list = CLASSOF (sub); + } } *subclass = nextSub; @@ -267,66 +292,31 @@ class_pose_as (Class* impostor, Class* super_class) /* set impostor to have no sibling classes */ impostor->sibling_class = 0; CLASSOF (impostor)->sibling_class = 0; - - /* impostor has a sibling... */ - if (super_is_base_class) - { - CLASSOF (super_class)->sibling_class = 0; - impostor->sibling_class = CLASSOF (super_class); - } } - /* check relationship of impostor and super_class */ + /* check relationship of impostor and super_class is kept. */ assert (impostor->super_class == super_class); assert (CLASSOF (impostor)->super_class == CLASSOF (super_class)); - /* by now, the re-organization of the class hierachy - is done. We only need to update various tables. */ - - /* First, we change the names in the hash table. - This will change the behavior of objc_get_class () */ - { - char* buffer = (char*) __objc_xmalloc(strlen (super_class->name) + 2); - - strcpy (buffer+1, super_class->name); - buffer[0] = '*'; + /* This is how to update the lookup table. Regardless of + what the keys of the hashtable is, change all values that are + suprecalss into impostor. */ - /* keep on prepending '*' until the name is unique */ - while (hash_value_for_key (__objc_class_hash, buffer)) - { - char *bbuffer = (char*) __objc_xmalloc (strlen (buffer)+2); - - strcpy (bbuffer+1, buffer); - bbuffer[0] = '*'; - free (buffer); - buffer = bbuffer; - } - - hash_remove (__objc_class_hash, super_class->name); - hash_add (&__objc_class_hash, buffer, super_class); - hash_add (&__objc_class_hash, super_class->name, impostor); - - /* Note that -name and +name will still respond with - the same strings as before. This way any - -isKindOfGivenName: will always work. */ - } + for (node = hash_next (__objc_class_hash, NULL); node; + node = hash_next (__objc_class_hash, node)) + { + class1 = (Class*)node->value; + if (class1 == super_class) + { + node->value = impostor; /* change hash table value */ + } + } /* next, we update the dispatch tables... */ - { - Class *subclass; - - for (subclass = impostor->subclass_list; - subclass; subclass = subclass->sibling_class) - { - /* we use the opportunity to check what we did */ - assert (subclass->super_class == impostor); - assert (CLASSOF (subclass)->super_class == CLASSOF (impostor)); - - __objc_update_dispatch_table_for_class (CLASSOF (subclass)); - __objc_update_dispatch_table_for_class (subclass); - } - } + __objc_update_dispatch_table_for_class (CLASSOF (impostor)); + __objc_update_dispatch_table_for_class (impostor); return impostor; } + diff --git a/gcc/objc/encoding.c b/gcc/objc/encoding.c index 075d2eee5cd8..479b4a1c6bfa 100644 --- a/gcc/objc/encoding.c +++ b/gcc/objc/encoding.c @@ -35,6 +35,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ({ typeof(X) __x = (X), __y = (Y); \ (__x < __y ? __x : __y); }) +#define ROUND(V, A) \ + ({ typeof(V) __v=(V); typeof(A) __a=(A); \ + __a*((__v+__a-1)/__a); }) + static inline int atoi (const char* str) @@ -121,8 +125,7 @@ objc_sizeof_type(const char* type) while (*type != _C_STRUCT_E); { align = objc_alignof_type (type); /* padd to alignment */ - if ((acc_size % align) != 0) - acc_size += align - (acc_size % align); + acc_size += ROUND (acc_size, align); acc_size += objc_sizeof_type (type); /* add component size */ type = objc_skip_typespec (type); /* skip component */ } @@ -244,11 +247,7 @@ objc_aligned_size (const char* type) { int size = objc_sizeof_type (type); int align = objc_alignof_type (type); - - if ((size % align) != 0) - return size + align - (size % align); - else - return size; + return ROUND (size, align); } /* @@ -262,10 +261,7 @@ objc_promoted_size (const char* type) int size = objc_sizeof_type (type); int wordsize = sizeof (void*); - if ((size % wordsize) != 0) - return size + wordsize - (size % wordsize); - else - return size; + return ROUND (size, wordsize); } /* diff --git a/gcc/objc/hash.c b/gcc/objc/hash.c index 2226a2630b16..e1d736abe39a 100644 --- a/gcc/objc/hash.c +++ b/gcc/objc/hash.c @@ -39,6 +39,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define EXPANSION(cache) \ ((cache)->size * 2) +void *__objc_xcalloc (size_t, size_t); + cache_ptr hash_new (unsigned int size, hash_func_type hash_func, compare_func_type compare_func) diff --git a/gcc/objc/init.c b/gcc/objc/init.c index 220d7d23e648..b41ce95ea6dc 100644 --- a/gcc/objc/init.c +++ b/gcc/objc/init.c @@ -28,7 +28,7 @@ You should have received a copy of the GNU General Public License along with /* The version number of this runtime. This must match the number defined in gcc (objc-act.c) */ -#define OBJC_VERSION 5 +#define OBJC_VERSION 6 #define PROTOCOL_VERSION 2 /* This list contains all modules currently loaded into the runtime */ @@ -49,6 +49,11 @@ static void __objc_class_add_protocols (Class*, struct objc_protocol_list*); /* Is all categories/classes resolved? */ BOOL __objc_dangling_categories = NO; +extern SEL +__sel_register_typed_name (const char *name, const char *types, + struct objc_selector *orig); + + /* This function is called by constructor functions generated for each module compiled. (_GLOBAL_$I$...) The purpose of this function is to gather the module pointers so that they may be processed by the @@ -70,7 +75,7 @@ __objc_exec_class (Module_t module) struct objc_list** cell; /* The table of selector references for this module */ - SEL *selectors = symtab->refs; + SEL selectors = symtab->refs; /* dummy counter */ int i; @@ -91,6 +96,19 @@ __objc_exec_class (Module_t module) /* Save the module pointer for later processing. (not currently used) */ __objc_module_list = list_cons(module, __objc_module_list); + /* Replace referenced selectors from names to SEL's. */ + if (selectors) + { + for (i = 0; selectors[i].sel_id; ++i) + { + const char *name, *type; + name = (char*)selectors[i].sel_id; + type = (char*)selectors[i].sel_types; + __sel_register_typed_name (name, type, + (struct objc_selector*)&(selectors[i])); + } + } + /* Parse the classes in the load module and gather selector information. */ DEBUG_PRINTF ("gathering selectors from module: %s\n", module->name); for (i = 0; i < symtab->cls_def_cnt; ++i) @@ -117,13 +135,6 @@ __objc_exec_class (Module_t module) __objc_init_protocols (class->protocols); } - /* Replace referenced selectors from names to SEL's. */ - if (selectors) - { - for (i = 0; selectors[i]; ++i) - selectors[i] = sel_register_name ((const char *) selectors[i]); - } - /* Process category information from the module. */ for (i = 0; i < symtab->cat_def_cnt; ++i) { @@ -166,7 +177,7 @@ __objc_exec_class (Module_t module) categories to objects. */ for (cell = &unclaimed_categories; *cell; - *cell && ((cell = &(*cell)->tail))) + ({ if (*cell) cell = &(*cell)->tail; })) { Category_t category = (*cell)->head; Class* class = objc_lookup_class (category->class_name); @@ -209,7 +220,7 @@ static void init_check_module_version(Module_t module) if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module))) { fprintf (stderr, "Module %s version %d doesn't match runtime %d\n", - module->name, module->version, OBJC_VERSION); + module->name, (int)module->version, OBJC_VERSION); if(module->version > OBJC_VERSION) fprintf (stderr, "Runtime (libobjc.a) is out of date\n"); else if (module->version < OBJC_VERSION) @@ -255,7 +266,7 @@ __objc_init_protocols (struct objc_protocol_list* protos) { fprintf (stderr, "Version %d doesn't match runtime protocol version %d\n", - ((size_t)protos->list[i]->class_pointer), + (int)((char*)protos->list[i]->class_pointer-(char*)0), PROTOCOL_VERSION); abort (); } diff --git a/gcc/objc/misc.c b/gcc/objc/misc.c index 6b6b34298225..7137fdacf32a 100644 --- a/gcc/objc/misc.c +++ b/gcc/objc/misc.c @@ -30,6 +30,12 @@ void objc_error(id object, const char* fmt, va_list); void (*_objc_error)(id, const char*, va_list) = objc_error; +#ifdef __alpha__ +#include +extern int write (int, const char*, int); +extern size_t strlen (const char*); +#endif + void objc_error(id object, const char* fmt, va_list ap) { @@ -40,7 +46,7 @@ objc_error(id object, const char* fmt, va_list ap) volatile void objc_fatal(const char* msg) { - write(2, msg, (size_t)strlen((char*)msg)); + write(2, msg, (int)strlen((const char*)msg)); abort(); } @@ -65,8 +71,12 @@ __objc_xrealloc(void* mem, size_t size) void* __objc_xcalloc(size_t nelem, size_t size) { - void* res = (void*)calloc(nelem, size); +#ifdef __alpha__ + extern bzero (void *, size_t); +#endif + void* res = (void*)malloc(nelem * size); if(!res) objc_fatal("Virtual memory exhausted\n"); + bzero (res, nelem * size); return res; } diff --git a/gcc/objc/objc-api.h b/gcc/objc/objc-api.h index 407793222f42..f94f9654a680 100644 --- a/gcc/objc/objc-api.h +++ b/gcc/objc/objc-api.h @@ -44,8 +44,6 @@ struct objc_method_description char *types; /* type encoding */ }; - - /* Filer types used to describe Ivars and Methods. */ #define _C_ID '@' #define _C_CLASS '#' @@ -92,7 +90,7 @@ extern BOOL objc_trace; */ typedef struct objc_symtab { unsigned long sel_ref_cnt; /* Unknown. */ - SEL *refs; /* Unknown. */ + SEL refs; /* Unknown. */ unsigned short cls_def_cnt; /* Number of classes compiled (defined) in the module. */ unsigned short cat_def_cnt; /* Number of categories @@ -146,7 +144,7 @@ typedef struct objc_ivar_list { const char* ivar_type; /* Description of the Ivar's type. Useful for debuggers. */ - int ivar_offset; /* Byte offset from the base + int ivar_offset; /* Byte offset from the base address of the instance structure to the variable. */ @@ -169,7 +167,7 @@ typedef struct objc_method_list { struct objc_method_list* method_next; /* This variable is used to link a method list to another. It is a singly linked list. */ - int method_count; /* Number of methods defined in + int method_count; /* Number of methods defined in this structure. */ struct objc_method { SEL method_name; /* This variable is the method's @@ -303,12 +301,23 @@ Class* objc_get_class(const char *name); Class* objc_lookup_class(const char *name); +Class* objc_next_class(void **enum_state); + const char *sel_get_name(SEL selector); +const char *sel_get_type(SEL selector); + SEL sel_get_uid(const char *name); +SEL sel_get_any_uid(const char *name); + +SEL sel_get_typed_uid(const char *name, const char*); + SEL sel_register_name(const char *name); +SEL sel_register_typed_name(const char *name, const char*type); + + BOOL sel_is_mapped (SEL aSel); extern id class_create_instance(Class* class); diff --git a/gcc/objc/objc.h b/gcc/objc/objc.h index a777a9f90b57..85d05852d459 100644 --- a/gcc/objc/objc.h +++ b/gcc/objc/objc.h @@ -40,12 +40,24 @@ typedef char BOOL; #define NO (BOOL)0 /* -** Definition of a selector. Selectors are really of type unsigned int. -** The runtime does this mapping from SEL's to names internally in the -** sel_... operations. You should never use the fact that it is actually -** an integer, since other Objective-C implementations use other conventions. +** Definition of a selector. Selectors themselves are not unique, but +** the sel_id is a unique identifier. */ -typedef void* SEL; +typedef const struct objc_selector +{ + void *sel_id; + const char *sel_types; +} *SEL; + +inline static BOOL +sel_eq (SEL s1, SEL s2) +{ + if (s1 == 0 || s2 == 0) + return s1 == s2; + else + return s1->sel_id == s2->sel_id; +} + /* ** ObjC uses this typedef for untyped instances. @@ -131,36 +143,8 @@ typedef union { } *arglist_t; /* argument frame */ -#if defined(__OBJC__) -#include "objc/sarray.h" - -/* - This is the function called when messages are send to nil. You may - set a breakpoint in your debugger at this function to catch messages - too nil. -*/ -extern id nil_method(id rcv, SEL op, ...); - -/* - The messager is inlined, thus it is defined here directly. The - inlining is quite time-consuming when optimizing. This will be - taken care of later by hand-coding the messager in the compiler. -*/ -extern __inline__ IMP -objc_msg_lookup(id receiver, SEL op) -{ - if(receiver) - return sarray_get(receiver->class_pointer->dtable, (size_t)(op)); - else - return nil_method; -} - -#else - IMP objc_msg_lookup(id receiver, SEL op); -#endif - #ifdef __cplusplus } #endif diff --git a/gcc/objc/objects.c b/gcc/objc/objects.c index dd4820acf716..aad1610e4ce5 100644 --- a/gcc/objc/objects.c +++ b/gcc/objc/objects.c @@ -43,7 +43,7 @@ class_create_instance(Class* class) new = (*_objc_object_alloc)(class); if (new!=nil) { - bzero (new, class->instance_size); + memchr (new, 0, class->instance_size); new->class_pointer = class; } return new; diff --git a/gcc/objc/runtime.h b/gcc/objc/runtime.h index aee2b93964c1..224c44900111 100644 --- a/gcc/objc/runtime.h +++ b/gcc/objc/runtime.h @@ -61,12 +61,14 @@ extern BOOL __objc_class_links_resolved; extern int __objc_selector_max_index; #ifdef DEBUG -#define DEBUG_PRINTF printf +#define DEBUG_PRINTF(format, args...) printf (format, ## args) #else -#define DEBUG_PRINTF +#define DEBUG_PRINTF(format, args...) #endif BOOL __objc_responds_to (id object, SEL sel); /* for internal use only! */ +SEL __sel_register_typed_name (const char*, const char*, + struct objc_selector*); #endif /* not __objc_runtime_INCLUDE_GNU */ diff --git a/gcc/objc/sarray.c b/gcc/objc/sarray.c index e3b322ae0099..78f5339596a1 100644 --- a/gcc/objc/sarray.c +++ b/gcc/objc/sarray.c @@ -40,6 +40,11 @@ const char* __objc_sparse2_id = "2 level sparse indices"; const char* __objc_sparse3_id = "3 level sparse indices"; #endif +#ifdef __alpha__ +const void *memcpy (void*, const void*, size_t); +void free (const void*); +#endif + void sarray_at_put(struct sarray* array, sidx index, void* element) { @@ -117,7 +122,7 @@ sarray_at_put(struct sarray* array, sidx index, void* element) /* The bucket was previously empty (or something like that), */ /* allocate a new. This is the effect of `lazy' allocation */ *the_bucket = (struct sbucket*)__objc_xmalloc(sizeof(struct sbucket)); - memcpy( *the_bucket,array->empty_bucket, sizeof(struct sbucket)); + memcpy((void *) *the_bucket, (const void*)array->empty_bucket, sizeof(struct sbucket)); (*the_bucket)->version = array->version; nbuckets += 1; diff --git a/gcc/objc/selector.c b/gcc/objc/selector.c index 40bc7a338c32..284967b26406 100644 --- a/gcc/objc/selector.c +++ b/gcc/objc/selector.c @@ -31,7 +31,8 @@ You should have received a copy of the GNU General Public License along with #define SELECTOR_HASH_SIZE 128 /* Tables mapping selector names to uid and opposite */ -static struct sarray* __objc_selector_array = 0; /* uid -> name */ +static struct sarray* __objc_selector_array = 0; /* uid -> sel */ +static struct sarray* __objc_selector_names = 0; /* uid -> name */ static cache_ptr __objc_selector_hash = 0; /* name -> uid */ static void register_selectors_from_list(MethodList_t); @@ -42,6 +43,7 @@ int __objc_selector_max_index = 0; void __objc_init_selector_tables() { __objc_selector_array = sarray_new (SELECTOR_HASH_SIZE, 0); + __objc_selector_names = sarray_new (SELECTOR_HASH_SIZE, 0); __objc_selector_hash = hash_new (SELECTOR_HASH_SIZE, (hash_func_type) hash_string, @@ -78,16 +80,67 @@ register_selectors_from_list (MethodList_t method_list) while (i < method_list->method_count) { Method_t method = &method_list->method_list[i]; - method->method_name = sel_register_name ((char*)method->method_name); + method->method_name + = sel_register_typed_name ((const char*)method->method_name, + method->method_types); i += 1; } } +/* return selector representing name */ +SEL +sel_get_typed_uid (const char *name, const char *types) +{ + struct objc_list *l; + sidx i; + + i = (sidx) hash_value_for_key (__objc_selector_hash, name); + if (i == 0) + return 0; + + for (l = (struct objc_list*)sarray_get (__objc_selector_array, i); + l; l = l->tail) + { + SEL s = (SEL)l->head; + if (types == 0 || s->sel_types == 0) + { + if (s->sel_types == types) + { + return s; + } + } + else if (! strcmp (s->sel_types, types)) + { + return s; + } + } + + return 0; +} + +/* return selector representing name */ +SEL +sel_get_any_uid (const char *name) +{ + struct objc_list *l; + sidx i; + + i = (sidx) hash_value_for_key (__objc_selector_hash, name); + if (soffset_decode (i) == 0) + return 0; + + l = (struct objc_list*)sarray_get (__objc_selector_array, i); + if (l == 0) + return 0; + + return (SEL)l->head; +} + /* return selector representing name */ SEL sel_get_uid (const char *name) { - return (SEL) hash_value_for_key (__objc_selector_hash, name); + return sel_register_typed_name (name, 0); } /* Get name of selector. If selector is unknown, the empty string "" @@ -95,45 +148,123 @@ sel_get_uid (const char *name) const char* sel_get_name (SEL selector) { - if ((soffset_decode((sidx)selector) > 0) - && (soffset_decode((sidx)selector) <= __objc_selector_max_index)) - return sarray_get (__objc_selector_array, (sidx) selector); + if ((soffset_decode((sidx)selector->sel_id) > 0) + && (soffset_decode((sidx)selector->sel_id) <= __objc_selector_max_index)) + return sarray_get (__objc_selector_array, (sidx) selector->sel_id); else - return NULL; + return 0; } BOOL sel_is_mapped (SEL selector) { - unsigned int idx = soffset_decode ((sidx)selector); + unsigned int idx = soffset_decode ((sidx)selector->sel_id); return ((idx > 0) && (idx <= __objc_selector_max_index)); } + +const char* +sel_get_type (SEL selector) +{ + if (selector) + return selector->sel_types; + else + return 0; +} + /* The uninstalled dispatch table */ extern struct sarray* __objc_uninstalled_dtable; /* Store the passed selector name in the selector record and return its selector value (value returned by sel_get_uid). */ SEL -sel_register_name (const char *sel) +__sel_register_typed_name (const char *name, const char *types, + struct objc_selector *orig) { - SEL j; + struct objc_selector* j; sidx i; + struct objc_list *l; - if ((j = sel_get_uid ((const char *) sel))) - return j; - - /* Save the selector name. */ - __objc_selector_max_index += 1; - i = soffset_encode(__objc_selector_max_index); + i = (sidx) hash_value_for_key (__objc_selector_hash, name); + if (soffset_decode (i) != 0) + { + for (l = (struct objc_list*)sarray_get (__objc_selector_array, i); + l; l = l->tail) + { + SEL s = (SEL)l->head; + if (types == 0 || s->sel_types == 0) + { + if (s->sel_types == types) + { + if (orig) + { + orig->sel_id = (void*)i; + return orig; + } + else + return s; + } + } + else if (strcmp (s->sel_types, types)) + { + if (orig) + { + orig->sel_id = (void*)i; + return orig; + } + else + return s; + } + } + if (orig) + j = orig; + else + j = __objc_xmalloc (sizeof (struct objc_selector)); - DEBUG_PRINTF ("Record selector %s as: %#x\n", sel, i); + j->sel_id = (void*)i; + j->sel_types = (const char*)types; + l = (struct objc_list*)sarray_get (__objc_selector_array, i); + } + else + { + __objc_selector_max_index += 1; + i = soffset_encode(__objc_selector_max_index); + if (orig) + j = orig; + else + j = __objc_xmalloc (sizeof (struct objc_selector)); + + j->sel_id = (void*)i; + j->sel_types = (const char*)types; + l = 0; + } - sarray_at_put_safe (__objc_selector_array, i, (void *) sel); - hash_add (&__objc_selector_hash, (void *) sel, (void *) i); + DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types, + soffset_decode (i)); + + { + int is_new = (l == 0); + l = list_cons ((void*)j, l); + sarray_at_put_safe (__objc_selector_names, i, (void *) name); + sarray_at_put_safe (__objc_selector_array, i, (void *) l); + if (is_new) + hash_add (&__objc_selector_hash, (void *) name, (void *) i); + } sarray_realloc(__objc_uninstalled_dtable, __objc_selector_max_index+1); - return (SEL) i; + return (SEL) j; +} + +SEL +sel_register_name (const char *name) +{ + return __sel_register_typed_name (name, 0, 0); +} + +SEL +sel_register_typed_name (const char *name, const char *type) +{ + return __sel_register_typed_name (name, type, 0); } diff --git a/gcc/objc/sendmsg.c b/gcc/objc/sendmsg.c index 01a1b1363313..442ea0fc5ebc 100644 --- a/gcc/objc/sendmsg.c +++ b/gcc/objc/sendmsg.c @@ -24,10 +24,21 @@ You should have received a copy of the GNU General Public License along with however invalidate any other reasons why the executable file might be covered by the GNU General Public License. */ +#include "../tconfig.h" #include "runtime.h" #include "sarray.h" #include "encoding.h" +/* this is how we hack STRUCT_VALUE to be 1 or 0 */ +#define gen_rtx(args...) 1 +#define rtx int + +#if STRUCT_VALUE == 0 +#define INVISIBLE_STRUCT_RETURN 1 +#else +#define INVISIBLE_STRUCT_RETURN 0 +#endif + /* The uninstalled dispatch table */ struct sarray* __objc_uninstalled_dtable = 0; @@ -38,7 +49,14 @@ static void __objc_install_dispatch_table_for_class (Class*); /* Forward declare some functions */ static void __objc_init_install_dtable(id, SEL); -static id __objc_missing_method(id, SEL, ...); +static id __objc_word_forward(id, SEL, ...); +typedef struct { id many[8]; } __big; +#if INVISIBLE_STRUCT_RETURN +static __big +#else +static id +#endif +__objc_block_forward(id, SEL, ...); static Method_t search_for_method_in_hierarchy (Class* class, SEL sel); static Method_t search_for_method_in_list(MethodList_t list, SEL op); id nil_method(id, SEL, ...); @@ -53,16 +71,34 @@ nil_method(id receiver, SEL op, ...) __inline__ IMP get_imp (Class* class, SEL sel) { - void* res = sarray_get (class->dtable, (size_t) sel); + IMP impl; + void* res = sarray_get (class->dtable, (size_t) sel->sel_id); if(res == __objc_init_install_dtable) - __objc_install_dispatch_table_for_class (class); - return sarray_get (class->dtable, (size_t) sel); + { + __objc_install_dispatch_table_for_class (class); + res = sarray_get (class->dtable, (size_t) sel->sel_id); + } + if (res == 0) + { + const char *t = sel->sel_types; + if (t && (*t == '[' || *t == '(' || *t == '{')) + res = (IMP)__objc_block_forward; + else + res = (IMP)__objc_word_forward; + } + return res; } __inline__ BOOL __objc_responds_to (id object, SEL sel) { - return get_imp (object->class_pointer, sel) != __objc_missing_method; + void* res = sarray_get (object->class_pointer->dtable, (size_t) sel->sel_id); + if(res == __objc_init_install_dtable) + { + __objc_install_dispatch_table_for_class (object->class_pointer); + res = sarray_get (object->class_pointer->dtable, (size_t) sel->sel_id); + } + return (res != 0); } /* This is the lookup function. All entries in the table are either a @@ -72,8 +108,20 @@ __objc_responds_to (id object, SEL sel) __inline__ IMP objc_msg_lookup(id receiver, SEL op) { + IMP result; if(receiver) - return sarray_get(receiver->class_pointer->dtable, (sidx)op); + { + result = sarray_get(receiver->class_pointer->dtable, (sidx)op->sel_id); + if (result == 0) + { + const char *t = op->sel_types; + if (t && (*t == '[' || *t == '(' || *t == '{')) + result = (IMP)__objc_block_forward; + else + result = (IMP)__objc_word_forward; + } + return result; + } else return nil_method; } @@ -87,6 +135,8 @@ objc_msg_lookup_super (Super_t super, SEL sel) return nil_method; } +int method_get_sizeof_arguments (Method*); + retval_t objc_msg_sendv(id object, SEL op, arglist_t arg_frame) { @@ -141,8 +191,8 @@ static void __objc_init_install_dtable(id receiver, SEL op) /* Install real dtable for factory methods */ __objc_install_dispatch_table_for_class (receiver->class_pointer); - - if(op != sel_get_uid ("initialize")) + + if (strcmp (sel_get_name (op), "initialize")) __objc_send_initialize((Class*)receiver); else CLS_SETINITIALIZED((Class*)receiver); @@ -155,7 +205,10 @@ allready_initialized: args = __builtin_apply_args(); result = __builtin_apply((apply_t)imp, args, 96); - __builtin_return (result); + if (result) + __builtin_return (result); + else + return; } @@ -170,8 +223,6 @@ void __objc_install_premature_dtable(Class* class) /* Send +initialize to class if not already done */ static void __objc_send_initialize(Class* class) { - Method_t m; - /* This *must* be a class object */ assert(CLS_ISCLASS(class)); assert(!CLS_ISMETA(class)); @@ -199,7 +250,7 @@ static void __objc_send_initialize(Class* class) Method_t method = &method_list->method_list[i]; - if (method->method_name == op) + if (method->method_name->sel_id == op->sel_id) (*method->method_imp)((id) class, op); } @@ -231,8 +282,7 @@ __objc_install_dispatch_table_for_class (Class* class) /* Allocate dtable if nessecary */ if (super == 0) { - class->dtable = sarray_new (__objc_selector_max_index, - __objc_missing_method); + class->dtable = sarray_new (__objc_selector_max_index, 0); } else class->dtable = sarray_lazy_copy (super->dtable); @@ -244,7 +294,7 @@ __objc_install_dispatch_table_for_class (Class* class) { Method_t method = &(mlist->method_list[counter]); sarray_at_put_safe (class->dtable, - (sidx) method->method_name, + (sidx) method->method_name->sel_id, method->method_imp); counter -= 1; } @@ -254,7 +304,6 @@ __objc_install_dispatch_table_for_class (Class* class) void __objc_update_dispatch_table_for_class (Class* class) { Class* next; - struct sarray* save; /* not yet installed -- skip it */ if (class->dtable == __objc_uninstalled_dtable) @@ -297,10 +346,12 @@ class_add_method_list (Class* class, MethodList_t list) if (method->method_name) /* Sometimes these are NULL */ { /* This is where selector names are transmogriffed to SEL's */ - method->method_name = sel_register_name ((char*)method->method_name); + method->method_name = + sel_register_typed_name ((const char*)method->method_name, + method->method_types); if (search_for_method_in_list (class->methods, method->method_name) - && method->method_name != initialize_sel) + && method->method_name->sel_id != initialize_sel->sel_id) { /* Duplication. Print a error message an change the method name to NULL. */ @@ -375,7 +426,7 @@ search_for_method_in_list (MethodList_t list, SEL op) Method_t method = &method_list->method_list[i]; if (method->method_name) - if (method->method_name == op) + if (method->method_name->sel_id == op->sel_id) return method; } @@ -387,40 +438,71 @@ search_for_method_in_list (MethodList_t list, SEL op) return NULL; } +static retval_t __objc_forward (id object, SEL sel, arglist_t args); + +static id +__objc_word_forward (id rcv, SEL op, ...) +{ + void *args, *res; + + args = __builtin_apply_args (); + res = __objc_forward (rcv, op, args); + if (res) + __builtin_return (res); + else + return res; +} + +#if INVISIBLE_STRUCT_RETURN +static __big +#else +static id +#endif +__objc_block_forward (id rcv, SEL op, ...) +{ + void *args, *res; + + args = __builtin_apply_args (); + res = __objc_forward (rcv, op, args); + if (res) + __builtin_return (res); +} + /* This fuction is installed in the dispatch table for all methods which are not implemented. Thus, it is called when a selector is not recognized. */ -static id -__objc_missing_method (id object, SEL sel, ...) +static retval_t +__objc_forward (id object, SEL sel, arglist_t args) { IMP imp; - SEL frwd_sel; + static SEL frwd_sel = 0; SEL err_sel; /* first try if the object understands forward:: */ - frwd_sel = sel_get_uid("forward::"); - imp = get_imp(object->class_pointer, frwd_sel); - if(imp != __objc_missing_method) + if (!frwd_sel) + frwd_sel = sel_get_any_uid("forward::"); + + if (__objc_responds_to (object, frwd_sel)) { - void *result, *args = __builtin_apply_args(); - result = (*imp)(object, frwd_sel, sel, args); - __builtin_return(result); + imp = get_imp(object->class_pointer, frwd_sel); + return (*imp)(object, frwd_sel, sel, args); } /* If the object recognizes the doesNotRecognize: method then we're going to send it. */ - err_sel = sel_get_uid ("doesNotRecognize:"); - imp = get_imp (object->class_pointer, err_sel); - if (imp != __objc_missing_method) + err_sel = sel_get_any_uid ("doesNotRecognize:"); + if (__objc_responds_to (object, err_sel)) { + imp = get_imp (object->class_pointer, err_sel); return (*imp) (object, err_sel, sel); } /* The object doesn't recognize the method. Check for responding to error:. If it does then sent it. */ { - char msg[256 + strlen ((char*)sel_get_name (sel)) - + strlen ((char*)object->class_pointer->name)]; + size_t strlen (const char*); + char msg[256 + strlen ((const char*)sel_get_name (sel)) + + strlen ((const char*)object->class_pointer->name)]; sprintf (msg, "(%s) %s does not recognize %s", (CLS_ISMETA(object->class_pointer) @@ -428,10 +510,12 @@ __objc_missing_method (id object, SEL sel, ...) : "instance" ), object->class_pointer->name, sel_get_name (sel)); - err_sel = sel_get_uid ("error:"); - imp = get_imp (object->class_pointer, err_sel); - if (imp != __objc_missing_method) - return (*imp) (object, sel_get_uid ("error:"), msg); + err_sel = sel_get_any_uid ("error:"); + if (__objc_responds_to (object, err_sel)) + { + imp = get_imp (object->class_pointer, err_sel); + return (*imp) (object, sel_get_any_uid ("error:"), msg); + } /* The object doesn't respond to doesNotRecognize: or error:; Therefore, a default action is taken. */ @@ -451,12 +535,12 @@ void __objc_print_dtable_stats() #endif ); - printf("arrays: %d = %d bytes\n", narrays, narrays*sizeof(struct sarray)); + printf("arrays: %d = %ld bytes\n", narrays, (int)narrays*sizeof(struct sarray)); total += narrays*sizeof(struct sarray); - printf("buckets: %d = %d bytes\n", nbuckets, nbuckets*sizeof(struct sbucket)); + printf("buckets: %d = %ld bytes\n", nbuckets, (int)nbuckets*sizeof(struct sbucket)); total += nbuckets*sizeof(struct sbucket); - printf("idxtables: %d = %d bytes\n", idxsize, idxsize*sizeof(void*)); + printf("idxtables: %d = %ld bytes\n", idxsize, (int)idxsize*sizeof(void*)); total += idxsize*sizeof(void*); printf("-----------------------------------\n"); printf("total: %d bytes\n", total); diff --git a/gcc/objc/typedstream.h b/gcc/objc/typedstream.h index ae4305afcb34..f3d7cd987cb9 100644 --- a/gcc/objc/typedstream.h +++ b/gcc/objc/typedstream.h @@ -30,8 +30,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "objc/hash.h" #include -#ifndef __alpha__ /* alpha is currently not supported */ - typedef int (*objc_typed_read_func)(void*, char*, int); typedef int (*objc_typed_write_func)(void*, const char*, int); typedef int (*objc_typed_flush_func)(void*); @@ -100,7 +98,7 @@ int objc_read_types (TypedStream* stream, const char* type, ...); int objc_write_object_reference (TypedStream* stream, id object); int objc_write_root_object (TypedStream* stream, id object); -int objc_get_stream_class_version (TypedStream* stream, Class* class); +long objc_get_stream_class_version (TypedStream* stream, Class* class); /* @@ -130,6 +128,4 @@ void objc_close_typed_stream (TypedStream* stream); BOOL objc_end_of_typed_stream (TypedStream* stream); void objc_flush_typed_stream (TypedStream* stream); -#endif /* __alpha__ */ - #endif /* not __typedstream_INCLUDE_GNU */ -- 2.43.5