1 #ifndef _OBJC_TEST_SUITE_NEXT_ENCODE_ASSIST_IMPL_H_
2 #define _OBJC_TEST_SUITE_NEXT_ENCODE_ASSIST_IMPL_H_
4 #ifdef __NEXT_RUNTIME__
6 /* Determine which API to use. */
8 #ifdef NEXT_OBJC_USE_NEW_INTERFACE
9 #include <objc/runtime.h>
11 #include <objc/objc-runtime.h>
21 # define MAX(X, Y) ((X > Y) ? X : Y)
22 # define MIN(X, Y) ((X < Y) ? X : Y)
23 # define ROUND(V, A) (A * ((V + A - 1) / A))
26 ({ typeof (X) __x = (X), __y = (Y); \
27 (__x > __y ? __x : __y); })
29 ({ typeof (X) __x = (X), __y = (Y); \
30 (__x < __y ? __x : __y); })
31 # define ROUND(V, A) \
32 ({ typeof (V) __v = (V); typeof (A) __a = (A); \
33 __a * ((__v+__a - 1)/__a); })
36 #define BITS_PER_UNIT __CHAR_BIT__
37 typedef struct{ char a
; } __small_struct
;
38 #define STRUCTURE_SIZE_BOUNDARY (BITS_PER_UNIT * sizeof (__small_struct))
41 return the size of an object specified by type
45 objc_sizeof_type (const char *type
)
47 /* Skip the variable name if any */
50 for (type
++; *type
++ != '"';)
60 return sizeof (Class
);
72 return sizeof (unsigned char);
76 return sizeof (short);
80 return sizeof (unsigned short);
88 return sizeof (unsigned int);
96 return sizeof (unsigned long);
100 return sizeof (long long);
104 return sizeof (unsigned long long);
108 return sizeof (float);
112 return sizeof (double);
118 return sizeof (char *);
123 int len
= atoi (type
+ 1);
124 while (isdigit ((unsigned char)*++type
))
126 return len
* objc_aligned_size (type
);
132 /* The NeXT encoding of bitfields is _still_: b 'size' */
133 int size
= atoi (type
+ 1);
134 /* Return an upper bound on byte size */
135 return (size
+ BITS_PER_UNIT
- 1) / BITS_PER_UNIT
;
140 struct objc_struct_layout layout
;
143 objc_layout_structure (type
, &layout
);
144 while (objc_layout_structure_next_member (&layout
))
146 objc_layout_finish_structure (&layout
, &size
, NULL
);
154 while (*type
!= _C_UNION_E
&& *type
++ != '=')
156 while (*type
!= _C_UNION_E
)
158 /* Skip the variable name if any */
161 for (type
++; *type
++ != '"';)
164 max_size
= MAX (max_size
, objc_sizeof_type (type
));
165 type
= objc_skip_typespec (type
);
170 return 0; /* error */
175 Return the alignment of an object specified by type
179 objc_alignof_type (const char *type
)
181 /* Skip the variable name if any */
184 for (type
++; *type
++ != '"';)
189 return __alignof__ (id
);
193 return __alignof__ (Class
);
197 return __alignof__ (SEL
);
201 return __alignof__ (char);
205 return __alignof__ (unsigned char);
209 return __alignof__ (short);
213 return __alignof__ (unsigned short);
217 case _C_BFLD
: /* This is for the NeXT only */
218 return __alignof__ (int);
222 return __alignof__ (unsigned int);
226 return __alignof__ (long);
230 return __alignof__ (unsigned long);
234 return __alignof__ (long long);
238 return __alignof__ (unsigned long long);
242 return __alignof__ (float);
246 return __alignof__ (double);
252 return __alignof__ (char *);
256 while (isdigit ((unsigned char)*++type
))
258 return objc_alignof_type (type
);
262 struct objc_struct_layout layout
;
265 objc_layout_structure (type
, &layout
);
266 while (objc_layout_structure_next_member (&layout
))
268 objc_layout_finish_structure (&layout
, NULL
, &align
);
276 while (*type
!= _C_UNION_E
&& *type
++ != '=')
278 while (*type
!= _C_UNION_E
)
280 /* Skip the variable name if any */
283 for (type
++; *type
++ != '"';)
286 maxalign
= MAX (maxalign
, objc_alignof_type (type
));
287 type
= objc_skip_typespec (type
);
292 return 0; /* error */
296 The aligned size if the size rounded up to the nearest alignment.
300 objc_aligned_size (const char *type
)
304 /* Skip the variable name */
307 for (type
++; *type
++ != '"';)
311 size
= objc_sizeof_type (type
);
312 align
= objc_alignof_type (type
);
314 return ROUND (size
, align
);
318 The size rounded up to the nearest integral of the wordsize, taken
319 to be the size of a void *.
323 objc_promoted_size (const char *type
)
327 /* Skip the variable name */
330 for (type
++; *type
++ != '"';)
334 size
= objc_sizeof_type (type
);
335 wordsize
= sizeof (void *);
337 return ROUND (size
, wordsize
);
341 Skip type qualifiers. These may eventually precede typespecs
342 occurring in method prototype encodings.
346 objc_skip_type_qualifiers (const char *type
)
348 while (*type
== _C_CONST
352 || *type
== _C_BYCOPY
354 || *type
== _C_ONEWAY
355 || *type
== _C_GCINVISIBLE
)
363 Skip one typespec element. If the typespec is prepended by type
364 qualifiers, these are skipped as well.
368 objc_skip_typespec (const char *type
)
370 /* Skip the variable name if any */
373 for (type
++; *type
++ != '"';)
377 type
= objc_skip_type_qualifiers (type
);
382 /* An id may be annotated by the actual type if it is known
383 with the @"ClassName" syntax */
389 while (*++type
!= '"')
394 /* The following are one character type codes */
417 /* skip digits, typespec and closing ']' */
419 while (isdigit ((unsigned char)*++type
))
421 type
= objc_skip_typespec (type
);
422 if (*type
== _C_ARY_E
)
428 /* The NeXT encoding for bitfields is _still_: b 'size' */
429 while (isdigit ((unsigned char)*++type
))
430 ; /* skip type and size */
434 /* skip name, and elements until closing '}' */
436 while (*type
!= _C_STRUCT_E
&& *type
++ != '=')
438 while (*type
!= _C_STRUCT_E
)
440 type
= objc_skip_typespec (type
);
445 /* skip name, and elements until closing ')' */
447 while (*type
!= _C_UNION_E
&& *type
++ != '=')
449 while (*type
!= _C_UNION_E
)
451 type
= objc_skip_typespec (type
);
456 /* Just skip the following typespec */
458 return objc_skip_typespec (++type
);
460 return 0; /* error */
464 Skip an offset as part of a method encoding. This is prepended by a
465 '+' if the argument is passed in registers.
468 objc_skip_offset (const char *type
)
472 while (isdigit ((unsigned char) *++type
))
478 Skip an argument specification of a method encoding.
481 objc_skip_argspec (const char *type
)
483 type
= objc_skip_typespec (type
);
484 type
= objc_skip_offset (type
);
489 objc_get_type_qualifiers (const char *type
)
497 case _C_CONST
: res
|= _F_CONST
; break;
498 case _C_IN
: res
|= _F_IN
; break;
499 case _C_INOUT
: res
|= _F_INOUT
; break;
500 case _C_OUT
: res
|= _F_OUT
; break;
501 case _C_BYCOPY
: res
|= _F_BYCOPY
; break;
502 case _C_BYREF
: res
|= _F_BYREF
; break;
503 case _C_ONEWAY
: res
|= _F_ONEWAY
; break;
504 case _C_GCINVISIBLE
: res
|= _F_GCINVISIBLE
; break;
512 /* The following three functions can be used to determine how a
513 structure is laid out by the compiler. For example:
515 struct objc_struct_layout layout;
518 objc_layout_structure (type, &layout);
519 while (objc_layout_structure_next_member (&layout))
524 objc_layout_structure_get_info (&layout, &position, &align, &type);
525 printf ("element %d has offset %d, alignment %d\n",
526 i++, position, align);
529 These functions are used by objc_sizeof_type and objc_alignof_type
530 functions to compute the size and alignment of structures. The
531 previous method of computing the size and alignment of a structure
532 was not working on some architectures, particularly on AIX, and in
533 the presence of bitfields inside the structure. */
535 objc_layout_structure (const char *type
,
536 struct objc_struct_layout
*layout
)
540 layout
->original_type
= ++type
;
542 /* Skip "<name>=" if any. Avoid embedded structures and unions. */
544 while (*ntype
!= _C_STRUCT_E
&& *ntype
!= _C_STRUCT_B
&& *ntype
!= _C_UNION_B
548 /* If there's a "<name>=", ntype - 1 points to '='; skip the name */
549 if (*(ntype
- 1) == '=')
553 layout
->prev_type
= NULL
;
554 layout
->record_size
= 0;
555 layout
->record_align
= MAX (BITS_PER_UNIT
, STRUCTURE_SIZE_BOUNDARY
);
559 objc_layout_structure_next_member (struct objc_struct_layout
*layout
)
561 register int desired_align
= 0;
563 /* The current type without the type qualifiers */
566 /* Add the size of the previous field to the size of the record. */
567 if (layout
->prev_type
)
569 type
= objc_skip_type_qualifiers (layout
->prev_type
);
571 if (*type
!= _C_BFLD
)
572 layout
->record_size
+= objc_sizeof_type (type
) * BITS_PER_UNIT
;
574 layout
->record_size
+= atoi (++type
);
577 if (*layout
->type
== _C_STRUCT_E
)
580 /* Skip the variable name if any */
581 if (*layout
->type
== '"')
583 for (layout
->type
++; *layout
->type
++ != '"';)
587 type
= objc_skip_type_qualifiers (layout
->type
);
589 desired_align
= objc_alignof_type (type
) * BITS_PER_UNIT
;
591 /* Record must have at least as much alignment as any field.
592 Otherwise, the alignment of the field within the record
594 layout
->record_align
= MAX (layout
->record_align
, desired_align
);
596 if (*type
== _C_BFLD
)
598 int bfld_size
= atoi (++type
);
599 int int_align
= __alignof__ (int) * BITS_PER_UNIT
;
600 /* If this bitfield would traverse a word alignment boundary, push it out
601 to that boundary instead. */
602 if (layout
->record_size
% int_align
603 && (layout
->record_size
/ int_align
604 < (layout
->record_size
+ bfld_size
- 1) / int_align
))
605 layout
->record_size
= ROUND (layout
->record_size
, int_align
);
607 else if (layout
->record_size
% desired_align
!= 0)
609 /* We need to skip space before this field.
610 Bump the cumulative size to multiple of field alignment. */
611 layout
->record_size
= ROUND (layout
->record_size
, desired_align
);
614 /* Jump to the next field in record. */
616 layout
->prev_type
= layout
->type
;
617 layout
->type
= objc_skip_typespec (layout
->type
); /* skip component */
623 void objc_layout_finish_structure (struct objc_struct_layout
*layout
,
627 if (layout
->type
&& *layout
->type
== _C_STRUCT_E
)
629 /* Round the size up to be a multiple of the required alignment */
630 layout
->record_size
= ROUND (layout
->record_size
, layout
->record_align
);
634 *size
= layout
->record_size
/ BITS_PER_UNIT
;
636 *align
= layout
->record_align
/ BITS_PER_UNIT
;
640 void objc_layout_structure_get_info (struct objc_struct_layout
*layout
,
641 unsigned int *offset
,
646 *offset
= layout
->record_size
/ BITS_PER_UNIT
;
648 *align
= layout
->record_align
/ BITS_PER_UNIT
;
650 *type
= layout
->prev_type
;
653 #endif /* __NEXT_RUNTIME__ */
654 #endif /* _OBJC_TEST_SUITE_NEXT_ENCODE_ASSIST_IMPL_H_ */