OSDN Git Service

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