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