xref: /dflybsd-src/contrib/gcc-4.7/libobjc/gc.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* Basic data types for Objective C.
2*e4b17023SJohn Marino    Copyright (C) 1998, 2002, 2004, 2005, 2006, 2009, 2010
3*e4b17023SJohn Marino    Free Software Foundation, Inc.
4*e4b17023SJohn Marino    Contributed by Ovidiu Predescu.
5*e4b17023SJohn Marino 
6*e4b17023SJohn Marino This file is part of GCC.
7*e4b17023SJohn Marino 
8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify
9*e4b17023SJohn Marino it under the terms of the GNU General Public License as published by
10*e4b17023SJohn Marino the Free Software Foundation; either version 3, or (at your option)
11*e4b17023SJohn Marino any later version.
12*e4b17023SJohn Marino 
13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful,
14*e4b17023SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
15*e4b17023SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*e4b17023SJohn Marino GNU General Public License for more details.
17*e4b17023SJohn Marino 
18*e4b17023SJohn Marino Under Section 7 of GPL version 3, you are granted additional
19*e4b17023SJohn Marino permissions described in the GCC Runtime Library Exception, version
20*e4b17023SJohn Marino 3.1, as published by the Free Software Foundation.
21*e4b17023SJohn Marino 
22*e4b17023SJohn Marino You should have received a copy of the GNU General Public License and
23*e4b17023SJohn Marino a copy of the GCC Runtime Library Exception along with this program;
24*e4b17023SJohn Marino see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
25*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
26*e4b17023SJohn Marino 
27*e4b17023SJohn Marino #include "objc-private/common.h"
28*e4b17023SJohn Marino #include "objc/objc.h"
29*e4b17023SJohn Marino 
30*e4b17023SJohn Marino #if OBJC_WITH_GC
31*e4b17023SJohn Marino 
32*e4b17023SJohn Marino #include "tconfig.h"
33*e4b17023SJohn Marino #include <assert.h>
34*e4b17023SJohn Marino #include <ctype.h> /* For isdigit.  */
35*e4b17023SJohn Marino #include <string.h>
36*e4b17023SJohn Marino #include <stdlib.h>
37*e4b17023SJohn Marino #include "objc/runtime.h"
38*e4b17023SJohn Marino #include "objc-private/module-abi-8.h"
39*e4b17023SJohn Marino 
40*e4b17023SJohn Marino #include <gc.h>
41*e4b17023SJohn Marino #include <limits.h>
42*e4b17023SJohn Marino 
43*e4b17023SJohn Marino /* gc_typed.h uses the following but doesn't declare them */
44*e4b17023SJohn Marino typedef GC_word word;
45*e4b17023SJohn Marino typedef GC_signed_word signed_word;
46*e4b17023SJohn Marino #define BITS_PER_WORD (CHAR_BIT * sizeof (word))
47*e4b17023SJohn Marino 
48*e4b17023SJohn Marino #include <gc_typed.h>
49*e4b17023SJohn Marino 
50*e4b17023SJohn Marino /* The following functions set up in `mask` the corresponding pointers.
51*e4b17023SJohn Marino    The offset is incremented with the size of the type.  */
52*e4b17023SJohn Marino 
53*e4b17023SJohn Marino #define ROUND(V, A) \
54*e4b17023SJohn Marino   ({ typeof (V) __v = (V); typeof (A) __a = (A); \
55*e4b17023SJohn Marino      __a * ((__v+__a - 1)/__a); })
56*e4b17023SJohn Marino 
57*e4b17023SJohn Marino #define SET_BIT_FOR_OFFSET(mask, offset) \
58*e4b17023SJohn Marino   GC_set_bit (mask, offset / sizeof (void *))
59*e4b17023SJohn Marino 
60*e4b17023SJohn Marino /* Some prototypes */
61*e4b17023SJohn Marino static void
62*e4b17023SJohn Marino __objc_gc_setup_struct (GC_bitmap mask, const char *type, int offset);
63*e4b17023SJohn Marino static void
64*e4b17023SJohn Marino __objc_gc_setup_union (GC_bitmap mask, const char *type, int offset);
65*e4b17023SJohn Marino 
66*e4b17023SJohn Marino 
67*e4b17023SJohn Marino static void
__objc_gc_setup_array(GC_bitmap mask,const char * type,int offset)68*e4b17023SJohn Marino __objc_gc_setup_array (GC_bitmap mask, const char *type, int offset)
69*e4b17023SJohn Marino {
70*e4b17023SJohn Marino   int i, len = atoi (type + 1);
71*e4b17023SJohn Marino 
72*e4b17023SJohn Marino   while (isdigit (*++type))
73*e4b17023SJohn Marino     /* do nothing */;		/* skip the size of the array */
74*e4b17023SJohn Marino 
75*e4b17023SJohn Marino   switch (*type) {
76*e4b17023SJohn Marino   case _C_ARY_B:
77*e4b17023SJohn Marino     for (i = 0; i < len; i++)
78*e4b17023SJohn Marino       __objc_gc_setup_array (mask, type, offset);
79*e4b17023SJohn Marino     break;
80*e4b17023SJohn Marino 
81*e4b17023SJohn Marino   case _C_STRUCT_B:
82*e4b17023SJohn Marino     for (i = 0; i < len; i++)
83*e4b17023SJohn Marino       __objc_gc_setup_struct (mask, type, offset);
84*e4b17023SJohn Marino     break;
85*e4b17023SJohn Marino 
86*e4b17023SJohn Marino   case _C_UNION_B:
87*e4b17023SJohn Marino     for (i = 0; i < len; i++)
88*e4b17023SJohn Marino       __objc_gc_setup_union (mask, type, offset);
89*e4b17023SJohn Marino     break;
90*e4b17023SJohn Marino 
91*e4b17023SJohn Marino   default:
92*e4b17023SJohn Marino     break;
93*e4b17023SJohn Marino   }
94*e4b17023SJohn Marino }
95*e4b17023SJohn Marino 
96*e4b17023SJohn Marino static void
__objc_gc_setup_struct(GC_bitmap mask,const char * type,int offset)97*e4b17023SJohn Marino __objc_gc_setup_struct (GC_bitmap mask, const char *type, int offset)
98*e4b17023SJohn Marino {
99*e4b17023SJohn Marino   struct objc_struct_layout layout;
100*e4b17023SJohn Marino   unsigned int position;
101*e4b17023SJohn Marino   const char *mtype;
102*e4b17023SJohn Marino 
103*e4b17023SJohn Marino   objc_layout_structure (type, &layout);
104*e4b17023SJohn Marino 
105*e4b17023SJohn Marino   while (objc_layout_structure_next_member (&layout))
106*e4b17023SJohn Marino     {
107*e4b17023SJohn Marino       BOOL gc_invisible = NO;
108*e4b17023SJohn Marino 
109*e4b17023SJohn Marino       objc_layout_structure_get_info (&layout, &position, NULL, &mtype);
110*e4b17023SJohn Marino 
111*e4b17023SJohn Marino       /* Skip the variable name */
112*e4b17023SJohn Marino       if (*mtype == '"')
113*e4b17023SJohn Marino 	{
114*e4b17023SJohn Marino 	  for (mtype++; *mtype++ != '"';)
115*e4b17023SJohn Marino 	    /* do nothing */;
116*e4b17023SJohn Marino 	}
117*e4b17023SJohn Marino 
118*e4b17023SJohn Marino       if (*mtype == _C_GCINVISIBLE)
119*e4b17023SJohn Marino 	{
120*e4b17023SJohn Marino 	  gc_invisible = YES;
121*e4b17023SJohn Marino 	  mtype++;
122*e4b17023SJohn Marino 	}
123*e4b17023SJohn Marino 
124*e4b17023SJohn Marino       /* Add to position the offset of this structure */
125*e4b17023SJohn Marino       position += offset;
126*e4b17023SJohn Marino 
127*e4b17023SJohn Marino       switch (*mtype) {
128*e4b17023SJohn Marino       case _C_ID:
129*e4b17023SJohn Marino       case _C_CLASS:
130*e4b17023SJohn Marino       case _C_SEL:
131*e4b17023SJohn Marino       case _C_PTR:
132*e4b17023SJohn Marino       case _C_CHARPTR:
133*e4b17023SJohn Marino       case _C_ATOM:
134*e4b17023SJohn Marino 	if (! gc_invisible)
135*e4b17023SJohn Marino 	  SET_BIT_FOR_OFFSET (mask, position);
136*e4b17023SJohn Marino 	break;
137*e4b17023SJohn Marino 
138*e4b17023SJohn Marino       case _C_ARY_B:
139*e4b17023SJohn Marino 	__objc_gc_setup_array (mask, mtype, position);
140*e4b17023SJohn Marino 	break;
141*e4b17023SJohn Marino 
142*e4b17023SJohn Marino       case _C_STRUCT_B:
143*e4b17023SJohn Marino 	__objc_gc_setup_struct (mask, mtype, position);
144*e4b17023SJohn Marino 	break;
145*e4b17023SJohn Marino 
146*e4b17023SJohn Marino       case _C_UNION_B:
147*e4b17023SJohn Marino 	__objc_gc_setup_union (mask, mtype, position);
148*e4b17023SJohn Marino 	break;
149*e4b17023SJohn Marino 
150*e4b17023SJohn Marino       default:
151*e4b17023SJohn Marino         break;
152*e4b17023SJohn Marino       }
153*e4b17023SJohn Marino     }
154*e4b17023SJohn Marino }
155*e4b17023SJohn Marino 
156*e4b17023SJohn Marino static void
__objc_gc_setup_union(GC_bitmap mask,const char * type,int offset)157*e4b17023SJohn Marino __objc_gc_setup_union (GC_bitmap mask, const char *type, int offset)
158*e4b17023SJohn Marino {
159*e4b17023SJohn Marino   /* Sub-optimal, quick implementation: assume the union is made of
160*e4b17023SJohn Marino      pointers, set up the mask accordingly. */
161*e4b17023SJohn Marino 
162*e4b17023SJohn Marino   int i, size, align;
163*e4b17023SJohn Marino 
164*e4b17023SJohn Marino   /* Skip the variable name */
165*e4b17023SJohn Marino   if (*type == '"')
166*e4b17023SJohn Marino     {
167*e4b17023SJohn Marino       for (type++; *type++ != '"';)
168*e4b17023SJohn Marino 	/* do nothing */;
169*e4b17023SJohn Marino     }
170*e4b17023SJohn Marino 
171*e4b17023SJohn Marino   size = objc_sizeof_type (type);
172*e4b17023SJohn Marino   align = objc_alignof_type (type);
173*e4b17023SJohn Marino 
174*e4b17023SJohn Marino   offset = ROUND (offset, align);
175*e4b17023SJohn Marino   for (i = 0; i < size; i += sizeof (void *))
176*e4b17023SJohn Marino     {
177*e4b17023SJohn Marino       SET_BIT_FOR_OFFSET (mask, offset);
178*e4b17023SJohn Marino       offset += sizeof (void *);
179*e4b17023SJohn Marino     }
180*e4b17023SJohn Marino }
181*e4b17023SJohn Marino 
182*e4b17023SJohn Marino 
183*e4b17023SJohn Marino /* Iterates over the types in the structure that represents the class
184*e4b17023SJohn Marino    encoding and sets the bits in mask according to each ivar type.  */
185*e4b17023SJohn Marino static void
__objc_gc_type_description_from_type(GC_bitmap mask,const char * type)186*e4b17023SJohn Marino __objc_gc_type_description_from_type (GC_bitmap mask, const char *type)
187*e4b17023SJohn Marino {
188*e4b17023SJohn Marino   struct objc_struct_layout layout;
189*e4b17023SJohn Marino   unsigned int offset, align;
190*e4b17023SJohn Marino   const char *ivar_type;
191*e4b17023SJohn Marino 
192*e4b17023SJohn Marino   objc_layout_structure (type, &layout);
193*e4b17023SJohn Marino 
194*e4b17023SJohn Marino   while (objc_layout_structure_next_member (&layout))
195*e4b17023SJohn Marino     {
196*e4b17023SJohn Marino       BOOL gc_invisible = NO;
197*e4b17023SJohn Marino 
198*e4b17023SJohn Marino       objc_layout_structure_get_info (&layout, &offset, &align, &ivar_type);
199*e4b17023SJohn Marino 
200*e4b17023SJohn Marino       /* Skip the variable name */
201*e4b17023SJohn Marino       if (*ivar_type == '"')
202*e4b17023SJohn Marino 	{
203*e4b17023SJohn Marino 	  for (ivar_type++; *ivar_type++ != '"';)
204*e4b17023SJohn Marino 	    /* do nothing */;
205*e4b17023SJohn Marino 	}
206*e4b17023SJohn Marino 
207*e4b17023SJohn Marino       if (*ivar_type == _C_GCINVISIBLE)
208*e4b17023SJohn Marino 	{
209*e4b17023SJohn Marino 	  gc_invisible = YES;
210*e4b17023SJohn Marino 	  ivar_type++;
211*e4b17023SJohn Marino 	}
212*e4b17023SJohn Marino 
213*e4b17023SJohn Marino       switch (*ivar_type) {
214*e4b17023SJohn Marino       case _C_ID:
215*e4b17023SJohn Marino       case _C_CLASS:
216*e4b17023SJohn Marino       case _C_SEL:
217*e4b17023SJohn Marino       case _C_PTR:
218*e4b17023SJohn Marino       case _C_CHARPTR:
219*e4b17023SJohn Marino         if (! gc_invisible)
220*e4b17023SJohn Marino           SET_BIT_FOR_OFFSET (mask, offset);
221*e4b17023SJohn Marino 	break;
222*e4b17023SJohn Marino 
223*e4b17023SJohn Marino       case _C_ARY_B:
224*e4b17023SJohn Marino 	__objc_gc_setup_array (mask, ivar_type, offset);
225*e4b17023SJohn Marino 	break;
226*e4b17023SJohn Marino 
227*e4b17023SJohn Marino       case _C_STRUCT_B:
228*e4b17023SJohn Marino 	__objc_gc_setup_struct (mask, ivar_type, offset);
229*e4b17023SJohn Marino 	break;
230*e4b17023SJohn Marino 
231*e4b17023SJohn Marino       case _C_UNION_B:
232*e4b17023SJohn Marino 	__objc_gc_setup_union (mask, ivar_type, offset);
233*e4b17023SJohn Marino 	break;
234*e4b17023SJohn Marino 
235*e4b17023SJohn Marino       default:
236*e4b17023SJohn Marino         break;
237*e4b17023SJohn Marino       }
238*e4b17023SJohn Marino     }
239*e4b17023SJohn Marino }
240*e4b17023SJohn Marino 
241*e4b17023SJohn Marino /* Computes in *type the full type encoding of this class including
242*e4b17023SJohn Marino    its super classes. '*size' gives the total number of bytes allocated
243*e4b17023SJohn Marino    into *type, '*current' the number of bytes used so far by the
244*e4b17023SJohn Marino    encoding. */
245*e4b17023SJohn Marino static void
__objc_class_structure_encoding(Class class,char ** type,int * size,int * current)246*e4b17023SJohn Marino __objc_class_structure_encoding (Class class, char **type, int *size,
247*e4b17023SJohn Marino                                  int *current)
248*e4b17023SJohn Marino {
249*e4b17023SJohn Marino   int i, ivar_count;
250*e4b17023SJohn Marino   struct objc_ivar_list *ivars;
251*e4b17023SJohn Marino 
252*e4b17023SJohn Marino   if (! class)
253*e4b17023SJohn Marino     {
254*e4b17023SJohn Marino       strcat (*type, "{");
255*e4b17023SJohn Marino       (*current)++;
256*e4b17023SJohn Marino       return;
257*e4b17023SJohn Marino     }
258*e4b17023SJohn Marino 
259*e4b17023SJohn Marino   /* Add the type encodings of the super classes */
260*e4b17023SJohn Marino   __objc_class_structure_encoding (class->super_class, type, size, current);
261*e4b17023SJohn Marino 
262*e4b17023SJohn Marino   ivars = class->ivars;
263*e4b17023SJohn Marino   if (! ivars)
264*e4b17023SJohn Marino     return;
265*e4b17023SJohn Marino 
266*e4b17023SJohn Marino   ivar_count = ivars->ivar_count;
267*e4b17023SJohn Marino 
268*e4b17023SJohn Marino   for (i = 0; i < ivar_count; i++)
269*e4b17023SJohn Marino     {
270*e4b17023SJohn Marino       struct objc_ivar *ivar = &(ivars->ivar_list[i]);
271*e4b17023SJohn Marino       const char *ivar_type = ivar->ivar_type;
272*e4b17023SJohn Marino       int len = strlen (ivar_type);
273*e4b17023SJohn Marino 
274*e4b17023SJohn Marino       if (*current + len + 1 >= *size)
275*e4b17023SJohn Marino         {
276*e4b17023SJohn Marino           /* Increase the size of the encoding string so that it
277*e4b17023SJohn Marino              contains this ivar's type. */
278*e4b17023SJohn Marino           *size = ROUND (*current + len + 1, 10);
279*e4b17023SJohn Marino           *type = objc_realloc (*type, *size);
280*e4b17023SJohn Marino         }
281*e4b17023SJohn Marino       strcat (*type + *current, ivar_type);
282*e4b17023SJohn Marino       *current += len;
283*e4b17023SJohn Marino     }
284*e4b17023SJohn Marino }
285*e4b17023SJohn Marino 
286*e4b17023SJohn Marino 
287*e4b17023SJohn Marino /* Allocates the memory that will hold the type description for class
288*e4b17023SJohn Marino    and calls the __objc_class_structure_encoding that generates this
289*e4b17023SJohn Marino    value. */
290*e4b17023SJohn Marino void
__objc_generate_gc_type_description(Class class)291*e4b17023SJohn Marino __objc_generate_gc_type_description (Class class)
292*e4b17023SJohn Marino {
293*e4b17023SJohn Marino   GC_bitmap mask;
294*e4b17023SJohn Marino   int bits_no, size;
295*e4b17023SJohn Marino   int type_size = 10, current;
296*e4b17023SJohn Marino   char *class_structure_type;
297*e4b17023SJohn Marino 
298*e4b17023SJohn Marino   if (! CLS_ISCLASS (class))
299*e4b17023SJohn Marino     return;
300*e4b17023SJohn Marino 
301*e4b17023SJohn Marino   /* We have to create a mask in which each bit counts for a pointer member.
302*e4b17023SJohn Marino      We take into consideration all the non-pointer instance variables and we
303*e4b17023SJohn Marino      round them up to the alignment. */
304*e4b17023SJohn Marino 
305*e4b17023SJohn Marino   /* The number of bits in the mask is the size of an instance in bytes divided
306*e4b17023SJohn Marino      by the size of a pointer. */
307*e4b17023SJohn Marino   bits_no = (ROUND (class_getInstanceSize (class), sizeof (void *))
308*e4b17023SJohn Marino              / sizeof (void *));
309*e4b17023SJohn Marino   size = ROUND (bits_no, BITS_PER_WORD) / BITS_PER_WORD;
310*e4b17023SJohn Marino   mask = objc_atomic_malloc (size * sizeof (int));
311*e4b17023SJohn Marino   memset (mask, 0, size * sizeof (int));
312*e4b17023SJohn Marino 
313*e4b17023SJohn Marino   class_structure_type = objc_atomic_malloc (type_size);
314*e4b17023SJohn Marino   *class_structure_type = current = 0;
315*e4b17023SJohn Marino   __objc_class_structure_encoding (class, &class_structure_type,
316*e4b17023SJohn Marino                                    &type_size, &current);
317*e4b17023SJohn Marino   if (current + 1 == type_size)
318*e4b17023SJohn Marino     class_structure_type = objc_realloc (class_structure_type, ++type_size);
319*e4b17023SJohn Marino   strcat (class_structure_type + current, "}");
320*e4b17023SJohn Marino #ifdef DEBUG
321*e4b17023SJohn Marino   printf ("type description for '%s' is %s\n", class->name, class_structure_type);
322*e4b17023SJohn Marino #endif
323*e4b17023SJohn Marino 
324*e4b17023SJohn Marino   __objc_gc_type_description_from_type (mask, class_structure_type);
325*e4b17023SJohn Marino   objc_free (class_structure_type);
326*e4b17023SJohn Marino 
327*e4b17023SJohn Marino #ifdef DEBUG
328*e4b17023SJohn Marino   printf ("  mask for '%s', type '%s' (bits %d, mask size %d) is:",
329*e4b17023SJohn Marino 	  class_structure_type, class->name, bits_no, size);
330*e4b17023SJohn Marino   {
331*e4b17023SJohn Marino     int i;
332*e4b17023SJohn Marino     for (i = 0; i < size; i++)
333*e4b17023SJohn Marino       printf (" %lx", mask[i]);
334*e4b17023SJohn Marino   }
335*e4b17023SJohn Marino   puts ("");
336*e4b17023SJohn Marino #endif
337*e4b17023SJohn Marino 
338*e4b17023SJohn Marino   class->gc_object_type = (void *) GC_make_descriptor (mask, bits_no);
339*e4b17023SJohn Marino }
340*e4b17023SJohn Marino 
341*e4b17023SJohn Marino 
342*e4b17023SJohn Marino /* Returns YES if type denotes a pointer type, NO otherwise */
343*e4b17023SJohn Marino static inline BOOL
__objc_ivar_pointer(const char * type)344*e4b17023SJohn Marino __objc_ivar_pointer (const char *type)
345*e4b17023SJohn Marino {
346*e4b17023SJohn Marino   type = objc_skip_type_qualifiers (type);
347*e4b17023SJohn Marino 
348*e4b17023SJohn Marino   return (*type == _C_ID
349*e4b17023SJohn Marino           || *type == _C_CLASS
350*e4b17023SJohn Marino           || *type == _C_SEL
351*e4b17023SJohn Marino           || *type == _C_PTR
352*e4b17023SJohn Marino           || *type == _C_CHARPTR
353*e4b17023SJohn Marino           || *type == _C_ATOM);
354*e4b17023SJohn Marino }
355*e4b17023SJohn Marino 
356*e4b17023SJohn Marino 
357*e4b17023SJohn Marino /* Mark the instance variable whose name is given by ivarname as a
358*e4b17023SJohn Marino    weak pointer (a pointer hidden to the garbage collector) if
359*e4b17023SJohn Marino    gc_invisible is true. If gc_invisible is false it unmarks the
360*e4b17023SJohn Marino    instance variable and makes it a normal pointer, visible to the
361*e4b17023SJohn Marino    garbage collector.
362*e4b17023SJohn Marino 
363*e4b17023SJohn Marino    This operation only makes sense on instance variables that are
364*e4b17023SJohn Marino    pointers.  */
365*e4b17023SJohn Marino void
class_ivar_set_gcinvisible(Class class,const char * ivarname,BOOL gc_invisible)366*e4b17023SJohn Marino class_ivar_set_gcinvisible (Class class, const char *ivarname,
367*e4b17023SJohn Marino                             BOOL gc_invisible)
368*e4b17023SJohn Marino {
369*e4b17023SJohn Marino   int i, ivar_count;
370*e4b17023SJohn Marino   struct objc_ivar_list *ivars;
371*e4b17023SJohn Marino 
372*e4b17023SJohn Marino   if (! class || ! ivarname)
373*e4b17023SJohn Marino     return;
374*e4b17023SJohn Marino 
375*e4b17023SJohn Marino   ivars = class->ivars;
376*e4b17023SJohn Marino   if (! ivars)
377*e4b17023SJohn Marino     return;
378*e4b17023SJohn Marino 
379*e4b17023SJohn Marino   ivar_count = ivars->ivar_count;
380*e4b17023SJohn Marino 
381*e4b17023SJohn Marino   for (i = 0; i < ivar_count; i++)
382*e4b17023SJohn Marino     {
383*e4b17023SJohn Marino       struct objc_ivar *ivar = &(ivars->ivar_list[i]);
384*e4b17023SJohn Marino       const char *type;
385*e4b17023SJohn Marino 
386*e4b17023SJohn Marino       if (! ivar->ivar_name || strcmp (ivar->ivar_name, ivarname))
387*e4b17023SJohn Marino 	continue;
388*e4b17023SJohn Marino 
389*e4b17023SJohn Marino       assert (ivar->ivar_type);
390*e4b17023SJohn Marino       type = ivar->ivar_type;
391*e4b17023SJohn Marino 
392*e4b17023SJohn Marino       /* Skip the variable name */
393*e4b17023SJohn Marino       if (*type == '"')
394*e4b17023SJohn Marino 	{
395*e4b17023SJohn Marino 	  for (type++; *type++ != '"';)
396*e4b17023SJohn Marino 	    /* do nothing */;
397*e4b17023SJohn Marino 	}
398*e4b17023SJohn Marino 
399*e4b17023SJohn Marino       if (*type == _C_GCINVISIBLE)
400*e4b17023SJohn Marino 	{
401*e4b17023SJohn Marino 	  char *new_type;
402*e4b17023SJohn Marino 	  size_t len;
403*e4b17023SJohn Marino 
404*e4b17023SJohn Marino 	  if (gc_invisible || ! __objc_ivar_pointer (type))
405*e4b17023SJohn Marino 	    return;	/* The type of the variable already matches the
406*e4b17023SJohn Marino 			   requested gc_invisible type */
407*e4b17023SJohn Marino 
408*e4b17023SJohn Marino 	  /* The variable is gc_invisible so we make it gc visible.  */
409*e4b17023SJohn Marino 	  new_type = objc_atomic_malloc (strlen(ivar->ivar_type));
410*e4b17023SJohn Marino 	  len = (type - ivar->ivar_type);
411*e4b17023SJohn Marino 	  memcpy (new_type, ivar->ivar_type, len);
412*e4b17023SJohn Marino 	  new_type[len] = 0;
413*e4b17023SJohn Marino 	  strcat (new_type, type + 1);
414*e4b17023SJohn Marino 	  ivar->ivar_type = new_type;
415*e4b17023SJohn Marino 	}
416*e4b17023SJohn Marino       else
417*e4b17023SJohn Marino 	{
418*e4b17023SJohn Marino 	  char *new_type;
419*e4b17023SJohn Marino 	  size_t len;
420*e4b17023SJohn Marino 
421*e4b17023SJohn Marino 	  if (! gc_invisible || ! __objc_ivar_pointer (type))
422*e4b17023SJohn Marino 	    return;	/* The type of the variable already matches the
423*e4b17023SJohn Marino 			   requested gc_invisible type */
424*e4b17023SJohn Marino 
425*e4b17023SJohn Marino 	  /* The variable is gc visible so we make it gc_invisible.  */
426*e4b17023SJohn Marino 	  new_type = objc_malloc (strlen(ivar->ivar_type) + 2);
427*e4b17023SJohn Marino 
428*e4b17023SJohn Marino 	  /* Copy the variable name.  */
429*e4b17023SJohn Marino 	  len = (type - ivar->ivar_type);
430*e4b17023SJohn Marino 	  memcpy (new_type, ivar->ivar_type, len);
431*e4b17023SJohn Marino 	  /* Add '!'.  */
432*e4b17023SJohn Marino 	  new_type[len++] = _C_GCINVISIBLE;
433*e4b17023SJohn Marino 	  /* Copy the original types.  */
434*e4b17023SJohn Marino 	  strcpy (new_type + len, type);
435*e4b17023SJohn Marino 
436*e4b17023SJohn Marino 	  ivar->ivar_type = new_type;
437*e4b17023SJohn Marino 	}
438*e4b17023SJohn Marino 
439*e4b17023SJohn Marino       __objc_generate_gc_type_description (class);
440*e4b17023SJohn Marino       return;
441*e4b17023SJohn Marino     }
442*e4b17023SJohn Marino 
443*e4b17023SJohn Marino   /* Search the instance variable in the superclasses */
444*e4b17023SJohn Marino   class_ivar_set_gcinvisible (class->super_class, ivarname, gc_invisible);
445*e4b17023SJohn Marino }
446*e4b17023SJohn Marino 
447*e4b17023SJohn Marino #else /* !OBJC_WITH_GC */
448*e4b17023SJohn Marino 
449*e4b17023SJohn Marino void
__objc_generate_gc_type_description(Class class)450*e4b17023SJohn Marino __objc_generate_gc_type_description (Class class __attribute__ ((__unused__)))
451*e4b17023SJohn Marino {
452*e4b17023SJohn Marino }
453*e4b17023SJohn Marino 
class_ivar_set_gcinvisible(Class class,const char * ivarname,BOOL gc_invisible)454*e4b17023SJohn Marino void class_ivar_set_gcinvisible (Class class __attribute__ ((__unused__)),
455*e4b17023SJohn Marino 				 const char *ivarname __attribute__ ((__unused__)),
456*e4b17023SJohn Marino 				 BOOL gc_invisible __attribute__ ((__unused__)))
457*e4b17023SJohn Marino {
458*e4b17023SJohn Marino }
459*e4b17023SJohn Marino 
460*e4b17023SJohn Marino #endif /* OBJC_WITH_GC */
461