1 /* Encoding of types for Objective C.
2 Copyright (C) 1993 Free Software Foundation, Inc.
4 Author: Kresten Krab Thorup
6 This file is part of GNU CC.
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING. If not, write to
20 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
22 /* As a special exception, if you link this library with files
23 compiled with GCC to produce an executable, this does not cause
24 the resulting executable to be covered by the GNU General Public License.
25 This exception does not however invalidate any other reasons why
26 the executable file might be covered by the GNU General Public License. */
31 ({ typeof(X) __x = (X), __y = (Y); \
32 (__x > __y ? __x : __y); })
35 ({ typeof(X) __x = (X), __y = (Y); \
36 (__x < __y ? __x : __y); })
40 atoi (const char* str
)
44 while (isdigit (*str
))
45 res
*= 10, res
+= (*str
++ - '0');
51 return the size of an object specified by type
55 objc_sizeof_type(const char* type
)
63 return sizeof(Class
*);
75 return sizeof(unsigned char);
83 return sizeof(unsigned short);
91 return sizeof(unsigned int);
99 return sizeof(unsigned long);
105 return sizeof(char*);
110 int len
= atoi(type
+1);
111 while (isdigit(*++type
));
112 return len
*objc_aligned_size (type
);
120 while (*type
!= _C_STRUCT_E
&& *type
++ != '='); /* skip "<name>=" */
121 while (*type
!= _C_STRUCT_E
);
123 align
= objc_alignof_type (type
); /* padd to alignment */
124 if ((acc_size
% align
) != 0)
125 acc_size
+= align
- (acc_size
% align
);
126 acc_size
+= objc_sizeof_type (type
); /* add component size */
127 type
= objc_skip_typespec (type
); /* skip component */
135 while (*type
!= _C_UNION_E
&& *type
++ != '=') /* do nothing */;
136 while (*type
!= _C_UNION_E
)
138 max_size
= MAX (max_size
, objc_sizeof_type (type
));
139 type
= objc_skip_typespec (type
);
151 Return the alignment of an object specified by type
155 objc_alignof_type(const char* type
)
159 return __alignof__(id
);
163 return __alignof__(Class
*);
167 return __alignof__(SEL
);
171 return __alignof__(char);
175 return __alignof__(unsigned char);
179 return __alignof__(short);
183 return __alignof__(unsigned short);
187 return __alignof__(int);
191 return __alignof__(unsigned int);
195 return __alignof__(long);
199 return __alignof__(unsigned long);
204 return __alignof__(char*);
208 while (isdigit(*++type
)) /* do nothing */;
209 return objc_alignof_type (type
);
213 struct { int x
; double y
; } fooalign
;
214 while(*type
!= _C_STRUCT_E
&& *type
++ != '=') /* do nothing */;
215 if (*type
!= _C_STRUCT_E
)
216 return MAX (objc_alignof_type (type
), __alignof__ (fooalign
));
218 return __alignof__ (fooalign
);
224 while (*type
!= _C_UNION_E
&& *type
++ != '=') /* do nothing */;
225 while (*type
!= _C_UNION_E
)
227 maxalign
= MAX (maxalign
, objc_alignof_type (type
));
228 type
= objc_skip_typespec (type
);
239 The aligned size if the size rounded up to the nearest alignment.
243 objc_aligned_size (const char* type
)
245 int size
= objc_sizeof_type (type
);
246 int align
= objc_alignof_type (type
);
248 if ((size
% align
) != 0)
249 return size
+ align
- (size
% align
);
255 The size rounded up to the nearest integral of the wordsize, taken
256 to be the size of a void*.
260 objc_promoted_size (const char* type
)
262 int size
= objc_sizeof_type (type
);
263 int wordsize
= sizeof (void*);
265 if ((size
% wordsize
) != 0)
266 return size
+ wordsize
- (size
% wordsize
);
272 Skip type qualifiers. These may eventually precede typespecs
273 occuring in method prototype encodings.
277 objc_skip_type_qualifiers (const char* type
)
279 while (*type
== _C_CONST
283 || *type
== _C_BYCOPY
284 || *type
== _C_ONEWAY
)
293 Skip one typespec element. If the typespec is prepended by type
294 qualifiers, these are skipped as well.
298 objc_skip_typespec (const char* type
)
300 type
= objc_skip_type_qualifiers (type
);
305 /* An id may be annotated by the actual type if it is known
306 with the @"ClassName" syntax */
312 while (*++type
!= '"') /* do nothing */;
316 /* The following are one character type codes */
336 /* skip digits, typespec and closing ']' */
338 while(isdigit(*++type
));
339 type
= objc_skip_typespec(type
);
340 if (*type
== _C_ARY_E
)
346 /* skip name, and elements until closing '}' */
348 while (*type
!= _C_STRUCT_E
&& *type
++ != '=');
349 while (*type
!= _C_STRUCT_E
) { type
= objc_skip_typespec (type
); }
353 /* skip name, and elements until closing ')' */
355 while (*type
!= _C_UNION_E
&& *type
++ != '=');
356 while (*type
!= _C_UNION_E
) { type
= objc_skip_typespec (type
); }
360 /* Just skip the following typespec */
362 return objc_skip_typespec (++type
);
370 Skip an offset as part of a method encoding. This is prepended by a
371 '+' if the argument is passed in registers.
374 objc_skip_offset (const char* type
)
376 if (*type
== '+') type
++;
377 while(isdigit(*++type
));
382 Skip an argument specification of a method encoding.
385 objc_skip_argspec (const char* type
)
387 type
= objc_skip_typespec (type
);
388 type
= objc_skip_offset (type
);
393 Return the number of arguments that the method MTH expects.
394 Note that all methods need two implicit arguments `self' and
398 method_get_number_of_arguments (struct objc_method
* mth
)
401 const char* type
= mth
->method_types
;
404 type
= objc_skip_argspec (type
);
411 Return the size of the argument block needed on the stack to invoke
412 the method MTH. This may be zero, if all arguments are passed in
417 method_get_sizeof_arguments (struct objc_method
* mth
)
419 const char* type
= objc_skip_typespec (mth
->method_types
);
424 Return a pointer to the next argument of ARGFRAME. type points to
425 the last argument. Typical use of this look like:
429 for (datum = method_get_first_argument (method, argframe, &type);
430 datum; datum = method_get_next_argument (argframe, &type))
432 unsigned flags = objc_get_type_qualifiers (type);
433 type = objc_skip_type_qualifiers (type);
435 [portal encodeData: datum ofType: type];
438 if ((flags & _F_IN) == _F_IN)
439 [portal encodeData: *(char**)datum ofType: ++type];
446 method_get_next_argument (arglist_t argframe
,
449 const char *t
= objc_skip_argspec (*type
);
455 t
= objc_skip_typespec (t
);
458 return argframe
->arg_regs
+ atoi (++t
);
460 return argframe
->arg_ptr
+ atoi (t
);
464 Return a pointer to the value of the first argument of the method
465 described in M with the given argumentframe ARGFRAME. The type
466 is returned in TYPE. type must be passed to successive calls of
467 method_get_next_argument.
470 method_get_first_argument (struct objc_method
* m
,
474 *type
= m
->method_types
;
475 return method_get_next_argument (argframe
, type
);
479 Return a pointer to the ARGth argument of the method
480 M from the frame ARGFRAME. The type of the argument
481 is returned in the value-result argument TYPE
485 method_get_nth_argument (struct objc_method
* m
,
486 arglist_t argframe
, int arg
,
489 const char* t
= objc_skip_argspec (m
->method_types
);
491 if (arg
> method_get_number_of_arguments (m
))
495 t
= objc_skip_argspec (t
);
498 t
= objc_skip_typespec (t
);
501 return argframe
->arg_regs
+ atoi (++t
);
503 return argframe
->arg_ptr
+ atoi (t
);
507 objc_get_type_qualifiers (const char* type
)
515 case _C_CONST
: res
|= _F_CONST
; break;
516 case _C_IN
: res
|= _F_IN
; break;
517 case _C_INOUT
: res
|= _F_INOUT
; break;
518 case _C_OUT
: res
|= _F_OUT
; break;
519 case _C_BYCOPY
: res
|= _F_BYCOPY
; break;
520 case _C_ONEWAY
: res
|= _F_ONEWAY
; break;