objc-layout.mm 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928
  1. /*
  2. * Copyright (c) 2004-2008 Apple Inc. All rights reserved.
  3. *
  4. * @APPLE_LICENSE_HEADER_START@
  5. *
  6. * This file contains Original Code and/or Modifications of Original Code
  7. * as defined in and that are subject to the Apple Public Source License
  8. * Version 2.0 (the 'License'). You may not use this file except in
  9. * compliance with the License. Please obtain a copy of the License at
  10. * http://www.opensource.apple.com/apsl/ and read it before using this
  11. * file.
  12. *
  13. * The Original Code and all software distributed under the License are
  14. * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  15. * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  16. * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  18. * Please see the License for the specific language governing rights and
  19. * limitations under the License.
  20. *
  21. * @APPLE_LICENSE_HEADER_END@
  22. */
  23. #include <stdlib.h>
  24. #include <assert.h>
  25. #include "objc-private.h"
  26. /**********************************************************************
  27. * Object Layouts.
  28. *
  29. * Layouts are used by the garbage collector to identify references from
  30. * the object to other objects.
  31. *
  32. * Layout information is in the form of a '\0' terminated byte string.
  33. * Each byte contains a word skip count in the high nibble and a
  34. * consecutive references count in the low nibble. Counts that exceed 15 are
  35. * continued in the succeeding byte with a zero in the opposite nibble.
  36. * Objects that should be scanned conservatively will have a NULL layout.
  37. * Objects that have no references have a empty byte string.
  38. *
  39. * Example;
  40. *
  41. * For a class with pointers at offsets 4,12, 16, 32-128
  42. * the layout is { 0x11, 0x12, 0x3f, 0x0a, 0x00 } or
  43. * skip 1 - 1 reference (4)
  44. * skip 1 - 2 references (12, 16)
  45. * skip 3 - 15 references (32-88)
  46. * no skip - 10 references (92-128)
  47. * end
  48. *
  49. **********************************************************************/
  50. /**********************************************************************
  51. * compress_layout
  52. * Allocates and returns a compressed string matching the given layout bitmap.
  53. **********************************************************************/
  54. static unsigned char *
  55. compress_layout(const uint8_t *bits, size_t bitmap_bits, bool weak)
  56. {
  57. bool all_set = YES;
  58. bool none_set = YES;
  59. unsigned char *result;
  60. // overallocate a lot; reallocate at correct size later
  61. unsigned char * const layout = (unsigned char *)
  62. calloc(bitmap_bits + 1, 1);
  63. unsigned char *l = layout;
  64. size_t i = 0;
  65. while (i < bitmap_bits) {
  66. size_t skip = 0;
  67. size_t scan = 0;
  68. // Count one range each of skip and scan.
  69. while (i < bitmap_bits) {
  70. uint8_t bit = (uint8_t)((bits[i/8] >> (i % 8)) & 1);
  71. if (bit) break;
  72. i++;
  73. skip++;
  74. }
  75. while (i < bitmap_bits) {
  76. uint8_t bit = (uint8_t)((bits[i/8] >> (i % 8)) & 1);
  77. if (!bit) break;
  78. i++;
  79. scan++;
  80. none_set = NO;
  81. }
  82. // Record skip and scan
  83. if (skip) all_set = NO;
  84. if (scan) none_set = NO;
  85. while (skip > 0xf) {
  86. *l++ = 0xf0;
  87. skip -= 0xf;
  88. }
  89. if (skip || scan) {
  90. *l = (uint8_t)(skip << 4); // NOT incremented - merges with scan
  91. while (scan > 0xf) {
  92. *l++ |= 0x0f; // May merge with short skip; must calloc
  93. scan -= 0xf;
  94. }
  95. *l++ |= scan; // NOT checked for zero - always increments
  96. // May merge with short skip; must calloc
  97. }
  98. }
  99. // insert terminating byte
  100. *l++ = '\0';
  101. // return result
  102. if (none_set && weak) {
  103. result = NULL; // NULL weak layout means none-weak
  104. } else if (all_set && !weak) {
  105. result = NULL; // NULL ivar layout means all-scanned
  106. } else {
  107. result = (unsigned char *)strdup((char *)layout);
  108. }
  109. free(layout);
  110. return result;
  111. }
  112. static void set_bits(layout_bitmap bits, size_t which, size_t count)
  113. {
  114. // fixme optimize for byte/word at a time
  115. size_t bit;
  116. for (bit = which; bit < which + count && bit < bits.bitCount; bit++) {
  117. bits.bits[bit/8] |= 1 << (bit % 8);
  118. }
  119. if (bit == bits.bitCount && bit < which + count) {
  120. // couldn't fit full type in bitmap
  121. _objc_fatal("layout bitmap too short");
  122. }
  123. }
  124. static void clear_bits(layout_bitmap bits, size_t which, size_t count)
  125. {
  126. // fixme optimize for byte/word at a time
  127. size_t bit;
  128. for (bit = which; bit < which + count && bit < bits.bitCount; bit++) {
  129. bits.bits[bit/8] &= ~(1 << (bit % 8));
  130. }
  131. if (bit == bits.bitCount && bit < which + count) {
  132. // couldn't fit full type in bitmap
  133. _objc_fatal("layout bitmap too short");
  134. }
  135. }
  136. static void move_bits(layout_bitmap bits, size_t src, size_t dst,
  137. size_t count)
  138. {
  139. // fixme optimize for byte/word at a time
  140. if (dst == src) {
  141. return;
  142. }
  143. else if (dst > src) {
  144. // Copy backwards in case of overlap
  145. size_t pos = count;
  146. while (pos--) {
  147. size_t srcbit = src + pos;
  148. size_t dstbit = dst + pos;
  149. if (bits.bits[srcbit/8] & (1 << (srcbit % 8))) {
  150. bits.bits[dstbit/8] |= 1 << (dstbit % 8);
  151. } else {
  152. bits.bits[dstbit/8] &= ~(1 << (dstbit % 8));
  153. }
  154. }
  155. }
  156. else {
  157. // Copy forwards in case of overlap
  158. size_t pos;
  159. for (pos = 0; pos < count; pos++) {
  160. size_t srcbit = src + pos;
  161. size_t dstbit = dst + pos;
  162. if (bits.bits[srcbit/8] & (1 << (srcbit % 8))) {
  163. bits.bits[dstbit/8] |= 1 << (dstbit % 8);
  164. } else {
  165. bits.bits[dstbit/8] &= ~(1 << (dstbit % 8));
  166. }
  167. }
  168. }
  169. }
  170. // emacs autoindent hack - it doesn't like the loop in set_bits/clear_bits
  171. #if 0
  172. } }
  173. #endif
  174. static void decompress_layout(const unsigned char *layout_string, layout_bitmap bits)
  175. {
  176. unsigned char c;
  177. size_t bit = 0;
  178. while ((c = *layout_string++)) {
  179. unsigned char skip = (c & 0xf0) >> 4;
  180. unsigned char scan = (c & 0x0f);
  181. bit += skip;
  182. set_bits(bits, bit, scan);
  183. bit += scan;
  184. }
  185. }
  186. /***********************************************************************
  187. * layout_bitmap_create
  188. * Allocate a layout bitmap.
  189. * The new bitmap spans the given instance size bytes.
  190. * The start of the bitmap is filled from the given layout string (which
  191. * spans an instance size of layoutStringSize); the rest is zero-filled.
  192. * The returned bitmap must be freed with layout_bitmap_free().
  193. **********************************************************************/
  194. layout_bitmap
  195. layout_bitmap_create(const unsigned char *layout_string,
  196. size_t layoutStringInstanceSize,
  197. size_t instanceSize, bool weak)
  198. {
  199. layout_bitmap result;
  200. size_t words = instanceSize / sizeof(id);
  201. result.weak = weak;
  202. result.bitCount = words;
  203. result.bitsAllocated = words;
  204. result.bits = (uint8_t *)calloc((words+7)/8, 1);
  205. if (!layout_string) {
  206. if (!weak) {
  207. // NULL ivar layout means all-scanned
  208. // (but only up to layoutStringSize instance size)
  209. set_bits(result, 0, layoutStringInstanceSize/sizeof(id));
  210. } else {
  211. // NULL weak layout means none-weak.
  212. }
  213. } else {
  214. decompress_layout(layout_string, result);
  215. }
  216. return result;
  217. }
  218. /***********************************************************************
  219. * layout_bitmap_create_empty
  220. * Allocate a layout bitmap.
  221. * The new bitmap spans the given instance size bytes.
  222. * The bitmap is empty, to represent an object whose ivars are completely unscanned.
  223. * The returned bitmap must be freed with layout_bitmap_free().
  224. **********************************************************************/
  225. layout_bitmap
  226. layout_bitmap_create_empty(size_t instanceSize, bool weak)
  227. {
  228. layout_bitmap result;
  229. size_t words = instanceSize / sizeof(id);
  230. result.weak = weak;
  231. result.bitCount = words;
  232. result.bitsAllocated = words;
  233. result.bits = (uint8_t *)calloc((words+7)/8, 1);
  234. return result;
  235. }
  236. void
  237. layout_bitmap_free(layout_bitmap bits)
  238. {
  239. if (bits.bits) free(bits.bits);
  240. }
  241. const unsigned char *
  242. layout_string_create(layout_bitmap bits)
  243. {
  244. const unsigned char *result =
  245. compress_layout(bits.bits, bits.bitCount, bits.weak);
  246. #if DEBUG
  247. // paranoia: cycle to bitmap and back to string again, and compare
  248. layout_bitmap check = layout_bitmap_create(result, bits.bitCount*sizeof(id),
  249. bits.bitCount*sizeof(id), bits.weak);
  250. unsigned char *result2 =
  251. compress_layout(check.bits, check.bitCount, check.weak);
  252. if (result != result2 && 0 != strcmp((char*)result, (char *)result2)) {
  253. layout_bitmap_print(bits);
  254. layout_bitmap_print(check);
  255. _objc_fatal("libobjc bug: mishandled layout bitmap");
  256. }
  257. free(result2);
  258. layout_bitmap_free(check);
  259. #endif
  260. return result;
  261. }
  262. void
  263. layout_bitmap_set_ivar(layout_bitmap bits, const char *type, size_t offset)
  264. {
  265. // fixme only handles some types
  266. size_t bit = offset / sizeof(id);
  267. if (!type) return;
  268. if (type[0] == '@' || 0 == strcmp(type, "^@")) {
  269. // id
  270. // id *
  271. // Block ("@?")
  272. set_bits(bits, bit, 1);
  273. }
  274. else if (type[0] == '[') {
  275. // id[]
  276. char *t;
  277. unsigned long count = strtoul(type+1, &t, 10);
  278. if (t && t[0] == '@') {
  279. set_bits(bits, bit, count);
  280. }
  281. }
  282. else if (strchr(type, '@')) {
  283. _objc_inform("warning: failing to set GC layout for '%s'\n", type);
  284. }
  285. }
  286. /***********************************************************************
  287. * layout_bitmap_grow
  288. * Expand a layout bitmap to span newCount bits.
  289. * The new bits are undefined.
  290. **********************************************************************/
  291. void
  292. layout_bitmap_grow(layout_bitmap *bits, size_t newCount)
  293. {
  294. if (bits->bitCount >= newCount) return;
  295. bits->bitCount = newCount;
  296. if (bits->bitsAllocated < newCount) {
  297. size_t newAllocated = bits->bitsAllocated * 2;
  298. if (newAllocated < newCount) newAllocated = newCount;
  299. bits->bits = (uint8_t *)
  300. realloc(bits->bits, (newAllocated+7) / 8);
  301. bits->bitsAllocated = newAllocated;
  302. }
  303. assert(bits->bitsAllocated >= bits->bitCount);
  304. assert(bits->bitsAllocated >= newCount);
  305. }
  306. /***********************************************************************
  307. * layout_bitmap_slide
  308. * Slide the end of a layout bitmap farther from the start.
  309. * Slides bits [oldPos, bits.bitCount) to [newPos, bits.bitCount+newPos-oldPos)
  310. * Bits [oldPos, newPos) are zero-filled.
  311. * The bitmap is expanded and bitCount updated if necessary.
  312. * newPos >= oldPos.
  313. **********************************************************************/
  314. void
  315. layout_bitmap_slide(layout_bitmap *bits, size_t oldPos, size_t newPos)
  316. {
  317. size_t shift;
  318. size_t count;
  319. if (oldPos == newPos) return;
  320. if (oldPos > newPos) _objc_fatal("layout bitmap sliding backwards");
  321. shift = newPos - oldPos;
  322. count = bits->bitCount - oldPos;
  323. layout_bitmap_grow(bits, bits->bitCount + shift);
  324. move_bits(*bits, oldPos, newPos, count); // slide
  325. clear_bits(*bits, oldPos, shift); // zero-fill
  326. }
  327. /***********************************************************************
  328. * layout_bitmap_slide_anywhere
  329. * Slide the end of a layout bitmap relative to the start.
  330. * Like layout_bitmap_slide, but can slide backwards too.
  331. * The end of the bitmap is truncated.
  332. **********************************************************************/
  333. void
  334. layout_bitmap_slide_anywhere(layout_bitmap *bits, size_t oldPos, size_t newPos)
  335. {
  336. size_t shift;
  337. size_t count;
  338. if (oldPos == newPos) return;
  339. if (oldPos < newPos) {
  340. layout_bitmap_slide(bits, oldPos, newPos);
  341. return;
  342. }
  343. shift = oldPos - newPos;
  344. count = bits->bitCount - oldPos;
  345. move_bits(*bits, oldPos, newPos, count); // slide
  346. bits->bitCount -= shift;
  347. }
  348. /***********************************************************************
  349. * layout_bitmap_splat
  350. * Pastes the contents of bitmap src to the start of bitmap dst.
  351. * dst bits between the end of src and oldSrcInstanceSize are zeroed.
  352. * dst must be at least as long as src.
  353. * Returns YES if any of dst's bits were changed.
  354. **********************************************************************/
  355. bool
  356. layout_bitmap_splat(layout_bitmap dst, layout_bitmap src,
  357. size_t oldSrcInstanceSize)
  358. {
  359. bool changed;
  360. size_t oldSrcBitCount;
  361. size_t bit;
  362. if (dst.bitCount < src.bitCount) _objc_fatal("layout bitmap too short");
  363. changed = NO;
  364. oldSrcBitCount = oldSrcInstanceSize / sizeof(id);
  365. // fixme optimize for byte/word at a time
  366. for (bit = 0; bit < oldSrcBitCount; bit++) {
  367. int dstset = dst.bits[bit/8] & (1 << (bit % 8));
  368. int srcset = (bit < src.bitCount)
  369. ? src.bits[bit/8] & (1 << (bit % 8))
  370. : 0;
  371. if (dstset != srcset) {
  372. changed = YES;
  373. if (srcset) {
  374. dst.bits[bit/8] |= 1 << (bit % 8);
  375. } else {
  376. dst.bits[bit/8] &= ~(1 << (bit % 8));
  377. }
  378. }
  379. }
  380. return changed;
  381. }
  382. /***********************************************************************
  383. * layout_bitmap_or
  384. * Set dst=dst|src.
  385. * dst must be at least as long as src.
  386. * Returns YES if any of dst's bits were changed.
  387. **********************************************************************/
  388. bool
  389. layout_bitmap_or(layout_bitmap dst, layout_bitmap src, const char *msg)
  390. {
  391. bool changed = NO;
  392. size_t bit;
  393. if (dst.bitCount < src.bitCount) {
  394. _objc_fatal("layout_bitmap_or: layout bitmap too short%s%s",
  395. msg ? ": " : "", msg ? msg : "");
  396. }
  397. // fixme optimize for byte/word at a time
  398. for (bit = 0; bit < src.bitCount; bit++) {
  399. int dstset = dst.bits[bit/8] & (1 << (bit % 8));
  400. int srcset = src.bits[bit/8] & (1 << (bit % 8));
  401. if (srcset && !dstset) {
  402. changed = YES;
  403. dst.bits[bit/8] |= 1 << (bit % 8);
  404. }
  405. }
  406. return changed;
  407. }
  408. /***********************************************************************
  409. * layout_bitmap_clear
  410. * Set dst=dst&~src.
  411. * dst must be at least as long as src.
  412. * Returns YES if any of dst's bits were changed.
  413. **********************************************************************/
  414. bool
  415. layout_bitmap_clear(layout_bitmap dst, layout_bitmap src, const char *msg)
  416. {
  417. bool changed = NO;
  418. size_t bit;
  419. if (dst.bitCount < src.bitCount) {
  420. _objc_fatal("layout_bitmap_clear: layout bitmap too short%s%s",
  421. msg ? ": " : "", msg ? msg : "");
  422. }
  423. // fixme optimize for byte/word at a time
  424. for (bit = 0; bit < src.bitCount; bit++) {
  425. int dstset = dst.bits[bit/8] & (1 << (bit % 8));
  426. int srcset = src.bits[bit/8] & (1 << (bit % 8));
  427. if (srcset && dstset) {
  428. changed = YES;
  429. dst.bits[bit/8] &= ~(1 << (bit % 8));
  430. }
  431. }
  432. return changed;
  433. }
  434. void
  435. layout_bitmap_print(layout_bitmap bits)
  436. {
  437. size_t i;
  438. printf("%zu: ", bits.bitCount);
  439. for (i = 0; i < bits.bitCount; i++) {
  440. int set = bits.bits[i/8] & (1 << (i % 8));
  441. printf("%c", set ? '#' : '.');
  442. }
  443. printf("\n");
  444. }
  445. #if 0
  446. // The code below may be useful when interpreting ivar types more precisely.
  447. /**********************************************************************
  448. * mark_offset_for_layout
  449. *
  450. * Marks the appropriate bit in the bits array cooresponding to a the
  451. * offset of a reference. If we are scanning a nested pointer structure
  452. * then the bits array will be NULL then this function does nothing.
  453. *
  454. **********************************************************************/
  455. static void mark_offset_for_layout(long offset, long bits_size, unsigned char *bits) {
  456. // references are ignored if bits is NULL
  457. if (bits) {
  458. long slot = offset / sizeof(long);
  459. // determine byte index using (offset / 8 bits per byte)
  460. long i_byte = slot >> 3;
  461. // if the byte index is valid
  462. if (i_byte < bits_size) {
  463. // set the (offset / 8 bits per byte)th bit
  464. bits[i_byte] |= 1 << (slot & 7);
  465. } else {
  466. // offset not within instance size
  467. _objc_inform ("layout - offset exceeds instance size");
  468. }
  469. }
  470. }
  471. /**********************************************************************
  472. * skip_ivar_type_name
  473. *
  474. * Skip over the name of a field/class in an ivar type string. Names
  475. * are in the form of a double-quoted string. Returns the remaining
  476. * string.
  477. *
  478. **********************************************************************/
  479. static char *skip_ivar_type_name(char *type) {
  480. // current character
  481. char ch;
  482. // if there is an open quote
  483. if (*type == '\"') {
  484. // skip quote
  485. type++;
  486. // while no closing quote
  487. while ((ch = *type) != '\"') {
  488. // if end of string return end of string
  489. if (!ch) return type;
  490. // skip character
  491. type++;
  492. }
  493. // skip closing quote
  494. type++;
  495. }
  496. // return remaining string
  497. return type;
  498. }
  499. /**********************************************************************
  500. * skip_ivar_struct_name
  501. *
  502. * Skip over the name of a struct in an ivar type string. Names
  503. * may be followed by an equals sign. Returns the remaining string.
  504. *
  505. **********************************************************************/
  506. static char *skip_ivar_struct_name(char *type) {
  507. // get first character
  508. char ch = *type;
  509. if (ch == _C_UNDEF) {
  510. // skip undefined name
  511. type++;
  512. } else if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_') {
  513. // if alphabetic
  514. // scan alphanumerics
  515. do {
  516. // next character
  517. ch = *++type;
  518. } while ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_' || (ch >= '0' && ch <= '9'));
  519. } else {
  520. // no struct name present
  521. return type;
  522. }
  523. // skip equals sign
  524. if (*type == '=') type++;
  525. return type;
  526. }
  527. /**********************************************************************
  528. * scan_basic_ivar_type
  529. *
  530. * Determines the size and alignment of a basic ivar type. If the basic
  531. * type is a possible reference to another garbage collected type the
  532. * is_reference is set to true (false otherwise.) Returns the remaining
  533. * string.
  534. *
  535. **********************************************************************/
  536. static char *scan_ivar_type_for_layout(char *type, long offset, long bits_size, unsigned char *bits, long *next_offset);
  537. static char *scan_basic_ivar_type(char *type, long *size, long *alignment, bool *is_reference) {
  538. // assume it is a non-reference type
  539. *is_reference = NO;
  540. // get the first character (advancing string)
  541. const char *full_type = type;
  542. char ch = *type++;
  543. // GCC 4 uses for const type*.
  544. if (ch == _C_CONST) ch = *type++;
  545. // act on first character
  546. switch (ch) {
  547. case _C_ID: {
  548. // ID type
  549. // skip over optional class name
  550. type = skip_ivar_type_name(type);
  551. // size and alignment of an id type
  552. *size = sizeof(id);
  553. *alignment = __alignof(id);
  554. // is a reference type
  555. *is_reference = YES;
  556. break;
  557. }
  558. case _C_PTR: {
  559. // C pointer type
  560. // skip underlying type
  561. long ignored_offset;
  562. type = scan_ivar_type_for_layout(type, 0, 0, NULL, &ignored_offset);
  563. // size and alignment of a generic pointer type
  564. *size = sizeof(void *);
  565. *alignment = __alignof(void *);
  566. // is a reference type
  567. *is_reference = YES;
  568. break;
  569. }
  570. case _C_CHARPTR: {
  571. // C string
  572. // size and alignment of a char pointer type
  573. *size = sizeof(char *);
  574. *alignment = __alignof(char *);
  575. // is a reference type
  576. *is_reference = YES;
  577. break;
  578. }
  579. case _C_CLASS:
  580. case _C_SEL: {
  581. // classes and selectors are ignored for now
  582. *size = sizeof(void *);
  583. *alignment = __alignof(void *);
  584. break;
  585. }
  586. case _C_CHR:
  587. case _C_UCHR: {
  588. // char and unsigned char
  589. *size = sizeof(char);
  590. *alignment = __alignof(char);
  591. break;
  592. }
  593. case _C_SHT:
  594. case _C_USHT: {
  595. // short and unsigned short
  596. *size = sizeof(short);
  597. *alignment = __alignof(short);
  598. break;
  599. }
  600. case _C_ATOM:
  601. case _C_INT:
  602. case _C_UINT: {
  603. // int and unsigned int
  604. *size = sizeof(int);
  605. *alignment = __alignof(int);
  606. break;
  607. }
  608. case _C_LNG:
  609. case _C_ULNG: {
  610. // long and unsigned long
  611. *size = sizeof(long);
  612. *alignment = __alignof(long);
  613. break;
  614. }
  615. case _C_LNG_LNG:
  616. case _C_ULNG_LNG: {
  617. // long long and unsigned long long
  618. *size = sizeof(long long);
  619. *alignment = __alignof(long long);
  620. break;
  621. }
  622. case _C_VECTOR: {
  623. // vector
  624. *size = 16;
  625. *alignment = 16;
  626. break;
  627. }
  628. case _C_FLT: {
  629. // float
  630. *size = sizeof(float);
  631. *alignment = __alignof(float);
  632. break;
  633. }
  634. case _C_DBL: {
  635. // double
  636. *size = sizeof(double);
  637. *alignment = __alignof(double);
  638. break;
  639. }
  640. case _C_BFLD: {
  641. // bit field
  642. // get number of bits in bit field (advance type string)
  643. long lng = strtol(type, &type, 10);
  644. // while next type is a bit field
  645. while (*type == _C_BFLD) {
  646. // skip over _C_BFLD
  647. type++;
  648. // get next bit field length
  649. long next_lng = strtol(type, &type, 10);
  650. // if spans next word then align to next word
  651. if ((lng & ~31) != ((lng + next_lng) & ~31)) lng = (lng + 31) & ~31;
  652. // increment running length
  653. lng += next_lng;
  654. // skip over potential field name
  655. type = skip_ivar_type_name(type);
  656. }
  657. // determine number of bytes bits represent
  658. *size = (lng + 7) / 8;
  659. // byte alignment
  660. *alignment = __alignof(char);
  661. break;
  662. }
  663. case _C_BOOL: {
  664. // double
  665. *size = sizeof(BOOL);
  666. *alignment = __alignof(BOOL);
  667. break;
  668. }
  669. case _C_VOID: {
  670. // skip void types
  671. *size = 0;
  672. *alignment = __alignof(char);
  673. break;
  674. }
  675. case _C_UNDEF: {
  676. *size = 0;
  677. *alignment = __alignof(char);
  678. break;
  679. }
  680. default: {
  681. // unhandled type
  682. _objc_fatal("unrecognized character \'%c\' in ivar type: \"%s\"", ch, full_type);
  683. }
  684. }
  685. return type;
  686. }
  687. /**********************************************************************
  688. * scan_ivar_type_for_layout
  689. *
  690. * Scan an ivar type string looking for references. The offset indicates
  691. * where the ivar begins. bits is a byte array of size bits_size used to
  692. * contain the references bit map. next_offset is the offset beyond the
  693. * ivar. Returns the remaining string.
  694. *
  695. **********************************************************************/
  696. static char *scan_ivar_type_for_layout(char *type, long offset, long bits_size, unsigned char *bits, long *next_offset) {
  697. long size; // size of a basic type
  698. long alignment; // alignment of the basic type
  699. bool is_reference; // true if the type indicates a reference to a garbage collected object
  700. // get the first character
  701. char ch = *type;
  702. // GCC 4 uses for const type*.
  703. if (ch == _C_CONST) ch = *++type;
  704. // act on first character
  705. switch (ch) {
  706. case _C_ARY_B: {
  707. // array type
  708. // get the array length
  709. long lng = strtol(type + 1, &type, 10);
  710. // next type will be where to advance the type string once the array is processed
  711. char *next_type = type;
  712. // repeat the next type x lng
  713. if (!lng) {
  714. next_type = scan_ivar_type_for_layout(type, 0, 0, NULL, &offset);
  715. } else {
  716. while (lng--) {
  717. // repeatedly scan the same type
  718. next_type = scan_ivar_type_for_layout(type, offset, bits_size, bits, &offset);
  719. }
  720. }
  721. // advance the type now
  722. type = next_type;
  723. // after the end of the array
  724. *next_offset = offset;
  725. // advance over closing bracket
  726. if (*type == _C_ARY_E) type++;
  727. else _objc_inform("missing \'%c\' in ivar type.", _C_ARY_E);
  728. break;
  729. }
  730. case _C_UNION_B: {
  731. // union type
  732. // skip over possible union name
  733. type = skip_ivar_struct_name(type + 1);
  734. // need to accumulate the maximum element offset
  735. long max_offset = 0;
  736. // while not closing paren
  737. while ((ch = *type) && ch != _C_UNION_E) {
  738. // skip over potential field name
  739. type = skip_ivar_type_name(type);
  740. // scan type
  741. long union_offset;
  742. type = scan_ivar_type_for_layout(type, offset, bits_size, bits, &union_offset);
  743. // adjust the maximum element offset
  744. if (max_offset < union_offset) max_offset = union_offset;
  745. }
  746. // after the largest element
  747. *next_offset = max_offset;
  748. // advance over closing paren
  749. if (ch == _C_UNION_E) {
  750. type++;
  751. } else {
  752. _objc_inform("missing \'%c\' in ivar type", _C_UNION_E);
  753. }
  754. break;
  755. }
  756. case _C_STRUCT_B: {
  757. // struct type
  758. // skip over possible struct name
  759. type = skip_ivar_struct_name(type + 1);
  760. // while not closing brace
  761. while ((ch = *type) && ch != _C_STRUCT_E) {
  762. // skip over potential field name
  763. type = skip_ivar_type_name(type);
  764. // scan type
  765. type = scan_ivar_type_for_layout(type, offset, bits_size, bits, &offset);
  766. }
  767. // after the end of the struct
  768. *next_offset = offset;
  769. // advance over closing brace
  770. if (ch == _C_STRUCT_E) type++;
  771. else _objc_inform("missing \'%c\' in ivar type", _C_STRUCT_E);
  772. break;
  773. }
  774. default: {
  775. // basic type
  776. // scan type
  777. type = scan_basic_ivar_type(type, &size, &alignment, &is_reference);
  778. // create alignment mask
  779. alignment--;
  780. // align offset
  781. offset = (offset + alignment) & ~alignment;
  782. // if is a reference then mark in the bit map
  783. if (is_reference) mark_offset_for_layout(offset, bits_size, bits);
  784. // after the basic type
  785. *next_offset = offset + size;
  786. break;
  787. }
  788. }
  789. // return remainder of type string
  790. return type;
  791. }
  792. #endif