|
|
1.1 root 1: /* Encoding of types for Objective C. 1.1.1.3 ! root 2: Copyright (C) 1993, 1995 Free Software Foundation, Inc. ! 3: Contributed by Kresten Krab Thorup 1.1 root 4: 5: This file is part of GNU CC. 6: 7: GNU CC is free software; you can redistribute it and/or modify 8: it under the terms of the GNU General Public License as published by 9: the Free Software Foundation; either version 2, or (at your option) 10: any later version. 11: 12: GNU CC is distributed in the hope that it will be useful, 13: but WITHOUT ANY WARRANTY; without even the implied warranty of 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15: GNU General Public License for more details. 16: 17: You should have received a copy of the GNU General Public License 18: along with GNU CC; see the file COPYING. If not, write to 1.1.1.3 ! root 19: the Free Software Foundation, 59 Temple Place - Suite 330, ! 20: Boston, MA 02111-1307, USA. */ 1.1 root 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: 1.1.1.3 ! root 67: return sizeof(Class); 1.1 root 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: 1.1.1.3 ! root 174: return __alignof__(Class); 1.1 root 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 1.1.1.3 ! root 285: occurring in method prototype encodings. 1.1 root 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.