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> */
7 #ifdef __NEXT_RUNTIME__
8 #include <objc/objc-class.h>
9 #include <objc/Object.h>
14 #define objc_get_class(C) objc_getClass(C)
15 #define objc_get_meta_class(C) objc_getMetaClass(C)
16 #define class_get_class_method(C, S) class_getClassMethod(C, S)
17 #define class_get_instance_method(C, S) class_getInstanceMethod(C, S)
18 #define method_get_imp(M) (((Method)M)->method_imp)
19 #define sel_get_name(S) sel_getName(S)
20 #define class_create_instance(C) class_createInstance(C, 0)
21 #define class_get_class_name(C) object_getClassName(C)
22 #define class_get_super_class(C) (((struct objc_class *)C)->super_class)
23 #define object_get_super_class(O) class_get_super_class(*(struct objc_class **)O)
24 #define objc_lookup_class(N) objc_lookUpClass(N)
25 #define object_get_class(O) (*(struct objc_class **)O)
26 #define class_is_class(C) (CLS_GETINFO((struct objc_class *)C, CLS_CLASS)? YES: NO)
27 #define class_is_meta_class(C) (CLS_GETINFO((struct objc_class *)C, CLS_META)? YES: NO)
28 #define object_is_class(O) class_is_meta_class(*(struct objc_class **)O)
29 #define object_is_meta_class(O) (class_is_meta_class(O) && class_is_meta_class(*(struct objc_class **)O))
31 /* You need either an empty +initialize method or an empty -forward:: method.
32 The NeXT runtime unconditionally sends +initialize to classes when they are
33 first used, and unconditionally tries to forward methods that the class
34 doesn't understand (including +initialize). If you have neither +initialize
35 nor -forward::, the runtime complains.
37 The simplest workaround is to add
39 + initialize { return self; }
41 to every root class @implementation. */
47 /* The following is necessary to "cover" the bf*.m test cases on NeXT. */
54 #define MAX(X, Y) ((X > Y) ? X : Y)
55 #define MIN(X, Y) ((X < Y) ? X : Y)
56 #define ROUND(V, A) (A * ((V + A - 1) / A))
59 ({ typeof (X) __x = (X), __y = (Y); \
60 (__x > __y ? __x : __y); })
62 ({ typeof (X) __x = (X), __y = (Y); \
63 (__x < __y ? __x : __y); })
65 ({ typeof (V) __v = (V); typeof (A) __a = (A); \
66 __a * ((__v+__a - 1)/__a); })
69 #define BITS_PER_UNIT __CHAR_BIT__
70 typedef struct{ char a
; } __small_struct
;
71 #define STRUCTURE_SIZE_BOUNDARY (BITS_PER_UNIT * sizeof (__small_struct))
73 /* Not sure why the following are missing from NeXT objc headers... */
76 #define _C_LNG_LNG 'q'
79 #define _C_ULNG_LNG 'Q'
95 #define _C_GCINVISIBLE '!'
100 #define _F_INOUT 0x03
101 #define _F_BYCOPY 0x04
102 #define _F_BYREF 0x08
103 #define _F_ONEWAY 0x10
104 #define _F_GCINVISIBLE 0x20
106 struct objc_struct_layout
108 const char *original_type
;
110 const char *prev_type
;
111 unsigned int record_size
;
112 unsigned int record_align
;
115 typedef union arglist
{
117 char arg_regs
[sizeof (char*)];
118 } *arglist_t
; /* argument frame */
120 const char *objc_skip_typespec (const char *type
);
121 void objc_layout_structure_get_info (struct objc_struct_layout
*layout
,
122 unsigned int *offset
, unsigned int *align
, const char **type
);
123 void objc_layout_structure (const char *type
,
124 struct objc_struct_layout
*layout
);
125 BOOL
objc_layout_structure_next_member (struct objc_struct_layout
*layout
);
126 void objc_layout_finish_structure (struct objc_struct_layout
*layout
,
127 unsigned int *size
, unsigned int *align
);
128 int objc_aligned_size (const char *type
);
131 return the size of an object specified by type
135 objc_sizeof_type (const char *type
)
137 /* Skip the variable name if any */
140 for (type
++; *type
++ != '"';)
150 return sizeof (Class
);
158 return sizeof (char);
162 return sizeof (unsigned char);
166 return sizeof (short);
170 return sizeof (unsigned short);
178 return sizeof (unsigned int);
182 return sizeof (long);
186 return sizeof (unsigned long);
190 return sizeof (long long);
194 return sizeof (unsigned long long);
198 return sizeof (float);
202 return sizeof (double);
208 return sizeof (char *);
213 int len
= atoi (type
+ 1);
214 while (isdigit ((unsigned char)*++type
))
216 return len
* objc_aligned_size (type
);
222 /* The NeXT encoding of bitfields is _still_: b 'size' */
223 int size
= atoi (type
+ 1);
224 /* Return an upper bound on byte size */
225 return (size
+ BITS_PER_UNIT
- 1) / BITS_PER_UNIT
;
230 struct objc_struct_layout layout
;
233 objc_layout_structure (type
, &layout
);
234 while (objc_layout_structure_next_member (&layout
))
236 objc_layout_finish_structure (&layout
, &size
, NULL
);
244 while (*type
!= _C_UNION_E
&& *type
++ != '=')
246 while (*type
!= _C_UNION_E
)
248 /* Skip the variable name if any */
251 for (type
++; *type
++ != '"';)
254 max_size
= MAX (max_size
, objc_sizeof_type (type
));
255 type
= objc_skip_typespec (type
);
260 return 0; /* error */
265 Return the alignment of an object specified by type
269 objc_alignof_type (const char *type
)
271 /* Skip the variable name if any */
274 for (type
++; *type
++ != '"';)
279 return __alignof__ (id
);
283 return __alignof__ (Class
);
287 return __alignof__ (SEL
);
291 return __alignof__ (char);
295 return __alignof__ (unsigned char);
299 return __alignof__ (short);
303 return __alignof__ (unsigned short);
307 case _C_BFLD
: /* This is for the NeXT only */
308 return __alignof__ (int);
312 return __alignof__ (unsigned int);
316 return __alignof__ (long);
320 return __alignof__ (unsigned long);
324 return __alignof__ (long long);
328 return __alignof__ (unsigned long long);
332 return __alignof__ (float);
336 return __alignof__ (double);
342 return __alignof__ (char *);
346 while (isdigit ((unsigned char)*++type
))
348 return objc_alignof_type (type
);
352 struct objc_struct_layout layout
;
355 objc_layout_structure (type
, &layout
);
356 while (objc_layout_structure_next_member (&layout
))
358 objc_layout_finish_structure (&layout
, NULL
, &align
);
366 while (*type
!= _C_UNION_E
&& *type
++ != '=')
368 while (*type
!= _C_UNION_E
)
370 /* Skip the variable name if any */
373 for (type
++; *type
++ != '"';)
376 maxalign
= MAX (maxalign
, objc_alignof_type (type
));
377 type
= objc_skip_typespec (type
);
382 return 0; /* error */
386 The aligned size if the size rounded up to the nearest alignment.
390 objc_aligned_size (const char *type
)
394 /* Skip the variable name */
397 for (type
++; *type
++ != '"';)
401 size
= objc_sizeof_type (type
);
402 align
= objc_alignof_type (type
);
404 return ROUND (size
, align
);
408 The size rounded up to the nearest integral of the wordsize, taken
409 to be the size of a void *.
413 objc_promoted_size (const char *type
)
417 /* Skip the variable name */
420 for (type
++; *type
++ != '"';)
424 size
= objc_sizeof_type (type
);
425 wordsize
= sizeof (void *);
427 return ROUND (size
, wordsize
);
431 Skip type qualifiers. These may eventually precede typespecs
432 occurring in method prototype encodings.
436 objc_skip_type_qualifiers (const char *type
)
438 while (*type
== _C_CONST
442 || *type
== _C_BYCOPY
444 || *type
== _C_ONEWAY
445 || *type
== _C_GCINVISIBLE
)
454 Skip one typespec element. If the typespec is prepended by type
455 qualifiers, these are skipped as well.
459 objc_skip_typespec (const char *type
)
461 /* Skip the variable name if any */
464 for (type
++; *type
++ != '"';)
468 type
= objc_skip_type_qualifiers (type
);
473 /* An id may be annotated by the actual type if it is known
474 with the @"ClassName" syntax */
480 while (*++type
!= '"')
485 /* The following are one character type codes */
508 /* skip digits, typespec and closing ']' */
510 while (isdigit ((unsigned char)*++type
))
512 type
= objc_skip_typespec (type
);
513 if (*type
== _C_ARY_E
)
519 /* The NeXT encoding for bitfields is _still_: b 'size' */
520 while (isdigit ((unsigned char)*++type
))
521 ; /* skip type and size */
525 /* skip name, and elements until closing '}' */
527 while (*type
!= _C_STRUCT_E
&& *type
++ != '=')
529 while (*type
!= _C_STRUCT_E
)
531 type
= objc_skip_typespec (type
);
536 /* skip name, and elements until closing ')' */
538 while (*type
!= _C_UNION_E
&& *type
++ != '=')
540 while (*type
!= _C_UNION_E
)
542 type
= objc_skip_typespec (type
);
547 /* Just skip the following typespec */
549 return objc_skip_typespec (++type
);
551 return 0; /* error */
555 Skip an offset as part of a method encoding. This is prepended by a
556 '+' if the argument is passed in registers.
559 objc_skip_offset (const char *type
)
563 while (isdigit ((unsigned char) *++type
))
569 Skip an argument specification of a method encoding.
572 objc_skip_argspec (const char *type
)
574 type
= objc_skip_typespec (type
);
575 type
= objc_skip_offset (type
);
580 Return the number of arguments that the method MTH expects.
581 Note that all methods need two implicit arguments `self' and
585 method_get_number_of_arguments (struct objc_method
*mth
)
588 const char *type
= mth
->method_types
;
591 type
= objc_skip_argspec (type
);
598 Return the size of the argument block needed on the stack to invoke
599 the method MTH. This may be zero, if all arguments are passed in
604 method_get_sizeof_arguments (struct objc_method
*mth
)
606 const char *type
= objc_skip_typespec (mth
->method_types
);
611 Return a pointer to the next argument of ARGFRAME. type points to
612 the last argument. Typical use of this look like:
616 for (datum = method_get_first_argument (method, argframe, &type);
617 datum; datum = method_get_next_argument (argframe, &type))
619 unsigned flags = objc_get_type_qualifiers (type);
620 type = objc_skip_type_qualifiers (type);
622 [portal encodeData: datum ofType: type];
625 if ((flags & _F_IN) == _F_IN)
626 [portal encodeData: *(char **) datum ofType: ++type];
633 method_get_next_argument (arglist_t argframe
, const char **type
)
635 const char *t
= objc_skip_argspec (*type
);
641 t
= objc_skip_typespec (t
);
644 return argframe
->arg_regs
+ atoi (++t
);
646 return argframe
->arg_ptr
+ atoi (t
);
650 Return a pointer to the value of the first argument of the method
651 described in M with the given argumentframe ARGFRAME. The type
652 is returned in TYPE. type must be passed to successive calls of
653 method_get_next_argument.
656 method_get_first_argument (struct objc_method
*m
,
660 *type
= m
->method_types
;
661 return method_get_next_argument (argframe
, type
);
665 Return a pointer to the ARGth argument of the method
666 M from the frame ARGFRAME. The type of the argument
667 is returned in the value-result argument TYPE
671 method_get_nth_argument (struct objc_method
*m
,
672 arglist_t argframe
, int arg
,
675 const char *t
= objc_skip_argspec (m
->method_types
);
677 if (arg
> method_get_number_of_arguments (m
))
681 t
= objc_skip_argspec (t
);
684 t
= objc_skip_typespec (t
);
687 return argframe
->arg_regs
+ atoi (++t
);
689 return argframe
->arg_ptr
+ atoi (t
);
693 objc_get_type_qualifiers (const char *type
)
701 case _C_CONST
: res
|= _F_CONST
; break;
702 case _C_IN
: res
|= _F_IN
; break;
703 case _C_INOUT
: res
|= _F_INOUT
; break;
704 case _C_OUT
: res
|= _F_OUT
; break;
705 case _C_BYCOPY
: res
|= _F_BYCOPY
; break;
706 case _C_BYREF
: res
|= _F_BYREF
; break;
707 case _C_ONEWAY
: res
|= _F_ONEWAY
; break;
708 case _C_GCINVISIBLE
: res
|= _F_GCINVISIBLE
; break;
716 /* The following three functions can be used to determine how a
717 structure is laid out by the compiler. For example:
719 struct objc_struct_layout layout;
722 objc_layout_structure (type, &layout);
723 while (objc_layout_structure_next_member (&layout))
728 objc_layout_structure_get_info (&layout, &position, &align, &type);
729 printf ("element %d has offset %d, alignment %d\n",
730 i++, position, align);
733 These functions are used by objc_sizeof_type and objc_alignof_type
734 functions to compute the size and alignment of structures. The
735 previous method of computing the size and alignment of a structure
736 was not working on some architectures, particulary on AIX, and in
737 the presence of bitfields inside the structure. */
739 objc_layout_structure (const char *type
,
740 struct objc_struct_layout
*layout
)
744 layout
->original_type
= ++type
;
746 /* Skip "<name>=" if any. Avoid embedded structures and unions. */
748 while (*ntype
!= _C_STRUCT_E
&& *ntype
!= _C_STRUCT_B
&& *ntype
!= _C_UNION_B
752 /* If there's a "<name>=", ntype - 1 points to '='; skip the name */
753 if (*(ntype
- 1) == '=')
757 layout
->prev_type
= NULL
;
758 layout
->record_size
= 0;
759 layout
->record_align
= MAX (BITS_PER_UNIT
, STRUCTURE_SIZE_BOUNDARY
);
764 objc_layout_structure_next_member (struct objc_struct_layout
*layout
)
766 register int desired_align
= 0;
768 /* The current type without the type qualifiers */
771 /* Add the size of the previous field to the size of the record. */
772 if (layout
->prev_type
)
774 type
= objc_skip_type_qualifiers (layout
->prev_type
);
776 if (*type
!= _C_BFLD
)
777 layout
->record_size
+= objc_sizeof_type (type
) * BITS_PER_UNIT
;
779 layout
->record_size
+= atoi (++type
);
782 if (*layout
->type
== _C_STRUCT_E
)
785 /* Skip the variable name if any */
786 if (*layout
->type
== '"')
788 for (layout
->type
++; *layout
->type
++ != '"';)
792 type
= objc_skip_type_qualifiers (layout
->type
);
794 desired_align
= objc_alignof_type (type
) * BITS_PER_UNIT
;
796 /* Record must have at least as much alignment as any field.
797 Otherwise, the alignment of the field within the record
799 layout
->record_align
= MAX (layout
->record_align
, desired_align
);
801 if (*type
== _C_BFLD
)
803 int bfld_size
= atoi (++type
);
804 int int_align
= __alignof__ (int) * BITS_PER_UNIT
;
805 /* If this bitfield would traverse a word alignment boundary, push it out
806 to that boundary instead. */
807 if (layout
->record_size
% int_align
808 && (layout
->record_size
/ int_align
809 < (layout
->record_size
+ bfld_size
- 1) / int_align
))
810 layout
->record_size
= ROUND (layout
->record_size
, int_align
);
812 else if (layout
->record_size
% desired_align
!= 0)
814 /* We need to skip space before this field.
815 Bump the cumulative size to multiple of field alignment. */
816 layout
->record_size
= ROUND (layout
->record_size
, desired_align
);
819 /* Jump to the next field in record. */
821 layout
->prev_type
= layout
->type
;
822 layout
->type
= objc_skip_typespec (layout
->type
); /* skip component */
828 void objc_layout_finish_structure (struct objc_struct_layout
*layout
,
832 if (layout
->type
&& *layout
->type
== _C_STRUCT_E
)
834 /* Round the size up to be a multiple of the required alignment */
835 layout
->record_size
= ROUND (layout
->record_size
, layout
->record_align
);
839 *size
= layout
->record_size
/ BITS_PER_UNIT
;
841 *align
= layout
->record_align
/ BITS_PER_UNIT
;
845 void objc_layout_structure_get_info (struct objc_struct_layout
*layout
,
846 unsigned int *offset
,
851 *offset
= layout
->record_size
/ BITS_PER_UNIT
;
853 *align
= layout
->record_align
/ BITS_PER_UNIT
;
855 *type
= layout
->prev_type
;
858 /* A small, portable NSConstantString implementation for use with the NeXT
861 On full-fledged Mac OS X systems, NSConstantString is provided
862 as part of the Foundation framework. However, on bare Darwin systems,
863 Foundation is not included, and hence there is no NSConstantString
864 implementation to link against.
866 This code is derived from the GNU runtime's NXConstantString implementation.
869 struct objc_class _NSConstantStringClassReference
;
871 @interface NSConstantString
: Object
877 -(const char *) cString
;
878 -(unsigned int) length
;
882 @implementation NSConstantString
884 -(const char *) cString
889 -(unsigned int) length
896 /* The NSConstantString metaclass will need to be initialized before we can
897 send messages to strings. */
899 void objc_constant_string_init (void) __attribute__((constructor
));
900 void objc_constant_string_init (void) {
901 memcpy (&_NSConstantStringClassReference
,
902 objc_getClass ("NSConstantString"),
903 sizeof (_NSConstantStringClassReference
));
906 #endif /* #ifdef __NEXT_RUNTIME__ */