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