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