|
|
1.1 root 1: /* Encoding of types for Objective C.
2: Copyright (C) 1993 Free Software Foundation, Inc.
3:
4: Author: Kresten Krab Thorup
5:
6: This file is part of GNU CC.
7:
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.
12:
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.
17:
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. */
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:
1.1.1.2 ! root 38: #define ROUND(V, A) \
! 39: ({ typeof(V) __v=(V); typeof(A) __a=(A); \
! 40: __a*((__v+__a-1)/__a); })
! 41:
1.1 root 42:
43: static inline int
44: atoi (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:
58: int
59: objc_sizeof_type(const char* type)
60: {
61: switch(*type) {
62: case _C_ID:
63: return sizeof(id);
64: break;
65:
66: case _C_CLASS:
67: return sizeof(Class*);
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:
1.1.1.2 ! root 106: case _C_FLT:
! 107: return sizeof(float);
! 108: break;
! 109:
! 110: case _C_DBL:
! 111: return sizeof(double);
! 112: break;
! 113:
1.1 root 114: case _C_PTR:
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>=" */
1.1.1.2 ! root 133: while (*type != _C_STRUCT_E)
1.1 root 134: {
135: align = objc_alignof_type (type); /* padd to alignment */
1.1.1.2 ! root 136: acc_size = ROUND (acc_size, align);
1.1 root 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:
156: abort();
157: }
158: }
159:
160:
161: /*
162: Return the alignment of an object specified by type
163: */
164:
165: int
166: objc_alignof_type(const char* type)
167: {
168: switch(*type) {
169: case _C_ID:
170: return __alignof__(id);
171: break;
172:
173: case _C_CLASS:
174: return __alignof__(Class*);
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:
1.1.1.2 ! root 213: case _C_FLT:
! 214: return __alignof__(float);
! 215: break;
! 216:
! 217: case _C_DBL:
! 218: return __alignof__(double);
! 219: break;
! 220:
1.1 root 221: case _C_ATOM:
222: case _C_CHARPTR:
223: return __alignof__(char*);
224: break;
225:
226: case _C_ARY_B:
227: while (isdigit(*++type)) /* do nothing */;
228: return objc_alignof_type (type);
229:
230: case _C_STRUCT_B:
231: {
232: struct { int x; double y; } fooalign;
233: while(*type != _C_STRUCT_E && *type++ != '=') /* do nothing */;
234: if (*type != _C_STRUCT_E)
235: return MAX (objc_alignof_type (type), __alignof__ (fooalign));
236: else
237: return __alignof__ (fooalign);
238: }
239:
240: case _C_UNION_B:
241: {
242: int maxalign = 0;
243: while (*type != _C_UNION_E && *type++ != '=') /* do nothing */;
244: while (*type != _C_UNION_E)
245: {
246: maxalign = MAX (maxalign, objc_alignof_type (type));
247: type = objc_skip_typespec (type);
248: }
249: return maxalign;
250: }
251:
252: default:
253: abort();
254: }
255: }
256:
257: /*
258: The aligned size if the size rounded up to the nearest alignment.
259: */
260:
261: int
262: objc_aligned_size (const char* type)
263: {
264: int size = objc_sizeof_type (type);
265: int align = objc_alignof_type (type);
1.1.1.2 ! root 266: return ROUND (size, align);
1.1 root 267: }
268:
269: /*
270: The size rounded up to the nearest integral of the wordsize, taken
271: to be the size of a void*.
272: */
273:
274: int
275: objc_promoted_size (const char* type)
276: {
277: int size = objc_sizeof_type (type);
278: int wordsize = sizeof (void*);
279:
1.1.1.2 ! root 280: return ROUND (size, wordsize);
1.1 root 281: }
282:
283: /*
284: Skip type qualifiers. These may eventually precede typespecs
285: occuring in method prototype encodings.
286: */
287:
288: inline const char*
289: objc_skip_type_qualifiers (const char* type)
290: {
291: while (*type == _C_CONST
292: || *type == _C_IN
293: || *type == _C_INOUT
294: || *type == _C_OUT
295: || *type == _C_BYCOPY
296: || *type == _C_ONEWAY)
297: {
298: type += 1;
299: }
300: return type;
301: }
302:
303:
304: /*
305: Skip one typespec element. If the typespec is prepended by type
306: qualifiers, these are skipped as well.
307: */
308:
309: const char*
310: objc_skip_typespec (const char* type)
311: {
312: type = objc_skip_type_qualifiers (type);
313:
314: switch (*type) {
315:
316: case _C_ID:
317: /* An id may be annotated by the actual type if it is known
318: with the @"ClassName" syntax */
319:
320: if (*++type != '"')
321: return type;
322: else
323: {
324: while (*++type != '"') /* do nothing */;
325: return type + 1;
326: }
327:
328: /* The following are one character type codes */
329: case _C_CLASS:
330: case _C_SEL:
331: case _C_CHR:
332: case _C_UCHR:
333: case _C_CHARPTR:
334: case _C_ATOM:
335: case _C_SHT:
336: case _C_USHT:
337: case _C_INT:
338: case _C_UINT:
339: case _C_LNG:
340: case _C_ULNG:
341: case _C_FLT:
342: case _C_DBL:
343: case _C_VOID:
344: return ++type;
345: break;
346:
347: case _C_ARY_B:
348: /* skip digits, typespec and closing ']' */
349:
350: while(isdigit(*++type));
351: type = objc_skip_typespec(type);
352: if (*type == _C_ARY_E)
353: return ++type;
354: else
355: abort();
356:
357: case _C_STRUCT_B:
358: /* skip name, and elements until closing '}' */
359:
360: while (*type != _C_STRUCT_E && *type++ != '=');
361: while (*type != _C_STRUCT_E) { type = objc_skip_typespec (type); }
362: return ++type;
363:
364: case _C_UNION_B:
365: /* skip name, and elements until closing ')' */
366:
367: while (*type != _C_UNION_E && *type++ != '=');
368: while (*type != _C_UNION_E) { type = objc_skip_typespec (type); }
369: return ++type;
370:
371: case _C_PTR:
372: /* Just skip the following typespec */
373:
374: return objc_skip_typespec (++type);
375:
376: default:
377: abort();
378: }
379: }
380:
381: /*
382: Skip an offset as part of a method encoding. This is prepended by a
383: '+' if the argument is passed in registers.
384: */
385: inline const char*
386: objc_skip_offset (const char* type)
387: {
388: if (*type == '+') type++;
389: while(isdigit(*++type));
390: return type;
391: }
392:
393: /*
394: Skip an argument specification of a method encoding.
395: */
396: const char*
397: objc_skip_argspec (const char* type)
398: {
399: type = objc_skip_typespec (type);
400: type = objc_skip_offset (type);
401: return type;
402: }
403:
404: /*
405: Return the number of arguments that the method MTH expects.
406: Note that all methods need two implicit arguments `self' and
407: `_cmd'.
408: */
409: int
410: method_get_number_of_arguments (struct objc_method* mth)
411: {
412: int i = 0;
413: const char* type = mth->method_types;
414: while (*type)
415: {
416: type = objc_skip_argspec (type);
417: i += 1;
418: }
419: return i - 1;
420: }
421:
422: /*
423: Return the size of the argument block needed on the stack to invoke
424: the method MTH. This may be zero, if all arguments are passed in
425: registers.
426: */
427:
428: int
429: method_get_sizeof_arguments (struct objc_method* mth)
430: {
431: const char* type = objc_skip_typespec (mth->method_types);
432: return atoi (type);
433: }
434:
435: /*
436: Return a pointer to the next argument of ARGFRAME. type points to
437: the last argument. Typical use of this look like:
438:
439: {
440: char *datum, *type;
441: for (datum = method_get_first_argument (method, argframe, &type);
442: datum; datum = method_get_next_argument (argframe, &type))
443: {
444: unsigned flags = objc_get_type_qualifiers (type);
445: type = objc_skip_type_qualifiers (type);
446: if (*type != _C_PTR)
447: [portal encodeData: datum ofType: type];
448: else
449: {
450: if ((flags & _F_IN) == _F_IN)
451: [portal encodeData: *(char**)datum ofType: ++type];
452: }
453: }
454: }
455: */
456:
457: char*
458: method_get_next_argument (arglist_t argframe,
459: const char **type)
460: {
461: const char *t = objc_skip_argspec (*type);
462:
463: if (*t == '\0')
464: return 0;
465:
466: *type = t;
467: t = objc_skip_typespec (t);
468:
469: if (*t == '+')
470: return argframe->arg_regs + atoi (++t);
471: else
472: return argframe->arg_ptr + atoi (t);
473: }
474:
475: /*
476: Return a pointer to the value of the first argument of the method
477: described in M with the given argumentframe ARGFRAME. The type
478: is returned in TYPE. type must be passed to successive calls of
479: method_get_next_argument.
480: */
481: char*
482: method_get_first_argument (struct objc_method* m,
483: arglist_t argframe,
484: const char** type)
485: {
486: *type = m->method_types;
487: return method_get_next_argument (argframe, type);
488: }
489:
490: /*
491: Return a pointer to the ARGth argument of the method
492: M from the frame ARGFRAME. The type of the argument
493: is returned in the value-result argument TYPE
494: */
495:
496: char*
497: method_get_nth_argument (struct objc_method* m,
498: arglist_t argframe, int arg,
499: const char **type)
500: {
501: const char* t = objc_skip_argspec (m->method_types);
502:
503: if (arg > method_get_number_of_arguments (m))
504: return 0;
505:
506: while (arg--)
507: t = objc_skip_argspec (t);
508:
509: *type = t;
510: t = objc_skip_typespec (t);
511:
512: if (*t == '+')
513: return argframe->arg_regs + atoi (++t);
514: else
515: return argframe->arg_ptr + atoi (t);
516: }
517:
518: unsigned
519: objc_get_type_qualifiers (const char* type)
520: {
521: unsigned res = 0;
522: BOOL flag = YES;
523:
524: while (flag)
525: switch (*type++)
526: {
527: case _C_CONST: res |= _F_CONST; break;
528: case _C_IN: res |= _F_IN; break;
529: case _C_INOUT: res |= _F_INOUT; break;
530: case _C_OUT: res |= _F_OUT; break;
531: case _C_BYCOPY: res |= _F_BYCOPY; break;
532: case _C_ONEWAY: res |= _F_ONEWAY; break;
533: default: flag = NO;
534: }
535:
536: return res;
537: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.