1#ifndef _OBJC_TEST_SUITE_NEXT_ENCODE_ASSIST_IMPL_H_ 2#define _OBJC_TEST_SUITE_NEXT_ENCODE_ASSIST_IMPL_H_ 3 4#ifdef __NEXT_RUNTIME__ 5 6/* Determine which API to use. */ 7#include "next-abi.h" 8#ifdef NEXT_OBJC_USE_NEW_INTERFACE 9#include <objc/runtime.h> 10#else 11#include <objc/objc-runtime.h> 12#endif 13 14/* ---- */ 15 16#undef MAX 17#undef MIN 18#undef ROUND 19 20#ifdef __cplusplus 21# define MAX(X, Y) ((X > Y) ? X : Y) 22# define MIN(X, Y) ((X < Y) ? X : Y) 23# define ROUND(V, A) (A * ((V + A - 1) / A)) 24#else 25# define MAX(X, Y) \ 26 ({ typeof (X) __x = (X), __y = (Y); \ 27 (__x > __y ? __x : __y); }) 28# define MIN(X, Y) \ 29 ({ typeof (X) __x = (X), __y = (Y); \ 30 (__x < __y ? __x : __y); }) 31# define ROUND(V, A) \ 32 ({ typeof (V) __v = (V); typeof (A) __a = (A); \ 33 __a * ((__v+__a - 1)/__a); }) 34#endif 35 36#define BITS_PER_UNIT __CHAR_BIT__ 37typedef struct{ char a; } __small_struct; 38#define STRUCTURE_SIZE_BOUNDARY (BITS_PER_UNIT * sizeof (__small_struct)) 39 40/* 41 return the size of an object specified by type 42*/ 43 44int 45objc_sizeof_type (const char *type) 46{ 47 /* Skip the variable name if any */ 48 if (*type == '"') 49 { 50 for (type++; *type++ != '"';) 51 /* do nothing */; 52 } 53 54 switch (*type) { 55 case _C_ID: 56 return sizeof (id); 57 break; 58 59 case _C_CLASS: 60 return sizeof (Class); 61 break; 62 63 case _C_SEL: 64 return sizeof (SEL); 65 break; 66 67 case _C_CHR: 68 return sizeof (char); 69 break; 70 71 case _C_UCHR: 72 return sizeof (unsigned char); 73 break; 74 75 case _C_SHT: 76 return sizeof (short); 77 break; 78 79 case _C_USHT: 80 return sizeof (unsigned short); 81 break; 82 83 case _C_INT: 84 return sizeof (int); 85 break; 86 87 case _C_UINT: 88 return sizeof (unsigned int); 89 break; 90 91 case _C_LNG: 92 return sizeof (long); 93 break; 94 95 case _C_ULNG: 96 return sizeof (unsigned long); 97 break; 98 99 case _C_LNG_LNG: 100 return sizeof (long long); 101 break; 102 103 case _C_ULNG_LNG: 104 return sizeof (unsigned long long); 105 break; 106 107 case _C_FLT: 108 return sizeof (float); 109 break; 110 111 case _C_DBL: 112 return sizeof (double); 113 break; 114 115 case _C_PTR: 116 case _C_ATOM: 117 case _C_CHARPTR: 118 return sizeof (char *); 119 break; 120 121 case _C_ARY_B: 122 { 123 int len = atoi (type + 1); 124 while (isdigit ((unsigned char)*++type)) 125 ; 126 return len * objc_aligned_size (type); 127 } 128 break; 129 130 case _C_BFLD: 131 { 132 /* The NeXT encoding of bitfields is _still_: b 'size' */ 133 int size = atoi (type + 1); 134 /* Return an upper bound on byte size */ 135 return (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT; 136 } 137 138 case _C_STRUCT_B: 139 { 140 struct objc_struct_layout layout; 141 unsigned int size; 142 143 objc_layout_structure (type, &layout); 144 while (objc_layout_structure_next_member (&layout)) 145 /* do nothing */ ; 146 objc_layout_finish_structure (&layout, &size, NULL); 147 148 return size; 149 } 150 151 case _C_UNION_B: 152 { 153 int max_size = 0; 154 while (*type != _C_UNION_E && *type++ != '=') 155 /* do nothing */; 156 while (*type != _C_UNION_E) 157 { 158 /* Skip the variable name if any */ 159 if (*type == '"') 160 { 161 for (type++; *type++ != '"';) 162 /* do nothing */; 163 } 164 max_size = MAX (max_size, objc_sizeof_type (type)); 165 type = objc_skip_typespec (type); 166 } 167 return max_size; 168 } 169 } 170 return 0; /* error */ 171} 172 173 174/* 175 Return the alignment of an object specified by type 176*/ 177 178int 179objc_alignof_type (const char *type) 180{ 181 /* Skip the variable name if any */ 182 if (*type == '"') 183 { 184 for (type++; *type++ != '"';) 185 /* do nothing */; 186 } 187 switch (*type) { 188 case _C_ID: 189 return __alignof__ (id); 190 break; 191 192 case _C_CLASS: 193 return __alignof__ (Class); 194 break; 195 196 case _C_SEL: 197 return __alignof__ (SEL); 198 break; 199 200 case _C_CHR: 201 return __alignof__ (char); 202 break; 203 204 case _C_UCHR: 205 return __alignof__ (unsigned char); 206 break; 207 208 case _C_SHT: 209 return __alignof__ (short); 210 break; 211 212 case _C_USHT: 213 return __alignof__ (unsigned short); 214 break; 215 216 case _C_INT: 217 case _C_BFLD: /* This is for the NeXT only */ 218 return __alignof__ (int); 219 break; 220 221 case _C_UINT: 222 return __alignof__ (unsigned int); 223 break; 224 225 case _C_LNG: 226 return __alignof__ (long); 227 break; 228 229 case _C_ULNG: 230 return __alignof__ (unsigned long); 231 break; 232 233 case _C_LNG_LNG: 234 return __alignof__ (long long); 235 break; 236 237 case _C_ULNG_LNG: 238 return __alignof__ (unsigned long long); 239 break; 240 241 case _C_FLT: 242 return __alignof__ (float); 243 break; 244 245 case _C_DBL: 246 return __alignof__ (double); 247 break; 248 249 case _C_PTR: 250 case _C_ATOM: 251 case _C_CHARPTR: 252 return __alignof__ (char *); 253 break; 254 255 case _C_ARY_B: 256 while (isdigit ((unsigned char)*++type)) 257 /* do nothing */; 258 return objc_alignof_type (type); 259 260 case _C_STRUCT_B: 261 { 262 struct objc_struct_layout layout; 263 unsigned int align; 264 265 objc_layout_structure (type, &layout); 266 while (objc_layout_structure_next_member (&layout)) 267 /* do nothing */; 268 objc_layout_finish_structure (&layout, NULL, &align); 269 270 return align; 271 } 272 273 case _C_UNION_B: 274 { 275 int maxalign = 0; 276 while (*type != _C_UNION_E && *type++ != '=') 277 /* do nothing */; 278 while (*type != _C_UNION_E) 279 { 280 /* Skip the variable name if any */ 281 if (*type == '"') 282 { 283 for (type++; *type++ != '"';) 284 /* do nothing */; 285 } 286 maxalign = MAX (maxalign, objc_alignof_type (type)); 287 type = objc_skip_typespec (type); 288 } 289 return maxalign; 290 } 291 } 292 return 0; /* error */ 293} 294 295/* 296 The aligned size if the size rounded up to the nearest alignment. 297*/ 298 299int 300objc_aligned_size (const char *type) 301{ 302 int size, align; 303 304 /* Skip the variable name */ 305 if (*type == '"') 306 { 307 for (type++; *type++ != '"';) 308 /* do nothing */; 309 } 310 311 size = objc_sizeof_type (type); 312 align = objc_alignof_type (type); 313 314 return ROUND (size, align); 315} 316 317/* 318 The size rounded up to the nearest integral of the wordsize, taken 319 to be the size of a void *. 320*/ 321 322int 323objc_promoted_size (const char *type) 324{ 325 int size, wordsize; 326 327 /* Skip the variable name */ 328 if (*type == '"') 329 { 330 for (type++; *type++ != '"';) 331 /* do nothing */; 332 } 333 334 size = objc_sizeof_type (type); 335 wordsize = sizeof (void *); 336 337 return ROUND (size, wordsize); 338} 339 340/* 341 Skip type qualifiers. These may eventually precede typespecs 342 occurring in method prototype encodings. 343*/ 344 345const char * 346objc_skip_type_qualifiers (const char *type) 347{ 348 while (*type == _C_CONST 349 || *type == _C_IN 350 || *type == _C_INOUT 351 || *type == _C_OUT 352 || *type == _C_BYCOPY 353 || *type == _C_BYREF 354 || *type == _C_ONEWAY 355 || *type == _C_GCINVISIBLE) 356 { 357 type += 1; 358 } 359 return type; 360} 361 362/* 363 Skip one typespec element. If the typespec is prepended by type 364 qualifiers, these are skipped as well. 365*/ 366 367const char * 368objc_skip_typespec (const char *type) 369{ 370 /* Skip the variable name if any */ 371 if (*type == '"') 372 { 373 for (type++; *type++ != '"';) 374 /* do nothing */; 375 } 376 377 type = objc_skip_type_qualifiers (type); 378 379 switch (*type) { 380 381 case _C_ID: 382 /* An id may be annotated by the actual type if it is known 383 with the @"ClassName" syntax */ 384 385 if (*++type != '"') 386 return type; 387 else 388 { 389 while (*++type != '"') 390 /* do nothing */; 391 return type + 1; 392 } 393 394 /* The following are one character type codes */ 395 case _C_CLASS: 396 case _C_SEL: 397 case _C_CHR: 398 case _C_UCHR: 399 case _C_CHARPTR: 400 case _C_ATOM: 401 case _C_SHT: 402 case _C_USHT: 403 case _C_INT: 404 case _C_UINT: 405 case _C_LNG: 406 case _C_ULNG: 407 case _C_LNG_LNG: 408 case _C_ULNG_LNG: 409 case _C_FLT: 410 case _C_DBL: 411 case _C_VOID: 412 case _C_UNDEF: 413 return ++type; 414 break; 415 416 case _C_ARY_B: 417 /* skip digits, typespec and closing ']' */ 418 419 while (isdigit ((unsigned char)*++type)) 420 ; 421 type = objc_skip_typespec (type); 422 if (*type == _C_ARY_E) 423 return ++type; 424 else 425 break; /* error */ 426 427 case _C_BFLD: 428 /* The NeXT encoding for bitfields is _still_: b 'size' */ 429 while (isdigit ((unsigned char)*++type)) 430 ; /* skip type and size */ 431 return type; 432 433 case _C_STRUCT_B: 434 /* skip name, and elements until closing '}' */ 435 436 while (*type != _C_STRUCT_E && *type++ != '=') 437 ; 438 while (*type != _C_STRUCT_E) 439 { 440 type = objc_skip_typespec (type); 441 } 442 return ++type; 443 444 case _C_UNION_B: 445 /* skip name, and elements until closing ')' */ 446 447 while (*type != _C_UNION_E && *type++ != '=') 448 ; 449 while (*type != _C_UNION_E) 450 { 451 type = objc_skip_typespec (type); 452 } 453 return ++type; 454 455 case _C_PTR: 456 /* Just skip the following typespec */ 457 458 return objc_skip_typespec (++type); 459 } 460 return 0; /* error */ 461} 462 463/* 464 Skip an offset as part of a method encoding. This is prepended by a 465 '+' if the argument is passed in registers. 466*/ 467const char * 468objc_skip_offset (const char *type) 469{ 470 if (*type == '+') 471 type++; 472 while (isdigit ((unsigned char) *++type)) 473 ; 474 return type; 475} 476 477/* 478 Skip an argument specification of a method encoding. 479*/ 480const char * 481objc_skip_argspec (const char *type) 482{ 483 type = objc_skip_typespec (type); 484 type = objc_skip_offset (type); 485 return type; 486} 487 488unsigned 489objc_get_type_qualifiers (const char *type) 490{ 491 unsigned res = 0; 492 BOOL flag = YES; 493 494 while (flag) 495 switch (*type++) 496 { 497 case _C_CONST: res |= _F_CONST; break; 498 case _C_IN: res |= _F_IN; break; 499 case _C_INOUT: res |= _F_INOUT; break; 500 case _C_OUT: res |= _F_OUT; break; 501 case _C_BYCOPY: res |= _F_BYCOPY; break; 502 case _C_BYREF: res |= _F_BYREF; break; 503 case _C_ONEWAY: res |= _F_ONEWAY; break; 504 case _C_GCINVISIBLE: res |= _F_GCINVISIBLE; break; 505 default: flag = NO; 506 } 507 508 return res; 509} 510 511 512/* The following three functions can be used to determine how a 513 structure is laid out by the compiler. For example: 514 515 struct objc_struct_layout layout; 516 int i; 517 518 objc_layout_structure (type, &layout); 519 while (objc_layout_structure_next_member (&layout)) 520 { 521 int position, align; 522 const char *type; 523 524 objc_layout_structure_get_info (&layout, &position, &align, &type); 525 printf ("element %d has offset %d, alignment %d\n", 526 i++, position, align); 527 } 528 529 These functions are used by objc_sizeof_type and objc_alignof_type 530 functions to compute the size and alignment of structures. The 531 previous method of computing the size and alignment of a structure 532 was not working on some architectures, particularly on AIX, and in 533 the presence of bitfields inside the structure. */ 534void 535objc_layout_structure (const char *type, 536 struct objc_struct_layout *layout) 537{ 538 const char *ntype; 539 540 layout->original_type = ++type; 541 542 /* Skip "<name>=" if any. Avoid embedded structures and unions. */ 543 ntype = type; 544 while (*ntype != _C_STRUCT_E && *ntype != _C_STRUCT_B && *ntype != _C_UNION_B 545 && *ntype++ != '=') 546 /* do nothing */; 547 548 /* If there's a "<name>=", ntype - 1 points to '='; skip the name */ 549 if (*(ntype - 1) == '=') 550 type = ntype; 551 552 layout->type = type; 553 layout->prev_type = NULL; 554 layout->record_size = 0; 555 layout->record_align = MAX (BITS_PER_UNIT, STRUCTURE_SIZE_BOUNDARY); 556} 557 558BOOL 559objc_layout_structure_next_member (struct objc_struct_layout *layout) 560{ 561 register int desired_align = 0; 562 563 /* The current type without the type qualifiers */ 564 const char *type; 565 566 /* Add the size of the previous field to the size of the record. */ 567 if (layout->prev_type) 568 { 569 type = objc_skip_type_qualifiers (layout->prev_type); 570 571 if (*type != _C_BFLD) 572 layout->record_size += objc_sizeof_type (type) * BITS_PER_UNIT; 573 else 574 layout->record_size += atoi (++type); 575 } 576 577 if (*layout->type == _C_STRUCT_E) 578 return NO; 579 580 /* Skip the variable name if any */ 581 if (*layout->type == '"') 582 { 583 for (layout->type++; *layout->type++ != '"';) 584 /* do nothing */; 585 } 586 587 type = objc_skip_type_qualifiers (layout->type); 588 589 desired_align = objc_alignof_type (type) * BITS_PER_UNIT; 590 591 /* Record must have at least as much alignment as any field. 592 Otherwise, the alignment of the field within the record 593 is meaningless. */ 594 layout->record_align = MAX (layout->record_align, desired_align); 595 596 if (*type == _C_BFLD) 597 { 598 int bfld_size = atoi (++type); 599 int int_align = __alignof__ (int) * BITS_PER_UNIT; 600 /* If this bitfield would traverse a word alignment boundary, push it out 601 to that boundary instead. */ 602 if (layout->record_size % int_align 603 && (layout->record_size / int_align 604 < (layout->record_size + bfld_size - 1) / int_align)) 605 layout->record_size = ROUND (layout->record_size, int_align); 606 } 607 else if (layout->record_size % desired_align != 0) 608 { 609 /* We need to skip space before this field. 610 Bump the cumulative size to multiple of field alignment. */ 611 layout->record_size = ROUND (layout->record_size, desired_align); 612 } 613 614 /* Jump to the next field in record. */ 615 616 layout->prev_type = layout->type; 617 layout->type = objc_skip_typespec (layout->type); /* skip component */ 618 619 return YES; 620} 621 622 623void objc_layout_finish_structure (struct objc_struct_layout *layout, 624 unsigned int *size, 625 unsigned int *align) 626{ 627 if (layout->type && *layout->type == _C_STRUCT_E) 628 { 629 /* Round the size up to be a multiple of the required alignment */ 630 layout->record_size = ROUND (layout->record_size, layout->record_align); 631 layout->type = NULL; 632 } 633 if (size) 634 *size = layout->record_size / BITS_PER_UNIT; 635 if (align) 636 *align = layout->record_align / BITS_PER_UNIT; 637} 638 639 640void objc_layout_structure_get_info (struct objc_struct_layout *layout, 641 unsigned int *offset, 642 unsigned int *align, 643 const char **type) 644{ 645 if (offset) 646 *offset = layout->record_size / BITS_PER_UNIT; 647 if (align) 648 *align = layout->record_align / BITS_PER_UNIT; 649 if (type) 650 *type = layout->prev_type; 651} 652 653#endif /* __NEXT_RUNTIME__ */ 654#endif /* _OBJC_TEST_SUITE_NEXT_ENCODE_ASSIST_IMPL_H_ */ 655