OSDN Git Service

* encoding.c (TREE_TYPE, ARRAY_TYPE): Define.
[pf3gnuchains/gcc-fork.git] / 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)      objc_skip_typespec(TYPE)
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_ONEWAY
406          || *type == _C_GCINVISIBLE)
407     {
408       type += 1;
409     }
410   return type;
411 }
412
413   
414 /*
415   Skip one typespec element.  If the typespec is prepended by type
416   qualifiers, these are skipped as well.
417 */
418
419 const char* 
420 objc_skip_typespec (const char* type)
421 {
422   /* Skip the variable name if any */
423   if (*type == '"')
424     {
425       for (type++; *type++ != '"';)
426         /* do nothing */;
427     }
428
429   type = objc_skip_type_qualifiers (type);
430   
431   switch (*type) {
432
433   case _C_ID:
434     /* An id may be annotated by the actual type if it is known
435        with the @"ClassName" syntax */
436
437     if (*++type != '"')
438       return type;
439     else
440       {
441         while (*++type != '"') /* do nothing */;
442         return type + 1;
443       }
444
445     /* The following are one character type codes */
446   case _C_CLASS:
447   case _C_SEL:
448   case _C_CHR:
449   case _C_UCHR:
450   case _C_CHARPTR:
451   case _C_ATOM:
452   case _C_SHT:
453   case _C_USHT:
454   case _C_INT:
455   case _C_UINT:
456   case _C_LNG:
457   case _C_ULNG:
458   case _C_LNG_LNG:
459   case _C_ULNG_LNG:
460   case _C_FLT:
461   case _C_DBL:
462   case _C_VOID:
463   case _C_UNDEF:
464     return ++type;
465     break;
466
467   case _C_ARY_B:
468     /* skip digits, typespec and closing ']' */
469     
470     while(isdigit(*++type));
471     type = objc_skip_typespec(type);
472     if (*type == _C_ARY_E)
473       return ++type;
474     else
475       {
476         objc_error(nil, OBJC_ERR_BAD_TYPE, "bad array type %s\n", type);
477         return 0;
478       }
479
480   case _C_BFLD:
481     /* The new encoding of bitfields is: b 'position' 'type' 'size' */
482     while (isdigit (*++type));  /* skip position */
483     while (isdigit (*++type));  /* skip type and size */
484     return type;
485
486   case _C_STRUCT_B:
487     /* skip name, and elements until closing '}'  */
488     
489     while (*type != _C_STRUCT_E && *type++ != '=');
490     while (*type != _C_STRUCT_E) { type = objc_skip_typespec (type); }
491     return ++type;
492
493   case _C_UNION_B:
494     /* skip name, and elements until closing ')'  */
495     
496     while (*type != _C_UNION_E && *type++ != '=');
497     while (*type != _C_UNION_E) { type = objc_skip_typespec (type); }
498     return ++type;
499
500   case _C_PTR:
501     /* Just skip the following typespec */
502     
503     return objc_skip_typespec (++type);
504     
505   default:
506     {
507       objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
508       return 0;
509     }
510   }
511 }
512
513 /*
514   Skip an offset as part of a method encoding.  This is prepended by a
515   '+' if the argument is passed in registers.
516 */
517 inline const char* 
518 objc_skip_offset (const char* type)
519 {
520   if (*type == '+') type++;
521   while(isdigit(*++type));
522   return type;
523 }
524
525 /*
526   Skip an argument specification of a method encoding.
527 */
528 const char*
529 objc_skip_argspec (const char* type)
530 {
531   type = objc_skip_typespec (type);
532   type = objc_skip_offset (type);
533   return type;
534 }
535
536 /*
537   Return the number of arguments that the method MTH expects.
538   Note that all methods need two implicit arguments `self' and
539   `_cmd'. 
540 */
541 int
542 method_get_number_of_arguments (struct objc_method* mth)
543 {
544   int i = 0;
545   const char* type = mth->method_types;
546   while (*type)
547     {
548       type = objc_skip_argspec (type);
549       i += 1;
550     }
551   return i - 1;
552 }
553
554 /*
555   Return the size of the argument block needed on the stack to invoke
556   the method MTH.  This may be zero, if all arguments are passed in
557   registers.
558 */
559
560 int
561 method_get_sizeof_arguments (struct objc_method* mth)
562 {
563   const char* type = objc_skip_typespec (mth->method_types);
564   return atoi (type);
565 }
566
567 /*
568   Return a pointer to the next argument of ARGFRAME.  type points to
569   the last argument.  Typical use of this look like:
570
571   {
572     char *datum, *type; 
573     for (datum = method_get_first_argument (method, argframe, &type);
574          datum; datum = method_get_next_argument (argframe, &type))
575       {
576         unsigned flags = objc_get_type_qualifiers (type);
577         type = objc_skip_type_qualifiers (type);
578         if (*type != _C_PTR)
579           [portal encodeData: datum ofType: type];
580         else
581           {
582             if ((flags & _F_IN) == _F_IN)
583               [portal encodeData: *(char**)datum ofType: ++type];
584           }
585       }
586   }
587 */  
588
589 char*
590 method_get_next_argument (arglist_t argframe,
591                           const char **type)
592 {
593   const char *t = objc_skip_argspec (*type);
594
595   if (*t == '\0')
596     return 0;
597
598   *type = t;
599   t = objc_skip_typespec (t);
600
601   if (*t == '+')
602     return argframe->arg_regs + atoi (++t);
603   else
604     return argframe->arg_ptr + atoi (t);
605 }
606
607 /*
608   Return a pointer to the value of the first argument of the method 
609   described in M with the given argumentframe ARGFRAME.  The type
610   is returned in TYPE.  type must be passed to successive calls of 
611   method_get_next_argument.
612 */
613 char*
614 method_get_first_argument (struct objc_method* m,
615                            arglist_t argframe, 
616                            const char** type)
617 {
618   *type = m->method_types;
619   return method_get_next_argument (argframe, type);
620 }
621
622 /*
623    Return a pointer to the ARGth argument of the method
624    M from the frame ARGFRAME.  The type of the argument
625    is returned in the value-result argument TYPE 
626 */
627
628 char*
629 method_get_nth_argument (struct objc_method* m,
630                          arglist_t argframe, int arg, 
631                          const char **type)
632 {
633   const char* t = objc_skip_argspec (m->method_types);
634
635   if (arg > method_get_number_of_arguments (m))
636     return 0;
637
638   while (arg--)
639     t = objc_skip_argspec (t);
640   
641   *type = t;
642   t = objc_skip_typespec (t);
643
644   if (*t == '+')
645     return argframe->arg_regs + atoi (++t);
646   else
647     return argframe->arg_ptr + atoi (t);
648 }
649
650 unsigned
651 objc_get_type_qualifiers (const char* type)
652 {
653   unsigned res = 0;
654   BOOL flag = YES;
655
656   while (flag)
657     switch (*type++)
658       {
659       case _C_CONST:    res |= _F_CONST; break;
660       case _C_IN:       res |= _F_IN; break;
661       case _C_INOUT:    res |= _F_INOUT; break;
662       case _C_OUT:      res |= _F_OUT; break;
663       case _C_BYCOPY:   res |= _F_BYCOPY; break;
664       case _C_ONEWAY:   res |= _F_ONEWAY; break;
665       case _C_GCINVISIBLE: res |= _F_GCINVISIBLE; break;
666       default: flag = NO;
667     }
668
669   return res;
670 }
671
672
673 /* The following three functions can be used to determine how a
674    structure is laid out by the compiler. For example:
675
676   struct objc_struct_layout layout;
677   int i;
678
679   objc_layout_structure (type, &layout);
680   while (objc_layout_structure_next_member (&layout))
681     {
682       int position, align;
683       const char *type;
684
685       objc_layout_structure_get_info (&layout, &position, &align, &type);
686       printf ("element %d has offset %d, alignment %d\n",
687               i++, position, align);
688     }
689
690   These functions are used by objc_sizeof_type and objc_alignof_type
691   functions to compute the size and alignment of structures. The
692   previous method of computing the size and alignment of a structure
693   was not working on some architectures, particulary on AIX, and in
694   the presence of bitfields inside the structure. */
695 void
696 objc_layout_structure (const char *type,
697                            struct objc_struct_layout *layout)
698 {
699   const char *ntype;
700
701   if (*type++ != _C_STRUCT_B)
702     {
703       objc_error(nil, OBJC_ERR_BAD_TYPE,
704                  "record type expected in objc_layout_structure, got %s\n",
705                  type);
706     }
707
708   layout->original_type = type;
709
710   /* Skip "<name>=" if any. Avoid embedded structures and unions. */
711   ntype = type;
712   while (*ntype != _C_STRUCT_E && *ntype != _C_STRUCT_B && *ntype != _C_UNION_B
713          && *ntype++ != '=')
714     /* do nothing */;
715
716   /* If there's a "<name>=", ntype - 1 points to '='; skip the the name */
717   if (*(ntype - 1) == '=')
718     type = ntype;
719
720   layout->type = type;
721   layout->prev_type = NULL;
722   layout->record_size = 0;
723   layout->record_align = BITS_PER_UNIT;
724
725 #ifdef STRUCTURE_SIZE_BOUNDARY
726   layout->record_align = MAX (layout->record_align, STRUCTURE_SIZE_BOUNDARY);
727 #endif
728 }
729
730
731 BOOL
732 objc_layout_structure_next_member (struct objc_struct_layout *layout)
733 {
734   register int known_align = layout->record_size;
735   register int desired_align = 0;
736
737   /* The following are used only if the field is a bitfield */
738   register const char *bfld_type;
739   register int bfld_type_size, bfld_type_align, bfld_field_size;
740
741   /* The current type without the type qualifiers */
742   const char *type;
743
744 #if 1
745   if (layout->prev_type == NULL)
746     {
747       layout->prev_type = layout->type;
748       layout->type = objc_skip_typespec (layout->prev_type);
749       return YES;
750     }
751 #endif
752
753   /* Add the size of the previous field to the size of the record.  */
754   if (layout->prev_type)
755     {
756       type = objc_skip_type_qualifiers (layout->prev_type);
757
758       if (*type != _C_BFLD)
759         layout->record_size += objc_sizeof_type (type) * BITS_PER_UNIT;
760       else {
761         desired_align = 1;
762         /* Get the bitfield's type */
763         for (bfld_type = type + 1;
764              isdigit(*bfld_type);
765              bfld_type++)
766           /* do nothing */;
767
768         bfld_type_size = objc_sizeof_type (bfld_type) * BITS_PER_UNIT;
769         bfld_type_align = objc_alignof_type (bfld_type) * BITS_PER_UNIT;
770         bfld_field_size = atoi (objc_skip_typespec (bfld_type));
771         layout->record_size += bfld_field_size;
772       }
773     }
774
775   if (*layout->type == _C_STRUCT_E)
776     return NO;
777
778   /* Skip the variable name if any */
779   if (*layout->type == '"')
780     {
781       for (layout->type++; *layout->type++ != '"';)
782         /* do nothing */;
783     }
784
785   type = objc_skip_type_qualifiers (layout->type);
786
787   if (*type != _C_BFLD)
788     desired_align = objc_alignof_type(type) * BITS_PER_UNIT;
789   else
790     {
791       desired_align = 1;
792       /* Skip the bitfield's offset */
793       for (bfld_type = type + 1; isdigit(*bfld_type); bfld_type++)
794         /* do nothing */;
795
796       bfld_type_size = objc_sizeof_type (bfld_type) * BITS_PER_UNIT;
797       bfld_type_align = objc_alignof_type (bfld_type) * BITS_PER_UNIT;
798       bfld_field_size = atoi (objc_skip_typespec (bfld_type));
799     }
800
801 #ifdef BIGGEST_FIELD_ALIGNMENT
802   desired_align = MIN (desired_align, BIGGEST_FIELD_ALIGNMENT);
803 #endif
804 #ifdef ADJUST_FIELD_ALIGN
805   desired_align = ADJUST_FIELD_ALIGN (type, desired_align);
806 #endif
807
808   /* Record must have at least as much alignment as any field.
809      Otherwise, the alignment of the field within the record
810      is meaningless.  */
811 #ifndef PCC_BITFIELD_TYPE_MATTERS
812   layout->record_align = MAX (layout->record_align, desired_align);
813 #else
814   if (*type == _C_BFLD)
815     {
816       /* For these machines, a zero-length field does not
817          affect the alignment of the structure as a whole.
818          It does, however, affect the alignment of the next field
819          within the structure.  */
820       if (bfld_field_size)
821         layout->record_align = MAX (layout->record_align, desired_align);
822       else
823         desired_align = objc_alignof_type (bfld_type) * BITS_PER_UNIT;
824
825       /* A named bit field of declared type `int'
826          forces the entire structure to have `int' alignment.
827          Q1: How is encoded this thing and how to check for it?
828          Q2: How to determine maximum_field_alignment at runtime? */
829
830 /*        if (DECL_NAME (field) != 0) */
831       {
832         int type_align = bfld_type_align;
833 #if 0
834         if (maximum_field_alignment != 0)
835           type_align = MIN (type_align, maximum_field_alignment);
836         else if (DECL_PACKED (field))
837           type_align = MIN (type_align, BITS_PER_UNIT);
838 #endif
839
840         layout->record_align = MAX (layout->record_align, type_align);
841       }
842     }
843   else
844     layout->record_align = MAX (layout->record_align, desired_align);
845 #endif
846
847   /* Does this field automatically have alignment it needs
848      by virtue of the fields that precede it and the record's
849      own alignment?  */
850
851   if (*type == _C_BFLD)
852     layout->record_size = atoi (type + 1);
853   else if (layout->record_size % desired_align != 0)
854     {
855       /* No, we need to skip space before this field.
856          Bump the cumulative size to multiple of field alignment.  */
857       layout->record_size = ROUND (layout->record_size, desired_align);
858     }
859   
860   /* Jump to the next field in record. */
861
862   layout->prev_type = layout->type;
863   layout->type = objc_skip_typespec (layout->type);      /* skip component */
864
865   return YES;
866 }
867
868
869 void objc_layout_finish_structure (struct objc_struct_layout *layout,
870                                    unsigned int *size,
871                                    unsigned int *align)
872 {
873   if (layout->type && *layout->type == _C_STRUCT_E)
874     {
875       /* Work out the alignment of the record as one expression and store
876          in the record type.  Round it up to a multiple of the record's
877          alignment. */
878
879 #ifdef ROUND_TYPE_ALIGN
880       layout->record_align = ROUND_TYPE_ALIGN (layout->original_type,
881                                                1,
882                                                layout->record_align);
883 #else
884       layout->record_align = MAX (1, layout->record_align);
885 #endif
886
887 #ifdef ROUND_TYPE_SIZE
888       layout->record_size = ROUND_TYPE_SIZE (layout->original_type,
889                                              layout->record_size,
890                                              layout->record_align);
891 #else
892       /* Round the size up to be a multiple of the required alignment */
893       layout->record_size = ROUND (layout->record_size, layout->record_align);
894 #endif
895
896       layout->type = NULL;
897     }
898   if (size)
899     *size = layout->record_size / BITS_PER_UNIT;
900   if (align)
901     *align = layout->record_align / BITS_PER_UNIT;
902 }
903
904
905 void objc_layout_structure_get_info (struct objc_struct_layout *layout,
906                                      unsigned int *offset,
907                                      unsigned int *align,
908                                      const char **type)
909 {
910   if (offset)
911     *offset = layout->record_size / BITS_PER_UNIT;
912   if (align)
913     *align = layout->record_align / BITS_PER_UNIT;
914   if (type)
915     *type = layout->prev_type;
916 }