]> err.no Git - sope/blob - gnustep-objc/encoding.c
improved rrule parser
[sope] / gnustep-objc / 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 "compiler-info.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 objc_atoi(register const char* str) {
67   register int res = 0;
68   
69   while (isdigit ((int)*str))
70     res *= 10, res += (*str++ - '0');
71
72   return res;
73 }
74
75 /*
76   return the size of an object specified by type 
77 */
78
79 int objc_sizeof_type (const char* type) {
80   /* Skip the variable name if any */
81   if (*type == '"')
82     {
83       for (type++; *type++ != '"';)
84         /* do nothing */;
85     }
86
87   switch(*type) {
88   case _C_ID:
89     return sizeof(id);
90     break;
91
92   case _C_CLASS:
93     return sizeof(Class);
94     break;
95
96   case _C_SEL:
97     return sizeof(SEL);
98     break;
99
100   case _C_CHR:
101     return sizeof(char);
102     break;
103     
104   case _C_UCHR:
105     return sizeof(unsigned char);
106     break;
107
108   case _C_SHT:
109     return sizeof(short);
110     break;
111
112   case _C_USHT:
113     return sizeof(unsigned short);
114     break;
115
116   case _C_INT:
117     return sizeof(int);
118     break;
119
120   case _C_UINT:
121     return sizeof(unsigned int);
122     break;
123
124   case _C_LNG:
125     return sizeof(long);
126     break;
127
128   case _C_ULNG:
129     return sizeof(unsigned long);
130     break;
131
132   case _C_LNG_LNG:
133     return sizeof(long long);
134     break;
135
136   case _C_ULNG_LNG:
137     return sizeof(unsigned long long);
138     break;
139
140   case _C_FLT:
141     return sizeof(float);
142     break;
143
144   case _C_DBL:
145     return sizeof(double);
146     break;
147
148   case _C_VOID:
149     return sizeof(void);
150     break;
151   case _C_PTR:
152   case _C_ATOM:
153   case _C_CHARPTR:
154     return sizeof(char*);
155     break;
156
157   case _C_ARY_B:
158     {
159       int len = objc_atoi(type+1);
160       while (isdigit((int)*++type));
161       return len*objc_aligned_size (type);
162     }
163     break; 
164
165   case _C_BFLD:
166     {
167       /* The new encoding of bitfields is: b 'position' 'type' 'size' */
168       int position, size;
169       int startByte, endByte;
170
171       position = objc_atoi (type + 1);
172       while (isdigit ((int)*++type));
173       size = objc_atoi (type + 1);
174
175       startByte = position / BITS_PER_UNIT;
176       endByte = (position + size) / BITS_PER_UNIT;
177       return endByte - startByte;
178     }
179
180   case _C_STRUCT_B:
181     {
182       struct objc_struct_layout layout;
183       unsigned int size;
184
185       objc_layout_structure (type, &layout);
186       while (objc_layout_structure_next_member (&layout))
187         /* do nothing */ ;
188       objc_layout_finish_structure (&layout, &size, NULL);
189
190       return size;
191     }
192
193   case _C_UNION_B:
194     {
195       int max_size = 0;
196       while (*type != _C_UNION_E && *type++ != '=') /* do nothing */;
197       while (*type != _C_UNION_E)
198         {
199           /* Skip the variable name if any */
200           if (*type == '"')
201             {
202               for (type++; *type++ != '"';)
203                 /* do nothing */;
204             }
205           max_size = MAX (max_size, objc_sizeof_type (type));
206           type = objc_skip_typespec (type);
207         }
208       return max_size;
209     }
210     
211   default:
212     {
213       objc_error(nil, OBJC_ERR_BAD_TYPE, "%s: unknown type %s\n",
214                  __PRETTY_FUNCTION__, type);
215       return 0;
216     }
217   }
218 }
219
220
221 /*
222   Return the alignment of an object specified by type 
223 */
224
225 int
226 objc_alignof_type(const char* type)
227 {
228   /* Skip the variable name if any */
229   if (*type == '"')
230     {
231       for (type++; *type++ != '"';)
232         /* do nothing */;
233     }
234   switch(*type) {
235   case _C_ID:
236     return __alignof__(id);
237     break;
238
239   case _C_CLASS:
240     return __alignof__(Class);
241     break;
242     
243   case _C_SEL:
244     return __alignof__(SEL);
245     break;
246
247   case _C_CHR:
248     return __alignof__(char);
249     break;
250     
251   case _C_UCHR:
252     return __alignof__(unsigned char);
253     break;
254
255   case _C_SHT:
256     return __alignof__(short);
257     break;
258
259   case _C_USHT:
260     return __alignof__(unsigned short);
261     break;
262
263   case _C_INT:
264     return __alignof__(int);
265     break;
266
267   case _C_UINT:
268     return __alignof__(unsigned int);
269     break;
270
271   case _C_LNG:
272     return __alignof__(long);
273     break;
274
275   case _C_ULNG:
276     return __alignof__(unsigned long);
277     break;
278
279   case _C_LNG_LNG:
280     return __alignof__(long long);
281     break;
282
283   case _C_ULNG_LNG:
284     return __alignof__(unsigned long long);
285     break;
286
287   case _C_FLT:
288     return __alignof__(float);
289     break;
290
291   case _C_DBL:
292     return __alignof__(double);
293     break;
294
295   case _C_PTR:
296   case _C_ATOM:
297   case _C_CHARPTR:
298     return __alignof__(char*);
299     break;
300
301   case _C_ARY_B:
302     while (isdigit((int)*++type)) /* do nothing */;
303     return objc_alignof_type (type);
304
305   case _C_STRUCT_B:
306     {
307       struct objc_struct_layout layout;
308       unsigned int align;
309
310       objc_layout_structure (type, &layout);
311       while (objc_layout_structure_next_member (&layout))
312         /* do nothing */;
313       objc_layout_finish_structure (&layout, NULL, &align);
314
315       return align;
316     }
317
318   case _C_UNION_B:
319     {
320       int maxalign = 0;
321       while (*type != _C_UNION_E && *type++ != '=') /* do nothing */;
322       while (*type != _C_UNION_E)
323         {
324           /* Skip the variable name if any */
325           if (*type == '"')
326             {
327               for (type++; *type++ != '"';)
328                 /* do nothing */;
329             }
330           maxalign = MAX (maxalign, objc_alignof_type (type));
331           type = objc_skip_typespec (type);
332         }
333       return maxalign;
334     }
335
336   default:
337     {
338       objc_error(nil, OBJC_ERR_BAD_TYPE, "%s: unknown type %s\n",
339                  __PRETTY_FUNCTION__, type);
340       return 0;
341     }
342   }
343 }
344
345 /*
346   The aligned size if the size rounded up to the nearest alignment.
347 */
348
349 int
350 objc_aligned_size (const char* type)
351 {
352   int size, align;
353
354   /* Skip the variable name */
355   if (*type == '"')
356     {
357       for (type++; *type++ != '"';)
358         /* do nothing */;
359     }
360
361   size = objc_sizeof_type (type);
362   align = objc_alignof_type (type);
363
364   return ROUND (size, align);
365 }
366
367 /*
368   The size rounded up to the nearest integral of the wordsize, taken
369   to be the size of a void*.
370 */
371
372 int 
373 objc_promoted_size (const char* type)
374 {
375   int size, wordsize;
376
377   /* Skip the variable name */
378   if (*type == '"')
379     {
380       for (type++; *type++ != '"';)
381         /* do nothing */;
382     }
383
384   size = objc_sizeof_type (type);
385   wordsize = sizeof (void*);
386
387   return ROUND (size, wordsize);
388 }
389
390 /*
391   Skip type qualifiers.  These may eventually precede typespecs
392   occurring in method prototype encodings.
393 */
394
395 __inline__ const char*
396 objc_skip_type_qualifiers (const char* type)
397 {
398   while (*type == _C_CONST
399          || *type == _C_IN 
400          || *type == _C_INOUT
401          || *type == _C_OUT 
402          || *type == _C_BYCOPY
403          || *type == _C_BYREF
404          || *type == _C_ONEWAY
405          || *type == _C_GCINVISIBLE)
406     {
407       type += 1;
408     }
409   return type;
410 }
411
412   
413 /*
414   Skip one typespec element.  If the typespec is prepended by type
415   qualifiers, these are skipped as well.
416 */
417
418 const char* 
419 objc_skip_typespec (const char* type)
420 {
421   /* Skip the variable name if any */
422   if (*type == '"')
423     {
424       for (type++; *type++ != '"';)
425         /* do nothing */;
426     }
427
428   type = objc_skip_type_qualifiers (type);
429   
430   switch (*type) {
431
432   case _C_ID:
433     /* An id may be annotated by the actual type if it is known
434        with the @"ClassName" syntax */
435
436     if (*++type != '"')
437       return type;
438     else
439       {
440         while (*++type != '"') /* do nothing */;
441         return type + 1;
442       }
443
444     /* The following are one character type codes */
445   case _C_CLASS:
446   case _C_SEL:
447   case _C_CHR:
448   case _C_UCHR:
449   case _C_CHARPTR:
450   case _C_ATOM:
451   case _C_SHT:
452   case _C_USHT:
453   case _C_INT:
454   case _C_UINT:
455   case _C_LNG:
456   case _C_ULNG:
457   case _C_LNG_LNG:
458   case _C_ULNG_LNG:
459   case _C_FLT:
460   case _C_DBL:
461   case _C_VOID:
462   case _C_UNDEF:
463     return ++type;
464     break;
465
466   case _C_ARY_B:
467     /* skip digits, typespec and closing ']' */
468     
469     while(isdigit((int)*++type));
470     type = objc_skip_typespec(type);
471     if (*type == _C_ARY_E)
472       return ++type;
473     else
474       {
475         objc_error(nil, OBJC_ERR_BAD_TYPE, "bad array type %s\n", type);
476         return 0;
477       }
478
479   case _C_BFLD:
480     /* The new encoding of bitfields is: b 'position' 'type' 'size' */
481     while (isdigit ((int)*++type));     /* skip position */
482     while (isdigit ((int)*++type));     /* skip type and size */
483     return type;
484
485   case _C_STRUCT_B:
486     /* skip name, and elements until closing '}'  */
487     
488     while (*type != _C_STRUCT_E && *type++ != '=');
489     while (*type != _C_STRUCT_E) { type = objc_skip_typespec (type); }
490     return ++type;
491
492   case _C_UNION_B:
493     /* skip name, and elements until closing ')'  */
494     
495     while (*type != _C_UNION_E && *type++ != '=');
496     while (*type != _C_UNION_E) { type = objc_skip_typespec (type); }
497     return ++type;
498
499   case _C_PTR:
500     /* Just skip the following typespec */
501     
502     return objc_skip_typespec (++type);
503     
504   default:
505     {
506       objc_error(nil, OBJC_ERR_BAD_TYPE, "%s: unknown type %s\n",
507                  __PRETTY_FUNCTION__, 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((int)*++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 objc_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 + objc_atoi (++t);
603   else
604     return argframe->arg_ptr + objc_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 + objc_atoi (++t);
646   else
647     return argframe->arg_ptr + objc_atoi (t);
648 }
649
650 unsigned objc_get_type_qualifiers (const char* type) {
651   unsigned res = 0;
652   BOOL flag = YES;
653
654   while (flag)
655     switch (*type++)
656       {
657       case _C_CONST:    res |= _F_CONST; break;
658       case _C_IN:       res |= _F_IN; break;
659       case _C_INOUT:    res |= _F_INOUT; break;
660       case _C_OUT:      res |= _F_OUT; break;
661       case _C_BYCOPY:   res |= _F_BYCOPY; break;
662       case _C_BYREF:  res |= _F_BYREF; break;
663       case _C_ONEWAY:   res |= _F_ONEWAY; break;
664       case _C_GCINVISIBLE: res |= _F_GCINVISIBLE; break;
665       default: flag = NO;
666     }
667
668   return res;
669 }
670
671
672 /* The following three functions can be used to determine how a
673    structure is laid out by the compiler. For example:
674
675   struct objc_struct_layout layout;
676   int i;
677
678   objc_layout_structure (type, &layout);
679   while (objc_layout_structure_next_member (&layout))
680     {
681       int position, align;
682       const char *type;
683
684       objc_layout_structure_get_info (&layout, &position, &align, &type);
685       printf ("element %d has offset %d, alignment %d\n",
686               i++, position, align);
687     }
688
689   These functions are used by objc_sizeof_type and objc_alignof_type
690   functions to compute the size and alignment of structures. The
691   previous method of computing the size and alignment of a structure
692   was not working on some architectures, particulary on AIX, and in
693   the presence of bitfields inside the structure. */
694 void
695 objc_layout_structure (const char *type,
696                            struct objc_struct_layout *layout)
697 {
698   const char *ntype;
699
700   if (*type++ != _C_STRUCT_B)
701     {
702       objc_error(nil, OBJC_ERR_BAD_TYPE,
703                  "record type expected in objc_layout_structure, got %s\n",
704                  type);
705     }
706
707   layout->original_type = type;
708
709   /* Skip "<name>=" if any. Avoid embedded structures and unions. */
710   ntype = type;
711   while (*ntype != _C_STRUCT_E && *ntype != _C_STRUCT_B && *ntype != _C_UNION_B
712          && *ntype++ != '=')
713     /* do nothing */;
714
715   /* If there's a "<name>=", ntype - 1 points to '='; skip the the name */
716   if (*(ntype - 1) == '=')
717     type = ntype;
718
719   layout->type = type;
720   layout->prev_type = NULL;
721   layout->record_size = 0;
722   layout->record_align = BITS_PER_UNIT;
723
724 #ifdef STRUCTURE_SIZE_BOUNDARY
725   layout->record_align = MAX (layout->record_align, STRUCTURE_SIZE_BOUNDARY);
726 #endif
727 }
728
729
730 BOOL
731 objc_layout_structure_next_member (struct objc_struct_layout *layout)
732 {
733   /* unused: register int known_align = layout->record_size; */
734   register int desired_align = 0;
735
736   /* The following are used only if the field is a bitfield */
737   register const char *bfld_type = NULL;
738   register int bfld_type_size  = 0;
739   register int bfld_type_align = 0;
740   register int bfld_field_size = 0;
741
742   /* The current type without the type qualifiers */
743   const char *type;
744
745 #if 1
746   if (layout->prev_type == NULL)
747     {
748       layout->prev_type = layout->type;
749       layout->type = objc_skip_typespec (layout->prev_type);
750       return YES;
751     }
752 #endif
753
754   /* Add the size of the previous field to the size of the record.  */
755   if (layout->prev_type)
756     {
757       type = objc_skip_type_qualifiers (layout->prev_type);
758
759       if (*type != _C_BFLD)
760         layout->record_size += objc_sizeof_type (type) * BITS_PER_UNIT;
761       else {
762         desired_align = 1;
763         /* Get the bitfield's type */
764         for (bfld_type = type + 1;
765              isdigit((int)*bfld_type);
766              bfld_type++)
767           /* do nothing */;
768
769         bfld_type_size = objc_sizeof_type (bfld_type) * BITS_PER_UNIT;
770         bfld_type_align = objc_alignof_type (bfld_type) * BITS_PER_UNIT;
771         bfld_field_size = objc_atoi (objc_skip_typespec (bfld_type));
772         layout->record_size += bfld_field_size;
773       }
774     }
775
776   if (*layout->type == _C_STRUCT_E)
777     return NO;
778
779   /* Skip the variable name if any */
780   if (*layout->type == '"')
781     {
782       for (layout->type++; *layout->type++ != '"';)
783         /* do nothing */;
784     }
785
786   type = objc_skip_type_qualifiers (layout->type);
787
788   if (*type != _C_BFLD)
789     desired_align = objc_alignof_type(type) * BITS_PER_UNIT;
790   else
791     {
792       desired_align = 1;
793       /* Skip the bitfield's offset */
794       for (bfld_type = type + 1; isdigit((int)*bfld_type); bfld_type++)
795         /* do nothing */;
796
797       bfld_type_size = objc_sizeof_type (bfld_type) * BITS_PER_UNIT;
798       bfld_type_align = objc_alignof_type (bfld_type) * BITS_PER_UNIT;
799       bfld_field_size = objc_atoi (objc_skip_typespec (bfld_type));
800     }
801
802 #ifdef BIGGEST_FIELD_ALIGNMENT
803   desired_align = MIN (desired_align, BIGGEST_FIELD_ALIGNMENT);
804 #endif
805 #ifdef ADJUST_FIELD_ALIGN
806   desired_align = ADJUST_FIELD_ALIGN (type, desired_align);
807 #endif
808
809   /* Record must have at least as much alignment as any field.
810      Otherwise, the alignment of the field within the record
811      is meaningless.  */
812 #ifndef PCC_BITFIELD_TYPE_MATTERS
813   layout->record_align = MAX (layout->record_align, desired_align);
814 #else
815   if (*type == _C_BFLD)
816     {
817       /* For these machines, a zero-length field does not
818          affect the alignment of the structure as a whole.
819          It does, however, affect the alignment of the next field
820          within the structure.  */
821       if (bfld_field_size)
822         layout->record_align = MAX (layout->record_align, desired_align);
823       else
824         desired_align = objc_alignof_type (bfld_type) * BITS_PER_UNIT;
825
826       /* A named bit field of declared type `int'
827          forces the entire structure to have `int' alignment.
828          Q1: How is encoded this thing and how to check for it?
829          Q2: How to determine maximum_field_alignment at runtime? */
830
831 /*        if (DECL_NAME (field) != 0) */
832       {
833         int type_align = bfld_type_align;
834 #if 0
835         if (maximum_field_alignment != 0)
836           type_align = MIN (type_align, maximum_field_alignment);
837         else if (DECL_PACKED (field))
838           type_align = MIN (type_align, BITS_PER_UNIT);
839 #endif
840
841         layout->record_align = MAX (layout->record_align, type_align);
842       }
843     }
844   else
845     layout->record_align = MAX (layout->record_align, desired_align);
846 #endif
847
848   /* Does this field automatically have alignment it needs
849      by virtue of the fields that precede it and the record's
850      own alignment?  */
851
852   if (*type == _C_BFLD)
853     layout->record_size = objc_atoi (type + 1);
854   else if (layout->record_size % desired_align != 0)
855     {
856       /* No, we need to skip space before this field.
857          Bump the cumulative size to multiple of field alignment.  */
858       layout->record_size = ROUND (layout->record_size, desired_align);
859     }
860   
861   /* Jump to the next field in record. */
862
863   layout->prev_type = layout->type;
864   layout->type = objc_skip_typespec (layout->type);      /* skip component */
865
866   return YES;
867 }
868
869
870 void objc_layout_finish_structure (struct objc_struct_layout *layout,
871                                    unsigned int *size,
872                                    unsigned int *align)
873 {
874   if (layout->type && *layout->type == _C_STRUCT_E)
875     {
876       /* Work out the alignment of the record as one expression and store
877          in the record type.  Round it up to a multiple of the record's
878          alignment. */
879
880 #ifdef ROUND_TYPE_ALIGN
881       layout->record_align = ROUND_TYPE_ALIGN (layout->original_type,
882                                                1,
883                                                layout->record_align);
884 #else
885       layout->record_align = MAX (1, layout->record_align);
886 #endif
887
888 #ifdef ROUND_TYPE_SIZE
889       layout->record_size = ROUND_TYPE_SIZE (layout->original_type,
890                                              layout->record_size,
891                                              layout->record_align);
892 #else
893       /* Round the size up to be a multiple of the required alignment */
894       layout->record_size = ROUND (layout->record_size, layout->record_align);
895 #endif
896
897       layout->type = NULL;
898     }
899   if (size)
900     *size = layout->record_size / BITS_PER_UNIT;
901   if (align)
902     *align = layout->record_align / BITS_PER_UNIT;
903 }
904
905
906 void objc_layout_structure_get_info (struct objc_struct_layout *layout,
907                                      unsigned int *offset,
908                                      unsigned int *align,
909                                      const char **type)
910 {
911   if (offset)
912     *offset = layout->record_size / BITS_PER_UNIT;
913   if (align)
914     *align = layout->record_align / BITS_PER_UNIT;
915   if (type)
916     *type = layout->prev_type;
917 }