OSDN Git Service

2002-04-19 David O'Brien <obrien@FreeBSD.org>
[pf3gnuchains/gcc-fork.git] / libobjc / encoding.c
1 /* Encoding of types for Objective C.
2    Copyright (C) 1993, 1995, 1996, 1997, 1998, 2000 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 #undef  MAX
34 #define MAX(X, Y)                    \
35   ({ typeof(X) __x = (X), __y = (Y); \
36      (__x > __y ? __x : __y); })
37
38 #undef  MIN
39 #define MIN(X, Y)                    \
40   ({ typeof(X) __x = (X), __y = (Y); \
41      (__x < __y ? __x : __y); })
42
43 #undef  ROUND
44 #define ROUND(V, A) \
45   ({ typeof(V) __v=(V); typeof(A) __a=(A); \
46      __a*((__v+__a-1)/__a); })
47
48
49 /* Various hacks for objc_layout_record. These are used by the target
50    macros. */
51
52 #define TREE_CODE(TYPE) *(TYPE)
53 #define TREE_TYPE(TREE) (TREE)
54
55 #define RECORD_TYPE     _C_STRUCT_B
56 #define UNION_TYPE      _C_UNION_B
57 #define QUAL_UNION_TYPE _C_UNION_B
58 #define ARRAY_TYPE      _C_ARY_B
59
60 #define REAL_TYPE       _C_DBL
61
62 #define VECTOR_TYPE     _C_VECTOR
63
64 #define TYPE_FIELDS(TYPE)     objc_skip_typespec (TYPE)
65
66 #define DECL_MODE(TYPE) *(TYPE)
67 #define TYPE_MODE(TYPE) *(TYPE)
68
69 #define DFmode          _C_DBL
70
71 #define get_inner_array_type(TYPE)      ((TYPE) + 1)
72
73 /* Some ports (eg ARM) allow the structure size boundary to be
74    selected at compile-time.  We override the normal definition with
75    one that has a constant value for this compilation.  */
76 #undef STRUCTURE_SIZE_BOUNDARY
77 #define STRUCTURE_SIZE_BOUNDARY (BITS_PER_UNIT * sizeof (struct{char a;}))
78
79 /* Some ROUND_TYPE_ALIGN macros use TARGET_foo, and consequently
80    target_flags.  Define a dummy entry here to so we don't die.  */
81
82 static int target_flags = 0;
83
84 static inline int
85 atoi (const char* str)
86 {
87   int res = 0;
88   
89   while (isdigit (*str))
90     res *= 10, res += (*str++ - '0');
91
92   return res;
93 }
94
95 /*
96   return the size of an object specified by type 
97 */
98
99 int
100 objc_sizeof_type (const char* type)
101 {
102   /* Skip the variable name if any */
103   if (*type == '"')
104     {
105       for (type++; *type++ != '"';)
106         /* do nothing */;
107     }
108
109   switch(*type) {
110   case _C_ID:
111     return sizeof(id);
112     break;
113
114   case _C_CLASS:
115     return sizeof(Class);
116     break;
117
118   case _C_SEL:
119     return sizeof(SEL);
120     break;
121
122   case _C_CHR:
123     return sizeof(char);
124     break;
125     
126   case _C_UCHR:
127     return sizeof(unsigned char);
128     break;
129
130   case _C_SHT:
131     return sizeof(short);
132     break;
133
134   case _C_USHT:
135     return sizeof(unsigned short);
136     break;
137
138   case _C_INT:
139     return sizeof(int);
140     break;
141
142   case _C_UINT:
143     return sizeof(unsigned int);
144     break;
145
146   case _C_LNG:
147     return sizeof(long);
148     break;
149
150   case _C_ULNG:
151     return sizeof(unsigned long);
152     break;
153
154   case _C_LNG_LNG:
155     return sizeof(long long);
156     break;
157
158   case _C_ULNG_LNG:
159     return sizeof(unsigned long long);
160     break;
161
162   case _C_FLT:
163     return sizeof(float);
164     break;
165
166   case _C_DBL:
167     return sizeof(double);
168     break;
169
170   case _C_VOID:
171     return sizeof(void);
172     break;
173   case _C_PTR:
174   case _C_ATOM:
175   case _C_CHARPTR:
176     return sizeof(char*);
177     break;
178
179   case _C_ARY_B:
180     {
181       int len = atoi(type+1);
182       while (isdigit(*++type));
183       return len*objc_aligned_size (type);
184     }
185     break; 
186
187   case _C_BFLD:
188     {
189       /* The new encoding of bitfields is: b 'position' 'type' 'size' */
190       int position, size;
191       int startByte, endByte;
192
193       position = atoi (type + 1);
194       while (isdigit (*++type));
195       size = atoi (type + 1);
196
197       startByte = position / BITS_PER_UNIT;
198       endByte = (position + size) / BITS_PER_UNIT;
199       return endByte - startByte;
200     }
201
202   case _C_STRUCT_B:
203     {
204       struct objc_struct_layout layout;
205       unsigned int size;
206
207       objc_layout_structure (type, &layout);
208       while (objc_layout_structure_next_member (&layout))
209         /* do nothing */ ;
210       objc_layout_finish_structure (&layout, &size, NULL);
211
212       return size;
213     }
214
215   case _C_UNION_B:
216     {
217       int max_size = 0;
218       while (*type != _C_UNION_E && *type++ != '=') /* do nothing */;
219       while (*type != _C_UNION_E)
220         {
221           /* Skip the variable name if any */
222           if (*type == '"')
223             {
224               for (type++; *type++ != '"';)
225                 /* do nothing */;
226             }
227           max_size = MAX (max_size, objc_sizeof_type (type));
228           type = objc_skip_typespec (type);
229         }
230       return max_size;
231     }
232     
233   default:
234     {
235       objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
236       return 0;
237     }
238   }
239 }
240
241
242 /*
243   Return the alignment of an object specified by type 
244 */
245
246 int
247 objc_alignof_type(const char* type)
248 {
249   /* Skip the variable name if any */
250   if (*type == '"')
251     {
252       for (type++; *type++ != '"';)
253         /* do nothing */;
254     }
255   switch(*type) {
256   case _C_ID:
257     return __alignof__(id);
258     break;
259
260   case _C_CLASS:
261     return __alignof__(Class);
262     break;
263     
264   case _C_SEL:
265     return __alignof__(SEL);
266     break;
267
268   case _C_CHR:
269     return __alignof__(char);
270     break;
271     
272   case _C_UCHR:
273     return __alignof__(unsigned char);
274     break;
275
276   case _C_SHT:
277     return __alignof__(short);
278     break;
279
280   case _C_USHT:
281     return __alignof__(unsigned short);
282     break;
283
284   case _C_INT:
285     return __alignof__(int);
286     break;
287
288   case _C_UINT:
289     return __alignof__(unsigned int);
290     break;
291
292   case _C_LNG:
293     return __alignof__(long);
294     break;
295
296   case _C_ULNG:
297     return __alignof__(unsigned long);
298     break;
299
300   case _C_LNG_LNG:
301     return __alignof__(long long);
302     break;
303
304   case _C_ULNG_LNG:
305     return __alignof__(unsigned long long);
306     break;
307
308   case _C_FLT:
309     return __alignof__(float);
310     break;
311
312   case _C_DBL:
313     return __alignof__(double);
314     break;
315
316   case _C_PTR:
317   case _C_ATOM:
318   case _C_CHARPTR:
319     return __alignof__(char*);
320     break;
321
322   case _C_ARY_B:
323     while (isdigit(*++type)) /* do nothing */;
324     return objc_alignof_type (type);
325
326   case _C_STRUCT_B:
327     {
328       struct objc_struct_layout layout;
329       unsigned int align;
330
331       objc_layout_structure (type, &layout);
332       while (objc_layout_structure_next_member (&layout))
333         /* do nothing */;
334       objc_layout_finish_structure (&layout, NULL, &align);
335
336       return align;
337     }
338
339   case _C_UNION_B:
340     {
341       int maxalign = 0;
342       while (*type != _C_UNION_E && *type++ != '=') /* do nothing */;
343       while (*type != _C_UNION_E)
344         {
345           /* Skip the variable name if any */
346           if (*type == '"')
347             {
348               for (type++; *type++ != '"';)
349                 /* do nothing */;
350             }
351           maxalign = MAX (maxalign, objc_alignof_type (type));
352           type = objc_skip_typespec (type);
353         }
354       return maxalign;
355     }
356
357   default:
358     {
359       objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
360       return 0;
361     }
362   }
363 }
364
365 /*
366   The aligned size if the size rounded up to the nearest alignment.
367 */
368
369 int
370 objc_aligned_size (const char* type)
371 {
372   int size, align;
373
374   /* Skip the variable name */
375   if (*type == '"')
376     {
377       for (type++; *type++ != '"';)
378         /* do nothing */;
379     }
380
381   size = objc_sizeof_type (type);
382   align = objc_alignof_type (type);
383
384   return ROUND (size, align);
385 }
386
387 /*
388   The size rounded up to the nearest integral of the wordsize, taken
389   to be the size of a void*.
390 */
391
392 int 
393 objc_promoted_size (const char* type)
394 {
395   int size, wordsize;
396
397   /* Skip the variable name */
398   if (*type == '"')
399     {
400       for (type++; *type++ != '"';)
401         /* do nothing */;
402     }
403
404   size = objc_sizeof_type (type);
405   wordsize = sizeof (void*);
406
407   return ROUND (size, wordsize);
408 }
409
410 /*
411   Skip type qualifiers.  These may eventually precede typespecs
412   occurring in method prototype encodings.
413 */
414
415 inline const char*
416 objc_skip_type_qualifiers (const char* type)
417 {
418   while (*type == _C_CONST
419          || *type == _C_IN 
420          || *type == _C_INOUT
421          || *type == _C_OUT 
422          || *type == _C_BYCOPY
423          || *type == _C_BYREF
424          || *type == _C_ONEWAY
425          || *type == _C_GCINVISIBLE)
426     {
427       type += 1;
428     }
429   return type;
430 }
431
432   
433 /*
434   Skip one typespec element.  If the typespec is prepended by type
435   qualifiers, these are skipped as well.
436 */
437
438 const char* 
439 objc_skip_typespec (const char* type)
440 {
441   /* Skip the variable name if any */
442   if (*type == '"')
443     {
444       for (type++; *type++ != '"';)
445         /* do nothing */;
446     }
447
448   type = objc_skip_type_qualifiers (type);
449   
450   switch (*type) {
451
452   case _C_ID:
453     /* An id may be annotated by the actual type if it is known
454        with the @"ClassName" syntax */
455
456     if (*++type != '"')
457       return type;
458     else
459       {
460         while (*++type != '"') /* do nothing */;
461         return type + 1;
462       }
463
464     /* The following are one character type codes */
465   case _C_CLASS:
466   case _C_SEL:
467   case _C_CHR:
468   case _C_UCHR:
469   case _C_CHARPTR:
470   case _C_ATOM:
471   case _C_SHT:
472   case _C_USHT:
473   case _C_INT:
474   case _C_UINT:
475   case _C_LNG:
476   case _C_ULNG:
477   case _C_LNG_LNG:
478   case _C_ULNG_LNG:
479   case _C_FLT:
480   case _C_DBL:
481   case _C_VOID:
482   case _C_UNDEF:
483     return ++type;
484     break;
485
486   case _C_ARY_B:
487     /* skip digits, typespec and closing ']' */
488     
489     while(isdigit(*++type));
490     type = objc_skip_typespec(type);
491     if (*type == _C_ARY_E)
492       return ++type;
493     else
494       {
495         objc_error(nil, OBJC_ERR_BAD_TYPE, "bad array type %s\n", type);
496         return 0;
497       }
498
499   case _C_BFLD:
500     /* The new encoding of bitfields is: b 'position' 'type' 'size' */
501     while (isdigit (*++type));  /* skip position */
502     while (isdigit (*++type));  /* skip type and size */
503     return type;
504
505   case _C_STRUCT_B:
506     /* skip name, and elements until closing '}'  */
507     
508     while (*type != _C_STRUCT_E && *type++ != '=');
509     while (*type != _C_STRUCT_E) { type = objc_skip_typespec (type); }
510     return ++type;
511
512   case _C_UNION_B:
513     /* skip name, and elements until closing ')'  */
514     
515     while (*type != _C_UNION_E && *type++ != '=');
516     while (*type != _C_UNION_E) { type = objc_skip_typespec (type); }
517     return ++type;
518
519   case _C_PTR:
520     /* Just skip the following typespec */
521     
522     return objc_skip_typespec (++type);
523     
524   default:
525     {
526       objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
527       return 0;
528     }
529   }
530 }
531
532 /*
533   Skip an offset as part of a method encoding.  This is prepended by a
534   '+' if the argument is passed in registers.
535 */
536 inline const char* 
537 objc_skip_offset (const char* type)
538 {
539   if (*type == '+') type++;
540   while(isdigit(*++type));
541   return type;
542 }
543
544 /*
545   Skip an argument specification of a method encoding.
546 */
547 const char*
548 objc_skip_argspec (const char* type)
549 {
550   type = objc_skip_typespec (type);
551   type = objc_skip_offset (type);
552   return type;
553 }
554
555 /*
556   Return the number of arguments that the method MTH expects.
557   Note that all methods need two implicit arguments `self' and
558   `_cmd'. 
559 */
560 int
561 method_get_number_of_arguments (struct objc_method* mth)
562 {
563   int i = 0;
564   const char* type = mth->method_types;
565   while (*type)
566     {
567       type = objc_skip_argspec (type);
568       i += 1;
569     }
570   return i - 1;
571 }
572
573 /*
574   Return the size of the argument block needed on the stack to invoke
575   the method MTH.  This may be zero, if all arguments are passed in
576   registers.
577 */
578
579 int
580 method_get_sizeof_arguments (struct objc_method* mth)
581 {
582   const char* type = objc_skip_typespec (mth->method_types);
583   return atoi (type);
584 }
585
586 /*
587   Return a pointer to the next argument of ARGFRAME.  type points to
588   the last argument.  Typical use of this look like:
589
590   {
591     char *datum, *type; 
592     for (datum = method_get_first_argument (method, argframe, &type);
593          datum; datum = method_get_next_argument (argframe, &type))
594       {
595         unsigned flags = objc_get_type_qualifiers (type);
596         type = objc_skip_type_qualifiers (type);
597         if (*type != _C_PTR)
598           [portal encodeData: datum ofType: type];
599         else
600           {
601             if ((flags & _F_IN) == _F_IN)
602               [portal encodeData: *(char**)datum ofType: ++type];
603           }
604       }
605   }
606 */  
607
608 char*
609 method_get_next_argument (arglist_t argframe,
610                           const char **type)
611 {
612   const char *t = objc_skip_argspec (*type);
613
614   if (*t == '\0')
615     return 0;
616
617   *type = t;
618   t = objc_skip_typespec (t);
619
620   if (*t == '+')
621     return argframe->arg_regs + atoi (++t);
622   else
623     return argframe->arg_ptr + atoi (t);
624 }
625
626 /*
627   Return a pointer to the value of the first argument of the method 
628   described in M with the given argumentframe ARGFRAME.  The type
629   is returned in TYPE.  type must be passed to successive calls of 
630   method_get_next_argument.
631 */
632 char*
633 method_get_first_argument (struct objc_method* m,
634                            arglist_t argframe, 
635                            const char** type)
636 {
637   *type = m->method_types;
638   return method_get_next_argument (argframe, type);
639 }
640
641 /*
642    Return a pointer to the ARGth argument of the method
643    M from the frame ARGFRAME.  The type of the argument
644    is returned in the value-result argument TYPE 
645 */
646
647 char*
648 method_get_nth_argument (struct objc_method* m,
649                          arglist_t argframe, int arg, 
650                          const char **type)
651 {
652   const char* t = objc_skip_argspec (m->method_types);
653
654   if (arg > method_get_number_of_arguments (m))
655     return 0;
656
657   while (arg--)
658     t = objc_skip_argspec (t);
659   
660   *type = t;
661   t = objc_skip_typespec (t);
662
663   if (*t == '+')
664     return argframe->arg_regs + atoi (++t);
665   else
666     return argframe->arg_ptr + atoi (t);
667 }
668
669 unsigned
670 objc_get_type_qualifiers (const char* type)
671 {
672   unsigned res = 0;
673   BOOL flag = YES;
674
675   while (flag)
676     switch (*type++)
677       {
678       case _C_CONST:    res |= _F_CONST; break;
679       case _C_IN:       res |= _F_IN; break;
680       case _C_INOUT:    res |= _F_INOUT; break;
681       case _C_OUT:      res |= _F_OUT; break;
682       case _C_BYCOPY:   res |= _F_BYCOPY; break;
683       case _C_BYREF:  res |= _F_BYREF; break;
684       case _C_ONEWAY:   res |= _F_ONEWAY; break;
685       case _C_GCINVISIBLE: res |= _F_GCINVISIBLE; break;
686       default: flag = NO;
687     }
688
689   return res;
690 }
691
692
693 /* The following three functions can be used to determine how a
694    structure is laid out by the compiler. For example:
695
696   struct objc_struct_layout layout;
697   int i;
698
699   objc_layout_structure (type, &layout);
700   while (objc_layout_structure_next_member (&layout))
701     {
702       int position, align;
703       const char *type;
704
705       objc_layout_structure_get_info (&layout, &position, &align, &type);
706       printf ("element %d has offset %d, alignment %d\n",
707               i++, position, align);
708     }
709
710   These functions are used by objc_sizeof_type and objc_alignof_type
711   functions to compute the size and alignment of structures. The
712   previous method of computing the size and alignment of a structure
713   was not working on some architectures, particulary on AIX, and in
714   the presence of bitfields inside the structure. */
715 void
716 objc_layout_structure (const char *type,
717                            struct objc_struct_layout *layout)
718 {
719   const char *ntype;
720
721   if (*type++ != _C_STRUCT_B)
722     {
723       objc_error(nil, OBJC_ERR_BAD_TYPE,
724                  "record type expected in objc_layout_structure, got %s\n",
725                  type);
726     }
727
728   layout->original_type = type;
729
730   /* Skip "<name>=" if any. Avoid embedded structures and unions. */
731   ntype = type;
732   while (*ntype != _C_STRUCT_E && *ntype != _C_STRUCT_B && *ntype != _C_UNION_B
733          && *ntype++ != '=')
734     /* do nothing */;
735
736   /* If there's a "<name>=", ntype - 1 points to '='; skip the the name */
737   if (*(ntype - 1) == '=')
738     type = ntype;
739
740   layout->type = type;
741   layout->prev_type = NULL;
742   layout->record_size = 0;
743   layout->record_align = BITS_PER_UNIT;
744
745   layout->record_align = MAX (layout->record_align, STRUCTURE_SIZE_BOUNDARY);
746 }
747
748
749 BOOL
750 objc_layout_structure_next_member (struct objc_struct_layout *layout)
751 {
752   register int known_align = layout->record_size;
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;
757   register int bfld_type_size, bfld_type_align, bfld_field_size;
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(*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(*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 }