|
|
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.