First version committed to git
[zpugcc/jano.git] / toolchain / gcc / gcc / testsuite / objc / execute / next_mapping.h
blob67c2ce342573ec841c38820855f57d0d205adbc0
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>
8 #include <ctype.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. */
39 #ifndef NULL
40 #define NULL 0
41 #endif
43 /* The following is necessary to "cover" the bf*.m test cases on NeXT. */
45 #undef MAX
46 #define MAX(X, Y) \
47 ({ typeof (X) __x = (X), __y = (Y); \
48 (__x > __y ? __x : __y); })
50 #undef MIN
51 #define MIN(X, Y) \
52 ({ typeof (X) __x = (X), __y = (Y); \
53 (__x < __y ? __x : __y); })
55 #undef ROUND
56 #define ROUND(V, A) \
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... */
65 #ifndef _C_LNG_LNG
66 #define _C_LNG_LNG 'q'
67 #endif
68 #ifndef _C_ULNG_LNG
69 #define _C_ULNG_LNG 'Q'
70 #endif
71 #ifndef _C_ATOM
72 #define _C_ATOM '%'
73 #endif
74 #ifndef _C_BOOL
75 #define _C_BOOL 'B'
76 #endif
78 #define _C_CONST 'r'
79 #define _C_IN 'n'
80 #define _C_INOUT 'N'
81 #define _C_OUT 'o'
82 #define _C_BYCOPY 'O'
83 #define _C_BYREF 'R'
84 #define _C_ONEWAY 'V'
85 #define _C_GCINVISIBLE '!'
87 #define _F_CONST 0x01
88 #define _F_IN 0x01
89 #define _F_OUT 0x02
90 #define _F_INOUT 0x03
91 #define _F_BYCOPY 0x04
92 #define _F_BYREF 0x08
93 #define _F_ONEWAY 0x10
94 #define _F_GCINVISIBLE 0x20
96 struct objc_struct_layout
98 const char *original_type;
99 const char *type;
100 const char *prev_type;
101 unsigned int record_size;
102 unsigned int record_align;
105 typedef union {
106 char *arg_ptr;
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 */
127 if (*type == '"')
129 for (type++; *type++ != '"';)
130 /* do nothing */;
133 switch (*type) {
134 case _C_ID:
135 return sizeof (id);
136 break;
138 case _C_CLASS:
139 return sizeof (Class);
140 break;
142 case _C_SEL:
143 return sizeof (SEL);
144 break;
146 case _C_CHR:
147 return sizeof (char);
148 break;
150 case _C_UCHR:
151 return sizeof (unsigned char);
152 break;
154 case _C_SHT:
155 return sizeof (short);
156 break;
158 case _C_USHT:
159 return sizeof (unsigned short);
160 break;
162 case _C_INT:
163 return sizeof (int);
164 break;
166 case _C_UINT:
167 return sizeof (unsigned int);
168 break;
170 case _C_LNG:
171 return sizeof (long);
172 break;
174 case _C_ULNG:
175 return sizeof (unsigned long);
176 break;
178 case _C_LNG_LNG:
179 return sizeof (long long);
180 break;
182 case _C_ULNG_LNG:
183 return sizeof (unsigned long long);
184 break;
186 case _C_FLT:
187 return sizeof (float);
188 break;
190 case _C_DBL:
191 return sizeof (double);
192 break;
194 case _C_VOID:
195 return sizeof (void);
196 break;
198 case _C_PTR:
199 case _C_ATOM:
200 case _C_CHARPTR:
201 return sizeof (char *);
202 break;
204 case _C_ARY_B:
206 int len = atoi (type + 1);
207 while (isdigit ((unsigned char)*++type))
209 return len * objc_aligned_size (type);
211 break;
213 case _C_BFLD:
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;
221 case _C_STRUCT_B:
223 struct objc_struct_layout layout;
224 unsigned int size;
226 objc_layout_structure (type, &layout);
227 while (objc_layout_structure_next_member (&layout))
228 /* do nothing */ ;
229 objc_layout_finish_structure (&layout, &size, NULL);
231 return size;
234 case _C_UNION_B:
236 int max_size = 0;
237 while (*type != _C_UNION_E && *type++ != '=')
238 /* do nothing */;
239 while (*type != _C_UNION_E)
241 /* Skip the variable name if any */
242 if (*type == '"')
244 for (type++; *type++ != '"';)
245 /* do nothing */;
247 max_size = MAX (max_size, objc_sizeof_type (type));
248 type = objc_skip_typespec (type);
250 return max_size;
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 */
265 if (*type == '"')
267 for (type++; *type++ != '"';)
268 /* do nothing */;
270 switch (*type) {
271 case _C_ID:
272 return __alignof__ (id);
273 break;
275 case _C_CLASS:
276 return __alignof__ (Class);
277 break;
279 case _C_SEL:
280 return __alignof__ (SEL);
281 break;
283 case _C_CHR:
284 return __alignof__ (char);
285 break;
287 case _C_UCHR:
288 return __alignof__ (unsigned char);
289 break;
291 case _C_SHT:
292 return __alignof__ (short);
293 break;
295 case _C_USHT:
296 return __alignof__ (unsigned short);
297 break;
299 case _C_INT:
300 case _C_BFLD: /* This is for the NeXT only */
301 return __alignof__ (int);
302 break;
304 case _C_UINT:
305 return __alignof__ (unsigned int);
306 break;
308 case _C_LNG:
309 return __alignof__ (long);
310 break;
312 case _C_ULNG:
313 return __alignof__ (unsigned long);
314 break;
316 case _C_LNG_LNG:
317 return __alignof__ (long long);
318 break;
320 case _C_ULNG_LNG:
321 return __alignof__ (unsigned long long);
322 break;
324 case _C_FLT:
325 return __alignof__ (float);
326 break;
328 case _C_DBL:
329 return __alignof__ (double);
330 break;
332 case _C_PTR:
333 case _C_ATOM:
334 case _C_CHARPTR:
335 return __alignof__ (char *);
336 break;
338 case _C_ARY_B:
339 while (isdigit ((unsigned char)*++type))
340 /* do nothing */;
341 return objc_alignof_type (type);
343 case _C_STRUCT_B:
345 struct objc_struct_layout layout;
346 unsigned int align;
348 objc_layout_structure (type, &layout);
349 while (objc_layout_structure_next_member (&layout))
350 /* do nothing */;
351 objc_layout_finish_structure (&layout, NULL, &align);
353 return align;
356 case _C_UNION_B:
358 int maxalign = 0;
359 while (*type != _C_UNION_E && *type++ != '=')
360 /* do nothing */;
361 while (*type != _C_UNION_E)
363 /* Skip the variable name if any */
364 if (*type == '"')
366 for (type++; *type++ != '"';)
367 /* do nothing */;
369 maxalign = MAX (maxalign, objc_alignof_type (type));
370 type = objc_skip_typespec (type);
372 return maxalign;
375 return 0; /* error */
379 The aligned size if the size rounded up to the nearest alignment.
383 objc_aligned_size (const char *type)
385 int size, align;
387 /* Skip the variable name */
388 if (*type == '"')
390 for (type++; *type++ != '"';)
391 /* do nothing */;
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)
408 int size, wordsize;
410 /* Skip the variable name */
411 if (*type == '"')
413 for (type++; *type++ != '"';)
414 /* do nothing */;
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.
428 inline const char *
429 objc_skip_type_qualifiers (const char *type)
431 while (*type == _C_CONST
432 || *type == _C_IN
433 || *type == _C_INOUT
434 || *type == _C_OUT
435 || *type == _C_BYCOPY
436 || *type == _C_BYREF
437 || *type == _C_ONEWAY
438 || *type == _C_GCINVISIBLE)
440 type += 1;
442 return type;
447 Skip one typespec element. If the typespec is prepended by type
448 qualifiers, these are skipped as well.
451 const char *
452 objc_skip_typespec (const char *type)
454 /* Skip the variable name if any */
455 if (*type == '"')
457 for (type++; *type++ != '"';)
458 /* do nothing */;
461 type = objc_skip_type_qualifiers (type);
463 switch (*type) {
465 case _C_ID:
466 /* An id may be annotated by the actual type if it is known
467 with the @"ClassName" syntax */
469 if (*++type != '"')
470 return type;
471 else
473 while (*++type != '"')
474 /* do nothing */;
475 return type + 1;
478 /* The following are one character type codes */
479 case _C_CLASS:
480 case _C_SEL:
481 case _C_CHR:
482 case _C_UCHR:
483 case _C_CHARPTR:
484 case _C_ATOM:
485 case _C_SHT:
486 case _C_USHT:
487 case _C_INT:
488 case _C_UINT:
489 case _C_LNG:
490 case _C_ULNG:
491 case _C_LNG_LNG:
492 case _C_ULNG_LNG:
493 case _C_FLT:
494 case _C_DBL:
495 case _C_VOID:
496 case _C_UNDEF:
497 return ++type;
498 break;
500 case _C_ARY_B:
501 /* skip digits, typespec and closing ']' */
503 while (isdigit ((unsigned char)*++type))
505 type = objc_skip_typespec (type);
506 if (*type == _C_ARY_E)
507 return ++type;
508 else
509 break; /* error */
511 case _C_BFLD:
512 /* The NeXT encoding for bitfields is _still_: b 'size' */
513 while (isdigit ((unsigned char)*++type))
514 ; /* skip type and size */
515 return type;
517 case _C_STRUCT_B:
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);
526 return ++type;
528 case _C_UNION_B:
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);
537 return ++type;
539 case _C_PTR:
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.
551 inline const char *
552 objc_skip_offset (const char *type)
554 if (*type == '+')
555 type++;
556 while (isdigit ((unsigned char) *++type))
558 return type;
562 Skip an argument specification of a method encoding.
564 const char *
565 objc_skip_argspec (const char *type)
567 type = objc_skip_typespec (type);
568 type = objc_skip_offset (type);
569 return type;
573 Return the number of arguments that the method MTH expects.
574 Note that all methods need two implicit arguments `self' and
575 `_cmd'.
578 method_get_number_of_arguments (struct objc_method *mth)
580 int i = 0;
581 const char *type = mth->method_types;
582 while (*type)
584 type = objc_skip_argspec (type);
585 i += 1;
587 return i - 1;
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
593 registers.
597 method_get_sizeof_arguments (struct objc_method *mth)
599 const char *type = objc_skip_typespec (mth->method_types);
600 return atoi (type);
604 Return a pointer to the next argument of ARGFRAME. type points to
605 the last argument. Typical use of this look like:
608 char *datum, *type;
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);
614 if (*type != _C_PTR)
615 [portal encodeData: datum ofType: type];
616 else
618 if ((flags & _F_IN) == _F_IN)
619 [portal encodeData: *(char **) datum ofType: ++type];
625 char *
626 method_get_next_argument (arglist_t argframe, const char **type)
628 const char *t = objc_skip_argspec (*type);
630 if (*t == '\0')
631 return 0;
633 *type = t;
634 t = objc_skip_typespec (t);
636 if (*t == '+')
637 return argframe->arg_regs + atoi (++t);
638 else
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.
648 char *
649 method_get_first_argument (struct objc_method *m,
650 arglist_t argframe,
651 const char **type)
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
663 char *
664 method_get_nth_argument (struct objc_method *m,
665 arglist_t argframe, int arg,
666 const char **type)
668 const char *t = objc_skip_argspec (m->method_types);
670 if (arg > method_get_number_of_arguments (m))
671 return 0;
673 while (arg--)
674 t = objc_skip_argspec (t);
676 *type = t;
677 t = objc_skip_typespec (t);
679 if (*t == '+')
680 return argframe->arg_regs + atoi (++t);
681 else
682 return argframe->arg_ptr + atoi (t);
685 unsigned
686 objc_get_type_qualifiers (const char *type)
688 unsigned res = 0;
689 BOOL flag = YES;
691 while (flag)
692 switch (*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;
702 default: flag = NO;
705 return res;
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;
713 int i;
715 objc_layout_structure (type, &layout);
716 while (objc_layout_structure_next_member (&layout))
718 int position, align;
719 const char *type;
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. */
731 void
732 objc_layout_structure (const char *type,
733 struct objc_struct_layout *layout)
735 const char *ntype;
737 layout->original_type = ++type;
739 /* Skip "<name>=" if any. Avoid embedded structures and unions. */
740 ntype = type;
741 while (*ntype != _C_STRUCT_E && *ntype != _C_STRUCT_B && *ntype != _C_UNION_B
742 && *ntype++ != '=')
743 /* do nothing */;
745 /* If there's a "<name>=", ntype - 1 points to '='; skip the the name */
746 if (*(ntype - 1) == '=')
747 type = ntype;
749 layout->type = type;
750 layout->prev_type = NULL;
751 layout->record_size = 0;
752 layout->record_align = MAX (BITS_PER_UNIT, STRUCTURE_SIZE_BOUNDARY);
756 BOOL
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 */
762 const char *type;
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;
771 else
772 layout->record_size += atoi (++type);
775 if (*layout->type == _C_STRUCT_E)
776 return NO;
778 /* Skip the variable name if any */
779 if (*layout->type == '"')
781 for (layout->type++; *layout->type++ != '"';)
782 /* do nothing */;
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
791 is meaningless. */
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 */
817 return YES;
821 void objc_layout_finish_structure (struct objc_struct_layout *layout,
822 unsigned int *size,
823 unsigned int *align)
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);
829 layout->type = NULL;
831 if (size)
832 *size = layout->record_size / BITS_PER_UNIT;
833 if (align)
834 *align = layout->record_align / BITS_PER_UNIT;
838 void objc_layout_structure_get_info (struct objc_struct_layout *layout,
839 unsigned int *offset,
840 unsigned int *align,
841 const char **type)
843 if (offset)
844 *offset = layout->record_size / BITS_PER_UNIT;
845 if (align)
846 *align = layout->record_align / BITS_PER_UNIT;
847 if (type)
848 *type = layout->prev_type;
851 #endif /* #ifdef __NEXT_RUNTIME__ */