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