]>
Commit | Line | Data |
---|---|---|
88e17b57 | 1 | /* Encoding of types for Objective C. |
5624e564 | 2 | Copyright (C) 1993-2015 Free Software Foundation, Inc. |
88e17b57 BE |
3 | Contributed by Kresten Krab Thorup |
4 | Bitfield support by Ovidiu Predescu | |
5 | ||
6c82ad25 | 6 | This file is part of GCC. |
88e17b57 | 7 | |
6c82ad25 | 8 | GCC is free software; you can redistribute it and/or modify |
88e17b57 | 9 | it under the terms of the GNU General Public License as published by |
748086b7 | 10 | the Free Software Foundation; either version 3, or (at your option) |
88e17b57 BE |
11 | any later version. |
12 | ||
6c82ad25 | 13 | GCC is distributed in the hope that it will be useful, |
88e17b57 BE |
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 | ||
748086b7 JJ |
18 | Under Section 7 of GPL version 3, you are granted additional |
19 | permissions described in the GCC Runtime Library Exception, version | |
20 | 3.1, as published by the Free Software Foundation. | |
88e17b57 | 21 | |
748086b7 JJ |
22 | You should have received a copy of the GNU General Public License and |
23 | a copy of the GCC Runtime Library Exception along with this program; | |
24 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
25 | <http://www.gnu.org/licenses/>. */ | |
88e17b57 | 26 | |
4977bab6 ZW |
27 | /* FIXME: This file has no business including tm.h. */ |
28 | ||
7b869986 | 29 | /* FIXME: This file contains functions that will abort the entire |
c994cc85 | 30 | program if they fail. Is that really needed ? */ |
7b869986 | 31 | |
539280a8 | 32 | #include "config.h" |
6dead247 | 33 | #include "objc-private/common.h" |
7b869986 | 34 | #include "objc-private/error.h" |
88e17b57 | 35 | #include "tconfig.h" |
4977bab6 ZW |
36 | #include "coretypes.h" |
37 | #include "tm.h" | |
718a8e53 NP |
38 | #include "objc/runtime.h" |
39 | #include "objc-private/module-abi-8.h" /* For struct objc_method */ | |
b62cc13a | 40 | #include <stdlib.h> |
718a8e53 | 41 | #include <ctype.h> |
ad49efbd | 42 | #include <string.h> /* For memcpy. */ |
88e17b57 | 43 | |
d0d091ae | 44 | #undef MAX |
88e17b57 | 45 | #define MAX(X, Y) \ |
40165636 | 46 | ({ typeof (X) __x = (X), __y = (Y); \ |
88e17b57 BE |
47 | (__x > __y ? __x : __y); }) |
48 | ||
d0d091ae | 49 | #undef MIN |
88e17b57 | 50 | #define MIN(X, Y) \ |
40165636 | 51 | ({ typeof (X) __x = (X), __y = (Y); \ |
88e17b57 BE |
52 | (__x < __y ? __x : __y); }) |
53 | ||
d0d091ae | 54 | #undef ROUND |
88e17b57 | 55 | #define ROUND(V, A) \ |
40165636 RB |
56 | ({ typeof (V) __v = (V); typeof (A) __a = (A); \ |
57 | __a * ((__v+__a - 1)/__a); }) | |
88e17b57 BE |
58 | |
59 | ||
60 | /* Various hacks for objc_layout_record. These are used by the target | |
61 | macros. */ | |
62 | ||
120d59bf DE |
63 | #define TREE_CODE(TYPE) *(TYPE) |
64 | #define TREE_TYPE(TREE) (TREE) | |
2e5f02a3 | 65 | |
88e17b57 BE |
66 | #define RECORD_TYPE _C_STRUCT_B |
67 | #define UNION_TYPE _C_UNION_B | |
68 | #define QUAL_UNION_TYPE _C_UNION_B | |
2e5f02a3 | 69 | #define ARRAY_TYPE _C_ARY_B |
88e17b57 | 70 | |
49073def JW |
71 | #define REAL_TYPE _C_DBL |
72 | ||
f4fdaeda AH |
73 | #define VECTOR_TYPE _C_VECTOR |
74 | ||
761c0d29 AP |
75 | #define TYPE_FIELDS(TYPE) ({const char *_field = (TYPE)+1; \ |
76 | while (*_field != _C_STRUCT_E && *_field != _C_STRUCT_B \ | |
77 | && *_field != _C_UNION_B && *_field++ != '=') \ | |
78 | /* do nothing */; \ | |
79 | _field;}) | |
88e17b57 | 80 | |
120d59bf DE |
81 | #define DECL_MODE(TYPE) *(TYPE) |
82 | #define TYPE_MODE(TYPE) *(TYPE) | |
88e17b57 BE |
83 | |
84 | #define DFmode _C_DBL | |
85 | ||
dd25a747 | 86 | #define strip_array_types(TYPE) ({const char *_field = (TYPE); \ |
761c0d29 AP |
87 | while (*_field == _C_ARY_B)\ |
88 | {\ | |
89 | while (isdigit ((unsigned char)*++_field))\ | |
90 | ;\ | |
91 | }\ | |
92 | _field;}) | |
88e17b57 | 93 | |
919ee051 RE |
94 | /* Some ports (eg ARM) allow the structure size boundary to be |
95 | selected at compile-time. We override the normal definition with | |
96 | one that has a constant value for this compilation. */ | |
e7ebc32a NC |
97 | #ifndef BITS_PER_UNIT |
98 | #define BITS_PER_UNIT 8 | |
99 | #endif | |
100 | #undef STRUCTURE_SIZE_BOUNDARY | |
919ee051 | 101 | #define STRUCTURE_SIZE_BOUNDARY (BITS_PER_UNIT * sizeof (struct{char a;})) |
88e17b57 | 102 | |
d5114db1 | 103 | /* Some ROUND_TYPE_ALIGN macros use TARGET_foo, and consequently |
0cf61401 ZW |
104 | target_flags. Define a dummy entry here to so we don't die. |
105 | We have to rename it because target_flags may already have been | |
106 | declared extern. */ | |
107 | #define target_flags not_target_flags | |
108 | static int __attribute__ ((__unused__)) not_target_flags = 0; | |
88e17b57 | 109 | |
45f17969 AP |
110 | /* Some ROUND_TYPE_ALIGN use ALTIVEC_VECTOR_MODE (rs6000 darwin). |
111 | Define a dummy ALTIVEC_VECTOR_MODE so it will not die. */ | |
112 | #undef ALTIVEC_VECTOR_MODE | |
113 | #define ALTIVEC_VECTOR_MODE(MODE) (0) | |
114 | ||
ad1a0853 MM |
115 | /* Replace TARGET_VSX, TARGET_ALTIVEC, and TARGET_64BIT with constants based on |
116 | the current switches, rather than looking in the options structure. */ | |
117 | #ifdef _ARCH_PPC | |
118 | #undef TARGET_VSX | |
119 | #undef TARGET_ALTIVEC | |
120 | #undef TARGET_64BIT | |
121 | ||
122 | #ifdef __VSX__ | |
123 | #define TARGET_VSX 1 | |
124 | #else | |
125 | #define TARGET_VSX 0 | |
126 | #endif | |
127 | ||
128 | #ifdef __ALTIVEC__ | |
129 | #define TARGET_ALTIVEC 1 | |
130 | #else | |
131 | #define TARGET_ALTIVEC 0 | |
132 | #endif | |
133 | ||
134 | #ifdef _ARCH_PPC64 | |
135 | #define TARGET_64BIT 1 | |
136 | #else | |
137 | #define TARGET_64BIT 0 | |
138 | #endif | |
139 | #endif | |
140 | ||
265a000d IS |
141 | /* Furthermore, some (powerpc) targets also use TARGET_ALIGN_NATURAL |
142 | in their alignment macros. Currently[4.5/6], rs6000.h points this | |
143 | to a static variable, initialized by target overrides. This is reset | |
144 | in linux64.h but not in darwin64.h. The macro is not used by *86*. */ | |
145 | ||
f436d2ff IS |
146 | #if __MACH__ |
147 | # if __LP64__ | |
148 | # undef TARGET_ALIGN_NATURAL | |
149 | # define TARGET_ALIGN_NATURAL 1 | |
150 | # endif | |
151 | ||
152 | /* On Darwin32, we need to recurse until we find the starting stuct type. */ | |
153 | static int | |
154 | _darwin_rs6000_special_round_type_align (const char *struc, int comp, int spec) | |
155 | { | |
156 | const char *_stp , *_fields = TYPE_FIELDS (struc); | |
157 | if (!_fields) | |
158 | return MAX (comp, spec); | |
159 | _stp = strip_array_types (_fields); | |
160 | if (TYPE_MODE(_stp) == _C_COMPLEX) | |
161 | _stp++; | |
162 | switch (TYPE_MODE(_stp)) | |
163 | { | |
164 | case RECORD_TYPE: | |
165 | case UNION_TYPE: | |
166 | return MAX (MAX (comp, spec), objc_alignof_type (_stp) * BITS_PER_UNIT); | |
167 | break; | |
168 | case DFmode: | |
169 | case _C_LNG_LNG: | |
170 | case _C_ULNG_LNG: | |
171 | return MAX (MAX (comp, spec), 64); | |
172 | break; | |
173 | ||
174 | default: | |
175 | return MAX (comp, spec); | |
176 | break; | |
177 | } | |
178 | } | |
179 | ||
180 | /* See comment below. */ | |
181 | #define darwin_rs6000_special_round_type_align(S,C,S2) \ | |
182 | (_darwin_rs6000_special_round_type_align ((char*)(S), (int)(C), (int)(S2))) | |
265a000d | 183 | #endif |
95727fb8 AP |
184 | |
185 | /* FIXME: while this file has no business including tm.h, this | |
186 | definitely has no business defining this macro but it | |
187 | is only way around without really rewritting this file, | |
f436d2ff | 188 | should look after the branch of 3.4 to fix this. */ |
95727fb8 | 189 | #define rs6000_special_round_type_align(STRUCT, COMPUTED, SPECIFIED) \ |
265a000d | 190 | ({ const char *_fields = TYPE_FIELDS (STRUCT); \ |
761c0d29 | 191 | ((_fields != 0 \ |
dd25a747 | 192 | && TYPE_MODE (strip_array_types (TREE_TYPE (_fields))) == DFmode) \ |
95727fb8 | 193 | ? MAX (MAX (COMPUTED, SPECIFIED), 64) \ |
761c0d29 | 194 | : MAX (COMPUTED, SPECIFIED));}) |
95727fb8 | 195 | |
98b383e4 | 196 | #define rs6000_special_adjust_field_align_p(FIELD, COMPUTED) 0 |
88e17b57 | 197 | |
c994cc85 NP |
198 | /* Skip a variable name, enclosed in quotes ("). */ |
199 | static inline | |
200 | const char * | |
201 | objc_skip_variable_name (const char *type) | |
88e17b57 | 202 | { |
c994cc85 | 203 | /* Skip the variable name if any. */ |
88e17b57 BE |
204 | if (*type == '"') |
205 | { | |
177b48f9 NP |
206 | /* FIXME: How do we know we won't read beyond the end of the |
207 | string. Here and in the rest of the file! */ | |
c994cc85 NP |
208 | /* Skip '"'. */ |
209 | type++; | |
210 | /* Skip to the next '"'. */ | |
211 | while (*type != '"') | |
212 | type++; | |
213 | /* Skip '"'. */ | |
214 | type++; | |
88e17b57 BE |
215 | } |
216 | ||
c994cc85 NP |
217 | return type; |
218 | } | |
219 | ||
220 | int | |
221 | objc_sizeof_type (const char *type) | |
222 | { | |
223 | type = objc_skip_variable_name (type); | |
224 | ||
40165636 | 225 | switch (*type) { |
153b4898 AP |
226 | case _C_BOOL: |
227 | return sizeof (_Bool); | |
228 | break; | |
229 | ||
88e17b57 | 230 | case _C_ID: |
40165636 | 231 | return sizeof (id); |
88e17b57 BE |
232 | break; |
233 | ||
234 | case _C_CLASS: | |
40165636 | 235 | return sizeof (Class); |
88e17b57 BE |
236 | break; |
237 | ||
238 | case _C_SEL: | |
40165636 | 239 | return sizeof (SEL); |
88e17b57 BE |
240 | break; |
241 | ||
242 | case _C_CHR: | |
40165636 | 243 | return sizeof (char); |
88e17b57 | 244 | break; |
42bac116 | 245 | |
88e17b57 | 246 | case _C_UCHR: |
40165636 | 247 | return sizeof (unsigned char); |
88e17b57 BE |
248 | break; |
249 | ||
250 | case _C_SHT: | |
40165636 | 251 | return sizeof (short); |
88e17b57 BE |
252 | break; |
253 | ||
254 | case _C_USHT: | |
40165636 | 255 | return sizeof (unsigned short); |
88e17b57 BE |
256 | break; |
257 | ||
258 | case _C_INT: | |
40165636 | 259 | return sizeof (int); |
88e17b57 BE |
260 | break; |
261 | ||
262 | case _C_UINT: | |
40165636 | 263 | return sizeof (unsigned int); |
88e17b57 BE |
264 | break; |
265 | ||
266 | case _C_LNG: | |
40165636 | 267 | return sizeof (long); |
88e17b57 BE |
268 | break; |
269 | ||
270 | case _C_ULNG: | |
40165636 | 271 | return sizeof (unsigned long); |
88e17b57 BE |
272 | break; |
273 | ||
274 | case _C_LNG_LNG: | |
40165636 | 275 | return sizeof (long long); |
88e17b57 BE |
276 | break; |
277 | ||
278 | case _C_ULNG_LNG: | |
40165636 | 279 | return sizeof (unsigned long long); |
88e17b57 BE |
280 | break; |
281 | ||
282 | case _C_FLT: | |
40165636 | 283 | return sizeof (float); |
88e17b57 BE |
284 | break; |
285 | ||
286 | case _C_DBL: | |
40165636 | 287 | return sizeof (double); |
88e17b57 BE |
288 | break; |
289 | ||
177b48f9 NP |
290 | case _C_LNG_DBL: |
291 | return sizeof (long double); | |
292 | break; | |
293 | ||
88e17b57 | 294 | case _C_VOID: |
40165636 | 295 | return sizeof (void); |
88e17b57 | 296 | break; |
40165636 | 297 | |
88e17b57 BE |
298 | case _C_PTR: |
299 | case _C_ATOM: | |
300 | case _C_CHARPTR: | |
40165636 | 301 | return sizeof (char *); |
88e17b57 BE |
302 | break; |
303 | ||
304 | case _C_ARY_B: | |
305 | { | |
40165636 RB |
306 | int len = atoi (type + 1); |
307 | while (isdigit ((unsigned char)*++type)) | |
308 | ; | |
309 | return len * objc_aligned_size (type); | |
88e17b57 | 310 | } |
42bac116 | 311 | break; |
88e17b57 | 312 | |
177b48f9 NP |
313 | case _C_VECTOR: |
314 | { | |
315 | /* Skip the '!'. */ | |
316 | type++; | |
317 | /* Skip the '['. */ | |
318 | type++; | |
319 | ||
320 | /* The size in bytes is the following number. */ | |
321 | int size = atoi (type); | |
322 | return size; | |
323 | } | |
324 | break; | |
325 | ||
88e17b57 BE |
326 | case _C_BFLD: |
327 | { | |
c994cc85 NP |
328 | /* The GNU encoding of bitfields is: b 'position' 'type' |
329 | 'size'. */ | |
88e17b57 BE |
330 | int position, size; |
331 | int startByte, endByte; | |
332 | ||
333 | position = atoi (type + 1); | |
40165636 RB |
334 | while (isdigit ((unsigned char)*++type)) |
335 | ; | |
88e17b57 BE |
336 | size = atoi (type + 1); |
337 | ||
338 | startByte = position / BITS_PER_UNIT; | |
339 | endByte = (position + size) / BITS_PER_UNIT; | |
340 | return endByte - startByte; | |
341 | } | |
342 | ||
4540a3ad | 343 | case _C_UNION_B: |
88e17b57 BE |
344 | case _C_STRUCT_B: |
345 | { | |
346 | struct objc_struct_layout layout; | |
347 | unsigned int size; | |
348 | ||
349 | objc_layout_structure (type, &layout); | |
350 | while (objc_layout_structure_next_member (&layout)) | |
351 | /* do nothing */ ; | |
352 | objc_layout_finish_structure (&layout, &size, NULL); | |
353 | ||
354 | return size; | |
355 | } | |
06b11455 AP |
356 | |
357 | case _C_COMPLEX: | |
358 | { | |
359 | type++; /* Skip after the 'j'. */ | |
360 | switch (*type) | |
361 | { | |
362 | case _C_CHR: | |
363 | return sizeof (_Complex char); | |
364 | break; | |
365 | ||
366 | case _C_UCHR: | |
367 | return sizeof (_Complex unsigned char); | |
368 | break; | |
369 | ||
370 | case _C_SHT: | |
371 | return sizeof (_Complex short); | |
372 | break; | |
373 | ||
374 | case _C_USHT: | |
375 | return sizeof (_Complex unsigned short); | |
376 | break; | |
377 | ||
378 | case _C_INT: | |
379 | return sizeof (_Complex int); | |
380 | break; | |
381 | ||
382 | case _C_UINT: | |
383 | return sizeof (_Complex unsigned int); | |
384 | break; | |
385 | ||
386 | case _C_LNG: | |
387 | return sizeof (_Complex long); | |
388 | break; | |
389 | ||
390 | case _C_ULNG: | |
391 | return sizeof (_Complex unsigned long); | |
392 | break; | |
393 | ||
394 | case _C_LNG_LNG: | |
395 | return sizeof (_Complex long long); | |
396 | break; | |
397 | ||
398 | case _C_ULNG_LNG: | |
399 | return sizeof (_Complex unsigned long long); | |
400 | break; | |
401 | ||
402 | case _C_FLT: | |
403 | return sizeof (_Complex float); | |
404 | break; | |
405 | ||
406 | case _C_DBL: | |
407 | return sizeof (_Complex double); | |
408 | break; | |
177b48f9 NP |
409 | |
410 | case _C_LNG_DBL: | |
411 | return sizeof (_Complex long double); | |
412 | break; | |
06b11455 AP |
413 | |
414 | default: | |
415 | { | |
7b869986 NP |
416 | /* FIXME: Is this so bad that we have to abort the |
417 | entire program ? (it applies to all the other | |
418 | _objc_abort calls in this file). | |
419 | */ | |
420 | _objc_abort ("unknown complex type %s\n", type); | |
06b11455 AP |
421 | return 0; |
422 | } | |
423 | } | |
424 | } | |
88e17b57 | 425 | |
88e17b57 BE |
426 | default: |
427 | { | |
7b869986 | 428 | _objc_abort ("unknown type %s\n", type); |
88e17b57 BE |
429 | return 0; |
430 | } | |
431 | } | |
432 | } | |
433 | ||
88e17b57 | 434 | int |
40165636 | 435 | objc_alignof_type (const char *type) |
88e17b57 | 436 | { |
c994cc85 NP |
437 | type = objc_skip_variable_name (type); |
438 | ||
40165636 | 439 | switch (*type) { |
153b4898 AP |
440 | case _C_BOOL: |
441 | return __alignof__ (_Bool); | |
442 | break; | |
443 | ||
88e17b57 | 444 | case _C_ID: |
40165636 | 445 | return __alignof__ (id); |
88e17b57 BE |
446 | break; |
447 | ||
448 | case _C_CLASS: | |
40165636 | 449 | return __alignof__ (Class); |
88e17b57 | 450 | break; |
42bac116 | 451 | |
88e17b57 | 452 | case _C_SEL: |
40165636 | 453 | return __alignof__ (SEL); |
88e17b57 BE |
454 | break; |
455 | ||
456 | case _C_CHR: | |
40165636 | 457 | return __alignof__ (char); |
88e17b57 | 458 | break; |
42bac116 | 459 | |
88e17b57 | 460 | case _C_UCHR: |
40165636 | 461 | return __alignof__ (unsigned char); |
88e17b57 BE |
462 | break; |
463 | ||
464 | case _C_SHT: | |
40165636 | 465 | return __alignof__ (short); |
88e17b57 BE |
466 | break; |
467 | ||
468 | case _C_USHT: | |
40165636 | 469 | return __alignof__ (unsigned short); |
88e17b57 BE |
470 | break; |
471 | ||
472 | case _C_INT: | |
40165636 | 473 | return __alignof__ (int); |
88e17b57 BE |
474 | break; |
475 | ||
476 | case _C_UINT: | |
40165636 | 477 | return __alignof__ (unsigned int); |
88e17b57 BE |
478 | break; |
479 | ||
480 | case _C_LNG: | |
40165636 | 481 | return __alignof__ (long); |
88e17b57 BE |
482 | break; |
483 | ||
484 | case _C_ULNG: | |
40165636 | 485 | return __alignof__ (unsigned long); |
88e17b57 BE |
486 | break; |
487 | ||
488 | case _C_LNG_LNG: | |
40165636 | 489 | return __alignof__ (long long); |
88e17b57 BE |
490 | break; |
491 | ||
492 | case _C_ULNG_LNG: | |
40165636 | 493 | return __alignof__ (unsigned long long); |
88e17b57 BE |
494 | break; |
495 | ||
496 | case _C_FLT: | |
40165636 | 497 | return __alignof__ (float); |
88e17b57 BE |
498 | break; |
499 | ||
500 | case _C_DBL: | |
40165636 | 501 | return __alignof__ (double); |
88e17b57 BE |
502 | break; |
503 | ||
177b48f9 NP |
504 | case _C_LNG_DBL: |
505 | return __alignof__ (long double); | |
506 | break; | |
507 | ||
88e17b57 BE |
508 | case _C_PTR: |
509 | case _C_ATOM: | |
510 | case _C_CHARPTR: | |
40165636 | 511 | return __alignof__ (char *); |
88e17b57 BE |
512 | break; |
513 | ||
514 | case _C_ARY_B: | |
40165636 RB |
515 | while (isdigit ((unsigned char)*++type)) |
516 | /* do nothing */; | |
88e17b57 BE |
517 | return objc_alignof_type (type); |
518 | ||
177b48f9 NP |
519 | case _C_VECTOR: |
520 | { | |
521 | /* Skip the '!'. */ | |
522 | type++; | |
523 | /* Skip the '['. */ | |
524 | type++; | |
525 | ||
526 | /* Skip the size. */ | |
527 | while (isdigit ((unsigned char)*type)) | |
528 | type++; | |
529 | ||
530 | /* Skip the ','. */ | |
531 | type++; | |
532 | ||
533 | /* The alignment in bytes is the following number. */ | |
534 | return atoi (type); | |
535 | } | |
88e17b57 | 536 | case _C_STRUCT_B: |
4540a3ad | 537 | case _C_UNION_B: |
88e17b57 BE |
538 | { |
539 | struct objc_struct_layout layout; | |
540 | unsigned int align; | |
541 | ||
542 | objc_layout_structure (type, &layout); | |
543 | while (objc_layout_structure_next_member (&layout)) | |
544 | /* do nothing */; | |
545 | objc_layout_finish_structure (&layout, NULL, &align); | |
546 | ||
547 | return align; | |
548 | } | |
06b11455 AP |
549 | |
550 | ||
551 | case _C_COMPLEX: | |
552 | { | |
553 | type++; /* Skip after the 'j'. */ | |
554 | switch (*type) | |
555 | { | |
556 | case _C_CHR: | |
557 | return __alignof__ (_Complex char); | |
558 | break; | |
559 | ||
560 | case _C_UCHR: | |
561 | return __alignof__ (_Complex unsigned char); | |
562 | break; | |
563 | ||
564 | case _C_SHT: | |
565 | return __alignof__ (_Complex short); | |
566 | break; | |
567 | ||
568 | case _C_USHT: | |
569 | return __alignof__ (_Complex unsigned short); | |
570 | break; | |
571 | ||
572 | case _C_INT: | |
573 | return __alignof__ (_Complex int); | |
574 | break; | |
575 | ||
576 | case _C_UINT: | |
577 | return __alignof__ (_Complex unsigned int); | |
578 | break; | |
579 | ||
580 | case _C_LNG: | |
581 | return __alignof__ (_Complex long); | |
582 | break; | |
583 | ||
584 | case _C_ULNG: | |
585 | return __alignof__ (_Complex unsigned long); | |
586 | break; | |
587 | ||
588 | case _C_LNG_LNG: | |
589 | return __alignof__ (_Complex long long); | |
590 | break; | |
591 | ||
592 | case _C_ULNG_LNG: | |
593 | return __alignof__ (_Complex unsigned long long); | |
594 | break; | |
595 | ||
596 | case _C_FLT: | |
597 | return __alignof__ (_Complex float); | |
598 | break; | |
599 | ||
600 | case _C_DBL: | |
601 | return __alignof__ (_Complex double); | |
602 | break; | |
177b48f9 NP |
603 | |
604 | case _C_LNG_DBL: | |
605 | return __alignof__ (_Complex long double); | |
606 | break; | |
06b11455 AP |
607 | |
608 | default: | |
609 | { | |
7b869986 | 610 | _objc_abort ("unknown complex type %s\n", type); |
06b11455 AP |
611 | return 0; |
612 | } | |
613 | } | |
614 | } | |
88e17b57 | 615 | |
88e17b57 BE |
616 | default: |
617 | { | |
7b869986 | 618 | _objc_abort ("unknown type %s\n", type); |
88e17b57 BE |
619 | return 0; |
620 | } | |
621 | } | |
622 | } | |
623 | ||
88e17b57 | 624 | int |
40165636 | 625 | objc_aligned_size (const char *type) |
88e17b57 BE |
626 | { |
627 | int size, align; | |
628 | ||
c994cc85 | 629 | type = objc_skip_variable_name (type); |
88e17b57 BE |
630 | size = objc_sizeof_type (type); |
631 | align = objc_alignof_type (type); | |
632 | ||
633 | return ROUND (size, align); | |
634 | } | |
635 | ||
42bac116 | 636 | int |
40165636 | 637 | objc_promoted_size (const char *type) |
88e17b57 BE |
638 | { |
639 | int size, wordsize; | |
640 | ||
c994cc85 | 641 | type = objc_skip_variable_name (type); |
88e17b57 | 642 | size = objc_sizeof_type (type); |
40165636 | 643 | wordsize = sizeof (void *); |
88e17b57 BE |
644 | |
645 | return ROUND (size, wordsize); | |
646 | } | |
647 | ||
c994cc85 | 648 | inline |
7116b6ea | 649 | const char * |
40165636 | 650 | objc_skip_type_qualifiers (const char *type) |
88e17b57 BE |
651 | { |
652 | while (*type == _C_CONST | |
42bac116 | 653 | || *type == _C_IN |
88e17b57 | 654 | || *type == _C_INOUT |
42bac116 | 655 | || *type == _C_OUT |
88e17b57 | 656 | || *type == _C_BYCOPY |
1df287f8 | 657 | || *type == _C_BYREF |
88e17b57 BE |
658 | || *type == _C_ONEWAY |
659 | || *type == _C_GCINVISIBLE) | |
660 | { | |
661 | type += 1; | |
662 | } | |
663 | return type; | |
664 | } | |
665 | ||
c994cc85 | 666 | inline |
40165636 RB |
667 | const char * |
668 | objc_skip_typespec (const char *type) | |
88e17b57 | 669 | { |
c994cc85 | 670 | type = objc_skip_variable_name (type); |
88e17b57 | 671 | type = objc_skip_type_qualifiers (type); |
42bac116 | 672 | |
88e17b57 BE |
673 | switch (*type) { |
674 | ||
675 | case _C_ID: | |
676 | /* An id may be annotated by the actual type if it is known | |
677 | with the @"ClassName" syntax */ | |
678 | ||
679 | if (*++type != '"') | |
680 | return type; | |
681 | else | |
682 | { | |
40165636 RB |
683 | while (*++type != '"') |
684 | /* do nothing */; | |
88e17b57 BE |
685 | return type + 1; |
686 | } | |
687 | ||
688 | /* The following are one character type codes */ | |
689 | case _C_CLASS: | |
690 | case _C_SEL: | |
691 | case _C_CHR: | |
692 | case _C_UCHR: | |
693 | case _C_CHARPTR: | |
694 | case _C_ATOM: | |
695 | case _C_SHT: | |
696 | case _C_USHT: | |
697 | case _C_INT: | |
698 | case _C_UINT: | |
699 | case _C_LNG: | |
153b4898 | 700 | case _C_BOOL: |
88e17b57 BE |
701 | case _C_ULNG: |
702 | case _C_LNG_LNG: | |
703 | case _C_ULNG_LNG: | |
704 | case _C_FLT: | |
705 | case _C_DBL: | |
177b48f9 | 706 | case _C_LNG_DBL: |
88e17b57 BE |
707 | case _C_VOID: |
708 | case _C_UNDEF: | |
709 | return ++type; | |
710 | break; | |
06b11455 AP |
711 | |
712 | case _C_COMPLEX: | |
713 | return type + 2; | |
714 | break; | |
88e17b57 BE |
715 | |
716 | case _C_ARY_B: | |
717 | /* skip digits, typespec and closing ']' */ | |
40165636 RB |
718 | while (isdigit ((unsigned char)*++type)) |
719 | ; | |
720 | type = objc_skip_typespec (type); | |
88e17b57 BE |
721 | if (*type == _C_ARY_E) |
722 | return ++type; | |
723 | else | |
724 | { | |
7b869986 | 725 | _objc_abort ("bad array type %s\n", type); |
88e17b57 BE |
726 | return 0; |
727 | } | |
728 | ||
177b48f9 NP |
729 | case _C_VECTOR: |
730 | /* Skip '!' */ | |
731 | type++; | |
732 | /* Skip '[' */ | |
733 | type++; | |
734 | /* Skip digits (size) */ | |
735 | while (isdigit ((unsigned char)*type)) | |
736 | type++; | |
737 | /* Skip ',' */ | |
738 | type++; | |
739 | /* Skip digits (alignment) */ | |
740 | while (isdigit ((unsigned char)*type)) | |
741 | type++; | |
742 | /* Skip typespec. */ | |
743 | type = objc_skip_typespec (type); | |
744 | /* Skip closing ']'. */ | |
745 | if (*type == _C_ARY_E) | |
746 | return ++type; | |
747 | else | |
748 | { | |
749 | _objc_abort ("bad vector type %s\n", type); | |
750 | return 0; | |
751 | } | |
752 | ||
88e17b57 | 753 | case _C_BFLD: |
c994cc85 NP |
754 | /* The GNU encoding of bitfields is: b 'position' 'type' |
755 | 'size'. */ | |
40165636 RB |
756 | while (isdigit ((unsigned char)*++type)) |
757 | ; /* skip position */ | |
758 | while (isdigit ((unsigned char)*++type)) | |
759 | ; /* skip type and size */ | |
88e17b57 BE |
760 | return type; |
761 | ||
762 | case _C_STRUCT_B: | |
763 | /* skip name, and elements until closing '}' */ | |
42bac116 | 764 | |
40165636 RB |
765 | while (*type != _C_STRUCT_E && *type++ != '=') |
766 | ; | |
767 | while (*type != _C_STRUCT_E) | |
768 | { | |
769 | type = objc_skip_typespec (type); | |
770 | } | |
88e17b57 BE |
771 | return ++type; |
772 | ||
773 | case _C_UNION_B: | |
774 | /* skip name, and elements until closing ')' */ | |
42bac116 | 775 | |
40165636 RB |
776 | while (*type != _C_UNION_E && *type++ != '=') |
777 | ; | |
778 | while (*type != _C_UNION_E) | |
779 | { | |
780 | type = objc_skip_typespec (type); | |
781 | } | |
88e17b57 BE |
782 | return ++type; |
783 | ||
784 | case _C_PTR: | |
785 | /* Just skip the following typespec */ | |
42bac116 | 786 | |
88e17b57 | 787 | return objc_skip_typespec (++type); |
42bac116 | 788 | |
88e17b57 BE |
789 | default: |
790 | { | |
7b869986 | 791 | _objc_abort ("unknown type %s\n", type); |
88e17b57 BE |
792 | return 0; |
793 | } | |
794 | } | |
795 | } | |
796 | ||
c994cc85 | 797 | inline |
7116b6ea | 798 | const char * |
40165636 | 799 | objc_skip_offset (const char *type) |
88e17b57 | 800 | { |
c994cc85 NP |
801 | /* The offset is prepended by a '+' if the argument is passed in |
802 | registers. PS: The compiler stopped generating this '+' in | |
803 | version 3.4. */ | |
40165636 RB |
804 | if (*type == '+') |
805 | type++; | |
c994cc85 NP |
806 | |
807 | /* Some people claim that on some platforms, where the stack grows | |
808 | backwards, the compiler generates negative offsets (??). Skip a | |
809 | '-' for such a negative offset. */ | |
810 | if (*type == '-') | |
811 | type++; | |
812 | ||
813 | /* Skip the digits that represent the offset. */ | |
814 | while (isdigit ((unsigned char) *type)) | |
815 | type++; | |
816 | ||
88e17b57 BE |
817 | return type; |
818 | } | |
819 | ||
40165636 RB |
820 | const char * |
821 | objc_skip_argspec (const char *type) | |
88e17b57 BE |
822 | { |
823 | type = objc_skip_typespec (type); | |
824 | type = objc_skip_offset (type); | |
825 | return type; | |
826 | } | |
827 | ||
ad49efbd NP |
828 | char * |
829 | method_copyReturnType (struct objc_method *method) | |
830 | { | |
831 | if (method == NULL) | |
832 | return 0; | |
833 | else | |
834 | { | |
835 | char *returnValue; | |
836 | size_t returnValueSize; | |
837 | ||
838 | /* Determine returnValueSize. */ | |
839 | { | |
840 | /* Find the end of the first argument. We want to return the | |
841 | first argument spec, plus 1 byte for the \0 at the end. */ | |
842 | const char *type = method->method_types; | |
843 | if (*type == '\0') | |
844 | return NULL; | |
845 | type = objc_skip_argspec (type); | |
846 | returnValueSize = type - method->method_types + 1; | |
847 | } | |
848 | ||
849 | /* Copy the first argument into returnValue. */ | |
850 | returnValue = malloc (sizeof (char) * returnValueSize); | |
851 | memcpy (returnValue, method->method_types, returnValueSize); | |
852 | returnValue[returnValueSize - 1] = '\0'; | |
853 | ||
854 | return returnValue; | |
855 | } | |
856 | } | |
857 | ||
858 | char * | |
859 | method_copyArgumentType (struct objc_method * method, unsigned int argumentNumber) | |
860 | { | |
861 | if (method == NULL) | |
862 | return 0; | |
863 | else | |
864 | { | |
865 | char *returnValue; | |
866 | const char *returnValueStart; | |
867 | size_t returnValueSize; | |
868 | ||
869 | /* Determine returnValueStart and returnValueSize. */ | |
870 | { | |
871 | const char *type = method->method_types; | |
872 | ||
873 | /* Skip the first argument (return type). */ | |
874 | type = objc_skip_argspec (type); | |
875 | ||
876 | /* Now keep skipping arguments until we get to | |
877 | argumentNumber. */ | |
878 | while (argumentNumber > 0) | |
879 | { | |
880 | /* We are supposed to skip an argument, but the string is | |
881 | finished. This means we were asked for a non-existing | |
882 | argument. */ | |
883 | if (*type == '\0') | |
884 | return NULL; | |
885 | ||
886 | type = objc_skip_argspec (type); | |
887 | argumentNumber--; | |
888 | } | |
889 | ||
890 | /* If the argument does not exist, return NULL. */ | |
891 | if (*type == '\0') | |
892 | return NULL; | |
893 | ||
894 | returnValueStart = type; | |
895 | type = objc_skip_argspec (type); | |
896 | returnValueSize = type - returnValueStart + 1; | |
897 | } | |
898 | ||
899 | /* Copy the argument into returnValue. */ | |
900 | returnValue = malloc (sizeof (char) * returnValueSize); | |
901 | memcpy (returnValue, returnValueStart, returnValueSize); | |
902 | returnValue[returnValueSize - 1] = '\0'; | |
903 | ||
904 | return returnValue; | |
905 | } | |
906 | } | |
907 | ||
908 | void method_getReturnType (struct objc_method * method, char *returnValue, | |
909 | size_t returnValueSize) | |
910 | { | |
911 | if (returnValue == NULL || returnValueSize == 0) | |
912 | return; | |
913 | ||
914 | /* Zero the string; we'll then write the argument type at the | |
915 | beginning of it, if needed. */ | |
916 | memset (returnValue, 0, returnValueSize); | |
917 | ||
918 | if (method == NULL) | |
919 | return; | |
920 | else | |
921 | { | |
922 | size_t argumentTypeSize; | |
923 | ||
924 | /* Determine argumentTypeSize. */ | |
925 | { | |
926 | /* Find the end of the first argument. We want to return the | |
927 | first argument spec. */ | |
928 | const char *type = method->method_types; | |
929 | if (*type == '\0') | |
930 | return; | |
931 | type = objc_skip_argspec (type); | |
932 | argumentTypeSize = type - method->method_types; | |
933 | if (argumentTypeSize > returnValueSize) | |
934 | argumentTypeSize = returnValueSize; | |
935 | } | |
936 | /* Copy the argument at the beginning of the string. */ | |
937 | memcpy (returnValue, method->method_types, argumentTypeSize); | |
938 | } | |
939 | } | |
940 | ||
941 | void method_getArgumentType (struct objc_method * method, unsigned int argumentNumber, | |
942 | char *returnValue, size_t returnValueSize) | |
943 | { | |
944 | if (returnValue == NULL || returnValueSize == 0) | |
945 | return; | |
946 | ||
947 | /* Zero the string; we'll then write the argument type at the | |
948 | beginning of it, if needed. */ | |
949 | memset (returnValue, 0, returnValueSize); | |
950 | ||
951 | if (method == NULL) | |
952 | return; | |
953 | else | |
954 | { | |
955 | const char *returnValueStart; | |
956 | size_t argumentTypeSize; | |
957 | ||
958 | /* Determine returnValueStart and argumentTypeSize. */ | |
959 | { | |
960 | const char *type = method->method_types; | |
961 | ||
962 | /* Skip the first argument (return type). */ | |
963 | type = objc_skip_argspec (type); | |
964 | ||
965 | /* Now keep skipping arguments until we get to | |
966 | argumentNumber. */ | |
967 | while (argumentNumber > 0) | |
968 | { | |
969 | /* We are supposed to skip an argument, but the string is | |
970 | finished. This means we were asked for a non-existing | |
971 | argument. */ | |
972 | if (*type == '\0') | |
973 | return; | |
974 | ||
975 | type = objc_skip_argspec (type); | |
976 | argumentNumber--; | |
977 | } | |
978 | ||
979 | /* If the argument does not exist, it's game over. */ | |
980 | if (*type == '\0') | |
981 | return; | |
982 | ||
983 | returnValueStart = type; | |
984 | type = objc_skip_argspec (type); | |
985 | argumentTypeSize = type - returnValueStart; | |
986 | if (argumentTypeSize > returnValueSize) | |
987 | argumentTypeSize = returnValueSize; | |
988 | } | |
989 | /* Copy the argument at the beginning of the string. */ | |
990 | memcpy (returnValue, returnValueStart, argumentTypeSize); | |
991 | } | |
992 | } | |
993 | ||
ad9eef11 NP |
994 | unsigned int |
995 | method_getNumberOfArguments (struct objc_method *method) | |
88e17b57 | 996 | { |
ad9eef11 NP |
997 | if (method == NULL) |
998 | return 0; | |
999 | else | |
88e17b57 | 1000 | { |
ad9eef11 NP |
1001 | unsigned int i = 0; |
1002 | const char *type = method->method_types; | |
1003 | while (*type) | |
1004 | { | |
1005 | type = objc_skip_argspec (type); | |
1006 | i += 1; | |
1007 | } | |
1008 | ||
1009 | if (i == 0) | |
1010 | { | |
1011 | /* This could only happen if method_types is invalid; in | |
1012 | that case, return 0. */ | |
1013 | return 0; | |
1014 | } | |
1015 | else | |
1016 | { | |
1017 | /* Remove the return type. */ | |
1018 | return (i - 1); | |
1019 | } | |
88e17b57 | 1020 | } |
ad9eef11 NP |
1021 | } |
1022 | ||
88e17b57 | 1023 | unsigned |
40165636 | 1024 | objc_get_type_qualifiers (const char *type) |
88e17b57 BE |
1025 | { |
1026 | unsigned res = 0; | |
1027 | BOOL flag = YES; | |
1028 | ||
1029 | while (flag) | |
1030 | switch (*type++) | |
1031 | { | |
c994cc85 NP |
1032 | case _C_CONST: res |= _F_CONST; break; |
1033 | case _C_IN: res |= _F_IN; break; | |
1034 | case _C_INOUT: res |= _F_INOUT; break; | |
1035 | case _C_OUT: res |= _F_OUT; break; | |
1036 | case _C_BYCOPY: res |= _F_BYCOPY; break; | |
1037 | case _C_BYREF: res |= _F_BYREF; break; | |
1038 | case _C_ONEWAY: res |= _F_ONEWAY; break; | |
88e17b57 BE |
1039 | case _C_GCINVISIBLE: res |= _F_GCINVISIBLE; break; |
1040 | default: flag = NO; | |
1041 | } | |
1042 | ||
1043 | return res; | |
1044 | } | |
1045 | ||
88e17b57 BE |
1046 | /* The following three functions can be used to determine how a |
1047 | structure is laid out by the compiler. For example: | |
1048 | ||
1049 | struct objc_struct_layout layout; | |
1050 | int i; | |
1051 | ||
1052 | objc_layout_structure (type, &layout); | |
1053 | while (objc_layout_structure_next_member (&layout)) | |
1054 | { | |
1055 | int position, align; | |
1056 | const char *type; | |
1057 | ||
1058 | objc_layout_structure_get_info (&layout, &position, &align, &type); | |
1059 | printf ("element %d has offset %d, alignment %d\n", | |
1060 | i++, position, align); | |
1061 | } | |
1062 | ||
1063 | These functions are used by objc_sizeof_type and objc_alignof_type | |
1064 | functions to compute the size and alignment of structures. The | |
1065 | previous method of computing the size and alignment of a structure | |
cad10e05 | 1066 | was not working on some architectures, particularly on AIX, and in |
c994cc85 | 1067 | the presence of bitfields inside the structure. */ |
88e17b57 BE |
1068 | void |
1069 | objc_layout_structure (const char *type, | |
177b48f9 | 1070 | struct objc_struct_layout *layout) |
88e17b57 BE |
1071 | { |
1072 | const char *ntype; | |
1073 | ||
4540a3ad | 1074 | if (*type != _C_UNION_B && *type != _C_STRUCT_B) |
88e17b57 | 1075 | { |
7b869986 NP |
1076 | _objc_abort ("record (or union) type expected in objc_layout_structure, got %s\n", |
1077 | type); | |
88e17b57 BE |
1078 | } |
1079 | ||
4540a3ad | 1080 | type ++; |
88e17b57 BE |
1081 | layout->original_type = type; |
1082 | ||
1083 | /* Skip "<name>=" if any. Avoid embedded structures and unions. */ | |
1084 | ntype = type; | |
1085 | while (*ntype != _C_STRUCT_E && *ntype != _C_STRUCT_B && *ntype != _C_UNION_B | |
1086 | && *ntype++ != '=') | |
1087 | /* do nothing */; | |
1088 | ||
1089 | /* If there's a "<name>=", ntype - 1 points to '='; skip the the name */ | |
1090 | if (*(ntype - 1) == '=') | |
1091 | type = ntype; | |
1092 | ||
1093 | layout->type = type; | |
1094 | layout->prev_type = NULL; | |
1095 | layout->record_size = 0; | |
1096 | layout->record_align = BITS_PER_UNIT; | |
1097 | ||
88e17b57 | 1098 | layout->record_align = MAX (layout->record_align, STRUCTURE_SIZE_BOUNDARY); |
88e17b57 BE |
1099 | } |
1100 | ||
88e17b57 BE |
1101 | BOOL |
1102 | objc_layout_structure_next_member (struct objc_struct_layout *layout) | |
1103 | { | |
88e17b57 BE |
1104 | register int desired_align = 0; |
1105 | ||
1106 | /* The following are used only if the field is a bitfield */ | |
8f8c44cb | 1107 | register const char *bfld_type = 0; |
288d6a77 | 1108 | register int bfld_type_align = 0, bfld_field_size = 0; |
88e17b57 BE |
1109 | |
1110 | /* The current type without the type qualifiers */ | |
1111 | const char *type; | |
4540a3ad | 1112 | BOOL unionp = layout->original_type[-1] == _C_UNION_B; |
88e17b57 | 1113 | |
88e17b57 BE |
1114 | /* Add the size of the previous field to the size of the record. */ |
1115 | if (layout->prev_type) | |
1116 | { | |
1117 | type = objc_skip_type_qualifiers (layout->prev_type); | |
4540a3ad AP |
1118 | if (unionp) |
1119 | layout->record_size = MAX (layout->record_size, | |
1120 | objc_sizeof_type (type) * BITS_PER_UNIT); | |
88e17b57 | 1121 | |
4540a3ad | 1122 | else if (*type != _C_BFLD) |
88e17b57 BE |
1123 | layout->record_size += objc_sizeof_type (type) * BITS_PER_UNIT; |
1124 | else { | |
88e17b57 BE |
1125 | /* Get the bitfield's type */ |
1126 | for (bfld_type = type + 1; | |
40165636 | 1127 | isdigit ((unsigned char)*bfld_type); |
88e17b57 BE |
1128 | bfld_type++) |
1129 | /* do nothing */; | |
1130 | ||
88e17b57 BE |
1131 | bfld_type_align = objc_alignof_type (bfld_type) * BITS_PER_UNIT; |
1132 | bfld_field_size = atoi (objc_skip_typespec (bfld_type)); | |
1133 | layout->record_size += bfld_field_size; | |
1134 | } | |
1135 | } | |
1136 | ||
4540a3ad AP |
1137 | if ((unionp && *layout->type == _C_UNION_E) |
1138 | || (!unionp && *layout->type == _C_STRUCT_E)) | |
88e17b57 BE |
1139 | return NO; |
1140 | ||
1141 | /* Skip the variable name if any */ | |
c994cc85 | 1142 | layout->type = objc_skip_variable_name (layout->type); |
88e17b57 BE |
1143 | type = objc_skip_type_qualifiers (layout->type); |
1144 | ||
1145 | if (*type != _C_BFLD) | |
40165636 | 1146 | desired_align = objc_alignof_type (type) * BITS_PER_UNIT; |
88e17b57 BE |
1147 | else |
1148 | { | |
1149 | desired_align = 1; | |
1150 | /* Skip the bitfield's offset */ | |
40165636 RB |
1151 | for (bfld_type = type + 1; |
1152 | isdigit ((unsigned char) *bfld_type); | |
1153 | bfld_type++) | |
88e17b57 BE |
1154 | /* do nothing */; |
1155 | ||
88e17b57 BE |
1156 | bfld_type_align = objc_alignof_type (bfld_type) * BITS_PER_UNIT; |
1157 | bfld_field_size = atoi (objc_skip_typespec (bfld_type)); | |
1158 | } | |
1159 | ||
177b48f9 | 1160 | /* The following won't work for vectors. */ |
88e17b57 BE |
1161 | #ifdef BIGGEST_FIELD_ALIGNMENT |
1162 | desired_align = MIN (desired_align, BIGGEST_FIELD_ALIGNMENT); | |
1163 | #endif | |
1164 | #ifdef ADJUST_FIELD_ALIGN | |
1165 | desired_align = ADJUST_FIELD_ALIGN (type, desired_align); | |
1166 | #endif | |
1167 | ||
1168 | /* Record must have at least as much alignment as any field. | |
1169 | Otherwise, the alignment of the field within the record | |
1170 | is meaningless. */ | |
539280a8 | 1171 | #ifndef HAVE_BITFIELD_TYPE_MATTERS |
88e17b57 | 1172 | layout->record_align = MAX (layout->record_align, desired_align); |
40165636 | 1173 | #else /* PCC_BITFIELD_TYPE_MATTERS */ |
88e17b57 BE |
1174 | if (*type == _C_BFLD) |
1175 | { | |
1176 | /* For these machines, a zero-length field does not | |
1177 | affect the alignment of the structure as a whole. | |
1178 | It does, however, affect the alignment of the next field | |
1179 | within the structure. */ | |
1180 | if (bfld_field_size) | |
1181 | layout->record_align = MAX (layout->record_align, desired_align); | |
1182 | else | |
1183 | desired_align = objc_alignof_type (bfld_type) * BITS_PER_UNIT; | |
1184 | ||
1185 | /* A named bit field of declared type `int' | |
1186 | forces the entire structure to have `int' alignment. | |
1187 | Q1: How is encoded this thing and how to check for it? | |
1188 | Q2: How to determine maximum_field_alignment at runtime? */ | |
1189 | ||
1190 | /* if (DECL_NAME (field) != 0) */ | |
1191 | { | |
1192 | int type_align = bfld_type_align; | |
1193 | #if 0 | |
1194 | if (maximum_field_alignment != 0) | |
1195 | type_align = MIN (type_align, maximum_field_alignment); | |
1196 | else if (DECL_PACKED (field)) | |
1197 | type_align = MIN (type_align, BITS_PER_UNIT); | |
1198 | #endif | |
1199 | ||
1200 | layout->record_align = MAX (layout->record_align, type_align); | |
1201 | } | |
1202 | } | |
1203 | else | |
1204 | layout->record_align = MAX (layout->record_align, desired_align); | |
40165636 | 1205 | #endif /* PCC_BITFIELD_TYPE_MATTERS */ |
88e17b57 BE |
1206 | |
1207 | /* Does this field automatically have alignment it needs | |
1208 | by virtue of the fields that precede it and the record's | |
1209 | own alignment? */ | |
1210 | ||
1211 | if (*type == _C_BFLD) | |
1212 | layout->record_size = atoi (type + 1); | |
1213 | else if (layout->record_size % desired_align != 0) | |
1214 | { | |
1215 | /* No, we need to skip space before this field. | |
1216 | Bump the cumulative size to multiple of field alignment. */ | |
1217 | layout->record_size = ROUND (layout->record_size, desired_align); | |
1218 | } | |
42bac116 | 1219 | |
88e17b57 BE |
1220 | /* Jump to the next field in record. */ |
1221 | ||
1222 | layout->prev_type = layout->type; | |
1223 | layout->type = objc_skip_typespec (layout->type); /* skip component */ | |
1224 | ||
1225 | return YES; | |
1226 | } | |
1227 | ||
88e17b57 BE |
1228 | void objc_layout_finish_structure (struct objc_struct_layout *layout, |
1229 | unsigned int *size, | |
1230 | unsigned int *align) | |
1231 | { | |
4540a3ad AP |
1232 | BOOL unionp = layout->original_type[-1] == _C_UNION_B; |
1233 | if (layout->type | |
1234 | && ((!unionp && *layout->type == _C_STRUCT_E) | |
1235 | || (unionp && *layout->type == _C_UNION_E))) | |
88e17b57 BE |
1236 | { |
1237 | /* Work out the alignment of the record as one expression and store | |
1238 | in the record type. Round it up to a multiple of the record's | |
1239 | alignment. */ | |
40165636 | 1240 | #if defined (ROUND_TYPE_ALIGN) && ! defined (__sparc__) |
761c0d29 | 1241 | layout->record_align = ROUND_TYPE_ALIGN (layout->original_type-1, |
88e17b57 BE |
1242 | 1, |
1243 | layout->record_align); | |
1244 | #else | |
1245 | layout->record_align = MAX (1, layout->record_align); | |
1246 | #endif | |
1247 | ||
88e17b57 BE |
1248 | /* Round the size up to be a multiple of the required alignment */ |
1249 | layout->record_size = ROUND (layout->record_size, layout->record_align); | |
88e17b57 BE |
1250 | |
1251 | layout->type = NULL; | |
1252 | } | |
1253 | if (size) | |
1254 | *size = layout->record_size / BITS_PER_UNIT; | |
1255 | if (align) | |
1256 | *align = layout->record_align / BITS_PER_UNIT; | |
1257 | } | |
1258 | ||
88e17b57 BE |
1259 | void objc_layout_structure_get_info (struct objc_struct_layout *layout, |
1260 | unsigned int *offset, | |
1261 | unsigned int *align, | |
1262 | const char **type) | |
1263 | { | |
1264 | if (offset) | |
1265 | *offset = layout->record_size / BITS_PER_UNIT; | |
1266 | if (align) | |
1267 | *align = layout->record_align / BITS_PER_UNIT; | |
1268 | if (type) | |
1269 | *type = layout->prev_type; | |
1270 | } |