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