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