(all insn and peephole patterns): Rewrite without using arm_output_asm_insn.
[official-gcc.git] / gcc / objc / encoding.c
blob075d2eee5cd82a167e13a84c8ace1e09ce03c68f
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)
11 any later version.
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. */
28 #include "encoding.h"
30 #define MAX(X, Y) \
31 ({ typeof(X) __x = (X), __y = (Y); \
32 (__x > __y ? __x : __y); })
34 #define MIN(X, Y) \
35 ({ typeof(X) __x = (X), __y = (Y); \
36 (__x < __y ? __x : __y); })
39 static inline int
40 atoi (const char* str)
42 int res = 0;
44 while (isdigit (*str))
45 res *= 10, res += (*str++ - '0');
47 return res;
51 return the size of an object specified by type
54 int
55 objc_sizeof_type(const char* type)
57 switch(*type) {
58 case _C_ID:
59 return sizeof(id);
60 break;
62 case _C_CLASS:
63 return sizeof(Class*);
64 break;
66 case _C_SEL:
67 return sizeof(SEL);
68 break;
70 case _C_CHR:
71 return sizeof(char);
72 break;
74 case _C_UCHR:
75 return sizeof(unsigned char);
76 break;
78 case _C_SHT:
79 return sizeof(short);
80 break;
82 case _C_USHT:
83 return sizeof(unsigned short);
84 break;
86 case _C_INT:
87 return sizeof(int);
88 break;
90 case _C_UINT:
91 return sizeof(unsigned int);
92 break;
94 case _C_LNG:
95 return sizeof(long);
96 break;
98 case _C_ULNG:
99 return sizeof(unsigned long);
100 break;
102 case _C_PTR:
103 case _C_ATOM:
104 case _C_CHARPTR:
105 return sizeof(char*);
106 break;
108 case _C_ARY_B:
110 int len = atoi(type+1);
111 while (isdigit(*++type));
112 return len*objc_aligned_size (type);
114 break;
116 case _C_STRUCT_B:
118 int acc_size = 0;
119 int align;
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 */
129 return acc_size;
132 case _C_UNION_B:
134 int max_size = 0;
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);
141 return max_size;
144 default:
145 abort();
151 Return the alignment of an object specified by type
155 objc_alignof_type(const char* type)
157 switch(*type) {
158 case _C_ID:
159 return __alignof__(id);
160 break;
162 case _C_CLASS:
163 return __alignof__(Class*);
164 break;
166 case _C_SEL:
167 return __alignof__(SEL);
168 break;
170 case _C_CHR:
171 return __alignof__(char);
172 break;
174 case _C_UCHR:
175 return __alignof__(unsigned char);
176 break;
178 case _C_SHT:
179 return __alignof__(short);
180 break;
182 case _C_USHT:
183 return __alignof__(unsigned short);
184 break;
186 case _C_INT:
187 return __alignof__(int);
188 break;
190 case _C_UINT:
191 return __alignof__(unsigned int);
192 break;
194 case _C_LNG:
195 return __alignof__(long);
196 break;
198 case _C_ULNG:
199 return __alignof__(unsigned long);
200 break;
202 case _C_ATOM:
203 case _C_CHARPTR:
204 return __alignof__(char*);
205 break;
207 case _C_ARY_B:
208 while (isdigit(*++type)) /* do nothing */;
209 return objc_alignof_type (type);
211 case _C_STRUCT_B:
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));
217 else
218 return __alignof__ (fooalign);
221 case _C_UNION_B:
223 int maxalign = 0;
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);
230 return maxalign;
233 default:
234 abort();
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);
250 else
251 return size;
255 The size rounded up to the nearest integral of the wordsize, taken
256 to be the size of a void*.
259 int
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);
267 else
268 return size;
272 Skip type qualifiers. These may eventually precede typespecs
273 occuring in method prototype encodings.
276 inline const char*
277 objc_skip_type_qualifiers (const char* type)
279 while (*type == _C_CONST
280 || *type == _C_IN
281 || *type == _C_INOUT
282 || *type == _C_OUT
283 || *type == _C_BYCOPY
284 || *type == _C_ONEWAY)
286 type += 1;
288 return type;
293 Skip one typespec element. If the typespec is prepended by type
294 qualifiers, these are skipped as well.
297 const char*
298 objc_skip_typespec (const char* type)
300 type = objc_skip_type_qualifiers (type);
302 switch (*type) {
304 case _C_ID:
305 /* An id may be annotated by the actual type if it is known
306 with the @"ClassName" syntax */
308 if (*++type != '"')
309 return type;
310 else
312 while (*++type != '"') /* do nothing */;
313 return type + 1;
316 /* The following are one character type codes */
317 case _C_CLASS:
318 case _C_SEL:
319 case _C_CHR:
320 case _C_UCHR:
321 case _C_CHARPTR:
322 case _C_ATOM:
323 case _C_SHT:
324 case _C_USHT:
325 case _C_INT:
326 case _C_UINT:
327 case _C_LNG:
328 case _C_ULNG:
329 case _C_FLT:
330 case _C_DBL:
331 case _C_VOID:
332 return ++type;
333 break;
335 case _C_ARY_B:
336 /* skip digits, typespec and closing ']' */
338 while(isdigit(*++type));
339 type = objc_skip_typespec(type);
340 if (*type == _C_ARY_E)
341 return ++type;
342 else
343 abort();
345 case _C_STRUCT_B:
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); }
350 return ++type;
352 case _C_UNION_B:
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); }
357 return ++type;
359 case _C_PTR:
360 /* Just skip the following typespec */
362 return objc_skip_typespec (++type);
364 default:
365 abort();
370 Skip an offset as part of a method encoding. This is prepended by a
371 '+' if the argument is passed in registers.
373 inline const char*
374 objc_skip_offset (const char* type)
376 if (*type == '+') type++;
377 while(isdigit(*++type));
378 return type;
382 Skip an argument specification of a method encoding.
384 const char*
385 objc_skip_argspec (const char* type)
387 type = objc_skip_typespec (type);
388 type = objc_skip_offset (type);
389 return type;
393 Return the number of arguments that the method MTH expects.
394 Note that all methods need two implicit arguments `self' and
395 `_cmd'.
398 method_get_number_of_arguments (struct objc_method* mth)
400 int i = 0;
401 const char* type = mth->method_types;
402 while (*type)
404 type = objc_skip_argspec (type);
405 i += 1;
407 return i - 1;
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
413 registers.
417 method_get_sizeof_arguments (struct objc_method* mth)
419 const char* type = objc_skip_typespec (mth->method_types);
420 return atoi (type);
424 Return a pointer to the next argument of ARGFRAME. type points to
425 the last argument. Typical use of this look like:
428 char *datum, *type;
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);
434 if (*type != _C_PTR)
435 [portal encodeData: datum ofType: type];
436 else
438 if ((flags & _F_IN) == _F_IN)
439 [portal encodeData: *(char**)datum ofType: ++type];
445 char*
446 method_get_next_argument (arglist_t argframe,
447 const char **type)
449 const char *t = objc_skip_argspec (*type);
451 if (*t == '\0')
452 return 0;
454 *type = t;
455 t = objc_skip_typespec (t);
457 if (*t == '+')
458 return argframe->arg_regs + atoi (++t);
459 else
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.
469 char*
470 method_get_first_argument (struct objc_method* m,
471 arglist_t argframe,
472 const char** type)
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
484 char*
485 method_get_nth_argument (struct objc_method* m,
486 arglist_t argframe, int arg,
487 const char **type)
489 const char* t = objc_skip_argspec (m->method_types);
491 if (arg > method_get_number_of_arguments (m))
492 return 0;
494 while (arg--)
495 t = objc_skip_argspec (t);
497 *type = t;
498 t = objc_skip_typespec (t);
500 if (*t == '+')
501 return argframe->arg_regs + atoi (++t);
502 else
503 return argframe->arg_ptr + atoi (t);
506 unsigned
507 objc_get_type_qualifiers (const char* type)
509 unsigned res = 0;
510 BOOL flag = YES;
512 while (flag)
513 switch (*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;
521 default: flag = NO;
524 return res;