]> gcc.gnu.org Git - gcc.git/blame - gcc/objc/encoding.c
More system.h cutover patches:
[gcc.git] / gcc / objc / encoding.c
CommitLineData
b783df23 1/* Encoding of types for Objective C.
b2948281 2 Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
0994488a 3 Contributed by Kresten Krab Thorup
b783df23
KKT
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
84c09f78
RK
19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
b783df23
KKT
21
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. */
27
28#include "encoding.h"
29
30#define MAX(X, Y) \
31 ({ typeof(X) __x = (X), __y = (Y); \
32 (__x > __y ? __x : __y); })
33
34#define MIN(X, Y) \
35 ({ typeof(X) __x = (X), __y = (Y); \
36 (__x < __y ? __x : __y); })
37
a39d31bc
KKT
38#define ROUND(V, A) \
39 ({ typeof(V) __v=(V); typeof(A) __a=(A); \
40 __a*((__v+__a-1)/__a); })
41
b783df23
KKT
42
43static inline int
44atoi (const char* str)
45{
46 int res = 0;
47
48 while (isdigit (*str))
49 res *= 10, res += (*str++ - '0');
50
51 return res;
52}
53
54/*
55 return the size of an object specified by type
56*/
57
58int
59objc_sizeof_type(const char* type)
60{
61 switch(*type) {
62 case _C_ID:
63 return sizeof(id);
64 break;
65
66 case _C_CLASS:
0994488a 67 return sizeof(Class);
b783df23
KKT
68 break;
69
70 case _C_SEL:
71 return sizeof(SEL);
72 break;
73
74 case _C_CHR:
75 return sizeof(char);
76 break;
77
78 case _C_UCHR:
79 return sizeof(unsigned char);
80 break;
81
82 case _C_SHT:
83 return sizeof(short);
84 break;
85
86 case _C_USHT:
87 return sizeof(unsigned short);
88 break;
89
90 case _C_INT:
91 return sizeof(int);
92 break;
93
94 case _C_UINT:
95 return sizeof(unsigned int);
96 break;
97
98 case _C_LNG:
99 return sizeof(long);
100 break;
101
102 case _C_ULNG:
103 return sizeof(unsigned long);
104 break;
105
f4e12fad
KKT
106 case _C_FLT:
107 return sizeof(float);
108 break;
109
110 case _C_DBL:
111 return sizeof(double);
112 break;
113
3ea4ff2e 114 case _C_PTR:
b783df23
KKT
115 case _C_ATOM:
116 case _C_CHARPTR:
117 return sizeof(char*);
118 break;
119
120 case _C_ARY_B:
121 {
122 int len = atoi(type+1);
123 while (isdigit(*++type));
124 return len*objc_aligned_size (type);
125 }
126 break;
127
128 case _C_STRUCT_B:
129 {
130 int acc_size = 0;
131 int align;
132 while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
f4e12fad 133 while (*type != _C_STRUCT_E)
b783df23
KKT
134 {
135 align = objc_alignof_type (type); /* padd to alignment */
f4e12fad 136 acc_size = ROUND (acc_size, align);
b783df23
KKT
137 acc_size += objc_sizeof_type (type); /* add component size */
138 type = objc_skip_typespec (type); /* skip component */
139 }
140 return acc_size;
141 }
142
143 case _C_UNION_B:
144 {
145 int max_size = 0;
146 while (*type != _C_UNION_E && *type++ != '=') /* do nothing */;
147 while (*type != _C_UNION_E)
148 {
149 max_size = MAX (max_size, objc_sizeof_type (type));
150 type = objc_skip_typespec (type);
151 }
152 return max_size;
153 }
154
155 default:
b2948281 156 objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
b783df23
KKT
157 }
158}
159
160
161/*
162 Return the alignment of an object specified by type
163*/
164
165int
166objc_alignof_type(const char* type)
167{
168 switch(*type) {
169 case _C_ID:
170 return __alignof__(id);
171 break;
172
173 case _C_CLASS:
0994488a 174 return __alignof__(Class);
b783df23
KKT
175 break;
176
177 case _C_SEL:
178 return __alignof__(SEL);
179 break;
180
181 case _C_CHR:
182 return __alignof__(char);
183 break;
184
185 case _C_UCHR:
186 return __alignof__(unsigned char);
187 break;
188
189 case _C_SHT:
190 return __alignof__(short);
191 break;
192
193 case _C_USHT:
194 return __alignof__(unsigned short);
195 break;
196
197 case _C_INT:
198 return __alignof__(int);
199 break;
200
201 case _C_UINT:
202 return __alignof__(unsigned int);
203 break;
204
205 case _C_LNG:
206 return __alignof__(long);
207 break;
208
209 case _C_ULNG:
210 return __alignof__(unsigned long);
211 break;
212
f4e12fad
KKT
213 case _C_FLT:
214 return __alignof__(float);
215 break;
216
217 case _C_DBL:
218 return __alignof__(double);
219 break;
220
3ea4ff2e 221 case _C_PTR:
b783df23
KKT
222 case _C_ATOM:
223 case _C_CHARPTR:
224 return __alignof__(char*);
225 break;
226
227 case _C_ARY_B:
228 while (isdigit(*++type)) /* do nothing */;
229 return objc_alignof_type (type);
230
231 case _C_STRUCT_B:
232 {
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));
237 else
238 return __alignof__ (fooalign);
239 }
240
241 case _C_UNION_B:
242 {
243 int maxalign = 0;
244 while (*type != _C_UNION_E && *type++ != '=') /* do nothing */;
245 while (*type != _C_UNION_E)
246 {
247 maxalign = MAX (maxalign, objc_alignof_type (type));
248 type = objc_skip_typespec (type);
249 }
250 return maxalign;
251 }
252
253 default:
b2948281 254 objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
b783df23
KKT
255 }
256}
257
258/*
259 The aligned size if the size rounded up to the nearest alignment.
260*/
261
262int
263objc_aligned_size (const char* type)
264{
265 int size = objc_sizeof_type (type);
266 int align = objc_alignof_type (type);
a39d31bc 267 return ROUND (size, align);
b783df23
KKT
268}
269
270/*
271 The size rounded up to the nearest integral of the wordsize, taken
272 to be the size of a void*.
273*/
274
275int
276objc_promoted_size (const char* type)
277{
278 int size = objc_sizeof_type (type);
279 int wordsize = sizeof (void*);
280
a39d31bc 281 return ROUND (size, wordsize);
b783df23
KKT
282}
283
284/*
285 Skip type qualifiers. These may eventually precede typespecs
9faa82d8 286 occurring in method prototype encodings.
b783df23
KKT
287*/
288
289inline const char*
290objc_skip_type_qualifiers (const char* type)
291{
292 while (*type == _C_CONST
293 || *type == _C_IN
294 || *type == _C_INOUT
295 || *type == _C_OUT
296 || *type == _C_BYCOPY
297 || *type == _C_ONEWAY)
298 {
299 type += 1;
300 }
301 return type;
302}
303
304
305/*
306 Skip one typespec element. If the typespec is prepended by type
307 qualifiers, these are skipped as well.
308*/
309
310const char*
311objc_skip_typespec (const char* type)
312{
313 type = objc_skip_type_qualifiers (type);
314
315 switch (*type) {
316
317 case _C_ID:
318 /* An id may be annotated by the actual type if it is known
319 with the @"ClassName" syntax */
320
321 if (*++type != '"')
322 return type;
323 else
324 {
325 while (*++type != '"') /* do nothing */;
326 return type + 1;
327 }
328
329 /* The following are one character type codes */
330 case _C_CLASS:
331 case _C_SEL:
332 case _C_CHR:
333 case _C_UCHR:
334 case _C_CHARPTR:
335 case _C_ATOM:
336 case _C_SHT:
337 case _C_USHT:
338 case _C_INT:
339 case _C_UINT:
340 case _C_LNG:
341 case _C_ULNG:
342 case _C_FLT:
343 case _C_DBL:
344 case _C_VOID:
f061780b 345 case _C_UNDEF:
b783df23
KKT
346 return ++type;
347 break;
348
349 case _C_ARY_B:
350 /* skip digits, typespec and closing ']' */
351
352 while(isdigit(*++type));
353 type = objc_skip_typespec(type);
354 if (*type == _C_ARY_E)
355 return ++type;
356 else
b2948281 357 objc_error(nil, OBJC_ERR_BAD_TYPE, "bad array type %s\n", type);
b783df23
KKT
358
359 case _C_STRUCT_B:
360 /* skip name, and elements until closing '}' */
361
362 while (*type != _C_STRUCT_E && *type++ != '=');
363 while (*type != _C_STRUCT_E) { type = objc_skip_typespec (type); }
364 return ++type;
365
366 case _C_UNION_B:
367 /* skip name, and elements until closing ')' */
368
369 while (*type != _C_UNION_E && *type++ != '=');
370 while (*type != _C_UNION_E) { type = objc_skip_typespec (type); }
371 return ++type;
372
373 case _C_PTR:
374 /* Just skip the following typespec */
375
376 return objc_skip_typespec (++type);
377
378 default:
b2948281 379 objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
b783df23
KKT
380 }
381}
382
383/*
384 Skip an offset as part of a method encoding. This is prepended by a
385 '+' if the argument is passed in registers.
386*/
387inline const char*
388objc_skip_offset (const char* type)
389{
390 if (*type == '+') type++;
391 while(isdigit(*++type));
392 return type;
393}
394
395/*
396 Skip an argument specification of a method encoding.
397*/
398const char*
399objc_skip_argspec (const char* type)
400{
401 type = objc_skip_typespec (type);
402 type = objc_skip_offset (type);
403 return type;
404}
405
406/*
407 Return the number of arguments that the method MTH expects.
408 Note that all methods need two implicit arguments `self' and
409 `_cmd'.
410*/
411int
412method_get_number_of_arguments (struct objc_method* mth)
413{
414 int i = 0;
415 const char* type = mth->method_types;
416 while (*type)
417 {
418 type = objc_skip_argspec (type);
419 i += 1;
420 }
421 return i - 1;
422}
423
424/*
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
427 registers.
428*/
429
430int
431method_get_sizeof_arguments (struct objc_method* mth)
432{
433 const char* type = objc_skip_typespec (mth->method_types);
434 return atoi (type);
435}
436
437/*
438 Return a pointer to the next argument of ARGFRAME. type points to
439 the last argument. Typical use of this look like:
440
441 {
442 char *datum, *type;
443 for (datum = method_get_first_argument (method, argframe, &type);
444 datum; datum = method_get_next_argument (argframe, &type))
445 {
446 unsigned flags = objc_get_type_qualifiers (type);
447 type = objc_skip_type_qualifiers (type);
448 if (*type != _C_PTR)
449 [portal encodeData: datum ofType: type];
450 else
451 {
452 if ((flags & _F_IN) == _F_IN)
453 [portal encodeData: *(char**)datum ofType: ++type];
454 }
455 }
456 }
457*/
458
459char*
460method_get_next_argument (arglist_t argframe,
461 const char **type)
462{
463 const char *t = objc_skip_argspec (*type);
464
465 if (*t == '\0')
466 return 0;
467
468 *type = t;
469 t = objc_skip_typespec (t);
470
471 if (*t == '+')
472 return argframe->arg_regs + atoi (++t);
473 else
474 return argframe->arg_ptr + atoi (t);
475}
476
477/*
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.
482*/
483char*
484method_get_first_argument (struct objc_method* m,
485 arglist_t argframe,
486 const char** type)
487{
488 *type = m->method_types;
489 return method_get_next_argument (argframe, type);
490}
491
492/*
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
496*/
497
498char*
499method_get_nth_argument (struct objc_method* m,
500 arglist_t argframe, int arg,
501 const char **type)
502{
503 const char* t = objc_skip_argspec (m->method_types);
504
505 if (arg > method_get_number_of_arguments (m))
506 return 0;
507
508 while (arg--)
509 t = objc_skip_argspec (t);
510
511 *type = t;
512 t = objc_skip_typespec (t);
513
514 if (*t == '+')
515 return argframe->arg_regs + atoi (++t);
516 else
517 return argframe->arg_ptr + atoi (t);
518}
519
520unsigned
521objc_get_type_qualifiers (const char* type)
522{
523 unsigned res = 0;
524 BOOL flag = YES;
525
526 while (flag)
527 switch (*type++)
528 {
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;
535 default: flag = NO;
536 }
537
538 return res;
539}
This page took 0.416305 seconds and 5 git commands to generate.