1 /* Encoding of types for Objective C.
2 Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
3 Contributed by Kresten Krab Thorup
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, 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); })
39 ({ typeof(V) __v=(V); typeof(A) __a=(A); \
40 __a*((__v+__a-1)/__a); })
44 atoi (const char* str
)
48 while (isdigit (*str
))
49 res
*= 10, res
+= (*str
++ - '0');
55 return the size of an object specified by type
59 objc_sizeof_type(const char* type
)
79 return sizeof(unsigned char);
87 return sizeof(unsigned short);
95 return sizeof(unsigned int);
103 return sizeof(unsigned long);
107 return sizeof(float);
111 return sizeof(double);
117 return sizeof(char*);
122 int len
= atoi(type
+1);
123 while (isdigit(*++type
));
124 return len
*objc_aligned_size (type
);
132 while (*type
!= _C_STRUCT_E
&& *type
++ != '='); /* skip "<name>=" */
133 while (*type
!= _C_STRUCT_E
)
135 align
= objc_alignof_type (type
); /* padd to alignment */
136 acc_size
= ROUND (acc_size
, align
);
137 acc_size
+= objc_sizeof_type (type
); /* add component size */
138 type
= objc_skip_typespec (type
); /* skip component */
146 while (*type
!= _C_UNION_E
&& *type
++ != '=') /* do nothing */;
147 while (*type
!= _C_UNION_E
)
149 max_size
= MAX (max_size
, objc_sizeof_type (type
));
150 type
= objc_skip_typespec (type
);
156 objc_error(nil
, OBJC_ERR_BAD_TYPE
, "unknown type %s\n", type
);
162 Return the alignment of an object specified by type
166 objc_alignof_type(const char* type
)
170 return __alignof__(id
);
174 return __alignof__(Class
);
178 return __alignof__(SEL
);
182 return __alignof__(char);
186 return __alignof__(unsigned char);
190 return __alignof__(short);
194 return __alignof__(unsigned short);
198 return __alignof__(int);
202 return __alignof__(unsigned int);
206 return __alignof__(long);
210 return __alignof__(unsigned long);
214 return __alignof__(float);
218 return __alignof__(double);
224 return __alignof__(char*);
228 while (isdigit(*++type
)) /* do nothing */;
229 return objc_alignof_type (type
);
233 struct { int x
; double y
; } fooalign
;
234 while(*type
!= _C_STRUCT_E
&& *type
++ != '=') /* do nothing */;
235 if (*type
!= _C_STRUCT_E
)
236 return MAX (objc_alignof_type (type
), __alignof__ (fooalign
));
238 return __alignof__ (fooalign
);
244 while (*type
!= _C_UNION_E
&& *type
++ != '=') /* do nothing */;
245 while (*type
!= _C_UNION_E
)
247 maxalign
= MAX (maxalign
, objc_alignof_type (type
));
248 type
= objc_skip_typespec (type
);
254 objc_error(nil
, OBJC_ERR_BAD_TYPE
, "unknown type %s\n", type
);
259 The aligned size if the size rounded up to the nearest alignment.
263 objc_aligned_size (const char* type
)
265 int size
= objc_sizeof_type (type
);
266 int align
= objc_alignof_type (type
);
267 return ROUND (size
, align
);
271 The size rounded up to the nearest integral of the wordsize, taken
272 to be the size of a void*.
276 objc_promoted_size (const char* type
)
278 int size
= objc_sizeof_type (type
);
279 int wordsize
= sizeof (void*);
281 return ROUND (size
, wordsize
);
285 Skip type qualifiers. These may eventually precede typespecs
286 occurring in method prototype encodings.
290 objc_skip_type_qualifiers (const char* type
)
292 while (*type
== _C_CONST
296 || *type
== _C_BYCOPY
297 || *type
== _C_ONEWAY
)
306 Skip one typespec element. If the typespec is prepended by type
307 qualifiers, these are skipped as well.
311 objc_skip_typespec (const char* type
)
313 type
= objc_skip_type_qualifiers (type
);
318 /* An id may be annotated by the actual type if it is known
319 with the @"ClassName" syntax */
325 while (*++type
!= '"') /* do nothing */;
329 /* The following are one character type codes */
350 /* skip digits, typespec and closing ']' */
352 while(isdigit(*++type
));
353 type
= objc_skip_typespec(type
);
354 if (*type
== _C_ARY_E
)
357 objc_error(nil
, OBJC_ERR_BAD_TYPE
, "bad array type %s\n", type
);
360 /* skip name, and elements until closing '}' */
362 while (*type
!= _C_STRUCT_E
&& *type
++ != '=');
363 while (*type
!= _C_STRUCT_E
) { type
= objc_skip_typespec (type
); }
367 /* skip name, and elements until closing ')' */
369 while (*type
!= _C_UNION_E
&& *type
++ != '=');
370 while (*type
!= _C_UNION_E
) { type
= objc_skip_typespec (type
); }
374 /* Just skip the following typespec */
376 return objc_skip_typespec (++type
);
379 objc_error(nil
, OBJC_ERR_BAD_TYPE
, "unknown type %s\n", type
);
384 Skip an offset as part of a method encoding. This is prepended by a
385 '+' if the argument is passed in registers.
388 objc_skip_offset (const char* type
)
390 if (*type
== '+') type
++;
391 while(isdigit(*++type
));
396 Skip an argument specification of a method encoding.
399 objc_skip_argspec (const char* type
)
401 type
= objc_skip_typespec (type
);
402 type
= objc_skip_offset (type
);
407 Return the number of arguments that the method MTH expects.
408 Note that all methods need two implicit arguments `self' and
412 method_get_number_of_arguments (struct objc_method
* mth
)
415 const char* type
= mth
->method_types
;
418 type
= objc_skip_argspec (type
);
425 Return the size of the argument block needed on the stack to invoke
426 the method MTH. This may be zero, if all arguments are passed in
431 method_get_sizeof_arguments (struct objc_method
* mth
)
433 const char* type
= objc_skip_typespec (mth
->method_types
);
438 Return a pointer to the next argument of ARGFRAME. type points to
439 the last argument. Typical use of this look like:
443 for (datum = method_get_first_argument (method, argframe, &type);
444 datum; datum = method_get_next_argument (argframe, &type))
446 unsigned flags = objc_get_type_qualifiers (type);
447 type = objc_skip_type_qualifiers (type);
449 [portal encodeData: datum ofType: type];
452 if ((flags & _F_IN) == _F_IN)
453 [portal encodeData: *(char**)datum ofType: ++type];
460 method_get_next_argument (arglist_t argframe
,
463 const char *t
= objc_skip_argspec (*type
);
469 t
= objc_skip_typespec (t
);
472 return argframe
->arg_regs
+ atoi (++t
);
474 return argframe
->arg_ptr
+ atoi (t
);
478 Return a pointer to the value of the first argument of the method
479 described in M with the given argumentframe ARGFRAME. The type
480 is returned in TYPE. type must be passed to successive calls of
481 method_get_next_argument.
484 method_get_first_argument (struct objc_method
* m
,
488 *type
= m
->method_types
;
489 return method_get_next_argument (argframe
, type
);
493 Return a pointer to the ARGth argument of the method
494 M from the frame ARGFRAME. The type of the argument
495 is returned in the value-result argument TYPE
499 method_get_nth_argument (struct objc_method
* m
,
500 arglist_t argframe
, int arg
,
503 const char* t
= objc_skip_argspec (m
->method_types
);
505 if (arg
> method_get_number_of_arguments (m
))
509 t
= objc_skip_argspec (t
);
512 t
= objc_skip_typespec (t
);
515 return argframe
->arg_regs
+ atoi (++t
);
517 return argframe
->arg_ptr
+ atoi (t
);
521 objc_get_type_qualifiers (const char* type
)
529 case _C_CONST
: res
|= _F_CONST
; break;
530 case _C_IN
: res
|= _F_IN
; break;
531 case _C_INOUT
: res
|= _F_INOUT
; break;
532 case _C_OUT
: res
|= _F_OUT
; break;
533 case _C_BYCOPY
: res
|= _F_BYCOPY
; break;
534 case _C_ONEWAY
: res
|= _F_ONEWAY
; break;