xref: /dflybsd-src/contrib/gcc-4.7/libobjc/encoding.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* Encoding of types for Objective C.
2*e4b17023SJohn Marino    Copyright (C) 1993, 1995, 1996, 1997, 1998, 2000, 2002, 2004, 2009, 2010
3*e4b17023SJohn Marino    Free Software Foundation, Inc.
4*e4b17023SJohn Marino    Contributed by Kresten Krab Thorup
5*e4b17023SJohn Marino    Bitfield support by Ovidiu Predescu
6*e4b17023SJohn Marino 
7*e4b17023SJohn Marino This file is part of GCC.
8*e4b17023SJohn Marino 
9*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify
10*e4b17023SJohn Marino it under the terms of the GNU General Public License as published by
11*e4b17023SJohn Marino the Free Software Foundation; either version 3, or (at your option)
12*e4b17023SJohn Marino any later version.
13*e4b17023SJohn Marino 
14*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful,
15*e4b17023SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
16*e4b17023SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17*e4b17023SJohn Marino GNU General Public License for more details.
18*e4b17023SJohn Marino 
19*e4b17023SJohn Marino Under Section 7 of GPL version 3, you are granted additional
20*e4b17023SJohn Marino permissions described in the GCC Runtime Library Exception, version
21*e4b17023SJohn Marino 3.1, as published by the Free Software Foundation.
22*e4b17023SJohn Marino 
23*e4b17023SJohn Marino You should have received a copy of the GNU General Public License and
24*e4b17023SJohn Marino a copy of the GCC Runtime Library Exception along with this program;
25*e4b17023SJohn Marino see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
26*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
27*e4b17023SJohn Marino 
28*e4b17023SJohn Marino /* FIXME: This file has no business including tm.h.  */
29*e4b17023SJohn Marino 
30*e4b17023SJohn Marino /* FIXME: This file contains functions that will abort the entire
31*e4b17023SJohn Marino    program if they fail.  Is that really needed ?  */
32*e4b17023SJohn Marino 
33*e4b17023SJohn Marino #include "objc-private/common.h"
34*e4b17023SJohn Marino #include "objc-private/error.h"
35*e4b17023SJohn Marino #include "tconfig.h"
36*e4b17023SJohn Marino #include "coretypes.h"
37*e4b17023SJohn Marino #include "tm.h"
38*e4b17023SJohn Marino #include "objc/runtime.h"
39*e4b17023SJohn Marino #include "objc-private/module-abi-8.h" /* For struct objc_method */
40*e4b17023SJohn Marino #include <stdlib.h>
41*e4b17023SJohn Marino #include <ctype.h>
42*e4b17023SJohn Marino #include <string.h>                    /* For memcpy.  */
43*e4b17023SJohn Marino 
44*e4b17023SJohn Marino #undef  MAX
45*e4b17023SJohn Marino #define MAX(X, Y)                    \
46*e4b17023SJohn Marino   ({ typeof (X) __x = (X), __y = (Y); \
47*e4b17023SJohn Marino      (__x > __y ? __x : __y); })
48*e4b17023SJohn Marino 
49*e4b17023SJohn Marino #undef  MIN
50*e4b17023SJohn Marino #define MIN(X, Y)                    \
51*e4b17023SJohn Marino   ({ typeof (X) __x = (X), __y = (Y); \
52*e4b17023SJohn Marino      (__x < __y ? __x : __y); })
53*e4b17023SJohn Marino 
54*e4b17023SJohn Marino #undef  ROUND
55*e4b17023SJohn Marino #define ROUND(V, A) \
56*e4b17023SJohn Marino   ({ typeof (V) __v = (V); typeof (A) __a = (A); \
57*e4b17023SJohn Marino      __a * ((__v+__a - 1)/__a); })
58*e4b17023SJohn Marino 
59*e4b17023SJohn Marino 
60*e4b17023SJohn Marino /* Various hacks for objc_layout_record. These are used by the target
61*e4b17023SJohn Marino    macros. */
62*e4b17023SJohn Marino 
63*e4b17023SJohn Marino #define TREE_CODE(TYPE) *(TYPE)
64*e4b17023SJohn Marino #define TREE_TYPE(TREE) (TREE)
65*e4b17023SJohn Marino 
66*e4b17023SJohn Marino #define RECORD_TYPE     _C_STRUCT_B
67*e4b17023SJohn Marino #define UNION_TYPE      _C_UNION_B
68*e4b17023SJohn Marino #define QUAL_UNION_TYPE _C_UNION_B
69*e4b17023SJohn Marino #define ARRAY_TYPE      _C_ARY_B
70*e4b17023SJohn Marino 
71*e4b17023SJohn Marino #define REAL_TYPE       _C_DBL
72*e4b17023SJohn Marino 
73*e4b17023SJohn Marino #define VECTOR_TYPE	_C_VECTOR
74*e4b17023SJohn Marino 
75*e4b17023SJohn Marino #define TYPE_FIELDS(TYPE)           ({const char *_field = (TYPE)+1; \
76*e4b17023SJohn Marino     while (*_field != _C_STRUCT_E && *_field != _C_STRUCT_B \
77*e4b17023SJohn Marino            && *_field != _C_UNION_B && *_field++ != '=') \
78*e4b17023SJohn Marino     /* do nothing */; \
79*e4b17023SJohn Marino     _field;})
80*e4b17023SJohn Marino 
81*e4b17023SJohn Marino #define DECL_MODE(TYPE) *(TYPE)
82*e4b17023SJohn Marino #define TYPE_MODE(TYPE) *(TYPE)
83*e4b17023SJohn Marino 
84*e4b17023SJohn Marino #define DFmode          _C_DBL
85*e4b17023SJohn Marino 
86*e4b17023SJohn Marino #define strip_array_types(TYPE)      ({const char *_field = (TYPE); \
87*e4b17023SJohn Marino   while (*_field == _C_ARY_B)\
88*e4b17023SJohn Marino     {\
89*e4b17023SJohn Marino       while (isdigit ((unsigned char)*++_field))\
90*e4b17023SJohn Marino 	;\
91*e4b17023SJohn Marino     }\
92*e4b17023SJohn Marino     _field;})
93*e4b17023SJohn Marino 
94*e4b17023SJohn Marino /* Some ports (eg ARM) allow the structure size boundary to be
95*e4b17023SJohn Marino    selected at compile-time.  We override the normal definition with
96*e4b17023SJohn Marino    one that has a constant value for this compilation.  */
97*e4b17023SJohn Marino #ifndef BITS_PER_UNIT
98*e4b17023SJohn Marino #define BITS_PER_UNIT 8
99*e4b17023SJohn Marino #endif
100*e4b17023SJohn Marino #undef  STRUCTURE_SIZE_BOUNDARY
101*e4b17023SJohn Marino #define STRUCTURE_SIZE_BOUNDARY (BITS_PER_UNIT * sizeof (struct{char a;}))
102*e4b17023SJohn Marino 
103*e4b17023SJohn Marino /* Some ROUND_TYPE_ALIGN macros use TARGET_foo, and consequently
104*e4b17023SJohn Marino    target_flags.  Define a dummy entry here to so we don't die.
105*e4b17023SJohn Marino    We have to rename it because target_flags may already have been
106*e4b17023SJohn Marino    declared extern.  */
107*e4b17023SJohn Marino #define target_flags not_target_flags
108*e4b17023SJohn Marino static int __attribute__ ((__unused__)) not_target_flags = 0;
109*e4b17023SJohn Marino 
110*e4b17023SJohn Marino /* Some ROUND_TYPE_ALIGN use ALTIVEC_VECTOR_MODE (rs6000 darwin).
111*e4b17023SJohn Marino    Define a dummy ALTIVEC_VECTOR_MODE so it will not die.  */
112*e4b17023SJohn Marino #undef ALTIVEC_VECTOR_MODE
113*e4b17023SJohn Marino #define ALTIVEC_VECTOR_MODE(MODE) (0)
114*e4b17023SJohn Marino 
115*e4b17023SJohn Marino /* Furthermore, some (powerpc) targets also use TARGET_ALIGN_NATURAL
116*e4b17023SJohn Marino  in their alignment macros. Currently[4.5/6], rs6000.h points this
117*e4b17023SJohn Marino  to a static variable, initialized by target overrides. This is reset
118*e4b17023SJohn Marino  in linux64.h but not in darwin64.h.  The macro is not used by *86*.  */
119*e4b17023SJohn Marino 
120*e4b17023SJohn Marino #if __MACH__
121*e4b17023SJohn Marino # if __LP64__
122*e4b17023SJohn Marino #  undef TARGET_ALIGN_NATURAL
123*e4b17023SJohn Marino #  define TARGET_ALIGN_NATURAL 1
124*e4b17023SJohn Marino # endif
125*e4b17023SJohn Marino 
126*e4b17023SJohn Marino /* On Darwin32, we need to recurse until we find the starting stuct type.  */
127*e4b17023SJohn Marino static int
_darwin_rs6000_special_round_type_align(const char * struc,int comp,int spec)128*e4b17023SJohn Marino _darwin_rs6000_special_round_type_align (const char *struc, int comp, int spec)
129*e4b17023SJohn Marino {
130*e4b17023SJohn Marino   const char *_stp , *_fields = TYPE_FIELDS (struc);
131*e4b17023SJohn Marino   if (!_fields)
132*e4b17023SJohn Marino     return MAX (comp, spec);
133*e4b17023SJohn Marino   _stp = strip_array_types (_fields);
134*e4b17023SJohn Marino   if (TYPE_MODE(_stp) == _C_COMPLEX)
135*e4b17023SJohn Marino    _stp++;
136*e4b17023SJohn Marino   switch (TYPE_MODE(_stp))
137*e4b17023SJohn Marino     {
138*e4b17023SJohn Marino       case RECORD_TYPE:
139*e4b17023SJohn Marino       case UNION_TYPE:
140*e4b17023SJohn Marino 	return MAX (MAX (comp, spec), objc_alignof_type (_stp) * BITS_PER_UNIT);
141*e4b17023SJohn Marino 	break;
142*e4b17023SJohn Marino       case DFmode:
143*e4b17023SJohn Marino       case _C_LNG_LNG:
144*e4b17023SJohn Marino       case _C_ULNG_LNG:
145*e4b17023SJohn Marino 	return MAX (MAX (comp, spec), 64);
146*e4b17023SJohn Marino 	break;
147*e4b17023SJohn Marino 
148*e4b17023SJohn Marino       default:
149*e4b17023SJohn Marino 	return MAX (comp, spec);
150*e4b17023SJohn Marino 	break;
151*e4b17023SJohn Marino     }
152*e4b17023SJohn Marino }
153*e4b17023SJohn Marino 
154*e4b17023SJohn Marino /* See comment below.  */
155*e4b17023SJohn Marino #define darwin_rs6000_special_round_type_align(S,C,S2)			\
156*e4b17023SJohn Marino   (_darwin_rs6000_special_round_type_align ((char*)(S), (int)(C), (int)(S2)))
157*e4b17023SJohn Marino #endif
158*e4b17023SJohn Marino 
159*e4b17023SJohn Marino /*  FIXME: while this file has no business including tm.h, this
160*e4b17023SJohn Marino     definitely has no business defining this macro but it
161*e4b17023SJohn Marino     is only way around without really rewritting this file,
162*e4b17023SJohn Marino     should look after the branch of 3.4 to fix this.   */
163*e4b17023SJohn Marino #define rs6000_special_round_type_align(STRUCT, COMPUTED, SPECIFIED)	\
164*e4b17023SJohn Marino   ({ const char *_fields = TYPE_FIELDS (STRUCT);			\
165*e4b17023SJohn Marino   ((_fields != 0							\
166*e4b17023SJohn Marino     && TYPE_MODE (strip_array_types (TREE_TYPE (_fields))) == DFmode)	\
167*e4b17023SJohn Marino    ? MAX (MAX (COMPUTED, SPECIFIED), 64)				\
168*e4b17023SJohn Marino    : MAX (COMPUTED, SPECIFIED));})
169*e4b17023SJohn Marino 
170*e4b17023SJohn Marino 
171*e4b17023SJohn Marino /* Skip a variable name, enclosed in quotes (").  */
172*e4b17023SJohn Marino static inline
173*e4b17023SJohn Marino const char *
objc_skip_variable_name(const char * type)174*e4b17023SJohn Marino objc_skip_variable_name (const char *type)
175*e4b17023SJohn Marino {
176*e4b17023SJohn Marino   /* Skip the variable name if any.  */
177*e4b17023SJohn Marino   if (*type == '"')
178*e4b17023SJohn Marino     {
179*e4b17023SJohn Marino       /* FIXME: How do we know we won't read beyond the end of the
180*e4b17023SJohn Marino 	 string.  Here and in the rest of the file!  */
181*e4b17023SJohn Marino       /* Skip '"'.  */
182*e4b17023SJohn Marino       type++;
183*e4b17023SJohn Marino       /* Skip to the next '"'.  */
184*e4b17023SJohn Marino       while (*type != '"')
185*e4b17023SJohn Marino 	type++;
186*e4b17023SJohn Marino       /* Skip '"'.  */
187*e4b17023SJohn Marino       type++;
188*e4b17023SJohn Marino     }
189*e4b17023SJohn Marino 
190*e4b17023SJohn Marino   return type;
191*e4b17023SJohn Marino }
192*e4b17023SJohn Marino 
193*e4b17023SJohn Marino int
objc_sizeof_type(const char * type)194*e4b17023SJohn Marino objc_sizeof_type (const char *type)
195*e4b17023SJohn Marino {
196*e4b17023SJohn Marino   type = objc_skip_variable_name (type);
197*e4b17023SJohn Marino 
198*e4b17023SJohn Marino   switch (*type) {
199*e4b17023SJohn Marino   case _C_BOOL:
200*e4b17023SJohn Marino     return sizeof (_Bool);
201*e4b17023SJohn Marino     break;
202*e4b17023SJohn Marino 
203*e4b17023SJohn Marino   case _C_ID:
204*e4b17023SJohn Marino     return sizeof (id);
205*e4b17023SJohn Marino     break;
206*e4b17023SJohn Marino 
207*e4b17023SJohn Marino   case _C_CLASS:
208*e4b17023SJohn Marino     return sizeof (Class);
209*e4b17023SJohn Marino     break;
210*e4b17023SJohn Marino 
211*e4b17023SJohn Marino   case _C_SEL:
212*e4b17023SJohn Marino     return sizeof (SEL);
213*e4b17023SJohn Marino     break;
214*e4b17023SJohn Marino 
215*e4b17023SJohn Marino   case _C_CHR:
216*e4b17023SJohn Marino     return sizeof (char);
217*e4b17023SJohn Marino     break;
218*e4b17023SJohn Marino 
219*e4b17023SJohn Marino   case _C_UCHR:
220*e4b17023SJohn Marino     return sizeof (unsigned char);
221*e4b17023SJohn Marino     break;
222*e4b17023SJohn Marino 
223*e4b17023SJohn Marino   case _C_SHT:
224*e4b17023SJohn Marino     return sizeof (short);
225*e4b17023SJohn Marino     break;
226*e4b17023SJohn Marino 
227*e4b17023SJohn Marino   case _C_USHT:
228*e4b17023SJohn Marino     return sizeof (unsigned short);
229*e4b17023SJohn Marino     break;
230*e4b17023SJohn Marino 
231*e4b17023SJohn Marino   case _C_INT:
232*e4b17023SJohn Marino     return sizeof (int);
233*e4b17023SJohn Marino     break;
234*e4b17023SJohn Marino 
235*e4b17023SJohn Marino   case _C_UINT:
236*e4b17023SJohn Marino     return sizeof (unsigned int);
237*e4b17023SJohn Marino     break;
238*e4b17023SJohn Marino 
239*e4b17023SJohn Marino   case _C_LNG:
240*e4b17023SJohn Marino     return sizeof (long);
241*e4b17023SJohn Marino     break;
242*e4b17023SJohn Marino 
243*e4b17023SJohn Marino   case _C_ULNG:
244*e4b17023SJohn Marino     return sizeof (unsigned long);
245*e4b17023SJohn Marino     break;
246*e4b17023SJohn Marino 
247*e4b17023SJohn Marino   case _C_LNG_LNG:
248*e4b17023SJohn Marino     return sizeof (long long);
249*e4b17023SJohn Marino     break;
250*e4b17023SJohn Marino 
251*e4b17023SJohn Marino   case _C_ULNG_LNG:
252*e4b17023SJohn Marino     return sizeof (unsigned long long);
253*e4b17023SJohn Marino     break;
254*e4b17023SJohn Marino 
255*e4b17023SJohn Marino   case _C_FLT:
256*e4b17023SJohn Marino     return sizeof (float);
257*e4b17023SJohn Marino     break;
258*e4b17023SJohn Marino 
259*e4b17023SJohn Marino   case _C_DBL:
260*e4b17023SJohn Marino     return sizeof (double);
261*e4b17023SJohn Marino     break;
262*e4b17023SJohn Marino 
263*e4b17023SJohn Marino   case _C_LNG_DBL:
264*e4b17023SJohn Marino     return sizeof (long double);
265*e4b17023SJohn Marino     break;
266*e4b17023SJohn Marino 
267*e4b17023SJohn Marino   case _C_VOID:
268*e4b17023SJohn Marino     return sizeof (void);
269*e4b17023SJohn Marino     break;
270*e4b17023SJohn Marino 
271*e4b17023SJohn Marino   case _C_PTR:
272*e4b17023SJohn Marino   case _C_ATOM:
273*e4b17023SJohn Marino   case _C_CHARPTR:
274*e4b17023SJohn Marino     return sizeof (char *);
275*e4b17023SJohn Marino     break;
276*e4b17023SJohn Marino 
277*e4b17023SJohn Marino   case _C_ARY_B:
278*e4b17023SJohn Marino     {
279*e4b17023SJohn Marino       int len = atoi (type + 1);
280*e4b17023SJohn Marino       while (isdigit ((unsigned char)*++type))
281*e4b17023SJohn Marino 	;
282*e4b17023SJohn Marino       return len * objc_aligned_size (type);
283*e4b17023SJohn Marino     }
284*e4b17023SJohn Marino     break;
285*e4b17023SJohn Marino 
286*e4b17023SJohn Marino   case _C_VECTOR:
287*e4b17023SJohn Marino     {
288*e4b17023SJohn Marino       /* Skip the '!'.  */
289*e4b17023SJohn Marino       type++;
290*e4b17023SJohn Marino       /* Skip the '['.  */
291*e4b17023SJohn Marino       type++;
292*e4b17023SJohn Marino 
293*e4b17023SJohn Marino       /* The size in bytes is the following number.  */
294*e4b17023SJohn Marino       int size = atoi (type);
295*e4b17023SJohn Marino       return size;
296*e4b17023SJohn Marino     }
297*e4b17023SJohn Marino     break;
298*e4b17023SJohn Marino 
299*e4b17023SJohn Marino   case _C_BFLD:
300*e4b17023SJohn Marino     {
301*e4b17023SJohn Marino       /* The GNU encoding of bitfields is: b 'position' 'type'
302*e4b17023SJohn Marino 	 'size'.  */
303*e4b17023SJohn Marino       int position, size;
304*e4b17023SJohn Marino       int startByte, endByte;
305*e4b17023SJohn Marino 
306*e4b17023SJohn Marino       position = atoi (type + 1);
307*e4b17023SJohn Marino       while (isdigit ((unsigned char)*++type))
308*e4b17023SJohn Marino 	;
309*e4b17023SJohn Marino       size = atoi (type + 1);
310*e4b17023SJohn Marino 
311*e4b17023SJohn Marino       startByte = position / BITS_PER_UNIT;
312*e4b17023SJohn Marino       endByte = (position + size) / BITS_PER_UNIT;
313*e4b17023SJohn Marino       return endByte - startByte;
314*e4b17023SJohn Marino     }
315*e4b17023SJohn Marino 
316*e4b17023SJohn Marino   case _C_UNION_B:
317*e4b17023SJohn Marino   case _C_STRUCT_B:
318*e4b17023SJohn Marino     {
319*e4b17023SJohn Marino       struct objc_struct_layout layout;
320*e4b17023SJohn Marino       unsigned int size;
321*e4b17023SJohn Marino 
322*e4b17023SJohn Marino       objc_layout_structure (type, &layout);
323*e4b17023SJohn Marino       while (objc_layout_structure_next_member (&layout))
324*e4b17023SJohn Marino         /* do nothing */ ;
325*e4b17023SJohn Marino       objc_layout_finish_structure (&layout, &size, NULL);
326*e4b17023SJohn Marino 
327*e4b17023SJohn Marino       return size;
328*e4b17023SJohn Marino     }
329*e4b17023SJohn Marino 
330*e4b17023SJohn Marino   case _C_COMPLEX:
331*e4b17023SJohn Marino     {
332*e4b17023SJohn Marino       type++; /* Skip after the 'j'. */
333*e4b17023SJohn Marino       switch (*type)
334*e4b17023SJohn Marino         {
335*e4b17023SJohn Marino 	    case _C_CHR:
336*e4b17023SJohn Marino 	      return sizeof (_Complex char);
337*e4b17023SJohn Marino 	      break;
338*e4b17023SJohn Marino 
339*e4b17023SJohn Marino 	    case _C_UCHR:
340*e4b17023SJohn Marino 	      return sizeof (_Complex unsigned char);
341*e4b17023SJohn Marino 	      break;
342*e4b17023SJohn Marino 
343*e4b17023SJohn Marino 	    case _C_SHT:
344*e4b17023SJohn Marino 	      return sizeof (_Complex short);
345*e4b17023SJohn Marino 	      break;
346*e4b17023SJohn Marino 
347*e4b17023SJohn Marino 	    case _C_USHT:
348*e4b17023SJohn Marino 	      return sizeof (_Complex unsigned short);
349*e4b17023SJohn Marino 	      break;
350*e4b17023SJohn Marino 
351*e4b17023SJohn Marino 	    case _C_INT:
352*e4b17023SJohn Marino 	      return sizeof (_Complex int);
353*e4b17023SJohn Marino 	      break;
354*e4b17023SJohn Marino 
355*e4b17023SJohn Marino 	    case _C_UINT:
356*e4b17023SJohn Marino 	      return sizeof (_Complex unsigned int);
357*e4b17023SJohn Marino 	      break;
358*e4b17023SJohn Marino 
359*e4b17023SJohn Marino 	    case _C_LNG:
360*e4b17023SJohn Marino 	      return sizeof (_Complex long);
361*e4b17023SJohn Marino 	      break;
362*e4b17023SJohn Marino 
363*e4b17023SJohn Marino 	    case _C_ULNG:
364*e4b17023SJohn Marino 	      return sizeof (_Complex unsigned long);
365*e4b17023SJohn Marino 	      break;
366*e4b17023SJohn Marino 
367*e4b17023SJohn Marino 	    case _C_LNG_LNG:
368*e4b17023SJohn Marino 	      return sizeof (_Complex long long);
369*e4b17023SJohn Marino 	      break;
370*e4b17023SJohn Marino 
371*e4b17023SJohn Marino 	    case _C_ULNG_LNG:
372*e4b17023SJohn Marino 	      return sizeof (_Complex unsigned long long);
373*e4b17023SJohn Marino 	      break;
374*e4b17023SJohn Marino 
375*e4b17023SJohn Marino 	    case _C_FLT:
376*e4b17023SJohn Marino 	      return sizeof (_Complex float);
377*e4b17023SJohn Marino 	      break;
378*e4b17023SJohn Marino 
379*e4b17023SJohn Marino 	    case _C_DBL:
380*e4b17023SJohn Marino 	      return sizeof (_Complex double);
381*e4b17023SJohn Marino 	      break;
382*e4b17023SJohn Marino 
383*e4b17023SJohn Marino 	    case _C_LNG_DBL:
384*e4b17023SJohn Marino 	      return sizeof (_Complex long double);
385*e4b17023SJohn Marino 	      break;
386*e4b17023SJohn Marino 
387*e4b17023SJohn Marino 	    default:
388*e4b17023SJohn Marino 	      {
389*e4b17023SJohn Marino 		/* FIXME: Is this so bad that we have to abort the
390*e4b17023SJohn Marino 		   entire program ?  (it applies to all the other
391*e4b17023SJohn Marino 		   _objc_abort calls in this file).
392*e4b17023SJohn Marino 		*/
393*e4b17023SJohn Marino 		_objc_abort ("unknown complex type %s\n", type);
394*e4b17023SJohn Marino 		return 0;
395*e4b17023SJohn Marino 	      }
396*e4b17023SJohn Marino 	}
397*e4b17023SJohn Marino     }
398*e4b17023SJohn Marino 
399*e4b17023SJohn Marino   default:
400*e4b17023SJohn Marino     {
401*e4b17023SJohn Marino       _objc_abort ("unknown type %s\n", type);
402*e4b17023SJohn Marino       return 0;
403*e4b17023SJohn Marino     }
404*e4b17023SJohn Marino   }
405*e4b17023SJohn Marino }
406*e4b17023SJohn Marino 
407*e4b17023SJohn Marino int
objc_alignof_type(const char * type)408*e4b17023SJohn Marino objc_alignof_type (const char *type)
409*e4b17023SJohn Marino {
410*e4b17023SJohn Marino   type = objc_skip_variable_name (type);
411*e4b17023SJohn Marino 
412*e4b17023SJohn Marino   switch (*type) {
413*e4b17023SJohn Marino   case _C_BOOL:
414*e4b17023SJohn Marino     return __alignof__ (_Bool);
415*e4b17023SJohn Marino     break;
416*e4b17023SJohn Marino 
417*e4b17023SJohn Marino   case _C_ID:
418*e4b17023SJohn Marino     return __alignof__ (id);
419*e4b17023SJohn Marino     break;
420*e4b17023SJohn Marino 
421*e4b17023SJohn Marino   case _C_CLASS:
422*e4b17023SJohn Marino     return __alignof__ (Class);
423*e4b17023SJohn Marino     break;
424*e4b17023SJohn Marino 
425*e4b17023SJohn Marino   case _C_SEL:
426*e4b17023SJohn Marino     return __alignof__ (SEL);
427*e4b17023SJohn Marino     break;
428*e4b17023SJohn Marino 
429*e4b17023SJohn Marino   case _C_CHR:
430*e4b17023SJohn Marino     return __alignof__ (char);
431*e4b17023SJohn Marino     break;
432*e4b17023SJohn Marino 
433*e4b17023SJohn Marino   case _C_UCHR:
434*e4b17023SJohn Marino     return __alignof__ (unsigned char);
435*e4b17023SJohn Marino     break;
436*e4b17023SJohn Marino 
437*e4b17023SJohn Marino   case _C_SHT:
438*e4b17023SJohn Marino     return __alignof__ (short);
439*e4b17023SJohn Marino     break;
440*e4b17023SJohn Marino 
441*e4b17023SJohn Marino   case _C_USHT:
442*e4b17023SJohn Marino     return __alignof__ (unsigned short);
443*e4b17023SJohn Marino     break;
444*e4b17023SJohn Marino 
445*e4b17023SJohn Marino   case _C_INT:
446*e4b17023SJohn Marino     return __alignof__ (int);
447*e4b17023SJohn Marino     break;
448*e4b17023SJohn Marino 
449*e4b17023SJohn Marino   case _C_UINT:
450*e4b17023SJohn Marino     return __alignof__ (unsigned int);
451*e4b17023SJohn Marino     break;
452*e4b17023SJohn Marino 
453*e4b17023SJohn Marino   case _C_LNG:
454*e4b17023SJohn Marino     return __alignof__ (long);
455*e4b17023SJohn Marino     break;
456*e4b17023SJohn Marino 
457*e4b17023SJohn Marino   case _C_ULNG:
458*e4b17023SJohn Marino     return __alignof__ (unsigned long);
459*e4b17023SJohn Marino     break;
460*e4b17023SJohn Marino 
461*e4b17023SJohn Marino   case _C_LNG_LNG:
462*e4b17023SJohn Marino     return __alignof__ (long long);
463*e4b17023SJohn Marino     break;
464*e4b17023SJohn Marino 
465*e4b17023SJohn Marino   case _C_ULNG_LNG:
466*e4b17023SJohn Marino     return __alignof__ (unsigned long long);
467*e4b17023SJohn Marino     break;
468*e4b17023SJohn Marino 
469*e4b17023SJohn Marino   case _C_FLT:
470*e4b17023SJohn Marino     return __alignof__ (float);
471*e4b17023SJohn Marino     break;
472*e4b17023SJohn Marino 
473*e4b17023SJohn Marino   case _C_DBL:
474*e4b17023SJohn Marino     return __alignof__ (double);
475*e4b17023SJohn Marino     break;
476*e4b17023SJohn Marino 
477*e4b17023SJohn Marino   case _C_LNG_DBL:
478*e4b17023SJohn Marino     return __alignof__ (long double);
479*e4b17023SJohn Marino     break;
480*e4b17023SJohn Marino 
481*e4b17023SJohn Marino   case _C_PTR:
482*e4b17023SJohn Marino   case _C_ATOM:
483*e4b17023SJohn Marino   case _C_CHARPTR:
484*e4b17023SJohn Marino     return __alignof__ (char *);
485*e4b17023SJohn Marino     break;
486*e4b17023SJohn Marino 
487*e4b17023SJohn Marino   case _C_ARY_B:
488*e4b17023SJohn Marino     while (isdigit ((unsigned char)*++type))
489*e4b17023SJohn Marino       /* do nothing */;
490*e4b17023SJohn Marino     return objc_alignof_type (type);
491*e4b17023SJohn Marino 
492*e4b17023SJohn Marino   case _C_VECTOR:
493*e4b17023SJohn Marino     {
494*e4b17023SJohn Marino       /* Skip the '!'.  */
495*e4b17023SJohn Marino       type++;
496*e4b17023SJohn Marino       /* Skip the '['.  */
497*e4b17023SJohn Marino       type++;
498*e4b17023SJohn Marino 
499*e4b17023SJohn Marino       /* Skip the size.  */
500*e4b17023SJohn Marino       while (isdigit ((unsigned char)*type))
501*e4b17023SJohn Marino 	type++;
502*e4b17023SJohn Marino 
503*e4b17023SJohn Marino       /* Skip the ','.  */
504*e4b17023SJohn Marino       type++;
505*e4b17023SJohn Marino 
506*e4b17023SJohn Marino       /* The alignment in bytes is the following number.  */
507*e4b17023SJohn Marino       return atoi (type);
508*e4b17023SJohn Marino     }
509*e4b17023SJohn Marino   case _C_STRUCT_B:
510*e4b17023SJohn Marino   case _C_UNION_B:
511*e4b17023SJohn Marino     {
512*e4b17023SJohn Marino       struct objc_struct_layout layout;
513*e4b17023SJohn Marino       unsigned int align;
514*e4b17023SJohn Marino 
515*e4b17023SJohn Marino       objc_layout_structure (type, &layout);
516*e4b17023SJohn Marino       while (objc_layout_structure_next_member (&layout))
517*e4b17023SJohn Marino         /* do nothing */;
518*e4b17023SJohn Marino       objc_layout_finish_structure (&layout, NULL, &align);
519*e4b17023SJohn Marino 
520*e4b17023SJohn Marino       return align;
521*e4b17023SJohn Marino     }
522*e4b17023SJohn Marino 
523*e4b17023SJohn Marino 
524*e4b17023SJohn Marino   case _C_COMPLEX:
525*e4b17023SJohn Marino     {
526*e4b17023SJohn Marino       type++; /* Skip after the 'j'. */
527*e4b17023SJohn Marino       switch (*type)
528*e4b17023SJohn Marino         {
529*e4b17023SJohn Marino 	    case _C_CHR:
530*e4b17023SJohn Marino 	      return __alignof__ (_Complex char);
531*e4b17023SJohn Marino 	      break;
532*e4b17023SJohn Marino 
533*e4b17023SJohn Marino 	    case _C_UCHR:
534*e4b17023SJohn Marino 	      return __alignof__ (_Complex unsigned char);
535*e4b17023SJohn Marino 	      break;
536*e4b17023SJohn Marino 
537*e4b17023SJohn Marino 	    case _C_SHT:
538*e4b17023SJohn Marino 	      return __alignof__ (_Complex short);
539*e4b17023SJohn Marino 	      break;
540*e4b17023SJohn Marino 
541*e4b17023SJohn Marino 	    case _C_USHT:
542*e4b17023SJohn Marino 	      return __alignof__ (_Complex unsigned short);
543*e4b17023SJohn Marino 	      break;
544*e4b17023SJohn Marino 
545*e4b17023SJohn Marino 	    case _C_INT:
546*e4b17023SJohn Marino 	      return __alignof__ (_Complex int);
547*e4b17023SJohn Marino 	      break;
548*e4b17023SJohn Marino 
549*e4b17023SJohn Marino 	    case _C_UINT:
550*e4b17023SJohn Marino 	      return __alignof__ (_Complex unsigned int);
551*e4b17023SJohn Marino 	      break;
552*e4b17023SJohn Marino 
553*e4b17023SJohn Marino 	    case _C_LNG:
554*e4b17023SJohn Marino 	      return __alignof__ (_Complex long);
555*e4b17023SJohn Marino 	      break;
556*e4b17023SJohn Marino 
557*e4b17023SJohn Marino 	    case _C_ULNG:
558*e4b17023SJohn Marino 	      return __alignof__ (_Complex unsigned long);
559*e4b17023SJohn Marino 	      break;
560*e4b17023SJohn Marino 
561*e4b17023SJohn Marino 	    case _C_LNG_LNG:
562*e4b17023SJohn Marino 	      return __alignof__ (_Complex long long);
563*e4b17023SJohn Marino 	      break;
564*e4b17023SJohn Marino 
565*e4b17023SJohn Marino 	    case _C_ULNG_LNG:
566*e4b17023SJohn Marino 	      return __alignof__ (_Complex unsigned long long);
567*e4b17023SJohn Marino 	      break;
568*e4b17023SJohn Marino 
569*e4b17023SJohn Marino 	    case _C_FLT:
570*e4b17023SJohn Marino 	      return __alignof__ (_Complex float);
571*e4b17023SJohn Marino 	      break;
572*e4b17023SJohn Marino 
573*e4b17023SJohn Marino 	    case _C_DBL:
574*e4b17023SJohn Marino 	      return __alignof__ (_Complex double);
575*e4b17023SJohn Marino 	      break;
576*e4b17023SJohn Marino 
577*e4b17023SJohn Marino 	    case _C_LNG_DBL:
578*e4b17023SJohn Marino 	      return __alignof__ (_Complex long double);
579*e4b17023SJohn Marino 	      break;
580*e4b17023SJohn Marino 
581*e4b17023SJohn Marino 	    default:
582*e4b17023SJohn Marino 	      {
583*e4b17023SJohn Marino 		_objc_abort ("unknown complex type %s\n", type);
584*e4b17023SJohn Marino 		return 0;
585*e4b17023SJohn Marino 	      }
586*e4b17023SJohn Marino 	}
587*e4b17023SJohn Marino     }
588*e4b17023SJohn Marino 
589*e4b17023SJohn Marino   default:
590*e4b17023SJohn Marino     {
591*e4b17023SJohn Marino       _objc_abort ("unknown type %s\n", type);
592*e4b17023SJohn Marino       return 0;
593*e4b17023SJohn Marino     }
594*e4b17023SJohn Marino   }
595*e4b17023SJohn Marino }
596*e4b17023SJohn Marino 
597*e4b17023SJohn Marino int
objc_aligned_size(const char * type)598*e4b17023SJohn Marino objc_aligned_size (const char *type)
599*e4b17023SJohn Marino {
600*e4b17023SJohn Marino   int size, align;
601*e4b17023SJohn Marino 
602*e4b17023SJohn Marino   type = objc_skip_variable_name (type);
603*e4b17023SJohn Marino   size = objc_sizeof_type (type);
604*e4b17023SJohn Marino   align = objc_alignof_type (type);
605*e4b17023SJohn Marino 
606*e4b17023SJohn Marino   return ROUND (size, align);
607*e4b17023SJohn Marino }
608*e4b17023SJohn Marino 
609*e4b17023SJohn Marino int
objc_promoted_size(const char * type)610*e4b17023SJohn Marino objc_promoted_size (const char *type)
611*e4b17023SJohn Marino {
612*e4b17023SJohn Marino   int size, wordsize;
613*e4b17023SJohn Marino 
614*e4b17023SJohn Marino   type = objc_skip_variable_name (type);
615*e4b17023SJohn Marino   size = objc_sizeof_type (type);
616*e4b17023SJohn Marino   wordsize = sizeof (void *);
617*e4b17023SJohn Marino 
618*e4b17023SJohn Marino   return ROUND (size, wordsize);
619*e4b17023SJohn Marino }
620*e4b17023SJohn Marino 
621*e4b17023SJohn Marino inline
622*e4b17023SJohn Marino const char *
objc_skip_type_qualifiers(const char * type)623*e4b17023SJohn Marino objc_skip_type_qualifiers (const char *type)
624*e4b17023SJohn Marino {
625*e4b17023SJohn Marino   while (*type == _C_CONST
626*e4b17023SJohn Marino 	 || *type == _C_IN
627*e4b17023SJohn Marino 	 || *type == _C_INOUT
628*e4b17023SJohn Marino 	 || *type == _C_OUT
629*e4b17023SJohn Marino 	 || *type == _C_BYCOPY
630*e4b17023SJohn Marino          || *type == _C_BYREF
631*e4b17023SJohn Marino 	 || *type == _C_ONEWAY
632*e4b17023SJohn Marino 	 || *type == _C_GCINVISIBLE)
633*e4b17023SJohn Marino     {
634*e4b17023SJohn Marino       type += 1;
635*e4b17023SJohn Marino     }
636*e4b17023SJohn Marino   return type;
637*e4b17023SJohn Marino }
638*e4b17023SJohn Marino 
639*e4b17023SJohn Marino inline
640*e4b17023SJohn Marino const char *
objc_skip_typespec(const char * type)641*e4b17023SJohn Marino objc_skip_typespec (const char *type)
642*e4b17023SJohn Marino {
643*e4b17023SJohn Marino   type = objc_skip_variable_name (type);
644*e4b17023SJohn Marino   type = objc_skip_type_qualifiers (type);
645*e4b17023SJohn Marino 
646*e4b17023SJohn Marino   switch (*type) {
647*e4b17023SJohn Marino 
648*e4b17023SJohn Marino   case _C_ID:
649*e4b17023SJohn Marino     /* An id may be annotated by the actual type if it is known
650*e4b17023SJohn Marino        with the @"ClassName" syntax */
651*e4b17023SJohn Marino 
652*e4b17023SJohn Marino     if (*++type != '"')
653*e4b17023SJohn Marino       return type;
654*e4b17023SJohn Marino     else
655*e4b17023SJohn Marino       {
656*e4b17023SJohn Marino 	while (*++type != '"')
657*e4b17023SJohn Marino 	  /* do nothing */;
658*e4b17023SJohn Marino 	return type + 1;
659*e4b17023SJohn Marino       }
660*e4b17023SJohn Marino 
661*e4b17023SJohn Marino     /* The following are one character type codes */
662*e4b17023SJohn Marino   case _C_CLASS:
663*e4b17023SJohn Marino   case _C_SEL:
664*e4b17023SJohn Marino   case _C_CHR:
665*e4b17023SJohn Marino   case _C_UCHR:
666*e4b17023SJohn Marino   case _C_CHARPTR:
667*e4b17023SJohn Marino   case _C_ATOM:
668*e4b17023SJohn Marino   case _C_SHT:
669*e4b17023SJohn Marino   case _C_USHT:
670*e4b17023SJohn Marino   case _C_INT:
671*e4b17023SJohn Marino   case _C_UINT:
672*e4b17023SJohn Marino   case _C_LNG:
673*e4b17023SJohn Marino   case _C_BOOL:
674*e4b17023SJohn Marino   case _C_ULNG:
675*e4b17023SJohn Marino   case _C_LNG_LNG:
676*e4b17023SJohn Marino   case _C_ULNG_LNG:
677*e4b17023SJohn Marino   case _C_FLT:
678*e4b17023SJohn Marino   case _C_DBL:
679*e4b17023SJohn Marino   case _C_LNG_DBL:
680*e4b17023SJohn Marino   case _C_VOID:
681*e4b17023SJohn Marino   case _C_UNDEF:
682*e4b17023SJohn Marino     return ++type;
683*e4b17023SJohn Marino     break;
684*e4b17023SJohn Marino 
685*e4b17023SJohn Marino   case _C_COMPLEX:
686*e4b17023SJohn Marino     return type + 2;
687*e4b17023SJohn Marino     break;
688*e4b17023SJohn Marino 
689*e4b17023SJohn Marino   case _C_ARY_B:
690*e4b17023SJohn Marino     /* skip digits, typespec and closing ']' */
691*e4b17023SJohn Marino     while (isdigit ((unsigned char)*++type))
692*e4b17023SJohn Marino       ;
693*e4b17023SJohn Marino     type = objc_skip_typespec (type);
694*e4b17023SJohn Marino     if (*type == _C_ARY_E)
695*e4b17023SJohn Marino       return ++type;
696*e4b17023SJohn Marino     else
697*e4b17023SJohn Marino       {
698*e4b17023SJohn Marino 	_objc_abort ("bad array type %s\n", type);
699*e4b17023SJohn Marino 	return 0;
700*e4b17023SJohn Marino       }
701*e4b17023SJohn Marino 
702*e4b17023SJohn Marino   case _C_VECTOR:
703*e4b17023SJohn Marino     /* Skip '!' */
704*e4b17023SJohn Marino     type++;
705*e4b17023SJohn Marino     /* Skip '[' */
706*e4b17023SJohn Marino     type++;
707*e4b17023SJohn Marino     /* Skip digits (size) */
708*e4b17023SJohn Marino     while (isdigit ((unsigned char)*type))
709*e4b17023SJohn Marino       type++;
710*e4b17023SJohn Marino     /* Skip ',' */
711*e4b17023SJohn Marino     type++;
712*e4b17023SJohn Marino     /* Skip digits (alignment) */
713*e4b17023SJohn Marino     while (isdigit ((unsigned char)*type))
714*e4b17023SJohn Marino       type++;
715*e4b17023SJohn Marino     /* Skip typespec.  */
716*e4b17023SJohn Marino     type = objc_skip_typespec (type);
717*e4b17023SJohn Marino     /* Skip closing ']'.  */
718*e4b17023SJohn Marino     if (*type == _C_ARY_E)
719*e4b17023SJohn Marino       return ++type;
720*e4b17023SJohn Marino     else
721*e4b17023SJohn Marino       {
722*e4b17023SJohn Marino 	_objc_abort ("bad vector type %s\n", type);
723*e4b17023SJohn Marino 	return 0;
724*e4b17023SJohn Marino       }
725*e4b17023SJohn Marino 
726*e4b17023SJohn Marino   case _C_BFLD:
727*e4b17023SJohn Marino     /* The GNU encoding of bitfields is: b 'position' 'type'
728*e4b17023SJohn Marino        'size'.  */
729*e4b17023SJohn Marino     while (isdigit ((unsigned char)*++type))
730*e4b17023SJohn Marino       ;	/* skip position */
731*e4b17023SJohn Marino     while (isdigit ((unsigned char)*++type))
732*e4b17023SJohn Marino       ;	/* skip type and size */
733*e4b17023SJohn Marino     return type;
734*e4b17023SJohn Marino 
735*e4b17023SJohn Marino   case _C_STRUCT_B:
736*e4b17023SJohn Marino     /* skip name, and elements until closing '}'  */
737*e4b17023SJohn Marino 
738*e4b17023SJohn Marino     while (*type != _C_STRUCT_E && *type++ != '=')
739*e4b17023SJohn Marino       ;
740*e4b17023SJohn Marino     while (*type != _C_STRUCT_E)
741*e4b17023SJohn Marino       {
742*e4b17023SJohn Marino 	type = objc_skip_typespec (type);
743*e4b17023SJohn Marino       }
744*e4b17023SJohn Marino     return ++type;
745*e4b17023SJohn Marino 
746*e4b17023SJohn Marino   case _C_UNION_B:
747*e4b17023SJohn Marino     /* skip name, and elements until closing ')'  */
748*e4b17023SJohn Marino 
749*e4b17023SJohn Marino     while (*type != _C_UNION_E && *type++ != '=')
750*e4b17023SJohn Marino       ;
751*e4b17023SJohn Marino     while (*type != _C_UNION_E)
752*e4b17023SJohn Marino       {
753*e4b17023SJohn Marino 	type = objc_skip_typespec (type);
754*e4b17023SJohn Marino       }
755*e4b17023SJohn Marino     return ++type;
756*e4b17023SJohn Marino 
757*e4b17023SJohn Marino   case _C_PTR:
758*e4b17023SJohn Marino     /* Just skip the following typespec */
759*e4b17023SJohn Marino 
760*e4b17023SJohn Marino     return objc_skip_typespec (++type);
761*e4b17023SJohn Marino 
762*e4b17023SJohn Marino   default:
763*e4b17023SJohn Marino     {
764*e4b17023SJohn Marino       _objc_abort ("unknown type %s\n", type);
765*e4b17023SJohn Marino       return 0;
766*e4b17023SJohn Marino     }
767*e4b17023SJohn Marino   }
768*e4b17023SJohn Marino }
769*e4b17023SJohn Marino 
770*e4b17023SJohn Marino inline
771*e4b17023SJohn Marino const char *
objc_skip_offset(const char * type)772*e4b17023SJohn Marino objc_skip_offset (const char *type)
773*e4b17023SJohn Marino {
774*e4b17023SJohn Marino   /* The offset is prepended by a '+' if the argument is passed in
775*e4b17023SJohn Marino      registers.  PS: The compiler stopped generating this '+' in
776*e4b17023SJohn Marino      version 3.4.  */
777*e4b17023SJohn Marino   if (*type == '+')
778*e4b17023SJohn Marino     type++;
779*e4b17023SJohn Marino 
780*e4b17023SJohn Marino   /* Some people claim that on some platforms, where the stack grows
781*e4b17023SJohn Marino      backwards, the compiler generates negative offsets (??).  Skip a
782*e4b17023SJohn Marino      '-' for such a negative offset.  */
783*e4b17023SJohn Marino   if (*type == '-')
784*e4b17023SJohn Marino     type++;
785*e4b17023SJohn Marino 
786*e4b17023SJohn Marino   /* Skip the digits that represent the offset.  */
787*e4b17023SJohn Marino   while (isdigit ((unsigned char) *type))
788*e4b17023SJohn Marino     type++;
789*e4b17023SJohn Marino 
790*e4b17023SJohn Marino   return type;
791*e4b17023SJohn Marino }
792*e4b17023SJohn Marino 
793*e4b17023SJohn Marino const char *
objc_skip_argspec(const char * type)794*e4b17023SJohn Marino objc_skip_argspec (const char *type)
795*e4b17023SJohn Marino {
796*e4b17023SJohn Marino   type = objc_skip_typespec (type);
797*e4b17023SJohn Marino   type = objc_skip_offset (type);
798*e4b17023SJohn Marino   return type;
799*e4b17023SJohn Marino }
800*e4b17023SJohn Marino 
801*e4b17023SJohn Marino char *
method_copyReturnType(struct objc_method * method)802*e4b17023SJohn Marino method_copyReturnType (struct objc_method *method)
803*e4b17023SJohn Marino {
804*e4b17023SJohn Marino   if (method == NULL)
805*e4b17023SJohn Marino     return 0;
806*e4b17023SJohn Marino   else
807*e4b17023SJohn Marino     {
808*e4b17023SJohn Marino       char *returnValue;
809*e4b17023SJohn Marino       size_t returnValueSize;
810*e4b17023SJohn Marino 
811*e4b17023SJohn Marino       /* Determine returnValueSize.  */
812*e4b17023SJohn Marino       {
813*e4b17023SJohn Marino 	/* Find the end of the first argument.  We want to return the
814*e4b17023SJohn Marino 	   first argument spec, plus 1 byte for the \0 at the end.  */
815*e4b17023SJohn Marino 	const char *type = method->method_types;
816*e4b17023SJohn Marino 	if (*type == '\0')
817*e4b17023SJohn Marino 	  return NULL;
818*e4b17023SJohn Marino 	type = objc_skip_argspec (type);
819*e4b17023SJohn Marino 	returnValueSize = type - method->method_types + 1;
820*e4b17023SJohn Marino       }
821*e4b17023SJohn Marino 
822*e4b17023SJohn Marino       /* Copy the first argument into returnValue.  */
823*e4b17023SJohn Marino       returnValue = malloc (sizeof (char) * returnValueSize);
824*e4b17023SJohn Marino       memcpy (returnValue, method->method_types, returnValueSize);
825*e4b17023SJohn Marino       returnValue[returnValueSize - 1] = '\0';
826*e4b17023SJohn Marino 
827*e4b17023SJohn Marino       return returnValue;
828*e4b17023SJohn Marino     }
829*e4b17023SJohn Marino }
830*e4b17023SJohn Marino 
831*e4b17023SJohn Marino char *
method_copyArgumentType(struct objc_method * method,unsigned int argumentNumber)832*e4b17023SJohn Marino method_copyArgumentType (struct objc_method * method, unsigned int argumentNumber)
833*e4b17023SJohn Marino {
834*e4b17023SJohn Marino   if (method == NULL)
835*e4b17023SJohn Marino     return 0;
836*e4b17023SJohn Marino   else
837*e4b17023SJohn Marino     {
838*e4b17023SJohn Marino       char *returnValue;
839*e4b17023SJohn Marino       const char *returnValueStart;
840*e4b17023SJohn Marino       size_t returnValueSize;
841*e4b17023SJohn Marino 
842*e4b17023SJohn Marino       /* Determine returnValueStart and returnValueSize.  */
843*e4b17023SJohn Marino       {
844*e4b17023SJohn Marino 	const char *type = method->method_types;
845*e4b17023SJohn Marino 
846*e4b17023SJohn Marino 	/* Skip the first argument (return type).  */
847*e4b17023SJohn Marino 	type = objc_skip_argspec (type);
848*e4b17023SJohn Marino 
849*e4b17023SJohn Marino 	/* Now keep skipping arguments until we get to
850*e4b17023SJohn Marino 	   argumentNumber.  */
851*e4b17023SJohn Marino 	while (argumentNumber > 0)
852*e4b17023SJohn Marino 	  {
853*e4b17023SJohn Marino 	    /* We are supposed to skip an argument, but the string is
854*e4b17023SJohn Marino 	       finished.  This means we were asked for a non-existing
855*e4b17023SJohn Marino 	       argument.  */
856*e4b17023SJohn Marino 	    if (*type == '\0')
857*e4b17023SJohn Marino 	      return NULL;
858*e4b17023SJohn Marino 
859*e4b17023SJohn Marino 	    type = objc_skip_argspec (type);
860*e4b17023SJohn Marino 	    argumentNumber--;
861*e4b17023SJohn Marino 	  }
862*e4b17023SJohn Marino 
863*e4b17023SJohn Marino 	/* If the argument does not exist, return NULL.  */
864*e4b17023SJohn Marino 	if (*type == '\0')
865*e4b17023SJohn Marino 	  return NULL;
866*e4b17023SJohn Marino 
867*e4b17023SJohn Marino 	returnValueStart = type;
868*e4b17023SJohn Marino 	type = objc_skip_argspec (type);
869*e4b17023SJohn Marino 	returnValueSize = type - returnValueStart + 1;
870*e4b17023SJohn Marino       }
871*e4b17023SJohn Marino 
872*e4b17023SJohn Marino       /* Copy the argument into returnValue.  */
873*e4b17023SJohn Marino       returnValue = malloc (sizeof (char) * returnValueSize);
874*e4b17023SJohn Marino       memcpy (returnValue, returnValueStart, returnValueSize);
875*e4b17023SJohn Marino       returnValue[returnValueSize - 1] = '\0';
876*e4b17023SJohn Marino 
877*e4b17023SJohn Marino       return returnValue;
878*e4b17023SJohn Marino     }
879*e4b17023SJohn Marino }
880*e4b17023SJohn Marino 
method_getReturnType(struct objc_method * method,char * returnValue,size_t returnValueSize)881*e4b17023SJohn Marino void method_getReturnType (struct objc_method * method, char *returnValue,
882*e4b17023SJohn Marino 			   size_t returnValueSize)
883*e4b17023SJohn Marino {
884*e4b17023SJohn Marino   if (returnValue == NULL  ||  returnValueSize == 0)
885*e4b17023SJohn Marino     return;
886*e4b17023SJohn Marino 
887*e4b17023SJohn Marino   /* Zero the string; we'll then write the argument type at the
888*e4b17023SJohn Marino      beginning of it, if needed.  */
889*e4b17023SJohn Marino   memset (returnValue, 0, returnValueSize);
890*e4b17023SJohn Marino 
891*e4b17023SJohn Marino   if (method == NULL)
892*e4b17023SJohn Marino     return;
893*e4b17023SJohn Marino   else
894*e4b17023SJohn Marino     {
895*e4b17023SJohn Marino       size_t argumentTypeSize;
896*e4b17023SJohn Marino 
897*e4b17023SJohn Marino       /* Determine argumentTypeSize.  */
898*e4b17023SJohn Marino       {
899*e4b17023SJohn Marino 	/* Find the end of the first argument.  We want to return the
900*e4b17023SJohn Marino 	   first argument spec.  */
901*e4b17023SJohn Marino 	const char *type = method->method_types;
902*e4b17023SJohn Marino 	if (*type == '\0')
903*e4b17023SJohn Marino 	  return;
904*e4b17023SJohn Marino 	type = objc_skip_argspec (type);
905*e4b17023SJohn Marino 	argumentTypeSize = type - method->method_types;
906*e4b17023SJohn Marino 	if (argumentTypeSize > returnValueSize)
907*e4b17023SJohn Marino 	  argumentTypeSize = returnValueSize;
908*e4b17023SJohn Marino       }
909*e4b17023SJohn Marino       /* Copy the argument at the beginning of the string.  */
910*e4b17023SJohn Marino       memcpy (returnValue, method->method_types, argumentTypeSize);
911*e4b17023SJohn Marino     }
912*e4b17023SJohn Marino }
913*e4b17023SJohn Marino 
method_getArgumentType(struct objc_method * method,unsigned int argumentNumber,char * returnValue,size_t returnValueSize)914*e4b17023SJohn Marino void method_getArgumentType (struct objc_method * method, unsigned int argumentNumber,
915*e4b17023SJohn Marino 			     char *returnValue, size_t returnValueSize)
916*e4b17023SJohn Marino {
917*e4b17023SJohn Marino   if (returnValue == NULL  ||  returnValueSize == 0)
918*e4b17023SJohn Marino     return;
919*e4b17023SJohn Marino 
920*e4b17023SJohn Marino   /* Zero the string; we'll then write the argument type at the
921*e4b17023SJohn Marino      beginning of it, if needed.  */
922*e4b17023SJohn Marino   memset (returnValue, 0, returnValueSize);
923*e4b17023SJohn Marino 
924*e4b17023SJohn Marino   if (method == NULL)
925*e4b17023SJohn Marino     return;
926*e4b17023SJohn Marino   else
927*e4b17023SJohn Marino     {
928*e4b17023SJohn Marino       const char *returnValueStart;
929*e4b17023SJohn Marino       size_t argumentTypeSize;
930*e4b17023SJohn Marino 
931*e4b17023SJohn Marino       /* Determine returnValueStart and argumentTypeSize.  */
932*e4b17023SJohn Marino       {
933*e4b17023SJohn Marino 	const char *type = method->method_types;
934*e4b17023SJohn Marino 
935*e4b17023SJohn Marino 	/* Skip the first argument (return type).  */
936*e4b17023SJohn Marino 	type = objc_skip_argspec (type);
937*e4b17023SJohn Marino 
938*e4b17023SJohn Marino 	/* Now keep skipping arguments until we get to
939*e4b17023SJohn Marino 	   argumentNumber.  */
940*e4b17023SJohn Marino 	while (argumentNumber > 0)
941*e4b17023SJohn Marino 	  {
942*e4b17023SJohn Marino 	    /* We are supposed to skip an argument, but the string is
943*e4b17023SJohn Marino 	       finished.  This means we were asked for a non-existing
944*e4b17023SJohn Marino 	       argument.  */
945*e4b17023SJohn Marino 	    if (*type == '\0')
946*e4b17023SJohn Marino 	      return;
947*e4b17023SJohn Marino 
948*e4b17023SJohn Marino 	    type = objc_skip_argspec (type);
949*e4b17023SJohn Marino 	    argumentNumber--;
950*e4b17023SJohn Marino 	  }
951*e4b17023SJohn Marino 
952*e4b17023SJohn Marino 	/* If the argument does not exist, it's game over.  */
953*e4b17023SJohn Marino 	if (*type == '\0')
954*e4b17023SJohn Marino 	  return;
955*e4b17023SJohn Marino 
956*e4b17023SJohn Marino 	returnValueStart = type;
957*e4b17023SJohn Marino 	type = objc_skip_argspec (type);
958*e4b17023SJohn Marino 	argumentTypeSize = type - returnValueStart;
959*e4b17023SJohn Marino 	if (argumentTypeSize > returnValueSize)
960*e4b17023SJohn Marino 	  argumentTypeSize = returnValueSize;
961*e4b17023SJohn Marino       }
962*e4b17023SJohn Marino       /* Copy the argument at the beginning of the string.  */
963*e4b17023SJohn Marino       memcpy (returnValue, returnValueStart, argumentTypeSize);
964*e4b17023SJohn Marino     }
965*e4b17023SJohn Marino }
966*e4b17023SJohn Marino 
967*e4b17023SJohn Marino unsigned int
method_getNumberOfArguments(struct objc_method * method)968*e4b17023SJohn Marino method_getNumberOfArguments (struct objc_method *method)
969*e4b17023SJohn Marino {
970*e4b17023SJohn Marino   if (method == NULL)
971*e4b17023SJohn Marino     return 0;
972*e4b17023SJohn Marino   else
973*e4b17023SJohn Marino     {
974*e4b17023SJohn Marino       unsigned int i = 0;
975*e4b17023SJohn Marino       const char *type = method->method_types;
976*e4b17023SJohn Marino       while (*type)
977*e4b17023SJohn Marino 	{
978*e4b17023SJohn Marino 	  type = objc_skip_argspec (type);
979*e4b17023SJohn Marino 	  i += 1;
980*e4b17023SJohn Marino 	}
981*e4b17023SJohn Marino 
982*e4b17023SJohn Marino       if (i == 0)
983*e4b17023SJohn Marino 	{
984*e4b17023SJohn Marino 	  /* This could only happen if method_types is invalid; in
985*e4b17023SJohn Marino 	     that case, return 0.  */
986*e4b17023SJohn Marino 	  return 0;
987*e4b17023SJohn Marino 	}
988*e4b17023SJohn Marino       else
989*e4b17023SJohn Marino 	{
990*e4b17023SJohn Marino 	  /* Remove the return type.  */
991*e4b17023SJohn Marino 	  return (i - 1);
992*e4b17023SJohn Marino 	}
993*e4b17023SJohn Marino     }
994*e4b17023SJohn Marino }
995*e4b17023SJohn Marino 
996*e4b17023SJohn Marino unsigned
objc_get_type_qualifiers(const char * type)997*e4b17023SJohn Marino objc_get_type_qualifiers (const char *type)
998*e4b17023SJohn Marino {
999*e4b17023SJohn Marino   unsigned res = 0;
1000*e4b17023SJohn Marino   BOOL flag = YES;
1001*e4b17023SJohn Marino 
1002*e4b17023SJohn Marino   while (flag)
1003*e4b17023SJohn Marino     switch (*type++)
1004*e4b17023SJohn Marino       {
1005*e4b17023SJohn Marino       case _C_CONST:       res |= _F_CONST; break;
1006*e4b17023SJohn Marino       case _C_IN:          res |= _F_IN; break;
1007*e4b17023SJohn Marino       case _C_INOUT:       res |= _F_INOUT; break;
1008*e4b17023SJohn Marino       case _C_OUT:         res |= _F_OUT; break;
1009*e4b17023SJohn Marino       case _C_BYCOPY:      res |= _F_BYCOPY; break;
1010*e4b17023SJohn Marino       case _C_BYREF:       res |= _F_BYREF; break;
1011*e4b17023SJohn Marino       case _C_ONEWAY:      res |= _F_ONEWAY; break;
1012*e4b17023SJohn Marino       case _C_GCINVISIBLE: res |= _F_GCINVISIBLE; break;
1013*e4b17023SJohn Marino       default: flag = NO;
1014*e4b17023SJohn Marino     }
1015*e4b17023SJohn Marino 
1016*e4b17023SJohn Marino   return res;
1017*e4b17023SJohn Marino }
1018*e4b17023SJohn Marino 
1019*e4b17023SJohn Marino /* The following three functions can be used to determine how a
1020*e4b17023SJohn Marino    structure is laid out by the compiler. For example:
1021*e4b17023SJohn Marino 
1022*e4b17023SJohn Marino   struct objc_struct_layout layout;
1023*e4b17023SJohn Marino   int i;
1024*e4b17023SJohn Marino 
1025*e4b17023SJohn Marino   objc_layout_structure (type, &layout);
1026*e4b17023SJohn Marino   while (objc_layout_structure_next_member (&layout))
1027*e4b17023SJohn Marino     {
1028*e4b17023SJohn Marino       int position, align;
1029*e4b17023SJohn Marino       const char *type;
1030*e4b17023SJohn Marino 
1031*e4b17023SJohn Marino       objc_layout_structure_get_info (&layout, &position, &align, &type);
1032*e4b17023SJohn Marino       printf ("element %d has offset %d, alignment %d\n",
1033*e4b17023SJohn Marino               i++, position, align);
1034*e4b17023SJohn Marino     }
1035*e4b17023SJohn Marino 
1036*e4b17023SJohn Marino   These functions are used by objc_sizeof_type and objc_alignof_type
1037*e4b17023SJohn Marino   functions to compute the size and alignment of structures. The
1038*e4b17023SJohn Marino   previous method of computing the size and alignment of a structure
1039*e4b17023SJohn Marino   was not working on some architectures, particulary on AIX, and in
1040*e4b17023SJohn Marino   the presence of bitfields inside the structure.  */
1041*e4b17023SJohn Marino void
objc_layout_structure(const char * type,struct objc_struct_layout * layout)1042*e4b17023SJohn Marino objc_layout_structure (const char *type,
1043*e4b17023SJohn Marino 		       struct objc_struct_layout *layout)
1044*e4b17023SJohn Marino {
1045*e4b17023SJohn Marino   const char *ntype;
1046*e4b17023SJohn Marino 
1047*e4b17023SJohn Marino   if (*type != _C_UNION_B && *type != _C_STRUCT_B)
1048*e4b17023SJohn Marino     {
1049*e4b17023SJohn Marino       _objc_abort ("record (or union) type expected in objc_layout_structure, got %s\n",
1050*e4b17023SJohn Marino 		   type);
1051*e4b17023SJohn Marino     }
1052*e4b17023SJohn Marino 
1053*e4b17023SJohn Marino   type ++;
1054*e4b17023SJohn Marino   layout->original_type = type;
1055*e4b17023SJohn Marino 
1056*e4b17023SJohn Marino   /* Skip "<name>=" if any. Avoid embedded structures and unions. */
1057*e4b17023SJohn Marino   ntype = type;
1058*e4b17023SJohn Marino   while (*ntype != _C_STRUCT_E && *ntype != _C_STRUCT_B && *ntype != _C_UNION_B
1059*e4b17023SJohn Marino          && *ntype++ != '=')
1060*e4b17023SJohn Marino     /* do nothing */;
1061*e4b17023SJohn Marino 
1062*e4b17023SJohn Marino   /* If there's a "<name>=", ntype - 1 points to '='; skip the the name */
1063*e4b17023SJohn Marino   if (*(ntype - 1) == '=')
1064*e4b17023SJohn Marino     type = ntype;
1065*e4b17023SJohn Marino 
1066*e4b17023SJohn Marino   layout->type = type;
1067*e4b17023SJohn Marino   layout->prev_type = NULL;
1068*e4b17023SJohn Marino   layout->record_size = 0;
1069*e4b17023SJohn Marino   layout->record_align = BITS_PER_UNIT;
1070*e4b17023SJohn Marino 
1071*e4b17023SJohn Marino   layout->record_align = MAX (layout->record_align, STRUCTURE_SIZE_BOUNDARY);
1072*e4b17023SJohn Marino }
1073*e4b17023SJohn Marino 
1074*e4b17023SJohn Marino BOOL
objc_layout_structure_next_member(struct objc_struct_layout * layout)1075*e4b17023SJohn Marino objc_layout_structure_next_member (struct objc_struct_layout *layout)
1076*e4b17023SJohn Marino {
1077*e4b17023SJohn Marino   register int desired_align = 0;
1078*e4b17023SJohn Marino 
1079*e4b17023SJohn Marino   /* The following are used only if the field is a bitfield */
1080*e4b17023SJohn Marino   register const char *bfld_type = 0;
1081*e4b17023SJohn Marino   register int bfld_type_align = 0, bfld_field_size = 0;
1082*e4b17023SJohn Marino 
1083*e4b17023SJohn Marino   /* The current type without the type qualifiers */
1084*e4b17023SJohn Marino   const char *type;
1085*e4b17023SJohn Marino   BOOL unionp = layout->original_type[-1] == _C_UNION_B;
1086*e4b17023SJohn Marino 
1087*e4b17023SJohn Marino   /* Add the size of the previous field to the size of the record.  */
1088*e4b17023SJohn Marino   if (layout->prev_type)
1089*e4b17023SJohn Marino     {
1090*e4b17023SJohn Marino       type = objc_skip_type_qualifiers (layout->prev_type);
1091*e4b17023SJohn Marino       if (unionp)
1092*e4b17023SJohn Marino         layout->record_size = MAX (layout->record_size,
1093*e4b17023SJohn Marino 				   objc_sizeof_type (type) * BITS_PER_UNIT);
1094*e4b17023SJohn Marino 
1095*e4b17023SJohn Marino       else if (*type != _C_BFLD)
1096*e4b17023SJohn Marino         layout->record_size += objc_sizeof_type (type) * BITS_PER_UNIT;
1097*e4b17023SJohn Marino       else {
1098*e4b17023SJohn Marino         /* Get the bitfield's type */
1099*e4b17023SJohn Marino         for (bfld_type = type + 1;
1100*e4b17023SJohn Marino              isdigit ((unsigned char)*bfld_type);
1101*e4b17023SJohn Marino              bfld_type++)
1102*e4b17023SJohn Marino           /* do nothing */;
1103*e4b17023SJohn Marino 
1104*e4b17023SJohn Marino         bfld_type_align = objc_alignof_type (bfld_type) * BITS_PER_UNIT;
1105*e4b17023SJohn Marino         bfld_field_size = atoi (objc_skip_typespec (bfld_type));
1106*e4b17023SJohn Marino         layout->record_size += bfld_field_size;
1107*e4b17023SJohn Marino       }
1108*e4b17023SJohn Marino     }
1109*e4b17023SJohn Marino 
1110*e4b17023SJohn Marino   if ((unionp && *layout->type == _C_UNION_E)
1111*e4b17023SJohn Marino       || (!unionp && *layout->type == _C_STRUCT_E))
1112*e4b17023SJohn Marino     return NO;
1113*e4b17023SJohn Marino 
1114*e4b17023SJohn Marino   /* Skip the variable name if any */
1115*e4b17023SJohn Marino   layout->type = objc_skip_variable_name (layout->type);
1116*e4b17023SJohn Marino   type = objc_skip_type_qualifiers (layout->type);
1117*e4b17023SJohn Marino 
1118*e4b17023SJohn Marino   if (*type != _C_BFLD)
1119*e4b17023SJohn Marino     desired_align = objc_alignof_type (type) * BITS_PER_UNIT;
1120*e4b17023SJohn Marino   else
1121*e4b17023SJohn Marino     {
1122*e4b17023SJohn Marino       desired_align = 1;
1123*e4b17023SJohn Marino       /* Skip the bitfield's offset */
1124*e4b17023SJohn Marino       for (bfld_type = type + 1;
1125*e4b17023SJohn Marino            isdigit ((unsigned char) *bfld_type);
1126*e4b17023SJohn Marino            bfld_type++)
1127*e4b17023SJohn Marino         /* do nothing */;
1128*e4b17023SJohn Marino 
1129*e4b17023SJohn Marino       bfld_type_align = objc_alignof_type (bfld_type) * BITS_PER_UNIT;
1130*e4b17023SJohn Marino       bfld_field_size = atoi (objc_skip_typespec (bfld_type));
1131*e4b17023SJohn Marino     }
1132*e4b17023SJohn Marino 
1133*e4b17023SJohn Marino   /* The following won't work for vectors.  */
1134*e4b17023SJohn Marino #ifdef BIGGEST_FIELD_ALIGNMENT
1135*e4b17023SJohn Marino   desired_align = MIN (desired_align, BIGGEST_FIELD_ALIGNMENT);
1136*e4b17023SJohn Marino #endif
1137*e4b17023SJohn Marino #ifdef ADJUST_FIELD_ALIGN
1138*e4b17023SJohn Marino   desired_align = ADJUST_FIELD_ALIGN (type, desired_align);
1139*e4b17023SJohn Marino #endif
1140*e4b17023SJohn Marino 
1141*e4b17023SJohn Marino   /* Record must have at least as much alignment as any field.
1142*e4b17023SJohn Marino      Otherwise, the alignment of the field within the record
1143*e4b17023SJohn Marino      is meaningless.  */
1144*e4b17023SJohn Marino #ifndef PCC_BITFIELD_TYPE_MATTERS
1145*e4b17023SJohn Marino   layout->record_align = MAX (layout->record_align, desired_align);
1146*e4b17023SJohn Marino #else	/* PCC_BITFIELD_TYPE_MATTERS */
1147*e4b17023SJohn Marino   if (*type == _C_BFLD)
1148*e4b17023SJohn Marino     {
1149*e4b17023SJohn Marino       /* For these machines, a zero-length field does not
1150*e4b17023SJohn Marino          affect the alignment of the structure as a whole.
1151*e4b17023SJohn Marino          It does, however, affect the alignment of the next field
1152*e4b17023SJohn Marino          within the structure.  */
1153*e4b17023SJohn Marino       if (bfld_field_size)
1154*e4b17023SJohn Marino         layout->record_align = MAX (layout->record_align, desired_align);
1155*e4b17023SJohn Marino       else
1156*e4b17023SJohn Marino         desired_align = objc_alignof_type (bfld_type) * BITS_PER_UNIT;
1157*e4b17023SJohn Marino 
1158*e4b17023SJohn Marino       /* A named bit field of declared type `int'
1159*e4b17023SJohn Marino          forces the entire structure to have `int' alignment.
1160*e4b17023SJohn Marino          Q1: How is encoded this thing and how to check for it?
1161*e4b17023SJohn Marino          Q2: How to determine maximum_field_alignment at runtime? */
1162*e4b17023SJohn Marino 
1163*e4b17023SJohn Marino /*	  if (DECL_NAME (field) != 0) */
1164*e4b17023SJohn Marino       {
1165*e4b17023SJohn Marino         int type_align = bfld_type_align;
1166*e4b17023SJohn Marino #if 0
1167*e4b17023SJohn Marino         if (maximum_field_alignment != 0)
1168*e4b17023SJohn Marino           type_align = MIN (type_align, maximum_field_alignment);
1169*e4b17023SJohn Marino         else if (DECL_PACKED (field))
1170*e4b17023SJohn Marino           type_align = MIN (type_align, BITS_PER_UNIT);
1171*e4b17023SJohn Marino #endif
1172*e4b17023SJohn Marino 
1173*e4b17023SJohn Marino         layout->record_align = MAX (layout->record_align, type_align);
1174*e4b17023SJohn Marino       }
1175*e4b17023SJohn Marino     }
1176*e4b17023SJohn Marino   else
1177*e4b17023SJohn Marino     layout->record_align = MAX (layout->record_align, desired_align);
1178*e4b17023SJohn Marino #endif	/* PCC_BITFIELD_TYPE_MATTERS */
1179*e4b17023SJohn Marino 
1180*e4b17023SJohn Marino   /* Does this field automatically have alignment it needs
1181*e4b17023SJohn Marino      by virtue of the fields that precede it and the record's
1182*e4b17023SJohn Marino      own alignment?  */
1183*e4b17023SJohn Marino 
1184*e4b17023SJohn Marino   if (*type == _C_BFLD)
1185*e4b17023SJohn Marino     layout->record_size = atoi (type + 1);
1186*e4b17023SJohn Marino   else if (layout->record_size % desired_align != 0)
1187*e4b17023SJohn Marino     {
1188*e4b17023SJohn Marino       /* No, we need to skip space before this field.
1189*e4b17023SJohn Marino          Bump the cumulative size to multiple of field alignment.  */
1190*e4b17023SJohn Marino       layout->record_size = ROUND (layout->record_size, desired_align);
1191*e4b17023SJohn Marino     }
1192*e4b17023SJohn Marino 
1193*e4b17023SJohn Marino   /* Jump to the next field in record. */
1194*e4b17023SJohn Marino 
1195*e4b17023SJohn Marino   layout->prev_type = layout->type;
1196*e4b17023SJohn Marino   layout->type = objc_skip_typespec (layout->type);      /* skip component */
1197*e4b17023SJohn Marino 
1198*e4b17023SJohn Marino   return YES;
1199*e4b17023SJohn Marino }
1200*e4b17023SJohn Marino 
objc_layout_finish_structure(struct objc_struct_layout * layout,unsigned int * size,unsigned int * align)1201*e4b17023SJohn Marino void objc_layout_finish_structure (struct objc_struct_layout *layout,
1202*e4b17023SJohn Marino                                    unsigned int *size,
1203*e4b17023SJohn Marino                                    unsigned int *align)
1204*e4b17023SJohn Marino {
1205*e4b17023SJohn Marino   BOOL unionp = layout->original_type[-1] == _C_UNION_B;
1206*e4b17023SJohn Marino   if (layout->type
1207*e4b17023SJohn Marino       && ((!unionp && *layout->type == _C_STRUCT_E)
1208*e4b17023SJohn Marino        	  || (unionp && *layout->type == _C_UNION_E)))
1209*e4b17023SJohn Marino     {
1210*e4b17023SJohn Marino       /* Work out the alignment of the record as one expression and store
1211*e4b17023SJohn Marino          in the record type.  Round it up to a multiple of the record's
1212*e4b17023SJohn Marino          alignment. */
1213*e4b17023SJohn Marino #if defined (ROUND_TYPE_ALIGN) && ! defined (__sparc__)
1214*e4b17023SJohn Marino       layout->record_align = ROUND_TYPE_ALIGN (layout->original_type-1,
1215*e4b17023SJohn Marino                                                1,
1216*e4b17023SJohn Marino                                                layout->record_align);
1217*e4b17023SJohn Marino #else
1218*e4b17023SJohn Marino       layout->record_align = MAX (1, layout->record_align);
1219*e4b17023SJohn Marino #endif
1220*e4b17023SJohn Marino 
1221*e4b17023SJohn Marino #ifdef ROUND_TYPE_SIZE
1222*e4b17023SJohn Marino       layout->record_size = ROUND_TYPE_SIZE (layout->original_type,
1223*e4b17023SJohn Marino                                              layout->record_size,
1224*e4b17023SJohn Marino                                              layout->record_align);
1225*e4b17023SJohn Marino #else
1226*e4b17023SJohn Marino       /* Round the size up to be a multiple of the required alignment */
1227*e4b17023SJohn Marino       layout->record_size = ROUND (layout->record_size, layout->record_align);
1228*e4b17023SJohn Marino #endif
1229*e4b17023SJohn Marino 
1230*e4b17023SJohn Marino       layout->type = NULL;
1231*e4b17023SJohn Marino     }
1232*e4b17023SJohn Marino   if (size)
1233*e4b17023SJohn Marino     *size = layout->record_size / BITS_PER_UNIT;
1234*e4b17023SJohn Marino   if (align)
1235*e4b17023SJohn Marino     *align = layout->record_align / BITS_PER_UNIT;
1236*e4b17023SJohn Marino }
1237*e4b17023SJohn Marino 
objc_layout_structure_get_info(struct objc_struct_layout * layout,unsigned int * offset,unsigned int * align,const char ** type)1238*e4b17023SJohn Marino void objc_layout_structure_get_info (struct objc_struct_layout *layout,
1239*e4b17023SJohn Marino                                      unsigned int *offset,
1240*e4b17023SJohn Marino                                      unsigned int *align,
1241*e4b17023SJohn Marino                                      const char **type)
1242*e4b17023SJohn Marino {
1243*e4b17023SJohn Marino   if (offset)
1244*e4b17023SJohn Marino     *offset = layout->record_size / BITS_PER_UNIT;
1245*e4b17023SJohn Marino   if (align)
1246*e4b17023SJohn Marino     *align = layout->record_align / BITS_PER_UNIT;
1247*e4b17023SJohn Marino   if (type)
1248*e4b17023SJohn Marino     *type = layout->prev_type;
1249*e4b17023SJohn Marino }
1250