1 /* Basic data types for Objective C.
2 Copyright (C) 1998-2016 Free Software Foundation, Inc.
3 Contributed by Ovidiu Predescu.
5 This file is part of GCC.
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)
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.
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.
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/>. */
26 #include "objc-private/common.h"
27 #include "objc/objc.h"
33 #include <ctype.h> /* For isdigit. */
36 #include "objc/runtime.h"
37 #include "objc-private/module-abi-8.h"
42 /* gc_typed.h uses the following but doesn't declare them */
44 typedef GC_signed_word signed_word;
45 #define BITS_PER_WORD (CHAR_BIT * sizeof (word))
49 /* The following functions set up in `mask` the corresponding pointers.
50 The offset is incremented with the size of the type. */
53 ({ typeof (V) __v = (V); typeof (A) __a = (A); \
54 __a * ((__v+__a - 1)/__a); })
56 #define SET_BIT_FOR_OFFSET(mask, offset) \
57 GC_set_bit (mask, offset / sizeof (void *))
61 __objc_gc_setup_struct (GC_bitmap mask, const char *type, int offset);
63 __objc_gc_setup_union (GC_bitmap mask, const char *type, int offset);
67 __objc_gc_setup_array (GC_bitmap mask, const char *type, int offset)
69 int i, len = atoi (type + 1);
71 while (isdigit (*++type))
72 /* do nothing */; /* skip the size of the array */
76 for (i = 0; i < len; i++)
77 __objc_gc_setup_array (mask, type, offset);
81 for (i = 0; i < len; i++)
82 __objc_gc_setup_struct (mask, type, offset);
86 for (i = 0; i < len; i++)
87 __objc_gc_setup_union (mask, type, offset);
96 __objc_gc_setup_struct (GC_bitmap mask, const char *type, int offset)
98 struct objc_struct_layout layout;
99 unsigned int position;
102 objc_layout_structure (type, &layout);
104 while (objc_layout_structure_next_member (&layout))
106 BOOL gc_invisible = NO;
108 objc_layout_structure_get_info (&layout, &position, NULL, &mtype);
110 /* Skip the variable name */
113 for (mtype++; *mtype++ != '"';)
117 if (*mtype == _C_GCINVISIBLE)
123 /* Add to position the offset of this structure */
134 SET_BIT_FOR_OFFSET (mask, position);
138 __objc_gc_setup_array (mask, mtype, position);
142 __objc_gc_setup_struct (mask, mtype, position);
146 __objc_gc_setup_union (mask, mtype, position);
156 __objc_gc_setup_union (GC_bitmap mask, const char *type, int offset)
158 /* Sub-optimal, quick implementation: assume the union is made of
159 pointers, set up the mask accordingly. */
163 /* Skip the variable name */
166 for (type++; *type++ != '"';)
170 size = objc_sizeof_type (type);
171 align = objc_alignof_type (type);
173 offset = ROUND (offset, align);
174 for (i = 0; i < size; i += sizeof (void *))
176 SET_BIT_FOR_OFFSET (mask, offset);
177 offset += sizeof (void *);
182 /* Iterates over the types in the structure that represents the class
183 encoding and sets the bits in mask according to each ivar type. */
185 __objc_gc_type_description_from_type (GC_bitmap mask, const char *type)
187 struct objc_struct_layout layout;
188 unsigned int offset, align;
189 const char *ivar_type;
191 objc_layout_structure (type, &layout);
193 while (objc_layout_structure_next_member (&layout))
195 BOOL gc_invisible = NO;
197 objc_layout_structure_get_info (&layout, &offset, &align, &ivar_type);
199 /* Skip the variable name */
200 if (*ivar_type == '"')
202 for (ivar_type++; *ivar_type++ != '"';)
206 if (*ivar_type == _C_GCINVISIBLE)
212 switch (*ivar_type) {
219 SET_BIT_FOR_OFFSET (mask, offset);
223 __objc_gc_setup_array (mask, ivar_type, offset);
227 __objc_gc_setup_struct (mask, ivar_type, offset);
231 __objc_gc_setup_union (mask, ivar_type, offset);
240 /* Computes in *type the full type encoding of this class including
241 its super classes. '*size' gives the total number of bytes allocated
242 into *type, '*current' the number of bytes used so far by the
245 __objc_class_structure_encoding (Class class, char **type, int *size,
249 struct objc_ivar_list *ivars;
258 /* Add the type encodings of the super classes */
259 __objc_class_structure_encoding (class->super_class, type, size, current);
261 ivars = class->ivars;
265 ivar_count = ivars->ivar_count;
267 for (i = 0; i < ivar_count; i++)
269 struct objc_ivar *ivar = &(ivars->ivar_list[i]);
270 const char *ivar_type = ivar->ivar_type;
271 int len = strlen (ivar_type);
273 if (*current + len + 1 >= *size)
275 /* Increase the size of the encoding string so that it
276 contains this ivar's type. */
277 *size = ROUND (*current + len + 1, 10);
278 *type = objc_realloc (*type, *size);
280 strcat (*type + *current, ivar_type);
286 /* Allocates the memory that will hold the type description for class
287 and calls the __objc_class_structure_encoding that generates this
290 __objc_generate_gc_type_description (Class class)
294 int type_size = 10, current;
295 char *class_structure_type;
297 if (! CLS_ISCLASS (class))
300 /* We have to create a mask in which each bit counts for a pointer member.
301 We take into consideration all the non-pointer instance variables and we
302 round them up to the alignment. */
304 /* The number of bits in the mask is the size of an instance in bytes divided
305 by the size of a pointer. */
306 bits_no = (ROUND (class_getInstanceSize (class), sizeof (void *))
308 size = ROUND (bits_no, BITS_PER_WORD) / BITS_PER_WORD;
309 mask = objc_atomic_malloc (size * sizeof (int));
310 memset (mask, 0, size * sizeof (int));
312 class_structure_type = objc_atomic_malloc (type_size);
313 *class_structure_type = current = 0;
314 __objc_class_structure_encoding (class, &class_structure_type,
315 &type_size, ¤t);
316 if (current + 1 == type_size)
317 class_structure_type = objc_realloc (class_structure_type, ++type_size);
318 strcat (class_structure_type + current, "}");
320 printf ("type description for '%s' is %s\n", class->name, class_structure_type);
323 __objc_gc_type_description_from_type (mask, class_structure_type);
324 objc_free (class_structure_type);
327 printf (" mask for '%s', type '%s' (bits %d, mask size %d) is:",
328 class_structure_type, class->name, bits_no, size);
331 for (i = 0; i < size; i++)
332 printf (" %lx", mask[i]);
337 class->gc_object_type = (void *) GC_make_descriptor (mask, bits_no);
341 /* Returns YES if type denotes a pointer type, NO otherwise */
343 __objc_ivar_pointer (const char *type)
345 type = objc_skip_type_qualifiers (type);
347 return (*type == _C_ID
351 || *type == _C_CHARPTR
352 || *type == _C_ATOM);
356 /* Mark the instance variable whose name is given by ivarname as a
357 weak pointer (a pointer hidden to the garbage collector) if
358 gc_invisible is true. If gc_invisible is false it unmarks the
359 instance variable and makes it a normal pointer, visible to the
362 This operation only makes sense on instance variables that are
365 class_ivar_set_gcinvisible (Class class, const char *ivarname,
369 struct objc_ivar_list *ivars;
371 if (! class || ! ivarname)
374 ivars = class->ivars;
378 ivar_count = ivars->ivar_count;
380 for (i = 0; i < ivar_count; i++)
382 struct objc_ivar *ivar = &(ivars->ivar_list[i]);
385 if (! ivar->ivar_name || strcmp (ivar->ivar_name, ivarname))
388 assert (ivar->ivar_type);
389 type = ivar->ivar_type;
391 /* Skip the variable name */
394 for (type++; *type++ != '"';)
398 if (*type == _C_GCINVISIBLE)
403 if (gc_invisible || ! __objc_ivar_pointer (type))
404 return; /* The type of the variable already matches the
405 requested gc_invisible type */
407 /* The variable is gc_invisible so we make it gc visible. */
408 new_type = objc_atomic_malloc (strlen(ivar->ivar_type));
409 len = (type - ivar->ivar_type);
410 memcpy (new_type, ivar->ivar_type, len);
412 strcat (new_type, type + 1);
413 ivar->ivar_type = new_type;
420 if (! gc_invisible || ! __objc_ivar_pointer (type))
421 return; /* The type of the variable already matches the
422 requested gc_invisible type */
424 /* The variable is gc visible so we make it gc_invisible. */
425 new_type = objc_malloc (strlen(ivar->ivar_type) + 2);
427 /* Copy the variable name. */
428 len = (type - ivar->ivar_type);
429 memcpy (new_type, ivar->ivar_type, len);
431 new_type[len++] = _C_GCINVISIBLE;
432 /* Copy the original types. */
433 strcpy (new_type + len, type);
435 ivar->ivar_type = new_type;
438 __objc_generate_gc_type_description (class);
442 /* Search the instance variable in the superclasses */
443 class_ivar_set_gcinvisible (class->super_class, ivarname, gc_invisible);
446 #else /* !OBJC_WITH_GC */
449 __objc_generate_gc_type_description (Class class __attribute__ ((__unused__)))
453 void class_ivar_set_gcinvisible (Class class __attribute__ ((__unused__)),
454 const char *ivarname __attribute__ ((__unused__)),
455 BOOL gc_invisible __attribute__ ((__unused__)))
459 #endif /* OBJC_WITH_GC */