OSDN Git Service

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