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