1 /* Basic data types for Objective C.
2 Copyright (C) 1998, 2002, 2004, 2005, 2006, 2009, 2010
3 Free Software Foundation, Inc.
4 Contributed by Ovidiu Predescu.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25 <http://www.gnu.org/licenses/>. */
27 #include "objc-private/common.h"
28 #include "objc/objc.h"
36 #include "objc/encoding.h"
41 /* gc_typed.h uses the following but doesn't declare them */
43 typedef GC_signed_word signed_word
;
44 #define BITS_PER_WORD (CHAR_BIT * sizeof (word))
48 /* The following functions set up in `mask` the corresponding pointers.
49 The offset is incremented with the size of the type. */
52 ({ typeof (V) __v = (V); typeof (A) __a = (A); \
53 __a * ((__v+__a - 1)/__a); })
55 #define SET_BIT_FOR_OFFSET(mask, offset) \
56 GC_set_bit (mask, offset / sizeof (void *))
60 __objc_gc_setup_struct (GC_bitmap mask
, const char *type
, int offset
);
62 __objc_gc_setup_union (GC_bitmap mask
, const char *type
, int offset
);
66 __objc_gc_setup_array (GC_bitmap mask
, const char *type
, int offset
)
68 int i
, len
= atoi (type
+ 1);
70 while (isdigit (*++type
))
71 /* do nothing */; /* skip the size of the array */
75 for (i
= 0; i
< len
; i
++)
76 __objc_gc_setup_array (mask
, type
, offset
);
80 for (i
= 0; i
< len
; i
++)
81 __objc_gc_setup_struct (mask
, type
, offset
);
85 for (i
= 0; i
< len
; i
++)
86 __objc_gc_setup_union (mask
, type
, offset
);
95 __objc_gc_setup_struct (GC_bitmap mask
, const char *type
, int offset
)
97 struct objc_struct_layout layout
;
98 unsigned int position
;
101 objc_layout_structure (type
, &layout
);
103 while (objc_layout_structure_next_member (&layout
))
105 BOOL gc_invisible
= NO
;
107 objc_layout_structure_get_info (&layout
, &position
, NULL
, &mtype
);
109 /* Skip the variable name */
112 for (mtype
++; *mtype
++ != '"';)
116 if (*mtype
== _C_GCINVISIBLE
)
122 /* Add to position the offset of this structure */
133 SET_BIT_FOR_OFFSET (mask
, position
);
137 __objc_gc_setup_array (mask
, mtype
, position
);
141 __objc_gc_setup_struct (mask
, mtype
, position
);
145 __objc_gc_setup_union (mask
, mtype
, position
);
155 __objc_gc_setup_union (GC_bitmap mask
, const char *type
, int offset
)
157 /* Sub-optimal, quick implementation: assume the union is made of
158 pointers, set up the mask accordingly. */
162 /* Skip the variable name */
165 for (type
++; *type
++ != '"';)
169 size
= objc_sizeof_type (type
);
170 align
= objc_alignof_type (type
);
172 offset
= ROUND (offset
, align
);
173 for (i
= 0; i
< size
; i
+= sizeof (void *))
175 SET_BIT_FOR_OFFSET (mask
, offset
);
176 offset
+= sizeof (void *);
181 /* Iterates over the types in the structure that represents the class
182 encoding and sets the bits in mask according to each ivar type. */
184 __objc_gc_type_description_from_type (GC_bitmap mask
, const char *type
)
186 struct objc_struct_layout layout
;
187 unsigned int offset
, align
;
188 const char *ivar_type
;
190 objc_layout_structure (type
, &layout
);
192 while (objc_layout_structure_next_member (&layout
))
194 BOOL gc_invisible
= NO
;
196 objc_layout_structure_get_info (&layout
, &offset
, &align
, &ivar_type
);
198 /* Skip the variable name */
199 if (*ivar_type
== '"')
201 for (ivar_type
++; *ivar_type
++ != '"';)
205 if (*ivar_type
== _C_GCINVISIBLE
)
211 switch (*ivar_type
) {
218 SET_BIT_FOR_OFFSET (mask
, offset
);
222 __objc_gc_setup_array (mask
, ivar_type
, offset
);
226 __objc_gc_setup_struct (mask
, ivar_type
, offset
);
230 __objc_gc_setup_union (mask
, ivar_type
, offset
);
239 /* Computes in *type the full type encoding of this class including
240 its super classes. '*size' gives the total number of bytes allocated
241 into *type, '*current' the number of bytes used so far by the
244 __objc_class_structure_encoding (Class
class, char **type
, int *size
,
248 struct objc_ivar_list
*ivars
;
257 /* Add the type encodings of the super classes */
258 __objc_class_structure_encoding (class->super_class
, type
, size
, current
);
260 ivars
= class->ivars
;
264 ivar_count
= ivars
->ivar_count
;
266 for (i
= 0; i
< ivar_count
; i
++)
268 struct objc_ivar
*ivar
= &(ivars
->ivar_list
[i
]);
269 const char *ivar_type
= ivar
->ivar_type
;
270 int len
= strlen (ivar_type
);
272 if (*current
+ len
+ 1 >= *size
)
274 /* Increase the size of the encoding string so that it
275 contains this ivar's type. */
276 *size
= ROUND (*current
+ len
+ 1, 10);
277 *type
= objc_realloc (*type
, *size
);
279 strcat (*type
+ *current
, ivar_type
);
285 /* Allocates the memory that will hold the type description for class
286 and calls the __objc_class_structure_encoding that generates this
289 __objc_generate_gc_type_description (Class
class)
293 int type_size
= 10, current
;
294 char *class_structure_type
;
296 if (! CLS_ISCLASS (class))
299 /* We have to create a mask in which each bit counts for a pointer member.
300 We take into consideration all the non-pointer instance variables and we
301 round them up to the alignment. */
303 /* The number of bits in the mask is the size of an instance in bytes divided
304 by the size of a pointer. */
305 bits_no
= (ROUND (class_get_instance_size (class), sizeof (void *))
307 size
= ROUND (bits_no
, BITS_PER_WORD
) / BITS_PER_WORD
;
308 mask
= objc_atomic_malloc (size
* sizeof (int));
309 memset (mask
, 0, size
* sizeof (int));
311 class_structure_type
= objc_atomic_malloc (type_size
);
312 *class_structure_type
= current
= 0;
313 __objc_class_structure_encoding (class, &class_structure_type
,
314 &type_size
, ¤t
);
315 if (current
+ 1 == type_size
)
316 class_structure_type
= objc_realloc (class_structure_type
, ++type_size
);
317 strcat (class_structure_type
+ current
, "}");
319 printf ("type description for '%s' is %s\n", class->name
, class_structure_type
);
322 __objc_gc_type_description_from_type (mask
, class_structure_type
);
323 objc_free (class_structure_type
);
326 printf (" mask for '%s', type '%s' (bits %d, mask size %d) is:",
327 class_structure_type
, class->name
, bits_no
, size
);
330 for (i
= 0; i
< size
; i
++)
331 printf (" %lx", mask
[i
]);
336 class->gc_object_type
= (void *) GC_make_descriptor (mask
, bits_no
);
340 /* Returns YES if type denotes a pointer type, NO otherwise */
342 __objc_ivar_pointer (const char *type
)
344 type
= objc_skip_type_qualifiers (type
);
346 return (*type
== _C_ID
350 || *type
== _C_CHARPTR
351 || *type
== _C_ATOM
);
355 /* Mark the instance variable whose name is given by ivarname as a
356 weak pointer (a pointer hidden to the garbage collector) if
357 gc_invisible is true. If gc_invisible is false it unmarks the
358 instance variable and makes it a normal pointer, visible to the
361 This operation only makes sense on instance variables that are
364 class_ivar_set_gcinvisible (Class
class, const char *ivarname
,
368 struct objc_ivar_list
*ivars
;
370 if (! class || ! ivarname
)
373 ivars
= class->ivars
;
377 ivar_count
= ivars
->ivar_count
;
379 for (i
= 0; i
< ivar_count
; i
++)
381 struct objc_ivar
*ivar
= &(ivars
->ivar_list
[i
]);
384 if (! ivar
->ivar_name
|| strcmp (ivar
->ivar_name
, ivarname
))
387 assert (ivar
->ivar_type
);
388 type
= ivar
->ivar_type
;
390 /* Skip the variable name */
393 for (type
++; *type
++ != '"';)
397 if (*type
== _C_GCINVISIBLE
)
402 if (gc_invisible
|| ! __objc_ivar_pointer (type
))
403 return; /* The type of the variable already matches the
404 requested gc_invisible type */
406 /* The variable is gc_invisible so we make it gc visible. */
407 new_type
= objc_atomic_malloc (strlen(ivar
->ivar_type
));
408 len
= (type
- ivar
->ivar_type
);
409 memcpy (new_type
, ivar
->ivar_type
, len
);
411 strcat (new_type
, type
+ 1);
412 ivar
->ivar_type
= new_type
;
419 if (! gc_invisible
|| ! __objc_ivar_pointer (type
))
420 return; /* The type of the variable already matches the
421 requested gc_invisible type */
423 /* The variable is gc visible so we make it gc_invisible. */
424 new_type
= objc_malloc (strlen(ivar
->ivar_type
) + 2);
426 /* Copy the variable name. */
427 len
= (type
- ivar
->ivar_type
);
428 memcpy (new_type
, ivar
->ivar_type
, len
);
430 new_type
[len
++] = _C_GCINVISIBLE
;
431 /* Copy the original types. */
432 strcpy (new_type
+ len
, type
);
434 ivar
->ivar_type
= new_type
;
437 __objc_generate_gc_type_description (class);
441 /* Search the instance variable in the superclasses */
442 class_ivar_set_gcinvisible (class->super_class
, ivarname
, gc_invisible
);
445 #else /* !OBJC_WITH_GC */
448 __objc_generate_gc_type_description (Class
class __attribute__ ((__unused__
)))
452 void class_ivar_set_gcinvisible (Class
class __attribute__ ((__unused__
)),
453 const char *ivarname
__attribute__ ((__unused__
)),
454 BOOL gc_invisible
__attribute__ ((__unused__
)))
458 #endif /* OBJC_WITH_GC */