]> git.ipfire.org Git - thirdparty/gcc.git/blob - libobjc/encoding.c
In libobjc/: 2010-12-21 Nicola Pero <nicola.pero@meta-innovation.com>
[thirdparty/gcc.git] / libobjc / encoding.c
1 /* Encoding of types for Objective C.
2 Copyright (C) 1993, 1995, 1996, 1997, 1998, 2000, 2002, 2004, 2009
3 Free Software Foundation, Inc.
4 Contributed by Kresten Krab Thorup
5 Bitfield support by Ovidiu Predescu
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
13
14 GCC is distributed in the hope that it will be useful,
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
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.
22
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/>. */
27
28 /* FIXME: This file has no business including tm.h. */
29
30 /* FIXME: This file contains functions that will abort the entire
31 program if they fail. Is that really needed ? */
32
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 #ifndef BITS_PER_UNIT
98 #define BITS_PER_UNIT 8
99 #endif
100 #undef STRUCTURE_SIZE_BOUNDARY
101 #define STRUCTURE_SIZE_BOUNDARY (BITS_PER_UNIT * sizeof (struct{char a;}))
102
103 /* Some ROUND_TYPE_ALIGN macros use TARGET_foo, and consequently
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;
109
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
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
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)))
157 #endif
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,
162 should look after the branch of 3.4 to fix this. */
163 #define rs6000_special_round_type_align(STRUCT, COMPUTED, SPECIFIED) \
164 ({ const char *_fields = TYPE_FIELDS (STRUCT); \
165 ((_fields != 0 \
166 && TYPE_MODE (strip_array_types (TREE_TYPE (_fields))) == DFmode) \
167 ? MAX (MAX (COMPUTED, SPECIFIED), 64) \
168 : MAX (COMPUTED, SPECIFIED));})
169
170
171 /* Skip a variable name, enclosed in quotes ("). */
172 static inline
173 const char *
174 objc_skip_variable_name (const char *type)
175 {
176 /* Skip the variable name if any. */
177 if (*type == '"')
178 {
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! */
181 /* Skip '"'. */
182 type++;
183 /* Skip to the next '"'. */
184 while (*type != '"')
185 type++;
186 /* Skip '"'. */
187 type++;
188 }
189
190 return type;
191 }
192
193 int
194 objc_sizeof_type (const char *type)
195 {
196 type = objc_skip_variable_name (type);
197
198 switch (*type) {
199 case _C_BOOL:
200 return sizeof (_Bool);
201 break;
202
203 case _C_ID:
204 return sizeof (id);
205 break;
206
207 case _C_CLASS:
208 return sizeof (Class);
209 break;
210
211 case _C_SEL:
212 return sizeof (SEL);
213 break;
214
215 case _C_CHR:
216 return sizeof (char);
217 break;
218
219 case _C_UCHR:
220 return sizeof (unsigned char);
221 break;
222
223 case _C_SHT:
224 return sizeof (short);
225 break;
226
227 case _C_USHT:
228 return sizeof (unsigned short);
229 break;
230
231 case _C_INT:
232 return sizeof (int);
233 break;
234
235 case _C_UINT:
236 return sizeof (unsigned int);
237 break;
238
239 case _C_LNG:
240 return sizeof (long);
241 break;
242
243 case _C_ULNG:
244 return sizeof (unsigned long);
245 break;
246
247 case _C_LNG_LNG:
248 return sizeof (long long);
249 break;
250
251 case _C_ULNG_LNG:
252 return sizeof (unsigned long long);
253 break;
254
255 case _C_FLT:
256 return sizeof (float);
257 break;
258
259 case _C_DBL:
260 return sizeof (double);
261 break;
262
263 case _C_LNG_DBL:
264 return sizeof (long double);
265 break;
266
267 case _C_VOID:
268 return sizeof (void);
269 break;
270
271 case _C_PTR:
272 case _C_ATOM:
273 case _C_CHARPTR:
274 return sizeof (char *);
275 break;
276
277 case _C_ARY_B:
278 {
279 int len = atoi (type + 1);
280 while (isdigit ((unsigned char)*++type))
281 ;
282 return len * objc_aligned_size (type);
283 }
284 break;
285
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
299 case _C_BFLD:
300 {
301 /* The GNU encoding of bitfields is: b 'position' 'type'
302 'size'. */
303 int position, size;
304 int startByte, endByte;
305
306 position = atoi (type + 1);
307 while (isdigit ((unsigned char)*++type))
308 ;
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
316 case _C_UNION_B:
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 }
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;
382
383 case _C_LNG_DBL:
384 return sizeof (_Complex long double);
385 break;
386
387 default:
388 {
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);
394 return 0;
395 }
396 }
397 }
398
399 default:
400 {
401 _objc_abort ("unknown type %s\n", type);
402 return 0;
403 }
404 }
405 }
406
407 int
408 objc_alignof_type (const char *type)
409 {
410 type = objc_skip_variable_name (type);
411
412 switch (*type) {
413 case _C_BOOL:
414 return __alignof__ (_Bool);
415 break;
416
417 case _C_ID:
418 return __alignof__ (id);
419 break;
420
421 case _C_CLASS:
422 return __alignof__ (Class);
423 break;
424
425 case _C_SEL:
426 return __alignof__ (SEL);
427 break;
428
429 case _C_CHR:
430 return __alignof__ (char);
431 break;
432
433 case _C_UCHR:
434 return __alignof__ (unsigned char);
435 break;
436
437 case _C_SHT:
438 return __alignof__ (short);
439 break;
440
441 case _C_USHT:
442 return __alignof__ (unsigned short);
443 break;
444
445 case _C_INT:
446 return __alignof__ (int);
447 break;
448
449 case _C_UINT:
450 return __alignof__ (unsigned int);
451 break;
452
453 case _C_LNG:
454 return __alignof__ (long);
455 break;
456
457 case _C_ULNG:
458 return __alignof__ (unsigned long);
459 break;
460
461 case _C_LNG_LNG:
462 return __alignof__ (long long);
463 break;
464
465 case _C_ULNG_LNG:
466 return __alignof__ (unsigned long long);
467 break;
468
469 case _C_FLT:
470 return __alignof__ (float);
471 break;
472
473 case _C_DBL:
474 return __alignof__ (double);
475 break;
476
477 case _C_LNG_DBL:
478 return __alignof__ (long double);
479 break;
480
481 case _C_PTR:
482 case _C_ATOM:
483 case _C_CHARPTR:
484 return __alignof__ (char *);
485 break;
486
487 case _C_ARY_B:
488 while (isdigit ((unsigned char)*++type))
489 /* do nothing */;
490 return objc_alignof_type (type);
491
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 }
509 case _C_STRUCT_B:
510 case _C_UNION_B:
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 }
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;
576
577 case _C_LNG_DBL:
578 return __alignof__ (_Complex long double);
579 break;
580
581 default:
582 {
583 _objc_abort ("unknown complex type %s\n", type);
584 return 0;
585 }
586 }
587 }
588
589 default:
590 {
591 _objc_abort ("unknown type %s\n", type);
592 return 0;
593 }
594 }
595 }
596
597 int
598 objc_aligned_size (const char *type)
599 {
600 int size, align;
601
602 type = objc_skip_variable_name (type);
603 size = objc_sizeof_type (type);
604 align = objc_alignof_type (type);
605
606 return ROUND (size, align);
607 }
608
609 int
610 objc_promoted_size (const char *type)
611 {
612 int size, wordsize;
613
614 type = objc_skip_variable_name (type);
615 size = objc_sizeof_type (type);
616 wordsize = sizeof (void *);
617
618 return ROUND (size, wordsize);
619 }
620
621 inline
622 const char *
623 objc_skip_type_qualifiers (const char *type)
624 {
625 while (*type == _C_CONST
626 || *type == _C_IN
627 || *type == _C_INOUT
628 || *type == _C_OUT
629 || *type == _C_BYCOPY
630 || *type == _C_BYREF
631 || *type == _C_ONEWAY
632 || *type == _C_GCINVISIBLE)
633 {
634 type += 1;
635 }
636 return type;
637 }
638
639 inline
640 const char *
641 objc_skip_typespec (const char *type)
642 {
643 type = objc_skip_variable_name (type);
644 type = objc_skip_type_qualifiers (type);
645
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 {
656 while (*++type != '"')
657 /* do nothing */;
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:
673 case _C_BOOL:
674 case _C_ULNG:
675 case _C_LNG_LNG:
676 case _C_ULNG_LNG:
677 case _C_FLT:
678 case _C_DBL:
679 case _C_LNG_DBL:
680 case _C_VOID:
681 case _C_UNDEF:
682 return ++type;
683 break;
684
685 case _C_COMPLEX:
686 return type + 2;
687 break;
688
689 case _C_ARY_B:
690 /* skip digits, typespec and closing ']' */
691 while (isdigit ((unsigned char)*++type))
692 ;
693 type = objc_skip_typespec (type);
694 if (*type == _C_ARY_E)
695 return ++type;
696 else
697 {
698 _objc_abort ("bad array type %s\n", type);
699 return 0;
700 }
701
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
726 case _C_BFLD:
727 /* The GNU encoding of bitfields is: b 'position' 'type'
728 'size'. */
729 while (isdigit ((unsigned char)*++type))
730 ; /* skip position */
731 while (isdigit ((unsigned char)*++type))
732 ; /* skip type and size */
733 return type;
734
735 case _C_STRUCT_B:
736 /* skip name, and elements until closing '}' */
737
738 while (*type != _C_STRUCT_E && *type++ != '=')
739 ;
740 while (*type != _C_STRUCT_E)
741 {
742 type = objc_skip_typespec (type);
743 }
744 return ++type;
745
746 case _C_UNION_B:
747 /* skip name, and elements until closing ')' */
748
749 while (*type != _C_UNION_E && *type++ != '=')
750 ;
751 while (*type != _C_UNION_E)
752 {
753 type = objc_skip_typespec (type);
754 }
755 return ++type;
756
757 case _C_PTR:
758 /* Just skip the following typespec */
759
760 return objc_skip_typespec (++type);
761
762 default:
763 {
764 _objc_abort ("unknown type %s\n", type);
765 return 0;
766 }
767 }
768 }
769
770 inline
771 const char *
772 objc_skip_offset (const char *type)
773 {
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. */
777 if (*type == '+')
778 type++;
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
790 return type;
791 }
792
793 const char *
794 objc_skip_argspec (const char *type)
795 {
796 type = objc_skip_typespec (type);
797 type = objc_skip_offset (type);
798 return type;
799 }
800
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
967 unsigned int
968 method_getNumberOfArguments (struct objc_method *method)
969 {
970 if (method == NULL)
971 return 0;
972 else
973 {
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 }
993 }
994 }
995
996 int
997 method_get_number_of_arguments (struct objc_method *mth)
998 {
999 return method_getNumberOfArguments (mth);
1000 }
1001
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. */
1005 int
1006 method_get_sizeof_arguments (struct objc_method *mth)
1007 {
1008 const char *type = objc_skip_typespec (mth->method_types);
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 {
1017 char *datum, *type;
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)
1028 [portal encodeData: *(char **) datum ofType: ++type];
1029 }
1030 }
1031 }
1032 */
1033 char *
1034 method_get_next_argument (arglist_t argframe, const char **type)
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
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. */
1054 char *
1055 method_get_first_argument (struct objc_method *m,
1056 arglist_t argframe,
1057 const char **type)
1058 {
1059 *type = m->method_types;
1060 return method_get_next_argument (argframe, type);
1061 }
1062
1063 /* Return a pointer to the ARGth argument of the method
1064 M from the frame ARGFRAME. The type of the argument
1065 is returned in the value-result argument TYPE. */
1066 char *
1067 method_get_nth_argument (struct objc_method *m,
1068 arglist_t argframe, int arg,
1069 const char **type)
1070 {
1071 const char *t = objc_skip_argspec (m->method_types);
1072
1073 if (arg > method_get_number_of_arguments (m))
1074 return 0;
1075
1076 while (arg--)
1077 t = objc_skip_argspec (t);
1078
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
1089 objc_get_type_qualifiers (const char *type)
1090 {
1091 unsigned res = 0;
1092 BOOL flag = YES;
1093
1094 while (flag)
1095 switch (*type++)
1096 {
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;
1104 case _C_GCINVISIBLE: res |= _F_GCINVISIBLE; break;
1105 default: flag = NO;
1106 }
1107
1108 return res;
1109 }
1110
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
1132 the presence of bitfields inside the structure. */
1133 void
1134 objc_layout_structure (const char *type,
1135 struct objc_struct_layout *layout)
1136 {
1137 const char *ntype;
1138
1139 if (*type != _C_UNION_B && *type != _C_STRUCT_B)
1140 {
1141 _objc_abort ("record (or union) type expected in objc_layout_structure, got %s\n",
1142 type);
1143 }
1144
1145 type ++;
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
1163 layout->record_align = MAX (layout->record_align, STRUCTURE_SIZE_BOUNDARY);
1164 }
1165
1166 BOOL
1167 objc_layout_structure_next_member (struct objc_struct_layout *layout)
1168 {
1169 register int desired_align = 0;
1170
1171 /* The following are used only if the field is a bitfield */
1172 register const char *bfld_type = 0;
1173 register int bfld_type_align = 0, bfld_field_size = 0;
1174
1175 /* The current type without the type qualifiers */
1176 const char *type;
1177 BOOL unionp = layout->original_type[-1] == _C_UNION_B;
1178
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);
1183 if (unionp)
1184 layout->record_size = MAX (layout->record_size,
1185 objc_sizeof_type (type) * BITS_PER_UNIT);
1186
1187 else if (*type != _C_BFLD)
1188 layout->record_size += objc_sizeof_type (type) * BITS_PER_UNIT;
1189 else {
1190 /* Get the bitfield's type */
1191 for (bfld_type = type + 1;
1192 isdigit ((unsigned char)*bfld_type);
1193 bfld_type++)
1194 /* do nothing */;
1195
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
1202 if ((unionp && *layout->type == _C_UNION_E)
1203 || (!unionp && *layout->type == _C_STRUCT_E))
1204 return NO;
1205
1206 /* Skip the variable name if any */
1207 layout->type = objc_skip_variable_name (layout->type);
1208 type = objc_skip_type_qualifiers (layout->type);
1209
1210 if (*type != _C_BFLD)
1211 desired_align = objc_alignof_type (type) * BITS_PER_UNIT;
1212 else
1213 {
1214 desired_align = 1;
1215 /* Skip the bitfield's offset */
1216 for (bfld_type = type + 1;
1217 isdigit ((unsigned char) *bfld_type);
1218 bfld_type++)
1219 /* do nothing */;
1220
1221 bfld_type_align = objc_alignof_type (bfld_type) * BITS_PER_UNIT;
1222 bfld_field_size = atoi (objc_skip_typespec (bfld_type));
1223 }
1224
1225 /* The following won't work for vectors. */
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);
1238 #else /* PCC_BITFIELD_TYPE_MATTERS */
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);
1270 #endif /* PCC_BITFIELD_TYPE_MATTERS */
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 }
1284
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
1293 void objc_layout_finish_structure (struct objc_struct_layout *layout,
1294 unsigned int *size,
1295 unsigned int *align)
1296 {
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)))
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. */
1305 #if defined (ROUND_TYPE_ALIGN) && ! defined (__sparc__)
1306 layout->record_align = ROUND_TYPE_ALIGN (layout->original_type-1,
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
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 }