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