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