Merge from vendor branch OPENSSL:
[dragonfly.git] / contrib / gcc-3.4 / libobjc / encoding.c
1 /* Encoding of types for Objective C.
2    Copyright (C) 1993, 1995, 1996, 1997, 1998, 2000, 2002
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 2, 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 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING.  If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA.  */
23
24 /* As a special exception, if you link this library with files
25    compiled with GCC to produce an executable, this does not cause
26    the resulting executable to be covered by the GNU General Public License.
27    This exception does not however invalidate any other reasons why
28    the executable file might be covered by the GNU General Public License.  */
29
30 /* FIXME: This file has no business including tm.h.  */
31
32 #include "tconfig.h"
33 #include "coretypes.h"
34 #include "tm.h"
35 #include "objc-api.h"
36 #include "encoding.h"
37 #include <stdlib.h>
38
39 #undef  MAX
40 #define MAX(X, Y)                    \
41   ({ typeof (X) __x = (X), __y = (Y); \
42      (__x > __y ? __x : __y); })
43
44 #undef  MIN
45 #define MIN(X, Y)                    \
46   ({ typeof (X) __x = (X), __y = (Y); \
47      (__x < __y ? __x : __y); })
48
49 #undef  ROUND
50 #define ROUND(V, A) \
51   ({ typeof (V) __v = (V); typeof (A) __a = (A); \
52      __a * ((__v+__a - 1)/__a); })
53
54
55 /* Various hacks for objc_layout_record. These are used by the target
56    macros. */
57
58 #define TREE_CODE(TYPE) *(TYPE)
59 #define TREE_TYPE(TREE) (TREE)
60
61 #define RECORD_TYPE     _C_STRUCT_B
62 #define UNION_TYPE      _C_UNION_B
63 #define QUAL_UNION_TYPE _C_UNION_B
64 #define ARRAY_TYPE      _C_ARY_B
65
66 #define REAL_TYPE       _C_DBL
67
68 #define VECTOR_TYPE     _C_VECTOR
69
70 #define TYPE_FIELDS(TYPE)     objc_skip_typespec (TYPE)
71
72 #define DECL_MODE(TYPE) *(TYPE)
73 #define TYPE_MODE(TYPE) *(TYPE)
74
75 #define DFmode          _C_DBL
76
77 #define get_inner_array_type(TYPE)      ((TYPE) + 1)
78
79 /* Some ports (eg ARM) allow the structure size boundary to be
80    selected at compile-time.  We override the normal definition with
81    one that has a constant value for this compilation.  */
82 #undef STRUCTURE_SIZE_BOUNDARY
83 #define STRUCTURE_SIZE_BOUNDARY (BITS_PER_UNIT * sizeof (struct{char a;}))
84
85 /* Some ROUND_TYPE_ALIGN macros use TARGET_foo, and consequently
86    target_flags.  Define a dummy entry here to so we don't die.  */
87 /* ??? FIXME: As of 2002-06-21, the attribute `unused' doesn't seem to
88    eliminate the warning.  */
89 static int __attribute__ ((__unused__)) target_flags = 0;
90
91
92 /*  FIXME: while this file has no business including tm.h, this
93     definitely has no business defining this macro but it
94     is only way around without really rewritting this file,
95     should look after the branch of 3.4 to fix this.  */
96 #define rs6000_special_round_type_align(STRUCT, COMPUTED, SPECIFIED)    \
97   ((TYPE_FIELDS (STRUCT) != 0                                           \
98     && DECL_MODE (TYPE_FIELDS (STRUCT)) == DFmode)                      \
99    ? MAX (MAX (COMPUTED, SPECIFIED), 64)                                \
100    : MAX (COMPUTED, SPECIFIED))
101
102 /*
103   return the size of an object specified by type
104 */
105
106 int
107 objc_sizeof_type (const char *type)
108 {
109   /* Skip the variable name if any */
110   if (*type == '"')
111     {
112       for (type++; *type++ != '"';)
113         /* do nothing */;
114     }
115
116   switch (*type) {
117   case _C_ID:
118     return sizeof (id);
119     break;
120
121   case _C_CLASS:
122     return sizeof (Class);
123     break;
124
125   case _C_SEL:
126     return sizeof (SEL);
127     break;
128
129   case _C_CHR:
130     return sizeof (char);
131     break;
132
133   case _C_UCHR:
134     return sizeof (unsigned char);
135     break;
136
137   case _C_SHT:
138     return sizeof (short);
139     break;
140
141   case _C_USHT:
142     return sizeof (unsigned short);
143     break;
144
145   case _C_INT:
146     return sizeof (int);
147     break;
148
149   case _C_UINT:
150     return sizeof (unsigned int);
151     break;
152
153   case _C_LNG:
154     return sizeof (long);
155     break;
156
157   case _C_ULNG:
158     return sizeof (unsigned long);
159     break;
160
161   case _C_LNG_LNG:
162     return sizeof (long long);
163     break;
164
165   case _C_ULNG_LNG:
166     return sizeof (unsigned long long);
167     break;
168
169   case _C_FLT:
170     return sizeof (float);
171     break;
172
173   case _C_DBL:
174     return sizeof (double);
175     break;
176
177   case _C_VOID:
178     return sizeof (void);
179     break;
180
181   case _C_PTR:
182   case _C_ATOM:
183   case _C_CHARPTR:
184     return sizeof (char *);
185     break;
186
187   case _C_ARY_B:
188     {
189       int len = atoi (type + 1);
190       while (isdigit ((unsigned char)*++type))
191         ;
192       return len * objc_aligned_size (type);
193     }
194     break;
195
196   case _C_BFLD:
197     {
198       /* The new encoding of bitfields is: b 'position' 'type' 'size' */
199       int position, size;
200       int startByte, endByte;
201
202       position = atoi (type + 1);
203       while (isdigit ((unsigned char)*++type))
204         ;
205       size = atoi (type + 1);
206
207       startByte = position / BITS_PER_UNIT;
208       endByte = (position + size) / BITS_PER_UNIT;
209       return endByte - startByte;
210     }
211
212   case _C_STRUCT_B:
213     {
214       struct objc_struct_layout layout;
215       unsigned int size;
216
217       objc_layout_structure (type, &layout);
218       while (objc_layout_structure_next_member (&layout))
219         /* do nothing */ ;
220       objc_layout_finish_structure (&layout, &size, NULL);
221
222       return size;
223     }
224
225   case _C_UNION_B:
226     {
227       int max_size = 0;
228       while (*type != _C_UNION_E && *type++ != '=')
229         /* do nothing */;
230       while (*type != _C_UNION_E)
231         {
232           /* Skip the variable name if any */
233           if (*type == '"')
234             {
235               for (type++; *type++ != '"';)
236                 /* do nothing */;
237             }
238           max_size = MAX (max_size, objc_sizeof_type (type));
239           type = objc_skip_typespec (type);
240         }
241       return max_size;
242     }
243
244   default:
245     {
246       objc_error (nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
247       return 0;
248     }
249   }
250 }
251
252
253 /*
254   Return the alignment of an object specified by type
255 */
256
257 int
258 objc_alignof_type (const char *type)
259 {
260   /* Skip the variable name if any */
261   if (*type == '"')
262     {
263       for (type++; *type++ != '"';)
264         /* do nothing */;
265     }
266   switch (*type) {
267   case _C_ID:
268     return __alignof__ (id);
269     break;
270
271   case _C_CLASS:
272     return __alignof__ (Class);
273     break;
274
275   case _C_SEL:
276     return __alignof__ (SEL);
277     break;
278
279   case _C_CHR:
280     return __alignof__ (char);
281     break;
282
283   case _C_UCHR:
284     return __alignof__ (unsigned char);
285     break;
286
287   case _C_SHT:
288     return __alignof__ (short);
289     break;
290
291   case _C_USHT:
292     return __alignof__ (unsigned short);
293     break;
294
295   case _C_INT:
296     return __alignof__ (int);
297     break;
298
299   case _C_UINT:
300     return __alignof__ (unsigned int);
301     break;
302
303   case _C_LNG:
304     return __alignof__ (long);
305     break;
306
307   case _C_ULNG:
308     return __alignof__ (unsigned long);
309     break;
310
311   case _C_LNG_LNG:
312     return __alignof__ (long long);
313     break;
314
315   case _C_ULNG_LNG:
316     return __alignof__ (unsigned long long);
317     break;
318
319   case _C_FLT:
320     return __alignof__ (float);
321     break;
322
323   case _C_DBL:
324     return __alignof__ (double);
325     break;
326
327   case _C_PTR:
328   case _C_ATOM:
329   case _C_CHARPTR:
330     return __alignof__ (char *);
331     break;
332
333   case _C_ARY_B:
334     while (isdigit ((unsigned char)*++type))
335       /* do nothing */;
336     return objc_alignof_type (type);
337
338   case _C_STRUCT_B:
339     {
340       struct objc_struct_layout layout;
341       unsigned int align;
342
343       objc_layout_structure (type, &layout);
344       while (objc_layout_structure_next_member (&layout))
345         /* do nothing */;
346       objc_layout_finish_structure (&layout, NULL, &align);
347
348       return align;
349     }
350
351   case _C_UNION_B:
352     {
353       int maxalign = 0;
354       while (*type != _C_UNION_E && *type++ != '=')
355         /* do nothing */;
356       while (*type != _C_UNION_E)
357         {
358           /* Skip the variable name if any */
359           if (*type == '"')
360             {
361               for (type++; *type++ != '"';)
362                 /* do nothing */;
363             }
364           maxalign = MAX (maxalign, objc_alignof_type (type));
365           type = objc_skip_typespec (type);
366         }
367       return maxalign;
368     }
369
370   default:
371     {
372       objc_error (nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
373       return 0;
374     }
375   }
376 }
377
378 /*
379   The aligned size if the size rounded up to the nearest alignment.
380 */
381
382 int
383 objc_aligned_size (const char *type)
384 {
385   int size, align;
386
387   /* Skip the variable name */
388   if (*type == '"')
389     {
390       for (type++; *type++ != '"';)
391         /* do nothing */;
392     }
393
394   size = objc_sizeof_type (type);
395   align = objc_alignof_type (type);
396
397   return ROUND (size, align);
398 }
399
400 /*
401   The size rounded up to the nearest integral of the wordsize, taken
402   to be the size of a void *.
403 */
404
405 int
406 objc_promoted_size (const char *type)
407 {
408   int size, wordsize;
409
410   /* Skip the variable name */
411   if (*type == '"')
412     {
413       for (type++; *type++ != '"';)
414         /* do nothing */;
415     }
416
417   size = objc_sizeof_type (type);
418   wordsize = sizeof (void *);
419
420   return ROUND (size, wordsize);
421 }
422
423 /*
424   Skip type qualifiers.  These may eventually precede typespecs
425   occurring in method prototype encodings.
426 */
427
428 inline const char *
429 objc_skip_type_qualifiers (const char *type)
430 {
431   while (*type == _C_CONST
432          || *type == _C_IN
433          || *type == _C_INOUT
434          || *type == _C_OUT
435          || *type == _C_BYCOPY
436          || *type == _C_BYREF
437          || *type == _C_ONEWAY
438          || *type == _C_GCINVISIBLE)
439     {
440       type += 1;
441     }
442   return type;
443 }
444
445
446 /*
447   Skip one typespec element.  If the typespec is prepended by type
448   qualifiers, these are skipped as well.
449 */
450
451 const char *
452 objc_skip_typespec (const char *type)
453 {
454   /* Skip the variable name if any */
455   if (*type == '"')
456     {
457       for (type++; *type++ != '"';)
458         /* do nothing */;
459     }
460
461   type = objc_skip_type_qualifiers (type);
462
463   switch (*type) {
464
465   case _C_ID:
466     /* An id may be annotated by the actual type if it is known
467        with the @"ClassName" syntax */
468
469     if (*++type != '"')
470       return type;
471     else
472       {
473         while (*++type != '"')
474           /* do nothing */;
475         return type + 1;
476       }
477
478     /* The following are one character type codes */
479   case _C_CLASS:
480   case _C_SEL:
481   case _C_CHR:
482   case _C_UCHR:
483   case _C_CHARPTR:
484   case _C_ATOM:
485   case _C_SHT:
486   case _C_USHT:
487   case _C_INT:
488   case _C_UINT:
489   case _C_LNG:
490   case _C_ULNG:
491   case _C_LNG_LNG:
492   case _C_ULNG_LNG:
493   case _C_FLT:
494   case _C_DBL:
495   case _C_VOID:
496   case _C_UNDEF:
497     return ++type;
498     break;
499
500   case _C_ARY_B:
501     /* skip digits, typespec and closing ']' */
502
503     while (isdigit ((unsigned char)*++type))
504       ;
505     type = objc_skip_typespec (type);
506     if (*type == _C_ARY_E)
507       return ++type;
508     else
509       {
510         objc_error (nil, OBJC_ERR_BAD_TYPE, "bad array type %s\n", type);
511         return 0;
512       }
513
514   case _C_BFLD:
515     /* The new encoding of bitfields is: b 'position' 'type' 'size' */
516     while (isdigit ((unsigned char)*++type))
517       ; /* skip position */
518     while (isdigit ((unsigned char)*++type))
519       ; /* skip type and size */
520     return type;
521
522   case _C_STRUCT_B:
523     /* skip name, and elements until closing '}'  */
524
525     while (*type != _C_STRUCT_E && *type++ != '=')
526       ;
527     while (*type != _C_STRUCT_E)
528       {
529         type = objc_skip_typespec (type);
530       }
531     return ++type;
532
533   case _C_UNION_B:
534     /* skip name, and elements until closing ')'  */
535
536     while (*type != _C_UNION_E && *type++ != '=')
537       ;
538     while (*type != _C_UNION_E)
539       {
540         type = objc_skip_typespec (type);
541       }
542     return ++type;
543
544   case _C_PTR:
545     /* Just skip the following typespec */
546
547     return objc_skip_typespec (++type);
548
549   default:
550     {
551       objc_error (nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
552       return 0;
553     }
554   }
555 }
556
557 /*
558   Skip an offset as part of a method encoding.  This is prepended by a
559   '+' if the argument is passed in registers.
560 */
561 inline const char *
562 objc_skip_offset (const char *type)
563 {
564   if (*type == '+')
565     type++;
566   while (isdigit ((unsigned char) *++type))
567     ;
568   return type;
569 }
570
571 /*
572   Skip an argument specification of a method encoding.
573 */
574 const char *
575 objc_skip_argspec (const char *type)
576 {
577   type = objc_skip_typespec (type);
578   type = objc_skip_offset (type);
579   return type;
580 }
581
582 /*
583   Return the number of arguments that the method MTH expects.
584   Note that all methods need two implicit arguments `self' and
585   `_cmd'.
586 */
587 int
588 method_get_number_of_arguments (struct objc_method *mth)
589 {
590   int i = 0;
591   const char *type = mth->method_types;
592   while (*type)
593     {
594       type = objc_skip_argspec (type);
595       i += 1;
596     }
597   return i - 1;
598 }
599
600 /*
601   Return the size of the argument block needed on the stack to invoke
602   the method MTH.  This may be zero, if all arguments are passed in
603   registers.
604 */
605
606 int
607 method_get_sizeof_arguments (struct objc_method *mth)
608 {
609   const char *type = objc_skip_typespec (mth->method_types);
610   return atoi (type);
611 }
612
613 /*
614   Return a pointer to the next argument of ARGFRAME.  type points to
615   the last argument.  Typical use of this look like:
616
617   {
618     char *datum, *type;
619     for (datum = method_get_first_argument (method, argframe, &type);
620          datum; datum = method_get_next_argument (argframe, &type))
621       {
622         unsigned flags = objc_get_type_qualifiers (type);
623         type = objc_skip_type_qualifiers (type);
624         if (*type != _C_PTR)
625           [portal encodeData: datum ofType: type];
626         else
627           {
628             if ((flags & _F_IN) == _F_IN)
629               [portal encodeData: *(char **) datum ofType: ++type];
630           }
631       }
632   }
633 */
634
635 char *
636 method_get_next_argument (arglist_t argframe, const char **type)
637 {
638   const char *t = objc_skip_argspec (*type);
639
640   if (*t == '\0')
641     return 0;
642
643   *type = t;
644   t = objc_skip_typespec (t);
645
646   if (*t == '+')
647     return argframe->arg_regs + atoi (++t);
648   else
649     return argframe->arg_ptr + atoi (t);
650 }
651
652 /*
653   Return a pointer to the value of the first argument of the method
654   described in M with the given argumentframe ARGFRAME.  The type
655   is returned in TYPE.  type must be passed to successive calls of
656   method_get_next_argument.
657 */
658 char *
659 method_get_first_argument (struct objc_method *m,
660                            arglist_t argframe,
661                            const char **type)
662 {
663   *type = m->method_types;
664   return method_get_next_argument (argframe, type);
665 }
666
667 /*
668    Return a pointer to the ARGth argument of the method
669    M from the frame ARGFRAME.  The type of the argument
670    is returned in the value-result argument TYPE
671 */
672
673 char *
674 method_get_nth_argument (struct objc_method *m,
675                          arglist_t argframe, int arg,
676                          const char **type)
677 {
678   const char *t = objc_skip_argspec (m->method_types);
679
680   if (arg > method_get_number_of_arguments (m))
681     return 0;
682
683   while (arg--)
684     t = objc_skip_argspec (t);
685
686   *type = t;
687   t = objc_skip_typespec (t);
688
689   if (*t == '+')
690     return argframe->arg_regs + atoi (++t);
691   else
692     return argframe->arg_ptr + atoi (t);
693 }
694
695 unsigned
696 objc_get_type_qualifiers (const char *type)
697 {
698   unsigned res = 0;
699   BOOL flag = YES;
700
701   while (flag)
702     switch (*type++)
703       {
704       case _C_CONST:    res |= _F_CONST; break;
705       case _C_IN:       res |= _F_IN; break;
706       case _C_INOUT:    res |= _F_INOUT; break;
707       case _C_OUT:      res |= _F_OUT; break;
708       case _C_BYCOPY:   res |= _F_BYCOPY; break;
709       case _C_BYREF:  res |= _F_BYREF; break;
710       case _C_ONEWAY:   res |= _F_ONEWAY; break;
711       case _C_GCINVISIBLE: res |= _F_GCINVISIBLE; break;
712       default: flag = NO;
713     }
714
715   return res;
716 }
717
718
719 /* The following three functions can be used to determine how a
720    structure is laid out by the compiler. For example:
721
722   struct objc_struct_layout layout;
723   int i;
724
725   objc_layout_structure (type, &layout);
726   while (objc_layout_structure_next_member (&layout))
727     {
728       int position, align;
729       const char *type;
730
731       objc_layout_structure_get_info (&layout, &position, &align, &type);
732       printf ("element %d has offset %d, alignment %d\n",
733               i++, position, align);
734     }
735
736   These functions are used by objc_sizeof_type and objc_alignof_type
737   functions to compute the size and alignment of structures. The
738   previous method of computing the size and alignment of a structure
739   was not working on some architectures, particulary on AIX, and in
740   the presence of bitfields inside the structure. */
741 void
742 objc_layout_structure (const char *type,
743                            struct objc_struct_layout *layout)
744 {
745   const char *ntype;
746
747   if (*type++ != _C_STRUCT_B)
748     {
749       objc_error (nil, OBJC_ERR_BAD_TYPE,
750                  "record type expected in objc_layout_structure, got %s\n",
751                  type);
752     }
753
754   layout->original_type = type;
755
756   /* Skip "<name>=" if any. Avoid embedded structures and unions. */
757   ntype = type;
758   while (*ntype != _C_STRUCT_E && *ntype != _C_STRUCT_B && *ntype != _C_UNION_B
759          && *ntype++ != '=')
760     /* do nothing */;
761
762   /* If there's a "<name>=", ntype - 1 points to '='; skip the the name */
763   if (*(ntype - 1) == '=')
764     type = ntype;
765
766   layout->type = type;
767   layout->prev_type = NULL;
768   layout->record_size = 0;
769   layout->record_align = BITS_PER_UNIT;
770
771   layout->record_align = MAX (layout->record_align, STRUCTURE_SIZE_BOUNDARY);
772 }
773
774
775 BOOL
776 objc_layout_structure_next_member (struct objc_struct_layout *layout)
777 {
778   register int desired_align = 0;
779
780   /* The following are used only if the field is a bitfield */
781   register const char *bfld_type = 0;
782   register int bfld_type_size, bfld_type_align = 0, bfld_field_size = 0;
783
784   /* The current type without the type qualifiers */
785   const char *type;
786
787   /* Add the size of the previous field to the size of the record.  */
788   if (layout->prev_type)
789     {
790       type = objc_skip_type_qualifiers (layout->prev_type);
791
792       if (*type != _C_BFLD)
793         layout->record_size += objc_sizeof_type (type) * BITS_PER_UNIT;
794       else {
795         /* Get the bitfield's type */
796         for (bfld_type = type + 1;
797              isdigit ((unsigned char)*bfld_type);
798              bfld_type++)
799           /* do nothing */;
800
801         bfld_type_size = objc_sizeof_type (bfld_type) * BITS_PER_UNIT;
802         bfld_type_align = objc_alignof_type (bfld_type) * BITS_PER_UNIT;
803         bfld_field_size = atoi (objc_skip_typespec (bfld_type));
804         layout->record_size += bfld_field_size;
805       }
806     }
807
808   if (*layout->type == _C_STRUCT_E)
809     return NO;
810
811   /* Skip the variable name if any */
812   if (*layout->type == '"')
813     {
814       for (layout->type++; *layout->type++ != '"';)
815         /* do nothing */;
816     }
817
818   type = objc_skip_type_qualifiers (layout->type);
819
820   if (*type != _C_BFLD)
821     desired_align = objc_alignof_type (type) * BITS_PER_UNIT;
822   else
823     {
824       desired_align = 1;
825       /* Skip the bitfield's offset */
826       for (bfld_type = type + 1;
827            isdigit ((unsigned char) *bfld_type);
828            bfld_type++)
829         /* do nothing */;
830
831       bfld_type_size = objc_sizeof_type (bfld_type) * BITS_PER_UNIT;
832       bfld_type_align = objc_alignof_type (bfld_type) * BITS_PER_UNIT;
833       bfld_field_size = atoi (objc_skip_typespec (bfld_type));
834     }
835
836 #ifdef BIGGEST_FIELD_ALIGNMENT
837   desired_align = MIN (desired_align, BIGGEST_FIELD_ALIGNMENT);
838 #endif
839 #ifdef ADJUST_FIELD_ALIGN
840   desired_align = ADJUST_FIELD_ALIGN (type, desired_align);
841 #endif
842
843   /* Record must have at least as much alignment as any field.
844      Otherwise, the alignment of the field within the record
845      is meaningless.  */
846 #ifndef PCC_BITFIELD_TYPE_MATTERS
847   layout->record_align = MAX (layout->record_align, desired_align);
848 #else   /* PCC_BITFIELD_TYPE_MATTERS */
849   if (*type == _C_BFLD)
850     {
851       /* For these machines, a zero-length field does not
852          affect the alignment of the structure as a whole.
853          It does, however, affect the alignment of the next field
854          within the structure.  */
855       if (bfld_field_size)
856         layout->record_align = MAX (layout->record_align, desired_align);
857       else
858         desired_align = objc_alignof_type (bfld_type) * BITS_PER_UNIT;
859
860       /* A named bit field of declared type `int'
861          forces the entire structure to have `int' alignment.
862          Q1: How is encoded this thing and how to check for it?
863          Q2: How to determine maximum_field_alignment at runtime? */
864
865 /*        if (DECL_NAME (field) != 0) */
866       {
867         int type_align = bfld_type_align;
868 #if 0
869         if (maximum_field_alignment != 0)
870           type_align = MIN (type_align, maximum_field_alignment);
871         else if (DECL_PACKED (field))
872           type_align = MIN (type_align, BITS_PER_UNIT);
873 #endif
874
875         layout->record_align = MAX (layout->record_align, type_align);
876       }
877     }
878   else
879     layout->record_align = MAX (layout->record_align, desired_align);
880 #endif  /* PCC_BITFIELD_TYPE_MATTERS */
881
882   /* Does this field automatically have alignment it needs
883      by virtue of the fields that precede it and the record's
884      own alignment?  */
885
886   if (*type == _C_BFLD)
887     layout->record_size = atoi (type + 1);
888   else if (layout->record_size % desired_align != 0)
889     {
890       /* No, we need to skip space before this field.
891          Bump the cumulative size to multiple of field alignment.  */
892       layout->record_size = ROUND (layout->record_size, desired_align);
893     }
894
895   /* Jump to the next field in record. */
896
897   layout->prev_type = layout->type;
898   layout->type = objc_skip_typespec (layout->type);      /* skip component */
899
900   return YES;
901 }
902
903
904 void objc_layout_finish_structure (struct objc_struct_layout *layout,
905                                    unsigned int *size,
906                                    unsigned int *align)
907 {
908   if (layout->type && *layout->type == _C_STRUCT_E)
909     {
910       /* Work out the alignment of the record as one expression and store
911          in the record type.  Round it up to a multiple of the record's
912          alignment. */
913
914 #if defined (ROUND_TYPE_ALIGN) && ! defined (__sparc__)
915       layout->record_align = ROUND_TYPE_ALIGN (layout->original_type,
916                                                1,
917                                                layout->record_align);
918 #else
919       layout->record_align = MAX (1, layout->record_align);
920 #endif
921
922 #ifdef ROUND_TYPE_SIZE
923       layout->record_size = ROUND_TYPE_SIZE (layout->original_type,
924                                              layout->record_size,
925                                              layout->record_align);
926 #else
927       /* Round the size up to be a multiple of the required alignment */
928       layout->record_size = ROUND (layout->record_size, layout->record_align);
929 #endif
930
931       layout->type = NULL;
932     }
933   if (size)
934     *size = layout->record_size / BITS_PER_UNIT;
935   if (align)
936     *align = layout->record_align / BITS_PER_UNIT;
937 }
938
939
940 void objc_layout_structure_get_info (struct objc_struct_layout *layout,
941                                      unsigned int *offset,
942                                      unsigned int *align,
943                                      const char **type)
944 {
945   if (offset)
946     *offset = layout->record_size / BITS_PER_UNIT;
947   if (align)
948     *align = layout->record_align / BITS_PER_UNIT;
949   if (type)
950     *type = layout->prev_type;
951 }