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 /* Author: Ziemowit Laski <zlaski@apple.com> */
6 #ifdef __NEXT_RUNTIME__
7 #include <objc/objc-class.h>
10 #define objc_get_class(C) objc_getClass(C)
11 #define objc_get_meta_class(C) objc_getMetaClass(C)
12 #define class_get_class_method(C, S) class_getClassMethod(C, S)
13 #define class_get_instance_method(C, S) class_getInstanceMethod(C, S)
14 #define method_get_imp(M) (((Method)M)->method_imp)
15 #define sel_get_name(S) sel_getName(S)
16 #define class_create_instance(C) class_createInstance(C, 0)
17 #define class_get_class_name(C) object_getClassName(C)
18 #define class_get_super_class(C) (((struct objc_class *)C)->super_class)
19 #define object_get_super_class(O) class_get_super_class(*(struct objc_class **)O)
20 #define objc_lookup_class(N) objc_lookUpClass(N)
21 #define object_get_class(O) (*(struct objc_class **)O)
22 #define class_is_class(C) (CLS_GETINFO((struct objc_class *)C, CLS_CLASS)? YES: NO)
23 #define class_is_meta_class(C) (CLS_GETINFO((struct objc_class *)C, CLS_META)? YES: NO)
24 #define object_is_class(O) class_is_meta_class(*(struct objc_class **)O)
25 #define object_is_meta_class(O) (class_is_meta_class(O) && class_is_meta_class(*(struct objc_class **)O))
27 /* You need either an empty +initialize method or an empty -forward:: method.
28 The NeXT runtime unconditionally sends +initialize to classes when they are
29 first used, and unconditionally tries to forward methods that the class
30 doesn't understand (including +initialize). If you have neither +initialize
31 nor -forward::, the runtime complains.
33 The simplest workaround is to add
35 + initialize { return self; }
37 to every root class @implementation. */
43 /* The following is necessary to "cover" the bf*.m test cases on NeXT. */
47 ({ typeof (X) __x = (X), __y = (Y); \
48 (__x > __y ? __x : __y); })
52 ({ typeof (X) __x = (X), __y = (Y); \
53 (__x < __y ? __x : __y); })
57 ({ typeof (V) __v = (V); typeof (A) __a = (A); \
58 __a * ((__v+__a - 1)/__a); })
60 #define BITS_PER_UNIT __CHAR_BIT__
61 #define STRUCTURE_SIZE_BOUNDARY (BITS_PER_UNIT * sizeof (struct{char a;}))
63 /* Not sure why the following are missing from NeXT objc headers... */
66 #define _C_LNG_LNG 'q'
69 #define _C_ULNG_LNG 'Q'
85 #define _C_GCINVISIBLE '!'
91 #define _F_BYCOPY 0x04
93 #define _F_ONEWAY 0x10
94 #define _F_GCINVISIBLE 0x20
96 struct objc_struct_layout
98 const char *original_type
;
100 const char *prev_type
;
101 unsigned int record_size
;
102 unsigned int record_align
;
107 char arg_regs
[sizeof (char*)];
108 } *arglist_t
; /* argument frame */
110 const char *objc_skip_typespec (const char *type
);
111 void objc_layout_structure_get_info (struct objc_struct_layout
*layout
,
112 unsigned int *offset
, unsigned int *align
, const char **type
);
113 void objc_layout_structure (const char *type
,
114 struct objc_struct_layout
*layout
);
115 BOOL
objc_layout_structure_next_member (struct objc_struct_layout
*layout
);
116 void objc_layout_finish_structure (struct objc_struct_layout
*layout
,
117 unsigned int *size
, unsigned int *align
);
120 return the size of an object specified by type
124 objc_sizeof_type (const char *type
)
126 /* Skip the variable name if any */
129 for (type
++; *type
++ != '"';)
139 return sizeof (Class
);
147 return sizeof (char);
151 return sizeof (unsigned char);
155 return sizeof (short);
159 return sizeof (unsigned short);
167 return sizeof (unsigned int);
171 return sizeof (long);
175 return sizeof (unsigned long);
179 return sizeof (long long);
183 return sizeof (unsigned long long);
187 return sizeof (float);
191 return sizeof (double);
195 return sizeof (void);
201 return sizeof (char *);
206 int len
= atoi (type
+ 1);
207 while (isdigit ((unsigned char)*++type
))
209 return len
* objc_aligned_size (type
);
215 /* The NeXT encoding of bitfields is _still_: b 'size' */
216 int size
= atoi (type
+ 1);
217 /* Return an upper bound on byte size */
218 return (size
+ BITS_PER_UNIT
- 1) / BITS_PER_UNIT
;
223 struct objc_struct_layout layout
;
226 objc_layout_structure (type
, &layout
);
227 while (objc_layout_structure_next_member (&layout
))
229 objc_layout_finish_structure (&layout
, &size
, NULL
);
237 while (*type
!= _C_UNION_E
&& *type
++ != '=')
239 while (*type
!= _C_UNION_E
)
241 /* Skip the variable name if any */
244 for (type
++; *type
++ != '"';)
247 max_size
= MAX (max_size
, objc_sizeof_type (type
));
248 type
= objc_skip_typespec (type
);
253 return 0; /* error */
258 Return the alignment of an object specified by type
262 objc_alignof_type (const char *type
)
264 /* Skip the variable name if any */
267 for (type
++; *type
++ != '"';)
272 return __alignof__ (id
);
276 return __alignof__ (Class
);
280 return __alignof__ (SEL
);
284 return __alignof__ (char);
288 return __alignof__ (unsigned char);
292 return __alignof__ (short);
296 return __alignof__ (unsigned short);
300 case _C_BFLD
: /* This is for the NeXT only */
301 return __alignof__ (int);
305 return __alignof__ (unsigned int);
309 return __alignof__ (long);
313 return __alignof__ (unsigned long);
317 return __alignof__ (long long);
321 return __alignof__ (unsigned long long);
325 return __alignof__ (float);
329 return __alignof__ (double);
335 return __alignof__ (char *);
339 while (isdigit ((unsigned char)*++type
))
341 return objc_alignof_type (type
);
345 struct objc_struct_layout layout
;
348 objc_layout_structure (type
, &layout
);
349 while (objc_layout_structure_next_member (&layout
))
351 objc_layout_finish_structure (&layout
, NULL
, &align
);
359 while (*type
!= _C_UNION_E
&& *type
++ != '=')
361 while (*type
!= _C_UNION_E
)
363 /* Skip the variable name if any */
366 for (type
++; *type
++ != '"';)
369 maxalign
= MAX (maxalign
, objc_alignof_type (type
));
370 type
= objc_skip_typespec (type
);
375 return 0; /* error */
379 The aligned size if the size rounded up to the nearest alignment.
383 objc_aligned_size (const char *type
)
387 /* Skip the variable name */
390 for (type
++; *type
++ != '"';)
394 size
= objc_sizeof_type (type
);
395 align
= objc_alignof_type (type
);
397 return ROUND (size
, align
);
401 The size rounded up to the nearest integral of the wordsize, taken
402 to be the size of a void *.
406 objc_promoted_size (const char *type
)
410 /* Skip the variable name */
413 for (type
++; *type
++ != '"';)
417 size
= objc_sizeof_type (type
);
418 wordsize
= sizeof (void *);
420 return ROUND (size
, wordsize
);
424 Skip type qualifiers. These may eventually precede typespecs
425 occurring in method prototype encodings.
429 objc_skip_type_qualifiers (const char *type
)
431 while (*type
== _C_CONST
435 || *type
== _C_BYCOPY
437 || *type
== _C_ONEWAY
438 || *type
== _C_GCINVISIBLE
)
447 Skip one typespec element. If the typespec is prepended by type
448 qualifiers, these are skipped as well.
452 objc_skip_typespec (const char *type
)
454 /* Skip the variable name if any */
457 for (type
++; *type
++ != '"';)
461 type
= objc_skip_type_qualifiers (type
);
466 /* An id may be annotated by the actual type if it is known
467 with the @"ClassName" syntax */
473 while (*++type
!= '"')
478 /* The following are one character type codes */
501 /* skip digits, typespec and closing ']' */
503 while (isdigit ((unsigned char)*++type
))
505 type
= objc_skip_typespec (type
);
506 if (*type
== _C_ARY_E
)
512 /* The NeXT encoding for bitfields is _still_: b 'size' */
513 while (isdigit ((unsigned char)*++type
))
514 ; /* skip type and size */
518 /* skip name, and elements until closing '}' */
520 while (*type
!= _C_STRUCT_E
&& *type
++ != '=')
522 while (*type
!= _C_STRUCT_E
)
524 type
= objc_skip_typespec (type
);
529 /* skip name, and elements until closing ')' */
531 while (*type
!= _C_UNION_E
&& *type
++ != '=')
533 while (*type
!= _C_UNION_E
)
535 type
= objc_skip_typespec (type
);
540 /* Just skip the following typespec */
542 return objc_skip_typespec (++type
);
544 return 0; /* error */
548 Skip an offset as part of a method encoding. This is prepended by a
549 '+' if the argument is passed in registers.
552 objc_skip_offset (const char *type
)
556 while (isdigit ((unsigned char) *++type
))
562 Skip an argument specification of a method encoding.
565 objc_skip_argspec (const char *type
)
567 type
= objc_skip_typespec (type
);
568 type
= objc_skip_offset (type
);
573 Return the number of arguments that the method MTH expects.
574 Note that all methods need two implicit arguments `self' and
578 method_get_number_of_arguments (struct objc_method
*mth
)
581 const char *type
= mth
->method_types
;
584 type
= objc_skip_argspec (type
);
591 Return the size of the argument block needed on the stack to invoke
592 the method MTH. This may be zero, if all arguments are passed in
597 method_get_sizeof_arguments (struct objc_method
*mth
)
599 const char *type
= objc_skip_typespec (mth
->method_types
);
604 Return a pointer to the next argument of ARGFRAME. type points to
605 the last argument. Typical use of this look like:
609 for (datum = method_get_first_argument (method, argframe, &type);
610 datum; datum = method_get_next_argument (argframe, &type))
612 unsigned flags = objc_get_type_qualifiers (type);
613 type = objc_skip_type_qualifiers (type);
615 [portal encodeData: datum ofType: type];
618 if ((flags & _F_IN) == _F_IN)
619 [portal encodeData: *(char **) datum ofType: ++type];
626 method_get_next_argument (arglist_t argframe
, const char **type
)
628 const char *t
= objc_skip_argspec (*type
);
634 t
= objc_skip_typespec (t
);
637 return argframe
->arg_regs
+ atoi (++t
);
639 return argframe
->arg_ptr
+ atoi (t
);
643 Return a pointer to the value of the first argument of the method
644 described in M with the given argumentframe ARGFRAME. The type
645 is returned in TYPE. type must be passed to successive calls of
646 method_get_next_argument.
649 method_get_first_argument (struct objc_method
*m
,
653 *type
= m
->method_types
;
654 return method_get_next_argument (argframe
, type
);
658 Return a pointer to the ARGth argument of the method
659 M from the frame ARGFRAME. The type of the argument
660 is returned in the value-result argument TYPE
664 method_get_nth_argument (struct objc_method
*m
,
665 arglist_t argframe
, int arg
,
668 const char *t
= objc_skip_argspec (m
->method_types
);
670 if (arg
> method_get_number_of_arguments (m
))
674 t
= objc_skip_argspec (t
);
677 t
= objc_skip_typespec (t
);
680 return argframe
->arg_regs
+ atoi (++t
);
682 return argframe
->arg_ptr
+ atoi (t
);
686 objc_get_type_qualifiers (const char *type
)
694 case _C_CONST
: res
|= _F_CONST
; break;
695 case _C_IN
: res
|= _F_IN
; break;
696 case _C_INOUT
: res
|= _F_INOUT
; break;
697 case _C_OUT
: res
|= _F_OUT
; break;
698 case _C_BYCOPY
: res
|= _F_BYCOPY
; break;
699 case _C_BYREF
: res
|= _F_BYREF
; break;
700 case _C_ONEWAY
: res
|= _F_ONEWAY
; break;
701 case _C_GCINVISIBLE
: res
|= _F_GCINVISIBLE
; break;
709 /* The following three functions can be used to determine how a
710 structure is laid out by the compiler. For example:
712 struct objc_struct_layout layout;
715 objc_layout_structure (type, &layout);
716 while (objc_layout_structure_next_member (&layout))
721 objc_layout_structure_get_info (&layout, &position, &align, &type);
722 printf ("element %d has offset %d, alignment %d\n",
723 i++, position, align);
726 These functions are used by objc_sizeof_type and objc_alignof_type
727 functions to compute the size and alignment of structures. The
728 previous method of computing the size and alignment of a structure
729 was not working on some architectures, particulary on AIX, and in
730 the presence of bitfields inside the structure. */
732 objc_layout_structure (const char *type
,
733 struct objc_struct_layout
*layout
)
737 layout
->original_type
= ++type
;
739 /* Skip "<name>=" if any. Avoid embedded structures and unions. */
741 while (*ntype
!= _C_STRUCT_E
&& *ntype
!= _C_STRUCT_B
&& *ntype
!= _C_UNION_B
745 /* If there's a "<name>=", ntype - 1 points to '='; skip the the name */
746 if (*(ntype
- 1) == '=')
750 layout
->prev_type
= NULL
;
751 layout
->record_size
= 0;
752 layout
->record_align
= MAX (BITS_PER_UNIT
, STRUCTURE_SIZE_BOUNDARY
);
757 objc_layout_structure_next_member (struct objc_struct_layout
*layout
)
759 register int desired_align
= 0;
761 /* The current type without the type qualifiers */
764 /* Add the size of the previous field to the size of the record. */
765 if (layout
->prev_type
)
767 type
= objc_skip_type_qualifiers (layout
->prev_type
);
769 if (*type
!= _C_BFLD
)
770 layout
->record_size
+= objc_sizeof_type (type
) * BITS_PER_UNIT
;
772 layout
->record_size
+= atoi (++type
);
775 if (*layout
->type
== _C_STRUCT_E
)
778 /* Skip the variable name if any */
779 if (*layout
->type
== '"')
781 for (layout
->type
++; *layout
->type
++ != '"';)
785 type
= objc_skip_type_qualifiers (layout
->type
);
787 desired_align
= objc_alignof_type (type
) * BITS_PER_UNIT
;
789 /* Record must have at least as much alignment as any field.
790 Otherwise, the alignment of the field within the record
792 layout
->record_align
= MAX (layout
->record_align
, desired_align
);
794 if (*type
== _C_BFLD
)
796 int bfld_size
= atoi (++type
);
797 int int_align
= __alignof__ (int) * BITS_PER_UNIT
;
798 /* If this bitfield would traverse a word alignment boundary, push it out
799 to that boundary instead. */
800 if (layout
->record_size
% int_align
801 && (layout
->record_size
/ int_align
802 < (layout
->record_size
+ bfld_size
- 1) / int_align
))
803 layout
->record_size
= ROUND (layout
->record_size
, int_align
);
805 else if (layout
->record_size
% desired_align
!= 0)
807 /* We need to skip space before this field.
808 Bump the cumulative size to multiple of field alignment. */
809 layout
->record_size
= ROUND (layout
->record_size
, desired_align
);
812 /* Jump to the next field in record. */
814 layout
->prev_type
= layout
->type
;
815 layout
->type
= objc_skip_typespec (layout
->type
); /* skip component */
821 void objc_layout_finish_structure (struct objc_struct_layout
*layout
,
825 if (layout
->type
&& *layout
->type
== _C_STRUCT_E
)
827 /* Round the size up to be a multiple of the required alignment */
828 layout
->record_size
= ROUND (layout
->record_size
, layout
->record_align
);
832 *size
= layout
->record_size
/ BITS_PER_UNIT
;
834 *align
= layout
->record_align
/ BITS_PER_UNIT
;
838 void objc_layout_structure_get_info (struct objc_struct_layout
*layout
,
839 unsigned int *offset
,
844 *offset
= layout
->record_size
/ BITS_PER_UNIT
;
846 *align
= layout
->record_align
/ BITS_PER_UNIT
;
848 *type
= layout
->prev_type
;
851 #endif /* #ifdef __NEXT_RUNTIME__ */