OSDN Git Service

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