1 /* This file "renames" various ObjC GNU runtime entry points
2 (and fakes the existence of several others)
3 if the NeXT runtime is being used. */
4 /* Authors: Ziemowit Laski <zlaski@apple.com> */
5 /* David Ayers <d.ayers@inode.at> */
6 /* Darwin 64bit/OBJC2 modifications Iain Sandoe */
8 #ifndef __NEXT_RUNTIME__
10 #define CLASSPTRFIELD(x) (x)->class_pointer
13 /* Includes next-abi.h to set NEXT_OBJC_USE_NEW_INTERFACE etc.*/
14 #ifndef _OBJC_OBJECT1_H_
17 #include <objc/objc-class.h>
22 #define objc_get_class(C) objc_getClass(C)
23 #define objc_get_meta_class(C) objc_getMetaClass(C)
24 #define class_get_class_method(C, S) class_getClassMethod(C, S)
25 #define class_get_instance_method(C, S) class_getInstanceMethod(C, S)
26 #define sel_get_name(S) sel_getName(S)
27 #define class_create_instance(C) class_createInstance(C, 0)
28 #define class_get_class_name(C) object_getClassName(C)
30 #define CLASSPTRFIELD(x) (x)->isa
32 #ifdef NEXT_OBJC_USE_NEW_INTERFACE
33 # define object_class_name(O) (object_getClassName(O))
34 # define object_get_class(O) (object_getClass((id)O))
35 # define object_get_super_class(O) class_get_super_class(object_get_class(O))
36 # define object_is_class(O) class_is_meta_class(object_get_class(O))
37 # define object_is_meta_class(O) (object_is_class(O) && class_is_meta_class(O) \
38 && class_is_meta_class(object_get_class(O)))
40 # define method_get_imp(M) (method_getImplementation((Method)M))
41 # define method_get_types(M) (method_getTypeEncoding((Method)M))
43 # define class_get_super_class(C) (class_getSuperclass((Class)C))
44 # define class_is_meta_class(C) (class_isMetaClass((Class)C) ? YES: NO)
45 # define class_is_class(C) (class_is_meta_class(C) == NO)
48 # define object_class_name(O) (O->name)
49 # define object_get_super_class(O) class_get_super_class(*(struct objc_class **)O)
50 # define object_get_class(O) (*(struct objc_class **)O)
51 # define object_is_class(O) class_is_meta_class(*(struct objc_class **)O)
52 # define object_is_meta_class(O) (class_is_meta_class(O) && class_is_meta_class(*(struct objc_class **)O))
54 # define method_get_imp(M) (((Method)M)->method_imp)
55 # define method_get_types(M) (((Method)M)->method_types)
57 # define class_get_super_class(C) (((struct objc_class *)C)->super_class)
58 # define class_is_meta_class(C) (CLS_GETINFO((struct objc_class *)C, CLS_META)? YES: NO)
59 # define class_is_class(C) (CLS_GETINFO((struct objc_class *)C, CLS_CLASS)? YES: NO)
62 #define objc_lookup_class(N) objc_lookUpClass(N)
64 /* You need either an empty +initialize method or an empty -forward:: method.
65 The NeXT runtime unconditionally sends +initialize to classes when they are
66 first used, and unconditionally tries to forward methods that the class
67 doesn't understand (including +initialize). If you have neither +initialize
68 nor -forward::, the runtime complains.
70 The simplest workaround is to add
72 + initialize { return self; }
74 to every root class @implementation. */
80 /* The following is necessary to "cover" the bf*.m test cases on NeXT. */
87 # define MAX(X, Y) ((X > Y) ? X : Y)
88 # define MIN(X, Y) ((X < Y) ? X : Y)
89 # define ROUND(V, A) (A * ((V + A - 1) / A))
92 ({ typeof (X) __x = (X), __y = (Y); \
93 (__x > __y ? __x : __y); })
95 ({ typeof (X) __x = (X), __y = (Y); \
96 (__x < __y ? __x : __y); })
97 # define ROUND(V, A) \
98 ({ typeof (V) __v = (V); typeof (A) __a = (A); \
99 __a * ((__v+__a - 1)/__a); })
102 #define BITS_PER_UNIT __CHAR_BIT__
103 typedef struct{ char a; } __small_struct;
104 #define STRUCTURE_SIZE_BOUNDARY (BITS_PER_UNIT * sizeof (__small_struct))
106 /* Not sure why the following are missing from NeXT objc headers... */
109 #define _C_LNG_LNG 'q'
112 #define _C_ULNG_LNG 'Q'
125 #define _C_BYCOPY 'O'
127 #define _C_ONEWAY 'V'
128 #define _C_GCINVISIBLE '!'
130 #define _F_CONST 0x01
133 #define _F_INOUT 0x03
134 #define _F_BYCOPY 0x04
135 #define _F_BYREF 0x08
136 #define _F_ONEWAY 0x10
137 #define _F_GCINVISIBLE 0x20
139 struct objc_struct_layout
141 const char *original_type;
143 const char *prev_type;
144 unsigned int record_size;
145 unsigned int record_align;
148 typedef union arglist {
150 char arg_regs[sizeof (char*)];
151 } *arglist_t; /* argument frame */
153 const char *objc_skip_typespec (const char *type);
154 void objc_layout_structure_get_info (struct objc_struct_layout *layout,
155 unsigned int *offset, unsigned int *align, const char **type);
156 void objc_layout_structure (const char *type,
157 struct objc_struct_layout *layout);
158 BOOL objc_layout_structure_next_member (struct objc_struct_layout *layout);
159 void objc_layout_finish_structure (struct objc_struct_layout *layout,
160 unsigned int *size, unsigned int *align);
161 int objc_aligned_size (const char *type);
164 return the size of an object specified by type
168 objc_sizeof_type (const char *type)
170 /* Skip the variable name if any */
173 for (type++; *type++ != '"';)
183 return sizeof (Class);
191 return sizeof (char);
195 return sizeof (unsigned char);
199 return sizeof (short);
203 return sizeof (unsigned short);
211 return sizeof (unsigned int);
215 return sizeof (long);
219 return sizeof (unsigned long);
223 return sizeof (long long);
227 return sizeof (unsigned long long);
231 return sizeof (float);
235 return sizeof (double);
241 return sizeof (char *);
246 int len = atoi (type + 1);
247 while (isdigit ((unsigned char)*++type))
249 return len * objc_aligned_size (type);
255 /* The NeXT encoding of bitfields is _still_: b 'size' */
256 int size = atoi (type + 1);
257 /* Return an upper bound on byte size */
258 return (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
263 struct objc_struct_layout layout;
266 objc_layout_structure (type, &layout);
267 while (objc_layout_structure_next_member (&layout))
269 objc_layout_finish_structure (&layout, &size, NULL);
277 while (*type != _C_UNION_E && *type++ != '=')
279 while (*type != _C_UNION_E)
281 /* Skip the variable name if any */
284 for (type++; *type++ != '"';)
287 max_size = MAX (max_size, objc_sizeof_type (type));
288 type = objc_skip_typespec (type);
293 return 0; /* error */
298 Return the alignment of an object specified by type
302 objc_alignof_type (const char *type)
304 /* Skip the variable name if any */
307 for (type++; *type++ != '"';)
312 return __alignof__ (id);
316 return __alignof__ (Class);
320 return __alignof__ (SEL);
324 return __alignof__ (char);
328 return __alignof__ (unsigned char);
332 return __alignof__ (short);
336 return __alignof__ (unsigned short);
340 case _C_BFLD: /* This is for the NeXT only */
341 return __alignof__ (int);
345 return __alignof__ (unsigned int);
349 return __alignof__ (long);
353 return __alignof__ (unsigned long);
357 return __alignof__ (long long);
361 return __alignof__ (unsigned long long);
365 return __alignof__ (float);
369 return __alignof__ (double);
375 return __alignof__ (char *);
379 while (isdigit ((unsigned char)*++type))
381 return objc_alignof_type (type);
385 struct objc_struct_layout layout;
388 objc_layout_structure (type, &layout);
389 while (objc_layout_structure_next_member (&layout))
391 objc_layout_finish_structure (&layout, NULL, &align);
399 while (*type != _C_UNION_E && *type++ != '=')
401 while (*type != _C_UNION_E)
403 /* Skip the variable name if any */
406 for (type++; *type++ != '"';)
409 maxalign = MAX (maxalign, objc_alignof_type (type));
410 type = objc_skip_typespec (type);
415 return 0; /* error */
419 The aligned size if the size rounded up to the nearest alignment.
423 objc_aligned_size (const char *type)
427 /* Skip the variable name */
430 for (type++; *type++ != '"';)
434 size = objc_sizeof_type (type);
435 align = objc_alignof_type (type);
437 return ROUND (size, align);
441 The size rounded up to the nearest integral of the wordsize, taken
442 to be the size of a void *.
446 objc_promoted_size (const char *type)
450 /* Skip the variable name */
453 for (type++; *type++ != '"';)
457 size = objc_sizeof_type (type);
458 wordsize = sizeof (void *);
460 return ROUND (size, wordsize);
464 Skip type qualifiers. These may eventually precede typespecs
465 occurring in method prototype encodings.
469 objc_skip_type_qualifiers (const char *type)
471 while (*type == _C_CONST
475 || *type == _C_BYCOPY
477 || *type == _C_ONEWAY
478 || *type == _C_GCINVISIBLE)
487 Skip one typespec element. If the typespec is prepended by type
488 qualifiers, these are skipped as well.
492 objc_skip_typespec (const char *type)
494 /* Skip the variable name if any */
497 for (type++; *type++ != '"';)
501 type = objc_skip_type_qualifiers (type);
506 /* An id may be annotated by the actual type if it is known
507 with the @"ClassName" syntax */
513 while (*++type != '"')
518 /* The following are one character type codes */
541 /* skip digits, typespec and closing ']' */
543 while (isdigit ((unsigned char)*++type))
545 type = objc_skip_typespec (type);
546 if (*type == _C_ARY_E)
552 /* The NeXT encoding for bitfields is _still_: b 'size' */
553 while (isdigit ((unsigned char)*++type))
554 ; /* skip type and size */
558 /* skip name, and elements until closing '}' */
560 while (*type != _C_STRUCT_E && *type++ != '=')
562 while (*type != _C_STRUCT_E)
564 type = objc_skip_typespec (type);
569 /* skip name, and elements until closing ')' */
571 while (*type != _C_UNION_E && *type++ != '=')
573 while (*type != _C_UNION_E)
575 type = objc_skip_typespec (type);
580 /* Just skip the following typespec */
582 return objc_skip_typespec (++type);
584 return 0; /* error */
588 Skip an offset as part of a method encoding. This is prepended by a
589 '+' if the argument is passed in registers.
592 objc_skip_offset (const char *type)
596 while (isdigit ((unsigned char) *++type))
602 Skip an argument specification of a method encoding.
605 objc_skip_argspec (const char *type)
607 type = objc_skip_typespec (type);
608 type = objc_skip_offset (type);
612 #ifdef NEXT_OBJC_USE_NEW_INTERFACE
615 typedef struct objc_method *PMETH;
619 Return the number of arguments that the method MTH expects.
620 Note that all methods need two implicit arguments `self' and
624 method_get_number_of_arguments (PMETH mth)
627 #ifdef NEXT_OBJC_USE_NEW_INTERFACE
628 const char *type = method_getTypeEncoding((Method)mth);
630 const char *type = mth->method_types;
634 type = objc_skip_argspec (type);
641 Return the size of the argument block needed on the stack to invoke
642 the method MTH. This may be zero, if all arguments are passed in
647 method_get_sizeof_arguments (PMETH mth)
649 #ifdef NEXT_OBJC_USE_NEW_INTERFACE
650 const char *type = objc_skip_typespec (method_getTypeEncoding((Method)mth));
652 const char *type = objc_skip_typespec (mth->method_types);
658 Return a pointer to the next argument of ARGFRAME. type points to
659 the last argument. Typical use of this look like:
663 for (datum = method_get_first_argument (method, argframe, &type);
664 datum; datum = method_get_next_argument (argframe, &type))
666 unsigned flags = objc_get_type_qualifiers (type);
667 type = objc_skip_type_qualifiers (type);
669 [portal encodeData: datum ofType: type];
672 if ((flags & _F_IN) == _F_IN)
673 [portal encodeData: *(char **) datum ofType: ++type];
680 method_get_next_argument (arglist_t argframe, const char **type)
682 const char *t = objc_skip_argspec (*type);
688 t = objc_skip_typespec (t);
691 return argframe->arg_regs + atoi (++t);
693 return argframe->arg_ptr + atoi (t);
697 Return a pointer to the value of the first argument of the method
698 described in M with the given argumentframe ARGFRAME. The type
699 is returned in TYPE. type must be passed to successive calls of
700 method_get_next_argument.
703 method_get_first_argument (PMETH m,
707 #ifdef NEXT_OBJC_USE_NEW_INTERFACE
708 *type = method_getTypeEncoding((Method)m);
710 *type = m->method_types;
713 return method_get_next_argument (argframe, type);
717 Return a pointer to the ARGth argument of the method
718 M from the frame ARGFRAME. The type of the argument
719 is returned in the value-result argument TYPE
723 method_get_nth_argument (PMETH m,
724 arglist_t argframe, int arg,
727 #ifdef NEXT_OBJC_USE_NEW_INTERFACE
728 const char *t = objc_skip_argspec (method_getTypeEncoding((Method)m));
730 const char *t = objc_skip_argspec (m->method_types);
733 if (arg > method_get_number_of_arguments (m))
737 t = objc_skip_argspec (t);
740 t = objc_skip_typespec (t);
743 return argframe->arg_regs + atoi (++t);
745 return argframe->arg_ptr + atoi (t);
749 objc_get_type_qualifiers (const char *type)
757 case _C_CONST: res |= _F_CONST; break;
758 case _C_IN: res |= _F_IN; break;
759 case _C_INOUT: res |= _F_INOUT; break;
760 case _C_OUT: res |= _F_OUT; break;
761 case _C_BYCOPY: res |= _F_BYCOPY; break;
762 case _C_BYREF: res |= _F_BYREF; break;
763 case _C_ONEWAY: res |= _F_ONEWAY; break;
764 case _C_GCINVISIBLE: res |= _F_GCINVISIBLE; break;
772 /* The following three functions can be used to determine how a
773 structure is laid out by the compiler. For example:
775 struct objc_struct_layout layout;
778 objc_layout_structure (type, &layout);
779 while (objc_layout_structure_next_member (&layout))
784 objc_layout_structure_get_info (&layout, &position, &align, &type);
785 printf ("element %d has offset %d, alignment %d\n",
786 i++, position, align);
789 These functions are used by objc_sizeof_type and objc_alignof_type
790 functions to compute the size and alignment of structures. The
791 previous method of computing the size and alignment of a structure
792 was not working on some architectures, particulary on AIX, and in
793 the presence of bitfields inside the structure. */
795 objc_layout_structure (const char *type,
796 struct objc_struct_layout *layout)
800 layout->original_type = ++type;
802 /* Skip "<name>=" if any. Avoid embedded structures and unions. */
804 while (*ntype != _C_STRUCT_E && *ntype != _C_STRUCT_B && *ntype != _C_UNION_B
808 /* If there's a "<name>=", ntype - 1 points to '='; skip the the name */
809 if (*(ntype - 1) == '=')
813 layout->prev_type = NULL;
814 layout->record_size = 0;
815 layout->record_align = MAX (BITS_PER_UNIT, STRUCTURE_SIZE_BOUNDARY);
820 objc_layout_structure_next_member (struct objc_struct_layout *layout)
822 register int desired_align = 0;
824 /* The current type without the type qualifiers */
827 /* Add the size of the previous field to the size of the record. */
828 if (layout->prev_type)
830 type = objc_skip_type_qualifiers (layout->prev_type);
832 if (*type != _C_BFLD)
833 layout->record_size += objc_sizeof_type (type) * BITS_PER_UNIT;
835 layout->record_size += atoi (++type);
838 if (*layout->type == _C_STRUCT_E)
841 /* Skip the variable name if any */
842 if (*layout->type == '"')
844 for (layout->type++; *layout->type++ != '"';)
848 type = objc_skip_type_qualifiers (layout->type);
850 desired_align = objc_alignof_type (type) * BITS_PER_UNIT;
852 /* Record must have at least as much alignment as any field.
853 Otherwise, the alignment of the field within the record
855 layout->record_align = MAX (layout->record_align, desired_align);
857 if (*type == _C_BFLD)
859 int bfld_size = atoi (++type);
860 int int_align = __alignof__ (int) * BITS_PER_UNIT;
861 /* If this bitfield would traverse a word alignment boundary, push it out
862 to that boundary instead. */
863 if (layout->record_size % int_align
864 && (layout->record_size / int_align
865 < (layout->record_size + bfld_size - 1) / int_align))
866 layout->record_size = ROUND (layout->record_size, int_align);
868 else if (layout->record_size % desired_align != 0)
870 /* We need to skip space before this field.
871 Bump the cumulative size to multiple of field alignment. */
872 layout->record_size = ROUND (layout->record_size, desired_align);
875 /* Jump to the next field in record. */
877 layout->prev_type = layout->type;
878 layout->type = objc_skip_typespec (layout->type); /* skip component */
884 void objc_layout_finish_structure (struct objc_struct_layout *layout,
888 if (layout->type && *layout->type == _C_STRUCT_E)
890 /* Round the size up to be a multiple of the required alignment */
891 layout->record_size = ROUND (layout->record_size, layout->record_align);
895 *size = layout->record_size / BITS_PER_UNIT;
897 *align = layout->record_align / BITS_PER_UNIT;
901 void objc_layout_structure_get_info (struct objc_struct_layout *layout,
902 unsigned int *offset,
907 *offset = layout->record_size / BITS_PER_UNIT;
909 *align = layout->record_align / BITS_PER_UNIT;
911 *type = layout->prev_type;
914 /* A small, portable NSConstantString implementation for use with the NeXT
917 On full-fledged Mac OS X systems, NSConstantString is provided
918 as part of the Foundation framework. However, on bare Darwin systems,
919 Foundation is not included, and hence there is no NSConstantString
920 implementation to link against.
922 This code is derived from the GNU runtime's NXConstantString implementation.
925 /* This definition cut out of <objc/Object.h> with the OBJC2 deprecation
928 #ifdef NEXT_OBJC_USE_NEW_INTERFACE
929 struct fudge_objc_class {
931 #if NEXT_OBJC_ABI_VERSION < 2
937 struct anon *ivars ; /* objc_ivar_list */
938 struct anon1 **methodLists ; /* objc_method_list */
939 struct objc_cache *cache ;
940 struct objc_protocol_list *protocols ;
942 } _NSConstantStringClassReference ;
944 struct objc_class _NSConstantStringClassReference ;
947 @interface NSConstantString : Object
953 -(const char *) cString;
954 -(unsigned int) length;
958 @implementation NSConstantString
960 -(const char *) cString
965 -(unsigned int) length
972 /* The NSConstantString metaclass will need to be initialized before we can
973 send messages to strings. */
975 void objc_constant_string_init (void) __attribute__((constructor));
976 void objc_constant_string_init (void) {
977 memcpy (&_NSConstantStringClassReference,
978 objc_getClass ("NSConstantString"),
979 sizeof (_NSConstantStringClassReference));
982 #endif /* #ifdef __NEXT_RUNTIME__ */